Compare commits

...

9 Commits

Author SHA1 Message Date
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
14 changed files with 332 additions and 44 deletions

View File

@@ -1 +1 @@
"1.4.168"
"1.4.169"

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,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.

View File

@@ -3,8 +3,11 @@ package restapi
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"path/filepath"
"strings"
goopenai "github.com/sashabaranov/go-openai"
@@ -21,11 +24,12 @@ type ChatHandler struct {
}
type PromptRequest struct {
UserInput string `json:"userInput"`
Vendor string `json:"vendor"`
Model string `json:"model"`
ContextName string `json:"contextName"`
PatternName string `json:"patternName"`
UserInput string `json:"userInput"`
Vendor string `json:"vendor"`
Model string `json:"model"`
ContextName string `json:"contextName"`
PatternName string `json:"patternName"`
StrategyName string `json:"strategyName"` // Optional strategy name
}
type ChatRequest struct {
@@ -80,13 +84,25 @@ func (h *ChatHandler) HandleChat(c *gin.Context) {
log.Printf("Processing prompt %d: Model=%s Pattern=%s Context=%s",
i+1, prompt.Model, prompt.PatternName, prompt.ContextName)
// Create chat channel for streaming
streamChan := make(chan string)
// Start chat processing in goroutine
go func(p PromptRequest) {
defer close(streamChan)
// Load and prepend strategy prompt if strategyName is set
if p.StrategyName != "" {
strategyFile := filepath.Join(os.Getenv("HOME"), ".config", "fabric", "strategies", p.StrategyName+".json")
data, err := ioutil.ReadFile(strategyFile)
if err == nil {
var s struct {
Prompt string `json:"prompt"`
}
if err := json.Unmarshal(data, &s); err == nil && s.Prompt != "" {
p.UserInput = s.Prompt + "\n" + p.UserInput
}
}
}
chatter, err := h.registry.GetChatter(p.Model, 2048, "", false, false)
if err != nil {
log.Printf("Error creating chatter: %v", err)
@@ -124,7 +140,6 @@ func (h *ChatHandler) HandleChat(c *gin.Context) {
return
}
// Get the last message from the session
lastMsg := session.GetLastMessage()
if lastMsg != nil {
streamChan <- lastMsg.Content
@@ -134,37 +149,32 @@ func (h *ChatHandler) HandleChat(c *gin.Context) {
}
}(prompt)
// Read from streamChan and write to client
for content := range streamChan {
select {
case <-clientGone:
return
default:
var response StreamResponse
if strings.HasPrefix(content, "Error:") {
response := StreamResponse{
response = StreamResponse{
Type: "error",
Format: "plain",
Content: content,
}
if err := writeSSEResponse(c.Writer, response); err != nil {
log.Printf("Error writing error response: %v", err)
return
}
} else {
response := StreamResponse{
response = StreamResponse{
Type: "content",
Format: detectFormat(content),
Content: content,
}
if err := writeSSEResponse(c.Writer, response); err != nil {
log.Printf("Error writing content response: %v", err)
return
}
}
if err := writeSSEResponse(c.Writer, response); err != nil {
log.Printf("Error writing response: %v", err)
return
}
}
}
// Signal completion of this prompt
completeResponse := StreamResponse{
Type: "complete",
Format: "plain",
@@ -192,26 +202,6 @@ func writeSSEResponse(w gin.ResponseWriter, response StreamResponse) error {
return nil
}
/*
func detectFormat(content string) string {
if strings.HasPrefix(content, "graph TD") ||
strings.HasPrefix(content, "gantt") ||
strings.HasPrefix(content, "flowchart") ||
strings.HasPrefix(content, "sequenceDiagram") ||
strings.HasPrefix(content, "classDiagram") ||
strings.HasPrefix(content, "stateDiagram") {
return "mermaid"
}
if strings.Contains(content, "```") ||
strings.Contains(content, "#") ||
strings.Contains(content, "*") ||
strings.Contains(content, "_") ||
strings.Contains(content, "-") {
return "markdown"
}
return "plain"
}
*/
func detectFormat(content string) string {
if strings.HasPrefix(content, "graph TD") ||
strings.HasPrefix(content, "gantt") ||

View File

@@ -28,6 +28,7 @@ func Serve(registry *core.PluginRegistry, address string, apiKey string) (err er
NewChatHandler(r, registry, fabricDb)
NewConfigHandler(r, fabricDb)
NewModelsHandler(r, registry.VendorManager)
NewStrategiesHandler(r)
// Start server
err = r.Run(address)

59
restapi/strategies.go Normal file
View File

@@ -0,0 +1,59 @@
package restapi
import (
"encoding/json"
"io/ioutil"
"net/http"
"os"
"path/filepath"
"github.com/gin-gonic/gin"
)
// StrategyMeta represents the minimal info about a strategy
type StrategyMeta struct {
Name string `json:"name"`
Description string `json:"description"`
}
// NewStrategiesHandler registers the /strategies GET endpoint
func NewStrategiesHandler(r *gin.Engine) {
r.GET("/strategies", func(c *gin.Context) {
strategiesDir := filepath.Join(os.Getenv("HOME"), ".config", "fabric", "strategies")
files, err := ioutil.ReadDir(strategiesDir)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to read strategies directory"})
return
}
var strategies []StrategyMeta
for _, file := range files {
if file.IsDir() || filepath.Ext(file.Name()) != ".json" {
continue
}
fullPath := filepath.Join(strategiesDir, file.Name())
data, err := ioutil.ReadFile(fullPath)
if err != nil {
continue
}
var s struct {
Name string `json:"name"`
Description string `json:"description"`
}
if err := json.Unmarshal(data, &s); err != nil {
continue
}
strategies = append(strategies, StrategyMeta{
Name: s.Name,
Description: s.Description,
})
}
c.JSON(http.StatusOK, strategies)
})
}

View File

@@ -1,3 +1,3 @@
package main
var version = "v1.4.168"
var version = "v1.4.169"

View File

@@ -35,6 +35,11 @@ https://youtu.be/fcVitd4Kb98
The tag filtering system has been deeply integrated into the Pattern Selection interface through several UI enhancements:
### 5. Strategy flags
- strategies are fetch from .config/fabric/strategies for server processing
- for gui, they are fetched from static/strategies
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

View File

@@ -4,6 +4,8 @@
import ModelConfig from "./ModelConfig.svelte";
import { Select } from "$lib/components/ui/select";
import { languageStore } from '$lib/store/language-store';
import { strategies, selectedStrategy, fetchStrategies } from '$lib/store/strategy-store';
import { onMount } from 'svelte';
const languages = [
{ code: '', name: 'Default Language' },
@@ -15,6 +17,10 @@
{ code: 'ja', name: 'Japanese' },
{ code: 'it', name: 'Italian' }
];
onMount(() => {
fetchStrategies();
});
</script>
<div class="flex gap-4">
@@ -36,6 +42,17 @@
{/each}
</Select>
</div>
<div>
<Select
bind:value={$selectedStrategy}
class="bg-primary-800/30 border-none hover:bg-primary-800/40 transition-colors"
>
<option value="">None</option>
{#each $strategies as strategy}
<option value={strategy.name}>{strategy.name} - {strategy.description}</option>
{/each}
</Select>
</div>
</div>
<!-- Right side - Model Config -->

View File

@@ -6,7 +6,8 @@ export interface ChatPrompt {
userInput: string;
systemPrompt: string;
model: string;
patternName: string;
patternName?: string;
strategyName?: string; // Optional strategy name to prepend strategy prompt
}
export interface ChatConfig {

View File

@@ -10,6 +10,7 @@ import { systemPrompt, selectedPatternName } from '$lib/store/pattern-store';
import { chatConfig } from '$lib/store/chat-config';
import { messageStore } from '$lib/store/chat-store';
import { languageStore } from '$lib/store/language-store';
import { selectedStrategy } from '$lib/store/strategy-store';
class LanguageValidator {
constructor(private targetLanguage: string) {}
@@ -179,7 +180,8 @@ export class ChatService {
userInput: finalUserInput,
systemPrompt: finalSystemPrompt,
model: config.model,
patternName: get(selectedPatternName)
patternName: get(selectedPatternName),
strategyName: get(selectedStrategy) // Add selected strategy to prompt
};
}

View File

@@ -0,0 +1,32 @@
import { writable } from 'svelte/store';
/**
* List of available strategies fetched from backend.
* Each strategy has a name and description.
*/
export const strategies = writable<Array<{ name: string; description: string }>>([]);
/**
* Currently selected strategy name.
* Default is empty string meaning "None".
*/
export const selectedStrategy = writable<string>("");
/**
* Fetches available strategies from the backend `/strategies` endpoint.
* Populates the `strategies` store.
*/
export async function fetchStrategies() {
try {
const response = await fetch('/strategies/strategies.json');
if (!response.ok) {
console.error('Failed to fetch strategies:', response.statusText);
return;
}
const data = await response.json();
// Expecting an array of { name, description }
strategies.set(data);
} catch (error) {
console.error('Error fetching strategies:', error);
}
}

View File

@@ -0,0 +1,10 @@
[
{ "name": "cod", "description": "Chain-of-Draft (CoD)" },
{ "name": "cot", "description": "Chain-of-Thought (CoT) Prompting" },
{ "name": "ltm", "description": "Least-to-Most Prompting" },
{ "name": "reflexion", "description": "Reflexion Prompting" },
{ "name": "self-consistent", "description": "Self-Consistency Prompting" },
{ "name": "self-refine", "description": "Self-Refinement" },
{ "name": "standard", "description": "Standard Prompting" },
{ "name": "tot", "description": "Tree-of-Thoughts (ToT)" }
]