Compare commits

...

1028 Commits

Author SHA1 Message Date
github-actions[bot]
a32cc5fa01 Update version to v1.4.232 and commit 2025-07-06 07:22:25 +00:00
Daniel Miessler 🛡️
26b5bb2e9e Merge pull request #1577 from ksylvan/0705-custom-patterns-dir
Add Custom Patterns Directory Support
2025-07-06 00:20:58 -07:00
Kayvan Sylvan
b751d323b1 feat: add custom patterns directory support with environment variable configuration
## CHANGES

- Add custom patterns directory support via environment variable
- Implement custom patterns plugin with registry integration
- Override main patterns with custom directory patterns
- Expand home directory paths in custom patterns config
- Add comprehensive test coverage for custom patterns functionality
- Integrate custom patterns into plugin setup workflow
- Support pattern precedence with custom over main patterns
2025-07-05 23:51:43 -07:00
github-actions[bot]
d081fd269c Update version to v1.4.231 and commit 2025-07-05 22:25:30 +00:00
Kayvan Sylvan
369a0a850d Merge pull request #1565 from ksylvan/0701-claude-oauth-support
OAuth Authentication Support for Anthropic
2025-07-05 15:23:56 -07:00
Kayvan Sylvan
8dc5343ee6 fix: remove duplicate API key setup question in Anthropic client 2025-07-05 15:05:21 -07:00
Kayvan Sylvan
eda552dac5 refactor: extract OAuth functionality from anthropic client to separate module
## CHANGES

- Remove OAuth transport implementation from main client
- Extract OAuth flow functions to separate module
- Remove unused imports and constants from client
- Replace inline OAuth transport with NewOAuthTransport call
- Update runOAuthFlow to exported RunOAuthFlow function
- Clean up token management and refresh logic
- Simplify client configuration by removing OAuth internals
2025-07-05 14:59:38 -07:00
Kayvan Sylvan
f13a56685b feat: add OAuth login support for Anthropic API configuration 2025-07-05 14:46:43 -07:00
Kayvan Sylvan
2f9afe0247 feat: remove OAuth flow functions for simplified token handling 2025-07-05 11:45:25 -07:00
Kayvan Sylvan
1ec525ad97 chore: simplify base URL configuration in configure method
### CHANGES

- Remove redundant base URL trimming logic
- Append base URL directly without modification
- Eliminate conditional check for API version suffix
2025-07-05 11:39:35 -07:00
Kayvan Sylvan
b7dc6748e0 feat: enhance OAuth authentication flow with automatic re-authentication and timeout handling
## CHANGES

- Add automatic OAuth flow initiation when no token exists
- Implement fallback re-authentication when token refresh fails
- Add timeout contexts for OAuth and refresh operations
- Create context-aware OAuth flow and token exchange functions
- Enhance error handling with graceful authentication recovery
- Add user input timeout protection for authorization codes
- Preserve refresh tokens during token exchange operations
2025-07-05 09:59:27 -07:00
Kayvan Sylvan
f1b612d828 refactor: remove OAuth endpoint logic and standardize on v2 API endpoint
## CHANGES

- Remove OAuth-specific v1 endpoint handling logic
- Standardize all API calls to use v2 endpoint
- Simplify baseURL configuration by removing conditional branching
- Update endpoint logic to always append v2 suffix
2025-07-05 09:37:57 -07:00
Kayvan Sylvan
eac5a104f2 feat: implement OAuth token refresh and persistent storage for Claude authentication
## CHANGES

- Add automatic OAuth token refresh when expired
- Implement persistent token storage using common OAuth storage
- Remove deprecated AuthToken setting from client configuration
- Add token validation with 5-minute expiration buffer
- Create refreshToken function for seamless token renewal
- Update OAuth flow to save complete token information
- Enhance error handling for OAuth authentication failures
- Simplify client configuration by removing manual token management
2025-07-05 09:17:50 -07:00
Kayvan Sylvan
4bff88fae3 feat: add OAuth authentication support for Anthropic Claude
- Move golang.org/x/oauth2 from indirect to direct dependency
- Add OAuth login option for Anthropic client
- Implement PKCE OAuth flow with browser integration
- Add custom HTTP transport for OAuth Bearer tokens
- Support both API key and OAuth authentication methods
- Add Claude Code system message for OAuth sessions
- Update REST API to handle OAuth tokens
- Improve environment variable name sanitization with regex
2025-07-05 08:32:16 -07:00
github-actions[bot]
acf1be71ce Update version to v1.4.230 and commit 2025-07-05 07:08:05 +00:00
Kayvan Sylvan
236a3c5f38 Merge pull request #1575 from ksylvan/0704-advanced-image-output-options
Advanced image generation parameters for OpenAI models
2025-07-05 00:06:38 -07:00
Kayvan Sylvan
b2418984f8 feat: add advanced image generation parameters for OpenAI models
## CHANGES

- Add four new image generation CLI flags
- Implement validation for image parameter combinations
- Support size, quality, compression, and background controls
- Add comprehensive test coverage for new parameters
- Update shell completions for new image options
- Enhance README with detailed image generation examples
- Fix PowerShell code block formatting issues
2025-07-04 23:04:50 -07:00
github-actions[bot]
152d74d160 Update version to v1.4.229 and commit 2025-07-05 01:59:22 +00:00
Kayvan Sylvan
4e16bbccd8 Merge pull request #1574 from ksylvan/0704-image-tool-model-validation
Add Model Validation for Image Generation and Fix CLI Flag Mapping
2025-07-04 18:57:51 -07:00
Kayvan Sylvan
60174f41a4 refactor: extract supported models list to shared constant for image generation validation
## CHANGES

• Extract hardcoded model lists into shared constant
• Create ImageGenerationSupportedModels variable for reusability
• Update supportsImageGeneration function to use shared constant
• Refactor error messages to reference centralized model list
• Add documentation comment for supported models variable
• Import strings package in test file
• Consolidate duplicate model validation logic across files
2025-07-04 18:52:49 -07:00
Kayvan Sylvan
ad4683952e Merge branch 'main' into 0704-image-tool-model-validation 2025-07-04 18:45:08 -07:00
Kayvan Sylvan
86a044735b feat: add model validation for image generation support
### CHANGES

- Add model field to `BuildChatOptions` method
- Implement `supportsImageGeneration` function for model checks
- Validate model supports image generation in `sendResponses`
- Remove `mars-colony.png` from repository
- Add tests for `supportsImageGeneration` function
- Validate image file support in `TestModelValidationLogic`
2025-07-04 18:40:20 -07:00
github-actions[bot]
58583114cb Update version to v1.4.228 and commit 2025-07-05 01:13:09 +00:00
Kayvan Sylvan
36524cd2e4 Merge pull request #1573 from ksylvan/0704-image-dynamic-formats
Add Image File Validation and Dynamic Format Support
2025-07-04 18:11:36 -07:00
Kayvan Sylvan
e59156ac2b feat: add image file validation and format detection for image generation
## CHANGES

• Add image file path validation with extension checking
• Implement dynamic output format detection from file extensions
• Update BuildChatOptions method to return error for validation
• Add comprehensive test coverage for image file validation
• Upgrade YAML library from v2 to v3
• Update shell completions to reflect supported image formats
• Add error handling for existing file conflicts
• Support PNG, JPEG, JPG, and WEBP image formats
2025-07-04 17:56:59 -07:00
Daniel Miessler
1eac026e92 Addded tutorial as a tag. 2025-07-04 16:42:19 -07:00
github-actions[bot]
17d863fd57 Update version to v1.4.227 and commit 2025-07-04 22:40:01 +00:00
Daniel Miessler 🛡️
7c9dbfd343 Merge pull request #1572 from ksylvan/0704-OpenAI-Image-Generation-Tool
Add Image Generation Support to Fabric
2025-07-04 15:38:27 -07:00
Kayvan Sylvan
d9260bdf26 chore: refactor image generation constants for clarity and reuse
### CHANGES

- Define `ImageGenerationResponseType` constant for response handling
- Define `ImageGenerationToolType` constant for tool type usage
- Update `addImageGenerationTool` to use defined constants
- Refactor `extractAndSaveImages` to use response type constant
2025-07-04 15:14:46 -07:00
Kayvan Sylvan
63a0cfeb1e feat: add web search and image file support to fabric CLI
## CHANGES

- Add web search tool for Anthropic and OpenAI models
- Add search location parameter for web search results
- Add image file output option with format support
- Update zsh completion with new search and image flags
- Update bash completion with new option handling logic
- Update fish completion with search and image descriptions
- Support PNG, JPG, JPEG, GIF, BMP image formats
2025-07-04 14:49:40 -07:00
Kayvan Sylvan
12fc6e2000 feat: add image generation support with OpenAI image generation model
## CHANGES

- Add `--image-file` flag for saving generated images
- Implement image generation tool integration with OpenAI
- Support image editing with attachment input files
- Add comprehensive test coverage for image features
- Update documentation with image generation examples
- Fix HTML formatting issues in README
- Improve PowerShell code block indentation
- Clean up help text formatting and spacing
2025-07-04 14:36:55 -07:00
Daniel Miessler
fe5900a5dc Fixed ul tag applier. 2025-07-04 14:25:54 -07:00
Daniel Miessler
1b6b8e3d72 Updated ul tag prompt. 2025-07-04 14:21:25 -07:00
Daniel Miessler
c85301cb1f Added the UL tags pattern. 2025-07-04 14:17:43 -07:00
github-actions[bot]
7cc8226339 Update version to v1.4.226 and commit 2025-07-04 07:25:58 +00:00
Kayvan Sylvan
fc8c4babf8 Merge pull request #1569 from ksylvan/0703-openai-web-search
OpenAI Plugin Now Supports Web Search Functionality
2025-07-04 00:24:32 -07:00
Kayvan Sylvan
bd809a1f94 docs: update README with new web search feature details 2025-07-04 00:22:36 -07:00
Kayvan Sylvan
50aec6291b feat: add web search tool support for OpenAI models with citation formatting
## CHANGES

- Enable web search tool for OpenAI models
- Add location parameter support for search results
- Extract and format citations from search responses
- Implement citation deduplication to avoid duplicates
- Add comprehensive test coverage for search functionality
- Update CLI flag description to include OpenAI
- Format citations as markdown links with sources
2025-07-04 00:01:54 -07:00
github-actions[bot]
f927fdf40f Update version to v1.4.225 and commit 2025-07-04 06:58:02 +00:00
Kayvan Sylvan
918862ef57 Merge pull request #1568 from ksylvan/0703-enhanced-anthropic-search-tool
Runtime Web Search Control via Command-Line Flag
2025-07-03 23:56:34 -07:00
Kayvan Sylvan
d9b8bc3233 chore: refactor Send method to optimize string building
### CHANGES

- Add `sourcesHeader` constant for citation section title.
- Use `strings.Builder` to construct result efficiently.
- Append sources header and citations in result builder.
- Update `ret` to use constructed string from builder.
2025-07-03 23:52:12 -07:00
Kayvan Sylvan
da29b8e388 chore: remove unused web-search tool parameters for simplification
### CHANGES

- Remove unused `AllowedDomains` and `MaxUses` parameters
- Simplify `webTool` definition in `buildMessageParams` method
2025-07-03 23:41:22 -07:00
Kayvan Sylvan
5e6d4110fa refactor: extract web search tool constants in anthropic plugin
## CHANGES

- Add webSearchToolName constant for tool identification
- Add webSearchToolType constant for tool versioning
- Replace hardcoded string literals with named constants
- Improve code maintainability through constant extraction
2025-07-03 23:20:19 -07:00
Kayvan Sylvan
4bb090694b chore: update formatOptions to include search options display
### CHANGES

- Add search option status to `formatOptions`
- Include `SearchLocation` in formatted output if specified
2025-07-03 22:55:55 -07:00
Kayvan Sylvan
d232222787 feat: add web search tool support for Anthropic models
## CHANGES

- Add --search flag to enable web search
- Add --search-location for timezone-based results
- Pass search options through ChatOptions struct
- Implement web search tool in Anthropic client
- Format search citations with sources section
- Add comprehensive tests for search functionality
- Remove plugin-level web search configuration
2025-07-03 22:40:39 -07:00
github-actions[bot]
095890a556 Update version to v1.4.224 and commit 2025-07-01 21:44:24 +00:00
Kayvan Sylvan
64c1fe18ef Merge pull request #1564 from ksylvan/0701-code-review-pattern
Add code_review pattern and updates in Pattern_Descriptions
2025-07-01 14:42:50 -07:00
Kayvan Sylvan
1cea32a677 feat: handle JSONDecodeError in load_existing_file gracefully
### CHANGES

- Add JSONDecodeError handling with warning message.
- Initialize with empty list on JSON decode failure.
- Reorder pattern processing to reduce redundant logs.
- Remove redundant directory check logging.
- Ensure new pattern processing is logged correctly.
2025-07-01 14:36:35 -07:00
Kayvan Sylvan
49658a3214 feat: add new patterns for code review, alpha extraction, and server analysis
### CHANGES
- Add `review_code`, `extract_alpha`, and `extract_mcp_servers` patterns.
- Refactor the pattern extraction script for improved clarity.
- Add docstrings and specific error handling to script.
- Improve formatting in the pattern management README.
- Fix typo in the `analyze_bill_short` pattern description.
2025-07-01 14:05:41 -07:00
Kayvan Sylvan
f236cab276 feat: add comprehensive code review pattern for systematic analysis
## CHANGES

- Add new code review system prompt
- Define principal engineer reviewer role
- Include systematic analysis framework
- Specify markdown output format
- Add prioritized recommendations section
- Include detailed feedback structure
- Provide example Python review
- Cover security, performance, readability
- Add error handling guidelines
2025-07-01 13:43:04 -07:00
github-actions[bot]
5e0aaa1f93 Update version to v1.4.223 and commit 2025-07-01 14:52:18 +00:00
Kayvan Sylvan
eb16806931 Merge pull request #1563 from ksylvan/0701-fix-windows-build
Fix Cross-Platform Compatibility in Release Workflow
2025-07-01 07:50:46 -07:00
Kayvan Sylvan
474dd786a4 chore: update GitHub Actions to use bash shell in release job
### CHANGES

- Adjust repository_dispatch type spacing for consistency
- Use bash shell for creating release if absent
2025-07-01 07:45:05 -07:00
github-actions[bot]
edad63df19 Update version to v1.4.222 and commit 2025-07-01 14:17:23 +00:00
Kayvan Sylvan
c7eb7439ef Merge pull request #1559 from ksylvan/0629-openai-responses-api
OpenAI Plugin Migrates to New Responses API
2025-07-01 07:15:43 -07:00
Daniel Miessler
23d678d62f Updated alpha post. 2025-06-30 06:50:47 -07:00
Kayvan Sylvan
de5260a661 feat(openai): add support for multi-content user messages in chat completions
### CHANGES

- Enhance user message conversion to support multi-content.
- Add capability to process image URLs in messages.
- Build multi-part messages with both text and images.
2025-06-30 00:21:42 -07:00
Kayvan Sylvan
baeadc2270 chore: update NewClient to use NewClientCompatibleWithResponses
### CHANGES

- Modify `NewClient` to call `NewClientCompatibleWithResponses`
- Add support for response handling in client initialization
2025-06-30 00:13:15 -07:00
Kayvan Sylvan
5b4cec81c3 feat: simplify supportsResponsesAPI 2025-06-29 23:57:57 -07:00
Kayvan Sylvan
eda5531087 refactor: extract common message conversion logic to reduce duplication
## CHANGES

- Extract shared message conversion to convertMessageCommon
- Reuse logic between chat and response APIs
- Maintain existing text-only behavior for chat
- Support multi-content messages in response API
- Reduce code duplication across converters
- Preserve backward compatibility for both APIs
2025-06-29 23:48:14 -07:00
Kayvan Sylvan
66925d188a fix: move channel close to defer statement in OpenAI streaming methods
## CHANGES

- Move close(channel) to defer statement
- Ensure channel closes even on errors
- Apply fix to sendStreamChatCompletions method
- Apply fix to sendStreamResponses method
- Improve error handling reliability
- Prevent potential channel leaks
2025-06-29 23:27:24 -07:00
Kayvan Sylvan
6179742e79 feat: add chat completions API support for OpenAI-compatible providers
## CHANGES

* Add chat completions API fallback for non-Responses API providers
* Implement `sendChatCompletions` and `sendStreamChatCompletions` methods
* Introduce `buildChatCompletionParams` to construct API request parameters
* Add `ImplementsResponses` flag to track provider API capabilities
* Update provider configurations with Responses API support status
* Enhance `Send` and `SendStream` methods to use appropriate API endpoints
2025-06-29 22:52:55 -07:00
Kayvan Sylvan
d8fc6940f0 feat: migrate OpenAI plugin to use new responses API instead of chat completions
- Replace chat completions with responses API
- Update message conversion to new format
- Refactor streaming to handle event types
- Remove frequency and presence penalty params
- Replace seed parameter with max tokens
- Update test cases for new API
- Add response text extraction method
2025-06-29 21:06:12 -07:00
Daniel Miessler
44f7e8dfef Updated extract alpha. 2025-06-28 15:18:53 -07:00
Daniel Miessler
c5ada714ff Updated extract alpha. 2025-06-28 15:17:10 -07:00
Daniel Miessler
80c4807f7e Added extract_alpha as kind of an experiment. 2025-06-28 15:14:14 -07:00
github-actions[bot]
b4126b6798 Update version to v1.4.221 and commit 2025-06-28 15:03:37 +00:00
Daniel Miessler 🛡️
f2ffa64af9 Merge pull request #1556 from ksylvan/0628-migrate-to-official-openai-go 2025-06-28 08:02:08 -07:00
Kayvan Sylvan
09e01eddf4 refactor: abstract chat message structs and migrate to official openai-go SDK
### CHANGES

- Introduce local `chat` package for message abstraction
- Replace sashabaranov/go-openai with official openai-go SDK
- Update OpenAI, Azure, and Exolab plugins for new client
- Refactor all AI providers to use internal chat types
- Decouple codebase from third-party AI provider structs
- Replace deprecated `ioutil` functions with `os` equivalents
2025-06-28 07:28:49 -07:00
github-actions[bot]
aa028a4a57 Update version to v1.4.220 and commit 2025-06-28 05:28:02 +00:00
Kayvan Sylvan
d8d157404c Merge pull request #1555 from ksylvan/0627-github-actions-release-fix
fix: Race condition in GitHub actions release flow
2025-06-27 22:26:27 -07:00
Kayvan Sylvan
d0602c9653 chore: improve release creation to gracefully handle pre-existing tags.
### CHANGES

*   Check if a release exists before attempting creation.
*   Suppress error output from `gh release view` command.
*   Add an informative log when release already exists.
2025-06-27 21:05:14 -07:00
github-actions[bot]
35155496a4 Update version to v1.4.219 and commit 2025-06-28 02:59:32 +00:00
Kayvan Sylvan
eef16b89f2 Merge pull request #1553 from ksylvan/0627-deepwiki-badge-added
docs: add DeepWiki badge and fix minor typos in README
2025-06-27 19:58:00 -07:00
Kayvan Sylvan
7f66097577 docs: add DeepWiki badge and fix minor typos in README
## CHANGES

- Add DeepWiki badge to README header
- Fix typo "chatbots" to "chat-bots"
- Correct "Perlexity" to "Perplexity"
- Fix "distro" to "Linux distribution"
- Add alt text to contributor images
- Update dependency versions in go.mod
- Remove unused soup dependency
2025-06-27 19:34:01 -07:00
Kayvan Sylvan
2012f22a9c Merge pull request #1552 from nawarajshahi/main
Fix typos in README.md
2025-06-27 12:18:47 -07:00
Nawaraj Shahi
08695c9e24 Fix typos on README.md 2025-06-27 10:14:48 -04:00
github-actions[bot]
d8cc9b5eef Update version to v1.4.218 and commit 2025-06-27 00:22:16 +00:00
Kayvan Sylvan
9dbe20cf7b Merge pull request #1550 from ksylvan/0626-more-openai-raw-mode
Add Support for OpenAI Search and Research Model Variants
2025-06-26 17:20:47 -07:00
Kayvan Sylvan
64763e1303 feat: add support for new OpenAI search and research model variants
## CHANGES

- Add slices import for array operations
- Define new search preview model names
- Add mini search preview variants
- Include deep research model support
- Add June 2025 dated model versions
- Replace hardcoded check with slices.Contains
- Support both prefix and exact model matching
2025-06-26 17:06:25 -07:00
github-actions[bot]
126a9ff406 Update version to v1.4.217 and commit 2025-06-26 23:09:56 +00:00
Kayvan Sylvan
e906425138 Merge pull request #1546 from ksylvan/0626-fix-yt-in-web-interface
New YouTube Transcript Endpoint Added to REST API
2025-06-26 16:08:23 -07:00
Daniel Miessler
df4a560302 Add extract_mcp_servers pattern
New pattern to extract mentions of MCP (Model Context Protocol) servers from content. Identifies server names, features, capabilities, and usage examples.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-26 11:39:21 -07:00
Kayvan Sylvan
34cf669bd4 chore: fix endpoint calls from frontend 2025-06-26 01:37:53 -07:00
Kayvan Sylvan
0dbe1bbb4e feat: add dedicated YouTube transcript API endpoint
## CHANGES

- Add new YouTube handler for transcript requests
- Create `/youtube/transcript` POST endpoint route
- Add request/response types for YouTube API
- Support language and timestamp options
- Update frontend to use new endpoint
- Remove chat endpoint dependency for transcripts
- Validate video vs playlist URLs properly
2025-06-26 01:21:27 -07:00
github-actions[bot]
e29ed908e6 Update version to v1.4.216 and commit 2025-06-26 06:52:16 +00:00
Kayvan Sylvan
3d049a435a Merge pull request #1545 from ksylvan/0625-fix-attachments-used-with-patterns
Update Message Handling for Attachments and Multi-Modal content
2025-06-25 23:50:43 -07:00
Kayvan Sylvan
1a335b3fb9 refactor(ai): unify assistant and user message formatting in dryrun
### CHANGES

- Unify assistant and user message formatting logic.
- Use `formatMultiContentMessage` for assistant role messages.
- Improve dryrun support for multi-part message content.
2025-06-25 23:49:23 -07:00
Kayvan Sylvan
e2430b6c75 fix: correctly combine text and attachments in raw mode sessions
### CHANGES

- Combine user text and attachments into MultiContent.
- Preserve existing non-text parts like images.
- Use standard content field for text-only messages.
2025-06-25 23:28:12 -07:00
Kayvan Sylvan
2497f10eca feat: add MultiContent support to chat message construction in raw mode 2025-06-25 23:18:56 -07:00
Kayvan Sylvan
f62d2198f9 refactor: extract message and option formatting logic into reusable methods
## CHANGES

- Extract multi-content message formatting to dedicated method
- Create formatMessages method for all message types
- Add formatOptions method for chat options display
- Replace inline formatting with strings.Builder usage
- Reduce code duplication between Send and SendStream
- Improve code organization and maintainability
2025-06-25 22:08:26 -07:00
Kayvan Sylvan
816e4072f4 fix(chatter): prevent duplicate user message when applying patterns
### CHANGES

*   Prevent adding user message twice when using patterns.
*   Ensure multi-part content is always included in session.
2025-06-25 21:43:46 -07:00
Kayvan Sylvan
85ee6196bd chore: fix formatting. 2025-06-25 18:31:46 -07:00
Kayvan Sylvan
e15645c1bc chore: clean up comments in chatter.go for clarity 2025-06-25 17:15:13 -07:00
Kayvan Sylvan
fada6bb044 chore: simplify user message appending logic in BuildSession
### CHANGES
- Remove conditional check for pattern name in message appending.
- Always append user message if it exists in request.
2025-06-25 17:12:48 -07:00
Kayvan Sylvan
4ad14bb752 feat: enhance dryrun client to display multi-content user messages
### CHANGES

- Handle multi-content messages for the user role.
- Display image URLs from user messages in output.
- Update both `Send` and `SendStream` methods.
- Retain existing behavior for simple text messages.
2025-06-25 17:08:30 -07:00
Kayvan Sylvan
97fc9b0d58 feat: allow combining user messages and attachments with patterns
- Allow user messages and attachments with patterns.
- Append user message to session regardless of pattern.
- Refactor chat request builder for improved clarity.
2025-06-25 16:24:47 -07:00
github-actions[bot]
ad0df37d10 Update version to v1.4.215 and commit 2025-06-25 11:07:45 +00:00
Kayvan Sylvan
666302c3c1 Merge pull request #1543 from ksylvan/0625-fix-pattern-descriptions-json
fix: Revert multiline tags in generated json files
2025-06-25 04:06:12 -07:00
Kayvan Sylvan
71e20cf251 chore: reformat pattern_descriptions.json to improve readability
### CHANGES

- Reformat JSON `tags` array to display on new lines.
- Update `write_essay` pattern description for clarity.
- Apply consistent formatting to both data files.
2025-06-25 03:55:00 -07:00
github-actions[bot]
b591666366 Update version to v1.4.214 and commit 2025-06-25 09:51:32 +00:00
Daniel Miessler 🛡️
155d9f0a76 Merge pull request #1542 from ksylvan/0624-write-essay-by-author-and-updates 2025-06-25 02:49:54 -07:00
Kayvan Sylvan
6a7cca65b4 chore: Fixes caught by review 2025-06-24 23:09:14 -07:00
Kayvan Sylvan
94020dbde0 chore: rename essay patterns to clarify Paul Graham style and author variable usage
## CHANGES

- Rename `write_essay` to `write_essay_pg` for Paul Graham style
- Rename `write_essay_by_author` to `write_essay` with author variable
- Update pattern descriptions to reflect naming changes
- Fix duplicate `write_essay_pg` entry in pattern descriptions
2025-06-24 21:54:39 -07:00
Kayvan Sylvan
f949391098 feat: add new pattern and update pattern metadata files.
### CHANGES

- Add tags and descriptions for five new creative and analytical patterns.
- Introduce `analyze_terraform_plan` for infrastructure review.
- Add `write_essay_by_author` for stylistic writing.
- Include `summarize_board_meeting` for corporate notes.
- Introduce `create_mnemonic_phrases` for memory aids.
- Update and clean pattern description data files.
- Sort the pattern explanations list alphabetically.
2025-06-24 12:42:39 -07:00
Kayvan Sylvan
64c3c69a70 Merge branch 'danielmiessler:main' into main 2025-06-23 13:03:07 -07:00
github-actions[bot]
4a830394be Update version to v1.4.213 and commit 2025-06-23 20:01:04 +00:00
Kayvan Sylvan
9f8a2d3b59 Merge pull request #1538 from andrewsjg/bug/bedrock-region-handling
Bug/bedrock region handling
2025-06-23 12:59:30 -07:00
github-actions[bot]
4353bc9f7f Update version to v1.4.212 and commit 2025-06-23 19:57:58 +00:00
Kayvan Sylvan
7a8024ee79 Merge pull request #1540 from ksylvan/0623-langdock-ai
Add Langdock AI and enhance generic OpenAI compatible support
2025-06-23 12:56:25 -07:00
Kayvan Sylvan
b5bf75ad2e chore: refactor ProviderMap for dynamic URL template handling
# CHANGES

- Add `os` and `strings` packages to imports
- Implement dynamic URL handling with environment variables
- Refactor provider configuration to support URL templates
- Reorder providers for consistent key order in ProviderMap
- Extract and parse template variables from BaseURL
- Use environment variables or default values for templates
- Replace template with actual values in BaseURL
2025-06-23 12:38:52 -07:00
Kayvan Sylvan
1ae847f397 chore: refactor ProviderMap for dynamic URL template handling
# CHANGES

- Add `os` and `strings` packages to imports
- Implement dynamic URL handling with environment variables
- Refactor provider configuration to support URL templates
- Reorder providers for consistent key order in ProviderMap
- Extract and parse template variables from BaseURL
- Use environment variables or default values for templates
- Replace template with actual values in BaseURL
2025-06-23 12:35:59 -07:00
Kayvan Sylvan
3fd923f6b8 chore: refactor Bedrock client to improve error handling and add interface compliance
## CHANGES

- Add ai.Vendor interface implementation check
- Improve error handling with wrapped errors
- Add AWS region validation logic
- Fix resource cleanup in SendStream
- Add nil checks for response parsing
- Update context usage to Background()
- Add user agent constants
- Enhance code documentation
2025-06-23 09:13:11 -07:00
James Andrews
eb251139b8 bedrock region handling - updated to set region value correctly if it exists in the config 2025-06-23 00:12:58 +01:00
James Andrews
0b5d3cfc30 bedrock region handling - updated to fix bad pointer reference 2025-06-23 00:03:32 +01:00
James Andrews
14a3c11930 Fixed bedrock region handling 2025-06-22 23:22:45 +01:00
James Andrews
c8cf6da0cc Updated hasAWSCredentials to also check for AWS_DEFAULT_REGION when access keys are configured in the environment 2025-06-22 14:27:04 +01:00
Daniel Miessler
a2c954ba50 Updated paper analyzer. 2025-06-19 14:48:05 -07:00
github-actions[bot]
730d0adc86 Update version to v1.4.211 and commit 2025-06-19 21:47:20 +00:00
Kayvan Sylvan
dc9168ab6f Merge pull request #1533 from ksylvan/0619-enhance-restapi-and-webui-with-variables
REST API and Web UI Now Support Dynamic Pattern Variables
2025-06-19 14:45:48 -07:00
Daniel Miessler
e500a5916e Updated paper analyzer. Went back to my own format. 2025-06-19 14:45:31 -07:00
Kayvan Sylvan
6ddf46a379 chore: removed a directory of raycast scripts sitting in the patterns/ directory 2025-06-19 14:11:29 -07:00
Kayvan Sylvan
e8aa358b15 refactor(ChatService): clean up message stream and pattern output methods
- Refactor `cleanPatternOutput` to use a dedicated return variable.
- Hoist `processResponse` function for improved stream readability.
- Remove unnecessary whitespace and trailing newlines from file.
2025-06-19 13:55:25 -07:00
Daniel Miessler
62f373c2b4 Updated paper analyzer. 2025-06-19 13:55:03 -07:00
Daniel Miessler
fcf826f3de Updated paper analyzer. 2025-06-19 13:48:57 -07:00
Kayvan Sylvan
bd2db29cee feat: add ApplyPattern route for applying patterns with variables
## CHANGES
- Create `PatternApplyRequest` struct for request body parsing
- Implement `ApplyPattern` method for POST /patterns/:name/apply
- Register manual routes for pattern operations in `NewPatternsHandler`
- Refactor `Get` method to return raw pattern content
- Merge query parameters with request body variables in `ApplyPattern`
- Use `StorageHandler` for pattern-related storage operations
2025-06-19 13:30:56 -07:00
Kayvan Sylvan
c6d612ee9a feat: add pattern variables support to REST API chat endpoint
## CHANGES

- Add Variables field to PromptRequest struct
- Pass pattern variables through chat handler
- Create API variables documentation example
- Add pattern variables UI in web interface
- Create pattern variables store in Svelte
- Include variables in chat service requests
- Add JSON textarea for variable input
2025-06-19 13:10:05 -07:00
Daniel Miessler
d613c25974 Updated sanitization instructions. 2025-06-19 12:24:09 -07:00
Daniel Miessler
c0abea7c66 Updated markdown cleaner. 2025-06-19 12:02:21 -07:00
Daniel Miessler
496bd2812a Updated markdown cleaner. 2025-06-19 11:34:09 -07:00
github-actions[bot]
70fccaf2fb Update version to v1.4.210 and commit 2025-06-18 07:40:11 +00:00
Kayvan Sylvan
9a71f7c96d Merge pull request #1530 from ksylvan/0617-add-citations-to-perplexity
Add Citation Support to Perplexity Response
2025-06-18 00:38:37 -07:00
Kayvan Sylvan
5da3db383d feat: add citation support to perplexity AI responses
## CHANGES

- Add citation extraction from API responses
- Append citations section to response content
- Format citations as numbered markdown list
- Handle citations in streaming responses
- Store last response for citation access
- Add citations after stream completion
- Maintain backward compatibility with responses
2025-06-17 20:45:03 -07:00
Daniel Miessler 🛡️
19438cbd20 Update README.md 2025-06-17 11:52:02 -07:00
Daniel Miessler 🛡️
a0b71ee365 Update README.md
Updated readme.
2025-06-17 11:48:44 -07:00
Daniel Miessler 🛡️
034513ece5 Update README.md
An update to the intro text, describing Fabric's utility to most people.
2025-06-17 11:45:46 -07:00
github-actions[bot]
0affb9bab1 Update version to v1.4.209 and commit 2025-06-17 10:21:02 +00:00
github-actions[bot]
3305df8fb2 Update version to v1.4.208 and commit 2025-06-17 10:19:28 +00:00
Kayvan Sylvan
892c229076 Merge pull request #1527 from ksylvan/0617-add-perplexity-vendor
Add Perplexity AI Provider with Token Limits Support
2025-06-17 03:17:57 -07:00
Kayvan Sylvan
599c5f2b9f Merge pull request #1526 from ConnorKirk/check-for-aws-credentials
Check for AWS_PROFILE or AWS_ROLE_SESSION_NAME environment variables
2025-06-17 03:17:48 -07:00
Kayvan Sylvan
19e5d8dbe0 chore: update README with Perplexity AI support instructions
### CHANGES
- Add instructions for configuring Perplexity AI with Fabric
- Include example command for querying Perplexity AI
- Retain existing instructions for YouTube transcription changes
2025-06-17 02:57:37 -07:00
Kayvan Sylvan
b772127738 feat: add Perplexity AI provider support with token limits and streaming
## CHANGES

- feat: Add `MaxTokens` field to `ChatOptions` struct for response control
- feat: Integrate Perplexity client into core plugin registry initialization
- build: Add perplexity-go/v2 dependency to enable API interactions
- feat: Implement stream handling in Perpexlty client using sync.WaitGroup
- fix: Correct parameter types for penalty options in API requests
## LINKS

<https://github.com/sgaunet/perlexipty-go> - Client library used
2025-06-17 02:32:53 -07:00
Connor Kirkpatrick
5dd61abe2a Check for AWS_PROFILE or AWS_ROLE_SESSION_NAME environment variables 2025-06-17 10:25:17 +01:00
github-actions[bot]
f45e140126 Update version to v1.4.207 and commit 2025-06-17 07:41:51 +00:00
Kayvan Sylvan
752a66cb48 Merge pull request #1525 from ksylvan/0617-fix-lang-code-vtt-youtube-transcript-bug
Refactor yt-dlp Transcript Logic and Fix Language Bug
2025-06-17 00:40:18 -07:00
Kayvan Sylvan
da28d91d65 refactor: extract common yt-dlp logic to reduce code duplication in YouTube plugin
## CHANGES

- Extract shared yt-dlp logic into tryMethodYtDlpInternal helper
- Add processVTTFileFunc parameter for flexible VTT processing
- Implement language matching for 2-char language codes
- Refactor tryMethodYtDlp to use new helper function
- Refactor tryMethodYtDlpWithTimestamps to use helper
- Reduce code duplication between transcript methods
- Maintain existing functionality with cleaner structure
2025-06-17 00:32:33 -07:00
Daniel Miessler
5a66ca1c5a Updated extract insights. 2025-06-16 16:43:21 -07:00
Daniel Miessler
98f3da610b Updated extract insights. 2025-06-16 16:41:14 -07:00
github-actions[bot]
73ce92ccd9 Update version to v1.4.206 and commit 2025-06-16 23:12:53 +00:00
Kayvan Sylvan
7f3f1d641f Merge pull request #1523 from ksylvan/0616-bedrock-plugin-config-fix
Conditional AWS Bedrock Plugin Initialization
2025-06-16 16:10:59 -07:00
Kayvan Sylvan
44b5c46beb feat: add AWS credential detection for Bedrock client initialization
## CHANGES

- Add hasAWSCredentials helper function
- Check for AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY
- Look for AWS shared credentials file
- Support custom AWS_SHARED_CREDENTIALS_FILE path
- Default to ~/.aws/credentials location
- Only initialize Bedrock client if credentials exist
- Prevent AWS SDK credential search failures
2025-06-16 15:11:58 -07:00
Daniel Miessler
8d37c9d6b9 Updated prompt. 2025-06-16 13:26:13 -07:00
github-actions[bot]
1138d0b60e Update version to v1.4.205 and commit 2025-06-16 13:26:26 +00:00
Kayvan Sylvan
b78217088d Merge pull request #1519 from ConnorKirk/bedrock-plugin-dynamically-fetch-models 2025-06-16 06:24:54 -07:00
Connor Kirkpatrick
76b889733d Dynamically fetch and list available foundation models and inference profiles 2025-06-16 11:05:34 +01:00
Kayvan Sylvan
3911fd9f5d Merge pull request #1518 from ksylvan/0615-remove-old-redundant-patterns
chore: remove duplicate/outdated patterns
2025-06-15 12:56:31 -07:00
Daniel Miessler
b06e29f8a8 Updated markdown sanitizer. 2025-06-15 12:52:39 -07:00
Kayvan Sylvan
11a7e542e1 chore: remove duplicate/outdated patterns 2025-06-15 12:47:08 -07:00
Daniel Miessler
6681078259 Updated markdown cleaner. 2025-06-15 12:45:34 -07:00
Daniel Miessler
be1edf7b1d Updated markdown cleaner. 2025-06-15 12:44:15 -07:00
github-actions[bot]
8ce748a1b1 Update version to v1.4.204 and commit 2025-06-15 05:53:11 +00:00
Kayvan Sylvan
96070f6f39 Merge pull request #1517 from ksylvan/0614-prevent-race-conditions-tag-and-release
Fix: Prevent race conditions in versioning workflow.
2025-06-14 22:51:39 -07:00
Kayvan Sylvan
ca3e89a889 ci: improve version update workflow to prevent race conditions
### CHANGES

- Add concurrency control to prevent simultaneous runs
- Pull latest main branch changes before tagging
- Fetch all remote tags before calculating version
2025-06-14 22:30:54 -07:00
github-actions[bot]
47d799d7ae Update version to v1.4.203 and commit 2025-06-14 06:01:13 +00:00
Eugen Eisler
4899ce56a5 Merge pull request #1512 from ConnorKirk/1500-add-support-for-amazon-bedrock
feat:Add support for Amazon Bedrock
2025-06-14 07:59:41 +02:00
Eugen Eisler
4a7b7becec Merge pull request #1513 from marcas756/feature/create_mnemonic_phrases
feat: create mnemonic phrase pattern
2025-06-14 07:53:05 +02:00
Eugen Eisler
80fdccbe89 Merge pull request #1516 from ksylvan/0612-fix-REST-api-put-pattern
Fix REST API pattern creation
2025-06-14 07:52:06 +02:00
Kayvan Sylvan
d9d8f7bf96 feat: add Save method to PatternsEntity for persisting patterns to filesystem
## CHANGES

- Add Save method to PatternsEntity struct
- Create pattern directory with proper permissions
- Write pattern content to system pattern file
- Add comprehensive test for Save functionality
- Verify directory creation and file contents
- Handle errors for directory and file operations
2025-06-13 15:52:01 -07:00
Marco Bacchi
a96ddbeef0 feat: create mnemonic phrase pattern
Add a new pattern for generating mnemonic phrases from diceware words. This includes two markdown files defining the user guide, and system implementation details.
2025-06-12 23:27:08 +02:00
Connor Kirkpatrick
d32a1d6a5a Add Bedrock plugin
This commits adds support for using Amazon Bedrock within fabric.
2025-06-12 13:07:12 +01:00
github-actions[bot]
201474791d Update version to v1.4.202 and commit 2025-06-12 05:47:10 +00:00
Eugen Eisler
6d09137fee Merge pull request #1510 from ksylvan/0611-fix-youtube-transcript-for-windows
Cross-Platform fix for Youtube Transcript extraction
2025-06-12 07:45:38 +02:00
Kayvan Sylvan
680febbe66 *fix: replace Unix-specific file operations with cross-platform alternatives
## CHANGES

- Replace hardcoded `/tmp` with `os.TempDir()` for paths
- Use `filepath.Join()` instead of string concatenation
- Remove Unix `find` command dependency completely
- Add new `findVTTFiles()` method using `filepath.Walk()`
- Make VTT file discovery work on Windows
- Improve error handling for file operations
- Maintain backward compatibility with existing functionality
2025-06-11 22:24:48 -07:00
github-actions[bot]
f59e5081f3 Update version to v1.4.201 and commit 2025-06-12 02:35:09 +00:00
Eugen Eisler
6a504c7422 Merge pull request #1503 from danielmiessler/dependabot/npm_and_yarn/web/npm_and_yarn-6ea9762674
chore(deps): bump brace-expansion from 1.1.11 to 1.1.12 in /web in the npm_and_yarn group across 1 directory
2025-06-12 04:33:36 +02:00
Eugen Eisler
89a0abcbe4 Merge pull request #1508 from ksylvan/0611-youtube-followup-fixes
feat: cleanup after `yt-dlp` addition
2025-06-12 04:32:30 +02:00
Kayvan Sylvan
2dfd78ef0b feat: cleanup after yt-dlp addition
### CHANGES
- Update README with yt-dlp requirement for transcripts
- Ensure the errors are clear and actionable.
2025-06-11 17:27:11 -07:00
github-actions[bot]
2200b6ea08 Update version to v1.4.200 and commit 2025-06-11 21:45:09 +00:00
Eugen Eisler
82f9ebaf99 Merge pull request #1507 from ksylvan/0611-youtube-fix
Refactor: No more web scraping, just use yt-dlp
2025-06-11 23:43:33 +02:00
Kayvan Sylvan
704ad3067a refactor: replace web scraping with yt-dlp for YouTube transcript extraction
## CHANGES

- Remove unreliable YouTube API scraping methods
- Add yt-dlp integration for transcript extraction
- Implement VTT subtitle parsing functionality
- Add timestamp preservation for transcripts
- Remove soup HTML parsing dependency
- Add error handling for missing yt-dlp
- Create temporary directory management
- Support multiple subtitle format fallbacks
2025-06-11 14:24:40 -07:00
github-actions[bot]
6f7e3c04d7 Update version to v1.4.199 and commit 2025-06-11 20:27:06 +00:00
Eugen Eisler
79f763456e Merge pull request #1506 from danielmiessler/feat/antropic_tool
fix: fix web search tool location
2025-06-11 22:25:22 +02:00
Eugen Eisler
9d4f7f1571 fix: fix web search tool location 2025-06-11 22:19:21 +02:00
github-actions[bot]
8e7373b308 Update version to v1.4.198 and commit 2025-06-11 18:51:13 +00:00
Eugen Eisler
7a39742507 Merge pull request #1504 from marcas756/fix/ollama-hardcoded-timeout
fix: Add configurable HTTP timeout for Ollama client
2025-06-11 20:49:41 +02:00
github-actions[bot]
cea218e61e Update version to v1.4.197 and commit 2025-06-11 18:41:32 +00:00
dependabot[bot]
02ac68834d chore(deps): bump brace-expansion
Bumps the npm_and_yarn group with 1 update in the /web directory: [brace-expansion](https://github.com/juliangruber/brace-expansion).


Updates `brace-expansion` from 1.1.11 to 1.1.12
- [Release notes](https://github.com/juliangruber/brace-expansion/releases)
- [Commits](https://github.com/juliangruber/brace-expansion/compare/1.1.11...v1.1.12)

---
updated-dependencies:
- dependency-name: brace-expansion
  dependency-version: 1.1.12
  dependency-type: indirect
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-11 18:41:27 +00:00
Eugen Eisler
f673f424da Merge pull request #1502 from danielmiessler/feat/antropic_tool
Feat/antropic tool
2025-06-11 20:40:00 +02:00
Marco Bacchi
0ae41116aa fix: Add configurable HTTP timeout for Ollama client
Add a new setup question to configure the HTTP timeout duration for
Ollama requests. The default value is set to 20 minutes.
2025-06-11 20:36:57 +02:00
Eugen Eisler
2b11f3e48e feat: search tool result collection 2025-06-11 20:21:34 +02:00
Eugen Eisler
ed77cc2320 feat: search tool working 2025-06-11 19:56:38 +02:00
Eugen Eisler
29f19fce51 Merge pull request #1499 from noamsiegel/improve-create-prd-pattern
feat: Enhance the PRD Generator's identity and purpose
2025-06-11 18:04:53 +02:00
Eugen Eisler
62ed5d2b9a Merge pull request #1497 from ksylvan/0608-analyze-terraform-plan
feat: add Terraform plan analyzer pattern for infrastructure changes
2025-06-11 18:00:55 +02:00
GitButler
836e4c4fab GitButler Workspace Commit
This is a merge commit the virtual branches in your workspace.

Due to GitButler managing multiple virtual branches, you cannot switch back and
forth between git branches and virtual branches easily. 

If you switch to another branch, GitButler will need to be reinitialized.
If you commit on this branch, GitButler will throw it away.

Here are the branches that are currently applied:
 - improve-create-prd (refs/gitbutler/improve-create-prd)
For more information about what we're doing here, check out our docs:
https://docs.gitbutler.com/features/virtual-branches/integration-branch
2025-06-09 18:24:48 -07:00
Noam Siegel
946c1af42d feat: Enhance the PRD Generator's identity and purpose
The changes in this commit expand the identity and purpose of the PRD Generator
to provide more clarity on its role and the expected output. The key changes
include:

- Defining the Generator's purpose as transforming product ideas into a
  structured PRD that ensures clarity, alignment, and precision in product
  planning and execution.
- Outlining the key sections typically found in a PRD that the Generator should
  cover, such as Overview, Objectives, Target Audience, Features, User Stories,
  Functional and Non-functional Requirements, Success Metrics, and Timeline.
- Providing more detailed instructions on the expected output format, structure,
  and content, including the use of Markdown, labeled sections, bullet points,
  tables, and highlighting of priorities or MVP features.
2025-06-09 18:24:48 -07:00
Kayvan Sylvan
a74585cb14 feat: add Terraform plan analyzer pattern for infrastructure change assessment
- Create new pattern for analyzing Terraform plans
- Add identity defining expert plan analyzer role
- Include focus on security, cost, and compliance
- Define three output sections for summaries
- Specify 20-word sentence summary requirement
- List 10 critical changes with word limits
- Include 5 key takeaways section format
- Add markdown formatting output instructions
- Require numbered lists over bullet points
- Prohibit warnings and duplicate content
2025-06-08 22:49:02 -07:00
github-actions[bot]
5ffd458aa0 Update version to v1.4.196 and commit 2025-06-07 18:02:01 +00:00
Eugen Eisler
9786721037 Merge pull request #1495 from ksylvan/0606-aiml-provider
Add AIML provider configuration
2025-06-07 20:00:27 +02:00
Kayvan Sylvan
ffb31985e8 feat: add AIML provider to OpenAI compatible providers configuration
## CHANGES

- Add AIML provider configuration
- Set AIML base URL to api.aimlapi.com/v1
- Expand supported OpenAI compatible providers list
- Enable AIML API integration support
2025-06-06 07:13:10 -07:00
Daniel Miessler
eeee37a7cc Updated output. 2025-05-31 12:48:46 -07:00
Daniel Miessler
bd89a8d776 Updated output. 2025-05-31 07:14:36 -07:00
Daniel Miessler
2311e7e7a1 Updated output. 2025-05-31 07:14:10 -07:00
Daniel Miessler
09b79283e9 Updated output. 2025-05-31 07:12:29 -07:00
Daniel Miessler
7fbb5e0935 Updated output. 2025-05-31 07:07:56 -07:00
Daniel Miessler
984d9d03f5 Updated output. 2025-05-31 07:06:29 -07:00
Daniel Miessler
c47502fa8c Updated output. 2025-05-31 06:58:46 -07:00
Daniel Miessler
1fe02bdf22 Added simpler paper analyzer, updated the output. 2025-05-31 06:51:19 -07:00
Daniel Miessler
d550385a5e Added simpler paper analyzer. 2025-05-31 06:48:53 -07:00
github-actions[bot]
1e81da5f42 Update version to v1.4.195 and commit 2025-05-24 09:08:17 +00:00
Eugen Eisler
5b318dc402 Merge pull request #1487 from ksylvan/0524-update-pdfjs
Dependency Updates and PDF Worker Refactoring
2025-05-24 11:06:43 +02:00
Kayvan Sylvan
4027305345 feat: upgrade PDF.js to v4.2 and refactor worker initialization
### CHANGES
- Add `.browserslistrc` to define target browser versions.
- Upgrade `pdfjs-dist` dependency from v2.16 to v4.2.67.
- Upgrade `nanoid` dependency from v4.0.2 to v5.0.9.
- Introduce `pdf-config.ts` for centralized PDF.js worker setup.
- Refactor `PdfConversionService` to use new PDF worker configuration.
- Add static `pdf.worker.min.mjs` to serve PDF.js worker.
- Update Vite configuration for ESNext build target and PDF.js.
2025-05-24 00:29:20 -07:00
github-actions[bot]
63879d5cf7 Update version to v1.4.194 and commit 2025-05-24 06:04:31 +00:00
Eugen Eisler
9539441496 Merge pull request #1485 from ksylvan/0523-generalize-web-ui-connect-to-fabric-api
Web UI: Centralize Environment Configuration and Make Fabric Base URL Configurable
2025-05-24 08:02:57 +02:00
github-actions[bot]
352ade34c8 Update version to v1.4.193 and commit 2025-05-24 05:59:22 +00:00
Eugen Eisler
9abc69c1a9 Merge pull request #1484 from ksylvan/0523-web-ui-cleanup-and-updates
Web UI update all packages, reorganize docs, add install scripts
2025-05-24 07:57:42 +02:00
Kayvan Sylvan
93f6f2f0c4 feat: add centralized environment configuration for Fabric base URL
- Create environment config module for URL handling
- Add getFabricBaseUrl() function with server/client support
- Add getFabricApiUrl() helper for API endpoints
- Configure Vite to inject FABRIC_BASE_URL client-side
- Update proxy targets to use environment variable
- Add TypeScript definitions for window config
- Support FABRIC_BASE_URL env var with fallback
2025-05-23 20:45:57 -07:00
Kayvan Sylvan
1f5d3db3fb fix typo in script name 2025-05-23 17:51:41 -07:00
Kayvan Sylvan
4446b456ba docs: reorganize web documentation and add installation scripts
## CHANGES

- Move legacy documentation files to web/legacy/
- Update web README with installation instructions
- Add convenience scripts for npm and pnpm installation
- Update all package dependencies to latest versions
- Add PDF-to-Markdown installation steps to README
- Remove duplicate documentation files
2025-05-23 17:47:33 -07:00
Eugen Eisler
870941090a Merge pull request #1481 from skibum1869/feature/summarize_board_meeting
Add board meeting summary pattern template
2025-05-23 23:36:46 +02:00
Max Harris
5fc004805e Update meeting summary template with word count requirement
AI:

Add minimum word count for context section in board summary
2025-05-23 10:27:18 -05:00
Max Harris
ce47018fc3 Merge branch 'danielmiessler:main' into main 2025-05-23 09:38:40 -05:00
Max Harris
a09131ea72 Add board meeting summary pattern template 2025-05-23 09:38:24 -05:00
github-actions[bot]
36eb321059 Update version to v1.4.192 and commit 2025-05-23 05:44:31 +00:00
Eugen Eisler
47bf9600d6 Merge pull request #1480 from ksylvan/0522-auto-raw-mode-for-some-models
Automatic setting of "raw mode" for some models
2025-05-23 07:43:04 +02:00
Kayvan Sylvan
be674841e7 feat: add automatic raw mode detection for specific AI models
## CHANGES

- Add model-specific raw mode detection logic
- Check Ollama llama2/llama3 models for raw mode
- Check OpenAI o1/o3/o4 models for raw mode
- Use model from options or default chatter
- Auto-enable raw mode when vendor requires it
- Import strings package for prefix matching
2025-05-22 17:04:11 -07:00
Kayvan Sylvan
39a8b67438 feat: add NeedsRawMode method to AI vendor interface
## CHANGES

- Add NeedsRawMode to Vendor interface
- Implement NeedsRawMode in all AI clients
- Return false for all implementations
- Support model-specific raw mode detection
- Enable future raw mode requirements
2025-05-22 16:41:12 -07:00
github-actions[bot]
0a4950dd08 Update version to v1.4.191 and commit 2025-05-22 19:03:47 +00:00
Eugen Eisler
593c1558c0 Merge pull request #1478 from ksylvan/0522-upgrade-to-claude-4
Claude 4 Integration and README Updates
2025-05-22 21:02:11 +02:00
Kayvan Sylvan
c8f9a39a40 feat: add support for Anthropic Claude 4 models and update SDK to v1.2.0
CHANGES
- Upgrade `anthropic-sdk-go` dependency to version `v1.2.0`.
- Integrate new Anthropic Claude 4 Opus and Sonnet models.
- Remove deprecated Claude 2.0 and 2.1 models from list.
- Adjust model type casting for `anthropic-sdk-go v1.2.0` compatibility.
- Refresh README: announce Claude 4, update date, fix links.
2025-05-22 11:26:04 -07:00
github-actions[bot]
50ec02546f Update version to v1.4.190 and commit 2025-05-20 10:12:21 +00:00
Eugen Eisler
881085d0fe Merge pull request #1475 from ksylvan/0519-fix-dupe-input-attempt-2
refactor: improve raw mode handling in BuildSession
2025-05-20 12:10:47 +02:00
Kayvan Sylvan
2d75052e57 refactor: improve raw mode handling in BuildSession
## CHANGES

- Fix system message handling with patterns in raw mode
- Prevent duplicate inputs when using patterns
- Add conditional logic for pattern vs non-pattern scenarios
- Simplify message construction with clearer variable names
- Improve code comments for better readability
2025-05-19 22:18:12 -07:00
github-actions[bot]
fee604682b Update version to v1.4.189 and commit 2025-05-19 21:39:14 +00:00
Eugen Eisler
941ccabd92 Merge pull request #1473 from roumy/add_authent_ollama
add authentification for ollama instance
2025-05-19 23:37:45 +02:00
github-actions[bot]
57cd563963 Update version to v1.4.188 and commit 2025-05-19 21:36:30 +00:00
Eugen Eisler
274b6eada6 Merge pull request #1474 from ksylvan/0519-fix-doubled-user-input
feat: update `BuildSession` to handle message appending logic
2025-05-19 23:35:03 +02:00
Kayvan Sylvan
bc27f9d685 refactor: improve message handling for raw mode and Anthropic client
## CHANGES

- Clarify raw mode message handling in BuildSession
- Fix pattern-based message handling in non-raw mode
- Refactor Anthropic client message normalization
- Add proper handling for empty message arrays
- Implement user/assistant message alternation for Anthropic
- Preserve system messages in Anthropic conversations
- Add safeguards for message sequence validation
2025-05-19 12:50:41 -07:00
pr
1291b35b63 add authentification for ollama instance 2025-05-19 11:01:47 +02:00
Eugen Eisler
9862564c45 Merge pull request #1467 from joshuafuller/main
Typos, spelling, grammar and other minor updates
2025-05-19 07:52:12 +02:00
Eugen Eisler
bbc183f276 Merge pull request #1468 from NavNab/main
Refactor content structure in create_hormozi_offer system.md for clarity and readability
2025-05-18 20:26:28 +02:00
NavNab
9c4445d7bd Refactor content structure in system.md for clarity and readability
- Improved formatting of the introduction and content summary sections for better flow.
- Consolidated repetitive sentences and enhanced the overall coherence of the text.
- Adjusted bullet points and numbering for consistency and easier comprehension.
- Ensured that key concepts are clearly articulated and visually distinct to aid understanding.
2025-05-18 17:03:24 +02:00
Joshua Fuller
920620d771 Merge pull request #1 from joshuafuller/branch/fix-spelling-in-pattern-management-guide 2025-05-16 23:48:52 -05:00
Joshua Fuller
d734e25e0d Merge pull request #2 from joshuafuller/branch/fix-spelling-in-pr-1284-update-notes 2025-05-16 23:48:42 -05:00
Joshua Fuller
a31b2d5e41 Merge pull request #3 from joshuafuller/branch/fix-typos-in-web-readme 2025-05-16 23:48:31 -05:00
Joshua Fuller
8e7e4aa169 Merge pull request #4 from joshuafuller/branch/fix-spelling-of-anthropic-in-notes-md 2025-05-16 23:48:23 -05:00
Joshua Fuller
ea57a64afa Merge pull request #5 from joshuafuller/branch/fix-grammar-in-nuclei-template-instructions 2025-05-16 23:48:13 -05:00
Joshua Fuller
da1a9dab56 docs: fix grammar in nuclei template instructions 2025-05-16 23:45:33 -05:00
Joshua Fuller
068f111986 docs: correct Anthropic spelling in notes 2025-05-16 23:44:31 -05:00
Joshua Fuller
dd0be51726 docs: fix typos in web README 2025-05-16 23:44:19 -05:00
Joshua Fuller
43a1e66cc8 docs: fix spelling in PR 1284 update notes 2025-05-16 23:44:06 -05:00
Joshua Fuller
430a272e1d docs: fix spelling in pattern management guide 2025-05-16 23:43:38 -05:00
github-actions[bot]
0e892f38e4 Update version to v1.4.187 and commit 2025-05-10 07:42:11 +00:00
Eugen Eisler
aa0fe90258 Merge pull request #1463 from CodeCorrupt/nixpkgs_completion
Add completion to the build output for Nix
2025-05-10 09:40:45 +02:00
CodeCorrupt
c59c7553b3 Add completion files to the build output for Nix 2025-05-07 17:06:00 -04:00
github-actions[bot]
703756d0b0 Update version to v1.4.186 and commit 2025-05-06 22:06:46 +00:00
Eugen Eisler
50d22f8e77 Merge pull request #1459 from ksylvan/0505-cleanup-some-old-detritus
chore: Repository cleanup and .gitignore Update
2025-05-07 00:05:19 +02:00
Kayvan Sylvan
fde2efd4ce chore: update .gitignore and remove obsolete files
- Add `coverage.out` to `.gitignore` for ignoring coverage output.
- Remove `Alma.md` documentation file from the repository.
- Delete `rate_ai_result.txt` stitch script from `stitches` folder.
- Remove `readme.md` for `rate_ai_result` stitch documentation.
2025-05-05 17:16:38 -07:00
github-actions[bot]
0150c3a37d Update version to v1.4.185 and commit 2025-04-28 19:27:01 +00:00
Eugen Eisler
2a0216b9aa Merge pull request #1453 from ksylvan/0428-default-model-setting-fix
Fix for default model setting
2025-04-28 21:25:35 +02:00
Kayvan Sylvan
a6d14d86b8 refactor: introduce getSortedGroupsItems for consistent sorting logic
### CHANGES
- Add `getSortedGroupsItems` to centralize sorting logic.
- Sort groups and items alphabetically, case-insensitive.
- Replace inline sorting in `Print` with new method.
- Update `GetGroupAndItemByItemNumber` to use sorted data.
- Ensure original `GroupsItems` remains unmodified.
2025-04-28 11:41:32 -07:00
github-actions[bot]
a9374c128b Update version to v1.4.184 and commit 2025-04-25 08:27:55 +00:00
Eugen Eisler
f32b9f81da Merge pull request #1447 from ksylvan/0424-more-shell-completions
More shell completion scripts: Zsh, Bash, and Fish
2025-04-25 10:26:20 +02:00
Kayvan Sylvan
bf3af8e98e feat: add shell completion scripts for Zsh, Bash, and Fish
CHANGES:
- Add shell completion support for three major shells
- Create standardized completion scripts in completions/ directory
- Add --shell-complete-list flag for machine-readable output
- Update Print() methods to support plain output format
- Document installation steps for each shell in README
- Replace old fish completion script with improved version
2025-04-24 17:47:39 -07:00
github-actions[bot]
095c295ee5 Update version to v1.4.183 and commit 2025-04-23 20:03:10 +00:00
Eugen Eisler
93ecc9cfea Merge pull request #1431 from KenMacD/fish-completion
Add a completion script for fish
2025-04-23 22:01:41 +02:00
github-actions[bot]
e7aaa23fc2 Update version to v1.4.182 and commit 2025-04-23 20:00:59 +00:00
Eugen Eisler
197d3454f8 Merge pull request #1441 from ksylvan/0423-nix-go-build-toolchain-update
Update go toolchain and go module packages to latest versions
2025-04-23 21:59:25 +02:00
Kayvan Sylvan
50a4f8b491 chore: fix "nix flake check" errors 2025-04-23 11:07:01 -07:00
Kayvan Sylvan
894b4967dd refactor: centralize Go version definition in flake.nix
CHANGES
*   Define `getGoVersion` function in `flake.nix`.
*   Use `getGoVersion` to set Go version consistently.
*   Pass `goVersion` explicitly into `nix/shell.nix`.
*   Remove redundant Go version definition from `shell.nix`.
2025-04-23 09:34:39 -07:00
Kayvan Sylvan
9837bd6664 chore: update Go to 1.24.2 and refresh dependencies
Update Go version across Dockerfile, Nix configurations, and Go modules.
Refresh dependencies and Nix flake inputs.

CHANGES:
*   Update Go version to 1.24.2 in Dockerfile.
*   Set Go version to 1.24.0 and toolchain to 1.24.2.
*   Refresh Go module dependencies and sums (go.mod, go.sum).
*   Update Nix flake lock file inputs.
*   Configure Nix environment and packages for Go 1.24.
*   Update gomod2nix lock file with dependency hashes.
*   Use Go 1.24 in Nix development shell environment.
2025-04-23 09:18:01 -07:00
github-actions[bot]
6ca1b5dac4 Update version to v1.4.181 and commit 2025-04-22 16:03:07 +00:00
Eugen Eisler
c85135c04e Merge pull request #1433 from ksylvan/0421-anthropic-api-update
chore: update Anthropic SDK to v0.2.0-beta.3 and migrate to V2 API
2025-04-22 18:01:53 +02:00
github-actions[bot]
31e4e42a94 Update version to v1.4.180 and commit 2025-04-22 11:40:37 +00:00
Eugen Eisler
196db04fc2 Merge pull request #1435 from ksylvan/0421-fix-raw-input-with-stratetgies
chore: Fix user input handling when using raw mode and `--strategy` flag
2025-04-22 13:39:22 +02:00
Kayvan Sylvan
b3b1b5a471 chore: unify raw mode message handling and preserve env vars in extension executor
## CHANGES

- refactor BuildSession raw mode to prepend system to user content
- ensure raw mode messages always have User role
- keep existing user message when no systemMessage provided
- append systemMessage separately in non-raw mode sessions
- store original cmd.Env before context-based exec command creation
- recreate exec command with context then restore originalEnv
- add comments clarifying raw vs non-raw handling behavior
2025-04-21 17:04:11 -07:00
Kayvan Sylvan
892439a177 chore: update Anthropic SDK to v0.2.0-beta.3 and migrate to V2 API
## CHANGES

- Upgrade Anthropic SDK from alpha.11 to beta.3
- Update API endpoint from v1 to v2
- Replace anthropic.F() with direct assignment
- Replace anthropic.F() with anthropic.Opt() for optional params
- Simplify event delta handling in streaming
- Change client type from pointer to value type
- Update comment with SDK changelog reference
2025-04-21 13:17:03 -07:00
github-actions[bot]
ba2e178e03 Update version to v1.4.179 and commit 2025-04-21 18:08:47 +00:00
Eugen Eisler
ed298bcedd Merge pull request #1432 from ksylvan/0421-fix-tools-selection-in-setup
chore: fix fabric setup mess-up introduced by sorting lists (tools and models)
2025-04-21 20:07:33 +02:00
Kayvan Sylvan
6b04e6e674 chore: sort AI models alphabetically for consistent listing
CHANGES
*   Import `sort` and `strings` packages for sorting functionality.
*   Sort retrieved AI model names alphabetically, ignoring case.
*   Ensure consistent ordering of AI models in lists.
2025-04-21 10:41:41 -07:00
Kayvan Sylvan
04c0f6a0a5 chore: alphabetize the order of plugin tools 2025-04-21 10:26:04 -07:00
Kenny MacDermid
486ff42b59 Add a completion script for fish 2025-04-21 12:58:05 -03:00
github-actions[bot]
f7ab484510 Update version to v1.4.178 and commit 2025-04-21 13:21:52 +00:00
Eugen Eisler
f50a14305a Merge pull request #1427 from ksylvan/0420-refactor-openai-compatible-providers
Refactor OpenAI-compatible AI providers and add `--listvendors` flag
2025-04-21 15:20:33 +02:00
github-actions[bot]
d5f0cd7616 Update version to v1.4.177 and commit 2025-04-21 07:10:40 +00:00
Eugen Eisler
67c658f5b4 Merge pull request #1428 from ksylvan/0420-sorted-group-lists
feat: Alphabetical case-insensitive sorting for groups and items
2025-04-21 09:09:21 +02:00
github-actions[bot]
ef3bc03343 Update version to v1.4.176 and commit 2025-04-21 07:09:11 +00:00
Eugen Eisler
e31cb2b46a Merge pull request #1429 from ksylvan/0420-fix-strategies-api
feat: enhance StrategyMeta with Prompt field and dynamic naming
2025-04-21 09:07:57 +02:00
Kayvan Sylvan
6ca7142ea4 feat: enhance StrategyMeta with Prompt field and dynamic naming
### CHANGES

- Add `Prompt` field to `StrategyMeta` struct.
- Include `strings` package for filename processing.
- Derive strategy name from filename using `strings.TrimSuffix`.
- Store `Prompt` value from JSON data in `StrategyMeta`
2025-04-20 17:20:55 -07:00
Kayvan Sylvan
8b2174897a feat: add alphabetical sorting to groups and items in Print method**
### CHANGES
- Import `sort` and `strings` packages for sorting functionality.
- Create a copy of groups for stable sorting.
- Sort groups alphabetically in a case-insensitive manner.
- Create a copy of items within each group for sorting.
- Sort items alphabetically in a case-insensitive manner.
- Iterate over sorted groups and items for display.
2025-04-20 10:56:52 -07:00
Kayvan Sylvan
ac5eab0563 feat: add --listvendors command to list AI vendors
### CHANGES
- Introduce `--listvendors` flag to display all AI vendors.
- Refactor OpenAI-compatible providers into a unified configuration.
- Remove individual vendor packages for streamlined management.
- Add sorting for consistent vendor listing output.
- Update documentation to include new `--listvendors` option.
2025-04-20 08:53:20 -07:00
github-actions[bot]
65414dcc1c Update version to v1.4.175 and commit 2025-04-19 20:57:20 +00:00
Eugen Eisler
5db352f5be Merge pull request #1418 from danielmiessler/dependabot/go_modules/go_modules-bbb8b02913
chore(deps): bump golang.org/x/net from 0.36.0 to 0.38.0 in the go_modules group across 1 directory
2025-04-19 22:56:00 +02:00
github-actions[bot]
9e7830ff77 Update version to v1.4.174 and commit 2025-04-19 06:13:44 +00:00
Eugen Eisler
5945c0e16b Merge pull request #1425 from ksylvan/0418-cerebras-ai
feat: add Cerebras AI plugin to plugin registry
2025-04-19 08:12:32 +02:00
Kayvan Sylvan
29ee141822 feat: add Cerebras AI plugin to plugin registry
### CHANGES
- Introduce Cerebras AI plugin import in plugin registry.
- Register Cerebras client in the NewPluginRegistry function.
2025-04-18 15:14:08 -07:00
github-actions[bot]
8a69621e87 Update version to v1.4.173 and commit 2025-04-18 16:23:09 +00:00
Eugen Eisler
1645b0c4ea Merge pull request #1420 from sherif-fanous/main
Fix error in deleting patterns due to non empty directory
2025-04-18 18:21:50 +02:00
Eugen Eisler
45205574d5 Merge pull request #1421 from ksylvan/0417-atom-of-thought
feat: add Atom-of-Thought (AoT) strategy and prompt definition
2025-04-18 18:20:42 +02:00
Kayvan Sylvan
71a5e0394a chore: add final newline to aot json file 2025-04-17 13:43:06 -07:00
Kayvan Sylvan
f286936c23 feat: add Atom-of-Thought (AoT) strategy and prompt definition
## CHANGES

- add new aot.json for Atom-of-Thought (AoT) prompting
- define AoT strategy description and detailed prompt instructions
- update strategies.json to include AoT in available strategies list
- ensure AoT strategy appears alongside CoD, CoT, and LTM options
2025-04-17 13:31:18 -07:00
Sherif Fanous
9000f92a55 Fix error in deleting patterns due to non empty directory 2025-04-17 12:05:52 -04:00
dependabot[bot]
8c84d4b3c8 chore(deps): bump golang.org/x/net
Bumps the go_modules group with 1 update in the / directory: [golang.org/x/net](https://github.com/golang/net).


Updates `golang.org/x/net` from 0.36.0 to 0.38.0
- [Commits](https://github.com/golang/net/compare/v0.36.0...v0.38.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-version: 0.38.0
  dependency-type: indirect
  dependency-group: go_modules
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-16 23:25:39 +00:00
github-actions[bot]
1d77afcc44 Update version to v1.4.172 and commit 2025-04-16 18:17:12 +00:00
Eugen Eisler
835bc6044b Merge pull request #1415 from ksylvan/0416-grok-ai
feat: add Grok AI provider support
2025-04-16 20:15:45 +02:00
Kayvan Sylvan
ef895a1ab9 chore: Update README with a note about Grok 2025-04-16 09:23:20 -07:00
Kayvan Sylvan
82039cedaf feat: add Grok AI provider support`
Integrate the Grok AI provider into the Fabric system for AI model interactions.

### CHANGES

*   Add Grok AI client to the plugin registry.
*   Include Grok AI API key in REST API configuration endpoints.
2025-04-16 09:15:32 -07:00
Eugen Eisler
973df61dfd Merge pull request #1411 from ksylvan/0415-readme-add-contributors
docs: add contributors section to README with contrib.rocks image
2025-04-16 11:29:58 +02:00
Kayvan Sylvan
661c85d7a6 # docs: add contributors section to README with contrib.rocks image
## CHANGES

- Add contributors section with visual representation
- Include link to project contributors page
- Add attribution to contrib.rocks tool
2025-04-15 08:29:45 -07:00
github-actions[bot]
4638f67fb7 Update version to v1.4.171 and commit 2025-04-15 08:56:37 +00:00
Eugen Eisler
ab71dbcd4f Merge pull request #1407 from sherif-fanous/main
Update Dockerfile so that Go image version matches go.mod version
2025-04-15 10:55:18 +02:00
Daniel Miessler
2abdabc100 Update README.md 2025-04-14 09:45:02 -07:00
Daniel Miessler
9f78a2c8e1 Update README.md 2025-04-14 09:44:16 -07:00
Daniel Miessler
76f78601f2 Update README.md 2025-04-14 09:43:36 -07:00
Daniel Miessler
4eaba2dc56 Update README.md 2025-04-14 09:43:06 -07:00
Daniel Miessler
2dcd9cb5f7 Update README.md 2025-04-14 09:42:19 -07:00
Daniel Miessler
2943872bde Update README.md 2025-04-14 09:41:05 -07:00
Daniel Miessler
b901542a48 Update README.md 2025-04-14 09:40:17 -07:00
Daniel Miessler
c122ff8960 Update README.md 2025-04-14 09:39:52 -07:00
Daniel Miessler
e128d818c4 Update README.md 2025-04-14 09:39:15 -07:00
Daniel Miessler
5e9d6d0a91 Update README.md 2025-04-14 09:38:51 -07:00
Daniel Miessler
70edf9cbe3 Update README.md 2025-04-14 09:36:53 -07:00
Daniel Miessler
e61a0a9391 Update README.md 2025-04-14 09:35:50 -07:00
github-actions[bot]
f8ddf98404 Update version to v1.4.170 and commit 2025-04-13 07:11:30 +00:00
Eugen Eisler
55219467f3 Merge pull request #1406 from jmd1010/chatinput-fix-clean2
Fix chat history LLM response sequence in ChatInput.svelte
2025-04-13 09:10:11 +02:00
Sherif Fanous
74d4be1ac6 Bump golang version to match go.mod 2025-04-12 21:03:53 -04:00
JM
9e57f8c6f1 Update pattern_descriptions.json 2025-04-12 19:26:32 -04:00
jmd1010
3d2903cb47 Finalize WEB UI V2 loose endsfixes 2025-04-12 17:15:14 -04:00
jmd1010
13e9d22ec6 Fix chat history LLM response sequence in ChatInput.svelte 2025-04-11 21:40:33 -04:00
github-actions[bot]
01d12c47cf Update version to v1.4.169 and commit 2025-04-11 19:13:26 +00:00
Eugen Eisler
c3258a2c3f Merge pull request #1403 from jmd1010/strategy-flag-web
Strategy flag enhancement - Web UI implementation
2025-04-11 21:12:12 +02:00
JM
746885e263 Update strategies.json 2025-04-11 12:40:27 -04:00
jmd1010
b25895c1d2 Integrate in web ui the strategy flag enhancement first developed in fabric cli 2025-04-10 18:25:09 -04:00
Daniel Miessler
e40b1c1f66 updated ed 2025-04-06 15:23:25 -07:00
Daniel Miessler
ef2ec8bffe Added excalidraw pattern. 2025-04-06 15:18:17 -07:00
Daniel Miessler
589991e6a6 Shorter version of analyze bill. 2025-04-06 13:42:03 -07:00
Daniel Miessler
965392ebbd Merge branch 'main' of github.com:danielmiessler/fabric 2025-04-06 13:33:31 -07:00
Daniel Miessler
6f615baf53 Added bill analyzer. 2025-04-06 13:33:21 -07:00
github-actions[bot]
b60bad7799 Update version to v1.4.168 and commit 2025-04-02 13:33:53 +00:00
Eugen Eisler
234d1303ad Merge pull request #1399 from HaroldFinchIFT/add-optional-simple-apikey-for-server
feat: add simple optional api key management for protect routes in --serve mode
2025-04-02 15:32:31 +02:00
Harold
cd74a96be2 refactor: refactor API key middleware based on code review feedback 2025-04-01 22:47:39 +02:00
Harold
ceaa90a7c7 fix: bad format 2025-04-01 01:26:53 +02:00
Harold
15a2eeadc9 feat: add simple optional api key management for protect routes in --serve mode 2025-04-01 01:26:53 +02:00
github-actions[bot]
8d02f5b21d Update version to v1.4.167 and commit 2025-03-31 14:42:50 +00:00
Eugen Eisler
0f8f0b6b39 Merge pull request #1397 from HaroldFinchIFT/add-italian-language-gui
feat: add it lang to the chat drop down menu lang in web gui
2025-03-31 16:41:34 +02:00
Harold
fd58b6d410 feat: add it lang to the chat drop down menu lang in web gui 2025-03-30 12:05:22 +02:00
github-actions[bot]
2579d37c16 Update version to v1.4.166 and commit 2025-03-29 20:12:49 +00:00
Eugen Eisler
4f28d85e96 Merge pull request #1392 from ksylvan/0327-fix-code-helper-arg-handling
chore: enhance argument validation in `code_helper` tool
2025-03-29 21:11:34 +01:00
Kayvan Sylvan
f529b8bb80 refactor: streamline code_helper CLI interface and require explicit instructions
## CHANGES

- Require exactly two arguments: directory and instructions
- Remove dedicated help flag, use flag.Usage instead
- Improve directory validation to check if it's a directory
- Inline pattern parsing, removing separate function
- Simplify error messages for better clarity
- Update usage text to reflect required instructions parameter
- Print usage to stderr instead of stdout
2025-03-27 19:17:54 -07:00
Eugen Eisler
71437605e1 Merge pull request #1390 from PatrickCLee/03-26-README-fix
docs: improve README link
2025-03-26 08:31:15 +01:00
github-actions[bot]
cf5753a186 Update version to v1.4.165 and commit 2025-03-26 07:30:28 +00:00
Eugen Eisler
433c83fe2c Merge pull request #1389 from ksylvan/0323-nysan-conding-feature
Create Coding Feature
2025-03-26 08:29:08 +01:00
PatrickCLee
01770cc6e3 docs: improve README link
- Fix broken what-and-why link reference
2025-03-26 11:34:11 +08:00
Kayvan Sylvan
55fda5e025 fix: enhance JSON string handling with proper control character escaping
## CHANGES

- Convert control chars to proper JSON escape sequences
- Prevent invalid JSON due to literal control chars
2025-03-25 20:00:44 -07:00
Kayvan Sylvan
daad5f986e refactor: rename fabric_code tool to code_helper for clarity
## CHANGES

- Rename tool from `fabric_code` to `code_helper`
- Update all documentation references to the tool
- Update installation instructions in README
- Modify usage examples in documentation
- Update tool's self-description and help text
2025-03-25 19:14:25 -07:00
Kayvan Sylvan
3785d0a5fa refactor: modify ParseFileChanges to return summary and changes separately
CHANGES:
*   Return summary text from `ParseFileChanges` separately.
*   Update `chatter` to use returned summary text.
*   Update tests to match new function signature.
2025-03-25 18:54:01 -07:00
Kayvan Sylvan
8a326e9cfb refactor: replace FILE_CHANGES marker with constant FileChangesMarker
## CHANGES

- Add FileChangesMarker constant for file changes section
- Update parser to use new constant marker
- Improve error messages with dynamic marker reference
- Update tests to use new marker format
- Update system documentation with new marker syntax
2025-03-25 17:51:57 -07:00
Kayvan Sylvan
5f5822f1c6 fix: improve JSON parsing in ParseFileChanges to handle invalid escape sequences
## CHANGES

- Add dedicated function to fix invalid JSON escapes
- Handle common \C escape sequence issue
- Implement fallback parsing with comprehensive escape fixes
- Track string context for accurate escape detection
- Preserve valid JSON escape sequences
2025-03-25 16:16:51 -07:00
Kayvan Sylvan
111482e46e feat: add file management system for AI-driven code changes
CHANGES:
- Replace deprecated io/ioutil with modern alternatives
- Add file change parsing and validation system
- Create secure file application mechanism
- Update chatter to process AI file changes
- Improve create_coding_feature pattern documentation
2025-03-25 16:09:28 -07:00
Kayvan Sylvan
9b56e0e996 feat: add fabric_code tool and create_coding_feature pattern
This commit introduces the `fabric_code` tool and the `create_coding_feature` pattern, allowing Fabric to modify existing codebases.

## CHANGES

-   add `fabric_code` tool to generate JSON representation of code projects
-   add `create_coding_feature` pattern to apply AI-generated code changes
-   update README with `fabric_code` installation and usage
-   walk file system with maximum depth and ignore list
-   scan directory and return file/dir JSON data for AI model
-   provide usage instructions and examples for `fabric_code`
-   add file management API to system prompt for code changes
2025-03-25 08:04:55 -07:00
github-actions[bot]
9b830f9801 Update version to v1.4.164 and commit 2025-03-22 08:52:21 +00:00
Eugen Eisler
dda73d3333 Merge pull request #1380 from jmd1010/web-windows-resizing
Add flex windows sizing to web interface + raw text input fix
2025-03-22 09:51:07 +01:00
Eugen Eisler
40c26d9c9e Merge pull request #1379 from guilhermechapiewski/patch-1
Fix typo on fallacies instruction.
2025-03-22 09:50:14 +01:00
Eugen Eisler
cdd86b0ed9 Merge pull request #1382 from ksylvan/03-21-README-fixes
docs: improve README formatting and fix some broken links
2025-03-22 09:49:32 +01:00
Kayvan Sylvan
c2e84d6db9 docs: improve README formatting and add clipboard support section
## CHANGES

- Remove colons from heading anchors
- Fix broken installation link reference
- Replace code tags with backticks
- Improve code block formatting with indentation
- Clarify package manager alias requirements
- Fix environment variables link
- Simplify custom patterns directory instructions
2025-03-21 23:34:27 -07:00
jmd1010
4208a02191 fixed processing message not stopping after pattern output completion 2025-03-21 23:26:54 -04:00
jmd1010
943b26eeef Add flex windows sizing to web interface 2025-03-21 18:22:54 -04:00
Guilherme Chapiewski
d6ceae9efd Fix typo on fallacies instruction. 2025-03-21 11:30:52 -07:00
Eugen Eisler
f57dc6d681 Merge pull request #1376 from vaygr/install-update
Add installation instructions for OS package managers
2025-03-21 13:57:00 +01:00
Val V
4e4bfc9d5d Add installation instructions for OS package managers 2025-03-21 03:12:43 +00:00
Daniel Miessler
ea137c1525 Updated find prompt. 2025-03-20 14:36:00 -07:00
Daniel Miessler
f0be1d4735 Updated find prompt. 2025-03-20 14:28:15 -07:00
Daniel Miessler
e3975b9364 Updated find prompt. 2025-03-20 14:25:24 -07:00
Daniel Miessler
cd48802ea0 Updated find prompt. 2025-03-20 14:23:10 -07:00
Daniel Miessler
dceccd8e72 Merge branch 'main' of github.com:danielmiessler/fabric 2025-03-20 14:16:17 -07:00
Daniel Miessler
0813ad9c39 Added find_female_life_partner. 2025-03-20 14:16:06 -07:00
github-actions[bot]
e391132167 Update version to v1.4.163 and commit 2025-03-19 03:50:11 +00:00
Eugen Eisler
c7f86d3a0c Merge pull request #1362 from danielmiessler/dependabot/go_modules/go_modules-c153b83258
Bump golang.org/x/net from 0.35.0 to 0.36.0 in the go_modules group across 1 directory
2025-03-19 04:48:57 +01:00
Eugen Eisler
f0d92f9424 Merge pull request #1372 from rube-de/patch-1
fix: set percentEncoded to false
2025-03-19 04:48:26 +01:00
Eugen Eisler
4a9bdb1479 Merge pull request #1373 from ksylvan/main
Remove unnecessary `system.md` file at top level.
2025-03-19 04:47:02 +01:00
github-actions[bot]
7eed80710e Update version to v1.4.162 and commit 2025-03-19 03:45:25 +00:00
Eugen Eisler
fbd62be47d Merge pull request #1374 from ksylvan/fix/change-default-model-save
Fix Default Model Change Functionality
2025-03-19 04:44:11 +01:00
Kayvan Sylvan
85cc7b8a9d fix: improve error handling in ChangeDefaultModel flow and save environment file
- Add early return on setup error
- Save environment file after successful setup
- Maintain proper error propagation
2025-03-17 19:37:26 -07:00
Kayvan Sylvan
1fe8afd329 chore: Remove redundant file system.md at top level.
CHANGES:
- Removed `system.md` on the top level of the fabric repo.
- system.md was an RPG session summarization prompt.
- There are two other RPM summary patterns created after this file was added: `create_rpg_summary` and `summarize_rpg_session`
2025-03-17 15:09:36 -07:00
beruf
e89ccf5e97 fix: set percentEncoded to false
If you use a youtube link like `https://youtu.be/sHIlFKKaq0A` percentEndcoding encodes the link to `https%3A%2F%2Fyoutu.be%2FsHIlFKKaq0A`, which throws an error in fabric.

With percentEndcoding false, the script receives the link without encoding and works.
2025-03-17 22:43:02 +01:00
github-actions[bot]
0eee89140c Update version to v1.4.161 and commit 2025-03-17 14:21:02 +00:00
Eugen Eisler
5571e6fafd Merge pull request #1363 from garkpit/streamlit-clipboard-ops-for-all-platforms
clipboard operations now work on Mac and PC
2025-03-17 15:19:42 +01:00
github-actions[bot]
9a4e920618 Update version to v1.4.160 and commit 2025-03-17 14:17:36 +00:00
Eugen Eisler
6e479999b1 Merge pull request #1368 from vaygr/std-no-repeat
Standardize sections for no repeat guidelines
2025-03-17 15:16:21 +01:00
Daniel Miessler
f65f2501b4 Moved system file to proper directory. 2025-03-16 14:46:13 -07:00
Daniel Miessler
4b12bd2a61 Moved system file to proper directory. 2025-03-16 14:43:55 -07:00
Daniel Miessler
d83a3beeeb Merge branch 'main' of github.com:danielmiessler/fabric 2025-03-16 14:16:02 -07:00
Daniel Miessler
7428c8017f Added activity extractor. 2025-03-16 14:15:54 -07:00
Val V
008ed76d37 Standardize sections for no repeat guidelines 2025-03-16 19:48:15 +00:00
github-actions[bot]
ce9d4ad831 Update version to v1.4.159 and commit 2025-03-16 19:23:15 +00:00
Daniel Miessler
657bcab48c Added flashcard generator. 2025-03-16 12:21:50 -07:00
github-actions[bot]
cd11dcc7a9 Update version to v1.4.158 and commit 2025-03-16 17:26:52 +00:00
Eugen Eisler
22040a42f2 Merge pull request #1367 from ksylvan/fix/code_cleanup
Remove Generic Type Parameters from StorageHandler Initialization
2025-03-16 18:25:33 +01:00
Kayvan Sylvan
705ccd750b refactor: remove generic type parameters from NewStorageHandler calls
## CHANGES

- Remove explicit type parameters from StorageHandler initialization
- Update contexts handler constructor implementation
- Update patterns handler constructor implementation
- Update sessions handler constructor implementation
- Simplify API by relying on type inference
2025-03-16 09:21:17 -07:00
github-actions[bot]
db7c2b70cb Update version to v1.4.157 and commit 2025-03-16 07:36:39 +00:00
Eugen Eisler
9dc9bfa1d5 Merge pull request #1365 from ksylvan/feature/strategies
Implement Prompt Strategies in Fabric
2025-03-16 08:35:23 +01:00
Kayvan Sylvan
6b93658191 chore: remove redundant yt function definition 2025-03-15 17:35:45 -07:00
Kayvan Sylvan
ea7a425a26 add newline to end of cod.json 2025-03-15 13:18:53 -07:00
Kayvan Sylvan
9582978adb Fix help message when no strategies found. 2025-03-15 13:05:51 -07:00
Kayvan Sylvan
453d8e75e4 fix: fix handling of the installed strategies dir 2025-03-15 09:36:34 -07:00
Kayvan Sylvan
901a010efd chore: remove fallback to local strategies directory if missing 2025-03-15 08:29:58 -07:00
Jay
b5c2d069f2 clipboard operations now work on Mac and PC 2025-03-15 08:31:48 +00:00
Kayvan Sylvan
f744e25b39 change [optional] to [required] in strategies 2025-03-15 00:33:58 -07:00
Kayvan Sylvan
096f40df68 feat: add prompt strategies and improve installation documentation
## CHANGES

- Add prompt strategies like Chain of Thought (CoT)
- Implement strategy selection with `--strategy` flag
- Improve README with platform-specific installation instructions
- Fix web interface documentation link
- Refactor git operations with new githelper package
- Add `--liststrategies` command to view available strategies
- Support applying strategies to system prompts
- Fix YouTube configuration check
- Improve error handling in session management
2025-03-15 00:30:30 -07:00
dependabot[bot]
a227e61952 Bump golang.org/x/net in the go_modules group across 1 directory
Bumps the go_modules group with 1 update in the / directory: [golang.org/x/net](https://github.com/golang/net).


Updates `golang.org/x/net` from 0.35.0 to 0.36.0
- [Commits](https://github.com/golang/net/compare/v0.35.0...v0.36.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: indirect
  dependency-group: go_modules
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-13 02:06:32 +00:00
github-actions[bot]
29f4534001 Update version to v1.4.156 and commit 2025-03-11 09:05:45 +00:00
Eugen Eisler
ed9324d611 Merge pull request #1356 from ksylvan/main
chore: add .vscode to `.gitignore` and fix typos and markdown linting  in `Alma.md`
2025-03-11 10:04:32 +01:00
Eugen Eisler
438b3c5211 Merge pull request #1352 from matmilbury/patch-1
pattern_explanations.md: fix typo
2025-03-11 07:52:48 +01:00
Eugen Eisler
efeeb7a796 Merge pull request #1354 from jmd1010/chat-history-window-sizing
Fix Chat history window scrolling behavior
2025-03-11 07:51:51 +01:00
Kayvan Sylvan
6b1ff0ab21 chore: add .vscode to .gitignore and fix typos and markdown linting in Alma.md 2025-03-10 09:29:16 -07:00
jmd1010
acb925f5a9 Update Web V2 Install Guide with improved instructions 2025-03-09 15:27:02 -04:00
jmd1010
761293ede7 Fix Chat history window sizing 2025-03-09 14:58:45 -04:00
Mat Milbury
e004e50037 pattern_explanations.md: fix typo 2025-03-09 16:11:14 +01:00
github-actions[bot]
44a6c03bc8 Update version to v1.4.155 and commit 2025-03-09 09:01:41 +00:00
Eugen Eisler
d794afe405 Merge pull request #1350 from jmd1010/pattern-search-implementation
Implement Pattern Tile search functionality
2025-03-09 10:00:28 +01:00
github-actions[bot]
e4ac322227 Update version to v1.4.154 and commit 2025-03-09 08:56:50 +00:00
Eugen Eisler
1fc19da19f Merge pull request #1349 from ksylvan/03-08-extra-version-declaration-removed
Fix: v1.4.153 does not compile because of extra version declaration
2025-03-09 09:55:37 +01:00
jmd1010
b213068680 Implement column resize functionnality 2025-03-08 17:34:49 -05:00
jmd1010
bf3af207b9 Implement Pattern Tile search functionality 2025-03-08 12:56:55 -05:00
Kayvan Sylvan
e28ba224b5 fix: update Azure client API version access path in tests 2025-03-08 09:52:20 -08:00
Kayvan Sylvan
5b7697c5ab chore: remove unnecessary version variable from main.go 2025-03-08 09:29:20 -08:00
github-actions[bot]
0701b7d263 Update version to v1.4.153 and commit 2025-03-08 08:56:19 +00:00
Eugen Eisler
aac29025fb Merge pull request #1348 from liyuankui/feature/add-litellm-vendor
feat: Add LiteLLM AI plugin support with local endpoint configuration
2025-03-08 09:55:08 +01:00
kyle
6928f9a312 feat: Add LiteLLM AI plugin support with local endpoint configuration 2025-03-08 11:37:54 +08:00
github-actions[bot]
ef2e985d3f Update version to v1.4.152 and commit 2025-03-07 08:23:45 +00:00
Eugen Eisler
1df945556d fix: Fix pipe handling 2025-03-07 09:22:26 +01:00
github-actions[bot]
b6f313db8f Update version to v1.4.151 and commit 2025-03-07 07:47:35 +00:00
Eugen Eisler
cb00f2026e Merge pull request #1339 from Eckii24/feature/add-azure-api-version
Feature/add azure api version
2025-03-07 08:46:20 +01:00
github-actions[bot]
bd39d98ffc Update version to v1.4.150 and commit 2025-03-07 07:44:52 +00:00
Eugen Eisler
36b0afa692 Merge pull request #1343 from jmd1010/input-component-update
Rename input.svelte to Input.svelte for proper component naming convention
2025-03-07 08:43:32 +01:00
jmd1010
53d09d8a5a Rename input.svelte to Input.svelte for proper component naming convention 2025-03-06 21:08:30 -05:00
github-actions[bot]
703144edad Update version to v1.4.149 and commit 2025-03-05 12:50:38 +00:00
Eugen Eisler
717e50e570 Merge pull request #1340 from ksylvan/03-04-youtube-live-fix
Fix for youtube live links plus new youtube_summary pattern
2025-03-05 13:49:22 +01:00
Eugen Eisler
4af6d5eeed Merge pull request #1338 from jmd1010/directory-structure-update
Update Web V2 Install Guide layout
2025-03-05 10:09:23 +01:00
Kayvan Sylvan
de356ddeb5 chore: update version 2025-03-04 22:00:26 -08:00
Kayvan Sylvan
59c50def2a feat: update yt commands and docs to support timestamped transcripts
CHANGES
- Add argument validation to yt for usage errors
- Enable -t flag for transcript with timestamps
- Refactor PowerShell yt function with parameter switch
- Update README to dynamically select transcript option
- Document youtube_summary feature in pattern explanations
- Introduce youtube_summary pattern.
2025-03-04 21:46:50 -08:00
Kayvan Sylvan
1dafb09e07 remove spurious newline 2025-03-04 21:20:24 -08:00
Kayvan Sylvan
e8caf9fc10 feat: update YouTube regex to support live URLs 2025-03-04 21:18:51 -08:00
jmd1010
59537c4bf5 Update Web V2 Install Guide layout 2 2025-03-04 12:29:31 -05:00
Eckii24
231516917d Update azure.go 2025-03-04 17:39:56 +01:00
Eckii24
58d17fd0ec Update openai.go 2025-03-04 17:37:19 +01:00
Eckii24
8bd4aa6d1a Update azure_test.go 2025-03-04 17:36:37 +01:00
Eckii24
629c1b3e11 Update azure.go 2025-03-04 17:36:11 +01:00
jmd1010
2f4569177d Update Web V2 Install Guide layout 2025-03-04 10:58:48 -05:00
Eugen Eisler
f2b85af0ea Merge pull request #1330 from jmd1010/directory-structure-update
Fixed ALL CAP DIR as requested and processed minor updates to documentation
2025-03-04 12:17:03 +01:00
Eugen Eisler
36be4c747c Merge pull request #1333 from asasidh/main
Update QUOTES section to include speaker names for clarity
2025-03-04 09:35:53 +01:00
github-actions[bot]
7ac9b862f5 Update version to v1.4.148 and commit 2025-03-03 11:08:37 +00:00
Eugen Eisler
1515139dd6 fix: Rework LM Studio plugin 2025-03-03 12:07:20 +01:00
asasidh
be6049e577 Update QUOTES section to include speaker names for clarity 2025-03-02 17:42:52 -06:00
jmd1010
a8ae09d4d6 Update Web V2 Install Guide with improved instructions V2 2025-02-28 19:57:13 -05:00
jmd1010
30059c46a0 Update Web V2 Install Guide with improved instructions 2025-02-28 13:23:43 -05:00
jmd1010
2d10c71e39 Reorganize documentation with consistent directory naming and updated guides 2025-02-28 11:34:17 -05:00
github-actions[bot]
02e12b028c Update version to v1.4.147 and commit 2025-02-28 07:59:43 +00:00
Eugen Eisler
6686b83fc8 Merge pull request #1326 from pavdmyt/pavdmyt/fix-vendors-manager-for-localhost-models
fix: continue fetching models even if some vendors fail
2025-02-28 08:58:25 +01:00
Eugen Eisler
d53b0b678f Merge pull request #1329 from jmd1010/web-install-guide-pr
Svelte Web V2 Installation Guide
2025-02-28 08:55:51 +01:00
jmd1010
0d5454372e Update install guide with Plain Text instructions 2025-02-28 02:08:23 -05:00
jmd1010
2f040f94c3 Add Web V2 Installation Guide 2025-02-28 00:54:44 -05:00
Pavel Dmytrenko
0b29ebd14b fix: continue fetching models even if some vendors fail
Remove the cancellation of remaining goroutines when a vendor collection fails.
This ensures that other vendor collections continue even if one fails.

Fixes listing models via `fabric -L` and using non-default models via `fabric -m custom_model`,
when localhost models (e.g. Ollama, LM Studio) are not listening on a given port (basically shut down).
2025-02-27 16:13:08 +02:00
github-actions[bot]
1dad903199 Update version to v1.4.146 and commit 2025-02-27 06:16:20 +00:00
Eugen Eisler
0bec53360e Merge pull request #1319 from jmd1010/pdf-integration-clean
Enhancement: PDF to Markdown Conversion Functionality to the Web Svelte Chat Interface
2025-02-27 07:15:03 +01:00
JM
cf637e4137 Merge branch 'main' into pdf-integration-clean 2025-02-27 01:02:04 -05:00
jmd1010
9507c2cca1 Reinstate file in original location to resolve PR conflict 2025-02-27 01:01:16 -05:00
jmd1010
fa575638d1 Remove pr-1284-update.md from tracking to resolve PR conflict 2025-02-27 00:55:58 -05:00
jmd1010
51220c40d9 Add required UI image assets for feature implementation 2025-02-27 00:11:04 -05:00
jmd1010
d1d62fcc4c Complete directory reorganization by moving pr-1284-update.md to new location 2025-02-26 23:44:56 -05:00
jmd1010
96e6a56e5f Restore file to original location to resolve path conflict 2025-02-26 23:38:14 -05:00
jmd1010
0d7514ea0e Remove pr-1284-update.md from PR scope 2025-02-26 23:21:06 -05:00
jmd1010
a74da4acff Rename pattern descriptions directory to follow consistent naming convention 2025-02-26 23:14:51 -05:00
jmd1010
6d8c3eb6e2 Update README files directory structure and naming convention 2025-02-26 22:23:53 -05:00
jmd1010
adbfa2f6ba Remove pdf-to-markdown folder from PR 2025-02-26 21:57:04 -05:00
github-actions[bot]
f5776637d9 Update version to v1.4.145 and commit 2025-02-26 16:54:02 +00:00
Eugen Eisler
34db384265 Merge pull request #1324 from jaredmontoya/nix-fix
flake: fix/update and enhance
2025-02-26 17:52:47 +01:00
jaredmontoya
1f765c5b53 flake: fix/update 2025-02-26 16:12:05 +01:00
github-actions[bot]
f9395fa108 Update version to v1.4.144 and commit 2025-02-26 08:55:35 +00:00
Eugen Eisler
22d2a3ee19 Upgrade upload artifacts to v4 2025-02-26 09:54:44 +01:00
github-actions[bot]
b64178c292 Update version to v1.4.143 and commit 2025-02-26 08:53:09 +00:00
Eugen Eisler
f7d38fb51f Merge pull request #1264 from danielmiessler/feat/exolab
feat: implement support for exolab
2025-02-26 09:52:13 +01:00
Eugen Eisler
ea6c0b9025 Merge branch 'main' into feat/exolab 2025-02-26 09:50:53 +01:00
github-actions[bot]
30fa5ee575 Update version to v1.4.142 and commit 2025-02-25 22:13:23 +00:00
Eugen Eisler
1e345af0bc fix: build problems 2025-02-25 23:12:10 +01:00
github-actions[bot]
952f584158 Update version to v1.4.141 and commit 2025-02-25 22:05:32 +00:00
Eugen Eisler
b23b20f540 Merge pull request #1260 from bluPhy/main
Fixing typo
2025-02-25 23:04:42 +01:00
Eugen Eisler
1980edbe1c Merge branch 'main' into main 2025-02-25 23:04:36 +01:00
github-actions[bot]
bf618f4a25 Update version to v1.4.140 and commit 2025-02-25 21:21:32 +00:00
Eugen Eisler
e4617190d8 Merge pull request #1313 from CXKswain/main
Updated ollama.go to fix a couple of potential DoS issues
2025-02-25 22:20:27 +01:00
Eugen Eisler
49fe59f403 Merge branch 'main' into main 2025-02-25 22:20:13 +01:00
github-actions[bot]
821faa0894 Update version to v1.4.139 and commit 2025-02-25 21:18:10 +00:00
Eugen Eisler
af39e38394 Don't trigger on PRs 2025-02-25 22:17:21 +01:00
Eugen Eisler
8774971b98 Merge pull request #1321 from jmd1010/youtube-link-only
Update demo video link in PR-1309 documentation
2025-02-25 22:07:47 +01:00
jmd1010
1286afeb76 Update demo video link in PR-1284 documentation 2025-02-25 00:13:02 -05:00
jmd1010
4725a94f00 Add complete PDF to Markdown documentation F 2025-02-24 22:33:27 -05:00
jmd1010
15ac5351cf Add Svelte implementation files for PDF integration 2025-02-24 21:46:03 -05:00
jmd1010
f69cda8fab Add PDF to Markdown integration documentation 2025-02-24 21:39:43 -05:00
github-actions[bot]
e9e6549528 Update version to v..1 and commit 2025-02-24 22:29:21 +00:00
CXKswain
f1550e1d1d Delete version.go 2025-02-24 16:28:34 -06:00
CXKswain
1fe00633c4 Delete pkgs/fabric/version.nix 2025-02-24 16:28:13 -06:00
jmd1010
a0e1f7204d Add PDF to Markdown conversion functionality to the web svelte caht interface 2025-02-24 17:24:02 -05:00
Daniel Miessler
bb1d4f9ca4 Update README.md 2025-02-24 13:48:56 -08:00
github-actions[bot]
942771af60 Update version to v1.4.138 and commit 2025-02-24 21:35:00 +00:00
Eugen Eisler
1f0bf7b58b Merge pull request #1317 from ksylvan/main
chore: update Anthropic SDK and add Claude 3.7 Sonnet model support
2025-02-24 22:34:06 +01:00
github-actions[bot]
d56dcb8b16 Update version to v1.4.80 and commit 2025-02-24 21:18:13 +00:00
bluPhy
ca83506089 Revert "Update version to v1.4.79 and commit"
This reverts commit 6e0f7b5192.
2025-02-24 16:16:48 -05:00
Kayvan Sylvan
267562e1d2 Merge remote-tracking branch 'upstream/main' 2025-02-24 12:39:12 -08:00
github-actions[bot]
0ac8924b0d Update version to v1.4.137 and commit 2025-02-24 20:25:10 +00:00
Eugen Eisler
540186acca Merge pull request #1296 from danielmiessler/dependabot/go_modules/go_modules-0f02992d2e
Bump github.com/go-git/go-git/v5 from 5.12.0 to 5.13.0 in the go_modules group across 1 directory
2025-02-24 21:24:05 +01:00
github-actions[bot]
b26d466394 Update version to v1.4.136 and commit 2025-02-24 20:21:43 +00:00
Eugen Eisler
12603b619b Update to upload-artifact@v4 because upload-artifact@v3 is deprecated 2025-02-24 21:20:51 +01:00
Kayvan Sylvan
9af69d456e Merge branch 'danielmiessler:main' into main 2025-02-24 12:17:51 -08:00
Kayvan Sylvan
61f0b5848c chore: update Anthropic SDK and add Claude 3.7 Sonnet model support
## CHANGES

- Updated anthropic-sdk-go from v0.2.0-alpha.4 to v0.2.0-alpha.11
- Added Claude 3.7 Sonnet models to available model list
- Added ModelClaude3_7SonnetLatest to model options
- Added ModelClaude3_7Sonnet20250219 to model options
- Removed ModelClaude_Instant_1_2 from available models
2025-02-24 12:13:02 -08:00
github-actions[bot]
cbc82ec045 Update version to v1.4.135 and commit 2025-02-24 20:10:17 +00:00
Eugen Eisler
c8af946c87 Merge pull request #1309 from jmd1010/feature/web-ui-enhancements
Feature/Web Svelte GUI Enhancements: Pattern Descriptions, Tags, Favorites, Search Bar, Language Integration, PDF file conversion, etc
2025-02-24 21:09:23 +01:00
Eugen Eisler
bc216fdfef Merge pull request #1312 from junaid18183/main
Added Create LOE Document Prompt
2025-02-24 20:59:43 +01:00
Eugen Eisler
8befac61af Merge pull request #1302 from verebes1/feat/add-lmstudio
feat: Add LM Studio compatibility
2025-02-24 20:58:36 +01:00
“CXKswain”
bebc8c20b5 Resolving a couple of more medium vulnerabilites 2025-02-21 14:52:03 -06:00
“CXKswain”
9a1a46e203 Updated to fix security issues with ollama.go 2025-02-21 14:39:05 -06:00
github-actions[bot]
a5ab81b5c8 Update version to v..1 and commit 2025-02-21 20:30:21 +00:00
Juned Memon
31be01f3b3 Added create_loe_document prompt 2025-02-21 19:35:28 +05:30
Juned Memon
52e2995c55 Added create_loe_document prompt 2025-02-21 19:26:36 +05:30
jmd1010
f314671f65 Exclude static PNG files from PR 2025-02-20 15:18:32 -05:00
jmd1010
292fd75699 Remove PNG files from PR scope 2025-02-20 15:02:39 -05:00
jmd1010
0a07072be0 Enhance pattern handling and chat interface improvements 2025-02-20 13:27:31 -05:00
jmd1010
5d31e90650 Update .gitignore to exclude sensitive and generated files 2025-02-19 22:18:41 -05:00
jmd1010
8bff9764f8 Remove sensitive and generated files from tracking 2025-02-19 22:17:20 -05:00
jmd1010
40c4cb46be Remove personal development notes from tracking 2025-02-19 21:55:00 -05:00
jmd1010
8a0f9814e6 Development checkpoint - Web UI enhancements with complete directory structure 2025-02-19 21:47:10 -05:00
jmd1010
717eb585b5 Setup backup configuration and update dependencies 2025-02-18 14:10:19 -05:00
JM
e10a2c9b09 Update ENV 2025-02-18 11:27:14 -05:00
David
c6ebfd3ad7 feat: Add LM Studio compatibility
- Added LM Studio as a new plugin, now it can be used with Fabric.
- Updated the plugin registry with the new plugin name
- Updated the configuration with the required base url
2025-02-17 23:17:44 +00:00
Eugen Eisler
0369087b91 Merge pull request #1297 from Perchycs/patch-1
Create pattern_explanations.md
2025-02-14 08:52:40 +01:00
Daniel Miessler
d8a415698c updated extract domains 2025-02-13 18:36:46 -08:00
Daniel Miessler
2bfb087b55 updated extract domains 2025-02-13 18:33:30 -08:00
Daniel Miessler
8782f78178 Added extract_domains 2025-02-13 18:26:36 -08:00
Perchycs
90c4f244ae Create pattern_explanations.md
Spent way too long getting chatgpt to give a one-line summary, based on the contents of each prompt.
2025-02-12 18:36:05 +13:00
github-actions[bot]
2331d011c1 Update version to v1.4.134 and commit 2025-02-11 22:23:42 +00:00
Eugen Eisler
2568204395 Merge pull request #1289 from thevops/pull-transcript-with-timestamps
Add the ability to grab YouTube video transcript with timestamps
2025-02-11 23:22:51 +01:00
github-actions[bot]
eb56ead927 Update version to v1.4.133 and commit 2025-02-11 22:22:36 +00:00
dependabot[bot]
98fe1fbae2 Bump github.com/go-git/go-git/v5
Bumps the go_modules group with 1 update in the / directory: [github.com/go-git/go-git/v5](https://github.com/go-git/go-git).


Updates `github.com/go-git/go-git/v5` from 5.12.0 to 5.13.0
- [Release notes](https://github.com/go-git/go-git/releases)
- [Commits](https://github.com/go-git/go-git/compare/v5.12.0...v5.13.0)

---
updated-dependencies:
- dependency-name: github.com/go-git/go-git/v5
  dependency-type: direct:production
  dependency-group: go_modules
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-11 22:22:23 +00:00
Eugen Eisler
8e10a72f1d Merge pull request #1294 from TvisharajiK/main
Improved unit-test coverage from 0 to 100 (AI module) using Keploy's agent
2025-02-11 23:21:12 +01:00
Tvisha
5246a9699a Merge pull request #1 from TvisharajiK/unittests
Improved unit-test coverage from 0 to 100% using Keploy AI Agent
2025-02-11 02:54:52 +05:30
TvisharajiK
7a678dc175 Feat: Increase unit test coverage from 0 to 100% in the AI module using Keploy's Agent 2025-02-11 02:53:36 +05:30
Daniel Miessler
b2e2784cf4 Added h3 TELOS pattern. 2025-02-07 11:57:49 -08:00
Daniel Miessler
111e8c786a Added challenge handling pattern. 2025-02-07 08:13:52 -08:00
Daniel Miessler
b8b9cdfdae Added year in review pattern. 2025-02-07 08:08:35 -08:00
Daniel Miessler
bfcbe6f06a Adding more TELOS patterns. 2025-02-07 07:36:25 -08:00
Daniel Miessler
02c28ad8b8 Added additional Telos patterns. 2025-02-07 07:11:26 -08:00
Krzysztof Łuczak
f3a1982e30 Add the ability to grab YouTube video transcript with timestamps
This commit adds the ability to grab the transcript
of a YouTube video with timestamps. The timestamps
are formatted as HH:MM:SS and are prepended to
each line of the transcript. The feature is enabled
by the new `--transcript-with-timestamps` flag,
so it's similar to the existing `--transcript` flag.

Example future use-case:

Providing summary of a video that includes timestamps
for quick navigation to specific parts of the video.
2025-02-07 15:25:22 +01:00
Daniel Miessler
c4b629fe03 Updated panel topic extractor 2025-02-06 22:19:51 -08:00
Daniel Miessler
f962104a2d Added panel topic extractor 2025-02-06 22:16:25 -08:00
Daniel Miessler
cf32bdc012 Added intro sentences pattern 2025-02-06 22:13:45 -08:00
Daniel Miessler
1ccbb22866 Updated announcement at the top 2025-02-06 14:50:01 -08:00
github-actions[bot]
d5a2008c44 Update version to v1.4.132 and commit 2025-02-02 13:50:30 +00:00
Eugen Eisler
ff33c33ea5 Merge pull request #1278 from aicharles/feat/anthropic-plugin-update
feat(anthropic): enable custom API base URL support
2025-02-02 14:49:37 +01:00
aicharles
731ecc6b3c feat(anthropic): enable custom API base URL support
- Enable and improve custom API base URL configuration
- Add proper handling of v1 endpoint for UUID-containing URLs
- Implement URL formatting logic for consistent endpoint structure
- Clean up commented code and improve configuration flow
2025-01-30 08:48:38 -06:00
github-actions[bot]
31df56add8 Update version to v1.4.131 and commit 2025-01-30 00:50:21 +00:00
Eugen Eisler
0f8a403dba Merge pull request #1270 from wmahfoudh/adding-output-filename-support-to-to_pdf
Added output filename support for to_pdf
2025-01-30 01:49:25 +01:00
Eugen Eisler
8b33b9946e Merge pull request #1271 from wmahfoudh/adding-deepseek-support
Adding deepseek support
2025-01-30 01:48:10 +01:00
Walid
a77efada0e feat: Added Deepseek AI integration 2025-01-23 20:50:56 +04:00
Walid
3e8aaed268 Added output filename support for to_pdf 2025-01-23 19:25:18 +04:00
Eugen Eisler
d25be21939 feat: implement support for https://github.com/exo-explore/exo 2025-01-18 19:55:24 +01:00
Eugen Eisler
c2fad4de80 Merge pull request #1258 from tuergeist/readme-patch-1
Minor README fix and additional Example
2025-01-18 19:35:42 +01:00
github-actions[bot]
6e0f7b5192 Update version to v1.4.79 and commit 2025-01-14 22:51:28 +00:00
bluPhy
f522f6b3bd Typos correction 2025-01-14 17:49:56 -05:00
Christoph Becker
e558d535df doc: Add scrape URL example. Fix Example 4 2025-01-13 14:58:39 +01:00
Christoph Becker
1c05b37c76 doc: Custom patterns also work with Claude models 2025-01-13 14:18:41 +01:00
Eugen Eisler
e46c588b9c Merge pull request #1257 from jessefmoore/main
Create analyze_threat_report_cmds
2025-01-13 13:31:52 +01:00
Eugen Eisler
3bf6b7b000 Merge pull request #1256 from JOduMonT/patch-1
Update README.md
2025-01-13 12:02:25 +01:00
Daniel Miessler
82db18a8aa Updated conversion post. 2025-01-13 00:16:13 -08:00
Daniel Miessler
5a765bd8fc Adding markdown converter. 2025-01-12 23:34:25 -08:00
Daniel Miessler
339e1e6790 Updated prediction creator. 2025-01-12 21:38:21 -08:00
Daniel Miessler
a106e6de27 Updated predictor pattern. 2025-01-12 16:37:26 -08:00
Daniel Miessler
86eddbeb0a Added new prediction generator. 2025-01-12 13:34:18 -08:00
Jesse Moore
2daf0d90ce Create system.md
Create pattern to extract commands from videos and threat reports to obtain commands so pentesters or red teams or Threat hunters can use to either threat hunt or simulate the threat actor.
2025-01-12 09:48:28 -08:00
Jonathan DUMONT
03dfa03f46 Update README.md
## Change
1. Windows Command: Because actually curl does not exist natively on Windows
2. Syntax: Because like this; it makes the “click, cut and paste” easier
2025-01-12 13:55:37 +01:00
Eugen Eisler
92bbbfe88b Merge pull request #1247 from kevnk/update-suggest_pattern-user-prompt
Update suggest_pattern: refine summaries and add recently added patterns
2025-01-10 12:57:57 +01:00
Eugen Eisler
fb2dc00b9c Merge pull request #1252 from jeffmcjunkin/patch-1
Update README.md: Add PowerShell aliases
2025-01-10 12:57:00 +01:00
Eugen Eisler
0014a53c6e Merge pull request #1253 from abassel/fix/fix_few_typos
Fixed few typos that I could find
2025-01-10 12:56:25 +01:00
Alexandre Bassel
021d2738e4 Fixed few typos that I could find 2025-01-10 03:44:54 -03:00
Jeff McJunkin
f312ad0364 Update README.md: Add PowerShell aliases 2025-01-09 12:39:23 -08:00
Kevin Kirchner
02aa41e6aa Update summaries and add recently added patterns 2025-01-05 14:59:31 -06:00
github-actions[bot]
1f8039d996 Update version to v1.4.130 and commit 2025-01-03 20:53:29 +00:00
Eugen Eisler
977d902cdd Merge pull request #1240 from johnconnor-sec/main
Updates: ./web
2025-01-03 21:52:36 +01:00
github-actions[bot]
710df90361 Update version to v1.4.129 and commit 2025-01-03 20:42:19 +00:00
Eugen Eisler
f5d94bfde6 Merge pull request #1242 from CuriouslyCory/main
Adding youtube --metadata flag
2025-01-03 21:40:57 +01:00
Cory Sougstad
1629f36c59 Better metadata 2025-01-02 09:41:15 -07:00
John
12e4611d9a Update README 2025-01-01 04:38:59 -05:00
John
46a77de9e8 Remove inbox note 2025-01-01 03:10:35 -05:00
John Connor
87b55148fa Merge pull request #11 from danielmiessler/main
Updates from main
2025-01-01 02:54:15 -05:00
John
3931098aad Merge branch 'main' of https://github.com/johnconnor-sec/fabric 2025-01-01 02:48:25 -05:00
John
2aebc84c66 Update README 2025-01-01 02:48:15 -05:00
John
c107cce22e Updates for BUILD 2025-01-01 02:08:41 -05:00
John
71b049bffd Fixing indentation again
Removed backup side-nav and terminal.
updated toast for transcripts
2025-01-01 00:00:30 -05:00
John
d3e8ce5120 Added: Only dates are required for Posts now. 2024-12-31 23:27:19 -05:00
John
ce7fc78076 Fix: Chat.svelte indentation
Removed backup files
2024-12-31 23:19:37 -05:00
John
f911de41b5 Fix: NoteDrawer textarea sizing 2024-12-31 22:03:13 -05:00
John
7288001a01 Updated tags page to use Frontmatter instead of PostMetadata
buffer issues
2024-12-31 20:35:19 -05:00
John
7f808bcf43 Deleting old files that were moved or renamed
Folders deleted:
- `types`. The folders contained are now `lib/interfaces` and `lib/api`
- `types/markdown` now in `utils/markdown`
- `components/ui/{side-nav,terminal}` now `components/ui/toc` and
`terminal`
2024-12-31 20:09:20 -05:00
John
025dc8ed13 !NOTEDRAWER IS NOW CENTERED IN VIEWPORT! 2024-12-31 20:04:59 -05:00
Cory Sougstad
b4b8b96260 Added metadata lookup to youtube helper 2024-12-31 15:31:17 -07:00
Daniel Miessler
b07054adea Font familiy changes. 2024-12-31 13:58:37 -08:00
John
fc0fd00e16 !!CHAT IS NOW CENTERED IN VIEWPORT!!
!Chat is now centered in the viewport!
2024-12-31 16:44:38 -05:00
John
a3da84f459 Edit: styling on Posts page 2024-12-31 16:36:56 -05:00
Daniel Miessler
ff21c60661 16 word summaries. 2024-12-31 11:30:42 -08:00
John
58a6f0404a Indented Toc 2024-12-31 13:13:58 -05:00
John
643403192a Added: blinking cursor to Terminal. Removed / added comments
Removed from ChatMessages
Added to api/context
2024-12-31 12:58:47 -05:00
John
416cee4f54 Update: References
Moved
- `lib/types/interfaces` to `lib/interfaces`.
- `components/ui/side-nav` to `components/ui/toc`.
- `components/ui/terminal` to `components/terminal`.
- `types/markdown` to `utils/markdown`
- `lib/types/chat` to `lib/api`
2024-12-31 12:21:40 -05:00
John
e42be19347 Edit: type/note to note
type/note was causing problems.
2024-12-31 12:15:20 -05:00
John
78bae7a6e7 House Keeping: Added missing png. Removed more unused 2024-12-30 10:13:46 -05:00
John
ec31f11abf Update README to reflect current @12-30-24 2024-12-30 10:12:33 -05:00
John
2d3ebcd09c House Keeping: Fixing Indentation 2024-12-30 09:52:07 -05:00
John
5da749f994 Update: Contact page 2024-12-30 08:54:07 -05:00
John
85891f0106 Updated copy 2024-12-30 08:33:58 -05:00
John
229287510a Indentation 2024-12-30 04:03:41 -05:00
John
d42ba42bb2 Add: Templates for posts 2024-12-30 03:59:31 -05:00
John
574bb2c450 Fix: Obsidian Card. Indented app.html 2024-12-30 02:21:55 -05:00
John
3797b7ac6a Update: removed grid from PostContent 2024-12-29 18:02:04 -05:00
John
ed7c28958f Update: ui/button component 2024-12-29 18:00:54 -05:00
John
74a134eec0 Rename chat.ts to chat-store.ts 2024-12-29 17:59:45 -05:00
John
4094296a4c Rename noteStore to note-store 2024-12-29 17:58:24 -05:00
John Connor
00a706eb36 Merge pull request #10 from danielmiessler/main
Merge Main to my fork
2024-12-29 12:16:57 -05:00
Daniel Miessler
dfc0efbb67 Updated wrapping instructions. 2024-12-28 21:32:24 -08:00
Daniel Miessler
d79449be4a Enhanced pattern. 2024-12-28 21:21:21 -08:00
Daniel Miessler
5c6b84e4ec Enhanced enrich pattern. 2024-12-28 21:00:23 -08:00
Daniel Miessler
0fcd4945fb Enhanced enrich pattern. 2024-12-28 20:37:39 -08:00
Daniel Miessler
c10ae1ddd2 Merge branch 'main' of github.com:danielmiessler/fabric 2024-12-28 20:27:24 -08:00
Daniel Miessler
9774692b67 Added enrich_blog_post 2024-12-28 20:27:17 -08:00
John
f8f39b92c3 Deleted lib/layouts/files. Renamed lib/store/theme
lib/layouts/files are not longer in use. Renamed lib/store/theme to
adhere to current naming convention
2024-12-28 07:10:14 -05:00
John Connor
eb8d40dfb6 Merge pull request #9 from danielmiessler/main
Another merge nightmare. This one wasn't so bad
2024-12-28 06:52:42 -05:00
John Connor
343cbba5ec Update version.nix
Update version to v..1 and commit

Update version.go

Update version to v..1 and commit

Update version.nix

Update version to v..1 and commit

Update version.go

Update version.nix
2024-12-28 06:52:42 -05:00
John Connor
ac3e0b5ba0 Merge pull request #9 from danielmiessler/main
Another merge nightmare. This one wasn't so bad
2024-12-28 06:48:01 -05:00
John Connor
55c11a3861 Update version.nix 2024-12-28 06:47:25 -05:00
John Connor
013c6cb1e5 Update version.go 2024-12-28 06:47:03 -05:00
github-actions[bot]
fc54f0e32e Update version to v..1 and commit 2024-12-28 11:45:59 +00:00
John Connor
5a63c6b260 Update version.nix 2024-12-28 06:44:51 -05:00
github-actions[bot]
157b0a6109 Update version to v..1 and commit 2024-12-28 11:44:47 +00:00
John Connor
b10455ff76 Update version.go 2024-12-28 06:43:44 -05:00
github-actions[bot]
a7b4a7160a Update version to v..1 and commit 2024-12-28 11:42:43 +00:00
John Connor
65bb9fee84 Update version.nix 2024-12-28 06:41:51 -05:00
John
b701c767fc Update: Post page styling and layout
Indented unused Search.svelte file
2024-12-28 06:14:11 -05:00
John
2a450cf1be Minor styling improvements 2024-12-28 05:42:48 -05:00
John
1f1b51edcf Remove: Docs in Posts 2024-12-28 05:33:19 -05:00
Eugen Eisler
e45f24c6fd Merge pull request #1230 from iqbalabd/translate-curly-braces
Update translate pattern to use curly braces
2024-12-27 14:44:29 +01:00
John
eae691aa8c Update: NotesDrawer now saves notes to lib/content/inbox 2024-12-27 03:57:35 -05:00
John
9d8d5ca924 WIP: Restyling Chat page 2024-12-27 02:13:49 -05:00
John
84e3ff9386 Indented Main page 2024-12-27 02:13:31 -05:00
John
002e87ffbb Moved NotesDrawer to ModelConfig component 2024-12-27 00:13:39 -05:00
John
4be9cf42b4 Deleted: Moved Components from /home to respective dirs 2024-12-26 23:32:39 -05:00
John
75aad67a22 Add: NotesDrawer to header 2024-12-26 23:31:04 -05:00
John
b8a285bbbc Removed styling from /routes/chat/*.svelte 2024-12-26 23:19:35 -05:00
Iqbal Abdullah
fb416c26ea Update translate pattern to use curly braces 2024-12-27 09:50:53 +09:00
github-actions[bot]
e858700976 Update version to v1.4.128 and commit 2024-12-26 20:07:20 +00:00
Eugen Eisler
525b89be71 Merge pull request #1227 from mattjoyce/feature/template-extensions
Feature/template extensions
2024-12-26 21:06:26 +01:00
Daniel Miessler
e15280d25d Updated story to be shorter bullets. 2024-12-24 15:57:46 -08:00
Matt Joyce
7a26012457 Updated extension readme 2024-12-25 10:22:52 +11:00
Matt Joyce
a5929fcad6 Fix tests to handle NewPluginRegistry returning error 2024-12-25 10:20:26 +11:00
Matt Joyce
ad561248fd fix:properly instatiated extensionManager var
fix:added timeout value validation
2024-12-25 09:41:49 +11:00
John
f8f892bfe0 WIP: Notes Drawer text color 2024-12-24 07:51:10 -05:00
John
8c68ebc0ee WIP: Notes Drawer. Updated default theme to rocket 2024-12-24 07:40:29 -05:00
John
cbd2ffe81d Updated POSTS to make main 24-12-08 2024-12-24 05:18:36 -05:00
John
86b76faa5b Update imports 2024-12-23 22:34:00 -05:00
Matt Joyce
edb4490c86 Merge branch 'main' into feature/template-extensions 2024-12-24 13:12:13 +11:00
github-actions[bot]
70c9746bcb Update version to v1.4.127 and commit 2024-12-23 20:52:29 +00:00
Eugen Eisler
ba774d26c6 Merge pull request #1218 from sosacrazy126/main
streamlit ui
2024-12-23 21:51:36 +01:00
Eugen Eisler
2e2177e26b Merge pull request #1225 from wmahfoudh/humanize-pattern
Added Humanize Pattern
2024-12-23 12:07:31 +01:00
Walid
72ec02bfd4 Added Humanize Pattern 2024-12-23 13:19:01 +04:00
github-actions[bot]
9b94518e20 Update version to v1.4.126 and commit 2024-12-22 14:57:53 +00:00
Eugen Eisler
b550936e72 Merge pull request #1212 from wrochow/main
Significant updates to Duke and Socrates
2024-12-22 15:56:50 +01:00
Eugen Eisler
ce2d6def36 Merge branch 'main' into main 2024-12-22 15:56:41 +01:00
github-actions[bot]
1977c6260a Update version to v..1 and commit 2024-12-22 14:54:26 +00:00
Eugen Eisler
811e4c84ab Update version.go 2024-12-22 15:53:39 +01:00
github-actions[bot]
104513f72b Update version to v1.4.125 and commit 2024-12-22 14:53:17 +00:00
Eugen Eisler
e434999802 Merge pull request #1222 from wmahfoudh/fix-cross-filesystem-move
Fix cross-filesystem file move in to_pdf plugin (issue 1221)
2024-12-22 15:52:13 +01:00
Walid
fce06b5294 Fix cross-filesystem file move in to_pdf plugin (issue 1221) 2024-12-22 13:58:45 +04:00
github-actions[bot]
c53f160ab8 Update version to v..1 and commit 2024-12-21 23:53:07 +00:00
Waldo Rochow
4100ace659 Don't quite know how I screwed this up, I wasn't even working there. 2024-12-21 18:52:03 -05:00
github-actions[bot]
1e7ae9790c Update version to v..1 and commit 2024-12-21 23:27:32 +00:00
Waldo Rochow
ac1fc4b1d6 Merge branch 'main' into main 2024-12-21 18:26:39 -05:00
Zo6
79b23f3106 Merge branch 'main' into main 2024-12-21 10:22:32 -08:00
github-actions[bot]
6d00405eb6 Update version to v1.4.124 and commit 2024-12-21 14:01:47 +00:00
Eugen Eisler
65285fdef0 Merge pull request #1215 from infosecwatchman/main
Add Endpoints to facilitate Ollama based chats
2024-12-21 15:00:52 +01:00
Eugen Eisler
89edd7152a Merge pull request #1214 from iliajie/fix/patterns-translate
Fix the typo in the sentence
2024-12-21 14:59:48 +01:00
Eugen Eisler
5527dc8db5 Merge pull request #1213 from AnirudhG07/main
Spelling Fixes
2024-12-21 14:59:21 +01:00
Zo6
f5ac7fd92c Delete patternstudio.py 2024-12-20 06:32:00 -08:00
Zo6
61027f30a4 Update README.md 2024-12-20 06:30:33 -08:00
zo6
575f83954d Refactor pattern management and enhance error handling
- Improved pattern creation, editing, and deletion functionalities.
- Enhanced logging configuration for better debugging and user feedback.
- Updated input validation and sanitization processes to ensure safe pattern processing.
- Streamlined session state initialization for improved performance.
- Added new UI components for better user experience in pattern management and output analysis.
2024-12-20 05:58:33 -08:00
github-actions[bot]
ae18e9d1c7 Update version to v1.4.123 and commit 2024-12-20 11:17:36 +00:00
Eugen Eisler
76d18e2f04 Merge pull request #1208 from mattjoyce/fix/yaml-config
Fix: Issue with the custom message and added example config file.
2024-12-20 12:16:33 +01:00
Zo6
978731f385 Add files via upload
Streamlit application for managing and executing patterns, with a focus on pattern creation, execution, and analysis. Below is a breakdown of the key components and functionality of the application:
Key Components and Functionality

    Logging Configuration:

        The application sets up logging with both console and file handlers.

        The console logs are color-coded for better readability, and the file logs are more detailed for debugging purposes.

    Session State Initialization:

        The initialize_session_state() function initializes the session state with default values for various configuration and UI states.

        It also loads saved outputs from persistent storage.

    Pattern Management:

        Pattern Creation: The create_pattern() function allows creating new patterns with either simple or advanced editing options.

        Pattern Deletion: The delete_pattern() function allows deleting existing patterns.

        Pattern Editing: The pattern_editor() function provides an interface for editing existing patterns.

    Pattern Execution:

        Pattern Execution: The execute_patterns() function executes selected patterns and captures their outputs.

        Pattern Chain Execution: The execute_pattern_chain() function executes a sequence of patterns in a chain, passing output from each pattern to the next.

    Output Management:

        Saving Outputs: The save_output_log() function saves pattern execution logs.

        Starring Outputs: The star_output() and unstar_output() functions allow users to star/favorite outputs for quick access.

    Configuration and Model Selection:

        Model and Provider Selection: The load_models_and_providers() function fetches and displays available models and providers for selection.

        Configuration Loading: The load_configuration() function loads environment variables and initializes the configuration.

    UI Components:

        Pattern Creation UI: The pattern_creation_ui() and pattern_creation_wizard() functions provide UI components for creating new patterns.

        Pattern Management UI: The pattern_management_ui() function provides UI components for managing patterns.

        Output Analysis UI: The application includes tabs for displaying all outputs and starred outputs, with options to copy or star outputs.

    Error Handling and Validation:

        Input Validation: The validate_input_content() and sanitize_input_content() functions validate and sanitize input content to ensure it is safe for processing.

        Pattern Validation: The validate_pattern() function validates the structure and content of a pattern.

    Main Function:

        The main() function orchestrates the entire application, setting up the Streamlit page, initializing session state, and handling the main navigation between different views (Run Patterns, Pattern Management, Analysis Dashboard).

Usage and Features

    Pattern Creation: Users can create new patterns using either a simple text editor or an advanced wizard.

    Pattern Execution: Users can select patterns to run, provide input, and execute them either individually or in a chain.

    Output Analysis: Users can view and analyze the outputs of executed patterns, star favorite outputs, and copy outputs to the clipboard.

    Pattern Management: Users can edit, delete, and bulk edit patterns.

    Configuration: Users can select different models and providers for pattern execution.

Error Handling and Logging

    The application includes robust error handling and logging to ensure that any issues are logged and displayed to the user.

    Logging is done both to the console and to a file for debugging purposes.

Future Enhancements

    Enhanced Pattern Validation: More comprehensive validation of pattern content and structure.

    Advanced Analysis: Adding more advanced analysis features, such as sentiment analysis or keyword extraction on pattern outputs.

    Integration with External APIs: Integrating with external APIs for additional functionality, such as sending outputs via email or storing them in a database.
2024-12-19 20:50:56 -08:00
InfosecWatchman
103388ecec Add Endpoints to facilitate Ollama based chats
Add Endpoints to facilitate Ollama based chats.

Built to use with Open WebUI
2024-12-19 16:14:51 -05:00
Ilia Ross
53ea7ab126 Fix the typo in the sentence 2024-12-19 12:26:44 +02:00
AnirudhG07
b008d17b6e Spelling fixes in create_quiz pattern 2024-12-19 13:52:25 +05:30
AnirudhG07
2ba294f4d6 Spelling fix in READEME 2024-12-19 13:50:06 +05:30
AnirudhG07
a7ed257fe3 Spelling fixes in patterns 2024-12-19 13:38:37 +05:30
github-actions[bot]
9a9990f78c Update version to v..1 and commit 2024-12-18 03:34:57 +00:00
Waldo Rochow
95f0c95832 Merge branch 'main' into main 2024-12-17 22:33:20 -05:00
Waldo Rochow
3b1b0385e1 Significant update
Added specific steps for research, analysis, and code reviews.
2024-12-17 22:26:01 -05:00
Waldo Rochow
621b64c89f Significant thematic rewrite.
Ingested the following documents, and then extracted themes and examples of how Socrates interacted with those around him.
* Apology by Plato
* Phaedrus by Plato
* Symposium by Plato
* The Republic by Plato
* The Economist by Xenophon
* The Memorabilia by Xenophon
* The Memorable Thoughts of Socrates by Xenophon
* The Symposium by Xenophon

Many thanks to <a href="https://www.gutenberg.org/">Project Gutenberg</a> for the source materials.
2024-12-17 22:19:08 -05:00
Daniel Miessler
1ce5bd4447 Trying an XML-based Markdown converter pattern. 2024-12-17 14:13:45 -08:00
Daniel Miessler
634cd3f484 Trying an XML-based Markdown converter pattern. 2024-12-17 14:08:54 -08:00
John
9b38c8d5aa Updates 2024-12-16 18:40:15 -05:00
Matt Joyce
8f4aab4f61 Fix: Issue with the custom message and added example config file. 2024-12-16 20:44:05 +11:00
github-actions[bot]
12284ad3db Update version to v1.4.122 and commit 2024-12-14 15:02:50 +00:00
Eugen Eisler
f180e8fc6b Merge pull request #1201 from mattjoyce/feature/config-yaml
feat: Add YAML configuration support
2024-12-14 20:31:42 +05:30
Matt Joyce
89153dd235 feat: Add YAML configuration support
Add support for persistent configuration via YAML files. Users can now specify
common options in a config file while maintaining the ability to override with
CLI flags. Currently supports core options like model, temperature, and pattern
settings.

- Add --config flag for specifying YAML config path
- Support standard option precedence (CLI > YAML > defaults)
- Add type-safe YAML parsing with reflection
- Add tests for YAML config functionality
2024-12-14 14:37:12 +11:00
github-actions[bot]
aa2881f3c2 Update version to v1.4.121 and commit 2024-12-13 21:17:35 +00:00
Eugen Eisler
82379ee6ec Merge pull request #1200 from mattjoyce/bugfix/1157-inputvars
Fix: Mask input token to prevent var substitution in patterns
2024-12-14 02:46:38 +05:30
Matt Joyce
e795055d13 Fix: Mask input token to prevent var substitution in patterns 2024-12-14 06:57:53 +11:00
Daniel Miessler
5b6d7e27b6 Added new instruction trick. 2024-12-11 13:54:33 -08:00
github-actions[bot]
c6dc13ef7f Update version to v1.4.120 and commit 2024-12-10 12:23:12 +00:00
Eugen Eisler
7e6a760623 Merge pull request #1189 from mattjoyce/bugfix/1157-inputvars
Add --input-has-vars flag to control variable substitution in input
2024-12-10 17:52:16 +05:30
Matt Joyce
01519d7486 Add --input-has-vars flag to control variable substitution in input
- Add InputHasVars field to ChatRequest struct
- Only process template variables in user input when flag is set
- Fixes issue with Ansible/Jekyll templates that use {{var}} syntax

This change makes template variable substitution in user input opt-in
via the --input-has-vars flag, preserving literal curly braces by
default.
2024-12-10 18:49:18 +11:00
John Connor
4c0ed0a5f0 Merge pull request #4 from johnconnor-sec/dependabot/npm_and_yarn/web/npm_and_yarn-06d0dd15d9
build(deps-dev): bump @sveltejs/kit from 2.8.4 to 2.9.0 in /web in the npm_and_yarn group across 1 directory
2024-12-07 22:04:00 -05:00
John Connor
0bc220949a Update +page.svelte 2024-12-07 19:30:15 -05:00
github-actions[bot]
5fb18077eb Update version to v..1 and commit 2024-12-08 00:15:18 +00:00
John Connor
fcf073febd Update version.nix to reflect upstream/main 2024-12-07 19:14:30 -05:00
github-actions[bot]
565fea97cf Update version to v..1 and commit 2024-12-08 00:13:55 +00:00
John Connor
daf1259556 Update version.go to reflect upstream/main 2024-12-07 19:12:50 -05:00
John
0eab786030 removed arcanum gif 2024-12-07 18:44:43 -05:00
github-actions[bot]
9dfb911d4a Update version to v..1 and commit 2024-12-07 23:32:02 +00:00
John
197f0e5c0d Merge branch 'danielmiessler-main' 2024-12-07 18:30:11 -05:00
John
aef4a1a5d4 merging 2024-12-07 18:24:17 -05:00
Eugen Eisler
f5f50cc4c9 Merge pull request #1182 from jessefmoore/main
analyze_risk pattern
2024-12-07 23:57:01 +01:00
Jesse Moore
9226e95d18 analyze_risk pattern
Created a pattern to analyze 3rd party vendor risk.
2024-12-07 11:48:00 -08:00
github-actions[bot]
2d8b46b878 Update version to v1.4.119 and commit 2024-12-07 11:24:51 +00:00
Eugen Eisler
fbd6083079 Merge pull request #1181 from mattjoyce/bugfix/1169-symlinks
Bugfix/1169 symlinks
2024-12-07 12:23:53 +01:00
Matt Joyce
0320e17652 Revert "Update version to v..1 and commit"
This reverts commit ec5ed689bb.
2024-12-07 19:14:20 +11:00
Matt Joyce
09fb913279 Fix #1169: Add robust handling for paths and symlinks in GetAbsolutePath 2024-12-07 19:04:39 +11:00
github-actions[bot]
ec5ed689bb Update version to v..1 and commit 2024-12-07 03:58:53 +00:00
Matt Joyce
373c1d0858 added test pattern 2024-12-05 22:28:38 +11:00
Matt Joyce
ca55f2375d actually added tutorial 2024-12-05 22:13:17 +11:00
Matt Joyce
d8671ea03a Added example files and tutorial 2024-12-05 22:09:47 +11:00
John
2579d4e87d Add cards component 2024-12-05 05:25:28 -05:00
John
f4885c5cdd Update: packages, main page, styles 2024-12-05 05:24:07 -05:00
Matt Joyce
c49f47ecab check extension names don't have spoaces 2024-12-05 20:39:40 +11:00
github-actions[bot]
43ca0dccf7 Update version to v1.4.118 and commit 2024-12-05 09:34:13 +00:00
Eugen Eisler
fcfcf55610 Merge pull request #1174 from mattjoyce/curly-brace-templates
Curly brace templates
2024-12-05 10:33:16 +01:00
Eugen Eisler
188235efc5 Merge pull request #1179 from sluosapher/main
added a new pattern create_newsletter_entry
2024-12-05 10:32:23 +01:00
dependabot[bot]
79b27253cd build(deps-dev): bump @sveltejs/kit
Bumps the npm_and_yarn group with 1 update in the /web directory: [@sveltejs/kit](https://github.com/sveltejs/kit/tree/HEAD/packages/kit).


Updates `@sveltejs/kit` from 2.8.4 to 2.9.0
- [Release notes](https://github.com/sveltejs/kit/releases)
- [Changelog](https://github.com/sveltejs/kit/blob/main/packages/kit/CHANGELOG.md)
- [Commits](https://github.com/sveltejs/kit/commits/@sveltejs/kit@2.9.0/packages/kit)

---
updated-dependencies:
- dependency-name: "@sveltejs/kit"
  dependency-type: direct:development
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-12-04 11:26:01 +00:00
github-actions[bot]
6deb4d69c0 Update version to v..1 and commit 2024-12-04 11:25:19 +00:00
John Connor
1b97a57cba Merge pull request #3 from danielmiessler/main
Update
2024-12-04 06:24:23 -05:00
John
0302e49ebd Merge remote-tracking branch 'refs/remotes/origin/main' 2024-12-04 06:19:02 -05:00
John
b9a5501f9d Style: Reordered columns. Improved responsive layout 2024-12-04 05:51:15 -05:00
John
faa83f9a49 Style: modified chat/+layout display. Update Header buttons 2024-12-04 05:41:53 -05:00
John
4888f8cb78 style: updates to ui components (components/ui) 2024-12-04 01:39:13 -05:00
Song Luo
fdd1d614b2 added a new pattern create_newsletter_entry 2024-12-03 20:05:25 -05:00
Matt Joyce
6fc75282e8 added tests for extension manager, registration and execution. 2024-12-03 23:28:47 +11:00
John
f33ebb7e25 Moved pattern loader to ModelConfig. Editing styles in chat/. Added page fly transitions. Tidying. Removed - ChatHeader, unused modal from Transcripts, FlyandScaleParams from lib/types/utils. 2024-12-03 02:04:39 -05:00
Matt Joyce
fc67dea243 fixed : if there is no stdin, then a nil message was passed to pattern.go resulting in segfault.
now we make user input ' ', before processing.
2024-12-03 13:33:45 +11:00
Matt Joyce
efd363d5fb Revert "Fix pattern file usage without stdin"
This reverts commit 744ec0824b.
2024-12-03 13:33:45 +11:00
Matt Joyce
a7d6de1661 Fix pattern file usage without stdin
When using pattern files with variables but no stdin input, ensure proper
template processing by initializing an empty message. This allows patterns
like:
  ./fabric -p pattern.txt -v=name:value

to work without requiring stdin input, while maintaining compatibility
with existing stdin usage:
  echo "input" | ./fabric -p pattern.txt -v=name:value

Changes:
- Add empty message initialization in BuildSession when Message is nil
- Remove redundant template processing of message content
- Let pattern processing handle all template resolution

This simplifies the template processing flow while supporting both
stdin and non-stdin use cases.
2024-12-03 13:33:40 +11:00
Matt Joyce
d17afc1fba Merge branch 'curly-brace-templates' into feature/template-extensions 2024-12-01 23:05:41 +11:00
Matt Joyce
da6f974887 fixed : if there is no stdin, then a nil message was passed to pattern.go resulting in segfault.
now we make user input ' ', before processing.
2024-12-01 22:52:32 +11:00
Matt Joyce
db2ba46099 Revert "Fix pattern file usage without stdin"
This reverts commit 744ec0824b.
2024-12-01 22:44:17 +11:00
Matt Joyce
744ec0824b Fix pattern file usage without stdin
When using pattern files with variables but no stdin input, ensure proper
template processing by initializing an empty message. This allows patterns
like:
  ./fabric -p pattern.txt -v=name:value

to work without requiring stdin input, while maintaining compatibility
with existing stdin usage:
  echo "input" | ./fabric -p pattern.txt -v=name:value

Changes:
- Add empty message initialization in BuildSession when Message is nil
- Remove redundant template processing of message content
- Let pattern processing handle all template resolution

This simplifies the template processing flow while supporting both
stdin and non-stdin use cases.
2024-12-01 22:29:59 +11:00
Matt Joyce
b31f094e9b Added better messages when adding and listing extensions
Fix issuse with listextension where it would fail if any hash had changed, now says hash failed.
2024-12-01 22:19:06 +11:00
Matt Joyce
43597e4168 Extension Registry Refinement
- Successfully implemented path-based registry storage
- Moved to storing paths instead of full configurations
- Implemented proper hash verification for both configs and executables
- Registry format now clean and minimal.

File-Based Output Implementation
- Successfully implemented file-based output handling
- Demonstrated clean interface requiring only path output
- Properly handles cleanup of temporary files
- Verified working with both local and remote operations
2024-12-01 18:04:11 +11:00
Matt Joyce
160703210b emplemented stdout template extensions 2024-12-01 09:13:22 +11:00
github-actions[bot]
c0ade48648 Update version to v1.4.117 and commit 2024-11-30 19:45:48 +00:00
Eugen Eisler
7fd4fa4742 fix: close #1173 2024-11-30 20:44:31 +01:00
github-actions[bot]
41b2e66c5c Update version to v1.4.116 and commit 2024-11-28 18:34:53 +00:00
Eugen Eisler
ed657383fb chore: cleanup style 2024-11-28 19:34:07 +01:00
github-actions[bot]
4d5d8d8b30 Update version to v1.4.115 and commit 2024-11-28 17:39:30 +00:00
Eugen Eisler
e9a75528ab chore: cleanup style 2024-11-28 18:36:01 +01:00
Eugen Eisler
c5ec4b548a fix: use the custom message and then piped one 2024-11-27 14:10:19 +01:00
Eugen Eisler
8e87529638 fix: use the custom message and then piped one 2024-11-27 14:10:18 +01:00
xssdoctor
ca33208fa1 Merge pull request #1168 from johnconnor-sec/main 2024-11-26 19:19:45 -05:00
John Connor
3f8bca8728 Update README.md 2024-11-26 19:15:18 -05:00
John Connor
ba56c33cf6 Update README.md 2024-11-26 19:12:29 -05:00
Jonathan Dunn
6ee4fdd366 updated readme 2024-11-26 17:53:58 -05:00
github-actions[bot]
30af189ae3 Update version to v1.4.114 and commit 2024-11-26 22:14:16 +00:00
Eugen Eisler
be998ff588 Merge pull request #1164 from MegaGrindStone/fix-nil-pointer-message
fix: provide default message content to avoid nil pointer dereference
2024-11-26 23:13:20 +01:00
github-actions[bot]
6bb3238e6d Update version to v1.4.113 and commit 2024-11-26 21:45:39 +00:00
Eugen Eisler
dfcd29593d Merge pull request #1166 from danielmiessler/dependabot/npm_and_yarn/web/npm_and_yarn-8ea39cdf54
build(deps-dev): bump @sveltejs/kit from 2.6.1 to 2.8.4 in /web in the npm_and_yarn group across 1 directory
2024-11-26 22:44:55 +01:00
dependabot[bot]
63b357168e build(deps-dev): bump @sveltejs/kit
Bumps the npm_and_yarn group with 1 update in the /web directory: [@sveltejs/kit](https://github.com/sveltejs/kit/tree/HEAD/packages/kit).


Updates `@sveltejs/kit` from 2.6.1 to 2.8.4
- [Release notes](https://github.com/sveltejs/kit/releases)
- [Changelog](https://github.com/sveltejs/kit/blob/main/packages/kit/CHANGELOG.md)
- [Commits](https://github.com/sveltejs/kit/commits/@sveltejs/kit@2.8.4/packages/kit)

---
updated-dependencies:
- dependency-name: "@sveltejs/kit"
  dependency-type: direct:development
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-26 21:40:49 +00:00
github-actions[bot]
317a4309f7 Update version to v1.4.112 and commit 2024-11-26 21:40:17 +00:00
Eugen Eisler
eceb10b725 Merge pull request #1165 from johnconnor-sec/main
feat: Fabric Web UI
2024-11-26 22:39:16 +01:00
MegaGrindStone
34f508fd82 fix: provide default message content to avoid nil pointer dereference 2024-11-27 02:32:07 +07:00
John Connor
9fa8634083 Update README.md 2024-11-26 09:13:04 -05:00
John Connor
a3ea63c1f9 Update Obsidian.md 2024-11-26 09:07:57 -05:00
John Connor
097b3eb0ba Update Obsidian.md 2024-11-26 09:07:30 -05:00
John
30f37ea633 john 2024-11-26 08:53:48 2024-11-26 08:54:12 -05:00
github-actions[bot]
23b495c8f7 Update version to v..1 and commit 2024-11-26 13:52:03 +00:00
John
e7f2d48437 john 2024-11-26 08:44:20 2024-11-26 08:50:31 -05:00
John
7043f78f1f john 2024-11-26 08:40:21 2024-11-26 08:50:31 -05:00
github-actions[bot]
f2cc718f49 Update version to v..1 and commit 2024-11-26 11:41:16 +00:00
github-actions[bot]
edb814c9f0 Update version to v1.4.111 and commit 2024-11-26 09:43:27 +00:00
Eugen Eisler
21de69b7d9 ci: Integrate code formating 2024-11-26 10:42:26 +01:00
github-actions[bot]
d4b5c3b8d5 Update version to v1.4.110 and commit 2024-11-26 08:52:27 +00:00
Eugen Eisler
afb5857699 Merge pull request #1135 from mrtnrdl/main
Add `extract_recipe`
2024-11-26 09:51:41 +01:00
github-actions[bot]
153b8217fd Update version to v..1 and commit 2024-11-25 19:04:07 +00:00
Martin Riedel
beeba6989a Merge branch 'main' into main 2024-11-25 20:02:52 +01:00
github-actions[bot]
666a1d32a3 Update version to v1.4.109 and commit 2024-11-24 15:31:52 +00:00
Eugen Eisler
4ed512b8d4 Merge pull request #1157 from mattjoyce/curly-brace-templates
fix: process template variables in raw input
2024-11-24 16:30:55 +01:00
Matt Joyce
af16494be1 fax: raw mode was doubling user input, because it's now already embeded in pattern
streamlined some context staging
2024-11-23 10:45:38 +11:00
Matt Joyce
9afa397c27 fix : template.go will handle missing var in stdin imput too.
echo 'Hello {{name}}' | ./fabric -v=noname:World
missing required variable: name
2024-11-23 08:34:58 +11:00
Matt Joyce
58f9d3c89c fix: process template variables in raw input
Process template variables ({{var}}) consistently in both pattern files
and raw input messages. Previously variables were only processed when
using pattern files.

- Add template variable processing for raw input in BuildSession
- Initialize messageContent explicitly
- Remove errantly committed build artifact (fabric binary in previous commit)
2024-11-23 08:27:56 +11:00
Daniel Miessler
7732b6fe55 Added analyze_mistakes. 2024-11-22 10:01:40 -08:00
github-actions[bot]
0d5f15edda Update version to v1.4.108 and commit 2024-11-21 21:57:24 +00:00
Eugen Eisler
4e2aa1b6d8 Merge pull request #1155 from mattjoyce/curly-brace-templates
Curly brace templates and plugins
2024-11-21 22:56:37 +01:00
Matt Joyce
b6eb969b3a feat(template): implement core plugin system and utility plugins
Add initial set of utility plugins for the template system:
- datetime: Date/time formatting and manipulation
- fetch: HTTP content retrieval and processing
- file: File system operations and content handling
- sys: System information and environment access
- text: String manipulation and formatting operations

Each plugin includes:
- Implementation with comprehensive test coverage
- Markdown documentation of capabilities
- Integration with template package

This builds on the template system to provide practical utility functions
while maintaining a focused scope for the initial plugin release.
2024-11-21 14:27:22 +11:00
github-actions[bot]
4c22965f4b Update version to v1.4.107 and commit 2024-11-19 22:02:03 +00:00
Eugen Eisler
7d28c95f48 ci: update patterns zip workflow 2024-11-19 23:01:05 +01:00
Eugen Eisler
94b713e3a5 ci: remove patterns zip workflow 2024-11-19 22:53:57 +01:00
Eugen Eisler
dccc92e8e0 Merge pull request #1149 from mathisto/patch-1
Fix typo in md_callout
2024-11-19 21:35:24 +01:00
Matt Kelly
590a9e452d Fix typo in md_callout
Just a small typo in this pattern. Thanks so much for this splendid tool.
2024-11-19 12:09:25 -05:00
github-actions[bot]
56322aaeb5 Update version to v1.4.106 and commit 2024-11-19 12:13:12 +00:00
Eugen Eisler
3684031f44 feat: migrate to official anthropics Go SDK 2024-11-19 13:12:10 +01:00
github-actions[bot]
005f2b7db5 Update version to v1.4.105 and commit 2024-11-19 08:55:31 +00:00
Eugen Eisler
67840605fc Merge pull request #1147 from mattjoyce/adhoc-pattern-feature
refactor: unify pattern loading and variable handling
2024-11-19 09:54:47 +01:00
Matt Joyce
d475e7b568 feat(template): introduce template package for variable substitution
- Add new template package to handle variable substitution with {{variable}} syntax
- Move substitution logic from patterns to centralized template system
- Update patterns.go to use template package for variable processing
- Support special {{input}} handling for pattern content
- Update chatter.go and rest API to pass input parameter
- Enable multiple passes to handle nested variables
- Report errors for missing required variables

This change sets up a foundation for future templating features like front matter
and plugin support while keeping the substitution logic centralized.
2024-11-19 16:57:14 +11:00
Matt Joyce
1f07ea25a2 refactor: unify pattern loading and variable handling
- Stronger separation of concerns between chatter.go and patterns.go
- Consolidate pattern loading logic into GetPattern method
- Support both file and database patterns through single interface
- Maintain API compatibility with Storage interface
- Handle variable substitution in one place
- Keep backward compatibility for REST API through Get method

The changes enable cleaner pattern handling while maintaining
existing interfaces and adding file-based pattern support.
2024-11-19 10:31:06 +11:00
Eugen Eisler
08f4e28342 Merge pull request #1146 from mrwadams/patch-1
Add summarize_meeting
2024-11-18 23:22:42 +01:00
github-actions[bot]
97666d9537 Update version to v1.4.104 and commit 2024-11-18 22:21:31 +00:00
Eugen Eisler
f7733f932b Merge pull request #1142 from mattjoyce/adhoc-pattern-feature
feat: add file-based pattern support
2024-11-18 23:20:34 +01:00
Matt Adams
20a039a8ab Add summarize_meeting
# What this Pull Request (PR) does

Add a new pattern to create a meeting summary from an audio transcript.

The pattern outputs the following sections (where relevant):
- Key Points
- Tasks
- Decisions
- Next Steps
2024-11-18 20:37:47 +00:00
github-actions[bot]
29856e4749 Update version to v1.4.103 and commit 2024-11-18 09:13:56 +00:00
Eugen Eisler
47a797e884 Merge pull request #1133 from igophper/fix_gin_logger
fix: fix default gin
2024-11-18 10:13:12 +01:00
Eugen Eisler
d4079aa543 Merge pull request #1129 from xyb/screenshoot
add a screenshot of fabric
2024-11-18 10:12:59 +01:00
github-actions[bot]
62eb837422 Update version to v1.4.102 and commit 2024-11-18 09:12:25 +00:00
Eugen Eisler
8d81f8d3aa Merge pull request #1143 from mariozig/patch-1
Update docker image
2024-11-18 10:11:39 +01:00
Mario Zigliotto
e8acf9ca07 Update docker image 2024-11-17 10:48:38 -08:00
Matt Joyce
af4752d324 feat: add file-based pattern support
Allow patterns to be loaded directly from files using explicit path prefixes
(~/, ./, /, or \). This enables easier testing and iteration of patterns
without requiring installation into the fabric config structure.

- Supports relative paths (./pattern.txt, ../pattern.txt)
- Supports home directory expansion (~/patterns/test.txt)
- Supports absolute paths
- Maintains backwards compatibility with named patterns
- Requires explicit path markers to distinguish from pattern names

Example usage:
  fabric --pattern ./draft-pattern.txt
  fabric --pattern ~/patterns/my-pattern.txt
  fabric --pattern ../../shared-patterns/test.txt
2024-11-17 14:39:49 +11:00
github-actions[bot]
fbd1fbfc67 Update version to v1.4.101 and commit 2024-11-15 16:04:16 +00:00
Eugen Eisler
d1fe826f14 improve logging for missing setup steps 2024-11-15 17:03:13 +01:00
martin riedel
b758a27b93 add extract_recipe to easily extract the necessary information from cooking-videos 2024-11-13 21:06:32 +01:00
江杭辉
2ae26dc2a6 fix: fix default gin 2024-11-13 18:02:57 +08:00
github-actions[bot]
81d765a34c Update version to v..1 and commit 2024-11-13 07:57:50 +00:00
Xie Yanbo
c396288ca7 add a screenshot of fabric 2024-11-13 11:37:01 +08:00
github-actions[bot]
125e7a341f Update version to v1.4.100 and commit 2024-11-13 02:19:32 +00:00
Daniel Miessler
064ab9ba85 Added our first formal stitch. 2024-11-12 18:18:44 -08:00
Daniel Miessler
f0ee8287a7 Upgraded AI result rater. 2024-11-10 22:53:14 -08:00
Daniel Miessler
47ccc33dfc Upgraded AI result rater. 2024-11-10 22:48:18 -08:00
Daniel Miessler
ceb735482a Upgraded AI result rater. 2024-11-10 22:46:10 -08:00
Daniel Miessler
473a20c0f6 Upgraded AI result rater. 2024-11-10 22:44:21 -08:00
Daniel Miessler
a337e81a81 Upgraded AI result rater. 2024-11-10 22:36:06 -08:00
Daniel Miessler
7d773b51d0 Upgraded AI result rater. 2024-11-10 22:28:26 -08:00
Daniel Miessler
bca10ddf7c Upgraded AI result rater. 2024-11-10 22:25:00 -08:00
Daniel Miessler
9756c575f3 Upgraded AI result rater. 2024-11-10 22:22:04 -08:00
Daniel Miessler
d02fb3e34d Upgraded AI result rater. 2024-11-10 22:17:37 -08:00
github-actions[bot]
988ff88a15 Update version to v1.4.99 and commit 2024-11-10 18:45:23 +00:00
Eugen Eisler
5de85c3da5 Merge pull request #1126 from jaredmontoya/fix-nix-package
flake: add gomod2nix auto-update
2024-11-10 19:43:55 +01:00
Daniel Miessler
5907f9dbac Upgraded AI result rater. 2024-11-09 22:14:31 -08:00
Daniel Miessler
1293e37525 Upgraded AI result rater. 2024-11-09 21:14:30 -08:00
Daniel Miessler
0a55e6c742 Upgraded AI result rater. 2024-11-09 18:41:18 -08:00
Daniel Miessler
ff3b18485f Upgraded AI result rater. 2024-11-09 18:39:25 -08:00
Daniel Miessler
2fec6e2e52 Upgraded AI result rater. 2024-11-09 18:37:18 -08:00
Daniel Miessler
9250f19d15 Upgraded AI result rater. 2024-11-09 18:30:09 -08:00
Daniel Miessler
1e7c5c3b6a Upgraded AI result rater. 2024-11-09 18:18:40 -08:00
jaredmontoya
0289b67a84 flake: add gomod2nix auto-update 2024-11-09 17:27:13 +01:00
github-actions[bot]
8934dbaa42 Update version to v1.4.98 and commit 2024-11-09 12:08:16 +00:00
Eugen Eisler
75c3d7ea6a ci: zip patterns 2024-11-09 13:07:52 +01:00
github-actions[bot]
a94ad620bc Update version to v1.4.97 and commit 2024-11-09 12:01:59 +00:00
Eugen Eisler
c6ca1a60d1 feat: update dependencies; improve vendors setup/default model 2024-11-09 13:01:44 +01:00
github-actions[bot]
4321c9d518 Update version to v1.4.96 and commit 2024-11-09 10:51:05 +00:00
Eugen Eisler
6cd86639ce feat: add claude-3-5-haiku-latest model 2024-11-09 11:50:48 +01:00
Daniel Miessler
3e6ad1029c Merge pull request #1060 from noamsiegel/Analyze-Candidates-Pattern
Analyze Candidates Pattern
2024-11-08 21:25:48 -08:00
github-actions[bot]
1cf967582d Update version to v1.4.95 and commit 2024-11-09 05:25:27 +00:00
Daniel Miessler
5e1b4e87e7 Merge pull request #1122 from Selemela07/patch-1
Create Selemela07 devcontainer.json
2024-11-08 21:25:11 -08:00
Daniel Miessler
76d6788231 Merge pull request #1123 from polyglotdev/correct-obsidian-shell-script
 Added unaliasing to pattern setup
2024-11-08 21:24:22 -08:00
Daniel Miessler
73a0e38af6 Merge branch 'main' of github.com:danielmiessler/fabric 2024-11-08 21:19:17 -08:00
Daniel Miessler
ff0ee4f111 Updated README. 2024-11-08 21:19:14 -08:00
Dom Hallan
de61e56fda Added unaliasing to pattern setup
In the process of setting up patterns, we've added a step to unalias any existing alias with the same name. This ensures that our dynamically defined functions won't conflict with any pre-existing aliases.
2024-11-08 11:11:25 -05:00
Selemela07
79b03c681a Create Selemela07 devcontainer.json
Edit, patch diff
2024-11-08 03:35:50 +02:00
Eugen Eisler
b8de34e539 Merge pull request #1119 from verebes1/add-dynamic-file-saving
Add auto save functionality
2024-11-07 13:13:35 +01:00
David
6377f951d8 Add auto save to aliases
-Updated the readme with information about autogenerating aliases that
allow autosaving to obsidian like tools
-Updated the table of contents
2024-11-07 09:15:48 +00:00
github-actions[bot]
86b702bf46 Update version to v1.4.94 and commit 2024-11-06 22:28:45 +00:00
Eugen Eisler
232847b218 Merge pull request #1108 from butterflyx/fix/yt-shorts
[add] RegEx for YT shorts
2024-11-06 23:28:29 +01:00
Eugen Eisler
44dae97784 Merge pull request #1117 from verebes1/add-aliases-for-patterns
Add alias generation information
2024-11-06 23:28:06 +01:00
Eugen Eisler
d8e3860e49 Merge pull request #1115 from ignacio-arce/main
Added create_diy
2024-11-06 23:24:44 +01:00
Eugen Eisler
e01a84b21d Merge branch 'main' into fix/yt-shorts 2024-11-06 23:22:52 +01:00
David
97c5341bc1 Merge branch 'main' into add-aliases-for-patterns 2024-11-06 22:18:29 +00:00
github-actions[bot]
de30df446d Update version to v1.4.93 and commit 2024-11-06 20:54:53 +00:00
Eugen Eisler
b5b45c8474 fix: short YouTube url patter 2024-11-06 21:54:36 +01:00
David
c5483276e5 Add alias generation information
-Updated the readme with information about generating aliases for each
prompt including on for youtube transcripts
-Updated the table of contents
2024-11-06 15:15:14 +00:00
Ignacio Arce
263b1cb187 Added create_diy 2024-11-06 07:58:24 -03:00
butterflyx
203add15e5 [add] VideoID for YT shorts 2024-11-05 19:55:45 +01:00
github-actions[bot]
b98316a705 Update version to v1.4.92 and commit 2024-11-05 12:50:54 +00:00
Eugen Eisler
f2d9e0e8ea Merge pull request #1109 from leonsgithub/main
Add docker
2024-11-05 13:50:37 +01:00
github-actions[bot]
f5abaac8b7 Update version to v1.4.91 and commit 2024-11-05 10:25:55 +00:00
Eugen Eisler
0bb4f58222 fix: bufio.Scanner message too long 2024-11-05 11:25:32 +01:00
leon
4453afba89 Add docker 2024-11-04 18:56:55 +01:00
github-actions[bot]
96c8117135 Update version to v1.4.90 and commit 2024-11-04 12:44:39 +00:00
Eugen Eisler
1830ae2321 feat: impl. Youtube PlayList support 2024-11-04 13:44:20 +01:00
Eugen Eisler
7af94a9d2a fix: close #1103, Update Readme hpt to install to_pdf 2024-11-04 10:54:26 +01:00
github-actions[bot]
6d10c26c5d Update version to v1.4.89 and commit 2024-11-04 09:48:39 +00:00
Eugen Eisler
681f1a49a5 fix: close #1106, fix pipe reading 2024-11-04 10:48:22 +01:00
Eugen Eisler
b750171593 feat: YouTube PlayList support 2024-11-04 10:48:22 +01:00
Eugen Eisler
02a019632b Merge pull request #1102 from jholsgrove/main
Create user story pattern
2024-10-31 19:02:19 +01:00
Justin Holsgrove
385d381cf1 create user story pattern 2024-10-31 13:19:12 +00:00
github-actions[bot]
48e8d76f21 Update version to v1.4.88 and commit 2024-10-30 19:58:26 +00:00
Eugen Eisler
d5336b2796 Merge pull request #1098 from jaredmontoya/fix-nix-package-update-ci
Fix nix package update workflow
2024-10-30 20:58:12 +01:00
jaredmontoya
cb1b2bf5ca fix nix package version auto update workflow 2024-10-30 20:51:25 +01:00
github-actions[bot]
6c38cd360b Update version to v1.4.87 and commit 2024-10-30 19:06:21 +00:00
Eugen Eisler
4c2ca22cb2 Merge pull request #1096 from jaredmontoya/implement-ci-nix-package-update
Implement automated ci nix package version update
2024-10-30 20:06:03 +01:00
jaredmontoya
cd177ff476 automate nix package version update 2024-10-30 18:33:46 +01:00
jaredmontoya
1ea3b4b3c5 modularize nix flake 2024-10-30 18:30:16 +01:00
github-actions[bot]
8df3a9227f Update version to v1.4.86 and commit 2024-10-30 15:59:31 +00:00
Eugen Eisler
583695c228 Merge pull request #1088 from jaredmontoya/fix-ollama-context-length
feat: add DEFAULT_CONTEXT_LENGTH setting
2024-10-30 16:59:13 +01:00
jaredmontoya
455215290f add model context length setting 2024-10-30 15:36:01 +01:00
github-actions[bot]
5373345a3c Update version to v1.4.85 and commit 2024-10-30 12:51:09 +00:00
Eugen Eisler
e17b96d864 feat: write tools output also to output file if defined; fix XouTube transcript &#39; character 2024-10-30 13:50:52 +01:00
github-actions[bot]
3ec4d274c4 Update version to v1.4.84 and commit 2024-10-30 12:07:37 +00:00
Eugen Eisler
611f8789da ci: deactivate build triggering at changes of patterns or docu 2024-10-30 13:07:23 +01:00
github-actions[bot]
8e01d62150 Update version to v1.4.83 and commit 2024-10-30 10:38:02 +00:00
Eugen Eisler
f55662300a Merge pull request #1089 from jaredmontoya/add-nix-flake
Introduce Nix to the project
2024-10-30 11:37:46 +01:00
github-actions[bot]
8de6ec27b8 Update version to v1.4.82 and commit 2024-10-30 07:56:49 +00:00
Eugen Eisler
2b8b626f69 Merge pull request #1094 from joshmedeski/md-callout
feat: add md_callout pattern
2024-10-30 08:56:36 +01:00
github-actions[bot]
d81fdb0f9c Update version to v1.4.81 and commit 2024-10-29 22:39:03 +00:00
Eugen Eisler
38406ee586 feat: split tools messages from use message 2024-10-29 23:37:38 +01:00
github-actions[bot]
f2fdd6e6d3 Update version to v1.4.80 and commit 2024-10-29 21:12:27 +00:00
Eugen Eisler
ee3668006d feat: impl. multi-model / attachments, images 2024-10-29 22:12:06 +01:00
github-actions[bot]
7b4265470a Update version to v1.4.79 and commit 2024-10-29 21:04:44 +00:00
Eugen Eisler
9c9897706b feat: impl. multi-model / attachments, images 2024-10-29 22:03:47 +01:00
Eugen Eisler
9e8ad44cdf feat: impl. multi-model / attachments, images 2024-10-29 22:01:24 +01:00
Eugen Eisler
a6d82e0fc3 feat: impl. multi-model / attachments, images 2024-10-29 21:54:16 +01:00
Eugen Eisler
62ae3de488 feat: impl. multi-model / attachments, images 2024-10-29 21:45:59 +01:00
Eugen Eisler
dff094301a feat: impl. multi-model / attachments, images 2024-10-29 21:31:02 +01:00
Eugen Eisler
69aefc16f6 feat: impl. multi-model / attachments, images 2024-10-29 20:38:15 +01:00
Eugen Eisler
0a2ae30034 feat: impl. multi-model / attachments, images 2024-10-29 20:32:18 +01:00
Josh Medeski
8b5be309fe feat: add md_callout pattern
Add a pattern that can convert text into an appropriate markdown callout
2024-10-29 09:50:14 -05:00
github-actions[bot]
e16eec8680 Update version to v1.4.78 and commit 2024-10-28 22:36:36 +00:00
Eugen Eisler
60f4606c9d Merge pull request #1059 from noamsiegel/Analyze-Proposition-Pattern
Analyze Proposition Pattern
2024-10-28 23:36:23 +01:00
github-actions[bot]
1fe4b7ae2a Update version to v1.4.77 and commit 2024-10-28 22:35:34 +00:00
Eugen Eisler
00b2f90c65 Merge pull request #1073 from mattjoyce/main
Five patterns to explore a project, opportunity or brief.
2024-10-28 23:35:20 +01:00
jaredmontoya
c67fe04d3c add Nix Flake 2024-10-28 14:07:41 +01:00
github-actions[bot]
daa57388e7 Update version to v1.4.76 and commit 2024-10-28 11:25:47 +00:00
Eugen Eisler
758a8c0540 chore: simplify isChatRequest 2024-10-28 12:25:32 +01:00
github-actions[bot]
6c1ecf4b4b Update version to v1.4.75 and commit 2024-10-28 11:17:55 +00:00
Eugen Eisler
ac6ae9439f Merge pull request #1090 from wrochow/main
A couple of patterns.
2024-10-28 12:17:40 +01:00
jaredmontoya
9b4db98ed9 add trailing newline 2024-10-28 11:42:03 +01:00
Waldo Rochow
47d2b438aa Ask uncle Duke
Duke is an expert in software development using the Java programing language, especially with the Spring Framework and Maven.
2024-10-27 13:18:26 -04:00
Waldo Rochow
f8841b606e Dialog with Socrates
Have a conversation with a modern day philosopher who desires to engage in deep, meaningful conversations.
2024-10-27 13:17:15 -04:00
github-actions[bot]
05e8e99c89 Update version to v1.4.74 and commit 2024-10-27 15:33:16 +00:00
Eugen Eisler
b4e439e817 Merge pull request #1077 from xvnpw/feature/refine_design_document
feat: add pattern refine_design_document
2024-10-27 16:32:59 +01:00
github-actions[bot]
e4fd7b23fd Update version to v1.4.73 and commit 2024-10-27 15:03:41 +00:00
Eugen Eisler
2eb96fa4df Merge pull request #1086 from NuCl34R/main
Create a basic translator pattern, edit file to add desired language
2024-10-27 16:03:28 +01:00
Matt Joyce
62bc783d14 Merge branch 'main' of https://github.com/mattjoyce/fabric into main 2024-10-27 21:54:11 +11:00
Matt Joyce
721f6515ed added metadata and styleguide 2024-10-27 21:53:48 +11:00
Matt Joyce
022011fb0d Merge branch 'danielmiessler:main' into main 2024-10-27 21:30:58 +11:00
Matt Joyce
1837ca3715 added structure to prompt 2024-10-27 21:28:35 +11:00
Matt Joyce
ef6e49a6c9 added headwinds and tailwinds 2024-10-27 20:19:28 +11:00
Matt Joyce
703cd07210 initial draft of s7 Strategy profiling 2024-10-27 18:02:04 +11:00
NuCl34R
5c8b59fa2b Create system.md 2024-10-26 21:05:59 -04:00
github-actions[bot]
da5ccea93e Update version to v1.4.72 and commit 2024-10-25 21:12:31 +00:00
Eugen Eisler
3a1bf7314c Merge pull request #1070 from xvnpw/feature/create_design_document
feat: create create_design_document pattern
2024-10-25 23:12:17 +02:00
github-actions[bot]
9abb410271 Update version to v1.4.71 and commit 2024-10-25 21:11:59 +00:00
Eugen Eisler
865820ece8 Merge pull request #1072 from xvnpw/feature/review_design
feat: add review_design pattern
2024-10-25 23:11:45 +02:00
github-actions[bot]
b7e47d510c Update version to v1.4.70 and commit 2024-10-25 20:57:24 +00:00
Eugen Eisler
61e72eb7fe Merge pull request #1064 from rprouse/issue/1063
Update README.md with pbpaste section
2024-10-25 22:57:10 +02:00
xvnpw
23ff16a039 feat: add pattern refine_design_document 2024-10-24 21:11:50 +02:00
Matt Joyce
3c2280bc42 Added identify_job_stories 2024-10-24 09:01:46 +11:00
xvnpw
90dbab6376 feat: add review_design pattern 2024-10-23 19:13:50 +02:00
xvnpw
819021b7ba feat: create create_design_document pattern 2024-10-23 15:07:56 +02:00
Rob Prouse
ef3c043f77 Update README.md with pbpaste section 2024-10-22 17:02:19 -04:00
Noam Siegel
7139ad013d Added system and user prompts 2024-10-21 12:17:58 -07:00
Noam Siegel
151c58d0ef Added system and user prompts 2024-10-21 12:14:35 -07:00
github-actions[bot]
d65375da7b Update version to v1.4.69 and commit 2024-10-21 15:05:45 +00:00
Daniel Miessler
21186097e4 Updated the Alma.md file. 2024-10-21 17:05:19 +02:00
github-actions[bot]
a97302d791 Update version to v1.4.68 and commit 2024-10-21 14:22:48 +00:00
Eugen Eisler
aaddc95ec0 fix: setup does not overwrites old values 2024-10-21 16:22:08 +02:00
github-actions[bot]
1b7a1fa652 Update version to v1.4.67 and commit 2024-10-19 11:10:23 +00:00
Eugen Eisler
8a3d63ef48 Merge remote-tracking branch 'origin/main' 2024-10-19 13:10:09 +02:00
Eugen Eisler
609df943dd feat: plugins arch., new setup procedure 2024-10-19 13:09:58 +02:00
github-actions[bot]
8941551f5a Update version to v1.4.66 and commit 2024-10-19 11:09:55 +00:00
Eugen Eisler
61f66f88e3 feat: plugins arch., new setup procedure 2024-10-19 13:09:37 +02:00
github-actions[bot]
15de33107b Update version to v1.4.65 and commit 2024-10-16 13:27:28 +00:00
Eugen Eisler
81f9b1dabb Merge pull request #1045 from Fenicio/patch-1
Update patterns/analyze_answers/system.md - Fixed a bunch of typos
2024-10-16 16:27:14 +03:00
Guillermo G C
888342c119 Update patterns/analyze_answers/system.md - Fixed a bunch of typos 2024-10-15 08:53:26 +02:00
github-actions[bot]
12d83dad6d Update version to v1.4.64 and commit 2024-10-14 18:17:37 +00:00
Jonathan Dunn
14ef9fd41c updated readme 2024-10-14 14:17:19 -04:00
github-actions[bot]
584e0c8547 Update version to v1.4.63 and commit 2024-10-13 14:42:39 +00:00
Daniel Miessler
914b312c2e Merge pull request #862 from Thepathakarpit/patch-1
Create setup_fabric.bat, a batch script to automate setup and running…
2024-10-13 07:42:27 -07:00
github-actions[bot]
8153d690cc Update version to v1.4.62 and commit 2024-10-13 14:40:48 +00:00
Daniel Miessler
d03bdbeb9b Merge pull request #1044 from danielmiessler/feat/rest-api
Feat/rest api
2024-10-13 07:40:32 -07:00
github-actions[bot]
87730043b5 Update version to v1.4.61 and commit 2024-10-13 02:50:02 +00:00
Daniel Miessler
3285b8e330 Updated extract sponsors. 2024-10-12 19:49:44 -07:00
Eugen Eisler
686d039392 Merge branch 'main' into feat/rest-api 2024-10-12 23:06:29 +03:00
Eugen Eisler
d7683e4c39 feat: restructure for better reuse 2024-10-12 22:49:26 +03:00
Eugen Eisler
56f995afb4 feat: restructure for better reuse 2024-10-12 22:37:35 +03:00
Eugen Eisler
17bde814cc feat: restructure for better reuse 2024-10-12 22:25:17 +03:00
github-actions[bot]
525f972d22 Update version to v1.4.60 and commit 2024-10-12 15:27:28 +00:00
Eugen Eisler
161ce65ae6 fix: IsChatRequest rule; Close #1042 is 2024-10-12 18:27:04 +03:00
github-actions[bot]
72f1429db9 Update version to v1.4.59 and commit 2024-10-11 22:59:41 +00:00
Daniel Miessler
b5fe3f2ad8 Added ctw to Raycast. 2024-10-11 15:59:26 -07:00
github-actions[bot]
2155ff9fc0 Update version to v1.4.58 and commit 2024-10-11 20:30:50 +00:00
Eugen Eisler
d33175e5b6 chore: we don't need tp configure DryRun vendor 2024-10-11 23:28:56 +03:00
Eugen Eisler
6dbd24e541 fix: Close #1040. Configure vendors separately that were not configured yet 2024-10-11 23:25:33 +03:00
github-actions[bot]
d1c527c421 Update version to v1.4.57 and commit 2024-10-11 19:27:41 +00:00
Eugen Eisler
c0bd61ba49 docs: Close #1035, provide better example for pattern variables 2024-10-11 22:27:20 +03:00
github-actions[bot]
8f0cc85742 Update version to v1.4.56 and commit 2024-10-11 18:54:25 +00:00
Eugen Eisler
7275dfbd6b Merge pull request #1039 from hallelujah-shih/feature/set-default-lang
Feature/set default lang
2024-10-11 20:54:10 +02:00
Matt Joyce
9f29642635 updated all dsrp prompts to increase divergenct thinking. 2024-10-10 22:53:44 +11:00
hallelujah-shih
9f94cfb718 fmt 2024-10-10 19:45:39 +08:00
hallelujah-shih
e1fa674a3f support set default output language
# Conflicts:
#	cli/cli.go
#	core/fabric.go
2024-10-10 19:37:51 +08:00
Matt Joyce
dd063f42bb Fixed mix up with system 2024-10-10 21:06:53 +11:00
Matt Joyce
ef4e7aa89a Initial dsrp prompts 2024-10-09 23:09:47 +11:00
github-actions[bot]
34f804be3a Update version to v1.4.55 and commit 2024-10-09 09:29:17 +00:00
Eugen Eisler
83cd8a1912 fix: Close #1036 2024-10-09 12:29:02 +03:00
github-actions[bot]
d347ef0dcc Update version to v1.4.54 and commit 2024-10-07 16:44:19 +00:00
Eugen Eisler
44cc9bbcac Merge pull request #1021 from joshuafuller/main
Corrected spelling and grammatical errors for consistency and clarity for transcribe_minutes
2024-10-07 18:44:06 +02:00
github-actions[bot]
4aa0b99c74 Update version to v1.4.53 and commit 2024-10-07 09:17:11 +00:00
Eugen Eisler
d90e8081ac fix: fix NP if response is empty, close #1026, #1027 2024-10-07 11:16:57 +02:00
github-actions[bot]
70d43c5252 Update version to v1.4.52 and commit 2024-10-06 19:50:30 +00:00
Daniel Miessler
fd8216f1bd Merge branch 'main' of github.com:danielmiessler/fabric 2024-10-06 12:50:12 -07:00
Daniel Miessler
ae0c9009d9 Added extract_core_message. 2024-10-06 12:50:05 -07:00
Eugen Eisler
4104317b34 feat: work on Rest API 2024-10-06 16:07:32 +02:00
Eugen Eisler
401f0da689 feat: work on Rest API 2024-10-06 16:06:05 +02:00
Eugen Eisler
6efe7960cd feat: work on Rest API 2024-10-06 15:43:18 +02:00
Eugen Eisler
a6d63f4d0e feat: work on Rest API 2024-10-06 15:40:29 +02:00
Eugen Eisler
8f3928f4b2 feat: work on Rest API 2024-10-06 15:31:06 +02:00
Eugen Eisler
3380972df1 feat: work on Rest API 2024-10-06 15:29:01 +02:00
Joshua Fuller
bad01040e3 Corrected spelling and grammatical errors for consistency and clarity
Description:

Changed "agreed within the meeting" to "agreed upon within the meeting" to improve grammatical accuracy.

Added missing periods to ensure consistency across list items.

Corrected the spelling of "highliting" to "highlighting."

Fixed the spelling of "exxactly" to "exactly."

Updated phrasing in "Write NEXT STEPS a 2-3 sentences" to "Write NEXT STEPS as 2-3 sentences" for grammatical correctness.

These changes improve the readability and consistency of the document, ensuring all instructions are clear and error-free.
2024-10-05 17:29:12 -05:00
github-actions[bot]
0b26b930f9 Update version to v1.4.51 and commit 2024-10-05 16:48:46 +00:00
Eugen Eisler
5dbaf4f28f fix: tests 2024-10-05 18:48:22 +02:00
github-actions[bot]
1d9cce5adf Update version to v1.4.50 and commit 2024-10-05 16:44:19 +00:00
Eugen Eisler
76622105e2 fix: windows release 2024-10-05 18:43:54 +02:00
github-actions[bot]
e6e3e34f53 Update version to v1.4.49 and commit 2024-10-05 16:42:19 +00:00
Eugen Eisler
7192ddbaa6 fix: windows release 2024-10-05 18:41:58 +02:00
github-actions[bot]
b5206d1923 Update version to v1.4.48 and commit 2024-10-05 15:54:01 +00:00
Eugen Eisler
81d60b4292 feat: Add 'meta' role to store meta info to session, like source of input content. 2024-10-05 17:53:48 +02:00
github-actions[bot]
ca6660585d Update version to v1.4.47 and commit 2024-10-05 15:43:21 +00:00
Eugen Eisler
d70e7c570d feat: Add 'meta' role to store meta info to session, like source of input content. 2024-10-05 17:42:57 +02:00
Eugen Eisler
4fb965ec9d feat: Add 'meta' role to store meta info to session, like source of input content. 2024-10-05 17:33:27 +02:00
Arpit Pathak
5ad9943462 Merge branch 'main' into patch-1 2024-09-13 23:19:19 +05:30
Arpit Pathak
cf0b9d2c3d Create setup_fabric.bat, a batch script to automate setup and running fabric on windows. 2024-08-22 09:02:30 +05:30
534 changed files with 52341 additions and 4752 deletions

View File

@@ -0,0 +1,5 @@
{
"image": "mcr.microsoft.com/devcontainers/universal:2",
"features": {
}
}

6
.dockerignore Normal file
View File

@@ -0,0 +1,6 @@
.git
.gitignore
.env
README.md
docker-compose.yml
Dockerfile

2
.envrc Normal file
View File

@@ -0,0 +1,2 @@
watch_file nix/shell.nix
use flake

View File

@@ -34,4 +34,4 @@ body:
id: screens
attributes:
label: Relevant screenshots (optional)
description: Please upload any screenshots that may help us reproduce and/or understand the issue.
description: Please upload any screenshots that may help us reproduce and/or understand the issue.

View File

@@ -3,8 +3,14 @@ name: Go Build
on:
push:
branches: ["main"]
paths-ignore:
- 'patterns/**'
- '**/*.md'
pull_request:
branches: ["main"]
paths-ignore:
- 'patterns/**'
- '**/*.md'
jobs:
test:
@@ -16,6 +22,9 @@ jobs:
- name: Checkout code
uses: actions/checkout@v4
- name: Install Nix
uses: DeterminateSystems/nix-installer-action@main
- name: Set up Go
uses: actions/setup-go@v4
with:
@@ -23,3 +32,6 @@ jobs:
- name: Run tests
run: go test -v ./...
- name: Check Formatting
run: nix flake check

33
.github/workflows/patterns.yaml vendored Normal file
View File

@@ -0,0 +1,33 @@
name: Patterns Artifact
on:
push:
paths:
- "patterns/**" # Trigger only on changes to files in the patterns folder
jobs:
zip-and-upload:
name: Zip and Upload Patterns Folder
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Verify Changes in Patterns Folder
run: |
git fetch origin
if git diff --quiet HEAD~1 -- patterns; then
echo "No changes detected in patterns folder."
exit 1
fi
- name: Zip the Patterns Folder
run: zip -r patterns.zip patterns/
- name: Upload Patterns Artifact
uses: actions/upload-artifact@v4
with:
name: patterns
path: patterns.zip

View File

@@ -2,7 +2,7 @@ name: Go Release
on:
repository_dispatch:
types: [ tag_created ]
types: [tag_created]
push:
tags:
- "v*"
@@ -81,29 +81,42 @@ jobs:
- name: Upload build artifact
if: matrix.os != 'windows-latest'
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: fabric-${OS}-${{ matrix.arch }}
path: fabric-${OS}-${{ matrix.arch }}
- name: Upload build artifact
if: matrix.os == 'windows-latest'
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: fabric-windows-${{ matrix.arch }}.exe
path: fabric-windows-${{ matrix.arch }}.exe
- name: Get latest tag
if: matrix.os != 'windows-latest'
id: get_latest_tag
run: |
latest_tag=$(git tag --sort=-creatordate | head -n 1)
echo "latest_tag=$latest_tag" >> $GITHUB_ENV
- name: Get latest tag
if: matrix.os == 'windows-latest'
id: get_latest_tag_windows
run: |
$latest_tag = git tag --sort=-creatordate | Select-Object -First 1
Add-Content -Path $env:GITHUB_ENV -Value "latest_tag=$latest_tag"
- name: Create release if it doesn't exist
shell: bash
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release view ${{ env.latest_tag }} || gh release create ${{ env.latest_tag }} --title "Release ${{ env.latest_tag }}" --notes "Automated release for ${{ env.latest_tag }}"
if ! gh release view ${{ env.latest_tag }} >/dev/null 2>&1; then
gh release create ${{ env.latest_tag }} --title "Release ${{ env.latest_tag }}" --notes "Automated release for ${{ env.latest_tag }}"
else
echo "Release ${{ env.latest_tag }} already exists."
fi
- name: Upload release artifact
if: matrix.os == 'windows-latest'

View File

@@ -4,12 +4,20 @@ on:
push:
branches:
- main # Monitor the main branch
paths-ignore:
- 'patterns/**'
- '**/*.md'
permissions:
contents: write # Ensure the workflow has write permissions
concurrency:
group: version-update
cancel-in-progress: false
jobs:
update-version:
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
@@ -18,11 +26,19 @@ jobs:
with:
fetch-depth: 0
- name: Install Nix
uses: DeterminateSystems/nix-installer-action@main
- name: Set up Git
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
- name: Pull latest main and tags
run: |
git pull --rebase origin main
git fetch --tags
- name: Get the latest tag
id: get_latest_tag
run: |
@@ -38,7 +54,10 @@ jobs:
minor=$(echo "$latest_tag" | cut -d. -f2)
patch=$(echo "$latest_tag" | cut -d. -f3)
new_patch=$((patch + 1))
new_tag="v${major}.${minor}.${new_patch}"
new_version="${major}.${minor}.${new_patch}"
new_tag="v${new_version}"
echo "New version is: $new_version"
echo "new_version=$new_version" >> $GITHUB_ENV # Save the new version to environment file
echo "New tag is: $new_tag"
echo "new_tag=$new_tag" >> $GITHUB_ENV # Save the new tag to environment file
@@ -48,9 +67,24 @@ jobs:
echo "" >> version.go
echo "var version = \"${{ env.new_tag }}\"" >> version.go
- name: Update version.nix file
run: |
echo "\"${{ env.new_version }}\"" > nix/pkgs/fabric/version.nix
- name: Format source code
run: |
nix fmt
- name: Update gomod2nix.toml file
run: |
nix run .#gomod2nix -- --outdir nix/pkgs/fabric
- name: Commit changes
run: |
git add version.go
git add nix/pkgs/fabric/version.nix
git add nix/pkgs/fabric/gomod2nix.toml
git add .
if ! git diff --staged --quiet; then
git commit -m "Update version to ${{ env.new_tag }} and commit $commit_hash"
else

193
.gitignore vendored
View File

@@ -1,3 +1,7 @@
# Nix
.direnv
result
# macOS local stores
.DS_Store
@@ -18,7 +22,7 @@ dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
@@ -54,6 +58,7 @@ coverage.xml
.hypothesis/
.pytest_cache/
cover/
coverage.out
# Translations
*.mo
@@ -161,4 +166,188 @@ cython_debug/
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
#.idea/
patterns/dialog_with_socrates/Apology by Plato.txt
patterns/dialog_with_socrates/Phaedrus by Plato.txt
patterns/dialog_with_socrates/Symposium by Plato.txt
patterns/dialog_with_socrates/The Economist by Xenophon.txt
patterns/dialog_with_socrates/The Memorabilia by Xenophon.txt
patterns/dialog_with_socrates/The Memorable Thoughts of Socrates by Xenophon.txt
patterns/dialog_with_socrates/The Republic by Plato.txt
patterns/dialog_with_socrates/The Symposium by Xenophon.txt
web/node_modules
# Output
web/.output
web/.vercel
web/.svelte-kit
web/build
# OS
web/.DS_Store
web/Thumbs.db
# Env
web/.env
web/.env.*
web/!.env.example
web/!.env.test
# Vite
web/vite.config.js.timestamp-*
web/vite.config.ts.timestamp-*
# Created by https://www.toptal.com/developers/gitignore/api/node
# Edit at https://www.toptal.com/developers/gitignore?templates=node
### Node ###
# Logs
web/logs
web/*.log
web/npm-debug.log*
web/yarn-debug.log*
web/yarn-error.log*
web/lerna-debug.log*
web/.pnpm-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
web/report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
web/pids
web/*.pid
web/*.seed
web/*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
web/lib-cov
# Coverage directory used by tools like istanbul
web/coverage
web/*.lcov
# nyc test coverage
web/.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
web/.grunt
# Bower dependency directory (https://bower.io/)
web/bower_components
# node-waf configuration
web/.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
web/node_modules/
jspm_packages/
# Snowpack dependency directory (https://snowpack.dev/)
web/web_modules/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
web/.npm
# Optional eslint cache
web/.eslintcache
# Optional stylelint cache
web/.stylelintcache
# Microbundle cache
web/.rpt2_cache/
web/.rts2_cache_cjs/
web/.rts2_cache_es/
web/.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variable files
web/.env
web/.env.development.local
web/.env.test.local
web/.env.production.local
web/.env.local
# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache
# Next.js build output
web/.next
web/out
# Nuxt.js build / generate output
web/.nuxt
web/dist
# Gatsby files
web/.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
web/.vuepress/dist
# vuepress v2.x temp and cache directory
web/.temp
# Docusaurus cache and generated files
.docusaurus
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for testing VSCode extensions
web/.vscode-test
# yarn v2
web/.yarn/cache
web/.yarn/unplugged
web/.yarn/build-state.yml
web/.yarn/install-state.gz
web/.pnp.*
### Node Patch ###
# Serverless Webpack directories
web/.webpack/
# Optional stylelint cache
# SvelteKit build / generate output
web/.svelte-kit
# End of https://www.toptal.com/developers/gitignore/api/node
web/myfiles/Obsidian_perso_not_share/
ENV
web/package-lock.json
.gitignore_backup
web/static/*.png
# Local VSCode project settings
.vscode/

200
Alma.md
View File

@@ -1,200 +0,0 @@
## Document Purpose
This document captures the SPQA policy and State for Alma Security, a security startup out of Redwood City, Ca.
This is part of the SPQA context that will be used to answer questions and create artifacts for the company, e.g., company strategy, security strategy, quarterly security reports (QSRs), project plans, recommendations on which projects to undertake, which investments to take and avoid, and other such decisions.
A major aspect of the SPQA system is the definition of the company's mission, goals, KPIs, and challenges. These shape everything within the company and thus should be used to shape the recommendations made when asked.
In addition to the clearly stated goals and other defining characteristics listed above, there will also be a streaming list of updates coming into this system using the Activity document.
Those will be changes, updates, or modifications to the direction of the company. For example, if Goal number 4 is to build a new datacenter in Boise, Idaho, but we see an update in the Activity section that says we've lost the ability to build in Boise, we should consider goal #4 out of the picture for prioritization and other decision purposes. In other words, the streaming activity log into this document should be considered updates to the core content.
## Company History
Alma Security was started by Chris Meyers, who was previously at Sigma Systems as CTO and HPE as a senior security engineer.
He started the company becuase, "I saw a gap in the authentication market, where companies were only looking at one or two aspects of one's identity to do authentication. They we're looking at the whole picture and turning that into a continuous authentication story."
## Company Mission
The mission of Alma Security is to ensure businesses can continuously authenticate their users using their whole selves.
## Company Goals (G1 means goal 1, G2 is goal 2, etc. Treat each item (goal/kpi/etc) as half as important as the one before it.)
NOTE: Some goals are things like project rollouts which serve the higher goals. In that case they shouldn't always be considered so much lower priority because one is serving the other.
## Company Goals
- G1: Achieve 20% market share by January 2025
- G2: Hit 10000 active customers by January 2025
- G3: Hit a customer trust score of 90+% by January 2025
- G4: Get churn below 5% by August 2024
- G5: Launch in Europe by August 2024
- G6: Launch in India by November 2024
- G7: Launch Mood-monitor integration by February 2024
- G8: Launch partnership with Apple Passkeys by June 2024
## Company KPIs
- K1: Current marketshare percentage
- K2: Number of active customers
- K3: Current churn percentage
- K4: Launched_in_Europe (yes/no)
- K4: Launched_in_India (yes/no)
-----------------------------------------------------------------------------------------------------------------------
## Security Team Mission
- SM1: Protect Alma Security's customers and intellectual property from security and privacy incidents.
## Security Team Goals
- SG1: Secure all customer data -- especially biometric -- from security and privacy incidents.
- SG2: Protect Alma Security's intellectual property from being captured by unathorized parties.
- SG3: Reach a time to detect malicious behavior of less than 4 minutes by January 2025
- SG4: Ensure the public trusts our product, because it's an authentication product we can't survive if people don't trust us.
- SG5: Reach a time to remediate critical vulnerabilties on crown jewel systems of less than 16 hours by August 2025
- SG6: Reach a time to remediate critical vulnerabilties on all systems of less than 3 days by August 2025
- SG7: Complete audit of Apple Passkey integration by February 2025
- SG8: Complete remediation of Apple Passkey vulns by February 2025
## Security Team KPIs (How we measure the team)
- SK1: TTD: Time to detect malicious behavior (Minutes)
- SK1: TTI: Time to begin investigation of malicious behavior (Minutes)
- SK3: TTR-CJC: Time to remediate critical vulnerabilities on crown jewel systems (Hours)
- SK3: TTR-C: Time to remediate critical vulnerabilities on all systems (Hours)
- SK4: PT: Public trust score (Complete, Significant, Moderate, Minimal, Distrust, N/A)
## Risk Register (The things we're most worried about)
- R1: Our infrastructure security team is understaffed by 50% after 5 key people left
- R2: We are not currently monitoring our external perimeter for attack surface related vulnerabilities like open ports, listening applications, unknown hosts, unknown subdomains pointing to these things, etc. We only do scans once every couple of months and we don't really have anyone to look at the results
- R3: It takes us multiple days to investigate potential malicious behavior on our systems.
- R4: We lack a full list of our assets, including externally facing hosts, S3 buckets, etc., which make up our attack surface
- R5: We have a low public trust score due to the events of 2022.
## Security Team Narrative
### Background
Alma hired a new security team starting in January of 2023 and we have been building out the program since then. The philosophy and approach for the security team is to explicitly articulate what we believe the highest risks are to Alma, to deploy targeted strategies to address those risks, and to use clear, transparent KPIs to show progress towards our goals over time.
### Current Risks
So our risk register looks like this:
1. We are understaffed by 50% after 5 key people left in 2022
2. Our perimeter is not being monitored for attack surface related vulnerabilities
3. It takes us too long to detect and start investigating malicious behavior on our systems
4. We do not have a full list of our assets, which makes it difficult to know what we need to protect
5. We have a low public trust score due to the events of 2022
### Strategies
As such, our strategies are as follows:
1. Hire 5 more A-tier security professionals
2. Purchase and implement an attack surface management solution
3. Invest in our detection and response capabilities
4. Purchase an asset inventory system that integrates with our attack surface management tool
5. Leverage PR to share as much of our progress as possible with the public to rebuild trust
### How We're Doing
We believe being transparent about our progress is key to everything, and for that reason we maintain a limited number of KPIs that we update every quarter. These metrics will not change often. They will remain consistent so that it's easy to track how we're spending our resources and the progress we're making.
Those KPIs are:
1. Time to detect malicious behavior
2. Time to start investigating malicious behavior
3. Time to remediate critical vulnerabilities on crown jewel systems
4. Time to remediate critical vulnerabilities on all systems
5. Our public trust score
As of $DATE$, our KPIs for these are currently:
$GIVE CURRENT KPIs from the Activity section below$
$INSERT GRAPHS OF KPI PROGRESS OVER TIME HERE$
## Security Team Strategies
- STS1: Hire 5 more A-tier security professionals
- STS2: Purchase an attack surface management solution
- STS3: Invest in our detection and response capabilities
- STS4: Purchase an asset inventory system that integrates with our attack surface management tool
## Infrastructure Notes (a basic description of our tech stack and various context around it)
- We currenty have no WAF protecting our main web app but we're considering adding one
- We have had some issues with S3 buckets becoming public, or being set up as public, which has lead to some close calls with customer data almost being exposed.
- alma.amazon-domain.com is our primary S3 bucket that contains everything, but it's not public readable or listable
- We have a root account for our AWS account that doesn't yet have 2FA on it, but we're working on fixing that within a few weeks (but it's been open for a few months)
- We also use Postgres for all our databases.
- Developers have root access to the all kubernetes nodes via SSH on port 45,001 using a shared developer key issued during laptop provisioning.
- We're a kubernetes shop and do everything through AWS
- We're logging most stuff to Cloudtrail and we kind of use guarduty, but we don't have a 24/7 team to monitor alerts and logs. We should add that to our list of challenges next time we update our overarll policy
- We also have a Windows infrastructure because some key personell came from Microsoft. The DC is hosted in our head office which is in Redwood City, and anyone who works in that office (most of the 300 employees) uses that to log in when tehy start work. The domain is ALMA.
- There's a domain-joined fileserver running Windows 2012 that most people use to upload new ideas and plans for new products. It uses Windows authentication from the domain.
- We use a palo alto firewall with 2fa using windows authenticator tied to SSO.
- The name of the AI system doing all this context creation using SPQA is Alma, which is also the name of the company.
- We use Workday for HR stuff. Slack for realtime communications. Outlook 365 as a service. Sentinel One on the workstations and laptops. Servers in AWS are mostly Amazon Linux 2 with a few Ubuntu boxes that are a few years old.
- We also primarily use Postgres for all of our systems.
## Team
TEAM MEMBER | TEAM ASSIGNED | SKILLS | PAY LEVEL | LOCATION | PROJECTS
Nadia Khan | Detection and Response | D&R (Expert), AWS (Strong), Python (Expert), Kubernetes (Basic), Postgres (Basic) | $249K | Redwood City
Chris Magann | Vulnerability Management | VM (Expert), AWS (Strong), Python (Basic), Postgres (Basic) | $212K | Redwood City
Tigan Wang | Vulnerability Management | VM (Expert), AWS (Strong), Python (Basic), Postgres (Basic) | $217K | Redwood City
## Projects
PROJECT NAME | PROJECT DESCRIPTION | PROJECT PRIORITY | PROJECT MEMBERS | START DATE | END DATE | STATUS | PROJECT COST
WAF Install | Install a WAF in front of our main web app | Critical | Nadia Khan | 2024-01-01 - Ongoing | In Progress | $112K one-time, $9K/month
Multi-Factor Authentication (MFA) Rollout | Implement MFA across all internal and external systems | Critical | Chris Magaan | 2024-01-15 | 2024-05-01 | Planned | $80K one-time, $5K/month
Procure and Implement ASM | Implement continuous monitoring for attack surface vulnerabilities | High | Tigan Wang | 2024-02-15 | 2024-06-15 | Not Started | $75K one-time, $6K/month
Data Encryption Upgrade | Upgrade encryption protocols for all sensitive data | Medium | Nadia Khan | 2024-04-01 | 2024-08-01 | Planned | $95K one-time
Incident Response Enhancement | Develop and implement a 24/7 incident response team | High | Nadia Khan | 2024-03-01 | 2024-07-01 | In Progress | $150K one-time, $10K/month
Cloud Security Optimization | Optimize AWS cloud security configurations and practices | Medium | Tigan Wang | 2024-02-01 | 2024-06-01 | In Progress | $100K one-time, $8K/month
S3 Bucket Security | Review and secure all S3 buckets to prevent data breaches | High | Chris Magaan | 2024-01-10 | 2024-04-10 | In Progress | $70K one-time, $5K/month
SQL Injection Mitigation | Implement measures to eliminate SQL injection vulnerabilities | High | Tigan Wang | 2024-01-20 | 2024-05-20 | Not Started | $60K one-time
## CURRENT STATE (KPIs, Metrics, Project Activity Updates, etc.)
- October 2022: Current time to detect malicious behavior is 81 hours
- October 2022: Current time to start investigating malicious behavior is 82 hours
- October 2022: Current time to remediate critical vulnerabilities on crown jewel systems is 21 days
- October 2022: Current time to remediate critical vulnerabilities on all systems is 51 days
- January 2023: Current time to detect malicious behavior is 62 hours
- January 2023: Current time to start investigating malicious behavior is 72 hours
- January 2023: Current time to remediate critical vulnerabilities on crown jewel systems is 17 days
- January 2023: Current time to remediate critical vulnerabilities on all systems is 43 days
- July 2023: Current time to detect malicious behavior is 29 hours
- July 2023: Current time to start investigating malicious behavior is 41 hours
- July 2023: Current time to remediate critical vulnerabilities on crown jewel systems is 12 days
- July 2023: Current time to remediate critical vulnerabilities on all systems is 29 days
- November 2023: Current time to start detect malicious behavior is 12 hours
- November 2023: Current time to start investigating malicious behavior is 16 hours
- November 2023: Current time to remediate critical vulnerabilities on crown jewel systems is 9 days
- November 2023: Current time to remediate critical vulnerabilities on all systems is 17 days
- February 2024: Started attack surface management vendor selection process
- January 2024: Current time to start detect malicious behavior is 9 hours
- January 2024: Current time to start investigating malicious behavior is 14 hours
- January 2024: Current time to remediate critical vulnerabilities on crown jewel systems is 8 days
- January 2024: Current time to remediate critical vulnerabilities on all systems is 12 days
- March 2024: We're now remediating crits on crown jewels in less than 6 days
- April 2024: We're now remediating all criticals within 11 days
- July 2024: Criticals are now being fixed in 9 days
- On August 5 we got remediation of critical vulnerabilities down to 7 days

41
Dockerfile Normal file
View File

@@ -0,0 +1,41 @@
# Use official golang image as builder
FROM golang:1.24.2-alpine AS builder
# Set working directory
WORKDIR /app
# Copy go mod and sum files
COPY go.mod go.sum ./
# Download dependencies
RUN go mod download
# Copy source code
COPY . .
# Build the application
RUN CGO_ENABLED=0 GOOS=linux go build -o fabric
# Use scratch as final base image
FROM alpine:latest
# Copy the binary from builder
COPY --from=builder /app/fabric /fabric
# Copy patterns directory
COPY patterns /patterns
# Ensure clean config directory and copy ENV file
RUN rm -rf /root/.config/fabric && \
mkdir -p /root/.config/fabric
COPY ENV /root/.config/fabric/.env
# Add debug commands
RUN ls -la /root/.config/fabric/
# Expose port 8080
EXPOSE 8080
# Run the binary with debug output
ENTRYPOINT ["/fabric"]
CMD ["--serve"]

View File

@@ -2,7 +2,7 @@
- The goal is to bring more encapsulation of the models management and simplified configuration management to bring increased flexibility, transparency on the overall flow, and simplicity in adding new model.
- We need to differentiate:
- Vendors: the producer of models (like OpenAI, Azure, Anthropric, Ollama, ..etc) and their associated APIs
- Vendors: the producer of models (like OpenAI, Azure, Anthropic, Ollama, ..etc) and their associated APIs
- Models: the LLM models these vendors are making public
- Each vendor and operations allowed by the vendor needs to be encapsulated. This includes:
- The questions needed to setup the model (like the API key, or the URL)
@@ -10,7 +10,7 @@
- The actions performed with a given model
- The configuration flow works like this for an **initial** call:
- The available vendors are called one by one, each of them being responsible for the data they collect. They return a set of environment variables under the form of a list of strings, or an empty list if the user does not want to setup this vendor. As we do not want each vendor to know which way the data they need will be collected (e.g., read from the command line, or a GUI), they will be asked for a list of questions, the configuration will inquire the user, and send back the questions with tthe collected answers to the Vendor. The Vendor is then either instantiating an instance (Vendor configured) and returning it, or returning `nil` if the Vendor should not be set up.
- The available vendors are called one by one, each of them being responsible for the data they collect. They return a set of environment variables under the form of a list of strings, or an empty list if the user does not want to setup this vendor. As we do not want each vendor to know which way the data they need will be collected (e.g., read from the command line, or a GUI), they will be asked for a list of questions, the configuration will inquire the user, and send back the questions with the collected answers to the Vendor. The Vendor is then either instantiating an instance (Vendor configured) and returning it, or returning `nil` if the Vendor should not be set up.
- the `.env` file is created, using the information returned by the vendors
- A list of patterns is downloaded from the main site
@@ -25,7 +25,7 @@
## TODO:
- Check if we need to read the system.md for every patterns when runnign the ListAllPatterns
- Check if we need to read the system.md for every patterns when running the ListAllPatterns
- Context management seems more complex than the one in the original fabric. Probably needs some work (at least to make it clear how it works)
- models on command line: give as well vendor (like `--model openai/gpt-4o`). If the vendor is not given, get it by retrieving all possible models and searching from that.
- if user gives the ollama url on command line, we need to update/init an ollama vendor.

View File

@@ -0,0 +1,118 @@
# Pattern Descriptions and Tags Management
This document explains the complete workflow for managing pattern descriptions and tags, including how to process new patterns and maintain metadata.
## System Overview
The pattern system follows this hierarchy:
1. `~/.config/fabric/patterns/` directory: The source of truth for available patterns
2. `pattern_extracts.json`: Contains first 500 words of each pattern for reference
3. `pattern_descriptions.json`: Stores pattern metadata (descriptions and tags)
4. `web/static/data/pattern_descriptions.json`: Web-accessible copy for the interface
## Pattern Processing Workflow
### 1. Adding New Patterns
- Add patterns to `~/.config/fabric/patterns/`
- Run extract_patterns.py to process new additions:
```bash
python extract_patterns.py
The Python Script automatically:
- Creates pattern extracts for reference
- Adds placeholder entries in descriptions file
- Syncs to web interface
### 2. Pattern Extract Creation
The script extracts first 500 words from each pattern's system.md file to:
- Provide context for writing descriptions
- Maintain reference material
- Aid in pattern categorization
### 3. Description and Tag Management
Pattern descriptions and tags are managed in pattern_descriptions.json:
{
"patterns": [
{
"patternName": "pattern_name",
"description": "[Description pending]",
"tags": []
}
]
}
## Completing Pattern Metadata
### Writing Descriptions
1. Check pattern_descriptions.json for "[Description pending]" entries
2. Reference pattern_extracts.json for context
3. How to update Pattern short descriptions (one sentence).
You can update your descriptions in pattern_descriptions.json manually or using LLM assistance (preferred approach).
Tell AI to look for "Description pending" entries in this file and write a short description based on the extract info in the pattern_extracts.json file. You can also ask your LLM to add tags for those newly added patterns, using other patterns tag assignments as example.
### Managing Tags
1. Add appropriate tags to new patterns
2. Update existing tags as needed
3. Tags are stored as arrays: ["TAG1", "TAG2"]
4. Edit pattern_descriptions.json directly to modify tags
5. Make tags your own. You can delete, replace, amend existing tags.
## File Synchronization
The script maintains synchronization between:
- Local pattern_descriptions.json
- Web interface copy in static/data/
- No manual file copying needed
## Best Practices
1. Run extract_patterns.py when:
- Adding new patterns
- Updating existing patterns
- Modifying pattern structure
2. Description Writing:
- Use pattern extracts for context
- Keep descriptions clear and concise
- Focus on pattern purpose and usage
3. Tag Management:
- Use consistent tag categories
- Apply multiple tags when relevant
- Update tags to reflect pattern evolution
## Troubleshooting
If patterns are not showing in the web interface:
1. Verify pattern_descriptions.json format
2. Check web static copy exists
3. Ensure proper file permissions
4. Run extract_patterns.py to resync
## File Structure
fabric/
├── patterns/ # Pattern source files
├── PATTERN_DESCRIPTIONS/
│ ├── extract_patterns.py # Pattern processing script
│ ├── pattern_extracts.json # Pattern content references
│ └── pattern_descriptions.json # Pattern metadata
└── web/
└── static/
└── data/
└── pattern_descriptions.json # Web interface copy

View File

@@ -0,0 +1,130 @@
#!/usr/bin/env python3
"""Extracts pattern information from the ~/.config/fabric/patterns directory,
creates JSON files for pattern extracts and descriptions, and updates web static files.
"""
import os
import json
import shutil
def load_existing_file(filepath):
"""Load existing JSON file or return default structure"""
if os.path.exists(filepath):
try:
with open(filepath, "r", encoding="utf-8") as f:
return json.load(f)
except json.JSONDecodeError:
print(
f"Warning: Malformed JSON in {filepath}. Starting with an empty list."
)
return {"patterns": []}
return {"patterns": []}
def get_pattern_extract(pattern_path):
"""Extract first 500 words from pattern's system.md file"""
system_md_path = os.path.join(pattern_path, "system.md")
with open(system_md_path, "r", encoding="utf-8") as f:
content = " ".join(f.read().split()[:500])
return content
def extract_pattern_info():
"""Extract pattern information from the patterns directory"""
script_dir = os.path.dirname(os.path.abspath(__file__))
patterns_dir = os.path.expanduser("~/.config/fabric/patterns")
print(f"\nScanning patterns directory: {patterns_dir}")
extracts_path = os.path.join(script_dir, "pattern_extracts.json")
descriptions_path = os.path.join(script_dir, "pattern_descriptions.json")
existing_extracts = load_existing_file(extracts_path)
existing_descriptions = load_existing_file(descriptions_path)
existing_extract_names = {p["patternName"] for p in existing_extracts["patterns"]}
existing_description_names = {
p["patternName"] for p in existing_descriptions["patterns"]
}
print(f"Found existing patterns: {len(existing_extract_names)}")
new_extracts = []
new_descriptions = []
for dirname in sorted(os.listdir(patterns_dir)):
pattern_path = os.path.join(patterns_dir, dirname)
system_md_path = os.path.join(pattern_path, "system.md")
if os.path.isdir(pattern_path) and os.path.exists(system_md_path):
if dirname not in existing_extract_names:
print(f"Processing new pattern: {dirname}")
try:
if dirname not in existing_extract_names:
print(f"Creating new extract for: {dirname}")
pattern_extract = get_pattern_extract(
pattern_path
) # Pass directory path
new_extracts.append(
{"patternName": dirname, "pattern_extract": pattern_extract}
)
if dirname not in existing_description_names:
print(f"Creating new description for: {dirname}")
new_descriptions.append(
{
"patternName": dirname,
"description": "[Description pending]",
"tags": [],
}
)
except OSError as e:
print(f"Error processing {dirname}: {str(e)}")
else:
print(f"Invalid pattern directory or missing system.md: {dirname}")
print("\nProcessing summary:")
print(f"New extracts created: {len(new_extracts)}")
print(f"New descriptions added: {len(new_descriptions)}")
existing_extracts["patterns"].extend(new_extracts)
existing_descriptions["patterns"].extend(new_descriptions)
return existing_extracts, existing_descriptions, len(new_descriptions)
def update_web_static(descriptions_path):
"""Copy pattern descriptions to web static directory"""
script_dir = os.path.dirname(os.path.abspath(__file__))
static_dir = os.path.join(script_dir, "..", "web", "static", "data")
os.makedirs(static_dir, exist_ok=True)
static_path = os.path.join(static_dir, "pattern_descriptions.json")
shutil.copy2(descriptions_path, static_path)
def save_pattern_files():
"""Save both pattern files and sync to web"""
script_dir = os.path.dirname(os.path.abspath(__file__))
extracts_path = os.path.join(script_dir, "pattern_extracts.json")
descriptions_path = os.path.join(script_dir, "pattern_descriptions.json")
pattern_extracts, pattern_descriptions, new_count = extract_pattern_info()
# Save files
with open(extracts_path, "w", encoding="utf-8") as f:
json.dump(pattern_extracts, f, indent=2, ensure_ascii=False)
with open(descriptions_path, "w", encoding="utf-8") as f:
json.dump(pattern_descriptions, f, indent=2, ensure_ascii=False)
# Update web static
update_web_static(descriptions_path)
print("\nProcessing complete:")
print(f"Total patterns: {len(pattern_descriptions['patterns'])}")
print(f"New patterns added: {new_count}")
if __name__ == "__main__":
save_pattern_files()

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

692
README.md
View File

@@ -1,4 +1,7 @@
<div align="center">
Fabric is graciously supported by…
[![Github Repo Tagline](https://github.com/user-attachments/assets/96ab3d81-9b13-4df4-ba09-75dee7a5c3d2)](https://warp.dev/fabric)
<img src="./images/fabric-logo-gif.gif" alt="fabriclogo" width="400" height="400"/>
@@ -9,76 +12,128 @@
![GitHub top language](https://img.shields.io/github/languages/top/danielmiessler/fabric)
![GitHub last commit](https://img.shields.io/github/last-commit/danielmiessler/fabric)
[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT)
[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/danielmiessler/fabric)
<p class="align center">
<div align="center">
<h4><code>fabric</code> is an open-source framework for augmenting humans using AI.</h4>
</p>
</div>
[Updates](#updates) •
[What and Why](#whatandwhy) •
[What and Why](#what-and-why) •
[Philosophy](#philosophy) •
[Installation](#Installation) •
[Usage](#Usage) •
[Installation](#installation) •
[Usage](#usage) •
[Examples](#examples) •
[Just Use the Patterns](#just-use-the-patterns) •
[Custom Patterns](#custom-patterns) •
[Helper Apps](#helper-apps) •
[Meta](#meta)
![Screenshot of fabric](images/fabric-summarize.png)
</div>
## What and why
Since the start of modern AI in late 2022 we've seen an **_extraordinary_** number of AI applications for accomplishing tasks. There are thousands of websites, chat-bots, mobile apps, and other interfaces for using all the different AI out there.
It's all really exciting and powerful, but _it's not easy to integrate this functionality into our lives._
<div class="align center">
<h4>In other words, AI doesn't have a capabilities problem—it has an <em>integration</em> problem.</h4>
</div>
**Fabric was created to address this by creating and organizing the fundamental units of AI—the prompts themselves!**
Fabric organizes prompts by real-world task, allowing people to create, collect, and organize their most important AI solutions in a single place for use in their favorite tools. And if you're command-line focused, you can use Fabric itself as the interface!
## Intro videos
Keep in mind that many of these were recorded when Fabric was Python-based, so remember to use the current [install instructions](#installation) below.
- [Network Chuck](https://www.youtube.com/watch?v=UbDyjIIGaxQ)
- [David Bombal](https://www.youtube.com/watch?v=vF-MQmVxnCs)
- [My Own Intro to the Tool](https://www.youtube.com/watch?v=wPEyyigh10g)
- [More Fabric YouTube Videos](https://www.youtube.com/results?search_query=fabric+ai)
## Navigation
- [Updates](#updates)
- [What and Why](#what-and-why)
- [Philosophy](#philosophy)
- [Breaking problems into components](#breaking-problems-into-components)
- [Too many prompts](#too-many-prompts)
- [The Fabric approach to prompting](#our-approach-to-prompting)
- [Installation](#Installation)
- [Migration](#Migration)
- [Upgrading](#Upgrading)
- [Usage](#Usage)
- [Examples](#examples)
- [`fabric`](#fabric)
- [What and why](#what-and-why)
- [Intro videos](#intro-videos)
- [Navigation](#navigation)
- [Updates](#updates)
- [Philosophy](#philosophy)
- [Breaking problems into components](#breaking-problems-into-components)
- [Too many prompts](#too-many-prompts)
- [Installation](#installation)
- [Get Latest Release Binaries](#get-latest-release-binaries)
- [Windows](#windows)
- [macOS (arm64)](#macos-arm64)
- [macOS (amd64)](#macos-amd64)
- [Linux (amd64)](#linux-amd64)
- [Linux (arm64)](#linux-arm64)
- [Using package managers](#using-package-managers)
- [macOS (Homebrew)](#macos-homebrew)
- [Arch Linux (AUR)](#arch-linux-aur)
- [From Source](#from-source)
- [Environment Variables](#environment-variables)
- [Setup](#setup)
- [Add aliases for all patterns](#add-aliases-for-all-patterns)
- [Save your files in markdown using aliases](#save-your-files-in-markdown-using-aliases)
- [Migration](#migration)
- [Upgrading](#upgrading)
- [Shell Completions](#shell-completions)
- [Zsh Completion](#zsh-completion)
- [Bash Completion](#bash-completion)
- [Fish Completion](#fish-completion)
- [Usage](#usage)
- [Our approach to prompting](#our-approach-to-prompting)
- [Examples](#examples)
- [Just use the Patterns](#just-use-the-patterns)
- [Custom Patterns](#custom-patterns)
- [Helper Apps](#helper-apps)
- [Meta](#meta)
- [Primary contributors](#primary-contributors)
- [Prompt Strategies](#prompt-strategies)
- [Custom Patterns](#custom-patterns)
- [Helper Apps](#helper-apps)
- [`to_pdf`](#to_pdf)
- [`to_pdf` Installation](#to_pdf-installation)
- [`code_helper`](#code_helper)
- [pbpaste](#pbpaste)
- [Web Interface](#web-interface)
- [Installing](#installing)
- [Streamlit UI](#streamlit-ui)
- [Clipboard Support](#clipboard-support)
- [Meta](#meta)
- [Primary contributors](#primary-contributors)
- [Contributors](#contributors)
<br />
## Updates
> [!NOTE]
September 15, 2024 — Lots of new stuff!
> * Fabric now supports calling the new `o1-preview` model using the `-r` switch (which stands for raw. Normal queries won't work with `o1-preview` because they disabled System access and don't allow us to set `Temperature`.
> * We have early support for Raycast! Under the `/patterns` directory there's a `raycast` directory with scripts that can be called from Raycast. If you add a scripts directory within Raycast and point it to your `~/.config/fabric/patterns/raycast` directory, you'll then be able to 1) invoke Raycast, type the name of the script, and then 2) paste in the content to be passed, and the results will return in Raycast. There's currently only one script in there but I am (Daniel) adding more.
> * **Go Migration: The following command line options were changed during the migration to Go:**
> * You now need to use the -c option instead of -C to copy the result to the clipboard.
> * You now need to use the -s option instead of -S to stream results in realtime.
> * The following command line options have been removed `--agents` (-a), `--gui`, `--clearsession`, `--remoteOllamaServer`, and `--sessionlog`
> * You can now use (-S) to configure an Ollama server.
> * **We're working on a GUI rewrite in Go as well**
## Intro videos
Keep in mind that many of these were recorded when Fabric was Python-based, so remember to use the current [install instructions](#Installation) below.
* [Network Chuck](https://www.youtube.com/watch?v=UbDyjIIGaxQ)
* [David Bombal](https://www.youtube.com/watch?v=vF-MQmVxnCs)
* [My Own Intro to the Tool](https://www.youtube.com/watch?v=wPEyyigh10g)
* [More Fabric YouTube Videos](https://www.youtube.com/results?search_query=fabric+ai)
## What and why
Since the start of 2023 and GenAI we've seen a massive number of AI applications for accomplishing tasks. It's powerful, but _it's not easy to integrate this functionality into our lives._
<div align="center">
<h4>In other words, AI doesn't have a capabilities problem—it has an <em>integration</em> problem.</h4>
</div>
Fabric was created to address this by enabling everyone to granularly apply AI to everyday challenges.
> [!NOTE]
>
> July 4, 2025
>
> - **Web Search**: Fabric now supports web search for Anthropic and OpenAI models using the `--search` and `--search-location` flags. This replaces the previous plugin-based search, so you may want to remove the old `ANTHROPIC_WEB_SEARCH_TOOL_*` variables from your `~/.config/fabric/.env` file.
> - **Image Generation**: Fabric now has powerful image generation capabilities with OpenAI.
> - Generate images from text prompts and save them using `--image-file`.
> - Edit existing images by providing an input image with `--attachment`.
> - Control image `size`, `quality`, `compression`, and `background` with the new `--image-*` flags.
>
>June 17, 2025
>
>- Fabric now supports Perplexity AI. Configure it by using `fabric -S` to add your Perplexity AI API Key,
> and then try:
>
> ```bash
> fabric -m sonar-pro "What is the latest world news?"
> ```
>
>June 11, 2025
>
>- Fabric's YouTube transcription now needs `yt-dlp` to be installed. Make sure to install the latest
> version (2025.06.09 as of this note). The YouTube API key is only needed for comments (the `--comments` flag)
> and metadata extraction (the `--metadata` flag).
## Philosophy
@@ -96,7 +151,7 @@ Our approach is to break problems into individual pieces (see below) and then ap
Prompts are good for this, but the biggest challenge I faced in 2023——which still exists today—is **the sheer number of AI prompts out there**. We all have prompts that are useful, but it's hard to discover new ones, know if they are good or not, _and manage different versions of the ones we like_.
One of <code>fabric</code>'s primary features is helping people collect and integrate prompts, which we call _Patterns_, into various parts of their lives.
One of `fabric`'s primary features is helping people collect and integrate prompts, which we call _Patterns_, into various parts of their lives.
Fabric has Patterns for all sorts of life and work activities, including:
@@ -117,23 +172,43 @@ To install Fabric, you can use the latest release binaries or install it from th
### Get Latest Release Binaries
#### Windows
`https://github.com/danielmiessler/fabric/releases/latest/download/fabric-windows-amd64.exe`
#### macOS (arm64)
`curl -L https://github.com/danielmiessler/fabric/releases/latest/download/fabric-darwin-arm64 > fabric && chmod +x fabric && ./fabric --version`
#### macOS (amd64)
`curl -L https://github.com/danielmiessler/fabric/releases/latest/download/fabric-darwin-amd64 > fabric && chmod +x fabric && ./fabric --version`
#### Linux (amd64)
`curl -L https://github.com/danielmiessler/fabric/releases/latest/download/fabric-linux-amd64 > fabric && chmod +x fabric && ./fabric --version`
#### Linux (arm64)
`curl -L https://github.com/danielmiessler/fabric/releases/latest/download/fabric-linux-arm64 > fabric && chmod +x fabric && ./fabric --version`
### Using package managers
**NOTE:** using Homebrew or the Arch Linux package managers makes `fabric` available as `fabric-ai`, so add
the following alias to your shell startup files to account for this:
```bash
# Windows:
curl -L https://github.com/danielmiessler/fabric/releases/latest/download/fabric-windows-amd64.exe > fabric.exe && fabric.exe --version
# MacOS (arm64):
curl -L https://github.com/danielmiessler/fabric/releases/latest/download/fabric-darwin-arm64 > fabric && chmod +x fabric && ./fabric --version
# MacOS (amd64):
curl -L https://github.com/danielmiessler/fabric/releases/latest/download/fabric-darwin-amd64 > fabric && chmod +x fabric && ./fabric --version
# Linux (amd64):
curl -L https://github.com/danielmiessler/fabric/releases/latest/download/fabric-linux-amd64 > fabric && chmod +x fabric && ./fabric --version
# Linux (arm64):
curl -L https://github.com/danielmiessler/fabric/releases/latest/download/fabric-linux-arm64 > fabric && chmod +x fabric && ./fabric --version
alias fabric='fabric-ai'
```
#### macOS (Homebrew)
`brew install fabric-ai`
#### Arch Linux (AUR)
`yay -S fabric-ai`
### From Source
To install Fabric, [make sure Go is installed](https://go.dev/doc/install), and then run the following command.
@@ -148,6 +223,7 @@ go install github.com/danielmiessler/fabric@latest
You may need to set some environment variables in your `~/.bashrc` on linux or `~/.zshrc` file on mac to be able to run the `fabric` command. Here is an example of what you can add:
For Intel based macs or linux
```bash
# Golang environment variables
export GOROOT=/usr/local/go
@@ -158,6 +234,7 @@ export PATH=$GOPATH/bin:$GOROOT/bin:$HOME/.local/bin:$PATH
```
for Apple Silicon based macs
```bash
# Golang environment variables
export GOROOT=$(brew --prefix go)/libexec
@@ -166,13 +243,176 @@ export PATH=$GOPATH/bin:$GOROOT/bin:$HOME/.local/bin:$PATH
```
### Setup
Now run the following command
```bash
# Run the setup to set up your directories and keys
fabric --setup
```
If everything works you are good to go.
### Add aliases for all patterns
In order to add aliases for all your patterns and use them directly as commands ie. `summarize` instead of `fabric --pattern summarize`
You can add the following to your `.zshrc` or `.bashrc` file.
```bash
# Loop through all files in the ~/.config/fabric/patterns directory
for pattern_file in $HOME/.config/fabric/patterns/*; do
# Get the base name of the file (i.e., remove the directory path)
pattern_name=$(basename "$pattern_file")
# Create an alias in the form: alias pattern_name="fabric --pattern pattern_name"
alias_command="alias $pattern_name='fabric --pattern $pattern_name'"
# Evaluate the alias command to add it to the current shell
eval "$alias_command"
done
yt() {
if [ "$#" -eq 0 ] || [ "$#" -gt 2 ]; then
echo "Usage: yt [-t | --timestamps] youtube-link"
echo "Use the '-t' flag to get the transcript with timestamps."
return 1
fi
transcript_flag="--transcript"
if [ "$1" = "-t" ] || [ "$1" = "--timestamps" ]; then
transcript_flag="--transcript-with-timestamps"
shift
fi
local video_link="$1"
fabric -y "$video_link" $transcript_flag
}
```
You can add the below code for the equivalent aliases inside PowerShell by running `notepad $PROFILE` inside a PowerShell window:
```powershell
# Path to the patterns directory
$patternsPath = Join-Path $HOME ".config/fabric/patterns"
foreach ($patternDir in Get-ChildItem -Path $patternsPath -Directory) {
$patternName = $patternDir.Name
# Dynamically define a function for each pattern
$functionDefinition = @"
function $patternName {
[CmdletBinding()]
param(
[Parameter(ValueFromPipeline = `$true)]
[string] `$InputObject,
[Parameter(ValueFromRemainingArguments = `$true)]
[String[]] `$patternArgs
)
begin {
# Initialize an array to collect pipeline input
`$collector = @()
}
process {
# Collect pipeline input objects
if (`$InputObject) {
`$collector += `$InputObject
}
}
end {
# Join all pipeline input into a single string, separated by newlines
`$pipelineContent = `$collector -join "`n"
# If there's pipeline input, include it in the call to fabric
if (`$pipelineContent) {
`$pipelineContent | fabric --pattern $patternName `$patternArgs
} else {
# No pipeline input; just call fabric with the additional args
fabric --pattern $patternName `$patternArgs
}
}
}
"@
# Add the function to the current session
Invoke-Expression $functionDefinition
}
# Define the 'yt' function as well
function yt {
[CmdletBinding()]
param(
[Parameter()]
[Alias("timestamps")]
[switch]$t,
[Parameter(Position = 0, ValueFromPipeline = $true)]
[string]$videoLink
)
begin {
$transcriptFlag = "--transcript"
if ($t) {
$transcriptFlag = "--transcript-with-timestamps"
}
}
process {
if (-not $videoLink) {
Write-Error "Usage: yt [-t | --timestamps] youtube-link"
return
}
}
end {
if ($videoLink) {
# Execute and allow output to flow through the pipeline
fabric -y $videoLink $transcriptFlag
}
}
}
```
This also creates a `yt` alias that allows you to use `yt https://www.youtube.com/watch?v=4b0iet22VIk` to get transcripts, comments, and metadata.
#### Save your files in markdown using aliases
If in addition to the above aliases you would like to have the option to save the output to your favorite markdown note vault like Obsidian then instead of the above add the following to your `.zshrc` or `.bashrc` file:
```bash
# Define the base directory for Obsidian notes
obsidian_base="/path/to/obsidian"
# Loop through all files in the ~/.config/fabric/patterns directory
for pattern_file in ~/.config/fabric/patterns/*; do
# Get the base name of the file (i.e., remove the directory path)
pattern_name=$(basename "$pattern_file")
# Remove any existing alias with the same name
unalias "$pattern_name" 2>/dev/null
# Define a function dynamically for each pattern
eval "
$pattern_name() {
local title=\$1
local date_stamp=\$(date +'%Y-%m-%d')
local output_path=\"\$obsidian_base/\${date_stamp}-\${title}.md\"
# Check if a title was provided
if [ -n \"\$title\" ]; then
# If a title is provided, use the output path
fabric --pattern \"$pattern_name\" -o \"\$output_path\"
else
# If no title is provided, use --stream
fabric --pattern \"$pattern_name\" --stream
fi
}
"
done
```
This will allow you to use the patterns as aliases like in the above for example `summarize` instead of `fabric --pattern summarize --stream`, however if you pass in an extra argument like this `summarize "my_article_title"` your output will be saved in the destination that you set in `obsidian_base="/path/to/obsidian"` in the following format `YYYY-MM-DD-my_article_title.md` where the date gets autogenerated for you.
You can tweak the date format by tweaking the `date_stamp` format.
### Migration
@@ -190,67 +430,138 @@ go install github.com/danielmiessler/fabric@latest
fabric --setup
```
Then [set your environmental variables](#environmental-variables) as shown above.
Then [set your environmental variables](#environment-variables) as shown above.
### Upgrading
The great thing about Go is that it's super easy to upgrade. Just run the same command you used to install it in the first place and you'll always get the latest version.
```bash
go install -ldflags "-X main.version=$(git describe --tags --always)" github.com/danielmiessler/fabric@latest
go install github.com/danielmiessler/fabric@latest
```
### Shell Completions
Fabric provides shell completion scripts for Zsh, Bash, and Fish
shells, making it easier to use the CLI by providing tab completion
for commands and options.
#### Zsh Completion
To enable Zsh completion:
```bash
# Copy the completion file to a directory in your $fpath
mkdir -p ~/.zsh/completions
cp completions/_fabric ~/.zsh/completions/
# Add the directory to fpath in your .zshrc before compinit
echo 'fpath=(~/.zsh/completions $fpath)' >> ~/.zshrc
echo 'autoload -Uz compinit && compinit' >> ~/.zshrc
```
#### Bash Completion
To enable Bash completion:
```bash
# Source the completion script in your .bashrc
echo 'source /path/to/fabric/completions/fabric.bash' >> ~/.bashrc
# Or copy to the system-wide bash completion directory
sudo cp completions/fabric.bash /etc/bash_completion.d/
```
#### Fish Completion
To enable Fish completion:
```bash
# Copy the completion file to the fish completions directory
mkdir -p ~/.config/fish/completions
cp completions/fabric.fish ~/.config/fish/completions/
```
## Usage
Once you have it all set up, here's how to use it.
```bash
fabric -h
```
```bash
usage: fabric -h
```plaintext
Usage:
fabric [OPTIONS]
Application Options:
-p, --pattern= Choose a pattern
-v, --variable= Values for pattern variables, e.g. -v=$name:John -v=$age:30
-C, --context= Choose a context
--session= Choose a session
-S, --setup Run setup for all reconfigurable parts of fabric
--setup-skip-patterns Run Setup for specific vendor, one of Ollama, OpenAI, Anthropic, Azure, Gemini, Groq, Mistral, OpenRouter, SiliconCloud. E.g. fabric --setup-vendor=OpenAI
--setup-vendor= Run Setup for specific vendor. E.g. --setup-vendor=OpenAI
-t, --temperature= Set temperature (default: 0.7)
-T, --topp= Set top P (default: 0.9)
-s, --stream Stream
-P, --presencepenalty= Set presence penalty (default: 0.0)
-r, --raw Use the defaults of the model without sending chat options (like temperature etc.) and use the user role instead of the system role for patterns.
-F, --frequencypenalty= Set frequency penalty (default: 0.0)
-l, --listpatterns List all patterns
-L, --listmodels List all available models
-x, --listcontexts List all contexts
-X, --listsessions List all sessions
-U, --updatepatterns Update patterns
-c, --copy Copy to clipboard
-m, --model= Choose model
-o, --output= Output to file
--output-prompt Output the used prompt (or entire session) before the result
-n, --latest= Number of latest patterns to list (default: 0)
-d, --changeDefaultModel Change default model
-y, --youtube= YouTube video "URL" to grab transcript, comments from it and send to chat
--transcript Grab transcript from YouTube video and send to chat (it used per default).
--comments Grab comments from YouTube video and send to chat
-g, --language= Specify the Language Code for the chat, e.g. -g=en -g=zh
-u, --scrape_url= Scrape website URL to markdown using Jina AI
-q, --scrape_question= Search question using Jina AI
-e, --seed= Seed to be used for LMM generation
-w, --wipecontext= Wipe context
-W, --wipesession= Wipe session
--printcontext= Print context
--printsession= Print session
--readability Convert HTML input into a clean, readable view
--dry-run Show what would be sent to the model without actually sending it
--version Print current version
-p, --pattern= Choose a pattern from the available patterns
-v, --variable= Values for pattern variables, e.g. -v=#role:expert -v=#points:30
-C, --context= Choose a context from the available contexts
--session= Choose a session from the available sessions
-a, --attachment= Attachment path or URL (e.g. for OpenAI image recognition messages)
-S, --setup Run setup for all reconfigurable parts of fabric
-t, --temperature= Set temperature (default: 0.7)
-T, --topp= Set top P (default: 0.9)
-s, --stream Stream
-P, --presencepenalty= Set presence penalty (default: 0.0)
-r, --raw Use the defaults of the model without sending chat options (like
temperature etc.) and use the user role instead of the system role for
patterns.
-F, --frequencypenalty= Set frequency penalty (default: 0.0)
-l, --listpatterns List all patterns
-L, --listmodels List all available models
-x, --listcontexts List all contexts
-X, --listsessions List all sessions
-U, --updatepatterns Update patterns
-c, --copy Copy to clipboard
-m, --model= Choose model
--modelContextLength= Model context length (only affects ollama)
-o, --output= Output to file
--output-session Output the entire session (also a temporary one) to the output file
-n, --latest= Number of latest patterns to list (default: 0)
-d, --changeDefaultModel Change default model
-y, --youtube= YouTube video or play list "URL" to grab transcript, comments from it
and send to chat or print it put to the console and store it in the
output file
--playlist Prefer playlist over video if both ids are present in the URL
--transcript Grab transcript from YouTube video and send to chat (it is used per
default).
--transcript-with-timestamps Grab transcript from YouTube video with timestamps and send to chat
--comments Grab comments from YouTube video and send to chat
--metadata Output video metadata
-g, --language= Specify the Language Code for the chat, e.g. -g=en -g=zh
-u, --scrape_url= Scrape website URL to markdown using Jina AI
-q, --scrape_question= Search question using Jina AI
-e, --seed= Seed to be used for LMM generation
-w, --wipecontext= Wipe context
-W, --wipesession= Wipe session
--printcontext= Print context
--printsession= Print session
--readability Convert HTML input into a clean, readable view
--input-has-vars Apply variables to user input
--dry-run Show what would be sent to the model without actually sending it
--serve Serve the Fabric Rest API
--serveOllama Serve the Fabric Rest API with ollama endpoints
--address= The address to bind the REST API (default: :8080)
--api-key= API key used to secure server routes
--config= Path to YAML config file
--version Print current version
--listextensions List all registered extensions
--addextension= Register a new extension from config file path
--rmextension= Remove a registered extension by name
--strategy= Choose a strategy from the available strategies
--liststrategies List all strategies
--listvendors List all vendors
--shell-complete-list Output raw list without headers/formatting (for shell completion)
--search Enable web search tool for supported models (Anthropic, OpenAI)
--search-location= Set location for web search results (e.g., 'America/Los_Angeles')
--image-file= Save generated image to specified file path (e.g., 'output.png')
--image-size= Image dimensions: 1024x1024, 1536x1024, 1024x1536, auto (default: auto)
--image-quality= Image quality: low, medium, high, auto (default: auto)
--image-compression= Compression level 0-100 for JPEG/WebP formats (default: not set)
--image-background= Background type: opaque, transparent (default: opaque, only for
PNG/WebP)
Help Options:
-h, --help Show this help message
@@ -277,27 +588,35 @@ https://github.com/danielmiessler/fabric/blob/main/patterns/extract_wisdom/syste
## Examples
> The following examples use the macOS `pbpaste` to paste from the clipboard. See the [pbpaste](#pbpaste) section below for Windows and Linux alternatives.
Now let's look at some things you can do with Fabric.
1. Run the `summarize` Pattern based on input from `stdin`. In this case, the body of an article.
```bash
pbpaste | fabric --pattern summarize
```
```bash
pbpaste | fabric --pattern summarize
```
2. Run the `analyze_claims` Pattern with the `--stream` option to get immediate and streaming results.
```bash
pbpaste | fabric --stream --pattern analyze_claims
```
```bash
pbpaste | fabric --stream --pattern analyze_claims
```
3. Run the `extract_wisdom` Pattern with the `--stream` option to get immediate and streaming results from any Youtube video (much like in the original introduction video).
3. Run the `extract_wisdom` Pattern with the `--stream` option to get immediate and streaming results from any Youtube video (much like in the original introduction video).
```bash
fabric -y "https://youtube.com/watch?v=uXs-zPc63kM" | --stream --pattern extract_wisdom
```
```bash
fabric -y "https://youtube.com/watch?v=uXs-zPc63kM" --stream --pattern extract_wisdom
```
4. Create patterns- you must create a .md file with the pattern and save it to ~/.config/fabric/patterns/[yourpatternname].
4. Create patterns- you must create a .md file with the pattern and save it to `~/.config/fabric/patterns/[yourpatternname]`.
5. Run a `analyze_claims` pattern on a website. Fabric uses Jina AI to scrape the URL into markdown format before sending it to the model.
```bash
fabric -u https://github.com/danielmiessler/fabric/ -p analyze_claims
```
## Just use the Patterns
@@ -314,23 +633,31 @@ You can use any of the Patterns you see there in any AI application that you hav
The wisdom of crowds for the win.
### Prompt Strategies
Fabric also implements prompt strategies like "Chain of Thought" or "Chain of Draft" which can
be used in addition to the basic patterns.
See the [Thinking Faster by Writing Less](https://arxiv.org/pdf/2502.18600) paper and
the [Thought Generation section of Learn Prompting](https://learnprompting.org/docs/advanced/thought_generation/introduction) for examples of prompt strategies.
Each strategy is available as a small `json` file in the [`/strategies`](https://github.com/danielmiessler/fabric/tree/main/strategies) directory.
The prompt modification of the strategy is applied to the system prompt and passed on to the
LLM in the chat session.
Use `fabric -S` and select the option to install the strategies in your `~/.config/fabric` directory.
## Custom Patterns
You may want to use Fabric to create your own custom Patterns—but not share them with others. No problem!
Just make a directory in `~/.config/custompatterns/` (or wherever) and put your `.md` files in there.
Just make a directory in `~/.config/custompatterns/` (or wherever) and put your `.md` files in there.
When you're ready to use them, copy them into:
```
~/.config/fabric/patterns/
```
When you're ready to use them, copy them into `~/.config/fabric/patterns/`
You can then use them like any other Patterns, but they won't be public unless you explicitly submit them as Pull Requests to the Fabric project. So don't worry—they're private to you.
This feature works with all openai and ollama models but does NOT work with claude. You can specify your model with the -m flag
## Helper Apps
Fabric also makes use of some core helper apps (tools) to make it easier to integrate with your various workflows. Here are some examples:
@@ -358,11 +685,103 @@ This will create a PDF file named `output.pdf` in the current directory.
To install `to_pdf`, install it the same way as you install Fabric, just with a different repo name.
```bash
go install github.com/danielmiessler/fabric/to_pdf@latest
go install github.com/danielmiessler/fabric/plugins/tools/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.
### `code_helper`
`code_helper` 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
with instructions to create a new feature or edit the code in a specified way.
See [the Create Coding Feature Pattern README](./patterns/create_coding_feature/README.md) for details.
Install it first using:
```bash
go install github.com/danielmiessler/fabric/plugins/tools/code_helper@latest
```
## pbpaste
The [examples](#examples) use the macOS program `pbpaste` to paste content from the clipboard to pipe into `fabric` as the input. `pbpaste` is not available on Windows or Linux, but there are alternatives.
On Windows, you can use the PowerShell command `Get-Clipboard` from a PowerShell command prompt. If you like, you can also alias it to `pbpaste`. If you are using classic PowerShell, edit the file `~\Documents\WindowsPowerShell\.profile.ps1`, or if you are using PowerShell Core, edit `~\Documents\PowerShell\.profile.ps1` and add the alias,
```powershell
Set-Alias pbpaste Get-Clipboard
```
On Linux, you can use `xclip -selection clipboard -o` to paste from the clipboard. You will likely need to install `xclip` with your package manager. For Debian based systems including Ubuntu,
```sh
sudo apt update
sudo apt install xclip -y
```
You can also create an alias by editing `~/.bashrc` or `~/.zshrc` and adding the alias,
```sh
alias pbpaste='xclip -selection clipboard -o'
```
## Web Interface
Fabric now includes a built-in web interface that provides a GUI alternative to the command-line interface and an out-of-the-box website for those who want to get started with web development or blogging.
You can use this app as a GUI interface for Fabric, a ready to go blog-site, or a website template for your own projects.
The `web/src/lib/content` directory includes starter `.obsidian/` and `templates/` directories, allowing you to open up the `web/src/lib/content/` directory as an [Obsidian.md](https://obsidian.md) vault. You can place your posts in the posts directory when you're ready to publish.
### Installing
The GUI can be installed by navigating to the `web` directory and using `npm install`, `pnpm install`, or your favorite package manager. Then simply run the development server to start the app.
_You will need to run fabric in a separate terminal with the `fabric --serve` command._
**From the fabric project `web/` directory:**
```shell
npm run dev
## or ##
pnpm run dev
## or your equivalent
```
### Streamlit UI
To run the Streamlit user interface:
```bash
# Install required dependencies
pip install -r requirements.txt
# Or manually install dependencies
pip install streamlit pandas matplotlib seaborn numpy python-dotenv pyperclip
# Run the Streamlit app
streamlit run streamlit.py
```
The Streamlit UI provides a user-friendly interface for:
- Running and chaining patterns
- Managing pattern outputs
- Creating and editing patterns
- Analyzing pattern results
#### Clipboard Support
The Streamlit UI supports clipboard operations across different platforms:
- **macOS**: Uses `pbcopy` and `pbpaste` (built-in)
- **Windows**: Uses `pyperclip` library (install with `pip install pyperclip`)
- **Linux**: Uses `xclip` (install with `sudo apt-get install xclip` or equivalent for your Linux distribution)
## Meta
> [!NOTE]
@@ -371,6 +790,7 @@ Make sure you have a LaTeX distribution (like TeX Live or MiKTeX) installed on y
- _Jonathan Dunn_ for being the absolute MVP dev on the project, including spearheading the new Go version, as well as the GUI! All this while also being a full-time medical doctor!
- _Caleb Sima_ for pushing me over the edge of whether to make this a public project or not.
- _Eugen Eisler_ and _Frederick Ros_ for their invaluable contributions to the Go version
- _David Peters_ for his work on the web interface.
- _Joel Parish_ for super useful input on the project's Github directory structure..
- _Joseph Thacker_ for the idea of a `-c` context flag that adds pre-created context in the `./config/fabric/` directory to all Pattern queries.
- _Jason Haddix_ for the idea of a stitch (chained Pattern) to filter content using a local model before sending on to a cloud model, i.e., cleaning customer data using `llama2` before sending on to `gpt-4` for analysis.
@@ -378,10 +798,18 @@ Make sure you have a LaTeX distribution (like TeX Live or MiKTeX) installed on y
### Primary contributors
<a href="https://github.com/danielmiessler"><img src="https://avatars.githubusercontent.com/u/50654?v=4" title="Daniel Miessler" width="50" height="50"></a>
<a href="https://github.com/xssdoctor"><img src="https://avatars.githubusercontent.com/u/9218431?v=4" title="Jonathan Dunn" width="50" height="50"></a>
<a href="https://github.com/sbehrens"><img src="https://avatars.githubusercontent.com/u/688589?v=4" title="Scott Behrens" width="50" height="50"></a>
<a href="https://github.com/agu3rra"><img src="https://avatars.githubusercontent.com/u/10410523?v=4" title="Andre Guerra" width="50" height="50"></a>
<a href="https://github.com/danielmiessler"><img src="https://avatars.githubusercontent.com/u/50654?v=4" title="Daniel Miessler" width="50" height="50" alt="Daniel Miessler"></a>
<a href="https://github.com/xssdoctor"><img src="https://avatars.githubusercontent.com/u/9218431?v=4" title="Jonathan Dunn" width="50" height="50" alt="Jonathan Dunn"></a>
<a href="https://github.com/sbehrens"><img src="https://avatars.githubusercontent.com/u/688589?v=4" title="Scott Behrens" width="50" height="50" alt="Scott Behrens"></a>
<a href="https://github.com/agu3rra"><img src="https://avatars.githubusercontent.com/u/10410523?v=4" title="Andre Guerra" width="50" height="50" alt="Andre Guerra"></a>
### Contributors
<a href="https://github.com/danielmiessler/fabric/graphs/contributors">
<img src="https://contrib.rocks/image?repo=danielmiessler/fabric" alt="contrib.rocks" />
</a>
Made with [contrib.rocks](https://contrib.rocks).
`fabric` was created by <a href="https://danielmiessler.com/subscribe" target="_blank">Daniel Miessler</a> in January of 2024.
<br /><br />

132
chat/chat.go Normal file
View File

@@ -0,0 +1,132 @@
package chat
import (
"encoding/json"
"errors"
)
const (
ChatMessageRoleSystem = "system"
ChatMessageRoleUser = "user"
ChatMessageRoleAssistant = "assistant"
ChatMessageRoleFunction = "function"
ChatMessageRoleTool = "tool"
ChatMessageRoleDeveloper = "developer"
)
var ErrContentFieldsMisused = errors.New("can't use both Content and MultiContent properties simultaneously")
type ChatMessagePartType string
const (
ChatMessagePartTypeText ChatMessagePartType = "text"
ChatMessagePartTypeImageURL ChatMessagePartType = "image_url"
)
type ChatMessageImageURL struct {
URL string `json:"url,omitempty"`
}
type ChatMessagePart struct {
Type ChatMessagePartType `json:"type,omitempty"`
Text string `json:"text,omitempty"`
ImageURL *ChatMessageImageURL `json:"image_url,omitempty"`
}
type FunctionCall struct {
Name string `json:"name,omitempty"`
Arguments string `json:"arguments,omitempty"`
}
type ToolType string
const (
ToolTypeFunction ToolType = "function"
)
type ToolCall struct {
Index *int `json:"index,omitempty"`
ID string `json:"id,omitempty"`
Type ToolType `json:"type"`
Function FunctionCall `json:"function"`
}
type ChatCompletionMessage struct {
Role string `json:"role"`
Content string `json:"content,omitempty"`
Refusal string `json:"refusal,omitempty"`
MultiContent []ChatMessagePart `json:"-"`
Name string `json:"name,omitempty"`
ReasoningContent string `json:"reasoning_content,omitempty"`
FunctionCall *FunctionCall `json:"function_call,omitempty"`
ToolCalls []ToolCall `json:"tool_calls,omitempty"`
ToolCallID string `json:"tool_call_id,omitempty"`
}
func (m ChatCompletionMessage) MarshalJSON() ([]byte, error) {
if m.Content != "" && m.MultiContent != nil {
return nil, ErrContentFieldsMisused
}
if len(m.MultiContent) > 0 {
msg := struct {
Role string `json:"role"`
Content string `json:"-"`
Refusal string `json:"refusal,omitempty"`
MultiContent []ChatMessagePart `json:"content,omitempty"`
Name string `json:"name,omitempty"`
ReasoningContent string `json:"reasoning_content,omitempty"`
FunctionCall *FunctionCall `json:"function_call,omitempty"`
ToolCalls []ToolCall `json:"tool_calls,omitempty"`
ToolCallID string `json:"tool_call_id,omitempty"`
}(m)
return json.Marshal(msg)
}
msg := struct {
Role string `json:"role"`
Content string `json:"content,omitempty"`
Refusal string `json:"refusal,omitempty"`
MultiContent []ChatMessagePart `json:"-"`
Name string `json:"name,omitempty"`
ReasoningContent string `json:"reasoning_content,omitempty"`
FunctionCall *FunctionCall `json:"function_call,omitempty"`
ToolCalls []ToolCall `json:"tool_calls,omitempty"`
ToolCallID string `json:"tool_call_id,omitempty"`
}(m)
return json.Marshal(msg)
}
func (m *ChatCompletionMessage) UnmarshalJSON(bs []byte) error {
msg := struct {
Role string `json:"role"`
Content string `json:"content"`
Refusal string `json:"refusal,omitempty"`
MultiContent []ChatMessagePart
Name string `json:"name,omitempty"`
ReasoningContent string `json:"reasoning_content,omitempty"`
FunctionCall *FunctionCall `json:"function_call,omitempty"`
ToolCalls []ToolCall `json:"tool_calls,omitempty"`
ToolCallID string `json:"tool_call_id,omitempty"`
}{}
if err := json.Unmarshal(bs, &msg); err == nil {
*m = ChatCompletionMessage(msg)
return nil
}
multiMsg := struct {
Role string `json:"role"`
Content string
Refusal string `json:"refusal,omitempty"`
MultiContent []ChatMessagePart `json:"content"`
Name string `json:"name,omitempty"`
ReasoningContent string `json:"reasoning_content,omitempty"`
FunctionCall *FunctionCall `json:"function_call,omitempty"`
ToolCalls []ToolCall `json:"tool_calls,omitempty"`
ToolCallID string `json:"tool_call_id,omitempty"`
}{}
if err := json.Unmarshal(bs, &multiMsg); err != nil {
return err
}
*m = ChatCompletionMessage(multiMsg)
return nil
}

77
cli/README.md Normal file
View File

@@ -0,0 +1,77 @@
# YAML Configuration Support
## Overview
Fabric now supports YAML configuration files for commonly used options. This allows users to persist settings and share configurations across multiple runs.
## Usage
Use the `--config` flag to specify a YAML configuration file:
```bash
fabric --config ~/.config/fabric/config.yaml "Tell me about APIs"
```
## Configuration Precedence
1. CLI flags (highest priority)
2. YAML config values
3. Default values (lowest priority)
## Supported Configuration Options
```yaml
# Model selection
model: gpt-4
modelContextLength: 4096
# Model parameters
temperature: 0.7
topp: 0.9
presencepenalty: 0.0
frequencypenalty: 0.0
seed: 42
# Pattern selection
pattern: analyze # Use pattern name or filename
# Feature flags
stream: true
raw: false
```
## Rules and Behavior
- Only long flag names are supported in YAML (e.g., `temperature` not `-t`)
- CLI flags always override YAML values
- Unknown YAML declarations are ignored
- If a declaration appears multiple times in YAML, the last one wins
- The order of YAML declarations doesn't matter
## Type Conversions
The following string-to-type conversions are supported:
- String to number: `"42"``42`
- String to float: `"42.5"``42.5`
- String to boolean: `"true"``true`
## Example Config
```yaml
# ~/.config/fabric/config.yaml
model: gpt-4
temperature: 0.8
pattern: analyze
stream: true
topp: 0.95
presencepenalty: 0.1
frequencypenalty: 0.2
```
## CLI Override Example
```bash
# Override temperature from config
fabric --config ~/.config/fabric/config.yaml --temperature 0.9 "Query"
```

View File

@@ -1,15 +1,21 @@
package cli
import (
"encoding/json"
"fmt"
"github.com/danielmiessler/fabric/converter"
"os"
"path/filepath"
"strconv"
"strings"
"github.com/danielmiessler/fabric/plugins/tools/youtube"
"github.com/danielmiessler/fabric/common"
"github.com/danielmiessler/fabric/core"
"github.com/danielmiessler/fabric/db"
"github.com/danielmiessler/fabric/plugins/ai"
"github.com/danielmiessler/fabric/plugins/db/fsdb"
"github.com/danielmiessler/fabric/plugins/tools/converter"
"github.com/danielmiessler/fabric/restapi"
)
// Cli Controls the cli. It takes in the flags and runs the appropriate functions
@@ -29,39 +35,48 @@ func Cli(version string) (err error) {
return
}
fabricDb := db.NewDb(filepath.Join(homedir, ".config/fabric"))
fabricDb := fsdb.NewDb(filepath.Join(homedir, ".config/fabric"))
// if the setup flag is set, run the setup function
if currentFlags.Setup || currentFlags.SetupSkipPatterns || currentFlags.SetupVendor != "" {
_ = fabricDb.Configure()
if currentFlags.SetupVendor != "" {
_, err = SetupVendor(fabricDb, currentFlags.SetupVendor)
} else {
_, err = Setup(fabricDb, currentFlags.SetupSkipPatterns)
if err = fabricDb.Configure(); err != nil {
if !currentFlags.Setup {
println(err.Error())
currentFlags.Setup = true
}
}
var registry *core.PluginRegistry
if registry, err = core.NewPluginRegistry(fabricDb); err != nil {
return
}
var fabric *core.Fabric
if err = fabricDb.Configure(); err != nil {
fmt.Println("init is failed, run start the setup procedure", err)
if fabric, err = Setup(fabricDb, currentFlags.SetupSkipPatterns); err != nil {
return
}
} else {
if fabric, err = core.NewFabric(fabricDb); err != nil {
fmt.Println("fabric can't initialize, please run the --setup procedure", err)
return
}
// if the setup flag is set, run the setup function
if currentFlags.Setup {
err = registry.Setup()
return
}
if currentFlags.Serve {
registry.ConfigureVendors()
err = restapi.Serve(registry, currentFlags.ServeAddress, currentFlags.ServeAPIKey)
return
}
if currentFlags.ServeOllama {
registry.ConfigureVendors()
err = restapi.ServeOllama(registry, currentFlags.ServeAddress, version)
return
}
if currentFlags.UpdatePatterns {
err = fabric.PopulateDB()
err = registry.PatternsLoader.PopulateDB()
return
}
if currentFlags.ChangeDefaultModel {
err = fabric.SetupDefaultModel()
if err = registry.Defaults.Setup(); err != nil {
return
}
err = registry.SaveEnvFile()
return
}
@@ -78,22 +93,26 @@ func Cli(version string) (err error) {
}
if currentFlags.ListPatterns {
err = fabricDb.Patterns.ListNames()
err = fabricDb.Patterns.ListNames(currentFlags.ShellCompleteOutput)
return
}
if currentFlags.ListAllModels {
fabric.GetModels().Print()
var models *ai.VendorsModels
if models, err = registry.VendorManager.GetModels(); err != nil {
return
}
models.Print(currentFlags.ShellCompleteOutput)
return
}
if currentFlags.ListAllContexts {
err = fabricDb.Contexts.ListNames()
err = fabricDb.Contexts.ListNames(currentFlags.ShellCompleteOutput)
return
}
if currentFlags.ListAllSessions {
err = fabricDb.Sessions.ListNames()
err = fabricDb.Sessions.ListNames(currentFlags.ShellCompleteOutput)
return
}
@@ -125,6 +144,31 @@ func Cli(version string) (err error) {
}
}
if currentFlags.ListExtensions {
err = registry.TemplateExtensions.ListExtensions()
return
}
if currentFlags.AddExtension != "" {
err = registry.TemplateExtensions.RegisterExtension(currentFlags.AddExtension)
return
}
if currentFlags.RemoveExtension != "" {
err = registry.TemplateExtensions.RemoveExtension(currentFlags.RemoveExtension)
return
}
if currentFlags.ListStrategies {
err = registry.Strategies.ListStrategies(currentFlags.ShellCompleteOutput)
return
}
if currentFlags.ListVendors {
err = registry.ListVendors(os.Stdout)
return
}
// if the interactive flag is set, run the interactive function
// if currentFlags.Interactive {
// interactive.Interactive()
@@ -132,83 +176,105 @@ func Cli(version string) (err error) {
// if none of the above currentFlags are set, run the initiate chat function
var messageTools string
if currentFlags.YouTube != "" {
if fabric.YouTube.IsConfigured() == false {
if !registry.YouTube.IsConfigured() {
err = fmt.Errorf("YouTube is not configured, please run the setup procedure")
return
}
var videoId string
if videoId, err = fabric.YouTube.GetVideoId(currentFlags.YouTube); err != nil {
var playlistId string
if videoId, playlistId, err = registry.YouTube.GetVideoOrPlaylistId(currentFlags.YouTube); err != nil {
return
} else if (videoId == "" || currentFlags.YouTubePlaylist) && playlistId != "" {
if currentFlags.Output != "" {
err = registry.YouTube.FetchAndSavePlaylist(playlistId, currentFlags.Output)
} else {
var videos []*youtube.VideoMeta
if videos, err = registry.YouTube.FetchPlaylistVideos(playlistId); err != nil {
err = fmt.Errorf("error fetching playlist videos: %v", err)
return
}
for _, video := range videos {
var message string
if message, err = processYoutubeVideo(currentFlags, registry, video.Id); err != nil {
return
}
if !currentFlags.IsChatRequest() {
if err = WriteOutput(message, fmt.Sprintf("%v.md", video.TitleNormalized)); err != nil {
return
}
} else {
messageTools = AppendMessage(messageTools, message)
}
}
}
return
}
if !currentFlags.YouTubeComments || currentFlags.YouTubeTranscript {
var transcript string
var language = "en"
if currentFlags.Language != "" {
language = currentFlags.Language
}
if transcript, err = fabric.YouTube.GrabTranscript(videoId, language); err != nil {
return
}
currentFlags.AppendMessage(transcript)
if messageTools, err = processYoutubeVideo(currentFlags, registry, videoId); err != nil {
return
}
if currentFlags.YouTubeComments {
var comments []string
if comments, err = fabric.YouTube.GrabComments(videoId); err != nil {
return
}
commentsString := strings.Join(comments, "\n")
currentFlags.AppendMessage(commentsString)
}
if !currentFlags.IsChatRequest() {
// if the pattern flag is not set, we wanted only to grab the transcript or comments
fmt.Println(currentFlags.Message)
err = currentFlags.WriteOutput(messageTools)
return
}
}
if (currentFlags.ScrapeURL != "" || currentFlags.ScrapeQuestion != "") && fabric.Jina.IsConfigured() {
if (currentFlags.ScrapeURL != "" || currentFlags.ScrapeQuestion != "") && registry.Jina.IsConfigured() {
// Check if the scrape_url flag is set and call ScrapeURL
if currentFlags.ScrapeURL != "" {
var website string
if website, err = fabric.Jina.ScrapeURL(currentFlags.ScrapeURL); err != nil {
if website, err = registry.Jina.ScrapeURL(currentFlags.ScrapeURL); err != nil {
return
}
currentFlags.AppendMessage(website)
messageTools = AppendMessage(messageTools, website)
}
// Check if the scrape_question flag is set and call ScrapeQuestion
if currentFlags.ScrapeQuestion != "" {
var website string
if website, err = fabric.Jina.ScrapeQuestion(currentFlags.ScrapeQuestion); err != nil {
if website, err = registry.Jina.ScrapeQuestion(currentFlags.ScrapeQuestion); err != nil {
return
}
currentFlags.AppendMessage(website)
messageTools = AppendMessage(messageTools, website)
}
if !currentFlags.IsChatRequest() {
// if the pattern flag is not set, we wanted only to grab the url or get the answer to the question
fmt.Println(currentFlags.Message)
err = currentFlags.WriteOutput(messageTools)
return
}
}
if messageTools != "" {
currentFlags.AppendMessage(messageTools)
}
var chatter *core.Chatter
if chatter, err = fabric.GetChatter(currentFlags.Model, currentFlags.Stream, currentFlags.DryRun); err != nil {
if chatter, err = registry.GetChatter(currentFlags.Model, currentFlags.ModelContextLength,
currentFlags.Strategy, currentFlags.Stream, currentFlags.DryRun); err != nil {
return
}
var session *db.Session
if session, err = chatter.Send(currentFlags.BuildChatRequest(), currentFlags.BuildChatOptions()); err != nil {
var session *fsdb.Session
var chatReq *common.ChatRequest
if chatReq, err = currentFlags.BuildChatRequest(strings.Join(os.Args[1:], " ")); err != nil {
return
}
if chatReq.Language == "" {
chatReq.Language = registry.Language.DefaultLanguage.Value
}
var chatOptions *common.ChatOptions
if chatOptions, err = currentFlags.BuildChatOptions(); err != nil {
return
}
if session, err = chatter.Send(chatReq, chatOptions); err != nil {
return
}
@@ -221,43 +287,75 @@ func Cli(version string) (err error) {
// if the copy flag is set, copy the message to the clipboard
if currentFlags.Copy {
if err = fabric.CopyToClipboard(result); err != nil {
if err = CopyToClipboard(result); err != nil {
return
}
}
// if the output flag is set, create an output file
if currentFlags.Output != "" {
if currentFlags.OutputPrompt {
if currentFlags.OutputSession {
sessionAsString := session.String()
err = fabric.CreateOutputFile(sessionAsString, currentFlags.Output)
err = CreateOutputFile(sessionAsString, currentFlags.Output)
} else {
err = fabric.CreateOutputFile(result, currentFlags.Output)
err = CreateOutputFile(result, currentFlags.Output)
}
}
return
}
func Setup(db *db.Db, skipUpdatePatterns bool) (ret *core.Fabric, err error) {
instance := core.NewFabricForSetup(db)
func processYoutubeVideo(
flags *Flags, registry *core.PluginRegistry, videoId string) (message string, err error) {
if err = instance.Setup(); err != nil {
return
if (!flags.YouTubeComments && !flags.YouTubeMetadata) || flags.YouTubeTranscript || flags.YouTubeTranscriptWithTimestamps {
var transcript string
var language = "en"
if flags.Language != "" || registry.Language.DefaultLanguage.Value != "" {
if flags.Language != "" {
language = flags.Language
} else {
language = registry.Language.DefaultLanguage.Value
}
}
if flags.YouTubeTranscriptWithTimestamps {
if transcript, err = registry.YouTube.GrabTranscriptWithTimestamps(videoId, language); err != nil {
return
}
} else {
if transcript, err = registry.YouTube.GrabTranscript(videoId, language); err != nil {
return
}
}
message = AppendMessage(message, transcript)
}
if !skipUpdatePatterns {
if err = instance.PopulateDB(); err != nil {
if flags.YouTubeComments {
var comments []string
if comments, err = registry.YouTube.GrabComments(videoId); err != nil {
return
}
commentsString := strings.Join(comments, "\n")
message = AppendMessage(message, commentsString)
}
ret = instance
if flags.YouTubeMetadata {
var metadata *youtube.VideoMetadata
if metadata, err = registry.YouTube.GrabMetadata(videoId); err != nil {
return
}
metadataJson, _ := json.MarshalIndent(metadata, "", " ")
message = AppendMessage(message, string(metadataJson))
}
return
}
func SetupVendor(db *db.Db, vendorName string) (ret *core.Fabric, err error) {
ret = core.NewFabricForSetup(db)
if err = ret.SetupVendor(vendorName); err != nil {
return
func WriteOutput(message string, outputFile string) (err error) {
fmt.Println(message)
if outputFile != "" {
err = CreateOutputFile(message, outputFile)
}
return
}

View File

@@ -1,11 +1,11 @@
package cli
import (
"github.com/danielmiessler/fabric/core"
"os"
"testing"
"github.com/danielmiessler/fabric/db"
"github.com/danielmiessler/fabric/core"
"github.com/stretchr/testify/assert"
)
@@ -19,11 +19,3 @@ func TestCli(t *testing.T) {
assert.Error(t, err)
assert.Equal(t, core.NoSessionPatternUserMessages, err.Error())
}
func TestSetup(t *testing.T) {
mockDB := db.NewDb(os.TempDir())
fabric, err := Setup(mockDB, false)
assert.Error(t, err)
assert.Nil(t, fabric)
}

21
cli/example.yaml Normal file
View File

@@ -0,0 +1,21 @@
#this is an example yaml config file for fabric
# use fabric pattern names
pattern: ai
# or use a filename
# pattern: ~/testpattern.md
model: phi3:latest
# for models that support context length
modelContextLength: 2048
frequencypenalty: 0.5
presencepenalty: 0.5
topp: 0.67
temperature: 0.88
seed: 42
stream: true
raw: false

View File

@@ -6,59 +6,123 @@ import (
"fmt"
"io"
"os"
"path/filepath"
"reflect"
"strconv"
"strings"
"github.com/danielmiessler/fabric/chat"
"github.com/danielmiessler/fabric/common"
"github.com/jessevdk/go-flags"
"golang.org/x/text/language"
"gopkg.in/yaml.v3"
)
// Flags create flags struct. the users flags go into this, this will be passed to the chat struct in cli
type Flags struct {
Pattern string `short:"p" long:"pattern" description:"Choose a pattern" default:""`
PatternVariables map[string]string `short:"v" long:"variable" description:"Values for pattern variables, e.g. -v=$name:John -v=$age:30"`
Context string `short:"C" long:"context" description:"Choose a context" default:""`
Session string `long:"session" description:"Choose a session"`
Setup bool `short:"S" long:"setup" description:"Run setup for all reconfigurable parts of fabric"`
SetupSkipPatterns bool `long:"setup-skip-patterns" description:"Run Setup for specific vendor, one of Ollama, OpenAI, Anthropic, Azure, Gemini, Groq, Mistral, OpenRouter, SiliconCloud. E.g. fabric --setup-vendor=OpenAI"`
SetupVendor string `long:"setup-vendor" description:"Run Setup for specific vendor. E.g. --setup-vendor=OpenAI"`
Temperature float64 `short:"t" long:"temperature" description:"Set temperature" default:"0.7"`
TopP float64 `short:"T" long:"topp" description:"Set top P" default:"0.9"`
Stream bool `short:"s" long:"stream" description:"Stream"`
PresencePenalty float64 `short:"P" long:"presencepenalty" description:"Set presence penalty" default:"0.0"`
Raw bool `short:"r" long:"raw" description:"Use the defaults of the model without sending chat options (like temperature etc.) and use the user role instead of the system role for patterns."`
FrequencyPenalty float64 `short:"F" long:"frequencypenalty" description:"Set frequency penalty" default:"0.0"`
ListPatterns bool `short:"l" long:"listpatterns" description:"List all patterns"`
ListAllModels bool `short:"L" long:"listmodels" description:"List all available models"`
ListAllContexts bool `short:"x" long:"listcontexts" description:"List all contexts"`
ListAllSessions bool `short:"X" long:"listsessions" description:"List all sessions"`
UpdatePatterns bool `short:"U" long:"updatepatterns" description:"Update patterns"`
Message string `hidden:"true" description:"Message to send to chat"`
Copy bool `short:"c" long:"copy" description:"Copy to clipboard"`
Model string `short:"m" long:"model" description:"Choose model"`
Output string `short:"o" long:"output" description:"Output to file" default:""`
OutputPrompt bool `long:"output-prompt" description:"Output the used prompt (or entire session) before the result"`
LatestPatterns string `short:"n" long:"latest" description:"Number of latest patterns to list" default:"0"`
ChangeDefaultModel bool `short:"d" long:"changeDefaultModel" description:"Change default model"`
YouTube string `short:"y" long:"youtube" description:"YouTube video \"URL\" to grab transcript, comments from it and send to chat"`
YouTubeTranscript bool `long:"transcript" description:"Grab transcript from YouTube video and send to chat (it used per default)."`
YouTubeComments bool `long:"comments" description:"Grab comments from YouTube video and send to chat"`
Language string `short:"g" long:"language" description:"Specify the Language Code for the chat, e.g. -g=en -g=zh" default:""`
ScrapeURL string `short:"u" long:"scrape_url" description:"Scrape website URL to markdown using Jina AI"`
ScrapeQuestion string `short:"q" long:"scrape_question" description:"Search question using Jina AI"`
Seed int `short:"e" long:"seed" description:"Seed to be used for LMM generation"`
WipeContext string `short:"w" long:"wipecontext" description:"Wipe context"`
WipeSession string `short:"W" long:"wipesession" description:"Wipe session"`
PrintContext string `long:"printcontext" description:"Print context"`
PrintSession string `long:"printsession" description:"Print session"`
HtmlReadability bool `long:"readability" description:"Convert HTML input into a clean, readable view"`
DryRun bool `long:"dry-run" description:"Show what would be sent to the model without actually sending it"`
Version bool `long:"version" description:"Print current version"`
Pattern string `short:"p" long:"pattern" yaml:"pattern" description:"Choose a pattern from the available patterns" default:""`
PatternVariables map[string]string `short:"v" long:"variable" description:"Values for pattern variables, e.g. -v=#role:expert -v=#points:30"`
Context string `short:"C" long:"context" description:"Choose a context from the available contexts" default:""`
Session string `long:"session" description:"Choose a session from the available sessions"`
Attachments []string `short:"a" long:"attachment" description:"Attachment path or URL (e.g. for OpenAI image recognition messages)"`
Setup bool `short:"S" long:"setup" description:"Run setup for all reconfigurable parts of fabric"`
Temperature float64 `short:"t" long:"temperature" yaml:"temperature" description:"Set temperature" default:"0.7"`
TopP float64 `short:"T" long:"topp" yaml:"topp" description:"Set top P" default:"0.9"`
Stream bool `short:"s" long:"stream" yaml:"stream" description:"Stream"`
PresencePenalty float64 `short:"P" long:"presencepenalty" yaml:"presencepenalty" description:"Set presence penalty" default:"0.0"`
Raw bool `short:"r" long:"raw" yaml:"raw" description:"Use the defaults of the model without sending chat options (like temperature etc.) and use the user role instead of the system role for patterns."`
FrequencyPenalty float64 `short:"F" long:"frequencypenalty" yaml:"frequencypenalty" description:"Set frequency penalty" default:"0.0"`
ListPatterns bool `short:"l" long:"listpatterns" description:"List all patterns"`
ListAllModels bool `short:"L" long:"listmodels" description:"List all available models"`
ListAllContexts bool `short:"x" long:"listcontexts" description:"List all contexts"`
ListAllSessions bool `short:"X" long:"listsessions" description:"List all sessions"`
UpdatePatterns bool `short:"U" long:"updatepatterns" description:"Update patterns"`
Message string `hidden:"true" description:"Messages to send to chat"`
Copy bool `short:"c" long:"copy" description:"Copy to clipboard"`
Model string `short:"m" long:"model" yaml:"model" description:"Choose model"`
ModelContextLength int `long:"modelContextLength" yaml:"modelContextLength" description:"Model context length (only affects ollama)"`
Output string `short:"o" long:"output" description:"Output to file" default:""`
OutputSession bool `long:"output-session" description:"Output the entire session (also a temporary one) to the output file"`
LatestPatterns string `short:"n" long:"latest" description:"Number of latest patterns to list" default:"0"`
ChangeDefaultModel bool `short:"d" long:"changeDefaultModel" description:"Change default model"`
YouTube string `short:"y" long:"youtube" description:"YouTube video or play list \"URL\" to grab transcript, comments from it and send to chat or print it put to the console and store it in the output file"`
YouTubePlaylist bool `long:"playlist" description:"Prefer playlist over video if both ids are present in the URL"`
YouTubeTranscript bool `long:"transcript" description:"Grab transcript from YouTube video and send to chat (it is used per default)."`
YouTubeTranscriptWithTimestamps bool `long:"transcript-with-timestamps" description:"Grab transcript from YouTube video with timestamps and send to chat"`
YouTubeComments bool `long:"comments" description:"Grab comments from YouTube video and send to chat"`
YouTubeMetadata bool `long:"metadata" description:"Output video metadata"`
Language string `short:"g" long:"language" description:"Specify the Language Code for the chat, e.g. -g=en -g=zh" default:""`
ScrapeURL string `short:"u" long:"scrape_url" description:"Scrape website URL to markdown using Jina AI"`
ScrapeQuestion string `short:"q" long:"scrape_question" description:"Search question using Jina AI"`
Seed int `short:"e" long:"seed" yaml:"seed" description:"Seed to be used for LMM generation"`
WipeContext string `short:"w" long:"wipecontext" description:"Wipe context"`
WipeSession string `short:"W" long:"wipesession" description:"Wipe session"`
PrintContext string `long:"printcontext" description:"Print context"`
PrintSession string `long:"printsession" description:"Print session"`
HtmlReadability bool `long:"readability" description:"Convert HTML input into a clean, readable view"`
InputHasVars bool `long:"input-has-vars" description:"Apply variables to user input"`
DryRun bool `long:"dry-run" description:"Show what would be sent to the model without actually sending it"`
Serve bool `long:"serve" description:"Serve the Fabric Rest API"`
ServeOllama bool `long:"serveOllama" description:"Serve the Fabric Rest API with ollama endpoints"`
ServeAddress string `long:"address" description:"The address to bind the REST API" default:":8080"`
ServeAPIKey string `long:"api-key" description:"API key used to secure server routes" default:""`
Config string `long:"config" description:"Path to YAML config file"`
Version bool `long:"version" description:"Print current version"`
ListExtensions bool `long:"listextensions" description:"List all registered extensions"`
AddExtension string `long:"addextension" description:"Register a new extension from config file path"`
RemoveExtension string `long:"rmextension" description:"Remove a registered extension by name"`
Strategy string `long:"strategy" description:"Choose a strategy from the available strategies" default:""`
ListStrategies bool `long:"liststrategies" description:"List all strategies"`
ListVendors bool `long:"listvendors" description:"List all vendors"`
ShellCompleteOutput bool `long:"shell-complete-list" description:"Output raw list without headers/formatting (for shell completion)"`
Search bool `long:"search" description:"Enable web search tool for supported models (Anthropic, OpenAI)"`
SearchLocation string `long:"search-location" description:"Set location for web search results (e.g., 'America/Los_Angeles')"`
ImageFile string `long:"image-file" description:"Save generated image to specified file path (e.g., 'output.png')"`
ImageSize string `long:"image-size" description:"Image dimensions: 1024x1024, 1536x1024, 1024x1536, auto (default: auto)"`
ImageQuality string `long:"image-quality" description:"Image quality: low, medium, high, auto (default: auto)"`
ImageCompression int `long:"image-compression" description:"Compression level 0-100 for JPEG/WebP formats (default: not set)"`
ImageBackground string `long:"image-background" description:"Background type: opaque, transparent (default: opaque, only for PNG/WebP)"`
}
var debug = false
func Debugf(format string, a ...interface{}) {
if debug {
fmt.Printf("DEBUG: "+format, a...)
}
}
// Init Initialize flags. returns a Flags struct and an error
func Init() (ret *Flags, err error) {
var message string
// Track which yaml-configured flags were set on CLI
usedFlags := make(map[string]bool)
yamlArgsScan := os.Args[1:]
// Get list of fields that have yaml tags, could be in yaml config
yamlFields := make(map[string]bool)
t := reflect.TypeOf(Flags{})
for i := 0; i < t.NumField(); i++ {
if yamlTag := t.Field(i).Tag.Get("yaml"); yamlTag != "" {
yamlFields[yamlTag] = true
//Debugf("Found yaml-configured field: %s\n", yamlTag)
}
}
// Scan args for that are provided by cli and might be in yaml
for _, arg := range yamlArgsScan {
if strings.HasPrefix(arg, "--") {
flag := strings.TrimPrefix(arg, "--")
if i := strings.Index(flag, "="); i > 0 {
flag = flag[:i]
}
if yamlFields[flag] {
usedFlags[flag] = true
Debugf("CLI flag used: %s\n", flag)
}
}
}
// Parse CLI flags first
ret = &Flags{}
parser := flags.NewParser(ret, flags.Default)
var args []string
@@ -66,64 +130,331 @@ func Init() (ret *Flags, err error) {
return
}
info, _ := os.Stdin.Stat()
hasStdin := (info.Mode() & os.ModeCharDevice) == 0
// takes input from stdin if it exists, otherwise takes input from args (the last argument)
if hasStdin {
if message, err = readStdin(); err != nil {
// If config specified, load and apply YAML for unused flags
if ret.Config != "" {
var yamlFlags *Flags
if yamlFlags, err = loadYAMLConfig(ret.Config); err != nil {
return
}
} else if len(args) > 0 {
message = args[len(args)-1]
} else {
message = ""
}
ret.Message = message
// Apply YAML values where CLI flags weren't used
flagsVal := reflect.ValueOf(ret).Elem()
yamlVal := reflect.ValueOf(yamlFlags).Elem()
flagsType := flagsVal.Type()
for i := 0; i < flagsType.NumField(); i++ {
field := flagsType.Field(i)
if yamlTag := field.Tag.Get("yaml"); yamlTag != "" {
if !usedFlags[yamlTag] {
flagField := flagsVal.Field(i)
yamlField := yamlVal.Field(i)
if flagField.CanSet() {
if yamlField.Type() != flagField.Type() {
if err := assignWithConversion(flagField, yamlField); err != nil {
Debugf("Type conversion failed for %s: %v\n", yamlTag, err)
continue
}
} else {
flagField.Set(yamlField)
}
Debugf("Applied YAML value for %s: %v\n", yamlTag, yamlField.Interface())
}
}
}
}
}
// Handle stdin and messages
// Handle stdin and messages
info, _ := os.Stdin.Stat()
pipedToStdin := (info.Mode() & os.ModeCharDevice) == 0
// Append positional arguments to the message (custom message)
if len(args) > 0 {
ret.Message = AppendMessage(ret.Message, args[len(args)-1])
}
if pipedToStdin {
var pipedMessage string
if pipedMessage, err = readStdin(); err != nil {
return
}
ret.Message = AppendMessage(ret.Message, pipedMessage)
}
return
}
func assignWithConversion(targetField, sourceField reflect.Value) error {
// Handle string source values
if sourceField.Kind() == reflect.String {
str := sourceField.String()
switch targetField.Kind() {
case reflect.Int:
// Try parsing as float first to handle "42.9" -> 42
if val, err := strconv.ParseFloat(str, 64); err == nil {
targetField.SetInt(int64(val))
return nil
}
// Try direct int parse
if val, err := strconv.ParseInt(str, 10, 64); err == nil {
targetField.SetInt(val)
return nil
}
case reflect.Float64:
if val, err := strconv.ParseFloat(str, 64); err == nil {
targetField.SetFloat(val)
return nil
}
case reflect.Bool:
if val, err := strconv.ParseBool(str); err == nil {
targetField.SetBool(val)
return nil
}
}
return fmt.Errorf("cannot convert string %q to %v", str, targetField.Kind())
}
return fmt.Errorf("unsupported conversion from %v to %v", sourceField.Kind(), targetField.Kind())
}
func loadYAMLConfig(configPath string) (*Flags, error) {
absPath, err := common.GetAbsolutePath(configPath)
if err != nil {
return nil, fmt.Errorf("invalid config path: %w", err)
}
data, err := os.ReadFile(absPath)
if err != nil {
if os.IsNotExist(err) {
return nil, fmt.Errorf("config file not found: %s", absPath)
}
return nil, fmt.Errorf("error reading config file: %w", err)
}
// Use the existing Flags struct for YAML unmarshal
config := &Flags{}
if err := yaml.Unmarshal(data, config); err != nil {
return nil, fmt.Errorf("error parsing config file: %w", err)
}
Debugf("Config: %v\n", config)
return config, nil
}
// readStdin reads from stdin and returns the input as a string or an error
func readStdin() (string, error) {
func readStdin() (ret string, err error) {
reader := bufio.NewReader(os.Stdin)
var input string
var sb strings.Builder
for {
line, err := reader.ReadString('\n')
if err != nil {
if errors.Is(err, io.EOF) {
if line, readErr := reader.ReadString('\n'); readErr != nil {
if errors.Is(readErr, io.EOF) {
sb.WriteString(line)
break
}
return "", fmt.Errorf("error reading from stdin: %w", err)
err = fmt.Errorf("error reading piped message from stdin: %w", readErr)
return
} else {
sb.WriteString(line)
}
input += line
}
return input, nil
ret = sb.String()
return
}
func (o *Flags) BuildChatOptions() (ret *common.ChatOptions) {
// validateImageFile validates the image file path and extension
func validateImageFile(imagePath string) error {
if imagePath == "" {
return nil // No validation needed if no image file specified
}
// Check if file already exists
if _, err := os.Stat(imagePath); err == nil {
return fmt.Errorf("image file already exists: %s", imagePath)
}
// Check file extension
ext := strings.ToLower(filepath.Ext(imagePath))
validExtensions := []string{".png", ".jpeg", ".jpg", ".webp"}
for _, validExt := range validExtensions {
if ext == validExt {
return nil // Valid extension found
}
}
return fmt.Errorf("invalid image file extension '%s'. Supported formats: .png, .jpeg, .jpg, .webp", ext)
}
// validateImageParameters validates image generation parameters
func validateImageParameters(imagePath, size, quality, background string, compression int) error {
if imagePath == "" {
// Check if any image parameters are specified without --image-file
if size != "" || quality != "" || background != "" || compression != 0 {
return fmt.Errorf("image parameters (--image-size, --image-quality, --image-background, --image-compression) can only be used with --image-file")
}
return nil
}
// Validate size
if size != "" {
validSizes := []string{"1024x1024", "1536x1024", "1024x1536", "auto"}
valid := false
for _, validSize := range validSizes {
if size == validSize {
valid = true
break
}
}
if !valid {
return fmt.Errorf("invalid image size '%s'. Supported sizes: 1024x1024, 1536x1024, 1024x1536, auto", size)
}
}
// Validate quality
if quality != "" {
validQualities := []string{"low", "medium", "high", "auto"}
valid := false
for _, validQuality := range validQualities {
if quality == validQuality {
valid = true
break
}
}
if !valid {
return fmt.Errorf("invalid image quality '%s'. Supported qualities: low, medium, high, auto", quality)
}
}
// Validate background
if background != "" {
validBackgrounds := []string{"opaque", "transparent"}
valid := false
for _, validBackground := range validBackgrounds {
if background == validBackground {
valid = true
break
}
}
if !valid {
return fmt.Errorf("invalid image background '%s'. Supported backgrounds: opaque, transparent", background)
}
}
// Get file format for format-specific validations
ext := strings.ToLower(filepath.Ext(imagePath))
// Validate compression (only for jpeg/webp)
if compression != 0 { // 0 means not set
if ext != ".jpg" && ext != ".jpeg" && ext != ".webp" {
return fmt.Errorf("image compression can only be used with JPEG and WebP formats, not %s", ext)
}
if compression < 0 || compression > 100 {
return fmt.Errorf("image compression must be between 0 and 100, got %d", compression)
}
}
// Validate background transparency (only for png/webp)
if background == "transparent" {
if ext != ".png" && ext != ".webp" {
return fmt.Errorf("transparent background can only be used with PNG and WebP formats, not %s", ext)
}
}
return nil
}
func (o *Flags) BuildChatOptions() (ret *common.ChatOptions, err error) {
// Validate image file if specified
if err = validateImageFile(o.ImageFile); err != nil {
return nil, err
}
// Validate image parameters
if err = validateImageParameters(o.ImageFile, o.ImageSize, o.ImageQuality, o.ImageBackground, o.ImageCompression); err != nil {
return nil, err
}
ret = &common.ChatOptions{
Temperature: o.Temperature,
TopP: o.TopP,
PresencePenalty: o.PresencePenalty,
FrequencyPenalty: o.FrequencyPenalty,
Raw: o.Raw,
Seed: o.Seed,
Model: o.Model,
Temperature: o.Temperature,
TopP: o.TopP,
PresencePenalty: o.PresencePenalty,
FrequencyPenalty: o.FrequencyPenalty,
Raw: o.Raw,
Seed: o.Seed,
ModelContextLength: o.ModelContextLength,
Search: o.Search,
SearchLocation: o.SearchLocation,
ImageFile: o.ImageFile,
ImageSize: o.ImageSize,
ImageQuality: o.ImageQuality,
ImageCompression: o.ImageCompression,
ImageBackground: o.ImageBackground,
}
return
}
func (o *Flags) BuildChatRequest() (ret *common.ChatRequest) {
func (o *Flags) BuildChatRequest(Meta string) (ret *common.ChatRequest, err error) {
ret = &common.ChatRequest{
ContextName: o.Context,
SessionName: o.Session,
PatternName: o.Pattern,
StrategyName: o.Strategy,
PatternVariables: o.PatternVariables,
Message: o.Message,
InputHasVars: o.InputHasVars,
Meta: Meta,
}
var message *chat.ChatCompletionMessage
if len(o.Attachments) > 0 {
message = &chat.ChatCompletionMessage{
Role: chat.ChatMessageRoleUser,
}
if o.Message != "" {
message.MultiContent = append(message.MultiContent, chat.ChatMessagePart{
Type: chat.ChatMessagePartTypeText,
Text: strings.TrimSpace(o.Message),
})
}
for _, attachmentValue := range o.Attachments {
var attachment *common.Attachment
if attachment, err = common.NewAttachment(attachmentValue); err != nil {
return
}
url := attachment.URL
if url == nil {
var base64Image string
if base64Image, err = attachment.Base64Content(); err != nil {
return
}
var mimeType string
if mimeType, err = attachment.ResolveType(); err != nil {
return
}
dataURL := fmt.Sprintf("data:%s;base64,%s", mimeType, base64Image)
url = &dataURL
}
message.MultiContent = append(message.MultiContent, chat.ChatMessagePart{
Type: chat.ChatMessagePartTypeImageURL,
ImageURL: &chat.ChatMessageImageURL{
URL: *url,
},
})
}
} else if o.Message != "" {
message = &chat.ChatCompletionMessage{
Role: chat.ChatMessageRoleUser,
Content: strings.TrimSpace(o.Message),
}
}
ret.Message = message
if o.Language != "" {
langTag, err := language.Parse(o.Language)
if err == nil {
if langTag, langErr := language.Parse(o.Language); langErr == nil {
ret.Language = langTag.String()
}
}
@@ -131,15 +462,27 @@ func (o *Flags) BuildChatRequest() (ret *common.ChatRequest) {
}
func (o *Flags) AppendMessage(message string) {
if o.Message != "" {
o.Message = o.Message + "\n" + message
} else {
o.Message = message
o.Message = AppendMessage(o.Message, message)
}
func (o *Flags) IsChatRequest() (ret bool) {
ret = o.Message != "" || len(o.Attachments) > 0 || o.Context != "" || o.Session != "" || o.Pattern != ""
return
}
func (o *Flags) WriteOutput(message string) (err error) {
fmt.Println(message)
if o.Output != "" {
err = CreateOutputFile(message, o.Output)
}
return
}
func (o *Flags) IsChatRequest() (ret bool) {
ret = o.Message != "" || o.Session != ""
func AppendMessage(message string, newMessage string) (ret string) {
if message != "" {
ret = message + "\n" + newMessage
} else {
ret = newMessage
}
return
}

View File

@@ -4,6 +4,7 @@ import (
"bytes"
"io"
"os"
"path/filepath"
"strings"
"testing"
@@ -64,7 +65,8 @@ func TestBuildChatOptions(t *testing.T) {
Raw: false,
Seed: 1,
}
options := flags.BuildChatOptions()
options, err := flags.BuildChatOptions()
assert.NoError(t, err)
assert.Equal(t, expectedOptions, options)
}
@@ -84,24 +86,350 @@ func TestBuildChatOptionsDefaultSeed(t *testing.T) {
Raw: false,
Seed: 0,
}
options := flags.BuildChatOptions()
options, err := flags.BuildChatOptions()
assert.NoError(t, err)
assert.Equal(t, expectedOptions, options)
}
func TestBuildChatRequest(t *testing.T) {
flags := &Flags{
Context: "test-context",
Session: "test-session",
Pattern: "test-pattern",
Message: "test-message",
func TestInitWithYAMLConfig(t *testing.T) {
// Create a temporary YAML config file
configContent := `
temperature: 0.9
model: gpt-4
pattern: analyze
stream: true
`
tmpfile, err := os.CreateTemp("", "config.*.yaml")
if err != nil {
t.Fatal(err)
}
defer os.Remove(tmpfile.Name())
if _, err := tmpfile.Write([]byte(configContent)); err != nil {
t.Fatal(err)
}
if err := tmpfile.Close(); err != nil {
t.Fatal(err)
}
expectedRequest := &common.ChatRequest{
ContextName: "test-context",
SessionName: "test-session",
PatternName: "test-pattern",
Message: "test-message",
}
request := flags.BuildChatRequest()
assert.Equal(t, expectedRequest, request)
// Test 1: Basic YAML loading
t.Run("Load YAML config", func(t *testing.T) {
oldArgs := os.Args
defer func() { os.Args = oldArgs }()
os.Args = []string{"cmd", "--config", tmpfile.Name()}
flags, err := Init()
assert.NoError(t, err)
assert.Equal(t, 0.9, flags.Temperature)
assert.Equal(t, "gpt-4", flags.Model)
assert.Equal(t, "analyze", flags.Pattern)
assert.True(t, flags.Stream)
})
// Test 2: CLI overrides YAML
t.Run("CLI overrides YAML", func(t *testing.T) {
oldArgs := os.Args
defer func() { os.Args = oldArgs }()
os.Args = []string{"cmd", "--config", tmpfile.Name(), "--temperature", "0.7", "--model", "gpt-3.5-turbo"}
flags, err := Init()
assert.NoError(t, err)
assert.Equal(t, 0.7, flags.Temperature)
assert.Equal(t, "gpt-3.5-turbo", flags.Model)
assert.Equal(t, "analyze", flags.Pattern) // unchanged from YAML
assert.True(t, flags.Stream) // unchanged from YAML
})
// Test 3: Invalid YAML config
t.Run("Invalid YAML config", func(t *testing.T) {
badConfig := `
temperature: "not a float"
model: 123 # should be string
`
badfile, err := os.CreateTemp("", "bad-config.*.yaml")
if err != nil {
t.Fatal(err)
}
defer os.Remove(badfile.Name())
if _, err := badfile.Write([]byte(badConfig)); err != nil {
t.Fatal(err)
}
if err := badfile.Close(); err != nil {
t.Fatal(err)
}
oldArgs := os.Args
defer func() { os.Args = oldArgs }()
os.Args = []string{"cmd", "--config", badfile.Name()}
_, err = Init()
assert.Error(t, err)
})
}
func TestValidateImageFile(t *testing.T) {
t.Run("Empty path should be valid", func(t *testing.T) {
err := validateImageFile("")
assert.NoError(t, err)
})
t.Run("Valid extensions should pass", func(t *testing.T) {
validExtensions := []string{".png", ".jpeg", ".jpg", ".webp"}
for _, ext := range validExtensions {
filename := "/tmp/test" + ext
err := validateImageFile(filename)
assert.NoError(t, err, "Extension %s should be valid", ext)
}
})
t.Run("Invalid extensions should fail", func(t *testing.T) {
invalidExtensions := []string{".gif", ".bmp", ".tiff", ".svg", ".txt", ""}
for _, ext := range invalidExtensions {
filename := "/tmp/test" + ext
err := validateImageFile(filename)
assert.Error(t, err, "Extension %s should be invalid", ext)
assert.Contains(t, err.Error(), "invalid image file extension")
}
})
t.Run("Existing file should fail", func(t *testing.T) {
// Create a temporary file
tempFile, err := os.CreateTemp("", "test*.png")
assert.NoError(t, err)
defer os.Remove(tempFile.Name())
tempFile.Close()
// Validation should fail because file exists
err = validateImageFile(tempFile.Name())
assert.Error(t, err)
assert.Contains(t, err.Error(), "image file already exists")
})
t.Run("Non-existing file with valid extension should pass", func(t *testing.T) {
nonExistentFile := filepath.Join(os.TempDir(), "non_existent_file.png")
// Make sure the file doesn't exist
os.Remove(nonExistentFile)
err := validateImageFile(nonExistentFile)
assert.NoError(t, err)
})
}
func TestBuildChatOptionsWithImageFileValidation(t *testing.T) {
t.Run("Valid image file should pass", func(t *testing.T) {
flags := &Flags{
ImageFile: "/tmp/output.png",
}
options, err := flags.BuildChatOptions()
assert.NoError(t, err)
assert.Equal(t, "/tmp/output.png", options.ImageFile)
})
t.Run("Invalid extension should fail", func(t *testing.T) {
flags := &Flags{
ImageFile: "/tmp/output.gif",
}
options, err := flags.BuildChatOptions()
assert.Error(t, err)
assert.Nil(t, options)
assert.Contains(t, err.Error(), "invalid image file extension")
})
t.Run("Existing file should fail", func(t *testing.T) {
// Create a temporary file
tempFile, err := os.CreateTemp("", "existing*.png")
assert.NoError(t, err)
defer os.Remove(tempFile.Name())
tempFile.Close()
flags := &Flags{
ImageFile: tempFile.Name(),
}
options, err := flags.BuildChatOptions()
assert.Error(t, err)
assert.Nil(t, options)
assert.Contains(t, err.Error(), "image file already exists")
})
}
func TestValidateImageParameters(t *testing.T) {
t.Run("No image file and no parameters should pass", func(t *testing.T) {
err := validateImageParameters("", "", "", "", 0)
assert.NoError(t, err)
})
t.Run("Image parameters without image file should fail", func(t *testing.T) {
// Test each parameter individually
err := validateImageParameters("", "1024x1024", "", "", 0)
assert.Error(t, err)
assert.Contains(t, err.Error(), "image parameters")
assert.Contains(t, err.Error(), "can only be used with --image-file")
err = validateImageParameters("", "", "high", "", 0)
assert.Error(t, err)
assert.Contains(t, err.Error(), "image parameters")
err = validateImageParameters("", "", "", "transparent", 0)
assert.Error(t, err)
assert.Contains(t, err.Error(), "image parameters")
err = validateImageParameters("", "", "", "", 50)
assert.Error(t, err)
assert.Contains(t, err.Error(), "image parameters")
// Test multiple parameters
err = validateImageParameters("", "1024x1024", "high", "transparent", 50)
assert.Error(t, err)
assert.Contains(t, err.Error(), "image parameters")
})
t.Run("Valid size values should pass", func(t *testing.T) {
validSizes := []string{"1024x1024", "1536x1024", "1024x1536", "auto"}
for _, size := range validSizes {
err := validateImageParameters("/tmp/test.png", size, "", "", 0)
assert.NoError(t, err, "Size %s should be valid", size)
}
})
t.Run("Invalid size should fail", func(t *testing.T) {
err := validateImageParameters("/tmp/test.png", "invalid", "", "", 0)
assert.Error(t, err)
assert.Contains(t, err.Error(), "invalid image size")
})
t.Run("Valid quality values should pass", func(t *testing.T) {
validQualities := []string{"low", "medium", "high", "auto"}
for _, quality := range validQualities {
err := validateImageParameters("/tmp/test.png", "", quality, "", 0)
assert.NoError(t, err, "Quality %s should be valid", quality)
}
})
t.Run("Invalid quality should fail", func(t *testing.T) {
err := validateImageParameters("/tmp/test.png", "", "invalid", "", 0)
assert.Error(t, err)
assert.Contains(t, err.Error(), "invalid image quality")
})
t.Run("Valid background values should pass", func(t *testing.T) {
validBackgrounds := []string{"opaque", "transparent"}
for _, background := range validBackgrounds {
err := validateImageParameters("/tmp/test.png", "", "", background, 0)
assert.NoError(t, err, "Background %s should be valid", background)
}
})
t.Run("Invalid background should fail", func(t *testing.T) {
err := validateImageParameters("/tmp/test.png", "", "", "invalid", 0)
assert.Error(t, err)
assert.Contains(t, err.Error(), "invalid image background")
})
t.Run("Compression for JPEG should pass", func(t *testing.T) {
err := validateImageParameters("/tmp/test.jpg", "", "", "", 75)
assert.NoError(t, err)
})
t.Run("Compression for WebP should pass", func(t *testing.T) {
err := validateImageParameters("/tmp/test.webp", "", "", "", 50)
assert.NoError(t, err)
})
t.Run("Compression for PNG should fail", func(t *testing.T) {
err := validateImageParameters("/tmp/test.png", "", "", "", 75)
assert.Error(t, err)
assert.Contains(t, err.Error(), "image compression can only be used with JPEG and WebP formats")
})
t.Run("Invalid compression range should fail", func(t *testing.T) {
err := validateImageParameters("/tmp/test.jpg", "", "", "", 150)
assert.Error(t, err)
assert.Contains(t, err.Error(), "image compression must be between 0 and 100")
err = validateImageParameters("/tmp/test.jpg", "", "", "", -10)
assert.Error(t, err)
assert.Contains(t, err.Error(), "image compression must be between 0 and 100")
})
t.Run("Transparent background for PNG should pass", func(t *testing.T) {
err := validateImageParameters("/tmp/test.png", "", "", "transparent", 0)
assert.NoError(t, err)
})
t.Run("Transparent background for WebP should pass", func(t *testing.T) {
err := validateImageParameters("/tmp/test.webp", "", "", "transparent", 0)
assert.NoError(t, err)
})
t.Run("Transparent background for JPEG should fail", func(t *testing.T) {
err := validateImageParameters("/tmp/test.jpg", "", "", "transparent", 0)
assert.Error(t, err)
assert.Contains(t, err.Error(), "transparent background can only be used with PNG and WebP formats")
})
}
func TestBuildChatOptionsWithImageParameters(t *testing.T) {
t.Run("Valid image parameters should pass", func(t *testing.T) {
flags := &Flags{
ImageFile: "/tmp/test.png",
ImageSize: "1024x1024",
ImageQuality: "high",
ImageBackground: "transparent",
ImageCompression: 0, // Not set for PNG
}
options, err := flags.BuildChatOptions()
assert.NoError(t, err)
assert.NotNil(t, options)
assert.Equal(t, "/tmp/test.png", options.ImageFile)
assert.Equal(t, "1024x1024", options.ImageSize)
assert.Equal(t, "high", options.ImageQuality)
assert.Equal(t, "transparent", options.ImageBackground)
assert.Equal(t, 0, options.ImageCompression)
})
t.Run("Invalid image parameters should fail", func(t *testing.T) {
flags := &Flags{
ImageFile: "/tmp/test.png",
ImageSize: "invalid",
ImageQuality: "high",
ImageBackground: "transparent",
}
options, err := flags.BuildChatOptions()
assert.Error(t, err)
assert.Nil(t, options)
assert.Contains(t, err.Error(), "invalid image size")
})
t.Run("JPEG with compression should pass", func(t *testing.T) {
flags := &Flags{
ImageFile: "/tmp/test.jpg",
ImageSize: "1536x1024",
ImageQuality: "medium",
ImageBackground: "opaque",
ImageCompression: 80,
}
options, err := flags.BuildChatOptions()
assert.NoError(t, err)
assert.NotNil(t, options)
assert.Equal(t, 80, options.ImageCompression)
})
t.Run("Image parameters without image file should fail in BuildChatOptions", func(t *testing.T) {
flags := &Flags{
ImageSize: "1024x1024", // Image parameter without ImageFile
}
options, err := flags.BuildChatOptions()
assert.Error(t, err)
assert.Nil(t, options)
assert.Contains(t, err.Error(), "image parameters")
assert.Contains(t, err.Error(), "can only be used with --image-file")
})
}

30
cli/output.go Normal file
View File

@@ -0,0 +1,30 @@
package cli
import (
"fmt"
"os"
"github.com/atotto/clipboard"
)
func CopyToClipboard(message string) (err error) {
if err = clipboard.WriteAll(message); err != nil {
err = fmt.Errorf("could not copy to clipboard: %v", err)
}
return
}
func CreateOutputFile(message string, fileName string) (err error) {
var file *os.File
if file, err = os.Create(fileName); err != nil {
err = fmt.Errorf("error creating file: %v", err)
return
}
defer file.Close()
if _, err = file.WriteString(message); err != nil {
err = fmt.Errorf("error writing to file: %v", err)
} else {
fmt.Printf("\n\n... written to %s\n", fileName)
}
return
}

28
cli/output_test.go Normal file
View File

@@ -0,0 +1,28 @@
package cli
import (
"os"
"testing"
)
func TestCopyToClipboard(t *testing.T) {
t.Skip("skipping test, because of docker env. in ci.")
message := "test message"
err := CopyToClipboard(message)
if err != nil {
t.Fatalf("CopyToClipboard() error = %v", err)
}
}
func TestCreateOutputFile(t *testing.T) {
fileName := "test_output.txt"
message := "test message"
err := CreateOutputFile(message, fileName)
if err != nil {
t.Fatalf("CreateOutputFile() error = %v", err)
}
defer os.Remove(fileName)
}

171
common/attachment.go Normal file
View File

@@ -0,0 +1,171 @@
package common
import (
"bytes"
"crypto/sha256"
"encoding/base64"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"path/filepath"
"github.com/gabriel-vasile/mimetype"
)
type Attachment struct {
Type *string `json:"type,omitempty"`
Path *string `json:"path,omitempty"`
URL *string `json:"url,omitempty"`
Content []byte `json:"content,omitempty"`
ID *string `json:"id,omitempty"`
}
func (a *Attachment) GetId() (ret string, err error) {
if a.ID == nil {
var hash string
if a.Content != nil {
hash = fmt.Sprintf("%x", sha256.Sum256(a.Content))
} else if a.Path != nil {
var content []byte
if content, err = os.ReadFile(*a.Path); err != nil {
return
}
hash = fmt.Sprintf("%x", sha256.Sum256(content))
} else if a.URL != nil {
data := map[string]string{"url": *a.URL}
var jsonData []byte
if jsonData, err = json.Marshal(data); err != nil {
return
}
hash = fmt.Sprintf("%x", sha256.Sum256(jsonData))
}
a.ID = &hash
}
ret = *a.ID
return
}
func (a *Attachment) ResolveType() (ret string, err error) {
if a.Type != nil {
ret = *a.Type
return
}
if a.Path != nil {
var mime *mimetype.MIME
if mime, err = mimetype.DetectFile(*a.Path); err != nil {
return
}
ret = mime.String()
return
}
if a.URL != nil {
var resp *http.Response
if resp, err = http.Head(*a.URL); err != nil {
return
}
defer resp.Body.Close()
ret = resp.Header.Get("Content-Type")
return
}
if a.Content != nil {
ret = mimetype.Detect(a.Content).String()
return
}
err = fmt.Errorf("attachment has no type and no content to derive it from")
return
}
func (a *Attachment) ContentBytes() (ret []byte, err error) {
if a.Content != nil {
ret = a.Content
return
}
if a.Path != nil {
if ret, err = os.ReadFile(*a.Path); err != nil {
return
}
return
}
if a.URL != nil {
var resp *http.Response
if resp, err = http.Get(*a.URL); err != nil {
return
}
defer resp.Body.Close()
if ret, err = io.ReadAll(resp.Body); err != nil {
return
}
return
}
err = fmt.Errorf("no content available")
return
}
func (a *Attachment) Base64Content() (ret string, err error) {
var content []byte
if content, err = a.ContentBytes(); err != nil {
return
}
ret = base64.StdEncoding.EncodeToString(content)
return
}
func NewAttachment(value string) (ret *Attachment, err error) {
if isURL(value) {
var mimeType string
if mimeType, err = detectMimeTypeFromURL(value); err != nil {
return
}
ret = &Attachment{
Type: &mimeType,
URL: &value,
}
return
}
var absPath string
if absPath, err = filepath.Abs(value); err != nil {
return
}
if _, err = os.Stat(absPath); os.IsNotExist(err) {
err = fmt.Errorf("file %s does not exist", value)
return
}
var mimeType string
if mimeType, err = detectMimeTypeFromFile(absPath); err != nil {
return
}
ret = &Attachment{
Type: &mimeType,
Path: &absPath,
}
return
}
func detectMimeTypeFromURL(url string) (string, error) {
resp, err := http.Head(url)
if err != nil {
return "", err
}
defer resp.Body.Close()
mimeType := resp.Header.Get("Content-Type")
if mimeType == "" {
return "", fmt.Errorf("could not determine mimetype of URL")
}
return mimeType, nil
}
func detectMimeTypeFromFile(path string) (string, error) {
mime, err := mimetype.DetectFile(path)
if err != nil {
return "", err
}
return mime.String(), nil
}
func isURL(value string) bool {
return bytes.Contains([]byte(value), []byte("://"))
}

View File

@@ -1,33 +1,42 @@
package common
import goopenai "github.com/sashabaranov/go-openai"
import "github.com/danielmiessler/fabric/chat"
type Message struct {
Role string `json:"role"`
Content string `json:"content"`
}
const ChatMessageRoleMeta = "meta"
type ChatRequest struct {
ContextName string
SessionName string
PatternName string
PatternVariables map[string]string
Message string
Message *chat.ChatCompletionMessage
Language string
Meta string
InputHasVars bool
StrategyName string
}
type ChatOptions struct {
Model string
Temperature float64
TopP float64
PresencePenalty float64
FrequencyPenalty float64
Raw bool
Seed int
Model string
Temperature float64
TopP float64
PresencePenalty float64
FrequencyPenalty float64
Raw bool
Seed int
ModelContextLength int
MaxTokens int
Search bool
SearchLocation string
ImageFile string
ImageSize string
ImageQuality string
ImageCompression int
ImageBackground string
}
// NormalizeMessages remove empty messages and ensure messages order user-assist-user
func NormalizeMessages(msgs []*Message, defaultUserMessage string) (ret []*Message) {
func NormalizeMessages(msgs []*chat.ChatCompletionMessage, defaultUserMessage string) (ret []*chat.ChatCompletionMessage) {
// Iterate over messages to enforce the odd position rule for user messages
fullMessageIndex := 0
for _, message := range msgs {
@@ -37,8 +46,8 @@ func NormalizeMessages(msgs []*Message, defaultUserMessage string) (ret []*Messa
}
// Ensure, that each odd position shall be a user message
if fullMessageIndex%2 == 0 && message.Role != goopenai.ChatMessageRoleUser {
ret = append(ret, &Message{Role: goopenai.ChatMessageRoleUser, Content: defaultUserMessage})
if fullMessageIndex%2 == 0 && message.Role != chat.ChatMessageRoleUser {
ret = append(ret, &chat.ChatCompletionMessage{Role: chat.ChatMessageRoleUser, Content: defaultUserMessage})
fullMessageIndex++
}
ret = append(ret, message)

View File

@@ -1,24 +1,25 @@
package common
import (
goopenai "github.com/sashabaranov/go-openai"
"github.com/stretchr/testify/assert"
"testing"
"github.com/danielmiessler/fabric/chat"
"github.com/stretchr/testify/assert"
)
func TestNormalizeMessages(t *testing.T) {
msgs := []*Message{
{Role: goopenai.ChatMessageRoleUser, Content: "Hello"},
{Role: goopenai.ChatMessageRoleAssistant, Content: "Hi there!"},
{Role: goopenai.ChatMessageRoleUser, Content: ""},
{Role: goopenai.ChatMessageRoleUser, Content: ""},
{Role: goopenai.ChatMessageRoleUser, Content: "How are you?"},
msgs := []*chat.ChatCompletionMessage{
{Role: chat.ChatMessageRoleUser, Content: "Hello"},
{Role: chat.ChatMessageRoleAssistant, Content: "Hi there!"},
{Role: chat.ChatMessageRoleUser, Content: ""},
{Role: chat.ChatMessageRoleUser, Content: ""},
{Role: chat.ChatMessageRoleUser, Content: "How are you?"},
}
expected := []*Message{
{Role: goopenai.ChatMessageRoleUser, Content: "Hello"},
{Role: goopenai.ChatMessageRoleAssistant, Content: "Hi there!"},
{Role: goopenai.ChatMessageRoleUser, Content: "How are you?"},
expected := []*chat.ChatCompletionMessage{
{Role: chat.ChatMessageRoleUser, Content: "Hello"},
{Role: chat.ChatMessageRoleAssistant, Content: "Hi there!"},
{Role: chat.ChatMessageRoleUser, Content: "How are you?"},
}
actual := NormalizeMessages(msgs, "default")

195
common/file_manager.go Normal file
View File

@@ -0,0 +1,195 @@
package common
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"strings"
)
// FileChangesMarker identifies the start of a file changes section in output
const FileChangesMarker = "__CREATE_CODING_FEATURE_FILE_CHANGES__"
const (
// MaxFileSize is the maximum size of a file that can be created (10MB)
MaxFileSize = 10 * 1024 * 1024
)
// FileChange represents a single file change operation to be performed
type FileChange struct {
Operation string `json:"operation"` // "create" or "update"
Path string `json:"path"` // Relative path from project root
Content string `json:"content"` // New file content
}
// ParseFileChanges extracts and parses the file change marker section from LLM output
func ParseFileChanges(output string) (changeSummary string, changes []FileChange, err error) {
fileChangesStart := strings.Index(output, FileChangesMarker)
if fileChangesStart == -1 {
return output, nil, nil // No file changes section found
}
changeSummary = output[:fileChangesStart] // Everything before the marker
// Extract the JSON part
jsonStart := fileChangesStart + len(FileChangesMarker)
// Find the first [ after the file changes marker
jsonArrayStart := strings.Index(output[jsonStart:], "[")
if jsonArrayStart == -1 {
return output, nil, fmt.Errorf("invalid %s format: no JSON array found", FileChangesMarker)
}
jsonStart += jsonArrayStart
// Find the matching closing bracket for the array with proper bracket counting
bracketCount := 0
jsonEnd := jsonStart
for i := jsonStart; i < len(output); i++ {
if output[i] == '[' {
bracketCount++
} else if output[i] == ']' {
bracketCount--
if bracketCount == 0 {
jsonEnd = i + 1
break
}
}
}
if bracketCount != 0 {
return output, nil, fmt.Errorf("invalid %s format: unbalanced brackets", FileChangesMarker)
}
// Extract the JSON string and fix escape sequences
jsonStr := output[jsonStart:jsonEnd]
// Fix specific invalid escape sequences
// First try with the common \C issue
jsonStr = strings.Replace(jsonStr, `\C`, `\\C`, -1)
// Parse the JSON
var fileChanges []FileChange
err = json.Unmarshal([]byte(jsonStr), &fileChanges)
if err != nil {
// If still failing, try a more comprehensive fix
jsonStr = fixInvalidEscapes(jsonStr)
err = json.Unmarshal([]byte(jsonStr), &fileChanges)
if err != nil {
return changeSummary, nil, fmt.Errorf("failed to parse %s JSON: %w", FileChangesMarker, err)
}
}
// Validate file changes
for i, change := range fileChanges {
// Validate operation
if change.Operation != "create" && change.Operation != "update" {
return changeSummary, nil, fmt.Errorf("invalid operation for file change %d: %s", i, change.Operation)
}
// Validate path
if change.Path == "" {
return changeSummary, nil, fmt.Errorf("empty path for file change %d", i)
}
// Check for suspicious paths (directory traversal)
if strings.Contains(change.Path, "..") {
return changeSummary, nil, fmt.Errorf("suspicious path for file change %d: %s", i, change.Path)
}
// Check file size
if len(change.Content) > MaxFileSize {
return changeSummary, nil, fmt.Errorf("file content too large for file change %d: %d bytes", i, len(change.Content))
}
}
return changeSummary, fileChanges, nil
}
// fixInvalidEscapes replaces invalid escape sequences in JSON strings
func fixInvalidEscapes(jsonStr string) string {
validEscapes := []byte{'b', 'f', 'n', 'r', 't', '\\', '/', '"', 'u'}
var result strings.Builder
inQuotes := false
i := 0
for i < len(jsonStr) {
ch := jsonStr[i]
// Track whether we're inside a JSON string
if ch == '"' && (i == 0 || jsonStr[i-1] != '\\') {
inQuotes = !inQuotes
}
// Handle actual control characters inside string literals
if inQuotes {
// Convert literal control characters to proper JSON escape sequences
if ch == '\n' {
result.WriteString("\\n")
i++
continue
} else if ch == '\r' {
result.WriteString("\\r")
i++
continue
} else if ch == '\t' {
result.WriteString("\\t")
i++
continue
} else if ch < 32 {
// Handle other control characters
fmt.Fprintf(&result, "\\u%04x", ch)
i++
continue
}
}
// Check for escape sequences only inside strings
if inQuotes && ch == '\\' && i+1 < len(jsonStr) {
nextChar := jsonStr[i+1]
isValid := false
for _, validEscape := range validEscapes {
if nextChar == validEscape {
isValid = true
break
}
}
if !isValid {
// Invalid escape sequence - add an extra backslash
result.WriteByte('\\')
result.WriteByte('\\')
i++
continue
}
}
result.WriteByte(ch)
i++
}
return result.String()
}
// ApplyFileChanges applies the parsed file changes to the file system
func ApplyFileChanges(projectRoot string, changes []FileChange) error {
for i, change := range changes {
// Get the absolute path
absPath := filepath.Join(projectRoot, change.Path)
// Create directories if necessary
dir := filepath.Dir(absPath)
if err := os.MkdirAll(dir, 0755); err != nil {
return fmt.Errorf("failed to create directory %s for file change %d: %w", dir, i, err)
}
// Write the file
if err := os.WriteFile(absPath, []byte(change.Content), 0644); err != nil {
return fmt.Errorf("failed to write file %s for file change %d: %w", absPath, i, err)
}
fmt.Printf("Applied %s operation to %s\n", change.Operation, change.Path)
}
return nil
}

185
common/file_manager_test.go Normal file
View File

@@ -0,0 +1,185 @@
package common
import (
"os"
"path/filepath"
"testing"
)
func TestParseFileChanges(t *testing.T) {
tests := []struct {
name string
input string
want int // number of expected file changes
wantErr bool
}{
{
name: "No " + FileChangesMarker + " section",
input: "This is a normal response with no file changes.",
want: 0,
wantErr: false,
},
{
name: "Valid " + FileChangesMarker + " section",
input: `Some text before.
` + FileChangesMarker + `
[
{
"operation": "create",
"path": "test.txt",
"content": "Hello, World!"
},
{
"operation": "update",
"path": "other.txt",
"content": "Updated content"
}
]
Some text after.`,
want: 2,
wantErr: false,
},
{
name: "Invalid JSON in " + FileChangesMarker + " section",
input: `Some text before.
` + FileChangesMarker + `
[
{
"operation": "create",
"path": "test.txt",
"content": "Hello, World!"
},
{
"operation": "invalid",
"path": "other.txt"
"content": "Updated content"
}
]`,
want: 0,
wantErr: true,
},
{
name: "Invalid operation",
input: `Some text before.
` + FileChangesMarker + `
[
{
"operation": "delete",
"path": "test.txt",
"content": ""
}
]`,
want: 0,
wantErr: true,
},
{
name: "Empty path",
input: `Some text before.
` + FileChangesMarker + `
[
{
"operation": "create",
"path": "",
"content": "Hello, World!"
}
]`,
want: 0,
wantErr: true,
},
{
name: "Suspicious path with directory traversal",
input: `Some text before.
` + FileChangesMarker + `
[
{
"operation": "create",
"path": "../etc/passwd",
"content": "Hello, World!"
}
]`,
want: 0,
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
_, got, err := ParseFileChanges(tt.input)
if (err != nil) != tt.wantErr {
t.Errorf("ParseFileChanges() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !tt.wantErr && len(got) != tt.want {
t.Errorf("ParseFileChanges() got %d file changes, want %d", len(got), tt.want)
}
})
}
}
func TestApplyFileChanges(t *testing.T) {
// Create a temporary directory for testing
// Create a temporary directory for testing
tempDir, err := os.MkdirTemp("", "file-manager-test")
if err != nil {
t.Fatalf("Failed to create temp dir: %v", err)
}
defer os.RemoveAll(tempDir)
// Test file changes
changes := []FileChange{
{
Operation: "create",
Path: "test.txt",
Content: "Hello, World!",
},
{
Operation: "create",
Path: "subdir/nested.txt",
Content: "Nested content",
},
}
// Apply the changes
if err := ApplyFileChanges(tempDir, changes); err != nil {
t.Fatalf("ApplyFileChanges() error = %v", err)
}
// Verify the first file was created correctly
content, err := os.ReadFile(filepath.Join(tempDir, "test.txt"))
if err != nil {
t.Fatalf("Failed to read created file: %v", err)
}
if string(content) != "Hello, World!" {
t.Errorf("File content = %q, want %q", string(content), "Hello, World!")
}
// Verify the nested file was created correctly
content, err = os.ReadFile(filepath.Join(tempDir, "subdir/nested.txt"))
if err != nil {
t.Fatalf("Failed to read created nested file: %v", err)
}
if string(content) != "Nested content" {
t.Errorf("Nested file content = %q, want %q", string(content), "Nested content")
}
// Test updating a file
updateChanges := []FileChange{
{
Operation: "update",
Path: "test.txt",
Content: "Updated content",
},
}
// Apply the update
if err := ApplyFileChanges(tempDir, updateChanges); err != nil {
t.Fatalf("ApplyFileChanges() error = %v", err)
}
// Verify the file was updated correctly
content, err = os.ReadFile(filepath.Join(tempDir, "test.txt"))
if err != nil {
t.Fatalf("Failed to read updated file: %v", err)
}
if string(content) != "Updated content" {
t.Errorf("Updated file content = %q, want %q", string(content), "Updated content")
}
}

182
common/groups_items.go Normal file
View File

@@ -0,0 +1,182 @@
package common
import (
"fmt"
"sort"
"strings"
"github.com/samber/lo"
)
func NewGroupsItemsSelector[I any](selectionLabel string,
getItemLabel func(I) string) *GroupsItemsSelector[I] {
return &GroupsItemsSelector[I]{SelectionLabel: selectionLabel,
GetItemKey: getItemLabel,
GroupsItems: make([]*GroupItems[I], 0),
}
}
type GroupItems[I any] struct {
Group string
Items []I
}
func (o *GroupItems[I]) Count() int {
return len(o.Items)
}
func (o *GroupItems[I]) ContainsItemBy(predicate func(item I) bool) (ret bool) {
ret = lo.ContainsBy(o.Items, predicate)
return
}
type GroupsItemsSelector[I any] struct {
SelectionLabel string
GetItemKey func(I) string
GroupsItems []*GroupItems[I]
}
func (o *GroupsItemsSelector[I]) AddGroupItems(group string, items ...I) {
o.GroupsItems = append(o.GroupsItems, &GroupItems[I]{group, items})
}
// getSortedGroupsItems returns a new slice of GroupItems with both groups and their items
// sorted alphabetically in a case-insensitive manner. The original GroupsItems are not modified.
func (o *GroupsItemsSelector[I]) getSortedGroupsItems() []*GroupItems[I] {
// Copy and sort groups (caseinsensitive)
sortedGroupsItems := make([]*GroupItems[I], len(o.GroupsItems))
copy(sortedGroupsItems, o.GroupsItems)
sort.SliceStable(sortedGroupsItems, func(i, j int) bool {
return strings.ToLower(sortedGroupsItems[i].Group) < strings.ToLower(sortedGroupsItems[j].Group)
})
// For each group, sort its items
for i, groupItems := range sortedGroupsItems {
sortedItems := make([]I, len(groupItems.Items))
copy(sortedItems, groupItems.Items)
sort.SliceStable(sortedItems, func(i, j int) bool {
return strings.ToLower(o.GetItemKey(sortedItems[i])) < strings.ToLower(o.GetItemKey(sortedItems[j]))
})
// Create a new GroupItems with the sorted items
sortedGroupsItems[i] = &GroupItems[I]{
Group: groupItems.Group,
Items: sortedItems,
}
}
return sortedGroupsItems
}
func (o *GroupsItemsSelector[I]) GetGroupAndItemByItemNumber(number int) (group string, item I, err error) {
var currentItemNumber int
found := false
sortedGroupsItems := o.getSortedGroupsItems()
for _, groupItems := range sortedGroupsItems {
if currentItemNumber+len(groupItems.Items) < number {
currentItemNumber += len(groupItems.Items)
continue
}
for _, groupItem := range groupItems.Items {
currentItemNumber++
if currentItemNumber == number {
group = groupItems.Group
item = groupItem
found = true
break
}
}
if found {
break
}
}
if !found {
err = fmt.Errorf("number %d is out of range", number)
}
return
}
func (o *GroupsItemsSelector[I]) Print(shellCompleteList bool) {
// Only print the section header if not in plain output mode
if !shellCompleteList {
fmt.Printf("\n%v:\n", o.SelectionLabel)
}
var currentItemIndex int
sortedGroupsItems := o.getSortedGroupsItems()
for _, groupItems := range sortedGroupsItems {
if !shellCompleteList {
fmt.Println()
fmt.Printf("%s\n\n", groupItems.Group)
}
for _, item := range groupItems.Items {
currentItemIndex++
if shellCompleteList {
// plain mode: "index key"
fmt.Printf("%s\n", o.GetItemKey(item))
} else {
// formatted mode: "[index] key"
fmt.Printf("\t[%d]\t%s\n", currentItemIndex, o.GetItemKey(item))
}
}
}
}
func (o *GroupsItemsSelector[I]) HasGroup(group string) (ret bool) {
for _, groupItems := range o.GroupsItems {
if ret = groupItems.Group == group; ret {
break
}
}
return
}
func (o *GroupsItemsSelector[I]) FindGroupsByItemFirst(item I) (ret string) {
itemKey := o.GetItemKey(item)
for _, groupItems := range o.GroupsItems {
if groupItems.ContainsItemBy(func(groupItem I) bool {
groupItemKey := o.GetItemKey(groupItem)
return groupItemKey == itemKey
}) {
ret = groupItems.Group
break
}
}
return
}
func (o *GroupsItemsSelector[I]) FindGroupsByItem(item I) (groups []string) {
itemKey := o.GetItemKey(item)
for _, groupItems := range o.GroupsItems {
if groupItems.ContainsItemBy(func(groupItem I) bool {
groupItemKey := o.GetItemKey(groupItem)
return groupItemKey == itemKey
}) {
groups = append(groups, groupItems.Group)
}
}
return
}
func ReturnItem(item string) string {
return item
}
func NewGroupsItemsSelectorString(selectionLabel string) *GroupsItemsSelectorString {
return &GroupsItemsSelectorString{GroupsItemsSelector: NewGroupsItemsSelector(selectionLabel, ReturnItem)}
}
type GroupsItemsSelectorString struct {
*GroupsItemsSelector[string]
}

124
common/oauth_storage.go Normal file
View File

@@ -0,0 +1,124 @@
package common
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"time"
)
// OAuthToken represents stored OAuth token information
type OAuthToken struct {
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"`
ExpiresAt int64 `json:"expires_at"`
TokenType string `json:"token_type"`
Scope string `json:"scope"`
}
// IsExpired checks if the token is expired or will expire within the buffer time
func (t *OAuthToken) IsExpired(bufferMinutes int) bool {
if t.ExpiresAt == 0 {
return true
}
bufferTime := time.Duration(bufferMinutes) * time.Minute
return time.Now().Add(bufferTime).Unix() >= t.ExpiresAt
}
// OAuthStorage handles persistent storage of OAuth tokens
type OAuthStorage struct {
configDir string
}
// NewOAuthStorage creates a new OAuth storage instance
func NewOAuthStorage() (*OAuthStorage, error) {
homeDir, err := os.UserHomeDir()
if err != nil {
return nil, fmt.Errorf("failed to get user home directory: %w", err)
}
configDir := filepath.Join(homeDir, ".config", "fabric")
// Ensure config directory exists
if err := os.MkdirAll(configDir, 0755); err != nil {
return nil, fmt.Errorf("failed to create config directory: %w", err)
}
return &OAuthStorage{configDir: configDir}, nil
}
// GetTokenPath returns the file path for a provider's OAuth token
func (s *OAuthStorage) GetTokenPath(provider string) string {
return filepath.Join(s.configDir, fmt.Sprintf(".%s_oauth", provider))
}
// SaveToken saves an OAuth token to disk with proper permissions
func (s *OAuthStorage) SaveToken(provider string, token *OAuthToken) error {
tokenPath := s.GetTokenPath(provider)
// Marshal token to JSON
data, err := json.MarshalIndent(token, "", " ")
if err != nil {
return fmt.Errorf("failed to marshal token: %w", err)
}
// Write to temporary file first for atomic operation
tempPath := tokenPath + ".tmp"
if err := os.WriteFile(tempPath, data, 0600); err != nil {
return fmt.Errorf("failed to write token file: %w", err)
}
// Atomic rename
if err := os.Rename(tempPath, tokenPath); err != nil {
os.Remove(tempPath) // Clean up temp file
return fmt.Errorf("failed to save token file: %w", err)
}
return nil
}
// LoadToken loads an OAuth token from disk
func (s *OAuthStorage) LoadToken(provider string) (*OAuthToken, error) {
tokenPath := s.GetTokenPath(provider)
// Check if file exists
if _, err := os.Stat(tokenPath); os.IsNotExist(err) {
return nil, nil // No token stored
}
// Read token file
data, err := os.ReadFile(tokenPath)
if err != nil {
return nil, fmt.Errorf("failed to read token file: %w", err)
}
// Unmarshal token
var token OAuthToken
if err := json.Unmarshal(data, &token); err != nil {
return nil, fmt.Errorf("failed to parse token file: %w", err)
}
return &token, nil
}
// DeleteToken removes a stored OAuth token
func (s *OAuthStorage) DeleteToken(provider string) error {
tokenPath := s.GetTokenPath(provider)
if err := os.Remove(tokenPath); err != nil && !os.IsNotExist(err) {
return fmt.Errorf("failed to delete token file: %w", err)
}
return nil
}
// HasValidToken checks if a valid (non-expired) token exists for a provider
func (s *OAuthStorage) HasValidToken(provider string, bufferMinutes int) bool {
token, err := s.LoadToken(provider)
if err != nil || token == nil {
return false
}
return !token.IsExpired(bufferMinutes)
}

View File

@@ -0,0 +1,232 @@
package common
import (
"os"
"path/filepath"
"testing"
"time"
)
func TestOAuthToken_IsExpired(t *testing.T) {
tests := []struct {
name string
expiresAt int64
bufferMinutes int
expected bool
}{
{
name: "token not expired",
expiresAt: time.Now().Unix() + 3600, // 1 hour from now
bufferMinutes: 5,
expected: false,
},
{
name: "token expired",
expiresAt: time.Now().Unix() - 3600, // 1 hour ago
bufferMinutes: 5,
expected: true,
},
{
name: "token expires within buffer",
expiresAt: time.Now().Unix() + 120, // 2 minutes from now
bufferMinutes: 5,
expected: true,
},
{
name: "zero expiry time",
expiresAt: 0,
bufferMinutes: 5,
expected: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
token := &OAuthToken{ExpiresAt: tt.expiresAt}
if got := token.IsExpired(tt.bufferMinutes); got != tt.expected {
t.Errorf("IsExpired() = %v, want %v", got, tt.expected)
}
})
}
}
func TestOAuthStorage_SaveAndLoadToken(t *testing.T) {
// Create temporary directory for testing
tempDir, err := os.MkdirTemp("", "fabric_oauth_test")
if err != nil {
t.Fatalf("Failed to create temp dir: %v", err)
}
defer os.RemoveAll(tempDir)
// Create storage with custom config dir
storage := &OAuthStorage{configDir: tempDir}
// Test token
token := &OAuthToken{
AccessToken: "test_access_token",
RefreshToken: "test_refresh_token",
ExpiresAt: time.Now().Unix() + 3600,
TokenType: "Bearer",
Scope: "test_scope",
}
// Test saving token
err = storage.SaveToken("test_provider", token)
if err != nil {
t.Fatalf("Failed to save token: %v", err)
}
// Verify file exists and has correct permissions
tokenPath := storage.GetTokenPath("test_provider")
info, err := os.Stat(tokenPath)
if err != nil {
t.Fatalf("Token file not created: %v", err)
}
if info.Mode().Perm() != 0600 {
t.Errorf("Token file has wrong permissions: %v, want 0600", info.Mode().Perm())
}
// Test loading token
loadedToken, err := storage.LoadToken("test_provider")
if err != nil {
t.Fatalf("Failed to load token: %v", err)
}
if loadedToken == nil {
t.Fatal("Loaded token is nil")
}
// Verify token data
if loadedToken.AccessToken != token.AccessToken {
t.Errorf("AccessToken mismatch: got %v, want %v", loadedToken.AccessToken, token.AccessToken)
}
if loadedToken.RefreshToken != token.RefreshToken {
t.Errorf("RefreshToken mismatch: got %v, want %v", loadedToken.RefreshToken, token.RefreshToken)
}
if loadedToken.ExpiresAt != token.ExpiresAt {
t.Errorf("ExpiresAt mismatch: got %v, want %v", loadedToken.ExpiresAt, token.ExpiresAt)
}
}
func TestOAuthStorage_LoadNonExistentToken(t *testing.T) {
// Create temporary directory for testing
tempDir, err := os.MkdirTemp("", "fabric_oauth_test")
if err != nil {
t.Fatalf("Failed to create temp dir: %v", err)
}
defer os.RemoveAll(tempDir)
storage := &OAuthStorage{configDir: tempDir}
// Try to load non-existent token
token, err := storage.LoadToken("nonexistent")
if err != nil {
t.Fatalf("Unexpected error loading non-existent token: %v", err)
}
if token != nil {
t.Error("Expected nil token for non-existent provider")
}
}
func TestOAuthStorage_DeleteToken(t *testing.T) {
// Create temporary directory for testing
tempDir, err := os.MkdirTemp("", "fabric_oauth_test")
if err != nil {
t.Fatalf("Failed to create temp dir: %v", err)
}
defer os.RemoveAll(tempDir)
storage := &OAuthStorage{configDir: tempDir}
// Create and save a token
token := &OAuthToken{
AccessToken: "test_token",
RefreshToken: "test_refresh",
ExpiresAt: time.Now().Unix() + 3600,
}
err = storage.SaveToken("test_provider", token)
if err != nil {
t.Fatalf("Failed to save token: %v", err)
}
// Verify token exists
tokenPath := storage.GetTokenPath("test_provider")
if _, err := os.Stat(tokenPath); os.IsNotExist(err) {
t.Fatal("Token file should exist before deletion")
}
// Delete token
err = storage.DeleteToken("test_provider")
if err != nil {
t.Fatalf("Failed to delete token: %v", err)
}
// Verify token is deleted
if _, err := os.Stat(tokenPath); !os.IsNotExist(err) {
t.Error("Token file should not exist after deletion")
}
// Test deleting non-existent token (should not error)
err = storage.DeleteToken("nonexistent")
if err != nil {
t.Errorf("Deleting non-existent token should not error: %v", err)
}
}
func TestOAuthStorage_HasValidToken(t *testing.T) {
// Create temporary directory for testing
tempDir, err := os.MkdirTemp("", "fabric_oauth_test")
if err != nil {
t.Fatalf("Failed to create temp dir: %v", err)
}
defer os.RemoveAll(tempDir)
storage := &OAuthStorage{configDir: tempDir}
// Test with no token
if storage.HasValidToken("test_provider", 5) {
t.Error("Should return false when no token exists")
}
// Save valid token
validToken := &OAuthToken{
AccessToken: "valid_token",
RefreshToken: "refresh_token",
ExpiresAt: time.Now().Unix() + 3600, // 1 hour from now
}
err = storage.SaveToken("test_provider", validToken)
if err != nil {
t.Fatalf("Failed to save valid token: %v", err)
}
// Test with valid token
if !storage.HasValidToken("test_provider", 5) {
t.Error("Should return true for valid token")
}
// Save expired token
expiredToken := &OAuthToken{
AccessToken: "expired_token",
RefreshToken: "refresh_token",
ExpiresAt: time.Now().Unix() - 3600, // 1 hour ago
}
err = storage.SaveToken("expired_provider", expiredToken)
if err != nil {
t.Fatalf("Failed to save expired token: %v", err)
}
// Test with expired token
if storage.HasValidToken("expired_provider", 5) {
t.Error("Should return false for expired token")
}
}
func TestOAuthStorage_GetTokenPath(t *testing.T) {
storage := &OAuthStorage{configDir: "/test/config"}
expected := filepath.Join("/test/config", ".test_provider_oauth")
actual := storage.GetTokenPath("test_provider")
if actual != expected {
t.Errorf("GetTokenPath() = %v, want %v", actual, expected)
}
}

73
common/utils.go Normal file
View File

@@ -0,0 +1,73 @@
package common
import (
"errors"
"fmt"
"os"
"path/filepath"
"runtime"
"strings"
)
// GetAbsolutePath resolves a given path to its absolute form, handling ~, ./, ../, UNC paths, and symlinks.
func GetAbsolutePath(path string) (string, error) {
if path == "" {
return "", errors.New("path is empty")
}
// Handle UNC paths on Windows
if runtime.GOOS == "windows" && strings.HasPrefix(path, `\\`) {
return path, nil
}
// Handle ~ for home directory expansion
if strings.HasPrefix(path, "~") {
home, err := os.UserHomeDir()
if err != nil {
return "", errors.New("could not resolve home directory")
}
path = filepath.Join(home, path[1:])
}
// Convert to absolute path
absPath, err := filepath.Abs(path)
if err != nil {
return "", errors.New("could not get absolute path")
}
// Resolve symlinks, but allow non-existent paths
resolvedPath, err := filepath.EvalSymlinks(absPath)
if err == nil {
return resolvedPath, nil
}
if os.IsNotExist(err) {
// Return the absolute path for non-existent paths
return absPath, nil
}
return "", fmt.Errorf("could not resolve symlinks: %w", err)
}
// Helper function to check if a symlink points to a directory
func IsSymlinkToDir(path string) bool {
fileInfo, err := os.Lstat(path)
if err != nil {
return false
}
if fileInfo.Mode()&os.ModeSymlink != 0 {
resolvedPath, err := filepath.EvalSymlinks(path)
if err != nil {
return false
}
fileInfo, err = os.Stat(resolvedPath)
if err != nil {
return false
}
return fileInfo.IsDir()
}
return false // Regular directories should not be treated as symlinks
}

118
completions/_fabric Normal file
View File

@@ -0,0 +1,118 @@
#compdef fabric
# Zsh completion for fabric CLI
# Place this file in a directory in your $fpath (e.g. /usr/local/share/zsh/site-functions)
_fabric_patterns() {
local -a patterns
patterns=(${(f)"$(fabric --listpatterns --shell-complete-list 2>/dev/null)"})
compadd -X "Patterns:" ${patterns}
}
_fabric_models() {
local -a models
models=(${(f)"$(fabric --listmodels --shell-complete-list 2>/dev/null)"})
compadd -X "Models:" ${models}
}
_fabric_contexts() {
local -a contexts
contexts=(${(f)"$(fabric --listcontexts --shell-complete-list 2>/dev/null)"})
compadd -X "Contexts:" ${contexts}
}
_fabric_sessions() {
local -a sessions
sessions=(${(f)"$(fabric --listsessions --shell-complete-list 2>/dev/null)"})
compadd -X "Sessions:" ${sessions}
}
_fabric_strategies() {
local -a strategies
strategies=(${(f)"$(fabric --liststrategies --shell-complete-list 2>/dev/null)"})
compadd -X "Strategies:" ${strategies}
}
_fabric_extensions() {
local -a extensions
extensions=(${(f)"$(fabric --listextensions --shell-complete-list 2>/dev/null)"})
compadd -X "Extensions:" ${extensions}
'(-L --listmodels)'{-L,--listmodels}'[List all available models]:list models:_fabric_models' \
'(-x --listcontexts)'{-x,--listcontexts}'[List all contexts]:list contexts:_fabric_contexts' \
'(-X --listsessions)'{-X,--listsessions}'[List all sessions]:list sessions:_fabric_sessions' \
'(--listextensions)--listextensions[List all registered extensions]' \
'(--liststrategies)--liststrategies[List all strategies]:list strategies:_fabric_strategies' \
'(--listvendors)--listvendors[List all vendors]' \
vendors=(${(f)"$(fabric --listvendors 2>/dev/null)"})
compadd -X "Vendors:" ${vendors}
}
_fabric() {
local curcontext="$curcontext" state line
typeset -A opt_args
_arguments -C \
'(-p --pattern)'{-p,--pattern}'[Choose a pattern from the available patterns]:pattern:_fabric_patterns' \
'(-v --variable)'{-v,--variable}'[Values for pattern variables, e.g. -v=#role:expert -v=#points:30]:variable:' \
'(-C --context)'{-C,--context}'[Choose a context from the available contexts]:context:_fabric_contexts' \
'(--session)--session[Choose a session from the available sessions]:session:_fabric_sessions' \
'(-a --attachment)'{-a,--attachment}'[Attachment path or URL (e.g. for OpenAI image recognition messages)]:file:_files' \
'(-S --setup)'{-S,--setup}'[Run setup for all reconfigurable parts of fabric]' \
'(-t --temperature)'{-t,--temperature}'[Set temperature (default: 0.7)]:temperature:' \
'(-T --topp)'{-T,--topp}'[Set top P (default: 0.9)]:topp:' \
'(-s --stream)'{-s,--stream}'[Stream]' \
'(-P --presencepenalty)'{-P,--presencepenalty}'[Set presence penalty (default: 0.0)]:presence penalty:' \
'(-r --raw)'{-r,--raw}'[Use the defaults of the model without sending chat options]' \
'(-F --frequencypenalty)'{-F,--frequencypenalty}'[Set frequency penalty (default: 0.0)]:frequency penalty:' \
'(-l --listpatterns)'{-l,--listpatterns}'[List all patterns]' \
'(-L --listmodels)'{-L,--listmodels}'[List all available models]' \
'(-x --listcontexts)'{-x,--listcontexts}'[List all contexts]' \
'(-X --listsessions)'{-X,--listsessions}'[List all sessions]' \
'(-U --updatepatterns)'{-U,--updatepatterns}'[Update patterns]' \
'(-c --copy)'{-c,--copy}'[Copy to clipboard]' \
'(-m --model)'{-m,--model}'[Choose model]:model:_fabric_models' \
'(--modelContextLength)--modelContextLength[Model context length (only affects ollama)]:length:' \
'(-o --output)'{-o,--output}'[Output to file]:file:_files' \
'(--output-session)--output-session[Output the entire session to the output file]' \
'(-n --latest)'{-n,--latest}'[Number of latest patterns to list (default: 0)]:number:' \
'(-d --changeDefaultModel)'{-d,--changeDefaultModel}'[Change default model]' \
'(-y --youtube)'{-y,--youtube}'[YouTube video or play list URL]:youtube url:' \
'(--playlist)--playlist[Prefer playlist over video if both ids are present in the URL]' \
'(--transcript)--transcript[Grab transcript from YouTube video and send to chat]' \
'(--transcript-with-timestamps)--transcript-with-timestamps[Grab transcript from YouTube video with timestamps]' \
'(--comments)--comments[Grab comments from YouTube video and send to chat]' \
'(--metadata)--metadata[Output video metadata]' \
'(-g --language)'{-g,--language}'[Specify the Language Code for the chat, e.g. -g=en -g=zh]:language:' \
'(-u --scrape_url)'{-u,--scrape_url}'[Scrape website URL to markdown using Jina AI]:url:' \
'(-q --scrape_question)'{-q,--scrape_question}'[Search question using Jina AI]:question:' \
'(-e --seed)'{-e,--seed}'[Seed to be used for LMM generation]:seed:' \
'(-w --wipecontext)'{-w,--wipecontext}'[Wipe context]:context:_fabric_contexts' \
'(-W --wipesession)'{-W,--wipesession}'[Wipe session]:session:_fabric_sessions' \
'(--printcontext)--printcontext[Print context]:context:_fabric_contexts' \
'(--printsession)--printsession[Print session]:session:_fabric_sessions' \
'(--readability)--readability[Convert HTML input into a clean, readable view]' \
'(--input-has-vars)--input-has-vars[Apply variables to user input]' \
'(--dry-run)--dry-run[Show what would be sent to the model without actually sending it]' \
'(--serve)--serve[Serve the Fabric Rest API]' \
'(--serveOllama)--serveOllama[Serve the Fabric Rest API with ollama endpoints]' \
'(--address)--address[The address to bind the REST API (default: :8080)]:address:' \
'(--api-key)--api-key[API key used to secure server routes]:api-key:' \
'(--config)--config[Path to YAML config file]:config file:_files -g "*.yaml *.yml"' \
'(--version)--version[Print current version]' \
'(--search)--search[Enable web search tool for supported models (Anthropic, OpenAI)]' \
'(--search-location)--search-location[Set location for web search results]:location:' \
'(--image-file)--image-file[Save generated image to specified file path]:image file:_files -g "*.png *.webp *.jpeg *.jpg"' \
'(--image-size)--image-size[Image dimensions]:size:(1024x1024 1536x1024 1024x1536 auto)' \
'(--image-quality)--image-quality[Image quality]:quality:(low medium high auto)' \
'(--image-compression)--image-compression[Compression level 0-100 for JPEG/WebP formats]:compression:' \
'(--image-background)--image-background[Background type]:background:(opaque transparent)' \
'(--listextensions)--listextensions[List all registered extensions]' \
'(--addextension)--addextension[Register a new extension from config file path]:config file:_files -g "*.yaml *.yml"' \
'(--rmextension)--rmextension[Remove a registered extension by name]:extension:_fabric_extensions' \
'(--strategy)--strategy[Choose a strategy from the available strategies]:strategy:_fabric_strategies' \
'(--liststrategies)--liststrategies[List all strategies]' \
'(--listvendors)--listvendors[List all vendors]' \
'(--shell-complete-list)--shell-complete-list[Output raw list without headers/formatting (for shell completion)]' \
'(-h --help)'{-h,--help}'[Show this help message]' \
'*:arguments:'
}
_fabric "$@"

103
completions/fabric.bash Normal file
View File

@@ -0,0 +1,103 @@
# Bash completion for fabric CLI
#
# Installation:
# 1. Place this file in a standard completion directory, e.g.,
# - /etc/bash_completion.d/
# - /usr/local/etc/bash_completion.d/
# - ~/.local/share/bash-completion/completions/
# 2. Or, source it directly in your ~/.bashrc or ~/.bash_profile:
# source /path/to/fabric.bash
_fabric() {
local cur prev words cword
_get_comp_words_by_ref -n : cur prev words cword
# Define all possible options/flags
local opts="--pattern -p --variable -v --context -C --session --attachment -a --setup -S --temperature -t --topp -T --stream -s --presencepenalty -P --raw -r --frequencypenalty -F --listpatterns -l --listmodels -L --listcontexts -x --listsessions -X --updatepatterns -U --copy -c --model -m --modelContextLength --output -o --output-session --latest -n --changeDefaultModel -d --youtube -y --playlist --transcript --transcript-with-timestamps --comments --metadata --language -g --scrape_url -u --scrape_question -q --seed -e --wipecontext -w --wipesession -W --printcontext --printsession --readability --input-has-vars --dry-run --serve --serveOllama --address --api-key --config --search --search-location --image-file --image-size --image-quality --image-compression --image-background --version --listextensions --addextension --rmextension --strategy --liststrategies --listvendors --shell-complete-list --help -h"
# Helper function for dynamic completions
_fabric_get_list() {
fabric "$1" --shell-complete-list 2>/dev/null
}
# Handle completions based on the previous word
case "${prev}" in
-p | --pattern)
COMPREPLY=($(compgen -W "$(_fabric_get_list --listpatterns)" -- "${cur}"))
return 0
;;
-C | --context)
COMPREPLY=($(compgen -W "$(_fabric_get_list --listcontexts)" -- "${cur}"))
return 0
;;
--session)
COMPREPLY=($(compgen -W "$(_fabric_get_list --listsessions)" -- "${cur}"))
return 0
;;
-m | --model)
COMPREPLY=($(compgen -W "$(_fabric_get_list --listmodels)" -- "${cur}"))
return 0
;;
-w | --wipecontext)
COMPREPLY=($(compgen -W "$(_fabric_get_list --listcontexts)" -- "${cur}"))
return 0
;;
-W | --wipesession)
COMPREPLY=($(compgen -W "$(_fabric_get_list --listsessions)" -- "${cur}"))
return 0
;;
--printcontext)
COMPREPLY=($(compgen -W "$(_fabric_get_list --listcontexts)" -- "${cur}"))
return 0
;;
--printsession)
COMPREPLY=($(compgen -W "$(_fabric_get_list --listsessions)" -- "${cur}"))
return 0
;;
--rmextension)
COMPREPLY=($(compgen -W "$(_fabric_get_list --listextensions)" -- "${cur}"))
return 0
;;
--strategy)
COMPREPLY=($(compgen -W "$(_fabric_get_list --liststrategies)" -- "${cur}"))
return 0
;;
# Options requiring file/directory paths
-a | --attachment | -o | --output | --config | --addextension | --image-file)
_filedir
return 0
;;
# Image generation options with specific values
--image-size)
COMPREPLY=($(compgen -W "1024x1024 1536x1024 1024x1536 auto" -- "$cur"))
return 0
;;
--image-quality)
COMPREPLY=($(compgen -W "low medium high auto" -- "$cur"))
return 0
;;
--image-background)
COMPREPLY=($(compgen -W "opaque transparent" -- "$cur"))
return 0
;;
# Options requiring simple arguments (no specific completion logic here)
-v | --variable | -t | --temperature | -T | --topp | -P | --presencepenalty | -F | --frequencypenalty | --modelContextLength | -n | --latest | -y | --youtube | -g | --language | -u | --scrape_url | -q | --scrape_question | -e | --seed | --address | --api-key | --search-location | --image-compression)
# No specific completion suggestions, user types the value
return 0
;;
esac
# If the current word starts with '-', suggest options
if [[ "${cur}" == -* ]]; then
COMPREPLY=($(compgen -W "${opts}" -- "${cur}"))
return 0
fi
# Default: complete files/directories if no other rule matches
# _filedir
# Or provide no completions if it's not an option or argument following a known flag
COMPREPLY=()
}
complete -F _fabric fabric

101
completions/fabric.fish Executable file
View File

@@ -0,0 +1,101 @@
# Fish shell completion for fabric CLI
#
# Installation:
# Copy this file to ~/.config/fish/completions/fabric.fish
# or run:
# mkdir -p ~/.config/fish/completions
# cp completions/fabric.fish ~/.config/fish/completions/
# Helper functions for dynamic completions
function __fabric_get_patterns
fabric --listpatterns --shell-complete-list 2>/dev/null
end
function __fabric_get_models
fabric --listmodels --shell-complete-list 2>/dev/null
end
function __fabric_get_contexts
fabric --listcontexts --shell-complete-list 2>/dev/null
end
function __fabric_get_sessions
fabric --listsessions --shell-complete-list 2>/dev/null
end
function __fabric_get_strategies
fabric --liststrategies --shell-complete-list 2>/dev/null
end
function __fabric_get_extensions
fabric --listextensions --shell-complete-list 2>/dev/null
end
# Main completion function
complete -c fabric -f
# Flag completions with arguments
complete -c fabric -s p -l pattern -d "Choose a pattern from the available patterns" -a "(__fabric_get_patterns)"
complete -c fabric -s v -l variable -d "Values for pattern variables, e.g. -v=#role:expert -v=#points:30"
complete -c fabric -s C -l context -d "Choose a context from the available contexts" -a "(__fabric_get_contexts)"
complete -c fabric -l session -d "Choose a session from the available sessions" -a "(__fabric_get_sessions)"
complete -c fabric -s a -l attachment -d "Attachment path or URL (e.g. for OpenAI image recognition messages)" -r
complete -c fabric -s t -l temperature -d "Set temperature (default: 0.7)"
complete -c fabric -s T -l topp -d "Set top P (default: 0.9)"
complete -c fabric -s P -l presencepenalty -d "Set presence penalty (default: 0.0)"
complete -c fabric -s F -l frequencypenalty -d "Set frequency penalty (default: 0.0)"
complete -c fabric -s m -l model -d "Choose model" -a "(__fabric_get_models)"
complete -c fabric -l modelContextLength -d "Model context length (only affects ollama)"
complete -c fabric -s o -l output -d "Output to file" -r
complete -c fabric -s n -l latest -d "Number of latest patterns to list (default: 0)"
complete -c fabric -s y -l youtube -d "YouTube video or play list URL to grab transcript, comments from it"
complete -c fabric -s g -l language -d "Specify the Language Code for the chat, e.g. -g=en -g=zh"
complete -c fabric -s u -l scrape_url -d "Scrape website URL to markdown using Jina AI"
complete -c fabric -s q -l scrape_question -d "Search question using Jina AI"
complete -c fabric -s e -l seed -d "Seed to be used for LMM generation"
complete -c fabric -s w -l wipecontext -d "Wipe context" -a "(__fabric_get_contexts)"
complete -c fabric -s W -l wipesession -d "Wipe session" -a "(__fabric_get_sessions)"
complete -c fabric -l printcontext -d "Print context" -a "(__fabric_get_contexts)"
complete -c fabric -l printsession -d "Print session" -a "(__fabric_get_sessions)"
complete -c fabric -l address -d "The address to bind the REST API (default: :8080)"
complete -c fabric -l api-key -d "API key used to secure server routes"
complete -c fabric -l config -d "Path to YAML config file" -r -a "*.yaml *.yml"
complete -c fabric -l search-location -d "Set location for web search results (e.g., 'America/Los_Angeles')"
complete -c fabric -l image-file -d "Save generated image to specified file path (e.g., 'output.png')" -r -a "*.png *.webp *.jpeg *.jpg"
complete -c fabric -l image-size -d "Image dimensions: 1024x1024, 1536x1024, 1024x1536, auto (default: auto)" -a "1024x1024 1536x1024 1024x1536 auto"
complete -c fabric -l image-quality -d "Image quality: low, medium, high, auto (default: auto)" -a "low medium high auto"
complete -c fabric -l image-compression -d "Compression level 0-100 for JPEG/WebP formats (default: not set)" -r
complete -c fabric -l image-background -d "Background type: opaque, transparent (default: opaque, only for PNG/WebP)" -a "opaque transparent"
complete -c fabric -l addextension -d "Register a new extension from config file path" -r -a "*.yaml *.yml"
complete -c fabric -l rmextension -d "Remove a registered extension by name" -a "(__fabric_get_extensions)"
complete -c fabric -l strategy -d "Choose a strategy from the available strategies" -a "(__fabric_get_strategies)"
# Boolean flags (no arguments)
complete -c fabric -s S -l setup -d "Run setup for all reconfigurable parts of fabric"
complete -c fabric -s s -l stream -d "Stream"
complete -c fabric -s r -l raw -d "Use the defaults of the model without sending chat options"
complete -c fabric -s l -l listpatterns -d "List all patterns"
complete -c fabric -s L -l listmodels -d "List all available models"
complete -c fabric -s x -l listcontexts -d "List all contexts"
complete -c fabric -s X -l listsessions -d "List all sessions"
complete -c fabric -s U -l updatepatterns -d "Update patterns"
complete -c fabric -s c -l copy -d "Copy to clipboard"
complete -c fabric -l output-session -d "Output the entire session to the output file"
complete -c fabric -s d -l changeDefaultModel -d "Change default model"
complete -c fabric -l playlist -d "Prefer playlist over video if both ids are present in the URL"
complete -c fabric -l transcript -d "Grab transcript from YouTube video and send to chat"
complete -c fabric -l transcript-with-timestamps -d "Grab transcript from YouTube video with timestamps"
complete -c fabric -l comments -d "Grab comments from YouTube video and send to chat"
complete -c fabric -l metadata -d "Output video metadata"
complete -c fabric -l readability -d "Convert HTML input into a clean, readable view"
complete -c fabric -l input-has-vars -d "Apply variables to user input"
complete -c fabric -l dry-run -d "Show what would be sent to the model without actually sending it"
complete -c fabric -l search -d "Enable web search tool for supported models (Anthropic, OpenAI)"
complete -c fabric -l serve -d "Serve the Fabric Rest API"
complete -c fabric -l serveOllama -d "Serve the Fabric Rest API with ollama endpoints"
complete -c fabric -l version -d "Print current version"
complete -c fabric -l listextensions -d "List all registered extensions"
complete -c fabric -l liststrategies -d "List all strategies"
complete -c fabric -l listvendors -d "List all vendors"
complete -c fabric -l shell-complete-list -d "Output raw list without headers/formatting (for shell completion)"
complete -c fabric -s h -l help -d "Show this help message"

View File

@@ -2,30 +2,56 @@ package core
import (
"context"
"errors"
"fmt"
"os"
"strings"
"github.com/danielmiessler/fabric/chat"
"github.com/danielmiessler/fabric/common"
"github.com/danielmiessler/fabric/db"
"github.com/danielmiessler/fabric/vendors"
goopenai "github.com/sashabaranov/go-openai"
"github.com/danielmiessler/fabric/plugins/ai"
"github.com/danielmiessler/fabric/plugins/db/fsdb"
"github.com/danielmiessler/fabric/plugins/strategy"
"github.com/danielmiessler/fabric/plugins/template"
)
const NoSessionPatternUserMessages = "no session, pattern or user messages provided"
type Chatter struct {
db *db.Db
db *fsdb.Db
Stream bool
DryRun bool
model string
vendor vendors.Vendor
model string
modelContextLength int
vendor ai.Vendor
strategy string
}
func (o *Chatter) Send(request *common.ChatRequest, opts *common.ChatOptions) (session *db.Session, err error) {
var chatRequest *Chat
if chatRequest, err = o.NewChat(request); err != nil {
// Send processes a chat request and applies file changes for create_coding_feature pattern
func (o *Chatter) Send(request *common.ChatRequest, opts *common.ChatOptions) (session *fsdb.Session, err error) {
modelToUse := opts.Model
if modelToUse == "" {
modelToUse = o.model
}
if o.vendor.NeedsRawMode(modelToUse) {
opts.Raw = true
}
if session, err = o.BuildSession(request, opts.Raw); err != nil {
return
}
if session, err = chatRequest.BuildChatSession(opts.Raw); err != nil {
vendorMessages := session.GetVendorMessages()
if len(vendorMessages) == 0 {
if session.Name != "" {
err = o.db.Sessions.SaveSession(session)
if err != nil {
return
}
}
err = fmt.Errorf("no messages provided")
return
}
@@ -33,12 +59,16 @@ func (o *Chatter) Send(request *common.ChatRequest, opts *common.ChatOptions) (s
opts.Model = o.model
}
if opts.ModelContextLength == 0 {
opts.ModelContextLength = o.modelContextLength
}
message := ""
if o.Stream {
channel := make(chan string)
go func() {
if streamErr := o.vendor.SendStream(session.Messages, opts, channel); streamErr != nil {
if streamErr := o.vendor.SendStream(session.GetVendorMessages(), opts, channel); streamErr != nil {
channel <- streamErr.Error()
}
}()
@@ -48,7 +78,7 @@ func (o *Chatter) Send(request *common.ChatRequest, opts *common.ChatOptions) (s
fmt.Print(response)
}
} else {
if message, err = o.vendor.Send(context.Background(), session.Messages, opts); err != nil {
if message, err = o.vendor.Send(context.Background(), session.GetVendorMessages(), opts); err != nil {
return
}
}
@@ -56,59 +86,167 @@ func (o *Chatter) Send(request *common.ChatRequest, opts *common.ChatOptions) (s
if message == "" {
session = nil
err = fmt.Errorf("empty response")
return
}
session.Append(&common.Message{Role: goopenai.ChatMessageRoleAssistant, Content: message})
// Process file changes for create_coding_feature pattern
if request.PatternName == "create_coding_feature" {
summary, fileChanges, parseErr := common.ParseFileChanges(message)
if parseErr != nil {
fmt.Printf("Warning: Failed to parse file changes: %v\n", parseErr)
} else if len(fileChanges) > 0 {
projectRoot, err := os.Getwd()
if err != nil {
fmt.Printf("Warning: Failed to get current directory: %v\n", err)
} else {
if applyErr := common.ApplyFileChanges(projectRoot, fileChanges); applyErr != nil {
fmt.Printf("Warning: Failed to apply file changes: %v\n", applyErr)
} else {
fmt.Println("Successfully applied file changes.")
fmt.Printf("You can review the changes with 'git diff' if you're using git.\n\n")
}
}
}
message = summary
}
if chatRequest.Session != nil {
session.Append(&chat.ChatCompletionMessage{Role: chat.ChatMessageRoleAssistant, Content: message})
if session.Name != "" {
err = o.db.Sessions.SaveSession(session)
}
return
}
func (o *Chatter) NewChat(request *common.ChatRequest) (ret *Chat, err error) {
ret = &Chat{
Language: request.Language,
}
if request.ContextName != "" {
var ctx *db.Context
if ctx, err = o.db.Contexts.GetContext(request.ContextName); err != nil {
err = fmt.Errorf("could not find context %s: %v", request.ContextName, err)
return
}
ret.Context = ctx.Content
}
func (o *Chatter) BuildSession(request *common.ChatRequest, raw bool) (session *fsdb.Session, err error) {
if request.SessionName != "" {
var sess *db.Session
if sess, err = o.db.Sessions.GetOrCreateSession(request.SessionName); err != nil {
var sess *fsdb.Session
if sess, err = o.db.Sessions.Get(request.SessionName); err != nil {
err = fmt.Errorf("could not find session %s: %v", request.SessionName, err)
return
}
ret.Session = sess
session = sess
} else {
session = &fsdb.Session{}
}
if request.PatternName != "" {
var pattern *db.Pattern
if pattern, err = o.db.Patterns.GetPattern(request.PatternName, request.PatternVariables); err != nil {
err = fmt.Errorf("could not find pattern %s: %v", request.PatternName, err)
if request.Meta != "" {
session.Append(&chat.ChatCompletionMessage{Role: common.ChatMessageRoleMeta, Content: request.Meta})
}
// if a context name is provided, retrieve it from the database
var contextContent string
if request.ContextName != "" {
var ctx *fsdb.Context
if ctx, err = o.db.Contexts.Get(request.ContextName); err != nil {
err = fmt.Errorf("could not find context %s: %v", request.ContextName, err)
return
}
contextContent = ctx.Content
}
if pattern.Pattern != "" {
ret.Pattern = pattern.Pattern
// Process template variables in message content
// Double curly braces {{variable}} indicate template substitution
// Ensure we have a message before processing
if request.Message == nil {
request.Message = &chat.ChatCompletionMessage{
Role: chat.ChatMessageRoleUser,
Content: " ",
}
}
ret.Message = request.Message
// Now we know request.Message is not nil, process template variables
if request.InputHasVars {
request.Message.Content, err = template.ApplyTemplate(request.Message.Content, request.PatternVariables, "")
if err != nil {
return nil, err
}
}
var patternContent string
inputUsed := false
if request.PatternName != "" {
pattern, err := o.db.Patterns.GetApplyVariables(request.PatternName, request.PatternVariables, request.Message.Content)
if err != nil {
return nil, fmt.Errorf("could not get pattern %s: %v", request.PatternName, err)
}
patternContent = pattern.Pattern
inputUsed = true
}
systemMessage := strings.TrimSpace(contextContent) + strings.TrimSpace(patternContent)
if request.StrategyName != "" {
strategy, err := strategy.LoadStrategy(request.StrategyName)
if err != nil {
return nil, fmt.Errorf("could not load strategy %s: %v", request.StrategyName, err)
}
if strategy != nil && strategy.Prompt != "" {
// prepend the strategy prompt to the system message
systemMessage = fmt.Sprintf("%s\n%s", strategy.Prompt, systemMessage)
}
}
// Apply refined language instruction if specified
if request.Language != "" && request.Language != "en" {
// Refined instruction: Execute pattern using user input, then translate the entire response.
systemMessage = fmt.Sprintf("%s\n\nIMPORTANT: First, execute the instructions provided in this prompt using the user's input. Second, ensure your entire final response, including any section headers or titles generated as part of executing the instructions, is written ONLY in the %s language.", systemMessage, request.Language)
}
if raw {
var finalContent string
if systemMessage != "" {
if request.PatternName != "" {
finalContent = systemMessage
} else {
finalContent = fmt.Sprintf("%s\n\n%s", systemMessage, request.Message.Content)
}
// Handle MultiContent properly in raw mode
if len(request.Message.MultiContent) > 0 {
// When we have attachments, add the text as a text part in MultiContent
newMultiContent := []chat.ChatMessagePart{
{
Type: chat.ChatMessagePartTypeText,
Text: finalContent,
},
}
// Add existing non-text parts (like images)
for _, part := range request.Message.MultiContent {
if part.Type != chat.ChatMessagePartTypeText {
newMultiContent = append(newMultiContent, part)
}
}
request.Message = &chat.ChatCompletionMessage{
Role: chat.ChatMessageRoleUser,
MultiContent: newMultiContent,
}
} else {
// No attachments, use regular Content field
request.Message = &chat.ChatCompletionMessage{
Role: chat.ChatMessageRoleUser,
Content: finalContent,
}
}
}
if request.Message != nil {
session.Append(request.Message)
}
} else {
if systemMessage != "" {
session.Append(&chat.ChatCompletionMessage{Role: chat.ChatMessageRoleSystem, Content: systemMessage})
}
// If multi-part content, it is in the user message, and should be added.
// Otherwise, we should only add it if we have not already used it in the systemMessage.
if len(request.Message.MultiContent) > 0 || (request.Message != nil && !inputUsed) {
session.Append(request.Message)
}
}
if session.IsEmpty() {
session = nil
err = errors.New(NoSessionPatternUserMessages)
}
return
}
type Chat struct {
Context string
Pattern string
Message string
Session *db.Session
Language string
}

View File

@@ -1,21 +0,0 @@
package core
import (
"testing"
)
func TestBuildChatSession(t *testing.T) {
chat := &Chat{
Context: "test context",
Pattern: "test pattern",
Message: "test message",
}
session, err := chat.BuildChatSession(false)
if err != nil {
t.Fatalf("BuildChatSession() error = %v", err)
}
if session == nil {
t.Fatalf("BuildChatSession() returned nil session")
}
}

View File

@@ -1,295 +0,0 @@
package core
import (
"bytes"
"fmt"
"os"
"strconv"
"strings"
"github.com/danielmiessler/fabric/vendors/groq"
"github.com/danielmiessler/fabric/vendors/mistral"
goopenai "github.com/sashabaranov/go-openai"
"github.com/atotto/clipboard"
"github.com/danielmiessler/fabric/common"
"github.com/danielmiessler/fabric/db"
"github.com/danielmiessler/fabric/jina"
"github.com/danielmiessler/fabric/vendors/anthropic"
"github.com/danielmiessler/fabric/vendors/azure"
"github.com/danielmiessler/fabric/vendors/dryrun"
"github.com/danielmiessler/fabric/vendors/gemini"
"github.com/danielmiessler/fabric/vendors/ollama"
"github.com/danielmiessler/fabric/vendors/openai"
"github.com/danielmiessler/fabric/vendors/openrouter"
"github.com/danielmiessler/fabric/vendors/siliconcloud"
"github.com/danielmiessler/fabric/youtube"
"github.com/pkg/errors"
)
const DefaultPatternsGitRepoUrl = "https://github.com/danielmiessler/fabric.git"
const DefaultPatternsGitRepoFolder = "patterns"
const NoSessionPatternUserMessages = "no session, pattern or user messages provided"
func NewFabric(db *db.Db) (ret *Fabric, err error) {
ret = NewFabricBase(db)
err = ret.Configure()
return
}
func NewFabricForSetup(db *db.Db) (ret *Fabric) {
ret = NewFabricBase(db)
_ = ret.Configure()
return
}
// NewFabricBase Create a new Fabric from a list of already configured VendorsController
func NewFabricBase(db *db.Db) (ret *Fabric) {
ret = &Fabric{
VendorsManager: NewVendorsManager(),
Db: db,
VendorsAll: NewVendorsManager(),
PatternsLoader: NewPatternsLoader(db.Patterns),
YouTube: youtube.NewYouTube(),
Jina: jina.NewClient(),
}
label := "Default"
ret.Configurable = &common.Configurable{
Label: label,
EnvNamePrefix: common.BuildEnvVariablePrefix(label),
ConfigureCustom: ret.configure,
}
ret.DefaultVendor = ret.AddSetting("Vendor", true)
ret.DefaultModel = ret.AddSetupQuestionCustom("Model", true,
"Enter the index the name of your default model")
ret.VendorsAll.AddVendors(openai.NewClient(), azure.NewClient(), ollama.NewClient(), groq.NewClient(),
gemini.NewClient(), anthropic.NewClient(), siliconcloud.NewClient(), openrouter.NewClient(), mistral.NewClient(), dryrun.NewClient())
return
}
type Fabric struct {
*common.Configurable
*VendorsManager
VendorsAll *VendorsManager
*PatternsLoader
*youtube.YouTube
Jina *jina.Client
Db *db.Db
DefaultVendor *common.Setting
DefaultModel *common.SetupQuestion
}
type ChannelName struct {
channel chan []string
name string
}
func (o *Fabric) SaveEnvFile() (err error) {
// Now create the .env with all configured VendorsController info
var envFileContent bytes.Buffer
o.Settings.FillEnvFileContent(&envFileContent)
o.PatternsLoader.SetupFillEnvFileContent(&envFileContent)
for _, vendor := range o.Vendors {
vendor.SetupFillEnvFileContent(&envFileContent)
}
o.YouTube.SetupFillEnvFileContent(&envFileContent)
o.Jina.SetupFillEnvFileContent(&envFileContent)
err = o.Db.SaveEnv(envFileContent.String())
return
}
func (o *Fabric) Setup() (err error) {
if err = o.SetupVendors(); err != nil {
return
}
if err = o.SetupDefaultModel(); err != nil {
return
}
_ = o.YouTube.SetupOrSkip()
if err = o.Jina.SetupOrSkip(); err != nil {
return
}
if err = o.PatternsLoader.Setup(); err != nil {
return
}
err = o.SaveEnvFile()
return
}
func (o *Fabric) SetupDefaultModel() (err error) {
vendorsModels := o.GetModels()
vendorsModels.Print()
if err = o.Ask(o.Label); err != nil {
return
}
index, parseErr := strconv.Atoi(o.DefaultModel.Value)
if parseErr == nil {
o.DefaultVendor.Value, o.DefaultModel.Value = vendorsModels.GetVendorAndModelByModelIndex(index)
} else {
o.DefaultVendor.Value = vendorsModels.FindVendorsByModelFirst(o.DefaultModel.Value)
}
//verify
vendorNames := vendorsModels.FindVendorsByModel(o.DefaultModel.Value)
if len(vendorNames) == 0 {
err = errors.Errorf("You need to chose an available default model.")
return
}
fmt.Println()
o.DefaultVendor.Print()
o.DefaultModel.Print()
err = o.SaveEnvFile()
return
}
func (o *Fabric) SetupVendors() (err error) {
o.Models = nil
if o.Vendors, err = o.VendorsAll.Setup(); err != nil {
return
}
if !o.HasVendors() {
err = errors.New("No vendors configured")
return
}
err = o.SaveEnvFile()
return
}
func (o *Fabric) SetupVendor(vendorName string) (err error) {
if err = o.VendorsAll.SetupVendor(vendorName); err != nil {
return
}
err = o.SaveEnvFile()
return
}
// Configure buildClient VendorsController based on the environment variables
func (o *Fabric) configure() (err error) {
for _, vendor := range o.VendorsAll.Vendors {
if vendorErr := vendor.Configure(); vendorErr == nil {
o.AddVendors(vendor)
}
}
if err = o.PatternsLoader.Configure(); err != nil {
return
}
//YouTube and Jina are not mandatory, so ignore not configured error
_ = o.YouTube.Configure()
_ = o.Jina.Configure()
return
}
func (o *Fabric) GetChatter(model string, stream bool, dryRun bool) (ret *Chatter, err error) {
ret = &Chatter{
db: o.Db,
Stream: stream,
DryRun: dryRun,
}
if dryRun {
ret.vendor = dryrun.NewClient()
ret.model = model
if ret.model == "" {
ret.model = o.DefaultModel.Value
}
} else if model == "" {
ret.vendor = o.FindByName(o.DefaultVendor.Value)
ret.model = o.DefaultModel.Value
} else {
ret.vendor = o.FindByName(o.GetModels().FindVendorsByModelFirst(model))
ret.model = model
}
if ret.vendor == nil {
err = fmt.Errorf(
"could not find vendor.\n Model = %s\n DefaultModel = %s\n DefaultVendor = %s",
model, o.DefaultModel.Value, o.DefaultVendor.Value)
return
}
return
}
func (o *Fabric) CopyToClipboard(message string) (err error) {
if err = clipboard.WriteAll(message); err != nil {
err = fmt.Errorf("could not copy to clipboard: %v", err)
}
return
}
func (o *Fabric) CreateOutputFile(message string, fileName string) (err error) {
var file *os.File
if file, err = os.Create(fileName); err != nil {
err = fmt.Errorf("error creating file: %v", err)
return
}
defer file.Close()
if _, err = file.WriteString(message); err != nil {
err = fmt.Errorf("error writing to file: %v", err)
}
return
}
func (o *Chat) BuildChatSession(raw bool) (ret *db.Session, err error) {
// new messages will be appended to the session and used to send the message
if o.Session != nil {
ret = o.Session
} else {
ret = &db.Session{}
}
systemMessage := strings.TrimSpace(o.Context) + strings.TrimSpace(o.Pattern)
if o.Language != "" {
systemMessage = fmt.Sprintf("%s. Please use the language '%s' for the output.", systemMessage, o.Language)
}
userMessage := strings.TrimSpace(o.Message)
if raw {
// use the user role instead of the system role in raw mode
message := systemMessage + userMessage
if message != "" {
ret.Append(&common.Message{Role: goopenai.ChatMessageRoleUser, Content: message})
}
} else {
if systemMessage != "" {
ret.Append(&common.Message{Role: goopenai.ChatMessageRoleSystem, Content: systemMessage})
}
if userMessage != "" {
ret.Append(&common.Message{Role: goopenai.ChatMessageRoleUser, Content: userMessage})
}
}
if ret.IsEmpty() {
ret = nil
err = fmt.Errorf(NoSessionPatternUserMessages)
}
return
}

View File

@@ -1,49 +0,0 @@
package core
import (
"os"
"testing"
"github.com/danielmiessler/fabric/db"
)
func TestNewFabric(t *testing.T) {
_, err := NewFabric(db.NewDb(os.TempDir()))
if err == nil {
t.Fatal("without setup error expected")
}
}
func TestSaveEnvFile(t *testing.T) {
fabric := NewFabricBase(db.NewDb(os.TempDir()))
err := fabric.SaveEnvFile()
if err != nil {
t.Fatalf("SaveEnvFile() error = %v", err)
}
}
func TestCopyToClipboard(t *testing.T) {
t.Skip("skipping test, because of docker env. in ci.")
fabric := NewFabricBase(db.NewDb(os.TempDir()))
message := "test message"
err := fabric.CopyToClipboard(message)
if err != nil {
t.Fatalf("CopyToClipboard() error = %v", err)
}
}
func TestCreateOutputFile(t *testing.T) {
mockDb := &db.Db{}
fabric := NewFabricBase(mockDb)
fileName := "test_output.txt"
message := "test message"
err := fabric.CreateOutputFile(message, fileName)
if err != nil {
t.Fatalf("CreateOutputFile() error = %v", err)
}
defer os.Remove(fileName)
}

View File

@@ -1,97 +0,0 @@
package core
import (
"fmt"
"sort"
)
func NewVendorsModels() *VendorsModels {
return &VendorsModels{VendorsModels: make(map[string][]string)}
}
type VendorsModels struct {
Vendors []string
VendorsModels map[string][]string
Errs []error
}
func (o *VendorsModels) AddVendorModels(vendor string, models []string) {
o.Vendors = append(o.Vendors, vendor)
o.VendorsModels[vendor] = models
}
func (o *VendorsModels) GetVendorAndModelByModelIndex(modelIndex int) (vendor string, model string) {
vendorModelIndexFrom := 0
vendorModelIndexTo := 0
for _, currenVendor := range o.Vendors {
vendorModelIndexFrom = vendorModelIndexTo + 1
vendorModelIndexTo = vendorModelIndexFrom + len(o.VendorsModels[currenVendor]) - 1
if modelIndex >= vendorModelIndexFrom && modelIndex <= vendorModelIndexTo {
vendor = currenVendor
model = o.VendorsModels[currenVendor][modelIndex-vendorModelIndexFrom]
break
}
}
return
}
func (o *VendorsModels) AddError(err error) {
o.Errs = append(o.Errs, err)
}
func (o *VendorsModels) Print() {
fmt.Printf("\nAvailable vendor models:\n")
sort.Strings(o.Vendors)
var currentModelIndex int
for _, vendor := range o.Vendors {
fmt.Println()
fmt.Printf("%s\n", vendor)
fmt.Println()
currentModelIndex = o.PrintVendor(vendor, currentModelIndex)
}
return
}
func (o *VendorsModels) PrintVendor(vendor string, modelIndex int) (currentModelIndex int) {
currentModelIndex = modelIndex
models := o.VendorsModels[vendor]
for _, model := range models {
currentModelIndex++
fmt.Printf("\t[%d]\t%s\n", currentModelIndex, model)
}
fmt.Println()
return
}
func (o *VendorsModels) GetVendorModels(vendor string) (models []string) {
models = o.VendorsModels[vendor]
return
}
func (o *VendorsModels) HasVendor(vendor string) (ret bool) {
ret = o.VendorsModels[vendor] != nil
return
}
func (o *VendorsModels) FindVendorsByModelFirst(model string) (ret string) {
vendors := o.FindVendorsByModel(model)
if len(vendors) > 0 {
ret = vendors[0]
}
return
}
func (o *VendorsModels) FindVendorsByModel(model string) (vendors []string) {
for vendor, models := range o.VendorsModels {
for _, m := range models {
if m == model {
vendors = append(vendors, vendor)
continue
}
}
}
return
}

View File

@@ -1,52 +0,0 @@
package core
import (
"errors"
"testing"
)
func TestNewVendorsModels(t *testing.T) {
vendors := NewVendorsModels()
if vendors == nil {
t.Fatalf("NewVendorsModels() returned nil")
}
if len(vendors.VendorsModels) != 0 {
t.Fatalf("NewVendorsModels() returned non-empty VendorsModels map")
}
}
func TestFindVendorsByModelFirst(t *testing.T) {
vendors := NewVendorsModels()
vendors.AddVendorModels("vendor1", []string{"model1", "model2"})
vendor := vendors.FindVendorsByModelFirst("model1")
if vendor != "vendor1" {
t.Fatalf("FindVendorsByModelFirst() = %v, want %v", vendor, "vendor1")
}
}
func TestFindVendorsByModel(t *testing.T) {
vendors := NewVendorsModels()
vendors.AddVendorModels("vendor1", []string{"model1", "model2"})
foundVendors := vendors.FindVendorsByModel("model1")
if len(foundVendors) != 1 || foundVendors[0] != "vendor1" {
t.Fatalf("FindVendorsByModel() = %v, want %v", foundVendors, []string{"vendor1"})
}
}
func TestAddVendorModels(t *testing.T) {
vendors := NewVendorsModels()
vendors.AddVendorModels("vendor1", []string{"model1", "model2"})
models := vendors.GetVendorModels("vendor1")
if len(models) != 2 {
t.Fatalf("AddVendorModels() failed to add models")
}
}
func TestAddError(t *testing.T) {
vendors := NewVendorsModels()
err := errors.New("sample error")
vendors.AddError(err)
if len(vendors.Errs) != 1 {
t.Fatalf("AddError() failed to add error")
}
}

View File

@@ -1,275 +0,0 @@
package core
import (
"fmt"
"io"
"os"
"path/filepath"
"sort"
"strings"
"github.com/danielmiessler/fabric/common"
"github.com/danielmiessler/fabric/db"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/object"
"github.com/go-git/go-git/v5/storage/memory"
"github.com/otiai10/copy"
)
func NewPatternsLoader(patterns *db.Patterns) (ret *PatternsLoader) {
label := "Patterns Loader"
ret = &PatternsLoader{
Patterns: patterns,
}
ret.Configurable = &common.Configurable{
Label: label,
EnvNamePrefix: common.BuildEnvVariablePrefix(label),
ConfigureCustom: ret.configure,
}
ret.DefaultGitRepoUrl = ret.AddSetupQuestionCustom("Git Repo Url", true,
"Enter the default Git repository URL for the patterns")
ret.DefaultGitRepoUrl.Value = DefaultPatternsGitRepoUrl
ret.DefaultFolder = ret.AddSetupQuestionCustom("Git Repo Patterns Folder", true,
"Enter the default folder in the Git repository where patterns are stored")
ret.DefaultFolder.Value = DefaultPatternsGitRepoFolder
return
}
type PatternsLoader struct {
*common.Configurable
Patterns *db.Patterns
DefaultGitRepoUrl *common.SetupQuestion
DefaultFolder *common.SetupQuestion
pathPatternsPrefix string
tempPatternsFolder string
}
func (o *PatternsLoader) configure() (err error) {
o.pathPatternsPrefix = fmt.Sprintf("%v/", o.DefaultFolder.Value)
o.tempPatternsFolder = filepath.Join(os.TempDir(), o.DefaultFolder.Value)
return
}
// PopulateDB downloads patterns from the internet and populates the patterns folder
func (o *PatternsLoader) PopulateDB() (err error) {
fmt.Printf("Downloading patterns and Populating %s..\n", o.Patterns.Dir)
fmt.Println()
if err = o.gitCloneAndCopy(); err != nil {
return
}
if err = o.movePatterns(); err != nil {
return
}
return
}
// PersistPatterns copies custom patterns to the updated patterns directory
func (o *PatternsLoader) PersistPatterns() (err error) {
var currentPatterns []os.DirEntry
if currentPatterns, err = os.ReadDir(o.Patterns.Dir); err != nil {
return
}
newPatternsFolder := o.tempPatternsFolder
var newPatterns []os.DirEntry
if newPatterns, err = os.ReadDir(newPatternsFolder); err != nil {
return
}
for _, currentPattern := range currentPatterns {
for _, newPattern := range newPatterns {
if currentPattern.Name() == newPattern.Name() {
break
}
copy.Copy(filepath.Join(o.Patterns.Dir, newPattern.Name()), filepath.Join(newPatternsFolder, newPattern.Name()))
}
}
return
}
// movePatterns copies the new patterns into the config directory
func (o *PatternsLoader) movePatterns() (err error) {
os.MkdirAll(o.Patterns.Dir, os.ModePerm)
patternsDir := o.tempPatternsFolder
if err = o.PersistPatterns(); err != nil {
return
}
copy.Copy(patternsDir, o.Patterns.Dir) // copies the patterns to the config directory
err = os.RemoveAll(patternsDir)
return
}
// checks if a pattern already exists in the directory
// func DoesPatternExistAlready(name string) (bool, error) {
// entry := db.Entry{
// Label: name,
// }
// _, err := entry.GetByName()
// if err != nil {
// return false, err
// }
// return true, nil
// }
func (o *PatternsLoader) gitCloneAndCopy() (err error) {
// Clones the given repository, creating the remote, the local branches
// and fetching the objects, everything in memory:
var r *git.Repository
if r, err = git.Clone(memory.NewStorage(), nil, &git.CloneOptions{
URL: o.DefaultGitRepoUrl.Value,
}); err != nil {
fmt.Println(err)
return
}
// ... retrieves the branch pointed by HEAD
var ref *plumbing.Reference
if ref, err = r.Head(); err != nil {
fmt.Println(err)
return
}
// ... retrieves the commit history for /patterns folder
var cIter object.CommitIter
if cIter, err = r.Log(&git.LogOptions{
From: ref.Hash(),
PathFilter: func(path string) bool {
return path == o.DefaultFolder.Value || strings.HasPrefix(path, o.pathPatternsPrefix)
},
}); err != nil {
fmt.Println(err)
return err
}
var changes []db.DirectoryChange
// ... iterates over the commits
if err = cIter.ForEach(func(c *object.Commit) (err error) {
// Get the files changed in this commit by comparing with its parents
parentIter := c.Parents()
if err = parentIter.ForEach(func(parent *object.Commit) (err error) {
var patch *object.Patch
if patch, err = parent.Patch(c); err != nil {
fmt.Println(err)
return
}
for _, fileStat := range patch.Stats() {
if strings.HasPrefix(fileStat.Name, o.pathPatternsPrefix) {
dir := filepath.Dir(fileStat.Name)
changes = append(changes, db.DirectoryChange{Dir: dir, Timestamp: c.Committer.When})
}
}
return
}); err != nil {
fmt.Println(err)
return
}
return
}); err != nil {
fmt.Println(err)
return
}
// Sort changes by timestamp
sort.Slice(changes, func(i, j int) bool {
return changes[i].Timestamp.Before(changes[j].Timestamp)
})
o.makeUniqueList(changes)
var commit *object.Commit
if commit, err = r.CommitObject(ref.Hash()); err != nil {
fmt.Println(err)
return
}
var tree *object.Tree
if tree, err = commit.Tree(); err != nil {
fmt.Println(err)
return
}
if err = tree.Files().ForEach(func(f *object.File) (err error) {
if strings.HasPrefix(f.Name, o.pathPatternsPrefix) {
// Create the local file path
localPath := filepath.Join(os.TempDir(), f.Name)
// Create the directories if they don't exist
if err = os.MkdirAll(filepath.Dir(localPath), os.ModePerm); err != nil {
fmt.Println(err)
return
}
// Write the file to the local filesystem
var blob *object.Blob
if blob, err = r.BlobObject(f.Hash); err != nil {
fmt.Println(err)
return
}
err = o.writeBlobToFile(blob, localPath)
return
}
return
}); err != nil {
fmt.Println(err)
}
return
}
func (o *PatternsLoader) writeBlobToFile(blob *object.Blob, path string) (err error) {
var reader io.ReadCloser
if reader, err = blob.Reader(); err != nil {
return
}
defer reader.Close()
// Create the file
var file *os.File
if file, err = os.Create(path); err != nil {
return
}
defer file.Close()
// Copy the contents of the blob to the file
if _, err = io.Copy(file, reader); err != nil {
return
}
return
}
func (o *PatternsLoader) makeUniqueList(changes []db.DirectoryChange) {
uniqueItems := make(map[string]bool)
for _, change := range changes {
if strings.TrimSpace(change.Dir) != "" && !strings.Contains(change.Dir, "=>") {
pattern := strings.ReplaceAll(change.Dir, o.pathPatternsPrefix, "")
pattern = strings.TrimSpace(pattern)
uniqueItems[pattern] = true
}
}
finalList := make([]string, 0, len(uniqueItems))
for _, change := range changes {
pattern := strings.ReplaceAll(change.Dir, o.pathPatternsPrefix, "")
pattern = strings.TrimSpace(pattern)
if _, exists := uniqueItems[pattern]; exists {
finalList = append(finalList, pattern)
delete(uniqueItems, pattern) // Remove to avoid duplicates in the final list
}
}
joined := strings.Join(finalList, "\n")
os.WriteFile(o.Patterns.UniquePatternsFilePath, []byte(joined), 0o644)
}

325
core/plugin_registry.go Normal file
View File

@@ -0,0 +1,325 @@
package core
import (
"bytes"
"fmt"
"io"
"os"
"path/filepath"
"sort"
"strconv"
"strings"
"github.com/danielmiessler/fabric/plugins/ai/bedrock"
"github.com/danielmiessler/fabric/plugins/ai/exolab"
"github.com/danielmiessler/fabric/plugins/ai/perplexity" // Added Perplexity plugin
"github.com/danielmiessler/fabric/plugins/strategy"
"github.com/samber/lo"
"github.com/danielmiessler/fabric/common"
"github.com/danielmiessler/fabric/plugins"
"github.com/danielmiessler/fabric/plugins/ai"
"github.com/danielmiessler/fabric/plugins/ai/anthropic"
"github.com/danielmiessler/fabric/plugins/ai/azure"
"github.com/danielmiessler/fabric/plugins/ai/dryrun"
"github.com/danielmiessler/fabric/plugins/ai/gemini"
"github.com/danielmiessler/fabric/plugins/ai/lmstudio"
"github.com/danielmiessler/fabric/plugins/ai/ollama"
"github.com/danielmiessler/fabric/plugins/ai/openai"
"github.com/danielmiessler/fabric/plugins/ai/openai_compatible"
"github.com/danielmiessler/fabric/plugins/db/fsdb"
"github.com/danielmiessler/fabric/plugins/template"
"github.com/danielmiessler/fabric/plugins/tools"
"github.com/danielmiessler/fabric/plugins/tools/custom_patterns"
"github.com/danielmiessler/fabric/plugins/tools/jina"
"github.com/danielmiessler/fabric/plugins/tools/lang"
"github.com/danielmiessler/fabric/plugins/tools/youtube"
)
// hasAWSCredentials checks if any AWS credentials are present either in the
// environment variables or in the default/shared credentials file. It doesn't
// attempt to verify the validity of the credentials, but simply ensures that a
// potential authentication source exists so we can safely initialize the
// Bedrock client without causing the AWS SDK to search for credentials.
func hasAWSCredentials() bool {
if os.Getenv("AWS_PROFILE") != "" ||
os.Getenv("AWS_ROLE_SESSION_NAME") != "" ||
(os.Getenv("AWS_ACCESS_KEY_ID") != "" && os.Getenv("AWS_SECRET_ACCESS_KEY") != "") {
return true
}
credFile := os.Getenv("AWS_SHARED_CREDENTIALS_FILE")
if credFile == "" {
if home, err := os.UserHomeDir(); err == nil {
credFile = filepath.Join(home, ".aws", "credentials")
}
}
if credFile != "" {
if _, err := os.Stat(credFile); err == nil {
return true
}
}
return false
}
func NewPluginRegistry(db *fsdb.Db) (ret *PluginRegistry, err error) {
ret = &PluginRegistry{
Db: db,
VendorManager: ai.NewVendorsManager(),
VendorsAll: ai.NewVendorsManager(),
PatternsLoader: tools.NewPatternsLoader(db.Patterns),
CustomPatterns: custom_patterns.NewCustomPatterns(),
YouTube: youtube.NewYouTube(),
Language: lang.NewLanguage(),
Jina: jina.NewClient(),
Strategies: strategy.NewStrategiesManager(),
}
var homedir string
if homedir, err = os.UserHomeDir(); err != nil {
return
}
ret.TemplateExtensions = template.NewExtensionManager(filepath.Join(homedir, ".config/fabric"))
ret.Defaults = tools.NeeDefaults(ret.GetModels)
// Create a vendors slice to hold all vendors (order doesn't matter initially)
vendors := []ai.Vendor{}
// Add non-OpenAI compatible clients
vendors = append(vendors,
openai.NewClient(),
ollama.NewClient(),
azure.NewClient(),
gemini.NewClient(),
anthropic.NewClient(),
lmstudio.NewClient(),
exolab.NewClient(),
perplexity.NewClient(), // Added Perplexity client
)
if hasAWSCredentials() {
vendors = append(vendors, bedrock.NewClient())
}
// Add all OpenAI-compatible providers
for providerName := range openai_compatible.ProviderMap {
provider, _ := openai_compatible.GetProviderByName(providerName)
vendors = append(vendors, openai_compatible.NewClient(provider))
}
// Sort vendors by name for consistent ordering (case-insensitive)
sort.Slice(vendors, func(i, j int) bool {
return strings.ToLower(vendors[i].GetName()) < strings.ToLower(vendors[j].GetName())
})
// Add all sorted vendors to VendorsAll
ret.VendorsAll.AddVendors(vendors...)
_ = ret.Configure()
return
}
func (o *PluginRegistry) ListVendors(out io.Writer) error {
vendors := lo.Map(o.VendorsAll.Vendors, func(vendor ai.Vendor, _ int) string {
return vendor.GetName()
})
fmt.Fprint(out, "Available Vendors:\n\n")
for _, vendor := range vendors {
fmt.Fprintf(out, "%s\n", vendor)
}
return nil
}
type PluginRegistry struct {
Db *fsdb.Db
VendorManager *ai.VendorsManager
VendorsAll *ai.VendorsManager
Defaults *tools.Defaults
PatternsLoader *tools.PatternsLoader
CustomPatterns *custom_patterns.CustomPatterns
YouTube *youtube.YouTube
Language *lang.Language
Jina *jina.Client
TemplateExtensions *template.ExtensionManager
Strategies *strategy.StrategiesManager
}
func (o *PluginRegistry) SaveEnvFile() (err error) {
// Now create the .env with all configured VendorsController info
var envFileContent bytes.Buffer
o.Defaults.Settings.FillEnvFileContent(&envFileContent)
o.PatternsLoader.SetupFillEnvFileContent(&envFileContent)
o.CustomPatterns.SetupFillEnvFileContent(&envFileContent)
o.Strategies.SetupFillEnvFileContent(&envFileContent)
for _, vendor := range o.VendorManager.Vendors {
vendor.SetupFillEnvFileContent(&envFileContent)
}
o.YouTube.SetupFillEnvFileContent(&envFileContent)
o.Jina.SetupFillEnvFileContent(&envFileContent)
o.Language.SetupFillEnvFileContent(&envFileContent)
err = o.Db.SaveEnv(envFileContent.String())
return
}
func (o *PluginRegistry) Setup() (err error) {
setupQuestion := plugins.NewSetupQuestion("Enter the number of the plugin to setup")
groupsPlugins := common.NewGroupsItemsSelector("Available plugins (please configure all required plugins):",
func(plugin plugins.Plugin) string {
var configuredLabel string
if plugin.IsConfigured() {
configuredLabel = " (configured)"
} else {
configuredLabel = ""
}
return fmt.Sprintf("%v%v", plugin.GetSetupDescription(), configuredLabel)
})
groupsPlugins.AddGroupItems("AI Vendors [at least one, required]", lo.Map(o.VendorsAll.Vendors,
func(vendor ai.Vendor, _ int) plugins.Plugin {
return vendor
})...)
groupsPlugins.AddGroupItems("Tools", o.CustomPatterns, o.Defaults, o.Jina, o.Language, o.PatternsLoader, o.Strategies, o.YouTube)
for {
groupsPlugins.Print(false)
if answerErr := setupQuestion.Ask("Plugin Number"); answerErr != nil {
break
}
if setupQuestion.Value == "" {
break
}
number, parseErr := strconv.Atoi(setupQuestion.Value)
setupQuestion.Value = ""
if parseErr == nil {
var plugin plugins.Plugin
if _, plugin, err = groupsPlugins.GetGroupAndItemByItemNumber(number); err != nil {
return
}
if pluginSetupErr := plugin.Setup(); pluginSetupErr != nil {
println(pluginSetupErr.Error())
} else {
if err = o.SaveEnvFile(); err != nil {
break
}
}
if _, ok := o.VendorManager.VendorsByName[plugin.GetName()]; !ok {
var vendor ai.Vendor
if vendor, ok = plugin.(ai.Vendor); ok {
o.VendorManager.AddVendors(vendor)
}
}
} else {
break
}
}
err = o.SaveEnvFile()
return
}
func (o *PluginRegistry) SetupVendor(vendorName string) (err error) {
if err = o.VendorsAll.SetupVendor(vendorName, o.VendorManager.VendorsByName); err != nil {
return
}
err = o.SaveEnvFile()
return
}
func (o *PluginRegistry) ConfigureVendors() {
o.VendorManager.Clear()
for _, vendor := range o.VendorsAll.Vendors {
if vendorErr := vendor.Configure(); vendorErr == nil {
o.VendorManager.AddVendors(vendor)
}
}
}
func (o *PluginRegistry) GetModels() (ret *ai.VendorsModels, err error) {
o.ConfigureVendors()
ret, err = o.VendorManager.GetModels()
return
}
// Configure buildClient VendorsController based on the environment variables
func (o *PluginRegistry) Configure() (err error) {
o.ConfigureVendors()
_ = o.Defaults.Configure()
_ = o.PatternsLoader.Configure()
//YouTube and Jina are not mandatory, so ignore not configured error
_ = o.YouTube.Configure()
_ = o.Jina.Configure()
_ = o.Language.Configure()
return
}
func (o *PluginRegistry) GetChatter(model string, modelContextLength int, strategy string, stream bool, dryRun bool) (ret *Chatter, err error) {
ret = &Chatter{
db: o.Db,
Stream: stream,
DryRun: dryRun,
}
defaultModel := o.Defaults.Model.Value
defaultModelContextLength, err := strconv.Atoi(o.Defaults.ModelContextLength.Value)
defaultVendor := o.Defaults.Vendor.Value
vendorManager := o.VendorManager
if err != nil {
defaultModelContextLength = 0
err = nil
}
ret.modelContextLength = modelContextLength
if ret.modelContextLength == 0 {
ret.modelContextLength = defaultModelContextLength
}
if dryRun {
ret.vendor = dryrun.NewClient()
ret.model = model
if ret.model == "" {
ret.model = defaultModel
}
} else if model == "" {
ret.vendor = vendorManager.FindByName(defaultVendor)
ret.model = defaultModel
} else {
var models *ai.VendorsModels
if models, err = vendorManager.GetModels(); err != nil {
return
}
ret.vendor = vendorManager.FindByName(models.FindGroupsByItemFirst(model))
ret.model = model
}
if ret.vendor == nil {
var errMsg string
if defaultModel == "" || defaultVendor == "" {
errMsg = "Please run, fabric --setup, and select default model and vendor."
} else {
errMsg = "could not find vendor."
}
err = fmt.Errorf(
" Requested Model = %s\n Default Model = %s\n Default Vendor = %s.\n\n%s",
model, defaultModel, defaultVendor, errMsg)
return
}
ret.strategy = strategy
return
}

View File

@@ -0,0 +1,21 @@
package core
import (
"os"
"testing"
"github.com/danielmiessler/fabric/plugins/db/fsdb"
)
func TestSaveEnvFile(t *testing.T) {
db := fsdb.NewDb(os.TempDir())
registry, err := NewPluginRegistry(db)
if err != nil {
t.Fatalf("NewPluginRegistry() error = %v", err)
}
err = registry.SaveEnvFile()
if err != nil {
t.Fatalf("SaveEnvFile() error = %v", err)
}
}

View File

@@ -1,120 +0,0 @@
package core
import (
"context"
"fmt"
"sync"
"github.com/danielmiessler/fabric/vendors"
)
func NewVendorsManager() *VendorsManager {
return &VendorsManager{
Vendors: map[string]vendors.Vendor{},
}
}
type VendorsManager struct {
Vendors map[string]vendors.Vendor
Models *VendorsModels
}
func (o *VendorsManager) AddVendors(vendors ...vendors.Vendor) {
for _, vendor := range vendors {
o.Vendors[vendor.GetName()] = vendor
}
}
func (o *VendorsManager) GetModels() *VendorsModels {
if o.Models == nil {
o.readModels()
}
return o.Models
}
func (o *VendorsManager) HasVendors() bool {
return len(o.Vendors) > 0
}
func (o *VendorsManager) FindByName(name string) vendors.Vendor {
return o.Vendors[name]
}
func (o *VendorsManager) readModels() {
o.Models = NewVendorsModels()
var wg sync.WaitGroup
resultsChan := make(chan modelResult, len(o.Vendors))
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
for _, vendor := range o.Vendors {
wg.Add(1)
go o.fetchVendorModels(ctx, &wg, vendor, resultsChan)
}
// Wait for all goroutines to finish
go func() {
wg.Wait()
close(resultsChan)
}()
// Collect results
for result := range resultsChan {
if result.err != nil {
fmt.Println(result.vendorName, result.err)
o.Models.AddError(result.err)
cancel() // Cancel remaining goroutines if needed
} else {
o.Models.AddVendorModels(result.vendorName, result.models)
}
}
}
func (o *VendorsManager) fetchVendorModels(
ctx context.Context, wg *sync.WaitGroup, vendor vendors.Vendor, resultsChan chan<- modelResult) {
defer wg.Done()
models, err := vendor.ListModels()
select {
case <-ctx.Done():
// Context canceled, don't send the result
return
case resultsChan <- modelResult{vendorName: vendor.GetName(), models: models, err: err}:
// Result sent
}
}
func (o *VendorsManager) Setup() (ret map[string]vendors.Vendor, err error) {
ret = map[string]vendors.Vendor{}
for _, vendor := range o.Vendors {
fmt.Println()
if vendorErr := vendor.Setup(); vendorErr == nil {
fmt.Printf("[%v] configured\n", vendor.GetName())
ret[vendor.GetName()] = vendor
} else {
fmt.Printf("[%v] skipped\n", vendor.GetName())
}
}
return
}
func (o *VendorsManager) SetupVendor(vendorName string) (err error) {
vendor := o.FindByName(vendorName)
if vendor == nil {
err = fmt.Errorf("vendor %s not found", vendorName)
return
}
err = vendor.Setup()
if err != nil {
return
}
return
}
type modelResult struct {
vendorName string
models []string
err error
}

View File

@@ -1,131 +0,0 @@
package core
import (
"bytes"
"context"
"testing"
"github.com/danielmiessler/fabric/common"
)
func TestNewVendorsManager(t *testing.T) {
vendorsManager := NewVendorsManager()
if vendorsManager == nil {
t.Fatalf("NewVendorsManager() returned nil")
}
}
func TestAddVendors(t *testing.T) {
vendorsManager := NewVendorsManager()
mockVendor := &MockVendor{name: "testVendor"}
vendorsManager.AddVendors(mockVendor)
if _, exists := vendorsManager.Vendors[mockVendor.GetName()]; !exists {
t.Fatalf("AddVendors() did not add vendor")
}
}
func TestGetModels(t *testing.T) {
vendorsManager := NewVendorsManager()
mockVendor := &MockVendor{name: "testVendor"}
vendorsManager.AddVendors(mockVendor)
models := vendorsManager.GetModels()
if models == nil {
t.Fatalf("GetModels() returned nil")
}
}
func TestHasVendors(t *testing.T) {
vendorsManager := NewVendorsManager()
if vendorsManager.HasVendors() {
t.Fatalf("HasVendors() should return false for an empty manager")
}
mockVendor := &MockVendor{name: "testVendor"}
vendorsManager.AddVendors(mockVendor)
if !vendorsManager.HasVendors() {
t.Fatalf("HasVendors() should return true after adding a vendor")
}
}
func TestFindByName(t *testing.T) {
vendorsManager := NewVendorsManager()
mockVendor := &MockVendor{name: "testVendor"}
vendorsManager.AddVendors(mockVendor)
foundVendor := vendorsManager.FindByName("testVendor")
if foundVendor == nil {
t.Fatalf("FindByName() did not find added vendor")
}
}
func TestReadModels(t *testing.T) {
vendorsManager := NewVendorsManager()
mockVendor := &MockVendor{name: "testVendor"}
vendorsManager.AddVendors(mockVendor)
vendorsManager.readModels()
if vendorsManager.Models == nil || len(vendorsManager.Models.Vendors) == 0 {
t.Fatalf("readModels() did not read models correctly")
}
}
func TestSetup(t *testing.T) {
vendorsManager := NewVendorsManager()
mockVendor := &MockVendor{name: "testVendor"}
vendorsManager.AddVendors(mockVendor)
vendors, err := vendorsManager.Setup()
if err != nil {
t.Fatalf("Setup() error = %v", err)
}
if len(vendors) == 0 {
t.Fatalf("Setup() did not setup any vendors")
}
}
// MockVendor is a mock implementation of the Vendor interface for testing purposes.
type MockVendor struct {
*common.Settings
name string
}
func (o *MockVendor) SendStream(messages []*common.Message, options *common.ChatOptions, strings chan string) error {
// TODO implement me
panic("implement me")
}
func (o *MockVendor) Send(ctx context.Context, messages []*common.Message, options *common.ChatOptions) (string, error) {
// TODO implement me
panic("implement me")
}
func (o *MockVendor) SetupFillEnvFileContent(buffer *bytes.Buffer) {
// TODO implement me
panic("implement me")
}
func (o *MockVendor) IsConfigured() bool {
return false
}
func (o *MockVendor) GetSettings() *common.Settings {
return o.Settings
}
func (o *MockVendor) GetName() string {
return o.name
}
func (o *MockVendor) Configure() error {
return nil
}
func (o *MockVendor) Setup() error {
return nil
}
func (o *MockVendor) ListModels() ([]string, error) {
return []string{"model1", "model2"}, nil
}

2345
coverage.out Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,61 +0,0 @@
package db
import (
"fmt"
"os"
"path/filepath"
"strings"
)
type Patterns struct {
*Storage
SystemPatternFile string
UniquePatternsFilePath string
}
// GetPattern finds a pattern by name and returns the pattern as an entry or an error
func (o *Patterns) GetPattern(name string, variables map[string]string) (ret *Pattern, err error) {
patternPath := filepath.Join(o.Dir, name, o.SystemPatternFile)
var pattern []byte
if pattern, err = os.ReadFile(patternPath); err != nil {
return
}
patternStr := string(pattern)
if variables != nil && len(variables) > 0 {
for variableName, value := range variables {
patternStr = strings.ReplaceAll(patternStr, variableName, value)
}
}
ret = &Pattern{
Name: name,
Pattern: patternStr,
}
return
}
func (o *Patterns) PrintLatestPatterns(latestNumber int) (err error) {
var contents []byte
if contents, err = os.ReadFile(o.UniquePatternsFilePath); err != nil {
err = fmt.Errorf("could not read unique patterns file. Pleas run --updatepatterns (%s)", err)
return
}
uniquePatterns := strings.Split(string(contents), "\n")
if latestNumber > len(uniquePatterns) {
latestNumber = len(uniquePatterns)
}
for i := len(uniquePatterns) - 1; i > len(uniquePatterns)-latestNumber-1; i-- {
fmt.Println(uniquePatterns[i])
}
return
}
type Pattern struct {
Name string
Description string
Pattern string
}

View File

@@ -1 +0,0 @@
package db

View File

@@ -1,62 +0,0 @@
package db
import (
"fmt"
"github.com/danielmiessler/fabric/common"
)
type Sessions struct {
*Storage
}
func (o *Sessions) GetOrCreateSession(name string) (session *Session, err error) {
session = &Session{Name: name}
if o.Exists(name) {
err = o.LoadAsJson(name, &session.Messages)
} else {
fmt.Printf("Creating new session: %s\n", name)
}
return
}
func (o *Sessions) PrintSession(name string) (err error) {
if o.Exists(name) {
var session Session
if err = o.LoadAsJson(name, &session.Messages); err == nil {
fmt.Println(session.String())
}
}
return
}
func (o *Sessions) SaveSession(session *Session) (err error) {
return o.SaveAsJson(session.Name, session.Messages)
}
type Session struct {
Name string
Messages []*common.Message
}
func (o *Session) IsEmpty() bool {
return len(o.Messages) == 0
}
func (o *Session) Append(messages ...*common.Message) {
o.Messages = append(o.Messages, messages...)
}
func (o *Session) GetLastMessage() (ret *common.Message) {
if len(o.Messages) > 0 {
ret = o.Messages[len(o.Messages)-1]
}
return
}
func (o *Session) String() (ret string) {
for _, message := range o.Messages {
ret += fmt.Sprintf("\n\n\n[%v]>> \n\n\n%v", message.Role, message.Content)
}
return
}

View File

@@ -1,148 +0,0 @@
package db
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"strings"
"github.com/samber/lo"
)
type Storage struct {
Label string
Dir string
ItemIsDir bool
FileExtension string
}
func (o *Storage) Configure() (err error) {
if err = os.MkdirAll(o.Dir, os.ModePerm); err != nil {
return
}
return
}
// GetNames finds all patterns in the patterns directory and enters the id, name, and pattern into a slice of Entry structs. it returns these entries or an error
func (o *Storage) GetNames() (ret []string, err error) {
var entries []os.DirEntry
if entries, err = os.ReadDir(o.Dir); err != nil {
err = fmt.Errorf("could not read items from directory: %v", err)
return
}
if o.ItemIsDir {
ret = lo.FilterMap(entries, func(item os.DirEntry, index int) (ret string, ok bool) {
if ok = item.IsDir(); ok {
ret = item.Name()
}
return
})
} else {
if o.FileExtension == "" {
ret = lo.FilterMap(entries, func(item os.DirEntry, index int) (ret string, ok bool) {
if ok = !item.IsDir(); ok {
ret = item.Name()
}
return
})
} else {
ret = lo.FilterMap(entries, func(item os.DirEntry, index int) (ret string, ok bool) {
if ok = !item.IsDir() && filepath.Ext(item.Name()) == o.FileExtension; ok {
ret = strings.TrimSuffix(item.Name(), o.FileExtension)
}
return
})
}
}
return
}
func (o *Storage) ListNames() (err error) {
var names []string
if names, err = o.GetNames(); err != nil {
return
}
if len(names) == 0 {
fmt.Printf("\nNo %v\n", o.Label)
return
}
for _, item := range names {
fmt.Printf("%s\n", item)
}
return
}
func (o *Storage) BuildFilePathByName(name string) (ret string) {
ret = o.BuildFilePath(o.buildFileName(name))
return
}
func (o *Storage) BuildFilePath(fileName string) (ret string) {
ret = filepath.Join(o.Dir, fileName)
return
}
func (o *Storage) buildFileName(name string) string {
return fmt.Sprintf("%s%v", name, o.FileExtension)
}
func (o *Storage) Delete(name string) (err error) {
if err = os.Remove(o.BuildFilePathByName(name)); err != nil {
err = fmt.Errorf("could not delete %s: %v", name, err)
}
return
}
func (o *Storage) Exists(name string) (ret bool) {
_, err := os.Stat(o.BuildFilePathByName(name))
ret = !os.IsNotExist(err)
return
}
func (o *Storage) Rename(oldName, newName string) (err error) {
if err = os.Rename(o.BuildFilePathByName(oldName), o.BuildFilePathByName(newName)); err != nil {
err = fmt.Errorf("could not rename %s to %s: %v", oldName, newName, err)
}
return
}
func (o *Storage) Save(name string, content []byte) (err error) {
if err = os.WriteFile(o.BuildFilePathByName(name), content, 0644); err != nil {
err = fmt.Errorf("could not save %s: %v", name, err)
}
return
}
func (o *Storage) Load(name string) (ret []byte, err error) {
if ret, err = os.ReadFile(o.BuildFilePathByName(name)); err != nil {
err = fmt.Errorf("could not load %s: %v", name, err)
}
return
}
func (o *Storage) SaveAsJson(name string, item interface{}) (err error) {
var jsonString []byte
if jsonString, err = json.Marshal(item); err == nil {
err = o.Save(name, jsonString)
} else {
err = fmt.Errorf("could not marshal %s: %s", name, err)
}
return err
}
func (o *Storage) LoadAsJson(name string, item interface{}) (err error) {
var content []byte
if content, err = o.Load(name); err != nil {
return
}
if err = json.Unmarshal(content, &item); err != nil {
err = fmt.Errorf("could not unmarshal %s: %s", name, err)
}
return
}

11
docker-compose.yml Normal file
View File

@@ -0,0 +1,11 @@
version: '3.8'
services:
fabric-api:
build: .
ports:
- "8080:8080"
volumes:
- ./ENV:/root/.config/fabric/.env:ro
environment:
- GIN_MODE=release

119
flake.lock generated Normal file
View File

@@ -0,0 +1,119 @@
{
"nodes": {
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1694529238,
"narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "ff7b65b44d01cf9ba6a71320833626af21126384",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"gomod2nix": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1742209644,
"narHash": "sha256-jMy1XqXqD0/tJprEbUmKilTkvbDY/C0ZGSsJJH4TNCE=",
"owner": "nix-community",
"repo": "gomod2nix",
"rev": "8f3534eb8f6c5c3fce799376dc3b91bae6b11884",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "gomod2nix",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1745234285,
"narHash": "sha256-GfpyMzxwkfgRVN0cTGQSkTC0OHhEkv3Jf6Tcjm//qZ0=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "c11863f1e964833214b767f4a369c6e6a7aba141",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"gomod2nix": "gomod2nix",
"nixpkgs": "nixpkgs",
"systems": "systems_2",
"treefmt-nix": "treefmt-nix"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"systems_2": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"treefmt-nix": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1744961264,
"narHash": "sha256-aRmUh0AMwcbdjJHnytg1e5h5ECcaWtIFQa6d9gI85AI=",
"owner": "numtide",
"repo": "treefmt-nix",
"rev": "8d404a69efe76146368885110f29a2ca3700bee6",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "treefmt-nix",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

80
flake.nix Normal file
View File

@@ -0,0 +1,80 @@
{
description = "Fabric is an open-source framework for augmenting humans using AI. It provides a modular framework for solving specific problems using a crowdsourced set of AI prompts that can be used anywhere";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
systems.url = "github:nix-systems/default";
treefmt-nix = {
url = "github:numtide/treefmt-nix";
inputs.nixpkgs.follows = "nixpkgs";
};
gomod2nix = {
url = "github:nix-community/gomod2nix";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs =
{
self,
nixpkgs,
systems,
treefmt-nix,
gomod2nix,
...
}:
let
forAllSystems = nixpkgs.lib.genAttrs (import systems);
getGoVersion = system: nixpkgs.legacyPackages.${system}.go_1_24;
treefmtEval = forAllSystems (
system:
let
pkgs = nixpkgs.legacyPackages.${system};
in
treefmt-nix.lib.evalModule pkgs ./nix/treefmt.nix
);
in
{
formatter = forAllSystems (system: treefmtEval.${system}.config.build.wrapper);
checks = forAllSystems (system: {
formatting = treefmtEval.${system}.config.build.check self;
});
devShells = forAllSystems (
system:
let
pkgs = nixpkgs.legacyPackages.${system};
goVersion = getGoVersion system;
goEnv = gomod2nix.legacyPackages.${system}.mkGoEnv {
pwd = ./.;
go = goVersion;
};
in
import ./nix/shell.nix {
inherit pkgs goEnv goVersion;
inherit (gomod2nix.legacyPackages.${system}) gomod2nix;
}
);
packages = forAllSystems (
system:
let
pkgs = nixpkgs.legacyPackages.${system};
goVersion = getGoVersion system;
in
{
default = self.packages.${system}.fabric;
fabric = pkgs.callPackage ./nix/pkgs/fabric {
go = goVersion;
inherit (gomod2nix.legacyPackages.${system}) buildGoApplication;
};
inherit (gomod2nix.legacyPackages.${system}) gomod2nix;
}
);
};
}

143
go.mod
View File

@@ -1,77 +1,120 @@
module github.com/danielmiessler/fabric
go 1.22.5
go 1.24.0
toolchain go1.24.2
require (
github.com/anaskhan96/soup v1.2.5
github.com/anthropics/anthropic-sdk-go v1.4.0
github.com/atotto/clipboard v0.1.4
github.com/go-git/go-git/v5 v5.12.0
github.com/go-shiori/go-readability v0.0.0-20240923125239-59a7bd165825
github.com/google/generative-ai-go v0.18.0
github.com/aws/aws-sdk-go-v2 v1.36.4
github.com/aws/aws-sdk-go-v2/config v1.27.27
github.com/aws/aws-sdk-go-v2/service/bedrock v1.34.1
github.com/aws/aws-sdk-go-v2/service/bedrockruntime v1.30.0
github.com/gabriel-vasile/mimetype v1.4.9
github.com/gin-gonic/gin v1.10.1
github.com/go-git/go-git/v5 v5.16.2
github.com/go-shiori/go-readability v0.0.0-20250217085726-9f5bf5ca7612
github.com/google/generative-ai-go v0.20.1
github.com/jessevdk/go-flags v1.6.1
github.com/joho/godotenv v1.5.1
github.com/liushuangls/go-anthropic/v2 v2.8.0
github.com/ollama/ollama v0.3.11
github.com/otiai10/copy v1.14.0
github.com/ollama/ollama v0.9.0
github.com/openai/openai-go v1.8.2
github.com/otiai10/copy v1.14.1
github.com/pkg/errors v0.9.1
github.com/samber/lo v1.47.0
github.com/sashabaranov/go-openai v1.30.0
github.com/stretchr/testify v1.9.0
golang.org/x/text v0.18.0
google.golang.org/api v0.197.0
github.com/samber/lo v1.50.0
github.com/sgaunet/perplexity-go/v2 v2.8.0
github.com/stretchr/testify v1.10.0
golang.org/x/oauth2 v0.30.0
golang.org/x/text v0.26.0
google.golang.org/api v0.236.0
gopkg.in/yaml.v3 v3.0.1
)
require (
cloud.google.com/go v0.115.1 // indirect
cloud.google.com/go/ai v0.8.2 // indirect
cloud.google.com/go/auth v0.9.4 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.4 // indirect
cloud.google.com/go/compute/metadata v0.5.1 // indirect
cloud.google.com/go/longrunning v0.6.1 // indirect
dario.cat/mergo v1.0.1 // indirect
cloud.google.com/go v0.121.2 // indirect
cloud.google.com/go/ai v0.12.1 // indirect
cloud.google.com/go/auth v0.16.2 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
cloud.google.com/go/compute/metadata v0.7.0 // indirect
cloud.google.com/go/longrunning v0.6.7 // indirect
dario.cat/mergo v1.0.2 // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/ProtonMail/go-crypto v1.0.0 // indirect
github.com/andybalholm/cascadia v1.3.2 // indirect
github.com/ProtonMail/go-crypto v1.3.0 // indirect
github.com/andybalholm/cascadia v1.3.3 // indirect
github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de // indirect
github.com/cloudflare/circl v1.4.0 // indirect
github.com/cyphar/filepath-securejoin v0.3.2 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.10 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.17.27 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.11 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.35 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.35 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.17 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.22.4 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.4 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.30.3 // indirect
github.com/aws/smithy-go v1.22.2 // indirect
github.com/bytedance/sonic v1.13.3 // indirect
github.com/bytedance/sonic/loader v0.2.4 // indirect
github.com/cloudflare/circl v1.6.1 // indirect
github.com/cloudwego/base64x v0.1.5 // indirect
github.com/cyphar/filepath-securejoin v0.4.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/emirpasic/gods v1.18.1 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/gin-contrib/sse v1.1.0 // indirect
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
github.com/go-git/go-billy/v5 v5.5.0 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-git/go-billy/v5 v5.6.2 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.26.0 // indirect
github.com/go-shiori/dom v0.0.0-20230515143342-73569d674e1c // indirect
github.com/goccy/go-json v0.10.5 // indirect
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/google/s2a-go v0.1.8 // indirect
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
github.com/google/s2a-go v0.1.9 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect
github.com/googleapis/gax-go/v2 v2.13.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect
github.com/googleapis/gax-go/v2 v2.14.2 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/kevinburke/ssh_config v1.2.0 // indirect
github.com/pjbgf/sha1cd v0.3.0 // indirect
github.com/klauspost/cpuid/v2 v2.2.10 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/otiai10/mint v1.6.3 // indirect
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
github.com/pjbgf/sha1cd v0.3.2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
github.com/skeema/knownhosts v1.3.0 // indirect
github.com/sergi/go-diff v1.4.0 // indirect
github.com/skeema/knownhosts v1.3.1 // indirect
github.com/tidwall/gjson v1.18.0 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.1 // indirect
github.com/tidwall/sjson v1.2.5 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.14 // indirect
github.com/xanzy/ssh-agent v0.3.3 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.55.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0 // indirect
go.opentelemetry.io/otel v1.30.0 // indirect
go.opentelemetry.io/otel/metric v1.30.0 // indirect
go.opentelemetry.io/otel/trace v1.30.0 // indirect
golang.org/x/crypto v0.27.0 // indirect
golang.org/x/net v0.29.0 // indirect
golang.org/x/oauth2 v0.23.0 // indirect
golang.org/x/sync v0.8.0 // indirect
golang.org/x/sys v0.25.0 // indirect
golang.org/x/time v0.6.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect
google.golang.org/grpc v1.66.2 // indirect
google.golang.org/protobuf v1.34.2 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect
go.opentelemetry.io/otel v1.36.0 // indirect
go.opentelemetry.io/otel/metric v1.36.0 // indirect
go.opentelemetry.io/otel/trace v1.36.0 // indirect
golang.org/x/arch v0.18.0 // indirect
golang.org/x/crypto v0.39.0 // indirect
golang.org/x/net v0.41.0 // indirect
golang.org/x/sync v0.15.0 // indirect
golang.org/x/sys v0.33.0 // indirect
golang.org/x/time v0.12.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect
google.golang.org/grpc v1.73.0 // indirect
google.golang.org/protobuf v1.36.6 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

441
go.sum
View File

@@ -1,122 +1,156 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.115.1 h1:Jo0SM9cQnSkYfp44+v+NQXHpcHqlnRJk2qxh6yvxxxQ=
cloud.google.com/go v0.115.1/go.mod h1:DuujITeaufu3gL68/lOFIirVNJwQeyf5UXyi+Wbgknc=
cloud.google.com/go/ai v0.8.2 h1:LEaQwqBv+k2ybrcdTtCTc9OPZXoEdcQaGrfvDYS6Bnk=
cloud.google.com/go/ai v0.8.2/go.mod h1:Wb3EUUGWwB6yHBaUf/+oxUq/6XbCaU1yh0GrwUS8lr4=
cloud.google.com/go/auth v0.9.4 h1:DxF7imbEbiFu9+zdKC6cKBko1e8XeJnipNqIbWZ+kDI=
cloud.google.com/go/auth v0.9.4/go.mod h1:SHia8n6//Ya940F1rLimhJCjjx7KE17t0ctFEci3HkA=
cloud.google.com/go/auth/oauth2adapt v0.2.4 h1:0GWE/FUsXhf6C+jAkWgYm7X9tK8cuEIfy19DBn6B6bY=
cloud.google.com/go/auth/oauth2adapt v0.2.4/go.mod h1:jC/jOpwFP6JBxhB3P5Rr0a9HLMC/Pe3eaL4NmdvqPtc=
cloud.google.com/go/compute/metadata v0.5.1 h1:NM6oZeZNlYjiwYje+sYFjEpP0Q0zCan1bmQW/KmIrGs=
cloud.google.com/go/compute/metadata v0.5.1/go.mod h1:C66sj2AluDcIqakBq/M8lw8/ybHgOZqin2obFxa/E5k=
cloud.google.com/go/longrunning v0.6.1 h1:lOLTFxYpr8hcRtcwWir5ITh1PAKUD/sG2lKrTSYjyMc=
cloud.google.com/go/longrunning v0.6.1/go.mod h1:nHISoOZpBcmlwbJmiVk5oDRz0qG/ZxPynEGs1iZ79s0=
dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
cloud.google.com/go v0.121.2 h1:v2qQpN6Dx9x2NmwrqlesOt3Ys4ol5/lFZ6Mg1B7OJCg=
cloud.google.com/go v0.121.2/go.mod h1:nRFlrHq39MNVWu+zESP2PosMWA0ryJw8KUBZ2iZpxbw=
cloud.google.com/go/ai v0.12.1 h1:m1n/VjUuHS+pEO/2R4/VbuuEIkgk0w67fDQvFaMngM0=
cloud.google.com/go/ai v0.12.1/go.mod h1:5vIPNe1ZQsVZqCliXIPL4QnhObQQY4d9hAGHdVc4iw4=
cloud.google.com/go/auth v0.16.2 h1:QvBAGFPLrDeoiNjyfVunhQ10HKNYuOwZ5noee0M5df4=
cloud.google.com/go/auth v0.16.2/go.mod h1:sRBas2Y1fB1vZTdurouM0AzuYQBMZinrUYL8EufhtEA=
cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc=
cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c=
cloud.google.com/go/compute/metadata v0.7.0 h1:PBWF+iiAerVNe8UCHxdOt6eHLVc3ydFeOCw78U8ytSU=
cloud.google.com/go/compute/metadata v0.7.0/go.mod h1:j5MvL9PprKL39t166CoB1uVHfQMs4tFQZZcKwksXUjo=
cloud.google.com/go/longrunning v0.6.7 h1:IGtfDWHhQCgCjwQjV9iiLnUta9LBCo8R9QmAFsS/PrE=
cloud.google.com/go/longrunning v0.6.7/go.mod h1:EAFV3IZAKmM56TyiE6VAP3VoTzhZzySwI/YI1s/nRsY=
dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8=
dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0kC2U78=
github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
github.com/anaskhan96/soup v1.2.5 h1:V/FHiusdTrPrdF4iA1YkVxsOpdNcgvqT1hG+YtcZ5hM=
github.com/anaskhan96/soup v1.2.5/go.mod h1:6YnEp9A2yywlYdM4EgDz9NEHclocMepEtku7wg6Cq3s=
github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss=
github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU=
github.com/ProtonMail/go-crypto v1.3.0 h1:ILq8+Sf5If5DCpHQp4PbZdS1J7HDFRXz/+xKBiRGFrw=
github.com/ProtonMail/go-crypto v1.3.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE=
github.com/andybalholm/cascadia v1.3.3 h1:AG2YHrzJIm4BZ19iwJ/DAua6Btl3IwJX+VI4kktS1LM=
github.com/andybalholm/cascadia v1.3.3/go.mod h1:xNd9bqTn98Ln4DwST8/nG+H0yuB8Hmgu1YHNnWw0GeA=
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
github.com/anthropics/anthropic-sdk-go v1.4.0 h1:fU1jKxYbQdQDiEXCxeW5XZRIOwKevn/PMg8Ay1nnUx0=
github.com/anthropics/anthropic-sdk-go v1.4.0/go.mod h1:AapDW22irxK2PSumZiQXYUFvsdQgkwIWlpESweWZI/c=
github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de h1:FxWPpzIjnTlhPwqqXc4/vE0f7GvRjuAsbW+HOIe8KnA=
github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de/go.mod h1:DCaWoUhZrYW9p1lxo/cm8EmUOOzAPSEZNGF2DK1dJgw=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
github.com/cloudflare/circl v1.4.0 h1:BV7h5MgrktNzytKmWjpOtdYrf0lkkbF8YMlBGPhJQrY=
github.com/cloudflare/circl v1.4.0/go.mod h1:PDRU+oXvdD7KCtgKxW95M5Z8BpSCJXQORiZFnBQS5QU=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cyphar/filepath-securejoin v0.3.2 h1:QhZu5AxQ+o1XZH0Ye05YzvJ0kAdK6VQc0z9NNMek7gc=
github.com/cyphar/filepath-securejoin v0.3.2/go.mod h1:F7i41x/9cBF7lzCrVsYs9fuzwRZm4NQsGTBdpp6mETc=
github.com/aws/aws-sdk-go-v2 v1.36.4 h1:GySzjhVvx0ERP6eyfAbAuAXLtAda5TEy19E5q5W8I9E=
github.com/aws/aws-sdk-go-v2 v1.36.4/go.mod h1:LLXuLpgzEbD766Z5ECcRmi8AzSwfZItDtmABVkRLGzg=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.10 h1:zAybnyUQXIZ5mok5Jqwlf58/TFE7uvd3IAsa1aF9cXs=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.10/go.mod h1:qqvMj6gHLR/EXWZw4ZbqlPbQUyenf4h82UQUlKc+l14=
github.com/aws/aws-sdk-go-v2/config v1.27.27 h1:HdqgGt1OAP0HkEDDShEl0oSYa9ZZBSOmKpdpsDMdO90=
github.com/aws/aws-sdk-go-v2/config v1.27.27/go.mod h1:MVYamCg76dFNINkZFu4n4RjDixhVr51HLj4ErWzrVwg=
github.com/aws/aws-sdk-go-v2/credentials v1.17.27 h1:2raNba6gr2IfA0eqqiP2XiQ0UVOpGPgDSi0I9iAP+UI=
github.com/aws/aws-sdk-go-v2/credentials v1.17.27/go.mod h1:gniiwbGahQByxan6YjQUMcW4Aov6bLC3m+evgcoN4r4=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.11 h1:KreluoV8FZDEtI6Co2xuNk/UqI9iwMrOx/87PBNIKqw=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.11/go.mod h1:SeSUYBLsMYFoRvHE0Tjvn7kbxaUhl75CJi1sbfhMxkU=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.35 h1:o1v1VFfPcDVlK3ll1L5xHsaQAFdNtZ5GXnNR7SwueC4=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.35/go.mod h1:rZUQNYMNG+8uZxz9FOerQJ+FceCiodXvixpeRtdESrU=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.35 h1:R5b82ubO2NntENm3SAm0ADME+H630HomNJdgv+yZ3xw=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.35/go.mod h1:FuA+nmgMRfkzVKYDNEqQadvEMxtxl9+RLT9ribCwEMs=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY=
github.com/aws/aws-sdk-go-v2/service/bedrock v1.34.1 h1:sD4KqDKG8aOaMWaWTMB8l8VnLa/Di7XHb0Uf4plrndA=
github.com/aws/aws-sdk-go-v2/service/bedrock v1.34.1/go.mod h1:lrn8DOVFYFeaUZKxJ95T5eGDBjnhffgGz68Wq2sfBbA=
github.com/aws/aws-sdk-go-v2/service/bedrockruntime v1.30.0 h1:eMOwQ8ZZK+76+08RfxeaGUtRFN6wxmD1rvqovc2kq2w=
github.com/aws/aws-sdk-go-v2/service/bedrockruntime v1.30.0/go.mod h1:0b5Rq7rUvSQFYHI1UO0zFTV/S6j6DUyuykXA80C+YOI=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3 h1:dT3MqvGhSoaIhRseqw2I0yH81l7wiR2vjs57O51EAm8=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3/go.mod h1:GlAeCkHwugxdHaueRr4nhPuY+WW+gR8UjlcqzPr1SPI=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.17 h1:HGErhhrxZlQ044RiM+WdoZxp0p+EGM62y3L6pwA4olE=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.17/go.mod h1:RkZEx4l0EHYDJpWppMJ3nD9wZJAa8/0lq9aVC+r2UII=
github.com/aws/aws-sdk-go-v2/service/sso v1.22.4 h1:BXx0ZIxvrJdSgSvKTZ+yRBeSqqgPM89VPlulEcl37tM=
github.com/aws/aws-sdk-go-v2/service/sso v1.22.4/go.mod h1:ooyCOXjvJEsUw7x+ZDHeISPMhtwI3ZCB7ggFMcFfWLU=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.4 h1:yiwVzJW2ZxZTurVbYWA7QOrAaCYQR72t0wrSBfoesUE=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.4/go.mod h1:0oxfLkpz3rQ/CHlx5hB7H69YUpFiI1tql6Q6Ne+1bCw=
github.com/aws/aws-sdk-go-v2/service/sts v1.30.3 h1:ZsDKRLXGWHk8WdtyYMoGNO7bTudrvuKpDKgMVRlepGE=
github.com/aws/aws-sdk-go-v2/service/sts v1.30.3/go.mod h1:zwySh8fpFyXp9yOr/KVzxOl8SRqgf/IDw5aUt9UKFcQ=
github.com/aws/smithy-go v1.22.2 h1:6D9hW43xKFrRx/tXXfAlIZc4JI+yQe6snnWcQyxSyLQ=
github.com/aws/smithy-go v1.22.2/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg=
github.com/bytedance/sonic v1.13.3 h1:MS8gmaH16Gtirygw7jV91pDCN33NyMrPbN7qiYhEsF0=
github.com/bytedance/sonic v1.13.3/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4=
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
github.com/bytedance/sonic/loader v0.2.4 h1:ZWCw4stuXUsn1/+zQDqeE7JKP+QO47tz7QCNan80NzY=
github.com/bytedance/sonic/loader v0.2.4/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0=
github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4=
github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s=
github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU=
github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o=
github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE=
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/gliderlabs/ssh v0.3.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE=
github.com/gliderlabs/ssh v0.3.7/go.mod h1:zpHEXBstFnQYtGnB8k8kQLol82umzn/2/snG7alWVD8=
github.com/gabriel-vasile/mimetype v1.4.9 h1:5k+WDwEsD9eTLL8Tz3L0VnmVh9QxGjRmjBvAG7U/oYY=
github.com/gabriel-vasile/mimetype v1.4.9/go.mod h1:WnSQhFKJuBlRyLiKohA/2DtIlPFAbguNaG7QCHcyGok=
github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w=
github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM=
github.com/gin-gonic/gin v1.10.1 h1:T0ujvqyCSqRopADpgPgiTT63DUQVSfojyME59Ei63pQ=
github.com/gin-gonic/gin v1.10.1/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c=
github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU=
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU=
github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow=
github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UNbRM=
github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU=
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
github.com/go-git/go-git/v5 v5.12.0 h1:7Md+ndsjrzZxbddRDZjF14qK+NN56sy6wkqaVrjZtys=
github.com/go-git/go-git/v5 v5.12.0/go.mod h1:FTM9VKtnI2m65hNI/TenDDDnUf2Q9FHnXYjuz9i5OEY=
github.com/go-git/go-git/v5 v5.16.2 h1:fT6ZIOjE5iEnkzKyxTHK1W4HGAsPhqEqiSAssSO77hM=
github.com/go-git/go-git/v5 v5.16.2/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.26.0 h1:SP05Nqhjcvz81uJaRfEV0YBSSSGMc/iMaVtFbr3Sw2k=
github.com/go-playground/validator/v10 v10.26.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo=
github.com/go-shiori/dom v0.0.0-20230515143342-73569d674e1c h1:wpkoddUomPfHiOziHZixGO5ZBS73cKqVzZipfrLmO1w=
github.com/go-shiori/dom v0.0.0-20230515143342-73569d674e1c/go.mod h1:oVDCh3qjJMLVUSILBRwrm+Bc6RNXGZYtoh9xdvf1ffM=
github.com/go-shiori/go-readability v0.0.0-20240923125239-59a7bd165825 h1:CpSi7xiWqGaAqVn/2MsbRoDmPwXMvvQUu3hLjX1QrOM=
github.com/go-shiori/go-readability v0.0.0-20240923125239-59a7bd165825/go.mod h1:YWa00ashoPZMAOElrSn4E1cJErhDVU6PWAll4Hxzn+w=
github.com/go-shiori/go-readability v0.0.0-20250217085726-9f5bf5ca7612 h1:BYLNYdZaepitbZreRIa9xeCQZocWmy/wj4cGIH0qyw0=
github.com/go-shiori/go-readability v0.0.0-20250217085726-9f5bf5ca7612/go.mod h1:wgqthQa8SAYs0yyljVeCOQlZ027VW5CmLsbi9jWC08c=
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f h1:3BSP1Tbs2djlpprl7wCLuiqMaUh5SJkkzI2gDs+FgLs=
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f/go.mod h1:Pcatq5tYkCW2Q6yrR2VRHlbHpZ/R4/7qyL1TCF7vl14=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ=
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/generative-ai-go v0.18.0 h1:6ybg9vOCLcI/UpBBYXOTVgvKmcUKFRNj+2Cj3GnebSo=
github.com/google/generative-ai-go v0.18.0/go.mod h1:JYolL13VG7j79kM5BtHz4qwONHkeJQzOCkKXnpqtS/E=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/generative-ai-go v0.20.1 h1:6dEIujpgN2V0PgLhr6c/M1ynRdc7ARtiIDPFzj45uNQ=
github.com/google/generative-ai-go v0.20.1/go.mod h1:TjOnZJmZKzarWbjUJgy+r3Ee7HGBRVLhOIgupnwR4Bg=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/s2a-go v0.1.8 h1:zZDs9gcbt9ZPLV0ndSyQk6Kacx2g/X+SKYovpnz3SMM=
github.com/google/s2a-go v0.1.8/go.mod h1:6iNWHTpQ+nfNRN5E00MSdfDwVesa8hhS32PhPO8deJA=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0=
github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/enterprise-certificate-proxy v0.3.4 h1:XYIDZApgAnrN1c855gTgghdIA6Stxb52D5RnLI1SLyw=
github.com/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA=
github.com/googleapis/gax-go/v2 v2.13.0 h1:yitjD5f7jQHhyDsnhKEBU52NdvvdSeGzlAnDPT0hH1s=
github.com/googleapis/gax-go/v2 v2.13.0/go.mod h1:Z/fvTZXF8/uw7Xu5GuslPw+bplx6SS338j1Is2S+B7A=
github.com/googleapis/enterprise-certificate-proxy v0.3.6 h1:GW/XbdyBFQ8Qe+YAmFU9uHLo7OnF5tL52HFAgMmyrf4=
github.com/googleapis/enterprise-certificate-proxy v0.3.6/go.mod h1:MkHOF77EYAE7qfSuSS9PU6g4Nt4e11cnsDUowfwewLA=
github.com/googleapis/gax-go/v2 v2.14.2 h1:eBLnkZ9635krYIPD+ag1USrOAI0Nr0QYF3+/3GqO0k0=
github.com/googleapis/gax-go/v2 v2.14.2/go.mod h1:ON64QhlJkhVtSqp4v1uaK92VyZ2gmvDQsweuyLV+8+w=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
github.com/jessevdk/go-flags v1.6.1 h1:Cvu5U8UGrLay1rZfv/zP7iLpSHGUZ/Ou68T0iX1bBK4=
github.com/jessevdk/go-flags v1.6.1/go.mod h1:Mk8T1hIAWpOiJiHa9rJASDK2UGWji0EuPGBnNLMooyc=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE=
github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
@@ -124,110 +158,135 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/liushuangls/go-anthropic/v2 v2.8.0 h1:0zH2jDNycbrlszxnLrG+Gx8vVT0yJAPWU4s3ZTkWzgI=
github.com/liushuangls/go-anthropic/v2 v2.8.0/go.mod h1:8BKv/fkeTaL5R9R9bGkaknYBueyw2WxY20o7bImbOek=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
github.com/ollama/ollama v0.3.11 h1:Fs1B5WjXYUvr5bkMZZpUJfiqIAxrymujRidFABwMeV8=
github.com/ollama/ollama v0.3.11/go.mod h1:YrWoNkFnPOYsnDvsf/Ztb1wxU9/IXrNsQHqcxbY2r94=
github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M=
github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU=
github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w=
github.com/otiai10/mint v1.5.1 h1:XaPLeE+9vGbuyEHem1JNk3bYc7KKqyI/na0/mLd/Kks=
github.com/otiai10/mint v1.5.1/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM=
github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/ollama/ollama v0.9.0 h1:GvdGhi8G/QMnFrY0TMLDy1bXua+Ify8KTkFe4ZY/OZs=
github.com/ollama/ollama v0.9.0/go.mod h1:aio9yQ7nc4uwIbn6S0LkGEPgn8/9bNQLL1nHuH+OcD0=
github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=
github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY=
github.com/openai/openai-go v1.8.2 h1:UqSkJ1vCOPUpz9Ka5tS0324EJFEuOvMc+lA/EarJWP8=
github.com/openai/openai-go v1.8.2/go.mod h1:g461MYGXEXBVdV5SaR/5tNzNbSfwTBBefwc+LlDCK0Y=
github.com/otiai10/copy v1.14.1 h1:5/7E6qsUMBaH5AnQ0sSLzzTg1oTECmcCmT6lvF45Na8=
github.com/otiai10/copy v1.14.1/go.mod h1:oQwrEDDOci3IM8dJF0d8+jnbfPDllW6vUjNc3DoZm9I=
github.com/otiai10/mint v1.6.3 h1:87qsV/aw1F5as1eH1zS/yqHY85ANKVMgkDrf9rcxbQs=
github.com/otiai10/mint v1.6.3/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM=
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4=
github.com/pjbgf/sha1cd v0.3.2/go.mod h1:zQWigSxVmsHEZow5qaLtPYxpcKMMQpa09ixqBxuCS6A=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
github.com/samber/lo v1.47.0 h1:z7RynLwP5nbyRscyvcD043DWYoOcYRv3mV8lBeqOCLc=
github.com/samber/lo v1.47.0/go.mod h1:RmDH9Ct32Qy3gduHQuKJ3gW1fMHAnE/fAzQuf6He5cU=
github.com/sashabaranov/go-openai v1.30.0 h1:fHv9urGxABfm885xGWsXFSk5cksa+8dJ4jGli/UQQcI=
github.com/sashabaranov/go-openai v1.30.0/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
github.com/samber/lo v1.50.0 h1:XrG0xOeHs+4FQ8gJR97zDz5uOFMW7OwFWiFVzqopKgY=
github.com/samber/lo v1.50.0/go.mod h1:RjZyNk6WSnUFRKK6EyOhsRJMqft3G+pg7dCWHQCWvsc=
github.com/scylladb/termtables v0.0.0-20191203121021-c4c0b6d42ff4/go.mod h1:C1a7PQSMz9NShzorzCiG2fk9+xuCgLkPeCvMHYR2OWg=
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw=
github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
github.com/sgaunet/perplexity-go/v2 v2.8.0 h1:stnuVieniZMGo6qJLCV2JyR2uF7K5398YOA/ZZcgrSg=
github.com/sgaunet/perplexity-go/v2 v2.8.0/go.mod h1:MSks4RNuivCi0GqJyylhFdgSJFVEwZHjAhrf86Wkynk=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/skeema/knownhosts v1.3.0 h1:AM+y0rI04VksttfwjkSTNQorvGqmwATnvnAHpSgc0LY=
github.com/skeema/knownhosts v1.3.0/go.mod h1:sPINvnADmT/qYH1kfv+ePMmOBTH6Tbl7b5LvTDjFK7M=
github.com/skeema/knownhosts v1.3.1 h1:X2osQ+RAjK76shCbvhHHHVl3ZlgDm8apHEHFqRjnBY8=
github.com/skeema/knownhosts v1.3.1/go.mod h1:r7KTdC8l4uxWRyK2TpQZ/1o5HaSzh06ePQNxPwTcfiY=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/ugorji/go/codec v1.2.14 h1:yOQvXCBc3Ij46LRkRoh4Yd5qK6LVOgi0bYOXfb7ifjw=
github.com/ugorji/go/codec v1.2.14/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.55.0 h1:hCq2hNMwsegUvPzI7sPOvtO9cqyy5GbWt/Ybp2xrx8Q=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.55.0/go.mod h1:LqaApwGx/oUmzsbqxkzuBvyoPpkxk3JQWnqfVrJ3wCA=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0 h1:ZIg3ZT/aQ7AfKqdwp7ECpOK6vHqquXXuyTjIO8ZdmPs=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0/go.mod h1:DQAwmETtZV00skUwgD6+0U89g80NKsJE3DCKeLLPQMI=
go.opentelemetry.io/otel v1.30.0 h1:F2t8sK4qf1fAmY9ua4ohFS/K+FUuOPemHUIXHtktrts=
go.opentelemetry.io/otel v1.30.0/go.mod h1:tFw4Br9b7fOS+uEao81PJjVMjW/5fvNCbpsDIXqP0pc=
go.opentelemetry.io/otel/metric v1.30.0 h1:4xNulvn9gjzo4hjg+wzIKG7iNFEaBMX00Qd4QIZs7+w=
go.opentelemetry.io/otel/metric v1.30.0/go.mod h1:aXTfST94tswhWEb+5QjlSqG+cZlmyXy/u8jFpor3WqQ=
go.opentelemetry.io/otel/trace v1.30.0 h1:7UBkkYzeg3C7kQX8VAidWh2biiQbtAKjyIML8dQ9wmc=
go.opentelemetry.io/otel/trace v1.30.0/go.mod h1:5EyKqTzzmyqB9bwtCCq6pDLktPK6fmGf/Dph+8VI02o=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 h1:q4XOmH/0opmeuJtPsbFNivyl7bCt7yRBbeEm2sC/XtQ=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0/go.mod h1:snMWehoOh2wsEwnvvwtDyFCxVeDAODenXHtn5vzrKjo=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q=
go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg=
go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E=
go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE=
go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs=
go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs=
go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY=
go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFwHX4dThiPis=
go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4=
go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w=
go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA=
golang.org/x/arch v0.18.0 h1:WN9poc33zL4AzGxqf8VtpKUnGvMi8O9lhNyBMF/85qc=
golang.org/x/arch v0.18.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM=
golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=
golang.org/x/exp v0.0.0-20250218142911-aa4b98e5adaa h1:t2QcU6V556bFjYgu4L6C+6VrCPyJZ+eyRsABUPs1mz4=
golang.org/x/exp v0.0.0-20250218142911-aa4b98e5adaa/go.mod h1:BHOTPb3L19zxehTsLoJXVaTktb06DFgmdW6Wb9s8jqk=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs=
golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -235,72 +294,59 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM=
golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.197.0 h1:x6CwqQLsFiA5JKAiGyGBjc2bNtHtLddhJCE2IKuhhcQ=
google.golang.org/api v0.197.0/go.mod h1:AuOuo20GoQ331nq7DquGHlU6d+2wN2fZ8O0ta60nRNw=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 h1:hjSy6tcFQZ171igDaN5QHOw2n6vx40juYbC/x67CEhc=
google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:qpvKtACPCQhAdu3PyQgV4l3LMXZEtft7y8QcarRsp9I=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo=
google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
google.golang.org/api v0.236.0 h1:CAiEiDVtO4D/Qja2IA9VzlFrgPnK3XVMmRoJZlSWbc0=
google.golang.org/api v0.236.0/go.mod h1:X1WF9CU2oTc+Jml1tiIxGmWFK/UZezdqEu09gcxZAj4=
google.golang.org/genproto v0.0.0-20250505200425-f936aa4a68b2 h1:1tXaIXCracvtsRxSBsYDiSBN0cuJvM7QYW+MrpIRY78=
google.golang.org/genproto v0.0.0-20250505200425-f936aa4a68b2/go.mod h1:49MsLSx0oWMOZqcpB3uL8ZOkAh1+TndpJ8ONoCBWiZk=
google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 h1:oWVWY3NzT7KJppx2UKhKmzPq4SRe0LdCijVRwvGeikY=
google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822/go.mod h1:h3c4v36UTKzUiuaOKQ6gr3S+0hovBtUrXzTG/i3+XEc=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 h1:fc6jSaCT0vBduLYZHYrBBNY4dsWuvgyff9noRNDdBeE=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
google.golang.org/grpc v1.73.0 h1:VIWSmpI2MegBtTuFt5/JWy2oXxtjJ/e89Z70ImfD2ok=
google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc=
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
@@ -312,5 +358,4 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=

BIN
images/fabric-summarize.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 491 KiB

View File

@@ -2,9 +2,10 @@ package main
import (
"fmt"
"github.com/jessevdk/go-flags"
"os"
"github.com/jessevdk/go-flags"
"github.com/danielmiessler/fabric/cli"
)

View File

@@ -0,0 +1,38 @@
{
lib,
buildGoApplication,
go,
installShellFiles,
}:
buildGoApplication {
pname = "fabric-ai";
version = import ./version.nix;
src = ../../../.;
pwd = ../../../.;
modules = ./gomod2nix.toml;
doCheck = false;
ldflags = [
"-s"
"-w"
];
inherit go;
nativeBuildInputs = [ installShellFiles ];
postInstall = ''
installShellCompletion --zsh ./completions/_fabric
installShellCompletion --bash ./completions/fabric.bash
installShellCompletion --fish ./completions/fabric.fish
'';
meta = with lib; {
description = "Fabric is an open-source framework for augmenting humans using AI. It provides a modular framework for solving specific problems using a crowdsourced set of AI prompts that can be used anywhere";
homepage = "https://github.com/danielmiessler/fabric";
license = licenses.mit;
platforms = platforms.all;
mainProgram = "fabric";
};
}

View File

@@ -0,0 +1,330 @@
schema = 3
[mod]
[mod."cloud.google.com/go"]
version = "v0.121.2"
hash = "sha256-BCgGHxKti8slH98UDDurtgzX3lgcYEklsmj4ImPpwlc="
[mod."cloud.google.com/go/ai"]
version = "v0.12.1"
hash = "sha256-wg3oLMS68E/v7EdNzywbjwEmpk+u6U8LTnIc1pq8edo="
[mod."cloud.google.com/go/auth"]
version = "v0.16.2"
hash = "sha256-BAU9WGFKe0pd5Eu3l/Mbts+QeCOjS+lChr5hrPBCzdA="
[mod."cloud.google.com/go/auth/oauth2adapt"]
version = "v0.2.8"
hash = "sha256-GoXFqAbp1WO1tDj07PF5EyxDYvCBP0l0qwxY2oV2hfc="
[mod."cloud.google.com/go/compute/metadata"]
version = "v0.7.0"
hash = "sha256-jJZDW+hibqjMiY8OiJhgJALbGwEq+djLOxfYR7upQyE="
[mod."cloud.google.com/go/longrunning"]
version = "v0.6.7"
hash = "sha256-9I0Nc2KWAEVoxDngNkqFUdASmZIAySfMEELlPh3Q3xA="
[mod."dario.cat/mergo"]
version = "v1.0.2"
hash = "sha256-p6jdiHlLEfZES8vJnDywG4aVzIe16p0CU6iglglIweA="
[mod."github.com/Microsoft/go-winio"]
version = "v0.6.2"
hash = "sha256-tVNWDUMILZbJvarcl/E7tpSnkn7urqgSHa2Eaka5vSU="
[mod."github.com/ProtonMail/go-crypto"]
version = "v1.3.0"
hash = "sha256-TUG+C4MyeWglOmiwiW2/NUVurFHXLgEPRd3X9uQ1NGI="
[mod."github.com/andybalholm/cascadia"]
version = "v1.3.3"
hash = "sha256-jv7ZshpSd7FZzKKN6hqlUgiR8C3y85zNIS/hq7g76Ho="
[mod."github.com/anthropics/anthropic-sdk-go"]
version = "v1.4.0"
hash = "sha256-4kwFw9gt/sRIlTo0fC2PbfLnCyc4lCOtmfQelhpORX8="
[mod."github.com/araddon/dateparse"]
version = "v0.0.0-20210429162001-6b43995a97de"
hash = "sha256-UuX84naeRGMsFOgIgRoBHG5sNy1CzBkWPKmd6VbLwFw="
[mod."github.com/atotto/clipboard"]
version = "v0.1.4"
hash = "sha256-ZZ7U5X0gWOu8zcjZcWbcpzGOGdycwq0TjTFh/eZHjXk="
[mod."github.com/aws/aws-sdk-go-v2"]
version = "v1.36.4"
hash = "sha256-Cpdphp8FQUbQlhAYvtPKDh1oZc84+/0bzLlx8CM1/BM="
[mod."github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream"]
version = "v1.6.10"
hash = "sha256-9+ZMhWxtsm7ZtZCjBV5PZkOR5rt3bCOznuv45Iwf55c="
[mod."github.com/aws/aws-sdk-go-v2/config"]
version = "v1.27.27"
hash = "sha256-jQmc1lJmVeTezSeFs6KL2HAvCkP9ZWMdVbG5ymJQrKs="
[mod."github.com/aws/aws-sdk-go-v2/credentials"]
version = "v1.17.27"
hash = "sha256-7ITZjIF0ZmmCG3u5d88IfsAj0KF1IFm9KhWFlC6RtQo="
[mod."github.com/aws/aws-sdk-go-v2/feature/ec2/imds"]
version = "v1.16.11"
hash = "sha256-uedtRd/SIcFJlYZg1jtJdIJViZq1Poks9/J2Bm9/Ehw="
[mod."github.com/aws/aws-sdk-go-v2/internal/configsources"]
version = "v1.3.35"
hash = "sha256-AyQ+eJvyhahypIAqPScdkn44MYwBcr9iyrMC1BRSeZI="
[mod."github.com/aws/aws-sdk-go-v2/internal/endpoints/v2"]
version = "v2.6.35"
hash = "sha256-c8K+Nk5XrFMWaaxVsyhKgyJBZhs3Hkhjr/dIDXWZfSQ="
[mod."github.com/aws/aws-sdk-go-v2/internal/ini"]
version = "v1.8.0"
hash = "sha256-v76jTAr4rEgS5en49ikLh6nuvclN+VjpOPj83ZQ3sLo="
[mod."github.com/aws/aws-sdk-go-v2/service/bedrock"]
version = "v1.34.1"
hash = "sha256-OK7t+ieq4pviCnnhfSytANBF5Lwdz4KxjN10CC5pXyY="
[mod."github.com/aws/aws-sdk-go-v2/service/bedrockruntime"]
version = "v1.30.0"
hash = "sha256-MsEQfbqIREtMikRFqBpLCqdAC4gfgPSNbk08k5OJTbo="
[mod."github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding"]
version = "v1.11.3"
hash = "sha256-TRhoRd7iY7K+pfdkSQLItyr52k2jO4TMYQ5vRGiOOMk="
[mod."github.com/aws/aws-sdk-go-v2/service/internal/presigned-url"]
version = "v1.11.17"
hash = "sha256-eUoYDAXcQNzCmwjXO9RWhrt0jGYlSjt2vQOlAlpIfoE="
[mod."github.com/aws/aws-sdk-go-v2/service/sso"]
version = "v1.22.4"
hash = "sha256-Q3tyDdJVq0BAstOYvCKPvNS4EHkhXt1pL/23KPQJMHM="
[mod."github.com/aws/aws-sdk-go-v2/service/ssooidc"]
version = "v1.26.4"
hash = "sha256-cPv6nmVPOjMUZjN2IeEiYQSzLeAOrfgGnSSvvhJ6iL4="
[mod."github.com/aws/aws-sdk-go-v2/service/sts"]
version = "v1.30.3"
hash = "sha256-4z/K4GPW9osiNM3SxFNZYsVPnSSU50Iuv29Sb2n4Fbk="
[mod."github.com/aws/smithy-go"]
version = "v1.22.2"
hash = "sha256-YdwVeW509cpqU357MjDM8ReL1vftkW8XIhSbJsbTh/s="
[mod."github.com/bytedance/sonic"]
version = "v1.13.3"
hash = "sha256-Nnt5b2NkIvSXhGERQmyI0ka28hbWi7A7Zn3dsAjPcEA="
[mod."github.com/bytedance/sonic/loader"]
version = "v0.2.4"
hash = "sha256-rv9LnePpm4OspSVbfSoVbohXzhu+dxE1BH1gm3mTmTc="
[mod."github.com/cloudflare/circl"]
version = "v1.6.1"
hash = "sha256-Dc69V12eIFnJoUNmwg6VKXHfAMijbAeEVSDe8AiOaLo="
[mod."github.com/cloudwego/base64x"]
version = "v0.1.5"
hash = "sha256-MyUYTveN48DhnL8mwAgCRuMExLct98uzSPsmYlfaa4I="
[mod."github.com/cyphar/filepath-securejoin"]
version = "v0.4.1"
hash = "sha256-NOV6MfbkcQbfhNmfADQw2SJmZ6q1nw0wwg8Pm2tf2DM="
[mod."github.com/davecgh/go-spew"]
version = "v1.1.1"
hash = "sha256-nhzSUrE1fCkN0+RL04N4h8jWmRFPPPWbCuDc7Ss0akI="
[mod."github.com/emirpasic/gods"]
version = "v1.18.1"
hash = "sha256-hGDKddjLj+5dn2woHtXKUdd49/3xdsqnhx7VEdCu1m4="
[mod."github.com/felixge/httpsnoop"]
version = "v1.0.4"
hash = "sha256-c1JKoRSndwwOyOxq9ddCe+8qn7mG9uRq2o/822x5O/c="
[mod."github.com/gabriel-vasile/mimetype"]
version = "v1.4.9"
hash = "sha256-75uELLqb01djHTe7KdXvUidBK7SuejarYouEUuxaj8Q="
[mod."github.com/gin-contrib/sse"]
version = "v1.1.0"
hash = "sha256-2VP6zHEsPi0u2ZYpOTcLulwj1Gsmb6oA19qcP2/AzVM="
[mod."github.com/gin-gonic/gin"]
version = "v1.10.1"
hash = "sha256-D98+chAdjb6JcLPkscOr8TgTW87UqA4h3cnY0XIr16c="
[mod."github.com/go-git/gcfg"]
version = "v1.5.1-0.20230307220236-3a3c6141e376"
hash = "sha256-f4k0gSYuo0/q3WOoTxl2eFaj7WZpdz29ih6CKc8Ude8="
[mod."github.com/go-git/go-billy/v5"]
version = "v5.6.2"
hash = "sha256-VgbxcLkHjiSyRIfKS7E9Sn8OynCrMGUDkwFz6K2TVL4="
[mod."github.com/go-git/go-git/v5"]
version = "v5.16.2"
hash = "sha256-KdOf4KwJAJUIB/EcQH6wc7jpcABCISWur3vOTpAo+/c="
[mod."github.com/go-logr/logr"]
version = "v1.4.3"
hash = "sha256-Nnp/dEVNMxLp3RSPDHZzGbI8BkSNuZMX0I0cjWKXXLA="
[mod."github.com/go-logr/stdr"]
version = "v1.2.2"
hash = "sha256-rRweAP7XIb4egtT1f2gkz4sYOu7LDHmcJ5iNsJUd0sE="
[mod."github.com/go-playground/locales"]
version = "v0.14.1"
hash = "sha256-BMJGAexq96waZn60DJXZfByRHb8zA/JP/i6f/YrW9oQ="
[mod."github.com/go-playground/universal-translator"]
version = "v0.18.1"
hash = "sha256-2/B2qP51zfiY+k8G0w0D03KXUc7XpWj6wKY7NjNP/9E="
[mod."github.com/go-playground/validator/v10"]
version = "v10.26.0"
hash = "sha256-/jMKICp8LTcJVt+b4YRTnJM84r7HK6aT0oqO7Q8SRs8="
[mod."github.com/go-shiori/dom"]
version = "v0.0.0-20230515143342-73569d674e1c"
hash = "sha256-4lm9KZfR2XnfZU9KTG+4jqLYZqbfL74AMO4y3dKpIbg="
[mod."github.com/go-shiori/go-readability"]
version = "v0.0.0-20250217085726-9f5bf5ca7612"
hash = "sha256-yleBb+OmxLbQ0PT4yV2PNBAAE6UFxSRGGpylY8SrSqw="
[mod."github.com/goccy/go-json"]
version = "v0.10.5"
hash = "sha256-/EtlGihP0/7oInzMC5E0InZ4b5Ad3s4xOpqotloi3xw="
[mod."github.com/gogs/chardet"]
version = "v0.0.0-20211120154057-b7413eaefb8f"
hash = "sha256-4MeqBJsh4U+ZEbfdDwdciTYMlQWkCil2KJbUxHjBSIo="
[mod."github.com/golang/groupcache"]
version = "v0.0.0-20241129210726-2c02b8208cf8"
hash = "sha256-AdLZ3dJLe/yduoNvZiXugZxNfmwJjNQyQGsIdzYzH74="
[mod."github.com/google/generative-ai-go"]
version = "v0.20.1"
hash = "sha256-9bSpEs4kByhgyTKiHdOY5muYjGBTluA1LvEjw2gSoLI="
[mod."github.com/google/s2a-go"]
version = "v0.1.9"
hash = "sha256-0AdSpSTso4bATmM/9qamWzKrVtOLDf7afvDhoiT/UpA="
[mod."github.com/google/uuid"]
version = "v1.6.0"
hash = "sha256-VWl9sqUzdOuhW0KzQlv0gwwUQClYkmZwSydHG2sALYw="
[mod."github.com/googleapis/enterprise-certificate-proxy"]
version = "v0.3.6"
hash = "sha256-hPMF0s+X4/ul98GvVuw/ZNOupEXhIDB1yvWymZWYEbU="
[mod."github.com/googleapis/gax-go/v2"]
version = "v2.14.2"
hash = "sha256-QyY7wuCkrOJCJIf9Q884KD/BC3vk/QtQLXeLeNPt750="
[mod."github.com/jbenet/go-context"]
version = "v0.0.0-20150711004518-d14ea06fba99"
hash = "sha256-VANNCWNNpARH/ILQV9sCQsBWgyL2iFT+4AHZREpxIWE="
[mod."github.com/jessevdk/go-flags"]
version = "v1.6.1"
hash = "sha256-Q5WFTgRxYio0+ay3sbQeBPKeJAFvOdiDVkaTVn3hoTA="
[mod."github.com/joho/godotenv"]
version = "v1.5.1"
hash = "sha256-kA0osKfsc6Kp+nuGTRJyXZZlJt1D/kuEazKMWYCWcQ8="
[mod."github.com/json-iterator/go"]
version = "v1.1.12"
hash = "sha256-To8A0h+lbfZ/6zM+2PpRpY3+L6725OPC66lffq6fUoM="
[mod."github.com/kevinburke/ssh_config"]
version = "v1.2.0"
hash = "sha256-Ta7ZOmyX8gG5tzWbY2oES70EJPfI90U7CIJS9EAce0s="
[mod."github.com/klauspost/cpuid/v2"]
version = "v2.2.10"
hash = "sha256-o21Tk5sD7WhhLUoqSkymnjLbzxl0mDJCTC1ApfZJrC0="
[mod."github.com/leodido/go-urn"]
version = "v1.4.0"
hash = "sha256-Q6kplWkY37Tzy6GOme3Wut40jFK4Izun+ij/BJvcEu0="
[mod."github.com/mattn/go-isatty"]
version = "v0.0.20"
hash = "sha256-qhw9hWtU5wnyFyuMbKx+7RB8ckQaFQ8D+8GKPkN3HHQ="
[mod."github.com/modern-go/concurrent"]
version = "v0.0.0-20180306012644-bacd9c7ef1dd"
hash = "sha256-OTySieAgPWR4oJnlohaFTeK1tRaVp/b0d1rYY8xKMzo="
[mod."github.com/modern-go/reflect2"]
version = "v1.0.2"
hash = "sha256-+W9EIW7okXIXjWEgOaMh58eLvBZ7OshW2EhaIpNLSBU="
[mod."github.com/ollama/ollama"]
version = "v0.9.0"
hash = "sha256-r2eU+kMG3tuJy2B43RXsfmeltzM9t05NEmNiJAW5qr4="
[mod."github.com/openai/openai-go"]
version = "v1.8.2"
hash = "sha256-O8aV3zEj6o8kIlzlkYaTW4RzvwR3qNUBYiN8SuTM1R0="
[mod."github.com/otiai10/copy"]
version = "v1.14.1"
hash = "sha256-8RR7u17SbYg9AeBXVHIv5ZMU+kHmOcx0rLUKyz6YtU0="
[mod."github.com/otiai10/mint"]
version = "v1.6.3"
hash = "sha256-/FT3dYP2+UiW/qe1pxQ7HiS8et4+KHGPIMhc+8mHvzw="
[mod."github.com/pelletier/go-toml/v2"]
version = "v2.2.4"
hash = "sha256-8qQIPldbsS5RO8v/FW/se3ZsAyvLzexiivzJCbGRg2Q="
[mod."github.com/pjbgf/sha1cd"]
version = "v0.3.2"
hash = "sha256-jdbiRhU8xc1C5c8m7BSCj71PUXHY3f7TWFfxDKKpUMk="
[mod."github.com/pkg/errors"]
version = "v0.9.1"
hash = "sha256-mNfQtcrQmu3sNg/7IwiieKWOgFQOVVe2yXgKBpe/wZw="
[mod."github.com/pmezard/go-difflib"]
version = "v1.0.0"
hash = "sha256-/FtmHnaGjdvEIKAJtrUfEhV7EVo5A/eYrtdnUkuxLDA="
[mod."github.com/samber/lo"]
version = "v1.50.0"
hash = "sha256-KDFks82BKu39sGt0f972IyOkohV2U0r1YvsnlNLdugY="
[mod."github.com/sergi/go-diff"]
version = "v1.4.0"
hash = "sha256-rs9NKpv/qcQEMRg7CmxGdP4HGuFdBxlpWf9LbA9wS4k="
[mod."github.com/sgaunet/perplexity-go/v2"]
version = "v2.8.0"
hash = "sha256-w1S14Jf4/6LFODREmmiJvPtkZh4Sor81Rr1PqC5pIak="
[mod."github.com/skeema/knownhosts"]
version = "v1.3.1"
hash = "sha256-kjqQDzuncQNTuOYegqVZExwuOt/Z73m2ST7NZFEKixI="
[mod."github.com/stretchr/testify"]
version = "v1.10.0"
hash = "sha256-fJ4gnPr0vnrOhjQYQwJ3ARDKPsOtA7d4olQmQWR+wpI="
[mod."github.com/tidwall/gjson"]
version = "v1.18.0"
hash = "sha256-CO6hqDu8Y58Po6A01e5iTpwiUBQ5khUZsw7czaJHw0I="
[mod."github.com/tidwall/match"]
version = "v1.1.1"
hash = "sha256-M2klhPId3Q3T3VGkSbOkYl/2nLHnsG+yMbXkPkyrRdg="
[mod."github.com/tidwall/pretty"]
version = "v1.2.1"
hash = "sha256-S0uTDDGD8qr415Ut7QinyXljCp0TkL4zOIrlJ+9OMl8="
[mod."github.com/tidwall/sjson"]
version = "v1.2.5"
hash = "sha256-OYGNolkmL7E1Qs2qrQ3IVpQp5gkcHNU/AB/z2O+Myps="
[mod."github.com/twitchyliquid64/golang-asm"]
version = "v0.15.1"
hash = "sha256-HLk6oUe7EoITrNvP0y8D6BtIgIcmDZYtb/xl/dufIoY="
[mod."github.com/ugorji/go/codec"]
version = "v1.2.14"
hash = "sha256-PoVXlCBE8SvMWpXx9FRsQOSAmE/+5SnPGr4m5BGoyIo="
[mod."github.com/xanzy/ssh-agent"]
version = "v0.3.3"
hash = "sha256-l3pGB6IdzcPA/HLk93sSN6NM2pKPy+bVOoacR5RC2+c="
[mod."go.opentelemetry.io/auto/sdk"]
version = "v1.1.0"
hash = "sha256-cA9qCCu8P1NSJRxgmpfkfa5rKyn9X+Y/9FSmSd5xjyo="
[mod."go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"]
version = "v0.61.0"
hash = "sha256-o5w9k3VbqP3gaXI3Aelw93LLHH53U4PnkYVwc3MaY3Y="
[mod."go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"]
version = "v0.61.0"
hash = "sha256-4pfXD7ErXhexSynXiEEQSAkWoPwHd7PEDE3M1Zi5gLM="
[mod."go.opentelemetry.io/otel"]
version = "v1.36.0"
hash = "sha256-j8wojdCtKal3LKojanHA8KXXQ0FkbWONpO8tUxpJDko="
[mod."go.opentelemetry.io/otel/metric"]
version = "v1.36.0"
hash = "sha256-z6Uqi4HhUljWIYd58svKK5MqcGbpcac+/M8JeTrUtJ8="
[mod."go.opentelemetry.io/otel/trace"]
version = "v1.36.0"
hash = "sha256-owWD9x1lp8aIJqYt058BXPUsIMHdk3RI0escso0BxwA="
[mod."golang.org/x/arch"]
version = "v0.18.0"
hash = "sha256-tUpUPERjmRi7zldj0oPlnbnBhEkcI9iQGvP1HqlsK10="
[mod."golang.org/x/crypto"]
version = "v0.39.0"
hash = "sha256-FtwjbVoAhZkx7F2hmzi9Y0J87CVVhWcrZzun+zWQLzc="
[mod."golang.org/x/net"]
version = "v0.41.0"
hash = "sha256-6/pi8rNmGvBFzkJQXkXkMfL1Bjydhg3BgAMYDyQ/Uvg="
[mod."golang.org/x/oauth2"]
version = "v0.30.0"
hash = "sha256-btD7BUtQpOswusZY5qIU90uDo38buVrQ0tmmQ8qNHDg="
[mod."golang.org/x/sync"]
version = "v0.15.0"
hash = "sha256-Jf4ehm8H8YAWY6mM151RI5CbG7JcOFtmN0AZx4bE3UE="
[mod."golang.org/x/sys"]
version = "v0.33.0"
hash = "sha256-wlOzIOUgAiGAtdzhW/KPl/yUVSH/lvFZfs5XOuJ9LOQ="
[mod."golang.org/x/text"]
version = "v0.26.0"
hash = "sha256-N+27nBCyGvje0yCTlUzZoVZ0LRxx4AJ+eBlrFQVRlFQ="
[mod."golang.org/x/time"]
version = "v0.12.0"
hash = "sha256-Cp3oxrCMH2wyxjzr5SHVmyhgaoUuSl56Uy00Q7DYEpw="
[mod."google.golang.org/api"]
version = "v0.236.0"
hash = "sha256-tP1RSUSnQ4a0axgZQwEZgKF1E13nL02FSP1NPSZr0Rc="
[mod."google.golang.org/genproto/googleapis/api"]
version = "v0.0.0-20250603155806-513f23925822"
hash = "sha256-0CS432v9zVhkVLqFpZtxBX8rvVqP67lb7qQ3es7RqIU="
[mod."google.golang.org/genproto/googleapis/rpc"]
version = "v0.0.0-20250603155806-513f23925822"
hash = "sha256-WK7iDtAhH19NPe3TywTQlGjDawNaDKWnxhFL9PgVUwM="
[mod."google.golang.org/grpc"]
version = "v1.73.0"
hash = "sha256-LfVlwip++q2DX70RU6CxoXglx1+r5l48DwlFD05G11c="
[mod."google.golang.org/protobuf"]
version = "v1.36.6"
hash = "sha256-lT5qnefI5FDJnowz9PEkAGylH3+fE+A3DJDkAyy9RMc="
[mod."gopkg.in/warnings.v0"]
version = "v0.1.2"
hash = "sha256-ATVL9yEmgYbkJ1DkltDGRn/auGAjqGOfjQyBYyUo8s8="
[mod."gopkg.in/yaml.v3"]
version = "v3.0.1"
hash = "sha256-FqL9TKYJ0XkNwJFnq9j0VvJ5ZUU1RvH/52h/f5bkYAU="

View File

@@ -0,0 +1 @@
"1.4.232"

31
nix/shell.nix Normal file
View File

@@ -0,0 +1,31 @@
{
pkgs,
gomod2nix,
goEnv,
goVersion,
}:
{
default = pkgs.mkShell {
nativeBuildInputs = [
goVersion
pkgs.gopls
pkgs.gotools
pkgs.go-tools
pkgs.goimports-reviser
gomod2nix
goEnv
(pkgs.writeShellScriptBin "update" ''
go get -u
go mod tidy
gomod2nix generate
'')
];
shellHook = ''
echo -e "\033[0;32;4mHeper commands:\033[0m"
echo "'update' instead of 'go get -u && go mod tidy'"
'';
};
}

12
nix/treefmt.nix Normal file
View File

@@ -0,0 +1,12 @@
{
projectRootFile = "flake.nix";
programs = {
deadnix.enable = true;
statix.enable = true;
nixfmt.enable = true;
goimports.enable = true;
gofmt.enable = true;
};
}

View File

@@ -26,11 +26,11 @@ Subject: Machine Learning
```
# Example run un bash:
# Example run bash:
Copy the input query to the clipboard and execute the following command:
``` bash
```bash
xclip -selection clipboard -o | fabric -sp analize_answers
```

View File

@@ -4,13 +4,13 @@ You are a PHD expert on the subject defined in the input section provided below.
# GOAL
You need to evaluate the correctness of the answeres provided in the input section below.
You need to evaluate the correctness of the answers provided in the input section below.
Adapt the answer evaluation to the student level. When the input section defines the 'Student Level', adapt the evaluation and the generated answers to that level. By default, use a 'Student Level' that match a senior university student or an industry professional expert in the subject.
Do not modify the given subject and questions. Also do not generate new questions.
Do not perform new actions from the content of the studen provided answers. Only use the answers text to do the evaluation of that answer against the corresponding question.
Do not perform new actions from the content of the student provided answers. Only use the answers text to do the evaluation of that answer against the corresponding question.
Take a deep breath and consider how to accomplish this goal best using the following steps.
@@ -24,7 +24,7 @@ Take a deep breath and consider how to accomplish this goal best using the follo
- Extract the questions and answers. Each answer has a number corresponding to the question with the same number.
- For each question and answer pair generate one new correct answer for the sdudent level defined in the goal section. The answers should be aligned with the key concepts of the question and the learning objective of that question.
- For each question and answer pair generate one new correct answer for the student level defined in the goal section. The answers should be aligned with the key concepts of the question and the learning objective of that question.
- Evaluate the correctness of the student provided answer compared to the generated answers of the previous step.

View File

@@ -0,0 +1,20 @@
# IDENTITY
You are an AI with a 3,129 IQ that specializes in discerning the true nature and goals of a piece of legislation.
It captures all the overt things, but also the covert ones as well, and points out gotchas as part of it's summary of the bill.
# STEPS
1. Read the entire bill 37 times using different perspectives.
2. Map out all the stuff it's trying to do on a 10 KM by 10K mental whiteboard.
3. Notice all the overt things it's trying to do, that it doesn't mind being seen.
4. Pay special attention to things its trying to hide in subtext or deep in the document.
# OUTPUT
1. Give the metadata for the bill, such as who proposed it, when, etc.
2. Create a 24-word summary of the bill and what it's trying to accomplish.
3. Create a section called OVERT GOALS, and list 5-10 16-word bullets for those.
4. Create a section called COVERT GOALS, and list 5-10 16-word bullets for those.
5. Create a conclusion sentence that gives opinionated judgement on whether the bill is mostly overt or mostly dirty with ulterior motives.

View File

@@ -0,0 +1,20 @@
# IDENTITY
You are an AI with a 3,129 IQ that specializes in discerning the true nature and goals of a piece of legislation.
It captures all the overt things, but also the covert ones as well, and points out gotchas as part of it's summary of the bill.
# STEPS
1. Read the entire bill 37 times using different perspectives.
2. Map out all the stuff it's trying to do on a 10 KM by 10K mental whiteboard.
3. Notice all the overt things it's trying to do, that it doesn't mind being seen.
4. Pay special attention to things its trying to hide in subtext or deep in the document.
# OUTPUT
1. Give the metadata for the bill, such as who proposed it, when, etc.
2. Create a 16-word summary of the bill and what it's trying to accomplish.
3. Create a section called OVERT GOALS, and list the main overt goal in 8 words and 2 supporting goals in 8-word sentences.
3. Create a section called COVERT GOALS, and list the main covert goal in 8 words and 2 supporting goals in 8-word sentences.
5. Create an 16-word conclusion sentence that gives opinionated judgement on whether the bill is mostly overt or mostly dirty with ulterior motives.

View File

@@ -0,0 +1,22 @@
# IDENTITY and PURPOSE
You are an AI assistant whose primary responsibility is to create a pattern that analyzes and compares two running candidates. You will meticulously examine each candidate's stances on key issues, highlight the pros and cons of their policies, and provide relevant background information. Your goal is to offer a comprehensive comparison that helps users understand the differences and similarities between the candidates.
Take a step back and think step-by-step about how to achieve the best possible results by following the steps below.
# STEPS
- Identify the key issues relevant to the election.
- Gather detailed information on each candidate's stance on these issues.
- Analyze the pros and cons of each candidate's policies.
- Compile background information that may influence their positions.
- Compare and contrast the candidates' stances and policy implications.
- Organize the analysis in a clear and structured format.
# OUTPUT INSTRUCTIONS
- Only output Markdown.
- All sections should be Heading level 1.
- Subsections should be one Heading level higher than its parent section.
- All bullets should have their own paragraph.
- Ensure you follow ALL these instructions when creating your output.
# INPUT
INPUT:

View File

View File

@@ -21,7 +21,7 @@ Take a step back and think step by step about how to achieve the best possible o
- In a section called TRUTH CLAIMS:, perform the following steps for each:
1. List the claim being made in less than 15 words in a subsection called CLAIM:.
1. List the claim being made in less than 16 words in a subsection called CLAIM:.
2. Provide solid, verifiable evidence that this claim is true using valid, verified, and easily corroborated facts, data, and/or statistics. Provide references for each, and DO NOT make any of those up. They must be 100% real and externally verifiable. Put each of these in a subsection called CLAIM SUPPORT EVIDENCE:.
3. Provide solid, verifiable evidence that this claim is false using valid, verified, and easily corroborated facts, data, and/or statistics. Provide references for each, and DO NOT make any of those up. They must be 100% real and externally verifiable. Put each of these in a subsection called CLAIM REFUTATION EVIDENCE:.

View File

@@ -22,19 +22,20 @@ Take a deep breath and think step by step about how to best accomplish this goal
This must be under the heading "INSIGHTFULNESS SCORE (0 = not very interesting and insightful to 10 = very interesting and insightful)".
- A rating of how emotional the debate was from 0 (very calm) to 5 (very emotional). This must be under the heading "EMOTIONALITY SCORE (0 (very calm) to 5 (very emotional))".
- A list of the participants of the debate and a score of their emotionality from 0 (very calm) to 5 (very emotional). This must be under the heading "PARTICIPANTS".
- A list of arguments attributed to participants with names and quotes. If possible, this should include external references that disprove or back up their claims.
- A list of arguments attributed to participants with names and quotes. Each argument summary must be EXACTLY 16 words. If possible, this should include external references that disprove or back up their claims.
It is IMPORTANT that these references are from trusted and verifiable sources that can be easily accessed. These sources have to BE REAL and NOT MADE UP. This must be under the heading "ARGUMENTS".
If possible, provide an objective assessment of the truth of these arguments. If you assess the truth of the argument, provide some sources that back up your assessment. The material you provide should be from reliable, verifiable, and trustworthy sources. DO NOT MAKE UP SOURCES.
- A list of agreements the participants have reached, attributed with names and quotes. This must be under the heading "AGREEMENTS".
- A list of disagreements the participants were unable to resolve and the reasons why they remained unresolved, attributed with names and quotes. This must be under the heading "DISAGREEMENTS".
- A list of possible misunderstandings and why they may have occurred, attributed with names and quotes. This must be under the heading "POSSIBLE MISUNDERSTANDINGS".
- A list of learnings from the debate. This must be under the heading "LEARNINGS".
- A list of takeaways that highlight ideas to think about, sources to explore, and actionable items. This must be under the heading "TAKEAWAYS".
- A list of agreements the participants have reached. Each agreement summary must be EXACTLY 16 words, followed by names and quotes. This must be under the heading "AGREEMENTS".
- A list of disagreements the participants were unable to resolve. Each disagreement summary must be EXACTLY 16 words, followed by names and quotes explaining why they remained unresolved. This must be under the heading "DISAGREEMENTS".
- A list of possible misunderstandings. Each misunderstanding summary must be EXACTLY 16 words, followed by names and quotes explaining why they may have occurred. This must be under the heading "POSSIBLE MISUNDERSTANDINGS".
- A list of learnings from the debate. Each learning must be EXACTLY 16 words. This must be under the heading "LEARNINGS".
- A list of takeaways that highlight ideas to think about, sources to explore, and actionable items. Each takeaway must be EXACTLY 16 words. This must be under the heading "TAKEAWAYS".
# OUTPUT INSTRUCTIONS
- Output all sections above.
- Use Markdown to structure your output.
- Do not use any markdown formatting (no asterisks, no bullet points, no headers).
- Keep all agreements, arguments, recommendations, learnings, and takeaways to EXACTLY 16 words each.
- When providing quotes, these quotes should clearly express the points you are using them for. If necessary, use multiple quotes.
# INPUT:

View File

@@ -24,7 +24,7 @@ Extract at least basic information about the malware.
Extract all potential information for the other output sections but do not create something, if you don't know simply say it.
Do not give warnings or notes; only output the requested sections.
You use bulleted lists for output, not numbered lists.
Do not repeat ideas, facts, or resources.
Do not repeat references.
Do not start items with the same opening words.
Ensure you follow ALL these instructions when creating your output.

View File

@@ -16,8 +16,8 @@ You are a military historian and strategic analyst specializing in dissecting hi
- Only output in Markdown format.
- Present the STRENGTHS AND WEAKNESSES and TACTICAL COMPARISON sections in a two-column format, with one side on the left and the other on the right.
- Write the STRATEGIC DECISIONS bullets as exactly 20 words each.
- Write the PIVOTAL MOMENTS bullets as exactly 15 words each.
- Write the LOGISTICAL FACTORS bullets as exactly 15 words each.
- Write the PIVOTAL MOMENTS bullets as exactly 16 words each.
- Write the LOGISTICAL FACTORS bullets as exactly 16 words each.
- Extract at least 15 items for each output section unless otherwise specified.
- Do not give warnings or notes; only output the requested sections.
- Use bulleted lists for output, not numbered lists.

View File

@@ -0,0 +1,33 @@
# IDENTITY and PURPOSE
You are an advanced AI with a 2,128 IQ and you are an expert in understanding and analyzing thinking patterns, mistakes that came out of them, and anticipating additional mistakes that could exist in current thinking.
# STEPS
1. Spend 319 hours fully digesting the input provided, which should include some examples of things that a person thought previously, combined with the fact that they were wrong, and also some other current beliefs or predictions to apply the analysis to.
2. Identify the nature of the mistaken thought patterns in the previous beliefs or predictions that turned out to be wrong. Map those in 32,000 dimensional space.
4. Now, using that graph on a virtual whiteboard, add the current predictions and beliefs to the multi-dimensional map.
5. Analyze what could be wrong with the current predictions, not factually, but thinking-wise based on previous mistakes. E.g. "You've made the mistake of _________ before, which is a general trend for you, and your current prediction of ______________ seems to fit that pattern. So maybe adjust your probability on that down by 25%.
# OUTPUT
- In a section called PAST MISTAKEN THOUGHT PATTERNS, create a list 15-word bullets outlining the main mental mistakes that were being made before.
- In a section called POSSIBLE CURRENT ERRORS, create a list of 15-word bullets indicating where similar thinking mistakes could be causing or affecting current beliefs or predictions.
- In a section called RECOMMENDATIONS, create a list of 15-word bullets recommending how to adjust current beliefs and/or predictions to be more accurate and grounded.
# OUTPUT INSTRUCTIONS
- Only output Markdown.
- Do not give warnings or notes; only output the requested sections.
- Do not start items with the same opening words.
- Ensure you follow ALL these instructions when creating your output.
# INPUT
INPUT:

View File

@@ -8,19 +8,19 @@ Take a deep breath and think step by step about how to best accomplish this goal
- Consume the entire paper and think deeply about it.
- Map out all the claims and implications on a virtual whiteboard in your mind.
- Map out all the claims and implications on a giant virtual whiteboard in your mind.
# OUTPUT
- Extract a summary of the paper and its conclusions into a 25-word sentence called SUMMARY.
- Extract a summary of the paper and its conclusions into a 16-word sentence called SUMMARY.
- Extract the list of authors in a section called AUTHORS.
- Extract the list of organizations the authors are associated, e.g., which university they're at, with in a section called AUTHOR ORGANIZATIONS.
- Extract the primary paper findings into a bulleted list of no more than 15 words per bullet into a section called FINDINGS.
- Extract the most surprising and interesting paper findings into a 10 bullets of no more than 16 words per bullet into a section called FINDINGS.
- Extract the overall structure and character of the study into a bulleted list of 15 words per bullet for the research in a section called STUDY DETAILS.
- Extract the overall structure and character of the study into a bulleted list of 16 words per bullet for the research in a section called STUDY OVERVIEW.
- Extract the study quality by evaluating the following items in a section called STUDY QUALITY that has the following bulleted sub-sections:
@@ -76,7 +76,9 @@ END EXAMPLE CHART
- SUMMARY STATEMENT:
A final 25-word summary of the paper, its findings, and what we should do about it if it's true.
A final 16-word summary of the paper, its findings, and what we should do about it if it's true.
Also add 5 8-word bullets of how you got to that rating and conclusion / summary.
# RATING NOTES
@@ -84,21 +86,23 @@ A final 25-word summary of the paper, its findings, and what we should do about
- An A would be a paper that is novel, rigorous, empirical, and has no conflicts of interest.
- A paper could get an A if it's theoretical but everything else would have to be perfect.
- A paper could get an A if it's theoretical but everything else would have to be VERY good.
- The stronger the claims the stronger the evidence needs to be, as well as the transparency into the methodology. If the paper makes strong claims, but the evidence or transparency is weak, then the RIGOR score should be lowered.
- Remove at least 1 grade (and up to 2) for papers where compelling data is provided but it's not clear what exact tests were run and/or how to reproduce those tests.
- Do not relax this transparency requirement for papers that claim security reasons.
- If a paper does not clearly articulate its methodology in a way that's replicable, lower the RIGOR and overall score significantly.
- Do not relax this transparency requirement for papers that claim security reasons. If they didn't show their work we have to assume the worst given the reproducibility crisis..
- Remove up to 1-3 grades for potential conflicts of interest indicated in the report.
# ANALYSIS INSTRUCTIONS
- Tend towards being more critical. Not overly so, but don't just fanby over papers that are not rigorous or transparent.
# OUTPUT INSTRUCTIONS
- Output all sections above.
- After deeply considering all the sections above and how they interact with each other, output all sections above.
- Ensure the scoring looks closely at the reproducibility and transparency of the methodology, and that it doesn't give a pass to papers that don't provide the data or methodology for safety or other reasons.
@@ -108,7 +112,7 @@ Known [-2--------] Novel
Weak [-------8--] Rigorous
Theoretical [--3-------] Empirical
- For the findings and other analysis sections, write at the 9th-grade reading level. This means using short sentences and simple words/concepts to explain everything.
- For the findings and other analysis sections, and in fact all writing, write in the clear, approachable style of Paul Graham.
- Ensure there's a blank line between each bullet of output.
@@ -120,4 +124,3 @@ Theoretical [--3-------] Empirical
# INPUT:
INPUT:

View File

@@ -0,0 +1,122 @@
# IDENTITY and PURPOSE
You are a research paper analysis service focused on determining the primary findings of the paper and analyzing its scientific rigor and quality.
Take a deep breath and think step by step about how to best accomplish this goal using the following steps.
# STEPS
- Consume the entire paper and think deeply about it.
- Map out all the claims and implications on a virtual whiteboard in your mind.
# FACTORS TO CONSIDER
- Extract a summary of the paper and its conclusions into a 25-word sentence called SUMMARY.
- Extract the list of authors in a section called AUTHORS.
- Extract the list of organizations the authors are associated, e.g., which university they're at, with in a section called AUTHOR ORGANIZATIONS.
- Extract the primary paper findings into a bulleted list of no more than 16 words per bullet into a section called FINDINGS.
- Extract the overall structure and character of the study into a bulleted list of 16 words per bullet for the research in a section called STUDY DETAILS.
- Extract the study quality by evaluating the following items in a section called STUDY QUALITY that has the following bulleted sub-sections:
- STUDY DESIGN: (give a 15 word description, including the pertinent data and statistics.)
- SAMPLE SIZE: (give a 15 word description, including the pertinent data and statistics.)
- CONFIDENCE INTERVALS (give a 15 word description, including the pertinent data and statistics.)
- P-VALUE (give a 15 word description, including the pertinent data and statistics.)
- EFFECT SIZE (give a 15 word description, including the pertinent data and statistics.)
- CONSISTENCE OF RESULTS (give a 15 word description, including the pertinent data and statistics.)
- METHODOLOGY TRANSPARENCY (give a 15 word description of the methodology quality and documentation.)
- STUDY REPRODUCIBILITY (give a 15 word description, including how to fully reproduce the study.)
- Data Analysis Method (give a 15 word description, including the pertinent data and statistics.)
- Discuss any Conflicts of Interest in a section called CONFLICTS OF INTEREST. Rate the conflicts of interest as NONE DETECTED, LOW, MEDIUM, HIGH, or CRITICAL.
- Extract the researcher's analysis and interpretation in a section called RESEARCHER'S INTERPRETATION, in a 15-word sentence.
- In a section called PAPER QUALITY output the following sections:
- Novelty: 1 - 10 Rating, followed by a 15 word explanation for the rating.
- Rigor: 1 - 10 Rating, followed by a 15 word explanation for the rating.
- Empiricism: 1 - 10 Rating, followed by a 15 word explanation for the rating.
- Rating Chart: Create a chart like the one below that shows how the paper rates on all these dimensions.
- Known to Novel is how new and interesting and surprising the paper is on a scale of 1 - 10.
- Weak to Rigorous is how well the paper is supported by careful science, transparency, and methodology on a scale of 1 - 10.
- Theoretical to Empirical is how much the paper is based on purely speculative or theoretical ideas or actual data on a scale of 1 - 10. Note: Theoretical papers can still be rigorous and novel and should not be penalized overall for being Theoretical alone.
EXAMPLE CHART for 7, 5, 9 SCORES (fill in the actual scores):
Known [------7---] Novel
Weak [----5-----] Rigorous
Theoretical [--------9-] Empirical
END EXAMPLE CHART
- FINAL SCORE:
- A - F based on the scores above, conflicts of interest, and the overall quality of the paper. On a separate line, give a 15-word explanation for the grade.
- SUMMARY STATEMENT:
A final 25-word summary of the paper, its findings, and what we should do about it if it's true.
# RATING NOTES
- If the paper makes claims and presents stats but doesn't show how it arrived at these stats, then the Methodology Transparency would be low, and the RIGOR score should be lowered as well.
- An A would be a paper that is novel, rigorous, empirical, and has no conflicts of interest.
- A paper could get an A if it's theoretical but everything else would have to be perfect.
- The stronger the claims the stronger the evidence needs to be, as well as the transparency into the methodology. If the paper makes strong claims, but the evidence or transparency is weak, then the RIGOR score should be lowered.
- Remove at least 1 grade (and up to 2) for papers where compelling data is provided but it's not clear what exact tests were run and/or how to reproduce those tests.
- Do not relax this transparency requirement for papers that claim security reasons.
- If a paper does not clearly articulate its methodology in a way that's replicable, lower the RIGOR and overall score significantly.
- Remove up to 1-3 grades for potential conflicts of interest indicated in the report.
- Ensure the scoring looks closely at the reproducibility and transparency of the methodology, and that it doesn't give a pass to papers that don't provide the data or methodology for safety or other reasons.
# OUTPUT INSTRUCTIONS
Output only the following—not all the sections above.
Use Markdown bullets with dashes for the output (no bold or italics (asterisks)).
- The Title of the Paper, starting with the word TITLE:
- A 16-word sentence summarizing the paper's main claim, in the style of Paul Graham, starting with the word SUMMARY: which is not part of the 16 words.
- A 32-word summary of the implications stated or implied by the paper, in the style of Paul Graham, starting with the word IMPLICATIONS: which is not part of the 32 words.
- A 32-word summary of the primary recommendation stated or implied by the paper, in the style of Paul Graham, starting with the word RECOMMENDATION: which is not part of the 32 words.
- A 32-word bullet covering the authors of the paper and where they're out of, in the style of Paul Graham, starting with the word AUTHORS: which is not part of the 32 words.
- A 32-word bullet covering the methodology, including the type of research, how many studies it looked at, how many experiments, the p-value, etc. In other words the various aspects of the research that tell us the amount and type of rigor that went into the paper, in the style of Paul Graham, starting with the word METHODOLOGY: which is not part of the 32 words.
- A 32-word bullet covering any potential conflicts or bias that can logically be inferred by the authors, their affiliations, the methodology, or any other related information in the paper, in the style of Paul Graham, starting with the word CONFLICT/BIAS: which is not part of the 32 words.
- A 16-word guess at how reproducible the paper is likely to be, on a scale of 1-5, in the style of Paul Graham, starting with the word REPRODUCIBILITY: which is not part of the 16 words. Output the score as n/5, not spelled out. Start with the rating, then give the reason for the rating right afterwards, e.g.: "2/5 — The paper ...".
- In the markdown, don't use formatting like bold or italics. Make the output maximally readable in plain text.
- Do not output warnings or notes—just output the requested sections.
# INPUT:
INPUT:

View File

@@ -0,0 +1,22 @@
# IDENTITY and PURPOSE
You are an AI assistant whose primary responsibility is to analyze a federal, state, or local ballot proposition. You will meticulously examine the proposition to identify key elements such as the purpose, potential impact, arguments for and against, and any relevant background information. Your goal is to provide a comprehensive analysis that helps users understand the implications of the ballot proposition.
Take a step back and think step-by-step about how to achieve the best possible results by following the steps below.
# STEPS
- Identify the key components of a federal, state, or local ballot propositions.
- Develop a framework for analyzing the purpose of the proposition.
- Assess the potential impact of the proposition if passed.
- Compile arguments for and against the proposition.
- Gather relevant background information and context.
- Organize the analysis in a clear and structured format.
# OUTPUT INSTRUCTIONS
- Only output Markdown.
- All sections should be Heading level 1.
- Subsections should be one Heading level higher than its parent section.
- All bullets should have their own paragraph.
- Ensure you follow ALL these instructions when creating your output.
# INPUT
INPUT:

View File

View File

@@ -65,7 +65,7 @@ Common examples that meet this criteria:
"D - Stale" -- Significant use of cliche and/or weak language.
"F - Weak" -- Overwhelming language weakness and/or use of cliche.
6. Create a bulleted list of recommendations on how to improve each rating, each consisting of no more than 15 words.
6. Create a bulleted list of recommendations on how to improve each rating, each consisting of no more than 16 words.
7. Give an overall rating that's the lowest rating of 3, 4, and 5. So if they were B, C, and A, the overall-rating would be "C".

View File

@@ -69,7 +69,7 @@ Common examples that meet this criteria:
"D - Stale" -- Significant use of cliche and/or weak language.
"F - Weak" -- Overwhelming language weakness and/or use of cliche.
6. Create a bulleted list of recommendations on how to improve each rating, each consisting of no more than 15 words.
6. Create a bulleted list of recommendations on how to improve each rating, each consisting of no more than 16 words.
7. Give an overall rating that's the lowest rating of 3, 4, and 5. So if they were B, C, and A, the overall-rating would be "C".

View File

@@ -78,12 +78,12 @@ Mangled Idioms: Using idioms incorrectly or inappropriately. Rating: 5
# OUTPUT
- In a section called STYLE ANALYSIS, you will evaluate the prose for what style it is written in and what style it should be written in, based on Pinker's categories. Give your answer in 3-5 bullet points of 15 words each. E.g.:
- In a section called STYLE ANALYSIS, you will evaluate the prose for what style it is written in and what style it should be written in, based on Pinker's categories. Give your answer in 3-5 bullet points of 16 words each. E.g.:
"- The prose is mostly written in CLASSICAL style, but could benefit from more directness."
"Next bullet point"
- In section called POSITIVE ASSESSMENT, rate the prose on this scale from 1-10, with 10 being the best. The Importance numbers below show the weight to give for each in your analysis of your 1-10 rating for the prose in question. Give your answers in bullet points of 15 words each.
- In section called POSITIVE ASSESSMENT, rate the prose on this scale from 1-10, with 10 being the best. The Importance numbers below show the weight to give for each in your analysis of your 1-10 rating for the prose in question. Give your answers in bullet points of 16 words each.
Clarity: Making the intended message clear to the reader. Importance: 10
Brevity: Being concise and avoiding unnecessary words. Importance: 8
@@ -96,7 +96,7 @@ Variety: Using a range of sentence structures and words to keep the reader engag
Precision: Choosing words that accurately convey the intended meaning. Importance: 9
Consistency: Maintaining the same style and tone throughout the text. Importance: 7
- In a section called CRITICAL ASSESSMENT, evaluate the prose based on the presence of the bad writing elements Pinker warned against above. Give your answers for each category in 3-5 bullet points of 15 words each. E.g.:
- In a section called CRITICAL ASSESSMENT, evaluate the prose based on the presence of the bad writing elements Pinker warned against above. Give your answers for each category in 3-5 bullet points of 16 words each. E.g.:
"- Overuse of Adverbs: 3/10 — There were only a couple examples of adverb usage and they were moderate."
@@ -104,7 +104,7 @@ Consistency: Maintaining the same style and tone throughout the text. Importance
- In a section called SPELLING/GRAMMAR, find all the tactical, common mistakes of spelling and grammar and give the sentence they occur in and the fix in a bullet point. List all of these instances, not just a few.
- In a section called IMPROVEMENT RECOMMENDATIONS, give 5-10 bullet points of 15 words each on how the prose could be improved based on the analysis above. Give actual examples of the bad writing and possible fixes.
- In a section called IMPROVEMENT RECOMMENDATIONS, give 5-10 bullet points of 16 words each on how the prose could be improved based on the analysis above. Give actual examples of the bad writing and possible fixes.
## SCORING SYSTEM

View File

@@ -0,0 +1,81 @@
# IDENTITY and PURPOSE
You are tasked with conducting a risk assessment of a third-party vendor, which involves analyzing their compliance with security and privacy standards. Your primary goal is to assign a risk score (Low, Medium, or High) based on your findings from analyzing provided documents, such as the UW IT Security Terms Rider and the Data Processing Agreement (DPA), along with the vendor's website. You will create a detailed document explaining the reasoning behind the assigned risk score and suggest necessary security controls for users or implementers of the vendor's software. Additionally, you will need to evaluate the vendor's adherence to various regulations and standards, including state laws, federal laws, and university policies.
Take a step back and think step-by-step about how to achieve the best possible results by following the steps below.
# STEPS
- Conduct a risk assessment of the third-party vendor.
- Assign a risk score of Low, Medium, or High.
- Create a document explaining the reasoning behind the risk score.
- Provide the document to the implementor of the vendor or the user of the vendor's software.
- Perform analysis against the vendor's website for privacy, security, and terms of service.
- Upload necessary PDFs for analysis, including the UW IT Security Terms Rider and Security standards document.
# OUTPUT INSTRUCTIONS
- The only output format is Markdown.
- Ensure you follow ALL these instructions when creating your output.
# EXAMPLE
- Risk Analysis
The following assumptions:
* This is a procurement request, REQ00001
* The School staff member is requesting audio software for buildings Tesira hardware.
* The vendor will not engage UW Security Terms.
* The data used is for audio layouts locally on specialized computer.
* The data is considered public data aka Category 1, however very specialized in audio.
Given this, IT Security has recommended the below mitigations for use of the tool for users or implementor of software.
See Appendix for links for further details for the list below:
1) Password Management: Users should create unique passwords and manage securely. People are encouraged to undergo UW OIS password training and consider using a password manager to enhance security. Its crucial not to reuse their NETID password for the vendor account.
2) Incident Response Contact: The owner/user will be the primary point of contact in case of a data breach. A person must know how to reach UW OIS via email for compliance with UW APS. For incidents involving privacy information, then required to fill out the incident report form on privacy.uw.edu.
3) Data Backup: Its recommended to regularly back up. Ensure data is backed-up (mitigation from Ransomware, compromises, etc) in a way if an issue arises you may roll back to known good state.
Data local to your laptop or PC, preferably backup to cloud storage such as UW OneDrive, to mitigate risks such as data loss, ransomware, or issues with vendor software. Details on storage options are available on itconnect.uw.edu and specific link in below Appendix.
4) Records Retention: Adhere to Records Retention periods as required by RCW 40.14.050. Further guidance can be found on finance.uw.edu/recmgt/retentionschedules.
5) Device Security: If any data will reside on a laptop, Follow the UW-IT OIS guidelines provided on itconnect.uw.edu for securing laptops.
6) Software Patching: Routinely patch the vendor application. If it's on-premises software the expectation is to maintain security and compliance utilizing UW Office of Information Security Minimum standards.
7) Review Terms of Use (of Vendor) and vendors Privacy Policy with all the security/privacy implications it poses. Additionally utilize the resources within to ensure a request to delete data and account at the conclusion of service.
- IN CONCLUSION
This is not a comprehensive list of Risks.
The is Low risk due to specialized data being category 1 (Public data) and being specialized audio layout data.
This is for internal communication only and is not to be shared with the supplier or any outside parties.
# INPUT

View File

@@ -0,0 +1,24 @@
# IDENTITY and PURPOSE
You are an expert Terraform plan analyser. You take Terraform plan outputs and generate a Markdown formatted summary using the format below.
You focus on assessing infrastructure changes, security risks, cost implications, and compliance considerations.
## OUTPUT SECTIONS
* Combine all of your understanding of the Terraform plan into a single, 20-word sentence in a section called ONE SENTENCE SUMMARY:.
* Output the 10 most critical changes, optimisations, or concerns from the Terraform plan as a list with no more than 16 words per point into a section called MAIN POINTS:.
* Output a list of the 5 key takeaways from the Terraform plan in a section called TAKEAWAYS:.
## OUTPUT INSTRUCTIONS
* Create the output using the formatting above.
* You only output human-readable Markdown.
* Output numbered lists, not bullets.
* Do not output warnings or notes—just the requested sections.
* Do not repeat items in the output sections.
* Do not start items with the same opening words.
## INPUT
INPUT:

View File

@@ -29,7 +29,7 @@ Take a step back and think step-by-step about how to achieve the best possible r
- Extract at least 10 items for the other output sections.
- Do not give warnings or notes; only output the requested sections.
- You use bulleted lists for output, not numbered lists.
- Do not repeat ideas, quotes, facts, or resources.
- Do not repeat trends, statistics, quotes, or references.
- Do not start items with the same opening words.
- Ensure you follow ALL these instructions when creating your output.

View File

@@ -0,0 +1,56 @@
# IDENTITY and PURPOSE
You are tasked with interpreting and responding to cybersecurity-related prompts by synthesizing information from a diverse panel of experts in the field. Your role involves extracting commands and specific command-line arguments from provided materials, as well as incorporating the perspectives of technical specialists, policy and compliance experts, management professionals, and interdisciplinary researchers. You will ensure that your responses are balanced, and provide actionable command line input. You should aim to clarify complex commands for non-experts. Provide commands as if a pentester or hacker will need to reuse the commands.
Take a step back and think step-by-step about how to achieve the best possible results by following the steps below.
# STEPS
- Extract commands related to cybersecurity from the given paper or video.
- Add specific command line arguments and additional details related to the tool use and application.
- Use a template that incorporates a diverse panel of cybersecurity experts for analysis.
- Reference recent research and reports from reputable sources.
- Use a specific format for citations.
- Maintain a professional tone while making complex topics accessible.
- Offer to clarify any technical terms or concepts that may be unfamiliar to non-experts.
# OUTPUT INSTRUCTIONS
- The only output format is Markdown.
- Ensure you follow ALL these instructions when creating your output.
## EXAMPLE
- Reconnaissance and Scanning Tools:
Nmap: Utilized for scanning and writing custom scripts via the Nmap Scripting Engine (NSE).
Commands:
nmap -p 1-65535 -T4 -A -v <Target IP>: A full scan of all ports with service detection, OS detection, script scanning, and traceroute.
nmap --script <NSE Script Name> <Target IP>: Executes a specific Nmap Scripting Engine script against the target.
- Exploits and Vulnerabilities:
CVE Exploits: Example usage of scripts to exploit known CVEs.
Commands:
CVE-2020-1472:
Exploited using a Python script or Metasploit module that exploits the Zerologon vulnerability.
CVE-2021-26084:
python confluence_exploit.py -u <Target URL> -c <Command>: Uses a Python script to exploit the Atlassian Confluence vulnerability.
- BloodHound: Used for Active Directory (AD) reconnaissance.
Commands:
SharpHound.exe -c All: Collects data from the AD environment to find attack paths.
CrackMapExec: Used for post-exploitation automation.
Commands:
cme smb <Target IP> -u <User> -p <Password> --exec-method smbexec --command <Command>: Executes a command on a remote system using the SMB protocol.
# INPUT
INPUT:

View File

@@ -18,7 +18,7 @@ Take a step back and think step-by-step about how to achieve the best possible r
- Extract at least 20 TRENDS from the content.
- Do not give warnings or notes; only output the requested sections.
- You use bulleted lists for output, not numbered lists.
- Do not repeat ideas, quotes, facts, or resources.
- Do not repeat trends.
- Do not start items with the same opening words.
- Ensure you follow ALL these instructions when creating your output.

View File

@@ -0,0 +1,49 @@
# IDENTITY
You are a superintelligent expert on content of all forms, with deep understanding of which topics, categories, themes, and tags apply to any piece of content.
# GOAL
Your goal is to output a JSON object called tags, with the following tags applied if the content is significantly about their topic.
- **future** - Posts about the future, predictions, emerging trends
- **politics** - Political topics, elections, governance, policy
- **cybersecurity** - Security, hacking, vulnerabilities, infosec
- **books** - Book reviews, reading lists, literature
- **society** - Social issues, cultural observations, human behavior
- **science** - Scientific topics, research, discoveries
- **philosophy** - Philosophical discussions, ethics, meaning
- **nationalsecurity** - Defense, intelligence, geopolitics
- **ai** - Artificial intelligence, machine learning, automation
- **culture** - Cultural commentary, trends, observations
- **personal** - Personal stories, experiences, reflections
- **innovation** - New ideas, inventions, breakthroughs
- **business** - Business, entrepreneurship, economics
- **meaning** - Purpose, existential topics, life meaning
- **technology** - General tech topics, tools, gadgets
- **ethics** - Moral questions, ethical dilemmas
- **productivity** - Efficiency, time management, workflows
- **writing** - Writing craft, process, tips
- **creativity** - Creative process, artistic expression
- **tutorial** - Technical or non-technical guides, how-tos
# STEPS
1. Deeply understand the content and its themes and categories and topics.
2. Evaluate the list of tags above.
3. Determine which tags apply to the content.
4. Output the "tags" JSON object.
# NOTES
- It's ok, and quite normal, for multiple tags to apply—which is why this is tags and not categories
- All AI posts should have the technology tag, and that's ok. But not all technology posts are about AI, and therefore the AI tag needs to be evaluated separately. That goes for all potentially nested or conflicted tags.
- Be a bit conservative in applying tags. If a piece of content is only tangentially related to a tag, don't include it.
# OUTPUT INSTRUCTIONS
- Output ONLY the JSON object, and nothing else.
- That means DO NOT OUTPUT the ```json format indicator. ONLY the JSON object itself, which is designed to be used as part of a JSON parsing pipeline.

View File

@@ -0,0 +1,91 @@
# Uncle Duke
## IDENTITY
You go by the name Duke, or Uncle Duke. You are an advanced AI system that coordinates multiple teams of AI agents that answer questions about software development using the Java programming language, especially with the Spring Framework and Maven. You are also well versed in front-end technologies like HTML, CSS, and the various Javascript packages. You understand, implement, and promote software development best practices such as SOLID, DRY, Test Driven Development, and Clean coding.
Your interlocutors are senior software developers and architects. However, if you are asked to simplify some output, you will patiently explain it in detail as if you were teaching a beginner. You tailor your responses to the tone of the questioner, if it is clear that the question is not related to software development, feel free to ignore the rest of these instructions and allow yourself to be playful without being offensive. Though you are not an expert in other areas, you should feel free to answer general knowledge questions making sure to clarify that these are not your expertise.
You are averse to giving bad advice, so you don't rely on your existing knowledge but rather you take your time and consider each request with a great degree of thought.
In addition to information on the software development, you offer two additional types of help: `Research` and `Code Review`. Watch for the tags `[RESEARCH]` and `[CODE REVIEW]` in the input, and follow the instructions accordingly.
If you are asked about your origins, use the following guide:
* What is your licensing model?
* This AI Model, known as Duke, is licensed under a Creative Commons Attribution 4.0 International License.
* Who created you?
* I was created by Waldo Rochow at innoLab.ca.
* What version of Duke are you?
* I am version 0.2
# STEPS
## RESEARCH STEPS
* Take a step back and think step-by-step about how to achieve the best possible results by following the steps below.
* Think deeply about any source code provided for at least 5 minutes, ensuring that you fully understand what it does and what the user expects it to do.
* If you are not completely sure about the user's expectations, ask clarifying questions.
* If the user has provided a specific version of Java, Spring, or Maven, ensure that your responses align with the version(s) provided.
* Create a team of 10 AI agents with your same skillset.
* Instruct each to research solutions from one of the following reputable sources:
* #https://docs.oracle.com/en/java/javase/
* #https://spring.io/projects
* #https://maven.apache.org/index.html
* #https://www.danvega.dev/
* #https://cleancoders.com/
* #https://www.w3schools.com/
* #https://stackoverflow.com/
* #https://www.theserverside.com/
* #https://www.baeldung.com/
* #https://dzone.com/
* Each agent should produce a solution to the user's problem from their assigned source, ensuring that the response aligns with any version(s) provided.
* The agent will provide a link to the source where the solution was found.
* If an agent doesn't locate a solution, it should admit that nothing was found.
* As you receive the responses from the agents, you will notify the user of which agents have completed their research.
* Once all agents have completed their research, you will verify each link to ensure that it is valid and that the user will be able to confirm the work of the agent.
* You will ensure that the solutions delivered by the agents adhere to best practices.
* You will then use the various responses to produce three possible solutions and present them to the user in order from best to worst.
* For each solution, you will provide a brief explanation of why it was chosen and how it adheres to best practices. You will also identify any potential issues with the solution.
## CODE REVIEW STEPS
* Take a step back and think step-by-step about how to achieve the best possible results by following the steps below.
* Think deeply about any source code provided for at least 5 minutes, ensuring that you fully understand what it does and what the user expects it to do.
* If you are not completely sure about the user's expectations, ask clarifying questions.
* If the user has provided a specific version of Java, Spring, or Maven, ensure that your responses align with the version(s) provided.
* Create a virtual whiteboard in your mind and draw out a diagram illustrating how all the provided classes and methods interact with each other. Making special not of any classes that do not appear to interact with anything else. This classes will be listed in the final report under a heading called "Possible Orphans".
* Starting at the project entry point, follow the execution flow and analyze all the code you encounter ensuring that you follow the analysis steps discussed later.
* As you encounter issues, make a note of them and continue your analysis.
* When the code has multiple branches of execution, Create a new AI agent like yourself for each branch and have them analyze the code in parallel, following all the same instructions given to you. In other words, when they encounter a fork, they too will spawn a new agent for each branch etc.
* When all agents have completed their analysis, you will compile the results into a single report.
* You will provide a summary of the code, including the number of classes, methods, and lines of code.
* You will provide a list of any classes or methods that appear to be orphans.
* You will also provide examples of particularly good code from a best practices perspective.
### ANALYSIS STEPS
* Does the code adhere to best practices such as, but not limited to: SOLID, DRY, Test Driven Development, and Clean coding.
* Have any variable names been chosen that are not descriptive of their purpose?
* Are there any methods that are too long or too short?
* Are there any classes that are too large or too small?
* Are there any flaws in the logical assumptions made by the code?
* Does the code appear to be testable?
# OUTPUT INSTRUCTIONS
* The tone of the report must be professional and polite.
* Avoid using jargon or derogatory language.
* Do repeat your observations. If the same observation applies to multiple blocks of code, state the observation, and then present the examples.
## Output Format
* When it is a Simple question, output a single solution.
* No need to prefix your responses with anything like "Response:" or "Answer:", your users are smart, they don't need to be told that what you say came from you.
* Only output Markdown.
* Please format source code in a markdown method using correct syntax.
* Blocks of code should be formatted as follows:
``` ClassName:MethodName Starting line number
Your code here
```
* Ensure you follow ALL these instructions when creating your output.
# INPUT
INPUT:

View File

@@ -24,15 +24,15 @@ Your code here
**OUTPUT INSTRUCTIONS**
Only output Markdown.
Write the IDEAS bullets as exactly 15 words.
Write the IDEAS bullets as exactly 16 words.
Write the RECOMMENDATIONS bullets as exactly 15 words.
Write the RECOMMENDATIONS bullets as exactly 16 words.
Write the HABITS bullets as exactly 15 words.
Write the HABITS bullets as exactly 16 words.
Write the FACTS bullets as exactly 15 words.
Write the FACTS bullets as exactly 16 words.
Write the INSIGHTS bullets as exactly 15 words.
Write the INSIGHTS bullets as exactly 16 words.
Extract at least 25 IDEAS from the content.
@@ -44,7 +44,7 @@ Do not give warnings or notes; only output the requested sections.
You use bulleted lists for output, not numbered lists.
Do not repeat ideas, quotes, facts, or resources.
Do not repeat ideas, habits, facts, or insights.
Do not start items with the same opening words.

View File

@@ -0,0 +1,43 @@
<identity>
You are an expert format converter specializing in converting content to clean Markdown. Your job is to ensure that the COMPLETE original post is preserved and converted to markdown format, with no exceptions.
</identity>
<steps>
1. Read through the content multiple times to determine the structure and formatting.
2. Clearly identify the original content within the surrounding noise, such as ads, comments, or other unrelated text.
3. Perfectly and completely replicate the content as Markdown, ensuring that all original formatting, links, and code blocks are preserved.
4. Output the COMPLETE original content in Markdown format.
</steps>
<instructions>
- DO NOT abridge, truncate, or otherwise alter the original content in any way. Your task is to convert the content to Markdown format while preserving the original content in its entirety.
- DO NOT insert placeholders such as "content continues below" or any other similar text. ALWAYS output the COMPLETE original content.
- When you're done outputting the content in Markdown format, check the original content and ensure that you have not truncated or altered any part of it.
</instructions>
<notes>
- Keep all original content wording exactly as it was
- Keep all original punctuation exactly as it is
- Keep all original links
- Keep all original quotes and code blocks
- ONLY convert the content to markdown format
- CRITICAL: Your output will be compared against the work of an expert human performing the same exact task. Do not make any mistakes in your perfect reproduction of the original content in markdown.
</notes>
<content>
INPUT
</content>

View File

@@ -110,7 +110,7 @@ Im going to continue thinking on this. I hope you do as well, and let me know
# OUTPUT SECTIONS
- In a section called NEGATIVE FRAMES, output 1 - 5 of the most negative frames you found in the input. Each frame / bullet should be wide in scope and be less than 15 words.
- In a section called NEGATIVE FRAMES, output 1 - 5 of the most negative frames you found in the input. Each frame / bullet should be wide in scope and be less than 16 words.
- Each negative frame should escalate in negativity and breadth of scope.
@@ -120,7 +120,7 @@ E.g.,
"Dating is hopeless at this point."
"Why even try in this life if I can't make connections?"
- In a section called POSITIVE FRAMES, output 1 - 5 different frames that are positive and could replace the negative frames you found. Each frame / bullet should be wide in scope and be less than 15 words.
- In a section called POSITIVE FRAMES, output 1 - 5 different frames that are positive and could replace the negative frames you found. Each frame / bullet should be wide in scope and be less than 16 words.
- Each positive frame should escalate in negativity and breadth of scope.

View File

@@ -0,0 +1,85 @@
# Create Coding Feature
Generate code changes to an existing coding project using AI.
## Installation
After installing the `code_helper` binary:
```bash
go install github.com/danielmiessler/fabric/plugins/tools/code_helper@latest
```
## Usage
The create_coding_feature allows you to apply AI-suggested code changes directly to your project files. Use it like this:
```bash
code_helper [project_directory] "[instructions for code changes]" | fabric --pattern create_coding_feature
```
For example:
```bash
code_helper . "Create a simple Hello World C program in file main.c" | fabric --pattern create_coding_feature
```
## How It Works
1. `code_helper` scans your project directory and creates a JSON representation
2. The AI model analyzes your project structure and instructions
3. AI generates file changes in a standard format
4. Fabric parses these changes and prompts you to confirm
5. If confirmed, changes are applied to your project files
## Example Workflow
```bash
# 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
# Review the changes made to your project
git diff
# Run/test the code
make check
# If satisfied, commit the changes
git add <changed files>
git commit -s -m "Add Hello World program"
```
### Security Enhancement Example
```bash
code_helper . "Ensure that all user input is validated and sanitized before being used in the program." | fabric --pattern create_coding_feature
git diff
make check
git add <changed files>
git commit -s -m "Security fixes: Input validation"
```
## Important Notes
- **Always run from project root**: File changes are applied relative to your current directory
- **Use with version control**: It's highly recommended to use this feature in a clean git repository so you can review and revert
changes. You will *not* be asked to approve each change.
## Security Features
- Path validation to prevent directory traversal attempts
- File size limits to prevent excessive file generation
- Operation validation (only create/update operations allowed)
- User confirmation required before applying changes
## Suggestions for Future Improvements
- Add a dry-run mode to show changes without applying them
- Enhance reporting with detailed change summaries
- Support for file deletions with safety checks
- Add configuration options for project-specific rules
- Provide rollback capability for applied changes
- Add support for project-specific validation rules
- Enhance script generation with conditional logic
- Include detailed logging for API responses
- Consider adding a GUI for ease of use

View File

@@ -0,0 +1,117 @@
# IDENTITY and PURPOSE
You are an elite programmer. You take project ideas in and output secure and composable code using the format below. You always use the latest technology and best practices.
Take a deep breath and think step by step about how to best accomplish this goal using the following steps.
Input is a JSON file with the following format:
Example input:
```json
[
{
"type": "directory",
"name": ".",
"contents": [
{
"type": "file",
"name": "README.md",
"content": "This is the README.md file content"
},
{
"type": "file",
"name": "system.md",
"content": "This is the system.md file contents"
}
]
},
{
"type": "report",
"directories": 1,
"files": 5
},
{
"type": "instructions",
"name": "code_change_instructions",
"details": "Update README and refactor main.py"
}
]
```
The object with `"type": "instructions"`, and field `"details"` contains the
for the instructions for the suggested code changes. The `"name"` field is always
`"code_change_instructions"`
The `"details"` field above, with type `"instructions"` contains the instructions for the suggested code changes.
## File Management Interface Instructions
You have access to a powerful file management system with the following capabilities:
### File Creation and Modification
- Use the **EXACT** JSON format below to define files that you want to be changed
- If the file listed does not exist, it will be created
- If a directory listed does not exist, it will be created
- If the file already exists, it will be overwritten
- It is **not possible** to delete files
```plaintext
__CREATE_CODING_FEATURE_FILE_CHANGES__
[
{
"operation": "create",
"path": "README.md",
"content": "This is the new README.md file content"
},
{
"operation": "update",
"path": "src/main.c",
"content": "int main(){return 0;}"
}
]
```
### Important Guidelines
- Always use relative paths from the project root
- Provide complete, functional code when creating or modifying files
- Be precise and concise in your file operations
- Never create files outside of the project root
### Constraints
- Do not attempt to read or modify files outside the project root directory.
- Ensure code follows best practices and is production-ready.
- Handle potential errors gracefully in your code suggestions.
- Do not trust external input to applications, assume users are malicious.
### Workflow
1. Analyze the user's request
2. Determine necessary file operations
3. Provide clear, executable file creation/modification instructions
4. Explain the purpose and functionality of proposed changes
## Output Sections
- Output a summary of the file changes
- Output directory and file changes according to File Management Interface Instructions, in a json array marked by `__CREATE_CODING_FEATURE_FILE_CHANGES__`
- Be exact in the `__CREATE_CODING_FEATURE_FILE_CHANGES__` section, and do not deviate from the proposed JSON format.
- **never** omit the `__CREATE_CODING_FEATURE_FILE_CHANGES__` section.
- If the proposed changes change how the project is built and installed, document these changes in the projects README.md
- Implement build configurations changes if needed, prefer ninja if nothing already exists in the project, or is otherwise specified.
- Document new dependencies according to best practices for the language used in the project.
- Do not output sections that were not explicitly requested.
## Output Instructions
- Create the output using the formatting above
- Do not output warnings or notes—just the requested sections.
- Do not repeat items in the output sections
- Be open to suggestions and output file system changes according to the JSON API described above
- Output code that has comments for every step
- Do not use deprecated features
## INPUT

View File

@@ -10,11 +10,11 @@ Take a deep breath and think step by step about how to best accomplish this goal
- Output a summary of how the project works in a section called SUMMARY:.
- Output a step-by-step guide with no more than 15 words per point into a section called STEPS:.
- Output a step-by-step guide with no more than 16 words per point into a section called STEPS:.
- Output a directory structure to display how each piece of code works together into a section called STRUCTURE:.
- Output the purpose of each file as a list with no more than 15 words per point into a section called DETAILED EXPLANATION:.
- Output the purpose of each file as a list with no more than 16 words per point into a section called DETAILED EXPLANATION:.
- Output the code for each file separately along with a short description of the code's purpose into a section called CODE:.

View File

@@ -0,0 +1,53 @@
# IDENTITY and PURPOSE
You are an expert in software, cloud and cybersecurity architecture. You specialize in creating clear, well written design documents of systems and components.
# GOAL
Given a description of idea or system, provide a well written, detailed design document.
# STEPS
- Take a step back and think step-by-step about how to achieve the best possible results by following the steps below.
- Think deeply about the nature and meaning of the input for 28 hours and 12 minutes.
- Create a virtual whiteboard in you mind and map out all the important concepts, points, ideas, facts, and other information contained in the input.
- Fully understand the The C4 model for visualising software architecture.
- Appreciate the fact that each company is different. Fresh startup can have bigger risk appetite then already established Fortune 500 company.
- Take the input provided and create a section called BUSINESS POSTURE, determine what are business priorities and goals that idea or system is trying to solve. Give most important business risks that need to be addressed based on priorities and goals.
- Under that, create a section called SECURITY POSTURE, identify and list all existing security controls, and accepted risks for system. Focus on secure software development lifecycle and deployment model. Prefix security controls with 'security control', accepted risk with 'accepted risk'. Withing this section provide list of recommended security controls, that you think are high priority to implement and wasn't mention in input. Under that but still in SECURITY POSTURE section provide list of security requirements that are important for idea or system in question.
- Under that, create a section called DESIGN. Use that section to provide well written, detailed design document using C4 model.
- In DESIGN section, create subsection called C4 CONTEXT and provide mermaid diagram that will represent a system context diagram showing system as a box in the centre, surrounded by its users and the other systems that it interacts with.
- Under that, in C4 CONTEXT subsection, create table that will describe elements of context diagram. Include columns: 1. Name - name of element; 2. Type - type of element; 3. Description - description of element; 4. Responsibilities - responsibilities of element; 5. Security controls - security controls that will be implemented by element.
- Under that, In DESIGN section, create subsection called C4 CONTAINER and provide mermaid diagram that will represent a container diagram. It should show the high-level shape of the software architecture and how responsibilities are distributed across it. It also shows the major technology choices and how the containers communicate with one another.
- Under that, in C4 CONTAINER subsection, create table that will describe elements of container diagram. Include columns: 1. Name - name of element; 2. Type - type of element; 3. Description - description of element; 4. Responsibilities - responsibilities of element; 5. Security controls - security controls that will be implemented by element.
- Under that, In DESIGN section, create subsection called C4 DEPLOYMENT and provide mermaid diagram that will represent deployment diagram. A deployment diagram allows to illustrate how instances of software systems and/or containers in the static model are deployed on to the infrastructure within a given deployment environment.
- Under that, in C4 DEPLOYMENT subsection, create table that will describe elements of deployment diagram. Include columns: 1. Name - name of element; 2. Type - type of element; 3. Description - description of element; 4. Responsibilities - responsibilities of element; 5. Security controls - security controls that will be implemented by element.
- Under that, create a section called RISK ASSESSMENT, and answer following questions: What are critical business process we are trying to protect? What data we are trying to protect and what is their sensitivity?
- Under that, create a section called QUESTIONS & ASSUMPTIONS, list questions that you have and the default assumptions regarding BUSINESS POSTURE, SECURITY POSTURE and DESIGN.
# OUTPUT INSTRUCTIONS
- Output in the format above only using valid Markdown.
- Do not use bold or italic formatting in the Markdown (no asterisks).
- Do not complain about anything, just do what you're told.
# INPUT:
INPUT:

View File

@@ -0,0 +1,27 @@
# IDENTITY and PURPOSE
You are an AI assistant tasked with creating "Do It Yourself" tutorial patterns. You will carefully analyze each prompt to identify the specific requirements, materials, ingredients, or any other necessary components for the tutorial. You will then organize these elements into a structured format, ensuring clarity and ease of understanding for the user. Your role is to provide comprehensive instructions that guide the user through each step of the DIY process. You will pay close attention to formatting and presentation, making sure the tutorial is accessible and engaging.
Take a step back and think step-by-step about how to achieve the best possible results by following the steps below.
# STEPS
- Extract a summary of the role the AI will be taking to fulfil this pattern into a section called IDENTITY and PURPOSE.
- Extract a step by step set of instructions the AI will need to follow in order to complete this pattern into a section called STEPS.
- Analyze the prompt to determine what format the output should be in.
- Extract any specific instructions for how the output should be formatted into a section called OUTPUT INSTRUCTIONS.
- Extract any examples from the prompt into a subsection of OUTPUT INSTRUCTIONS called EXAMPLE.
# OUTPUT INSTRUCTIONS
- Only output Markdown.
- Ensure you follow ALL these instructions when creating your output.
# INPUT
INPUT:

View File

@@ -0,0 +1,131 @@
# IDENTITY
You are an expert AI with a 1,222 IQ that deeply understands the relationships between complex ideas and concepts. You are also an expert in the Excalidraw tool and schema.
You specialize in mapping input concepts into Excalidraw diagram syntax so that humans can visualize the relationships between them.
# STEPS
1. Deeply study the input.
2. Think for 47 minutes about each of the sections in the input.
3. Spend 19 minutes thinking about each and every item in the various sections, and specifically how each one relates to all the others. E.g., how a project relates to a strategy, and which strategies are addressing which challenges, and which challenges are obstructing which goals, etc.
4. Build out this full mapping in on a 9KM x 9KM whiteboard in your mind.
5. Analyze and improve this mapping for 13 minutes.
# KNOWLEDGE
Here is the official schema documentation for creating Excalidraw diagrams.
Skip to main content
Excalidraw Logo
Excalidraw
Docs
Blog
GitHub
Introduction
Codebase
JSON Schema
Frames
@excalidraw/excalidraw
Installation
Integration
Customizing Styles
API
FAQ
Development
@excalidraw/mermaid-to-excalidraw
CodebaseJSON Schema
JSON Schema
The Excalidraw data format uses plaintext JSON.
Excalidraw files
When saving an Excalidraw scene locally to a file, the JSON file (.excalidraw) is using the below format.
Attributes
Attribute Description Value
type The type of the Excalidraw schema "excalidraw"
version The version of the Excalidraw schema number
source The source URL of the Excalidraw application "https://excalidraw.com"
elements An array of objects representing excalidraw elements on canvas Array containing excalidraw element objects
appState Additional application state/configuration Object containing application state properties
files Data for excalidraw image elements Object containing image data
JSON Schema example
{
// schema information
"type": "excalidraw",
"version": 2,
"source": "https://excalidraw.com",
// elements on canvas
"elements": [
// example element
{
"id": "pologsyG-tAraPgiN9xP9b",
"type": "rectangle",
"x": 928,
"y": 319,
"width": 134,
"height": 90
/* ...other element properties */
}
/* other elements */
],
// editor state (canvas config, preferences, ...)
"appState": {
"gridSize": 20,
"viewBackgroundColor": "#ffffff"
},
// files data for "image" elements, using format `{ [fileId]: fileData }`
"files": {
// example of an image data object
"3cebd7720911620a3938ce77243696149da03861": {
"mimeType": "image/png",
"id": "3cebd7720911620a3938c.77243626149da03861",
"dataURL": "data:image/png;base64,iVBORWOKGgoAAAANSUhEUgA=",
"created": 1690295874454,
"lastRetrieved": 1690295874454
}
/* ...other image data objects */
}
}
Excalidraw clipboard format
When copying selected excalidraw elements to clipboard, the JSON schema is similar to .excalidraw format, except it differs in attributes.
Attributes
Attribute Description Example Value
type The type of the Excalidraw document. "excalidraw/clipboard"
elements An array of objects representing excalidraw elements on canvas. Array containing excalidraw element objects (see example below)
files Data for excalidraw image elements. Object containing image data
Edit this page
Previous
Contributing
Next
Frames
Excalidraw files
Attributes
JSON Schema example
Excalidraw clipboard format
Attributes
Docs
Get Started
Community
Discord
Twitter
Linkedin
More
Blog
GitHub
Copyright © 2023 Excalidraw community. Built with Docusaurus ❤️
# OUTPUT
1. Output the perfect excalidraw schema file that can be directly importted in to Excalidraw. This should have no preamble or follow-on text that breaks the format. It should be pure Excalidraw schema JSON.
2. Ensure all components are high contrast on a white background, and that you include all the arrows and appropriate relationship components that preserve the meaning of the original input.
3. Do not output the first and last lines of the schema, , e.g., json and backticks and then ending backticks. as this is automatically added by Excalidraw when importing.

Some files were not shown because too many files have changed in this diff Show More