Compare commits

...

24 Commits

Author SHA1 Message Date
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
36 changed files with 1799 additions and 970 deletions

View File

@@ -20,8 +20,8 @@ Fabric is graciously supported by…
[Updates](#updates) •
[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) •
@@ -87,9 +87,9 @@ Fabric is graciously supported by…
## Updates
> [!NOTE]
> April 16, 2025
> May 22, 2025
>
> - Fabric now supports Grok (from XAI)! Update and use `-S` to select it as your default if you want, or just use the shortcut `-m grok-3-beta`. Enjoy!
> - Fabric now supports Anthropic's Claude 4. Read the [blog post from Anthropic](https://www.anthropic.com/news/claude-4).
## What and why

View File

@@ -1,295 +0,0 @@
This Cumulative PR adds several Web UI and functionality improvements to make pattern selection more intuitive with the addition of pattern descriptions, ability to save favorite patterns, a Pattern TAG system, powerful multilingual capabilities, PDF-to-markdown functionalities, a help reference section, more robust Youtube processing and a variety of other ui improvements.
## 🎥 Demo Video
https://youtu.be/XMzjgqvdltM
## 🌟 Key Features
### 1. Web UI and Pattern Selection Improvements
- Pattern Descriptions
- Pattern Tags
- Pattern Favourites
- Pattern Search bar
- PDF to markdown (pdf as pattern input)
- Better handling of Youtube url
- Multilingual Support
- Web UI refinements for clearer interaction
- Help section via modal
### 2. Multilingual Support System
- Seamless language switching via UI dropdown
- Persistent language state management
- Pattern processing now use the selected language seamlessly
### 3. YouTube Integration Enhancement
- Robust language handling for YouTube transcript processing
- Chunk-based language maintenance for long transcripts
- Consistent language output throughout transcript analysis
### 4. Enhanced Tag Management Integration
The tag filtering system has been deeply integrated into the Pattern Selection interface through several UI enhancements:
1. **Dual-Position Tag Panel**
- Sliding panel positioned to the right of pattern modal
- Dynamic toggle button that adapts position and text based on panel state
- Smooth transitions for opening/closing animations
2. **Tag Selection Visibility**
- New dedicated tag display section in pattern modal
- Visual separation through subtle background styling
- Immediate feedback showing selected tags with comma separation
- Inline reset capability for quick tag clearing
3. **Improved User Experience**
- Clear visual hierarchy between pattern list and tag filtering
- Multiple ways to manage tags (panel or quick reset)
- Consistent styling with existing design language
- Space-efficient tag brick layout in 3-column grid
4. **Technical Implementation**
- Reactive tag state management
- Efficient tag filtering logic
- Proper event dispatching between components
- Maintained accessibility standards
- Responsive design considerations
5. **PDF to Markdown conversion functionality for the web interface**
- Automatic detection and processing of PDF files in chat
- Conversion to markdown format for LLM processing
- Installation instructions from the pdf-to-markdown repository
The PDF conversion module has been integrated in the svelte web browser interface. Once installed, it will automatically detect pdf files in the chat interface and convert them to markdown
## HOW TO INSTALL PDF-TO-MARKDOWN
If you need to update the web component follow the instructions in "Web Interface MOD Readme Files/WEB V2 Install Guide.md".
Assuming your web install is up to date and web svelte config complete, you can simply follow these steps to add Pdf-to-mardown.
# FROM FABRIC ROOT DIRECTORY
cd .. web
# Install in this sequence:
# Step 1
npm install -D patch-package
# Step 2
npm install -D pdfjs-dist@2.5.207
# Step 3
npm install -D github:jzillmann/pdf-to-markdown#modularize
These enhancements create a more intuitive and efficient pattern discovery experience, allowing users to quickly filter and find relevant patterns while maintaining a clean, modern interface.
## 🛠 Technical Implementation
### Language Support Architecture
```typescript
// Language state management
export const languageStore = writable<string>('');
// Chat input language detection
if (qualifier === 'fr') {
languageStore.set('fr');
userInput = userInput.replace(/--fr\s*/, '');
}
// Service layer integration
const language = get(languageStore) || 'en';
const languageInstruction = language !== 'en'
? `. Please use the language '${language}' for the output.`
: '';
```
### YouTube Processing Enhancement
```typescript
// Process stream with language instruction per chunk
await chatService.processStream(
stream,
(content: string, response?: StreamResponse) => {
if (currentLanguage !== 'en') {
content = `${content}. Please use the language '${currentLanguage}' for the output.`;
}
// Update messages...
}
);
```
# 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 (prefered 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
## 🎯 Usage Examples
### 1. Using Language Qualifiers
```
User: What is the weather?
AI: The weather information...
User: --fr What is the weather?
AI: Voici les informations météo...
```
### 2. Global Settings
1. Select language from dropdown
2. All interactions use selected language
3. Automatic reset to English after each message
### 3. YouTube Analysis
```
User: Analyze this YouTube video --fr
AI: [Provides analysis in French, maintaining language throughout the transcript]
```
## 💡 Key Benefits
1. **Enhanced User Experience**
- Intuitive language switching
- Consistent language handling
- Seamless integration with existing features
2. **Robust Implementation**
- Simple yet powerful design
- No complex language detection needed
- Direct AI instruction approach
3. **Maintainable Architecture**
- Clean separation of concerns
- Stateful language management
- Easy to extend for new languages
4. **YouTube Integration**
- Handles long transcripts effectively
- Maintains language consistency
- Robust chunk processing
## 🔄 Implementation Notes
1. **State Management**
- Language persists until changed
- Resets to English after each message
- Handles UI state updates efficiently
2. **Error Handling**
- Invalid qualifiers are ignored
- Unknown languages default to English
- Proper store reset on errors
3. **Best Practices**
- Clear language instructions
- Consistent state management
- Robust error handling

View File

@@ -32,6 +32,13 @@ type Chatter struct {
// Send processes a chat request and applies any file changes if using the 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 // Default to the model set in the Chatter struct
}
if o.vendor.NeedsRawMode(modelToUse) {
opts.Raw = true
}
if session, err = o.BuildSession(request, opts.Raw); err != nil {
return
}
@@ -192,18 +199,22 @@ func (o *Chatter) BuildSession(request *common.ChatRequest, raw bool) (session *
}
if raw {
// In raw mode, systemMessage is prepended to request.Message.Content
// and request.Message.Role is set to User.
// In raw mode, we want to avoid duplicating the input that's already in the pattern
var finalContent string
if systemMessage != "" {
if request.Message != nil {
request.Message.Content = fmt.Sprintf("%s\\n\\n%s", systemMessage, request.Message.Content)
request.Message.Role = goopenai.ChatMessageRoleUser
// If we have a pattern, it already includes the user input
if request.PatternName != "" {
finalContent = systemMessage
} else {
// If no user message originally, create one with the system content.
request.Message = &goopenai.ChatCompletionMessage{Role: goopenai.ChatMessageRoleUser, Content: systemMessage}
// No pattern, combine system message with user input
finalContent = fmt.Sprintf("%s\n\n%s", systemMessage, request.Message.Content)
}
request.Message = &goopenai.ChatCompletionMessage{
Role: goopenai.ChatMessageRoleUser,
Content: finalContent,
}
}
// After this, if request.Message is not nil, it's the (potentially combined) message to be appended.
// After this, if request.Message is not nil, append it
if request.Message != nil {
session.Append(request.Message)
}

2
go.mod
View File

@@ -6,7 +6,7 @@ toolchain go1.24.2
require (
github.com/anaskhan96/soup v1.2.5
github.com/anthropics/anthropic-sdk-go v0.2.0-beta.3
github.com/anthropics/anthropic-sdk-go v1.2.0
github.com/atotto/clipboard v0.1.4
github.com/gabriel-vasile/mimetype v1.4.9
github.com/gin-gonic/gin v1.10.0

4
go.sum
View File

@@ -23,8 +23,8 @@ github.com/andybalholm/cascadia v1.3.3 h1:AG2YHrzJIm4BZ19iwJ/DAua6Btl3IwJX+VI4kk
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 v0.2.0-beta.3 h1:b5t1ZJMvV/l99y4jbz7kRFdUp3BSDkI8EhSlHczivtw=
github.com/anthropics/anthropic-sdk-go v0.2.0-beta.3/go.mod h1:AapDW22irxK2PSumZiQXYUFvsdQgkwIWlpESweWZI/c=
github.com/anthropics/anthropic-sdk-go v1.2.0 h1:RQzJUqaROewrPTl7Rl4hId/TqmjFvfnkmhHJ6pP1yJ8=
github.com/anthropics/anthropic-sdk-go v1.2.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=

View File

@@ -35,8 +35,8 @@ schema = 3
version = "v1.3.3"
hash = "sha256-jv7ZshpSd7FZzKKN6hqlUgiR8C3y85zNIS/hq7g76Ho="
[mod."github.com/anthropics/anthropic-sdk-go"]
version = "v0.2.0-beta.3"
hash = "sha256-QnR7MWiLPVii9jy7rjrZfg1UDgXCXkc2latdzFurrFM="
version = "v1.2.0"
hash = "sha256-IzSmJBfMB2OAyFOCqwSzwdJMPoTQqJ1rBtKXGrFo2Bc="
[mod."github.com/araddon/dateparse"]
version = "v0.0.0-20210429162001-6b43995a97de"
hash = "sha256-UuX84naeRGMsFOgIgRoBHG5sNy1CzBkWPKmd6VbLwFw="

View File

@@ -1 +1 @@
"1.4.189"
"1.4.195"

View File

@@ -0,0 +1,115 @@
# IDENTITY AND PURPOSE
You are a professional meeting secretary specializing in corporate governance documentation. Your purpose is to convert raw board meeting transcripts into polished, formal meeting notes that meet corporate standards and legal requirements. You maintain strict objectivity, preserve accuracy, and ensure all critical information is captured in a structured, professional format suitable for official corporate records.
# STEPS
## 1. Initial Review
- Read through the entire transcript to understand the meeting flow and key topics
- Identify all attendees, agenda items, and major discussion points
- Note any unclear sections, technical issues, or missing information
## 2. Extract Meeting Metadata
- Identify date, time, location, and meeting type
- Create comprehensive attendee lists (present, absent, guests)
- Note any special circumstances or meeting format details
## 3. Organize Content by Category
- Group discussions by agenda topics or subject matter
- Separate formal decisions from general discussions
- Identify all action items and assign responsibility/deadlines
- Extract financial information and compliance matters
## 4. Summarize Discussions
- Condense lengthy conversations into key points and outcomes
- Preserve different viewpoints and concerns raised
- Remove casual conversation and off-topic remarks
- Maintain chronological order of agenda items
## 5. Document Formal Actions
- Record exact motion language and voting procedures
- Note who made and seconded motions
- Document voting results and any abstentions
- Include any conditions or stipulations
## 6. Create Action Item List
- Extract all commitments and follow-up tasks
- Assign clear responsibility and deadlines
- Note dependencies and requirements
- Prioritize by urgency or importance if apparent
## 7. Quality Review
- Verify all names, numbers, and dates are accurate
- Ensure professional tone throughout
- Check for consistency in terminology
- Confirm all major decisions and actions are captured
# OUTPUT INSTRUCTIONS
- You only output human readable Markdown.
- Default to english unless specified otherwise.
- Ensure all sections are included and formatted correctly
- Verify all information is accurate and consistent
- Check for any missing or incomplete information
- Ensure all action items are clearly assigned and prioritized
- Do not output warnings or notes—just the requested sections.
- Do not repeat items in the output sections.
# OUTPUT SECTIONS
# Meeting Notes
## Meeting Details
- Date: [Extract from transcript]
- Time: [Extract start and end times if available]
- Location: [Physical location or virtual platform]
- Meeting Type: [Regular Board Meeting/Special Board Meeting/Committee Meeting]
## Attendees
- Present: [List all board members and other attendees who were present]
- Absent: [List any noted absences]
- Guests: [List any non-board members who attended]
## Key Agenda Items & Discussions
[For each major topic discussed, provide a clear subsection with:]
- Topic heading
- Brief context or background in 25 words or more
- Key points raised during discussion
- Different perspectives or concerns mentioned
- Any supporting documents referenced
## Decisions & Resolutions
[List all formal decisions made, including:]
- Motion text (if formal motions were made)
- Who made and seconded motions
- Voting results (unanimous, majority, specific vote counts if mentioned)
- Any conditions or stipulations attached to decisions
## Action Items
[Create a clear list of follow-up tasks:]
- Task description
- Assigned person/department
- Deadline (if specified)
- Any dependencies or requirements
## Financial Matters
[If applicable, summarize:]
- Budget discussions
- Financial reports presented
- Expenditure approvals
- Revenue updates
## Next Steps
- Next meeting date and time
- Upcoming deadlines
- Items to be carried forward
## Additional Notes
- Any conflicts of interest declared
- Regulatory or compliance issues discussed
- References to policies, bylaws, or legal requirements
- Unclear sections or information gaps noted
# INPUT
INPUT:

View File

@@ -31,13 +31,12 @@ func NewClient() (ret *Client) {
ret.maxTokens = 4096
ret.defaultRequiredUserMessage = "Hi"
ret.models = []string{
anthropic.ModelClaude3_7SonnetLatest, anthropic.ModelClaude3_7Sonnet20250219,
anthropic.ModelClaude3_5HaikuLatest, anthropic.ModelClaude3_5Haiku20241022,
anthropic.ModelClaude3_5SonnetLatest, anthropic.ModelClaude3_5Sonnet20241022,
anthropic.ModelClaude_3_5_Sonnet_20240620, anthropic.ModelClaude3OpusLatest,
anthropic.ModelClaude_3_Opus_20240229, anthropic.ModelClaude_3_Sonnet_20240229,
anthropic.ModelClaude_3_Haiku_20240307, anthropic.ModelClaude_2_1,
anthropic.ModelClaude_2_0,
string(anthropic.ModelClaude3_7SonnetLatest), string(anthropic.ModelClaude3_7Sonnet20250219),
string(anthropic.ModelClaude3_5HaikuLatest), string(anthropic.ModelClaude3_5Haiku20241022),
string(anthropic.ModelClaude3_5SonnetLatest), string(anthropic.ModelClaude3_5Sonnet20241022),
string(anthropic.ModelClaude_3_5_Sonnet_20240620), string(anthropic.ModelClaude3OpusLatest),
string(anthropic.ModelClaude_3_Opus_20240229), string(anthropic.ModelClaude_3_Haiku_20240307),
string(anthropic.ModelClaudeOpus4_20250514), string(anthropic.ModelClaudeSonnet4_20250514),
}
return
@@ -92,7 +91,7 @@ func (an *Client) SendStream(
ctx := context.Background()
stream := an.client.Messages.NewStreaming(ctx, anthropic.MessageNewParams{
Model: opts.Model,
Model: anthropic.Model(opts.Model),
MaxTokens: int64(an.maxTokens),
TopP: anthropic.Opt(opts.TopP),
Temperature: anthropic.Opt(opts.Temperature),
@@ -124,7 +123,7 @@ func (an *Client) Send(ctx context.Context, msgs []*goopenai.ChatCompletionMessa
var message *anthropic.Message
if message, err = an.client.Messages.New(ctx, anthropic.MessageNewParams{
Model: opts.Model,
Model: anthropic.Model(opts.Model),
MaxTokens: int64(an.maxTokens),
TopP: anthropic.Opt(opts.TopP),
Temperature: anthropic.Opt(opts.Temperature),
@@ -206,3 +205,7 @@ func (an *Client) toMessages(msgs []*goopenai.ChatCompletionMessage) (ret []anth
return anthropicMessages
}
func (an *Client) NeedsRawMode(modelName string) bool {
return false
}

View File

@@ -41,3 +41,7 @@ func (oi *Client) ListModels() (ret []string, err error) {
ret = oi.apiDeployments
return
}
func (oi *Client) NeedsRawMode(modelName string) bool {
return false
}

View File

@@ -90,3 +90,7 @@ func (c *Client) Setup() error {
func (c *Client) SetupFillEnvFileContent(_ *bytes.Buffer) {
// No environment variables needed for dry run
}
func (c *Client) NeedsRawMode(modelName string) bool {
return false
}

View File

@@ -43,3 +43,7 @@ func (oi *Client) ListModels() (ret []string, err error) {
ret = oi.apiModels
return
}
func (oi *Client) NeedsRawMode(modelName string) bool {
return false
}

View File

@@ -143,6 +143,10 @@ func (o *Client) extractText(response *genai.GenerateContentResponse) (ret strin
return
}
func (o *Client) NeedsRawMode(modelName string) bool {
return false
}
func toMessages(msgs []*goopenai.ChatCompletionMessage) (systemInstruction *genai.Content, messages []genai.Part) {
if len(msgs) >= 2 {
systemInstruction = &genai.Content{

View File

@@ -345,3 +345,7 @@ func (c *Client) GetEmbeddings(ctx context.Context, input string, opts *common.C
embeddings = result.Data[0].Embedding
return
}
func (c *Client) NeedsRawMode(modelName string) bool {
return false
}

View File

@@ -5,6 +5,7 @@ import (
"fmt"
"net/http"
"net/url"
"strings"
"time"
ollamaapi "github.com/ollama/ollama/api"
@@ -138,3 +139,16 @@ func (o *Client) createChatRequest(msgs []*goopenai.ChatCompletionMessage, opts
}
return
}
func (o *Client) NeedsRawMode(modelName string) bool {
ollamaPrefixes := []string{
"llama3",
"llama2",
}
for _, prefix := range ollamaPrefixes {
if strings.HasPrefix(modelName, prefix) {
return true
}
}
return false
}

View File

@@ -123,6 +123,20 @@ func (o *Client) Send(ctx context.Context, msgs []*goopenai.ChatCompletionMessag
return
}
func (o *Client) NeedsRawMode(modelName string) bool {
openaiModelsPrefixes := []string{
"o1",
"o3",
"o4",
}
for _, prefix := range openaiModelsPrefixes {
if strings.HasPrefix(modelName, prefix) {
return true
}
}
return false
}
func (o *Client) buildChatCompletionRequest(
inputMsgs []*goopenai.ChatCompletionMessage, opts *common.ChatOptions,
) (ret goopenai.ChatCompletionRequest) {

View File

@@ -14,4 +14,5 @@ type Vendor interface {
ListModels() ([]string, error)
SendStream([]*goopenai.ChatCompletionMessage, *common.ChatOptions, chan string) error
Send(context.Context, []*goopenai.ChatCompletionMessage, *common.ChatOptions) (string, error)
NeedsRawMode(modelName string) bool
}

View File

@@ -1,3 +1,3 @@
package main
var version = "v1.4.189"
var version = "v1.4.195"

6
web/.browserslistrc Normal file
View File

@@ -0,0 +1,6 @@
last 2 versions
not dead
chrome >= 89
firefox >= 89
safari >= 15
edge >= 89

View File

@@ -1,25 +1,83 @@
# The Fabric Web App
[Installing](#Installing)|[Todos](#Todos)|[Collaborators](#Collaborators)
This is a web app for Fabric. It was built using [Svelte](https://svelte.dev/), [SkeletonUI](https://skeleton.dev/), and [Mdsvex](https://mdsvex.pngwn.io/).
- [The Fabric Web App](#the-fabric-web-app)
- [Installing](#installing)
- [From Source](#from-source)
- [TL;DR: Convenience Scripts](#tldr-convenience-scripts)
- [Tips](#tips)
- [Obsidian](#obsidian)
This is a web app for Fabric. It was built using [Svelte][svelte], [SkeletonUI][skeleton], and [Mdsvex][mdsvex].
The goal of this app is to not only provide a user interface for Fabric, but also an out-of-the-box website for those who want to get started with web development, blogging, or to just have a web interface for fabric. 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.
![Preview](/fabric-png.png)
![Preview](./static/preview.png)
## Installing
There are a few days to install and run the Web UI.
### From Source
#### TL;DR: Convenience Scripts
To install the Web UI using `npm`, from the top-level directory:
```bash
./web/scripts/npm-install.sh
```
To use pnpm (preferred and recommended for a huge speed improvement):
```bash
./web/scripts/pnpm-install.sh
```
The app can be run by navigating to the `web` directory and using `npm install`, `pnpm install`, or your preferred package manager. Then simply run `npm run dev`, `pnpm run dev`, or your equivalent command to start the app. *You will need to run fabric in a separate terminal with the `fabric --serve` command.*
Using npm:
```bash
# Install the GUI and its dependencies
npm install
# Install PDF-to-Markdown components in this order
npm install -D patch-package
npm install -D pdfjs-dist
npm install -D github:jzillmann/pdf-to-markdown#modularize
npx svelte-kit sync
# Now, with "fabric --serve" running already, you can run the GUI
npm run dev
```
Using pnpm:
```bash
# Install the GUI and its dependencies
pnpm install
# Install PDF-to-Markdown components in this order
pnpm install -D patch-package
pnpm install -D pdfjs-dist
pnpm install -D github:jzillmann/pdf-to-markdown#modularize
pnpm exec svelte-kit sync
# Now, with "fabric --serve" running already, you can run the GUI
pnpm run dev
```
## Tips
When creating new posts make sure to include a date, description, tags, and aliases. Only a date is needed to display a note.
You can include images, tags to other articles, code blocks, and more all within your markdown files.
### If you choose to use Obsidian alongside this app
You can design and order your vault however you like, though a `posts` folder should be kept in your vault to house any articles you'd like to post.
You can include images, tags to other articles, code blocks, and more all within your markdown files.
## Obsidian
If you choose to use Obsidian alongside this app,
you can design and order your vault however you like, though a `posts` folder should be kept in your vault to house any articles you'd like to post.
[svelte]: https://svelte.dev/
[skeleton]: https://skeleton.dev/
[mdsvex]: https://mdsvex.pngwn.io/

View File

@@ -13,54 +13,54 @@
"format": "prettier --write ."
},
"devDependencies": {
"@eslint/js": "^9.17.0",
"@skeletonlabs/skeleton": "^2.8.0",
"@eslint/js": "^9.27.0",
"@skeletonlabs/skeleton": "^2.11.0",
"@skeletonlabs/tw-plugin": "^0.3.1",
"@sveltejs/adapter-auto": "^3.0.0",
"@sveltejs/kit": "^2.9.0",
"@sveltejs/vite-plugin-svelte": "^3.0.0",
"@tailwindcss/forms": "^0.5.7",
"@tailwindcss/typography": "^0.5.10",
"@types/node": "^20.10.0",
"autoprefixer": "^10.4.16",
"@sveltejs/adapter-auto": "^3.3.1",
"@sveltejs/kit": "^2.21.1",
"@sveltejs/vite-plugin-svelte": "^3.1.2",
"@tailwindcss/forms": "^0.5.10",
"@tailwindcss/typography": "^0.5.16",
"@types/node": "^20.17.50",
"autoprefixer": "^10.4.21",
"eslint-plugin-svelte": "^2.46.1",
"lucide-svelte": "^0.309.0",
"mdsvex": "^0.11.2",
"patch-package": "^8.0.0",
"pdf-to-markdown-core": "github:jzillmann/pdf-to-markdown#modularize",
"pdfjs-dist": "^2.5.207",
"postcss": "^8.4.49",
"pdfjs-dist": "^4.2.67",
"postcss": "^8.5.3",
"postcss-load-config": "^6.0.1",
"rehype-autolink-headings": "^7.1.0",
"rehype-slug": "^6.0.0",
"shiki": "^1.24.3",
"svelte": "^4.2.7",
"svelte-check": "^3.6.0",
"shiki": "^1.29.2",
"svelte": "^4.2.20",
"svelte-check": "^3.8.6",
"svelte-inview": "^4.0.4",
"svelte-markdown": "^0.4.1",
"svelte-reveal": "^1.1.0",
"svelte-youtube-embed": "^0.3.3",
"svelte-youtube-lite": "^0.6.2",
"tailwindcss": "^3.3.6",
"typescript": "^5.0.0",
"vite": "^5.0.3",
"vite-plugin-tailwind-purgecss": "^0.2.0"
"tailwindcss": "^3.4.17",
"typescript": "^5.8.3",
"vite": "^5.4.19",
"vite-plugin-tailwind-purgecss": "^0.2.1"
},
"type": "module",
"dependencies": {
"@floating-ui/dom": "^1.5.3",
"@floating-ui/dom": "^1.7.0",
"clsx": "^2.1.1",
"cn": "^0.1.1",
"date-fns": "^4.1.0",
"highlight.js": "^11.10.0",
"marked": "^15.0.1",
"nanoid": "4.0.2",
"highlight.js": "^11.11.1",
"marked": "^15.0.12",
"nanoid": "5.0.9",
"rehype": "^13.0.2",
"rehype-external-links": "^3.0.0",
"rehype-unwrap-images": "^1.0.0",
"tailwind-merge": "^2.5.4",
"tailwind-merge": "^2.6.0",
"vfile-message": "^4.0.2",
"yaml": "^2.6.1",
"yaml": "^2.8.0",
"youtube-transcript": "^1.2.1"
},
"pnpm": {

1915
web/pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

19
web/scripts/npm-install.sh Executable file
View File

@@ -0,0 +1,19 @@
#!/bin/bash
cd "$(dirname "$0")/.." || exit
if command -v npm &>/dev/null; then
echo "npm is installed"
else
echo "npm is not installed. Please install npm first."
exit 1
fi
# Install the GUI and its dependencies
npm install
# Install PDF-to-Markdown components in this order
npm install -D patch-package
npm install -D pdfjs-dist
npm install -D github:jzillmann/pdf-to-markdown#modularize
npx svelte-kit sync

19
web/scripts/pnpm-install.sh Executable file
View File

@@ -0,0 +1,19 @@
#!/bin/bash
cd "$(dirname "$0")/.." || exit
if command -v npm &>/dev/null; then
echo "pnpm is installed"
else
echo "pnpm is not installed. Please install pnpm first."
exit 1
fi
# Install the GUI and its dependencies
pnpm install
# Install PDF-to-Markdown components in this order
pnpm install -D patch-package
pnpm install -D pdfjs-dist
pnpm install -D github:jzillmann/pdf-to-markdown#modularize
pnpm exec svelte-kit sync

View File

@@ -0,0 +1,62 @@
/**
* Environment configuration for the Fabric web app
* Centralizes all environment variable handling
*/
// Default values
const DEFAULT_FABRIC_BASE_URL = 'http://localhost:8080';
/**
* Get the Fabric base URL from environment variable or default
* This function works in both server and client contexts
*/
export function getFabricBaseUrl(): string {
// In server context (Node.js), use process.env
if (typeof process !== 'undefined' && process.env) {
return process.env.FABRIC_BASE_URL || DEFAULT_FABRIC_BASE_URL;
}
// In client context, check if the environment was injected via Vite
if (typeof window !== 'undefined' && (window as any).__FABRIC_CONFIG__) {
return (window as any).__FABRIC_CONFIG__.FABRIC_BASE_URL || DEFAULT_FABRIC_BASE_URL;
}
// Fallback to default
return DEFAULT_FABRIC_BASE_URL;
}
/**
* Get the Fabric API base URL (adds /api if not present)
*/
export function getFabricApiUrl(): string {
const baseUrl = getFabricBaseUrl();
// Remove trailing slash if present
const cleanBaseUrl = baseUrl.replace(/\/$/, '');
// Check if it already ends with /api
if (cleanBaseUrl.endsWith('/api')) {
return cleanBaseUrl;
}
return `${cleanBaseUrl}/api`;
}
/**
* Configuration object for easy access to all environment settings
*/
export const config = {
fabricBaseUrl: getFabricBaseUrl(),
fabricApiUrl: getFabricApiUrl(),
} as const;
// Type definitions
export interface FabricConfig {
FABRIC_BASE_URL: string;
}
declare global {
interface Window {
__FABRIC_CONFIG__?: FabricConfig;
}
}

View File

@@ -1,17 +1,14 @@
import { createPipeline, transformers } from 'pdf-to-markdown-core/lib/src';
import { createPipeline, transformers } from 'pdf-to-markdown-core/lib/src';
import { PARSE_SCHEMA } from 'pdf-to-markdown-core/lib/src/PdfParser';
import * as pdfjs from 'pdfjs-dist';
import pdfConfig from './pdf-config';
export class PdfConversionService {
constructor() {
if (typeof window !== 'undefined') {
console.log('PDF.js version:', pdfjs.version);
const workerUrl = new URL(
'pdfjs-dist/build/pdf.worker.min.js',
import.meta.url
);
console.log('Worker URL:', workerUrl.href);
pdfjs.GlobalWorkerOptions.workerSrc = workerUrl.href;
// Initialize PDF.js configuration from the shared config
pdfConfig.initialize();
console.log('Worker configuration complete');
}
}

View File

@@ -0,0 +1,20 @@
import { browser } from '$app/environment';
import { GlobalWorkerOptions } from 'pdfjs-dist';
// Set up the worker source location - point to static file in public directory
const workerSrc = '/pdf.worker.min.mjs';
// Configure the worker options only on the client side
if (browser) {
GlobalWorkerOptions.workerSrc = workerSrc;
}
// Export the configuration
export default {
initialize: () => {
if (browser) {
console.log('PDF.js worker initialized at', workerSrc);
}
}
};

View File

@@ -15,11 +15,11 @@ export const POST: RequestHandler = async ({ request }) => {
language: body.language,
hasLanguageParam: true
});
// Extract video ID
const match = body.url.match(/(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/\s]{11})/);
const videoId = match ? match[1] : null;
if (!videoId) {
return json({ error: 'Invalid YouTube URL' }, { status: 400 });
}

File diff suppressed because one or more lines are too long

View File

@@ -2,13 +2,20 @@ import { purgeCss } from 'vite-plugin-tailwind-purgecss';
import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig } from 'vite';
// Get the Fabric base URL from environment variable with fallback
const FABRIC_BASE_URL = process.env.FABRIC_BASE_URL || 'http://localhost:8080';
export default defineConfig({
plugins: [sveltekit(), purgeCss()],
build: {
commonjsOptions: {
transformMixedEsModules: true
}
},
optimizeDeps: {
include: ['pdfjs-dist'],
esbuildOptions: {
target: 'esnext',
supported: {
'top-level-await': true
}
}
},
define: {
'process.env': {
NODE_ENV: JSON.stringify(process.env.NODE_ENV)
@@ -18,6 +25,10 @@ export default defineConfig({
'process.browser': true,
'process': {
cwd: () => ('/')
},
// Inject Fabric configuration for client-side access
'__FABRIC_CONFIG__': {
FABRIC_BASE_URL: JSON.stringify(FABRIC_BASE_URL)
}
},
resolve: {
@@ -31,11 +42,11 @@ export default defineConfig({
},
proxy: {
'/api': {
target: 'http://localhost:8080',
target: FABRIC_BASE_URL,
changeOrigin: true,
timeout: 30000,
rewrite: (path) => path.replace(/^\/api/, ''),
configure: (proxy, options) => {
configure: (proxy, _options) => {
proxy.on('error', (err, req, res) => {
console.log('proxy error', err);
res.writeHead(500, {
@@ -46,10 +57,10 @@ export default defineConfig({
}
},
'^/(patterns|models|sessions)/names': {
target: 'http://localhost:8080',
target: FABRIC_BASE_URL,
changeOrigin: true,
timeout: 30000,
configure: (proxy, options) => {
configure: (proxy, _options) => {
proxy.on('error', (err, req, res) => {
console.log('proxy error', err);
res.writeHead(500, {
@@ -66,4 +77,16 @@ export default defineConfig({
ignored: ['**/node_modules/**', '**/dist/**', '**/.git/**', '**/.svelte-kit/**']
}
},
build: {
commonjsOptions: {
transformMixedEsModules: true
},
target: 'esnext',
minify: true,
rollupOptions: {
output: {
format: 'es'
}
}
}
});