claude-code-arcane 2.9.8 → 2.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +26 -0
- package/README.md +40 -38
- package/agents/business/business-ops-lead.md +1 -14
- package/agents/game/gameplay-programmer.md +3 -4
- package/agents/game/technical-artist.md +3 -4
- package/dist/cli.js +105 -39
- package/docs/USER-GUIDE.md +24 -22
- package/docs/coordination-rules.md +1 -1
- package/docs/directory-structure.md +93 -122
- package/package.json +1 -1
- package/profiles/ai.yaml +3 -0
- package/profiles/android-native.yaml +2 -0
- package/profiles/backend-go.yaml +1 -8
- package/profiles/backend-ts.yaml +2 -8
- package/profiles/backend-typescript.yaml +51 -0
- package/profiles/flutter.yaml +2 -0
- package/profiles/frontend-react-vite.yaml +39 -0
- package/profiles/frontend.yaml +2 -0
- package/profiles/integrations.yaml +6 -1
- package/profiles/ios-native.yaml +2 -0
- package/profiles/mobile-android-kotlin.yaml +36 -0
- package/profiles/mobile-flutter.yaml +37 -0
- package/profiles/mobile-ios-swift.yaml +37 -0
- package/profiles/mobile-react-native.yaml +39 -0
- package/profiles/mobile.yaml +2 -0
- package/rules/gamedev/engine-code.md +1 -1
- package/rules/gamedev/shader-code.md +1 -2
- package/rules/gamedev/vn-code.md +3 -2
- package/rules/implementation-workflow.md +1 -1
- package/rules/{ai-code.md → llm-code.md} +5 -5
- package/skills/agent-designer/README.md +2 -1
- package/skills/agent-designer/agent_evaluator.py +0 -5
- package/skills/ai-sdk-setup/SKILL.md +4 -4
- package/skills/arcane-add/SKILL.md +1 -1
- package/skills/arcane-list/SKILL.md +3 -3
- package/skills/arcane-status/SKILL.md +1 -1
- package/skills/architecture-decision/SKILL.md +3 -4
- package/skills/architecture-review/SKILL.md +1 -1
- package/skills/asset-audit/SKILL.md +0 -1
- package/skills/balance-check/SKILL.md +1 -1
- package/skills/brainstorm/SKILL.md +3 -3
- package/skills/brainstorm/references/next-steps-pipeline.md +8 -9
- package/skills/consistency-check/SKILL.md +2 -2
- package/skills/design-system/SKILL.md +1 -1
- package/skills/design-system/references/post-design-validation.md +2 -3
- package/skills/freelance-kickoff/SKILL.md +1 -1
- package/skills/frontend-dev/SKILL.md +27 -28
- package/skills/frontend-dev/references/asset-prompt-guide.md +1 -1
- package/skills/frontend-dev/references/motion-recipes.md +1 -1
- package/skills/help/SKILL.md +1 -2
- package/skills/hotfix/SKILL.md +2 -2
- package/skills/milestone-review/SKILL.md +1 -1
- package/skills/patch-notes/SKILL.md +1 -1
- package/skills/playtest-report/SKILL.md +2 -3
- package/skills/playwright-pro/CLAUDE.md +2 -2
- package/skills/playwright-pro/SKILL.md +13 -9
- package/skills/playwright-pro/agents/migration-planner.md +2 -2
- package/skills/playwright-pro/agents/test-architect.md +1 -2
- package/skills/playwright-pro/agents/test-debugger.md +1 -1
- package/skills/playwright-pro/hooks/detect-playwright.sh +1 -1
- package/skills/playwright-pro/skills/browserstack/SKILL.md +5 -5
- package/skills/playwright-pro/skills/migrate/SKILL.md +1 -1
- package/skills/playwright-pro/skills/report/SKILL.md +2 -2
- package/skills/playwright-pro/skills/testrail/SKILL.md +5 -5
- package/skills/playwright-pro/templates/README.md +2 -2
- package/skills/prototype/SKILL.md +1 -1
- package/skills/quick-design/SKILL.md +1 -1
- package/skills/release-checklist/SKILL.md +0 -1
- package/skills/security-audit/SKILL.md +1 -1
- package/skills/self-improving-agent/CLAUDE.md +12 -12
- package/skills/self-improving-agent/SKILL.md +16 -12
- package/skills/self-improving-agent/agents/memory-analyst.md +1 -1
- package/skills/self-improving-agent/hooks/error-capture.sh +2 -2
- package/skills/self-improving-agent/reference/memory-architecture.md +2 -2
- package/skills/self-improving-agent/reference/promotion-rules.md +3 -3
- package/skills/self-improving-agent/reference/rules-directory-patterns.md +1 -1
- package/skills/self-improving-agent/settings.json +5 -5
- package/skills/self-improving-agent/skills/extract/SKILL.md +7 -7
- package/skills/self-improving-agent/skills/promote/SKILL.md +5 -5
- package/skills/self-improving-agent/skills/remember/SKILL.md +9 -9
- package/skills/self-improving-agent/skills/review/SKILL.md +7 -7
- package/skills/self-improving-agent/skills/status/SKILL.md +8 -8
- package/skills/senior-ml-engineer/references/llm_integration_guide.md +14 -31
- package/skills/senior-prompt-engineer/SKILL.md +10 -10
- package/skills/senior-prompt-engineer/references/prompt_engineering_patterns.md +1 -1
- package/skills/senior-prompt-engineer/scripts/agent_orchestrator.py +43 -40
- package/skills/senior-prompt-engineer/scripts/prompt_optimizer.py +23 -66
- package/skills/shader-dev/reference/fluid-simulation.md +4 -4
- package/skills/shader-dev/reference/simulation-physics.md +6 -6
- package/skills/shader-dev/reference/voxel-rendering.md +1 -1
- package/skills/shader-dev/techniques/ambient-occlusion.md +1 -1
- package/skills/shader-dev/techniques/analytic-ray-tracing.md +2 -2
- package/skills/shader-dev/techniques/domain-warping.md +2 -2
- package/skills/shader-dev/techniques/fluid-simulation.md +45 -45
- package/skills/shader-dev/techniques/multipass-buffer.md +24 -24
- package/skills/shader-dev/techniques/normal-estimation.md +1 -1
- package/skills/shader-dev/techniques/particle-system.md +16 -16
- package/skills/shader-dev/techniques/polar-uv-manipulation.md +1 -1
- package/skills/shader-dev/techniques/post-processing.md +7 -7
- package/skills/shader-dev/techniques/sdf-3d.md +1 -1
- package/skills/shader-dev/techniques/simulation-physics.md +24 -24
- package/skills/shader-dev/techniques/sound-synthesis.md +2 -2
- package/skills/shader-dev/techniques/voronoi-cellular-noise.md +1 -1
- package/skills/shader-dev/techniques/voxel-rendering.md +60 -60
- package/skills/smoke-check/SKILL.md +1 -1
- package/skills/sprint-plan/SKILL.md +1 -2
- package/skills/start/SKILL.md +7 -7
- package/skills/story-done/SKILL.md +1 -1
- package/skills/test-helpers/SKILL.md +7 -2
- package/skills/test-setup/SKILL.md +1 -1
- package/skills/ue-actor-component-architecture/SKILL.md +0 -1
- package/skills/ue-ai-navigation/SKILL.md +0 -1
- package/skills/ue-animation-system/SKILL.md +0 -1
- package/skills/ue-async-threading/SKILL.md +0 -1
- package/skills/ue-audio-system/SKILL.md +0 -1
- package/skills/ue-blueprints/SKILL.md +0 -1
- package/skills/ue-character-movement/SKILL.md +0 -1
- package/skills/ue-cpp-foundations/SKILL.md +0 -1
- package/skills/ue-data-assets-tables/SKILL.md +0 -1
- package/skills/ue-editor-tools/SKILL.md +0 -1
- package/skills/ue-game-features/SKILL.md +0 -1
- package/skills/ue-gameplay-abilities/SKILL.md +0 -1
- package/skills/ue-gameplay-framework/SKILL.md +0 -1
- package/skills/ue-input-system/SKILL.md +0 -1
- package/skills/ue-mass-entity/SKILL.md +0 -1
- package/skills/ue-materials-rendering/SKILL.md +0 -1
- package/skills/ue-module-build-system/SKILL.md +0 -1
- package/skills/ue-naming-conventions/SKILL.md +0 -1
- package/skills/ue-networking-replication/SKILL.md +0 -1
- package/skills/ue-niagara-effects/SKILL.md +0 -1
- package/skills/ue-packaging/SKILL.md +0 -1
- package/skills/ue-physics-collision/SKILL.md +0 -1
- package/skills/ue-procedural-generation/SKILL.md +0 -1
- package/skills/ue-project-context/SKILL.md +0 -1
- package/skills/ue-sequencer-cinematics/SKILL.md +0 -1
- package/skills/ue-serialization-savegames/SKILL.md +0 -1
- package/skills/ue-state-trees/SKILL.md +0 -1
- package/skills/ue-testing-debugging/SKILL.md +0 -1
- package/skills/ue-ui-umg-slate/SKILL.md +0 -1
- package/skills/ue-world-level-streaming/SKILL.md +0 -1
- package/skills/ux-review/SKILL.md +1 -1
- package/docs/RELEASE-SETUP.md +0 -99
- package/docs/presentations/arcane-overview-12.pptx +0 -0
- package/docs/presentations/arcane-overview.pptx +0 -0
- package/docs/presentations/build_arcane_deck.py +0 -310
- package/docs/presentations/build_arcane_deck_12.py +0 -399
- package/docs/trusted-publishing-setup.md +0 -163
|
@@ -7,17 +7,17 @@ user-invocable: false
|
|
|
7
7
|
allowed-tools: Read, Glob, Grep, Bash
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
-
# /
|
|
10
|
+
# /self-improving-agent review — Analyze Auto-Memory
|
|
11
11
|
|
|
12
12
|
Performs a comprehensive audit of Claude Code's auto-memory and produces actionable recommendations.
|
|
13
13
|
|
|
14
14
|
## Usage
|
|
15
15
|
|
|
16
16
|
```
|
|
17
|
-
/
|
|
18
|
-
/
|
|
19
|
-
/
|
|
20
|
-
/
|
|
17
|
+
/self-improving-agent review # Full review
|
|
18
|
+
/self-improving-agent review --quick # Summary only (counts + top 3 candidates)
|
|
19
|
+
/self-improving-agent review --stale # Focus on stale/outdated entries
|
|
20
|
+
/self-improving-agent review --candidates # Show only promotion candidates
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
## What It Does
|
|
@@ -117,14 +117,14 @@ Memory Health:
|
|
|
117
117
|
## When to Use
|
|
118
118
|
|
|
119
119
|
- After completing a major feature or debugging session
|
|
120
|
-
- When `/
|
|
120
|
+
- When `/self-improving-agent status` shows MEMORY.md is over 150 lines
|
|
121
121
|
- Weekly during active development
|
|
122
122
|
- Before starting a new project phase
|
|
123
123
|
- After onboarding a new team member (review what Claude learned)
|
|
124
124
|
|
|
125
125
|
## Tips
|
|
126
126
|
|
|
127
|
-
- Run `/
|
|
127
|
+
- Run `/self-improving-agent review --quick` frequently (low overhead)
|
|
128
128
|
- Full review is most valuable when MEMORY.md is getting crowded
|
|
129
129
|
- Act on promotion candidates promptly — they're proven patterns
|
|
130
130
|
- Don't hesitate to delete stale entries — auto-memory will re-learn if needed
|
|
@@ -7,15 +7,15 @@ user-invocable: false
|
|
|
7
7
|
allowed-tools: Read, Glob, Grep, Bash
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
-
# /
|
|
10
|
+
# /self-improving-agent status — Memory Health Dashboard
|
|
11
11
|
|
|
12
12
|
Quick overview of your project's memory state across all memory systems.
|
|
13
13
|
|
|
14
14
|
## Usage
|
|
15
15
|
|
|
16
16
|
```
|
|
17
|
-
/
|
|
18
|
-
/
|
|
17
|
+
/self-improving-agent status # Full dashboard
|
|
18
|
+
/self-improving-agent status --brief # One-line summary
|
|
19
19
|
```
|
|
20
20
|
|
|
21
21
|
## What It Reports
|
|
@@ -88,7 +88,7 @@ done
|
|
|
88
88
|
### Brief mode
|
|
89
89
|
|
|
90
90
|
```
|
|
91
|
-
/
|
|
91
|
+
/self-improving-agent status --brief
|
|
92
92
|
```
|
|
93
93
|
|
|
94
94
|
Output: `📊 Memory: {{n}}/200 lines | {{count}} rules | {{status_emoji}} {{status_word}}`
|
|
@@ -96,12 +96,12 @@ Output: `📊 Memory: {{n}}/200 lines | {{count}} rules | {{status_emoji}} {{sta
|
|
|
96
96
|
## Interpretation
|
|
97
97
|
|
|
98
98
|
- **Green (< 60%)**: Plenty of room. Auto-memory is working well.
|
|
99
|
-
- **Yellow (60-90%)**: Getting full. Consider running `/
|
|
100
|
-
- **Red (> 90%)**: Near capacity. Auto-memory may start dropping older entries. Run `/
|
|
99
|
+
- **Yellow (60-90%)**: Getting full. Consider running `/self-improving-agent review` to promote or clean up.
|
|
100
|
+
- **Red (> 90%)**: Near capacity. Auto-memory may start dropping older entries. Run `/self-improving-agent review` now.
|
|
101
101
|
|
|
102
102
|
## Tips
|
|
103
103
|
|
|
104
|
-
- Run `/
|
|
105
|
-
- If capacity is yellow+, run `/
|
|
104
|
+
- Run `/self-improving-agent status --brief` as a quick check anytime
|
|
105
|
+
- If capacity is yellow+, run `/self-improving-agent review` to identify promotion candidates
|
|
106
106
|
- Stale entries waste space — delete references to files that no longer exist
|
|
107
107
|
- Topic files are fine — Claude creates them to keep MEMORY.md under 200 lines
|
|
@@ -47,13 +47,14 @@ class OpenAIProvider(LLMProvider):
|
|
|
47
47
|
return response.choices[0].text
|
|
48
48
|
|
|
49
49
|
class AnthropicProvider(LLMProvider):
|
|
50
|
-
def __init__(self, api_key: str, model: str = "claude-
|
|
50
|
+
def __init__(self, api_key: str, model: str = "claude-opus-5-5"):
|
|
51
51
|
self.client = Anthropic(api_key=api_key)
|
|
52
52
|
self.model = model
|
|
53
53
|
|
|
54
54
|
def chat(self, messages: List[Dict], **kwargs) -> str:
|
|
55
55
|
response = self.client.messages.create(
|
|
56
56
|
model=self.model,
|
|
57
|
+
max_tokens=kwargs.pop("max_tokens", 16000),
|
|
57
58
|
messages=messages,
|
|
58
59
|
**kwargs
|
|
59
60
|
)
|
|
@@ -97,7 +98,7 @@ def call_with_fallback(
|
|
|
97
98
|
|---------|----------|-----------|
|
|
98
99
|
| Zero-shot | Simple tasks | Task description + input |
|
|
99
100
|
| Few-shot | Complex tasks | Examples + task + input |
|
|
100
|
-
|
|
|
101
|
+
| Reasoning | Multi-step problems | On models with adaptive thinking, raise `effort` instead of asking for step-by-step text |
|
|
101
102
|
| Role-based | Specialized output | System role + task |
|
|
102
103
|
|
|
103
104
|
### Few-Shot Template
|
|
@@ -178,10 +179,8 @@ def truncate_to_token_limit(text: str, max_tokens: int, model: str = "gpt-4") ->
|
|
|
178
179
|
|
|
179
180
|
| Model | Context Window | Effective Limit |
|
|
180
181
|
|-------|----------------|-----------------|
|
|
181
|
-
|
|
|
182
|
-
|
|
|
183
|
-
| Claude 3 | 200,000 | ~180,000 |
|
|
184
|
-
| Llama 3 | 8,192 | ~6,000 |
|
|
182
|
+
| Claude Opus 5.5 / Sonnet 5.5 / Haiku 5.5 | 1,000,000 | leave room for `max_tokens` |
|
|
183
|
+
| Other providers | check the provider's model docs | context windows change every release |
|
|
185
184
|
|
|
186
185
|
### Chunking Strategy
|
|
187
186
|
|
|
@@ -206,12 +205,7 @@ def chunk_text(text: str, chunk_size: int = 1000, overlap: int = 100) -> List[st
|
|
|
206
205
|
|
|
207
206
|
### Cost Calculation
|
|
208
207
|
|
|
209
|
-
|
|
210
|
-
|----------|------------|-------------|---------------------|
|
|
211
|
-
| GPT-4 | $0.03/1K | $0.06/1K | $0.09 |
|
|
212
|
-
| GPT-3.5 | $0.0005/1K | $0.0015/1K | $0.002 |
|
|
213
|
-
| Claude 3 Opus | $0.015/1K | $0.075/1K | $0.09 |
|
|
214
|
-
| Claude 3 Haiku | $0.00025/1K | $0.00125/1K | $0.0015 |
|
|
208
|
+
Prices change with every model release, so keep them out of code: read them from config, and take the numbers from each provider's pricing page. Count tokens with the provider's response metadata (`usage`), not with a character estimate.
|
|
215
209
|
|
|
216
210
|
### Cost Tracking
|
|
217
211
|
|
|
@@ -229,30 +223,19 @@ class LLMUsage:
|
|
|
229
223
|
def calculate_cost(
|
|
230
224
|
input_tokens: int,
|
|
231
225
|
output_tokens: int,
|
|
232
|
-
|
|
226
|
+
prices: dict,
|
|
233
227
|
) -> float:
|
|
234
|
-
"""
|
|
235
|
-
|
|
236
|
-
"gpt-4": {"input": 0.03, "output": 0.06},
|
|
237
|
-
"gpt-3.5-turbo": {"input": 0.0005, "output": 0.0015},
|
|
238
|
-
"claude-3-opus": {"input": 0.015, "output": 0.075},
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
prices = PRICING.get(model, {"input": 0.01, "output": 0.03})
|
|
242
|
-
|
|
243
|
-
input_cost = (input_tokens / 1000) * prices["input"]
|
|
244
|
-
output_cost = (output_tokens / 1000) * prices["output"]
|
|
245
|
-
|
|
246
|
-
return input_cost + output_cost
|
|
228
|
+
"""Cost in USD. `prices` comes from config: {"input": usd_per_mtok, "output": usd_per_mtok}."""
|
|
229
|
+
return (input_tokens * prices["input"] + output_tokens * prices["output"]) / 1_000_000
|
|
247
230
|
```
|
|
248
231
|
|
|
249
232
|
### Cost Optimization Strategies
|
|
250
233
|
|
|
251
|
-
1. **Use smaller
|
|
252
|
-
2. **Cache
|
|
253
|
-
3. **Batch
|
|
254
|
-
4. **
|
|
255
|
-
5. **Set max_tokens
|
|
234
|
+
1. **Use a smaller model where it holds quality** - measure on real requests before routing a task to it
|
|
235
|
+
2. **Cache repeated context** - provider prompt caching makes a stable system prompt or document far cheaper on repeat calls
|
|
236
|
+
3. **Batch non-urgent work** - batch APIs trade latency for a lower price
|
|
237
|
+
4. **Cache common responses** - store results for repeated queries
|
|
238
|
+
5. **Set max_tokens deliberately** - high enough not to cut answers off, as a ceiling on runaway output
|
|
256
239
|
|
|
257
240
|
---
|
|
258
241
|
|
|
@@ -23,12 +23,12 @@ python scripts/agent_orchestrator.py agent_config.yaml --visualize # Visua
|
|
|
23
23
|
|
|
24
24
|
### 1. Prompt Optimizer
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
Static checks for clarity and structure, with an approximate token count (characters / 4). `--optimize` only normalizes whitespace; the real rewrite is yours.
|
|
27
27
|
|
|
28
28
|
```bash
|
|
29
29
|
python scripts/prompt_optimizer.py prompt.txt --analyze # Full analysis
|
|
30
|
-
python scripts/prompt_optimizer.py prompt.txt --optimize #
|
|
31
|
-
python scripts/prompt_optimizer.py prompt.txt --tokens
|
|
30
|
+
python scripts/prompt_optimizer.py prompt.txt --optimize # Normalize whitespace
|
|
31
|
+
python scripts/prompt_optimizer.py prompt.txt --tokens # Approximate token count
|
|
32
32
|
python scripts/prompt_optimizer.py prompt.txt --extract-examples --output examples.json
|
|
33
33
|
```
|
|
34
34
|
|
|
@@ -50,7 +50,7 @@ Parses agent definitions and visualizes execution flows. Validates tool configur
|
|
|
50
50
|
python scripts/agent_orchestrator.py agent.yaml --validate # Validate config
|
|
51
51
|
python scripts/agent_orchestrator.py agent.yaml --visualize # Show workflow (ASCII)
|
|
52
52
|
python scripts/agent_orchestrator.py agent.yaml --visualize --format mermaid # Mermaid
|
|
53
|
-
python scripts/agent_orchestrator.py agent.yaml --estimate-cost #
|
|
53
|
+
python scripts/agent_orchestrator.py agent.yaml --estimate-cost --price-in 4 --price-out 20 # Tokens; dollars with your current prices (USD/Mtok)
|
|
54
54
|
```
|
|
55
55
|
|
|
56
56
|
## Prompt Engineering Workflows
|
|
@@ -65,7 +65,7 @@ python scripts/agent_orchestrator.py agent.yaml --estimate-cost # Token estimat
|
|
|
65
65
|
|-------|---------|
|
|
66
66
|
| Ambiguous output | Add explicit format specification |
|
|
67
67
|
| Too verbose | Extract to few-shot examples |
|
|
68
|
-
| Inconsistent results | Add
|
|
68
|
+
| Inconsistent results | Add 2-3 varied examples and state the success criteria |
|
|
69
69
|
| Missing edge cases | Add constraint boundaries |
|
|
70
70
|
|
|
71
71
|
4. **Optimize**: `python scripts/prompt_optimizer.py current_prompt.txt --optimize --output optimized.txt`
|
|
@@ -77,15 +77,15 @@ python scripts/agent_orchestrator.py agent.yaml --estimate-cost # Token estimat
|
|
|
77
77
|
1. Define task clearly (input format, output format)
|
|
78
78
|
2. Select 3-5 diverse examples: simple case, edge case, complex case, negative case
|
|
79
79
|
3. Format consistently
|
|
80
|
-
4.
|
|
80
|
+
4. Check what the prompt contains: `python scripts/prompt_optimizer.py prompt_with_examples.txt --extract-examples`
|
|
81
81
|
5. Test with held-out cases
|
|
82
82
|
|
|
83
83
|
### Structured Output Design
|
|
84
84
|
|
|
85
85
|
1. Define JSON/XML schema with types, constraints, enums
|
|
86
|
-
2.
|
|
87
|
-
3.
|
|
88
|
-
4. Validate
|
|
86
|
+
2. Pass the schema through the API's structured outputs (`output_config.format` on Claude) so the response is guaranteed to match it; do not rely on "respond ONLY with valid JSON" in the prompt
|
|
87
|
+
3. Describe in the prompt what each field means, not the JSON syntax
|
|
88
|
+
4. Validate the parsed result against the schema in code before using it
|
|
89
89
|
|
|
90
90
|
## Reference Documentation
|
|
91
91
|
|
|
@@ -103,6 +103,6 @@ python scripts/agent_orchestrator.py agent.yaml --estimate-cost # Token estimat
|
|
|
103
103
|
|---------|-------------|---------|
|
|
104
104
|
| **Zero-shot** | Simple, well-defined tasks | "Classify this email as spam or not spam" |
|
|
105
105
|
| **Few-shot** | Complex tasks, consistent format | Provide 3-5 examples before task |
|
|
106
|
-
| **
|
|
106
|
+
| **Reasoning depth** | Reasoning, math, multi-step | Models with adaptive thinking: raise `effort`. Models without it: "Think step by step..." |
|
|
107
107
|
| **Role Prompting** | Expertise, specific perspective | "You are an expert tax accountant..." |
|
|
108
108
|
| **Structured Output** | Need parseable JSON/XML | Include schema + format enforcement |
|
|
@@ -164,7 +164,7 @@ The 7 apples cost $11.20
|
|
|
164
164
|
| Reasoning chain | "Explain your reasoning" | Justification needed |
|
|
165
165
|
|
|
166
166
|
**Zero-shot CoT:**
|
|
167
|
-
|
|
167
|
+
Append "Let's think step by step." only on models without built-in thinking. On models with adaptive thinking, control depth with `effort`; asking for the reasoning in the output can be declined as reasoning extraction.
|
|
168
168
|
|
|
169
169
|
---
|
|
170
170
|
|
|
@@ -55,7 +55,7 @@ class AgentConfig:
|
|
|
55
55
|
max_iterations: int = 10
|
|
56
56
|
system_prompt: str = ""
|
|
57
57
|
temperature: float = 0.7
|
|
58
|
-
model: str = "
|
|
58
|
+
model: str = ""
|
|
59
59
|
|
|
60
60
|
|
|
61
61
|
@dataclass
|
|
@@ -177,7 +177,7 @@ def load_config(path: Path) -> AgentConfig:
|
|
|
177
177
|
max_iterations=int(data.get('max_iterations', 10)),
|
|
178
178
|
system_prompt=data.get('system_prompt', ''),
|
|
179
179
|
temperature=float(data.get('temperature', 0.7)),
|
|
180
|
-
model=data.get('model', '
|
|
180
|
+
model=data.get('model', '')
|
|
181
181
|
)
|
|
182
182
|
|
|
183
183
|
|
|
@@ -369,44 +369,39 @@ def generate_mermaid_diagram(config: AgentConfig) -> str:
|
|
|
369
369
|
return '\n'.join(lines)
|
|
370
370
|
|
|
371
371
|
|
|
372
|
-
def estimate_cost(config: AgentConfig, runs: int = 100
|
|
373
|
-
|
|
372
|
+
def estimate_cost(config: AgentConfig, runs: int = 100,
|
|
373
|
+
price_in: Optional[float] = None, price_out: Optional[float] = None) -> Dict[str, Any]:
|
|
374
|
+
"""Estimate tokens per run; dollars only when the caller supplies current prices.
|
|
375
|
+
|
|
376
|
+
Prices are USD per million tokens. They are not built in because provider prices
|
|
377
|
+
change and a stale table gives confidently wrong numbers.
|
|
378
|
+
"""
|
|
374
379
|
validation = validate_agent(config)
|
|
375
380
|
min_tokens, max_tokens = validation.estimated_tokens_per_run
|
|
376
381
|
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
'claude-3-opus': {'input': 0.015, 'output': 0.075},
|
|
383
|
-
'claude-3-sonnet': {'input': 0.003, 'output': 0.015},
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
model_cost = costs.get(config.model, costs['gpt-4'])
|
|
387
|
-
|
|
388
|
-
# Assume 60% input, 40% output
|
|
389
|
-
input_tokens = min_tokens * 0.6
|
|
390
|
-
output_tokens = min_tokens * 0.4
|
|
382
|
+
def dollars(tokens: float) -> Optional[float]:
|
|
383
|
+
if price_in is None or price_out is None:
|
|
384
|
+
return None
|
|
385
|
+
# Assume 60% input, 40% output
|
|
386
|
+
return (tokens * 0.6 * price_in + tokens * 0.4 * price_out) / 1_000_000
|
|
391
387
|
|
|
392
|
-
|
|
393
|
-
|
|
388
|
+
per_run_min, per_run_max = dollars(min_tokens), dollars(max_tokens)
|
|
389
|
+
monthly_runs = runs * 30
|
|
394
390
|
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
cost_per_run_max = (input_tokens_max / 1000 * model_cost['input'] +
|
|
398
|
-
output_tokens_max / 1000 * model_cost['output'])
|
|
399
|
-
|
|
400
|
-
return {
|
|
401
|
-
'model': config.model,
|
|
391
|
+
result = {
|
|
392
|
+
'model': config.model or None,
|
|
402
393
|
'tokens_per_run': {'min': min_tokens, 'max': max_tokens},
|
|
403
|
-
'cost_per_run': {'min': round(cost_per_run_min, 4), 'max': round(cost_per_run_max, 4)},
|
|
404
394
|
'estimated_monthly': {
|
|
405
|
-
'runs':
|
|
406
|
-
'
|
|
407
|
-
'
|
|
408
|
-
}
|
|
395
|
+
'runs': monthly_runs,
|
|
396
|
+
'tokens_min': min_tokens * monthly_runs,
|
|
397
|
+
'tokens_max': max_tokens * monthly_runs,
|
|
398
|
+
},
|
|
409
399
|
}
|
|
400
|
+
if per_run_min is not None:
|
|
401
|
+
result['cost_per_run'] = {'min': round(per_run_min, 4), 'max': round(per_run_max, 4)}
|
|
402
|
+
result['estimated_monthly']['cost_min'] = round(per_run_min * monthly_runs, 2)
|
|
403
|
+
result['estimated_monthly']['cost_max'] = round(per_run_max * monthly_runs, 2)
|
|
404
|
+
return result
|
|
410
405
|
|
|
411
406
|
|
|
412
407
|
def format_validation_report(config: AgentConfig, result: ValidationResult) -> str:
|
|
@@ -461,6 +456,9 @@ def format_validation_report(config: AgentConfig, result: ValidationResult) -> s
|
|
|
461
456
|
|
|
462
457
|
|
|
463
458
|
def main():
|
|
459
|
+
# The report uses emoji; a Windows console defaults to cp1252 and cannot print them.
|
|
460
|
+
if hasattr(sys.stdout, "reconfigure"):
|
|
461
|
+
sys.stdout.reconfigure(encoding="utf-8")
|
|
464
462
|
parser = argparse.ArgumentParser(
|
|
465
463
|
description="Agent Orchestrator - Design and validate agent workflows",
|
|
466
464
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
@@ -469,13 +467,13 @@ Examples:
|
|
|
469
467
|
%(prog)s agent.yaml --validate
|
|
470
468
|
%(prog)s agent.yaml --visualize
|
|
471
469
|
%(prog)s agent.yaml --visualize --format mermaid
|
|
472
|
-
%(prog)s agent.yaml --estimate-cost --runs 100
|
|
470
|
+
%(prog)s agent.yaml --estimate-cost --runs 100 --price-in 4 --price-out 20
|
|
473
471
|
|
|
474
472
|
Agent config format (YAML):
|
|
475
473
|
|
|
476
474
|
name: research_assistant
|
|
477
475
|
pattern: react
|
|
478
|
-
model:
|
|
476
|
+
model: claude-opus-5-5
|
|
479
477
|
max_iterations: 10
|
|
480
478
|
tools:
|
|
481
479
|
- name: web_search
|
|
@@ -493,6 +491,8 @@ tools:
|
|
|
493
491
|
help='Visualization format (default: ascii)')
|
|
494
492
|
parser.add_argument('--estimate-cost', '-e', action='store_true', help='Estimate token costs')
|
|
495
493
|
parser.add_argument('--runs', '-r', type=int, default=100, help='Daily runs for cost estimation')
|
|
494
|
+
parser.add_argument('--price-in', type=float, help='Current input price, USD per million tokens')
|
|
495
|
+
parser.add_argument('--price-out', type=float, help='Current output price, USD per million tokens')
|
|
496
496
|
parser.add_argument('--output', '-o', help='Output file path')
|
|
497
497
|
parser.add_argument('--json', '-j', action='store_true', help='Output as JSON')
|
|
498
498
|
|
|
@@ -534,18 +534,21 @@ tools:
|
|
|
534
534
|
|
|
535
535
|
# Cost estimation
|
|
536
536
|
if args.estimate_cost:
|
|
537
|
-
costs = estimate_cost(config, args.runs)
|
|
537
|
+
costs = estimate_cost(config, args.runs, args.price_in, args.price_out)
|
|
538
538
|
if args.json:
|
|
539
539
|
output_parts.append(json.dumps(costs, indent=2))
|
|
540
540
|
else:
|
|
541
541
|
output_parts.append("")
|
|
542
542
|
output_parts.append("💰 COST ESTIMATION")
|
|
543
|
-
output_parts.append(f" Model: {costs['model']}")
|
|
543
|
+
output_parts.append(f" Model: {costs['model'] or '(not set)'}")
|
|
544
544
|
output_parts.append(f" Tokens per run: {costs['tokens_per_run']['min']:,} - {costs['tokens_per_run']['max']:,}")
|
|
545
|
-
|
|
546
|
-
output_parts.append(f" Monthly ({
|
|
547
|
-
|
|
548
|
-
|
|
545
|
+
monthly = costs['estimated_monthly']
|
|
546
|
+
output_parts.append(f" Monthly ({monthly['runs']:,} runs): {monthly['tokens_min']:,} - {monthly['tokens_max']:,} tokens")
|
|
547
|
+
if 'cost_per_run' in costs:
|
|
548
|
+
output_parts.append(f" Cost per run: ${costs['cost_per_run']['min']:.4f} - ${costs['cost_per_run']['max']:.4f}")
|
|
549
|
+
output_parts.append(f" Monthly cost: ${monthly['cost_min']:.2f} - ${monthly['cost_max']:.2f}")
|
|
550
|
+
else:
|
|
551
|
+
output_parts.append(" Cost: pass --price-in and --price-out (USD per million tokens) to get dollars")
|
|
549
552
|
|
|
550
553
|
# Output
|
|
551
554
|
output = '\n'.join(output_parts)
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Prompt Optimizer - Static analysis tool for prompt engineering
|
|
4
4
|
|
|
5
5
|
Features:
|
|
6
|
-
-
|
|
6
|
+
- Approximate token count (characters / 4, not a real tokenizer)
|
|
7
7
|
- Prompt structure analysis
|
|
8
8
|
- Clarity scoring
|
|
9
9
|
- Few-shot example extraction and management
|
|
@@ -11,7 +11,7 @@ Features:
|
|
|
11
11
|
|
|
12
12
|
Usage:
|
|
13
13
|
python prompt_optimizer.py prompt.txt --analyze
|
|
14
|
-
python prompt_optimizer.py prompt.txt --tokens
|
|
14
|
+
python prompt_optimizer.py prompt.txt --tokens
|
|
15
15
|
python prompt_optimizer.py prompt.txt --optimize --output optimized.txt
|
|
16
16
|
python prompt_optimizer.py prompt.txt --extract-examples --output examples.json
|
|
17
17
|
"""
|
|
@@ -25,32 +25,15 @@ from typing import Dict, List, Optional, Tuple
|
|
|
25
25
|
from dataclasses import dataclass, asdict
|
|
26
26
|
|
|
27
27
|
|
|
28
|
-
#
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
'gpt-3.5': 4.0,
|
|
32
|
-
'claude': 3.5,
|
|
33
|
-
'default': 4.0
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
# Cost per 1K tokens (input)
|
|
37
|
-
COST_PER_1K = {
|
|
38
|
-
'gpt-4': 0.03,
|
|
39
|
-
'gpt-4-turbo': 0.01,
|
|
40
|
-
'gpt-3.5-turbo': 0.0005,
|
|
41
|
-
'claude-3-opus': 0.015,
|
|
42
|
-
'claude-3-sonnet': 0.003,
|
|
43
|
-
'claude-3-haiku': 0.00025,
|
|
44
|
-
'default': 0.01
|
|
45
|
-
}
|
|
28
|
+
# Rough characters-per-token ratio. Real tokenizers differ by model and by text, so
|
|
29
|
+
# every count here is an estimate; use the provider's token-counting API for exact numbers.
|
|
30
|
+
CHARS_PER_TOKEN = 4.0
|
|
46
31
|
|
|
47
32
|
|
|
48
33
|
@dataclass
|
|
49
34
|
class PromptAnalysis:
|
|
50
35
|
"""Results of prompt analysis"""
|
|
51
36
|
token_count: int
|
|
52
|
-
estimated_cost: float
|
|
53
|
-
model: str
|
|
54
37
|
clarity_score: int
|
|
55
38
|
structure_score: int
|
|
56
39
|
issues: List[Dict[str, str]]
|
|
@@ -71,16 +54,9 @@ class FewShotExample:
|
|
|
71
54
|
index: int
|
|
72
55
|
|
|
73
56
|
|
|
74
|
-
def estimate_tokens(text: str
|
|
75
|
-
"""
|
|
76
|
-
|
|
77
|
-
return int(len(text) / ratio)
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
def estimate_cost(token_count: int, model: str = 'default') -> float:
|
|
81
|
-
"""Estimate cost based on token count"""
|
|
82
|
-
cost_per_1k = COST_PER_1K.get(model, COST_PER_1K['default'])
|
|
83
|
-
return round((token_count / 1000) * cost_per_1k, 6)
|
|
57
|
+
def estimate_tokens(text: str) -> int:
|
|
58
|
+
"""Approximate token count from the character count"""
|
|
59
|
+
return int(len(text) / CHARS_PER_TOKEN)
|
|
84
60
|
|
|
85
61
|
|
|
86
62
|
def find_ambiguous_instructions(text: str) -> List[Dict[str, str]]:
|
|
@@ -89,11 +65,9 @@ def find_ambiguous_instructions(text: str) -> List[Dict[str, str]]:
|
|
|
89
65
|
|
|
90
66
|
# Vague verbs that need specificity
|
|
91
67
|
vague_patterns = [
|
|
92
|
-
(r'\b(analyze|process|handle|deal with)\b', 'Vague verb - specify the exact action'),
|
|
93
68
|
(r'\b(good|nice|appropriate|suitable)\b', 'Subjective term - define specific criteria'),
|
|
94
69
|
(r'\b(etc\.|and so on|and more)\b', 'Open-ended list - enumerate all items explicitly'),
|
|
95
70
|
(r'\b(if needed|as necessary|when appropriate)\b', 'Conditional without criteria - specify when'),
|
|
96
|
-
(r'\b(some|several|many|few|various)\b', 'Vague quantity - use specific numbers'),
|
|
97
71
|
]
|
|
98
72
|
|
|
99
73
|
lines = text.split('\n')
|
|
@@ -155,7 +129,7 @@ def check_output_format(text: str) -> Tuple[bool, List[str]]:
|
|
|
155
129
|
has_format = any(re.search(p, text, re.IGNORECASE) for p in format_indicators)
|
|
156
130
|
|
|
157
131
|
if not has_format:
|
|
158
|
-
suggestions.append('
|
|
132
|
+
suggestions.append('State the expected output format (structure, length, what to include)')
|
|
159
133
|
|
|
160
134
|
return has_format, suggestions
|
|
161
135
|
|
|
@@ -277,7 +251,7 @@ def generate_suggestions(analysis: PromptAnalysis) -> List[str]:
|
|
|
277
251
|
suggestions = []
|
|
278
252
|
|
|
279
253
|
if not analysis.has_output_format:
|
|
280
|
-
suggestions.append('
|
|
254
|
+
suggestions.append('State the output format. If code will parse the response as JSON, enforce it with structured outputs instead of describing it in the prompt')
|
|
281
255
|
|
|
282
256
|
if analysis.example_count == 0:
|
|
283
257
|
suggestions.append('Consider adding 2-3 few-shot examples for consistent outputs')
|
|
@@ -289,22 +263,14 @@ def generate_suggestions(analysis: PromptAnalysis) -> List[str]:
|
|
|
289
263
|
if analysis.clarity_score < 70:
|
|
290
264
|
suggestions.append('Improve clarity: replace vague terms with specific instructions')
|
|
291
265
|
|
|
292
|
-
if analysis.token_count > 2000:
|
|
293
|
-
suggestions.append(f'Prompt is {analysis.token_count} tokens - consider condensing for cost efficiency')
|
|
294
|
-
|
|
295
|
-
# Check for role prompting
|
|
296
|
-
if not re.search(r'you are|act as|as a\s+\w+', analysis.sections[0].get('content', [''])[0] if analysis.sections else '', re.IGNORECASE):
|
|
297
|
-
suggestions.append('Consider adding role context: "You are an expert..."')
|
|
298
|
-
|
|
299
266
|
return suggestions
|
|
300
267
|
|
|
301
268
|
|
|
302
|
-
def analyze_prompt(text: str
|
|
269
|
+
def analyze_prompt(text: str) -> PromptAnalysis:
|
|
303
270
|
"""Perform comprehensive prompt analysis"""
|
|
304
271
|
|
|
305
272
|
# Basic metrics
|
|
306
|
-
token_count = estimate_tokens(text
|
|
307
|
-
cost = estimate_cost(token_count, model)
|
|
273
|
+
token_count = estimate_tokens(text)
|
|
308
274
|
word_count = len(text.split())
|
|
309
275
|
line_count = len(text.split('\n'))
|
|
310
276
|
|
|
@@ -324,8 +290,6 @@ def analyze_prompt(text: str, model: str = 'gpt-4') -> PromptAnalysis:
|
|
|
324
290
|
|
|
325
291
|
analysis = PromptAnalysis(
|
|
326
292
|
token_count=token_count,
|
|
327
|
-
estimated_cost=cost,
|
|
328
|
-
model=model,
|
|
329
293
|
clarity_score=clarity_score,
|
|
330
294
|
structure_score=structure_score,
|
|
331
295
|
issues=all_issues,
|
|
@@ -367,8 +331,7 @@ def format_report(analysis: PromptAnalysis) -> str:
|
|
|
367
331
|
report.append("")
|
|
368
332
|
|
|
369
333
|
report.append("📊 METRICS")
|
|
370
|
-
report.append(f"
|
|
371
|
-
report.append(f" Estimated cost: ${analysis.estimated_cost:.4f} ({analysis.model})")
|
|
334
|
+
report.append(f" Tokens (approx): {analysis.token_count:,}")
|
|
372
335
|
report.append(f" Word count: {analysis.word_count:,}")
|
|
373
336
|
report.append(f" Line count: {analysis.line_count}")
|
|
374
337
|
report.append("")
|
|
@@ -411,13 +374,16 @@ def format_report(analysis: PromptAnalysis) -> str:
|
|
|
411
374
|
|
|
412
375
|
|
|
413
376
|
def main():
|
|
377
|
+
# The report uses emoji; a Windows console defaults to cp1252 and cannot print them.
|
|
378
|
+
if hasattr(sys.stdout, "reconfigure"):
|
|
379
|
+
sys.stdout.reconfigure(encoding="utf-8")
|
|
414
380
|
parser = argparse.ArgumentParser(
|
|
415
381
|
description="Prompt Optimizer - Analyze and optimize prompts",
|
|
416
382
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
417
383
|
epilog="""
|
|
418
384
|
Examples:
|
|
419
385
|
%(prog)s prompt.txt --analyze
|
|
420
|
-
%(prog)s prompt.txt --tokens
|
|
386
|
+
%(prog)s prompt.txt --tokens
|
|
421
387
|
%(prog)s prompt.txt --optimize --output optimized.txt
|
|
422
388
|
%(prog)s prompt.txt --extract-examples --output examples.json
|
|
423
389
|
"""
|
|
@@ -428,9 +394,6 @@ Examples:
|
|
|
428
394
|
parser.add_argument('--tokens', '-t', action='store_true', help='Count tokens only')
|
|
429
395
|
parser.add_argument('--optimize', '-O', action='store_true', help='Generate optimized version')
|
|
430
396
|
parser.add_argument('--extract-examples', '-e', action='store_true', help='Extract few-shot examples')
|
|
431
|
-
parser.add_argument('--model', '-m', default='gpt-4',
|
|
432
|
-
choices=['gpt-4', 'gpt-4-turbo', 'gpt-3.5-turbo', 'claude-3-opus', 'claude-3-sonnet', 'claude-3-haiku'],
|
|
433
|
-
help='Model for token/cost estimation')
|
|
434
397
|
parser.add_argument('--output', '-o', help='Output file path')
|
|
435
398
|
parser.add_argument('--json', '-j', action='store_true', help='Output as JSON')
|
|
436
399
|
parser.add_argument('--compare', '-c', help='Compare with baseline analysis JSON')
|
|
@@ -447,17 +410,11 @@ Examples:
|
|
|
447
410
|
|
|
448
411
|
# Tokens only
|
|
449
412
|
if args.tokens:
|
|
450
|
-
token_count = estimate_tokens(text
|
|
451
|
-
cost = estimate_cost(token_count, args.model)
|
|
413
|
+
token_count = estimate_tokens(text)
|
|
452
414
|
if args.json:
|
|
453
|
-
print(json.dumps({
|
|
454
|
-
'tokens': token_count,
|
|
455
|
-
'cost': cost,
|
|
456
|
-
'model': args.model
|
|
457
|
-
}, indent=2))
|
|
415
|
+
print(json.dumps({'tokens_approx': token_count}, indent=2))
|
|
458
416
|
else:
|
|
459
|
-
print(f"Tokens: {token_count:,}")
|
|
460
|
-
print(f"Estimated cost: ${cost:.4f} ({args.model})")
|
|
417
|
+
print(f"Tokens (approx): {token_count:,}")
|
|
461
418
|
sys.exit(0)
|
|
462
419
|
|
|
463
420
|
# Extract examples
|
|
@@ -481,8 +438,8 @@ Examples:
|
|
|
481
438
|
print(f"Optimized prompt written to {args.output}")
|
|
482
439
|
|
|
483
440
|
# Show comparison
|
|
484
|
-
orig_tokens = estimate_tokens(text
|
|
485
|
-
new_tokens = estimate_tokens(optimized
|
|
441
|
+
orig_tokens = estimate_tokens(text)
|
|
442
|
+
new_tokens = estimate_tokens(optimized)
|
|
486
443
|
saved = orig_tokens - new_tokens
|
|
487
444
|
print(f"Tokens: {orig_tokens:,} -> {new_tokens:,} (saved {saved:,})")
|
|
488
445
|
else:
|
|
@@ -490,7 +447,7 @@ Examples:
|
|
|
490
447
|
sys.exit(0)
|
|
491
448
|
|
|
492
449
|
# Default: full analysis
|
|
493
|
-
analysis = analyze_prompt(text
|
|
450
|
+
analysis = analyze_prompt(text)
|
|
494
451
|
|
|
495
452
|
# Compare with baseline
|
|
496
453
|
if args.compare:
|
|
@@ -180,7 +180,7 @@ if (p.x < 1.0 || p.y < 1.0 ||
|
|
|
180
180
|
c.xyw *= 0.0;
|
|
181
181
|
}
|
|
182
182
|
|
|
183
|
-
//
|
|
183
|
+
// Ink decay: must use multiplicative decay; subtractive decay causes saturation in high-concentration areas and overly fast decay in low-concentration areas
|
|
184
184
|
c.w *= 0.995; // 0.5% decay per frame, adjustable [0.99=fast dissipation, 0.999=persistent]
|
|
185
185
|
|
|
186
186
|
// Numerical clamping (prevent explosion)
|
|
@@ -199,14 +199,14 @@ void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
|
|
199
199
|
vec2 uv = fragCoord / iResolution.xy;
|
|
200
200
|
vec4 c = texture(iChannel0, uv);
|
|
201
201
|
|
|
202
|
-
//
|
|
202
|
+
// Color base must be bright enough! 0.5+0.5*cos produces bright colors in [0,1] range
|
|
203
203
|
// Never use extremely dark base colors like vec3(0.02, 0.01, 0.08) — multiplied by ink, they become invisible
|
|
204
204
|
vec3 col = 0.5 + 0.5 * cos(atan(c.y, c.x) + vec3(0.0, 2.1, 4.2));
|
|
205
|
-
//
|
|
205
|
+
// Use smoothstep instead of linear division to preserve gradient variation
|
|
206
206
|
float ink = smoothstep(0.0, 2.0, c.w);
|
|
207
207
|
col *= ink;
|
|
208
208
|
|
|
209
|
-
//
|
|
209
|
+
// Background color must be visible to the eye (RGB at least > 5/255 ≈ 0.02), otherwise users think the page is all black
|
|
210
210
|
col = max(col, vec3(0.02, 0.012, 0.035));
|
|
211
211
|
|
|
212
212
|
fragColor = vec4(col, 1.0);
|