mirror of
https://github.com/danielmiessler/Fabric.git
synced 2026-01-10 06:48:04 -05:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
90712506f1 | ||
|
|
edc02120bb | ||
|
|
8f05883581 | ||
|
|
996933e687 | ||
|
|
8806f4c2f4 | ||
|
|
b381bae24a | ||
|
|
a6c753499b | ||
|
|
90b2975fba | ||
|
|
145499ee4c | ||
|
|
f9359c99dc | ||
|
|
cb2759a5a1 | ||
|
|
c32a650eaa | ||
|
|
8a28ca7b1e | ||
|
|
435d61ae0e |
22
CHANGELOG.md
22
CHANGELOG.md
@@ -1,5 +1,27 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## v1.4.374 (2026-01-05)
|
||||||
|
|
||||||
|
### PR [#1924](https://github.com/danielmiessler/Fabric/pull/1924) by [ksylvan](https://github.com/ksylvan): Rename `code_helper` to `code2context` across documentation and CLI
|
||||||
|
|
||||||
|
- Rename `code_helper` command to `code2context` throughout codebase
|
||||||
|
- Update README.md table of contents and references
|
||||||
|
- Update installation instructions with new binary name
|
||||||
|
- Update all usage examples in main.go help text
|
||||||
|
- Update create_coding_feature pattern documentation
|
||||||
|
|
||||||
|
## v1.4.373 (2026-01-04)
|
||||||
|
|
||||||
|
### PR [#1914](https://github.com/danielmiessler/Fabric/pull/1914) by [majiayu000](https://github.com/majiayu000): feat(code_helper): add stdin support for piping file lists
|
||||||
|
|
||||||
|
- Added stdin support for piping file lists to code_helper, enabling commands like `find . -name '*.go' | code_helper "instructions"` and `git ls-files '*.py' | code_helper "Add type hints"`
|
||||||
|
- Implemented automatic detection of stdin pipe mode with single argument (instructions) support
|
||||||
|
- Enhanced tool to read file paths from stdin line by line while maintaining backward compatibility with existing directory scanning functionality
|
||||||
|
|
||||||
|
### PR [#1915](https://github.com/danielmiessler/Fabric/pull/1915) by [majiayu000](https://github.com/majiayu000): feat: parallelize audio chunk transcription for improved performance
|
||||||
|
|
||||||
|
- Parallelize audio chunk transcription using goroutines for improved performance
|
||||||
|
|
||||||
## v1.4.372 (2026-01-04)
|
## v1.4.372 (2026-01-04)
|
||||||
|
|
||||||
### PR [#1913](https://github.com/danielmiessler/Fabric/pull/1913) by [majiayu000](https://github.com/majiayu000): fix: REST API /chat endpoint doesn't pass 'search' parameter to ChatOptions
|
### PR [#1913](https://github.com/danielmiessler/Fabric/pull/1913) by [majiayu000](https://github.com/majiayu000): fix: REST API /chat endpoint doesn't pass 'search' parameter to ChatOptions
|
||||||
|
|||||||
@@ -185,7 +185,7 @@ Keep in mind that many of these were recorded when Fabric was Python-based, so r
|
|||||||
- [Helper Apps](#helper-apps)
|
- [Helper Apps](#helper-apps)
|
||||||
- [`to_pdf`](#to_pdf)
|
- [`to_pdf`](#to_pdf)
|
||||||
- [`to_pdf` Installation](#to_pdf-installation)
|
- [`to_pdf` Installation](#to_pdf-installation)
|
||||||
- [`code_helper`](#code_helper)
|
- [`code2context`](#code2context)
|
||||||
- [pbpaste](#pbpaste)
|
- [pbpaste](#pbpaste)
|
||||||
- [Web Interface (Fabric Web App)](#web-interface-fabric-web-app)
|
- [Web Interface (Fabric Web App)](#web-interface-fabric-web-app)
|
||||||
- [Meta](#meta)
|
- [Meta](#meta)
|
||||||
@@ -904,9 +904,9 @@ go install github.com/danielmiessler/fabric/cmd/to_pdf@latest
|
|||||||
|
|
||||||
Make sure you have a LaTeX distribution (like TeX Live or MiKTeX) installed on your system, as `to_pdf` requires `pdflatex` to be available in your system's PATH.
|
Make sure you have a LaTeX distribution (like TeX Live or MiKTeX) installed on your system, as `to_pdf` requires `pdflatex` to be available in your system's PATH.
|
||||||
|
|
||||||
### `code_helper`
|
### `code2context`
|
||||||
|
|
||||||
`code_helper` is used in conjunction with the `create_coding_feature` pattern.
|
`code2context` is used in conjunction with the `create_coding_feature` pattern.
|
||||||
It generates a `json` representation of a directory of code that can be fed into an AI model
|
It generates a `json` representation of a directory of code that can be fed into an AI model
|
||||||
with instructions to create a new feature or edit the code in a specified way.
|
with instructions to create a new feature or edit the code in a specified way.
|
||||||
|
|
||||||
@@ -915,7 +915,7 @@ See [the Create Coding Feature Pattern README](./data/patterns/create_coding_fea
|
|||||||
Install it first using:
|
Install it first using:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
go install github.com/danielmiessler/fabric/cmd/code_helper@latest
|
go install github.com/danielmiessler/fabric/cmd/code2context@latest
|
||||||
```
|
```
|
||||||
|
|
||||||
## pbpaste
|
## pbpaste
|
||||||
|
|||||||
@@ -131,6 +131,75 @@ func ScanDirectory(rootDir string, maxDepth int, instructions string, ignoreList
|
|||||||
return json.MarshalIndent(data, "", " ")
|
return json.MarshalIndent(data, "", " ")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ScanFiles scans specific files and returns a JSON representation
|
||||||
|
func ScanFiles(files []string, instructions string) ([]byte, error) {
|
||||||
|
fileCount := 0
|
||||||
|
dirSet := make(map[string]bool)
|
||||||
|
|
||||||
|
// Create root directory item
|
||||||
|
rootItem := FileItem{
|
||||||
|
Type: "directory",
|
||||||
|
Name: ".",
|
||||||
|
Contents: []FileItem{},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, filePath := range files {
|
||||||
|
// Skip directories
|
||||||
|
info, err := os.Stat(filePath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error accessing file %s: %v", filePath, err)
|
||||||
|
}
|
||||||
|
if info.IsDir() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Track unique directories
|
||||||
|
dir := filepath.Dir(filePath)
|
||||||
|
if dir != "." {
|
||||||
|
dirSet[dir] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
fileCount++
|
||||||
|
|
||||||
|
// Read file content
|
||||||
|
content, err := os.ReadFile(filePath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error reading file %s: %v", filePath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean path for consistent handling
|
||||||
|
cleanPath := filepath.Clean(filePath)
|
||||||
|
if strings.HasPrefix(cleanPath, "./") {
|
||||||
|
cleanPath = cleanPath[2:]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add file to the structure
|
||||||
|
addFileToDirectory(&rootItem, cleanPath, string(content), ".")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create final data structure
|
||||||
|
var data []any
|
||||||
|
data = append(data, rootItem)
|
||||||
|
|
||||||
|
// Add report
|
||||||
|
reportItem := map[string]any{
|
||||||
|
"type": "report",
|
||||||
|
"directories": len(dirSet) + 1,
|
||||||
|
"files": fileCount,
|
||||||
|
}
|
||||||
|
data = append(data, reportItem)
|
||||||
|
|
||||||
|
// Add instructions
|
||||||
|
instructionsItem := map[string]any{
|
||||||
|
"type": "instructions",
|
||||||
|
"name": "code_change_instructions",
|
||||||
|
"details": instructions,
|
||||||
|
}
|
||||||
|
data = append(data, instructionsItem)
|
||||||
|
|
||||||
|
return json.MarshalIndent(data, "", " ")
|
||||||
|
}
|
||||||
|
|
||||||
// addFileToDirectory adds a file to the correct directory in the structure
|
// addFileToDirectory adds a file to the correct directory in the structure
|
||||||
func addFileToDirectory(root *FileItem, path, content, rootDir string) {
|
func addFileToDirectory(root *FileItem, path, content, rootDir string) {
|
||||||
parts := strings.Split(path, string(filepath.Separator))
|
parts := strings.Split(path, string(filepath.Separator))
|
||||||
100
cmd/code2context/code_test.go
Normal file
100
cmd/code2context/code_test.go
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestScanFiles(t *testing.T) {
|
||||||
|
// Create temp directory with test files
|
||||||
|
tmpDir := t.TempDir()
|
||||||
|
|
||||||
|
// Create test files
|
||||||
|
file1 := filepath.Join(tmpDir, "test1.go")
|
||||||
|
file2 := filepath.Join(tmpDir, "test2.go")
|
||||||
|
subDir := filepath.Join(tmpDir, "subdir")
|
||||||
|
file3 := filepath.Join(subDir, "test3.go")
|
||||||
|
|
||||||
|
require.NoError(t, os.WriteFile(file1, []byte("package main\n"), 0644))
|
||||||
|
require.NoError(t, os.WriteFile(file2, []byte("package main\n\nfunc main() {}\n"), 0644))
|
||||||
|
require.NoError(t, os.MkdirAll(subDir, 0755))
|
||||||
|
require.NoError(t, os.WriteFile(file3, []byte("package subdir\n"), 0644))
|
||||||
|
|
||||||
|
// Test scanning specific files
|
||||||
|
files := []string{file1, file3}
|
||||||
|
instructions := "Test instructions"
|
||||||
|
|
||||||
|
jsonData, err := ScanFiles(files, instructions)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Parse the JSON output
|
||||||
|
var result []any
|
||||||
|
err = json.Unmarshal(jsonData, &result)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Len(t, result, 3) // directory, report, instructions
|
||||||
|
|
||||||
|
// Check report
|
||||||
|
report := result[1].(map[string]any)
|
||||||
|
assert.Equal(t, "report", report["type"])
|
||||||
|
assert.Equal(t, float64(2), report["files"])
|
||||||
|
|
||||||
|
// Check instructions
|
||||||
|
instr := result[2].(map[string]any)
|
||||||
|
assert.Equal(t, "instructions", instr["type"])
|
||||||
|
assert.Equal(t, "Test instructions", instr["details"])
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestScanFilesSkipsDirectories(t *testing.T) {
|
||||||
|
tmpDir := t.TempDir()
|
||||||
|
|
||||||
|
file1 := filepath.Join(tmpDir, "test.go")
|
||||||
|
subDir := filepath.Join(tmpDir, "subdir")
|
||||||
|
|
||||||
|
require.NoError(t, os.WriteFile(file1, []byte("package main\n"), 0644))
|
||||||
|
require.NoError(t, os.MkdirAll(subDir, 0755))
|
||||||
|
|
||||||
|
// Include a directory in the file list - should be skipped
|
||||||
|
files := []string{file1, subDir}
|
||||||
|
|
||||||
|
jsonData, err := ScanFiles(files, "test")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
var result []any
|
||||||
|
err = json.Unmarshal(jsonData, &result)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Check that only 1 file was counted (directory was skipped)
|
||||||
|
report := result[1].(map[string]any)
|
||||||
|
assert.Equal(t, float64(1), report["files"])
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestScanFilesNonExistentFile(t *testing.T) {
|
||||||
|
files := []string{"/nonexistent/file.go"}
|
||||||
|
_, err := ScanFiles(files, "test")
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.Contains(t, err.Error(), "error accessing file")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestScanDirectory(t *testing.T) {
|
||||||
|
tmpDir := t.TempDir()
|
||||||
|
|
||||||
|
file1 := filepath.Join(tmpDir, "main.go")
|
||||||
|
require.NoError(t, os.WriteFile(file1, []byte("package main\n"), 0644))
|
||||||
|
|
||||||
|
jsonData, err := ScanDirectory(tmpDir, 3, "Test instructions", []string{})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
var result []any
|
||||||
|
err = json.Unmarshal(jsonData, &result)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Len(t, result, 3)
|
||||||
|
|
||||||
|
// Check instructions
|
||||||
|
instr := result[2].(map[string]any)
|
||||||
|
assert.Equal(t, "Test instructions", instr["details"])
|
||||||
|
}
|
||||||
109
cmd/code2context/main.go
Normal file
109
cmd/code2context/main.go
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Command line flags
|
||||||
|
maxDepth := flag.Int("depth", 3, "Maximum directory depth to scan")
|
||||||
|
ignorePatterns := flag.String("ignore", ".git,node_modules,vendor", "Comma-separated patterns to ignore")
|
||||||
|
outputFile := flag.String("out", "", "Output file (default: stdout)")
|
||||||
|
flag.Usage = printUsage
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
// Check if stdin has data (is a pipe)
|
||||||
|
stdinInfo, _ := os.Stdin.Stat()
|
||||||
|
hasStdin := (stdinInfo.Mode() & os.ModeCharDevice) == 0
|
||||||
|
|
||||||
|
var jsonData []byte
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if hasStdin {
|
||||||
|
// Stdin mode: read file list from stdin, instructions from argument
|
||||||
|
if flag.NArg() != 1 {
|
||||||
|
fmt.Fprintf(os.Stderr, "Error: When piping file list via stdin, provide exactly 1 argument: <instructions>\n")
|
||||||
|
fmt.Fprintf(os.Stderr, "Usage: find . -name '*.go' | code2context \"instructions\"\n")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
instructions := flag.Arg(0)
|
||||||
|
|
||||||
|
// Read file paths from stdin
|
||||||
|
var files []string
|
||||||
|
scanner := bufio.NewScanner(os.Stdin)
|
||||||
|
for scanner.Scan() {
|
||||||
|
line := strings.TrimSpace(scanner.Text())
|
||||||
|
if line != "" {
|
||||||
|
files = append(files, line)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := scanner.Err(); err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "Error reading stdin: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(files) == 0 {
|
||||||
|
fmt.Fprintf(os.Stderr, "Error: No files provided via stdin\n")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonData, err = ScanFiles(files, instructions)
|
||||||
|
} else {
|
||||||
|
// Directory mode: require directory and instructions arguments
|
||||||
|
if flag.NArg() != 2 {
|
||||||
|
printUsage()
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
directory := flag.Arg(0)
|
||||||
|
instructions := flag.Arg(1)
|
||||||
|
|
||||||
|
// Validate directory
|
||||||
|
if info, err := os.Stat(directory); err != nil || !info.IsDir() {
|
||||||
|
fmt.Fprintf(os.Stderr, "Error: Directory '%s' does not exist or is not a directory\n", directory)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse ignore patterns and scan directory
|
||||||
|
jsonData, err = ScanDirectory(directory, *maxDepth, instructions, strings.Split(*ignorePatterns, ","))
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "Error scanning: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output result
|
||||||
|
if *outputFile != "" {
|
||||||
|
if err := os.WriteFile(*outputFile, jsonData, 0644); err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "Error writing file: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fmt.Print(string(jsonData))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func printUsage() {
|
||||||
|
fmt.Fprintf(os.Stderr, `code2context - Code project scanner for use with Fabric AI
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
code2context [options] <directory> <instructions>
|
||||||
|
<file_list> | code2context [options] <instructions>
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
code2context . "Add input validation to all user inputs"
|
||||||
|
code2context -depth 4 ./my-project "Implement error handling"
|
||||||
|
code2context -out project.json ./src "Fix security issues"
|
||||||
|
find . -name '*.go' | code2context "Refactor error handling"
|
||||||
|
git ls-files '*.py' | code2context "Add type hints"
|
||||||
|
|
||||||
|
Options:
|
||||||
|
`)
|
||||||
|
flag.PrintDefaults()
|
||||||
|
}
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
// Command line flags
|
|
||||||
maxDepth := flag.Int("depth", 3, "Maximum directory depth to scan")
|
|
||||||
ignorePatterns := flag.String("ignore", ".git,node_modules,vendor", "Comma-separated patterns to ignore")
|
|
||||||
outputFile := flag.String("out", "", "Output file (default: stdout)")
|
|
||||||
flag.Usage = printUsage
|
|
||||||
flag.Parse()
|
|
||||||
|
|
||||||
// Require exactly two positional arguments: directory and instructions
|
|
||||||
if flag.NArg() != 2 {
|
|
||||||
printUsage()
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
directory := flag.Arg(0)
|
|
||||||
instructions := flag.Arg(1)
|
|
||||||
|
|
||||||
// Validate directory
|
|
||||||
if info, err := os.Stat(directory); err != nil || !info.IsDir() {
|
|
||||||
fmt.Fprintf(os.Stderr, "Error: Directory '%s' does not exist or is not a directory\n", directory)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse ignore patterns and scan directory
|
|
||||||
jsonData, err := ScanDirectory(directory, *maxDepth, instructions, strings.Split(*ignorePatterns, ","))
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "Error scanning directory: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Output result
|
|
||||||
if *outputFile != "" {
|
|
||||||
if err := os.WriteFile(*outputFile, jsonData, 0644); err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "Error writing file: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fmt.Print(string(jsonData))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func printUsage() {
|
|
||||||
fmt.Fprintf(os.Stderr, `code_helper - Code project scanner for use with Fabric AI
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
code_helper [options] <directory> <instructions>
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
code_helper . "Add input validation to all user inputs"
|
|
||||||
code_helper -depth 4 ./my-project "Implement error handling"
|
|
||||||
code_helper -out project.json ./src "Fix security issues"
|
|
||||||
|
|
||||||
Options:
|
|
||||||
`)
|
|
||||||
flag.PrintDefaults()
|
|
||||||
}
|
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
var version = "v1.4.372"
|
var version = "v1.4.374"
|
||||||
|
|||||||
Binary file not shown.
@@ -4,10 +4,10 @@ Generate code changes to an existing coding project using AI.
|
|||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
After installing the `code_helper` binary:
|
After installing the `code2context` binary:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
go install github.com/danielmiessler/fabric/cmd/code_helper@latest
|
go install github.com/danielmiessler/fabric/cmd/code2context@latest
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
@@ -15,18 +15,18 @@ go install github.com/danielmiessler/fabric/cmd/code_helper@latest
|
|||||||
The create_coding_feature allows you to apply AI-suggested code changes directly to your project files. Use it like this:
|
The create_coding_feature allows you to apply AI-suggested code changes directly to your project files. Use it like this:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
code_helper [project_directory] "[instructions for code changes]" | fabric --pattern create_coding_feature
|
code2context [project_directory] "[instructions for code changes]" | fabric --pattern create_coding_feature
|
||||||
```
|
```
|
||||||
|
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
code_helper . "Create a simple Hello World C program in file main.c" | fabric --pattern create_coding_feature
|
code2context . "Create a simple Hello World C program in file main.c" | fabric --pattern create_coding_feature
|
||||||
```
|
```
|
||||||
|
|
||||||
## How It Works
|
## How It Works
|
||||||
|
|
||||||
1. `code_helper` scans your project directory and creates a JSON representation
|
1. `code2context` scans your project directory and creates a JSON representation
|
||||||
2. The AI model analyzes your project structure and instructions
|
2. The AI model analyzes your project structure and instructions
|
||||||
3. AI generates file changes in a standard format
|
3. AI generates file changes in a standard format
|
||||||
4. Fabric parses these changes and prompts you to confirm
|
4. Fabric parses these changes and prompts you to confirm
|
||||||
@@ -36,7 +36,7 @@ code_helper . "Create a simple Hello World C program in file main.c" | fabric --
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Request AI to create a Hello World program
|
# Request AI to create a Hello World program
|
||||||
code_helper . "Create a simple Hello World C program in file main.c" | fabric --pattern create_coding_feature
|
code2context . "Create a simple Hello World C program in file main.c" | fabric --pattern create_coding_feature
|
||||||
|
|
||||||
# Review the changes made to your project
|
# Review the changes made to your project
|
||||||
git diff
|
git diff
|
||||||
@@ -52,7 +52,7 @@ git commit -s -m "Add Hello World program"
|
|||||||
### Security Enhancement Example
|
### Security Enhancement Example
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
code_helper . "Ensure that all user input is validated and sanitized before being used in the program." | fabric --pattern create_coding_feature
|
code2context . "Ensure that all user input is validated and sanitized before being used in the program." | fabric --pattern create_coding_feature
|
||||||
git diff
|
git diff
|
||||||
make check
|
make check
|
||||||
git add <changed files>
|
git add <changed files>
|
||||||
|
|||||||
@@ -10,12 +10,20 @@ import (
|
|||||||
"slices"
|
"slices"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
debuglog "github.com/danielmiessler/fabric/internal/log"
|
debuglog "github.com/danielmiessler/fabric/internal/log"
|
||||||
|
|
||||||
openai "github.com/openai/openai-go"
|
openai "github.com/openai/openai-go"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// transcriptionResult holds the result of a single chunk transcription.
|
||||||
|
type transcriptionResult struct {
|
||||||
|
index int
|
||||||
|
text string
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
// MaxAudioFileSize defines the maximum allowed size for audio uploads (25MB).
|
// MaxAudioFileSize defines the maximum allowed size for audio uploads (25MB).
|
||||||
const MaxAudioFileSize int64 = 25 * 1024 * 1024
|
const MaxAudioFileSize int64 = 25 * 1024 * 1024
|
||||||
|
|
||||||
@@ -73,27 +81,56 @@ func (o *Client) TranscribeFile(ctx context.Context, filePath, model string, spl
|
|||||||
files = []string{filePath}
|
files = []string{filePath}
|
||||||
}
|
}
|
||||||
|
|
||||||
var builder strings.Builder
|
resultsChan := make(chan transcriptionResult, len(files))
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
|
||||||
for i, f := range files {
|
for i, f := range files {
|
||||||
debuglog.Log("Using model %s to transcribe part %d (file name: %s)...\n", model, i+1, f)
|
wg.Add(1)
|
||||||
var chunk *os.File
|
go func(index int, filePath string) {
|
||||||
if chunk, err = os.Open(f); err != nil {
|
defer wg.Done()
|
||||||
return "", err
|
debuglog.Log("Using model %s to transcribe part %d (file name: %s)...\n", model, index+1, filePath)
|
||||||
}
|
|
||||||
params := openai.AudioTranscriptionNewParams{
|
chunk, openErr := os.Open(filePath)
|
||||||
File: chunk,
|
if openErr != nil {
|
||||||
Model: openai.AudioModel(model),
|
resultsChan <- transcriptionResult{index: index, err: openErr}
|
||||||
}
|
return
|
||||||
var resp *openai.Transcription
|
}
|
||||||
resp, err = o.ApiClient.Audio.Transcriptions.New(ctx, params)
|
defer chunk.Close()
|
||||||
chunk.Close()
|
|
||||||
if err != nil {
|
params := openai.AudioTranscriptionNewParams{
|
||||||
return "", err
|
File: chunk,
|
||||||
|
Model: openai.AudioModel(model),
|
||||||
|
}
|
||||||
|
resp, transcribeErr := o.ApiClient.Audio.Transcriptions.New(ctx, params)
|
||||||
|
if transcribeErr != nil {
|
||||||
|
resultsChan <- transcriptionResult{index: index, err: transcribeErr}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resultsChan <- transcriptionResult{index: index, text: resp.Text}
|
||||||
|
}(i, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
close(resultsChan)
|
||||||
|
|
||||||
|
results := make([]transcriptionResult, 0, len(files))
|
||||||
|
for result := range resultsChan {
|
||||||
|
if result.err != nil {
|
||||||
|
return "", result.err
|
||||||
}
|
}
|
||||||
|
results = append(results, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Slice(results, func(i, j int) bool {
|
||||||
|
return results[i].index < results[j].index
|
||||||
|
})
|
||||||
|
|
||||||
|
var builder strings.Builder
|
||||||
|
for i, result := range results {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
builder.WriteString(" ")
|
builder.WriteString(" ")
|
||||||
}
|
}
|
||||||
builder.WriteString(resp.Text)
|
builder.WriteString(result.text)
|
||||||
}
|
}
|
||||||
|
|
||||||
return builder.String(), nil
|
return builder.String(), nil
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
"1.4.372"
|
"1.4.374"
|
||||||
|
|||||||
Reference in New Issue
Block a user