@causyne/agent 0.0.0-stage → 1.10.1
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/LICENSE +102 -0
- package/README.md +31 -2
- package/SECURITY.md +24 -0
- package/bin/causyne.js +13 -0
- package/docs/ARCHITECTURE.md +63 -0
- package/docs/PROVENANCE.md +29 -0
- package/docs/SECURITY_REVIEW.md +89 -0
- package/docs/THIRD_PARTY_NOTICES.md +49 -0
- package/native-skills/ai-engineering/context-window-management/SKILL.md +43 -0
- package/native-skills/ai-engineering/llm-evaluation/SKILL.md +46 -0
- package/native-skills/ai-engineering/model-cost-and-latency/SKILL.md +46 -0
- package/native-skills/ai-engineering/prompt-construction/SKILL.md +42 -0
- package/native-skills/ai-engineering/retrieval-augmented-generation/SKILL.md +42 -0
- package/native-skills/ai-engineering/structured-output-and-schemas/SKILL.md +45 -0
- package/native-skills/ai-engineering/tool-calling-agents/SKILL.md +43 -0
- package/native-skills/android/app-performance-profiling/SKILL.md +42 -0
- package/native-skills/android/background-work-scheduling/SKILL.md +47 -0
- package/native-skills/android/compose-state-and-recomposition/SKILL.md +43 -0
- package/native-skills/android/gradle-build-configuration/SKILL.md +41 -0
- package/native-skills/android/lifecycle-and-leaks/SKILL.md +46 -0
- package/native-skills/android/play-store-release/SKILL.md +43 -0
- package/native-skills/android/room-and-persistence/SKILL.md +40 -0
- package/native-skills/backend/authentication-and-sessions/SKILL.md +45 -0
- package/native-skills/backend/background-jobs-and-queues/SKILL.md +42 -0
- package/native-skills/backend/caching-strategy/SKILL.md +44 -0
- package/native-skills/backend/graceful-shutdown/SKILL.md +42 -0
- package/native-skills/backend/rate-limiting-and-quotas/SKILL.md +40 -0
- package/native-skills/backend/rest-api-design/SKILL.md +40 -0
- package/native-skills/backend/webhook-delivery-and-receipt/SKILL.md +43 -0
- package/native-skills/cloud/cost-optimisation/SKILL.md +46 -0
- package/native-skills/cloud/iam-least-privilege/SKILL.md +43 -0
- package/native-skills/cloud/infrastructure-as-code/SKILL.md +43 -0
- package/native-skills/cloud/multi-region-and-failover/SKILL.md +43 -0
- package/native-skills/cloud/serverless-patterns/SKILL.md +47 -0
- package/native-skills/data/data-quality-monitoring/SKILL.md +51 -0
- package/native-skills/data/etl-pipeline-reliability/SKILL.md +43 -0
- package/native-skills/data/exploratory-analysis/SKILL.md +43 -0
- package/native-skills/data/metric-definition/SKILL.md +42 -0
- package/native-skills/data/notebook-to-production/SKILL.md +43 -0
- package/native-skills/database/backup-and-recovery/SKILL.md +43 -0
- package/native-skills/database/connection-pooling/SKILL.md +42 -0
- package/native-skills/database/data-integrity-and-constraints/SKILL.md +42 -0
- package/native-skills/database/query-optimisation/SKILL.md +38 -0
- package/native-skills/database/safe-migrations/SKILL.md +47 -0
- package/native-skills/database/schema-design/SKILL.md +38 -0
- package/native-skills/database/transactions-and-isolation/SKILL.md +41 -0
- package/native-skills/design/colour-system-construction/SKILL.md +38 -0
- package/native-skills/design/design-direction-brief/SKILL.md +41 -0
- package/native-skills/design/motion-and-transitions/SKILL.md +38 -0
- package/native-skills/design/responsive-strategy/SKILL.md +39 -0
- package/native-skills/design/spacing-and-rhythm/SKILL.md +38 -0
- package/native-skills/design/type-scale-and-hierarchy/SKILL.md +39 -0
- package/native-skills/design/visual-qa-loop/SKILL.md +42 -0
- package/native-skills/devops/docker-multi-stage-builds/SKILL.md +60 -0
- package/native-skills/devops/github-actions-ci/SKILL.md +60 -0
- package/native-skills/devops/incident-triage/SKILL.md +38 -0
- package/native-skills/devops/kubernetes-deployment-hardening/SKILL.md +64 -0
- package/native-skills/devops/observability-baseline/SKILL.md +38 -0
- package/native-skills/devops/secret-management/SKILL.md +40 -0
- package/native-skills/devops/terraform-state-and-modules/SKILL.md +36 -0
- package/native-skills/devops/zero-downtime-deploys/SKILL.md +40 -0
- package/native-skills/git/bisect-regression-hunt/SKILL.md +43 -0
- package/native-skills/git/branch-strategy/SKILL.md +39 -0
- package/native-skills/git/commit-hygiene/SKILL.md +41 -0
- package/native-skills/git/history-recovery/SKILL.md +44 -0
- package/native-skills/git/large-repository-surgery/SKILL.md +46 -0
- package/native-skills/git/merge-conflict-resolution/SKILL.md +42 -0
- package/native-skills/media/cinematic-3d-shot/SKILL.md +104 -0
- package/native-skills/mobile/app-startup-optimisation/SKILL.md +41 -0
- package/native-skills/mobile/cross-platform-tradeoffs/SKILL.md +42 -0
- package/native-skills/mobile/deep-linking/SKILL.md +39 -0
- package/native-skills/mobile/mobile-storage-security/SKILL.md +45 -0
- package/native-skills/mobile/offline-first-sync/SKILL.md +42 -0
- package/native-skills/mobile/push-notifications/SKILL.md +38 -0
- package/native-skills/performance/algorithmic-complexity/SKILL.md +43 -0
- package/native-skills/performance/concurrency-and-parallelism/SKILL.md +42 -0
- package/native-skills/performance/load-testing/SKILL.md +42 -0
- package/native-skills/performance/memory-and-leak-hunting/SKILL.md +41 -0
- package/native-skills/performance/network-and-payload-efficiency/SKILL.md +42 -0
- package/native-skills/performance/profiling-methodology/SKILL.md +46 -0
- package/native-skills/python/async-correctness/SKILL.md +40 -0
- package/native-skills/python/cli-tool-construction/SKILL.md +44 -0
- package/native-skills/python/data-processing-pipelines/SKILL.md +38 -0
- package/native-skills/python/environment-isolation/SKILL.md +41 -0
- package/native-skills/python/packaging-and-distribution/SKILL.md +56 -0
- package/native-skills/python/pytest-suite-design/SKILL.md +39 -0
- package/native-skills/python/type-hints-and-static-checking/SKILL.md +42 -0
- package/native-skills/security/authorization-model/SKILL.md +42 -0
- package/native-skills/security/crypto-usage/SKILL.md +48 -0
- package/native-skills/security/dependency-supply-chain/SKILL.md +42 -0
- package/native-skills/security/input-validation-and-injection/SKILL.md +44 -0
- package/native-skills/security/secure-file-uploads/SKILL.md +46 -0
- package/native-skills/security/security-headers-and-csp/SKILL.md +44 -0
- package/native-skills/security/threat-modelling/SKILL.md +46 -0
- package/native-skills/testing/end-to-end-test-stability/SKILL.md +42 -0
- package/native-skills/testing/property-based-testing/SKILL.md +46 -0
- package/native-skills/testing/regression-test-from-a-bug/SKILL.md +41 -0
- package/native-skills/testing/snapshot-and-visual-regression/SKILL.md +42 -0
- package/native-skills/testing/test-doubles-and-mocking/SKILL.md +43 -0
- package/native-skills/testing/test-strategy-and-pyramid/SKILL.md +39 -0
- package/native-skills/testing/writing-good-assertions/SKILL.md +42 -0
- package/native-skills/web/accessible-components/SKILL.md +45 -0
- package/native-skills/web/api-client-resilience/SKILL.md +39 -0
- package/native-skills/web/bundle-size-reduction/SKILL.md +38 -0
- package/native-skills/web/core-web-vitals/SKILL.md +40 -0
- package/native-skills/web/css-layout-systems/SKILL.md +41 -0
- package/native-skills/web/form-validation-ux/SKILL.md +39 -0
- package/native-skills/web/react-state-architecture/SKILL.md +41 -0
- package/native-skills/web/ssr-hydration-correctness/SKILL.md +45 -0
- package/package.json +68 -4
- package/src/agentLoop.js +2458 -0
- package/src/appChannel.js +109 -0
- package/src/approvalGrants.js +66 -0
- package/src/auditLog.js +52 -0
- package/src/autoUpdate.js +12 -0
- package/src/capabilities.js +36 -0
- package/src/checkpoints.js +1199 -0
- package/src/cliMode.js +638 -0
- package/src/commands.js +805 -0
- package/src/compiledSkills.js +540 -0
- package/src/config.js +130 -0
- package/src/contextManager.js +498 -0
- package/src/cortex/autoCondenser.js +192 -0
- package/src/cortex/provisioner.js +27 -0
- package/src/cortex/vectorDb.js +447 -0
- package/src/designPalettes.js +99 -0
- package/src/devMode.js +6 -0
- package/src/embodimentSession.js +180 -0
- package/src/entrypoint.js +194 -0
- package/src/execSafe.js +21 -0
- package/src/gitSnapshot.js +378 -0
- package/src/mcp/jsonRpc.js +165 -0
- package/src/mcp/mcpClient.js +136 -0
- package/src/mcp/mcpRegistry.js +207 -0
- package/src/memory.js +62 -0
- package/src/memoryManager.js +124 -0
- package/src/modelCatalogue.js +132 -0
- package/src/modelIds.js +42 -0
- package/src/modelRouter.js +145 -0
- package/src/outputStore.js +246 -0
- package/src/perception.js +124 -0
- package/src/planCache.js +437 -0
- package/src/procSignal.js +32 -0
- package/src/providers/anthropic.js +408 -0
- package/src/providers/base.js +328 -0
- package/src/providers/dashscope-byok.js +86 -0
- package/src/providers/deepseek.js +80 -0
- package/src/providers/factory.js +37 -0
- package/src/providers/gemini.js +346 -0
- package/src/providers/moonshot.js +73 -0
- package/src/providers/muse.js +169 -0
- package/src/providers/ollama.js +104 -0
- package/src/providers/openai-compatible.js +84 -0
- package/src/providers/openai.js +20 -0
- package/src/providers/qwen-byok.js +76 -0
- package/src/providers/xai.js +73 -0
- package/src/provisioning/capabilityConsent.js +24 -0
- package/src/provisioning/capabilityProvisioner.js +271 -0
- package/src/provisioning/capabilityTools.js +29 -0
- package/src/reporting.js +373 -0
- package/src/sandbox.js +529 -0
- package/src/sessionStore.js +279 -0
- package/src/skillsManager.js +288 -0
- package/src/slopDetector.js +307 -0
- package/src/taskBuffer.js +45 -0
- package/src/taskShape.js +241 -0
- package/src/textDiff.js +150 -0
- package/src/tokenTracker.js +560 -0
- package/src/tool-scripts/ax_snapshot.applescript +39 -0
- package/src/tool-scripts/ax_snapshot.ps1 +10 -0
- package/src/tool-scripts/desktop_act.applescript +58 -0
- package/src/tool-scripts/resolve_automator.py +119 -0
- package/src/toolPacks.js +524 -0
- package/src/tools/archive.js +63 -0
- package/src/tools/astryxOracle.js +78 -0
- package/src/tools/axSnapshot.js +165 -0
- package/src/tools/blenderAutomator.js +349 -0
- package/src/tools/browserAutomator.js +252 -0
- package/src/tools/checkSystemSpecs.js +64 -0
- package/src/tools/clipboard.js +36 -0
- package/src/tools/codeSearchAst.js +101 -0
- package/src/tools/codeSearcher.js +230 -0
- package/src/tools/codeTools.js +262 -0
- package/src/tools/codebaseSearch.js +75 -0
- package/src/tools/createSkill.js +129 -0
- package/src/tools/deferredMcpSearch.js +246 -0
- package/src/tools/desktopAct.js +208 -0
- package/src/tools/desktopOpen.js +34 -0
- package/src/tools/dynamicLoader.js +44 -0
- package/src/tools/executeProceduralMedia.js +93 -0
- package/src/tools/fsDelete.js +51 -0
- package/src/tools/fsEdit.js +105 -0
- package/src/tools/fsFind.js +128 -0
- package/src/tools/fsList.js +77 -0
- package/src/tools/fsMove.js +57 -0
- package/src/tools/fsRead.js +87 -0
- package/src/tools/fsSearch.js +198 -0
- package/src/tools/fsWrite.js +41 -0
- package/src/tools/gameAiBehaviorTree.js +208 -0
- package/src/tools/gameAnimationRig.js +194 -0
- package/src/tools/gameAssetFetcher.js +372 -0
- package/src/tools/gameAssetHarvester.js +210 -0
- package/src/tools/gameAudioSynth.js +267 -0
- package/src/tools/gameBuilder.js +886 -0
- package/src/tools/gameCanvasAudit.js +101 -0
- package/src/tools/gameCinematicSequencer.js +151 -0
- package/src/tools/gameDataForge.js +124 -0
- package/src/tools/gameDialogueTreeGen.js +166 -0
- package/src/tools/gameEconomyBalancer.js +161 -0
- package/src/tools/gameEntitySpawner.js +207 -0
- package/src/tools/gameLoreForge.js +153 -0
- package/src/tools/gameQuestArcBuilder.js +152 -0
- package/src/tools/gameSceneBuilder.js +158 -0
- package/src/tools/gameShaderForge.js +181 -0
- package/src/tools/gameTilemapGenerator.js +164 -0
- package/src/tools/gameUiHudBuilder.js +292 -0
- package/src/tools/gameVfxEmitterGen.js +108 -0
- package/src/tools/gameWebRuntimeInspector.js +91 -0
- package/src/tools/generateMediaViaApi.js +358 -0
- package/src/tools/gitExec.js +54 -0
- package/src/tools/godotAutomator.js +437 -0
- package/src/tools/manageLocalAiDependencies.js +220 -0
- package/src/tools/memoryWrite.js +99 -0
- package/src/tools/multiEdit.js +107 -0
- package/src/tools/palmierAutomator.js +104 -0
- package/src/tools/pdfReader.js +112 -0
- package/src/tools/persistentShell.js +148 -0
- package/src/tools/printer.js +316 -0
- package/src/tools/procTerm.js +91 -0
- package/src/tools/processList.js +52 -0
- package/src/tools/readNativeSkill.js +39 -0
- package/src/tools/registry.js +277 -0
- package/src/tools/resolveAutomator.js +102 -0
- package/src/tools/screenshot.js +75 -0
- package/src/tools/subagentOrchestrator.js +305 -0
- package/src/tools/sysRun.js +125 -0
- package/src/tools/todoWrite.js +75 -0
- package/src/tools/toolDispatch.js +127 -0
- package/src/tools/toolForge.js +124 -0
- package/src/tools/updatePlan.js +88 -0
- package/src/tools/viewImage.js +82 -0
- package/src/tools/visionInspector.js +154 -0
- package/src/tools/webFetch.js +74 -0
- package/src/tools/webSearch.js +82 -0
- package/src/tui/ask.js +164 -0
- package/src/tui/banner.js +158 -0
- package/src/tui/block.js +152 -0
- package/src/tui/chatRenderer.js +953 -0
- package/src/tui/completion.js +424 -0
- package/src/tui/dialogs.js +606 -0
- package/src/tui/diff.js +296 -0
- package/src/tui/history.js +135 -0
- package/src/tui/home.js +217 -0
- package/src/tui/invocation.js +105 -0
- package/src/tui/keys.js +443 -0
- package/src/tui/lineEditor.js +256 -0
- package/src/tui/overlay.js +256 -0
- package/src/tui/prompt.js +1258 -0
- package/src/tui/selectList.js +335 -0
- package/src/tui/stage.js +330 -0
- package/src/tui/stageSurface.js +609 -0
- package/src/tui/statusLine.js +254 -0
- package/src/tui/text.js +345 -0
- package/src/tui/theme.js +393 -0
- package/src/tui/toolDisplay.js +176 -0
- package/src/tui/transcript.js +235 -0
- package/src/tui/viewport.js +337 -0
- package/src/uncertainty.js +271 -0
- package/src/userSkills.js +265 -0
- package/src/utils/cli_ui.js +0 -0
- package/src/utils/inquirer.js +12 -0
- package/src/utils/paths.js +37 -0
- package/src/version.js +38 -0
- package/src/vfeTracker.js +220 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import json
|
|
3
|
+
import os
|
|
4
|
+
|
|
5
|
+
def run_bridge(args):
|
|
6
|
+
try:
|
|
7
|
+
import DaVinciResolveScript as dvr_script
|
|
8
|
+
except ImportError:
|
|
9
|
+
print(json.dumps({"success": False, "error": "[ENGINE MISSING] DaVinci Resolve Studio Python API not found. Please ensure 'External scripting using: Local' is enabled in Preferences -> System -> General, and DaVinci Resolve Studio is running."}))
|
|
10
|
+
return
|
|
11
|
+
|
|
12
|
+
resolve = dvr_script.scriptapp("Resolve")
|
|
13
|
+
if resolve is None:
|
|
14
|
+
print(json.dumps({"success": False, "error": "[CONNECTION ERROR] Could not connect to DaVinci Resolve. Please ensure DaVinci Resolve Studio is open."}))
|
|
15
|
+
return
|
|
16
|
+
|
|
17
|
+
projectManager = resolve.GetProjectManager()
|
|
18
|
+
project = projectManager.GetCurrentProject()
|
|
19
|
+
if not project:
|
|
20
|
+
print(json.dumps({"success": False, "error": "No open project found."}))
|
|
21
|
+
return
|
|
22
|
+
|
|
23
|
+
mediaPool = project.GetMediaPool()
|
|
24
|
+
timeline = project.GetCurrentTimeline()
|
|
25
|
+
|
|
26
|
+
action = args.get("action")
|
|
27
|
+
|
|
28
|
+
if action == "checkConnection":
|
|
29
|
+
print(json.dumps({
|
|
30
|
+
"success": True,
|
|
31
|
+
"message": f"Connected to DaVinci Resolve. Active Project: {project.GetName()}"
|
|
32
|
+
}))
|
|
33
|
+
return
|
|
34
|
+
|
|
35
|
+
elif action == "setupColorManagement":
|
|
36
|
+
mode = args.get("color_space_mode", "automatic").lower()
|
|
37
|
+
try:
|
|
38
|
+
project.SetSetting("colorScienceMode", "davinciYRGBColorManaged")
|
|
39
|
+
|
|
40
|
+
if mode == "automatic":
|
|
41
|
+
project.SetSetting("automaticColorManagement", "1")
|
|
42
|
+
print(json.dumps({
|
|
43
|
+
"success": True,
|
|
44
|
+
"message": "Successfully applied Automatic Resolve Color Management (RCM). DaVinci will now auto-detect S-Log, LogC, BRAW, etc."
|
|
45
|
+
}))
|
|
46
|
+
else:
|
|
47
|
+
project.SetSetting("automaticColorManagement", "0")
|
|
48
|
+
project.SetSetting("colorSpaceManager", "Custom")
|
|
49
|
+
project.SetSetting("colorSpaceInput", args.get("input_color_space", "ARRI LogC3"))
|
|
50
|
+
project.SetSetting("colorSpaceTimeline", "DaVinci WG/Intermediate")
|
|
51
|
+
project.SetSetting("colorSpaceOutput", args.get("output_color_space", "Rec.709 Gamma 2.4"))
|
|
52
|
+
|
|
53
|
+
print(json.dumps({
|
|
54
|
+
"success": True,
|
|
55
|
+
"message": f"Successfully applied Custom RCM: {args.get('input_color_space', 'ARRI LogC3')} to {args.get('output_color_space', 'Rec.709 Gamma 2.4')}."
|
|
56
|
+
}))
|
|
57
|
+
except Exception as e:
|
|
58
|
+
print(json.dumps({"success": False, "error": f"Failed to setup RCM: {str(e)}"}))
|
|
59
|
+
return
|
|
60
|
+
|
|
61
|
+
elif action == "importAndAssemble":
|
|
62
|
+
media_path = args.get("mediaPath")
|
|
63
|
+
if not media_path or not os.path.exists(media_path):
|
|
64
|
+
print(json.dumps({"success": False, "error": f"Media path not found: {media_path}"}))
|
|
65
|
+
return
|
|
66
|
+
|
|
67
|
+
try:
|
|
68
|
+
imported_clips = mediaPool.ImportMedia([media_path])
|
|
69
|
+
if not imported_clips:
|
|
70
|
+
print(json.dumps({"success": False, "error": "No media found or imported."}))
|
|
71
|
+
return
|
|
72
|
+
|
|
73
|
+
fps = str(args.get("fps", "auto")).lower()
|
|
74
|
+
res_x = str(args.get("resolution_x", "auto")).lower()
|
|
75
|
+
res_y = str(args.get("resolution_y", "auto")).lower()
|
|
76
|
+
|
|
77
|
+
if fps == "auto" or res_x == "auto" or res_y == "auto":
|
|
78
|
+
first_clip = imported_clips[0]
|
|
79
|
+
|
|
80
|
+
if fps == "auto":
|
|
81
|
+
detected_fps = first_clip.GetClipProperty("FPS")
|
|
82
|
+
fps = str(detected_fps) if detected_fps else "23.976"
|
|
83
|
+
|
|
84
|
+
if res_x == "auto" or res_y == "auto":
|
|
85
|
+
detected_res = first_clip.GetClipProperty("Resolution")
|
|
86
|
+
if detected_res and "x" in str(detected_res):
|
|
87
|
+
parts = str(detected_res).split("x")
|
|
88
|
+
res_x, res_y = parts[0], parts[1]
|
|
89
|
+
else:
|
|
90
|
+
res_x, res_y = "4096", "2160"
|
|
91
|
+
|
|
92
|
+
project.SetSetting("timelineFrameRate", fps)
|
|
93
|
+
project.SetSetting("timelineResolutionWidth", res_x)
|
|
94
|
+
project.SetSetting("timelineResolutionHeight", res_y)
|
|
95
|
+
|
|
96
|
+
if not timeline:
|
|
97
|
+
timeline = mediaPool.CreateEmptyTimeline("Causyne_Automated_Timeline")
|
|
98
|
+
|
|
99
|
+
mediaPool.AppendToTimeline(imported_clips)
|
|
100
|
+
|
|
101
|
+
print(json.dumps({
|
|
102
|
+
"success": True,
|
|
103
|
+
"message": f"Successfully imported {len(imported_clips)} clips and auto-assembled on timeline '{timeline.GetName()}' at detected {res_x}x{res_y} {fps}fps."
|
|
104
|
+
}))
|
|
105
|
+
except Exception as e:
|
|
106
|
+
print(json.dumps({"success": False, "error": f"Failed during auto-import/assembly: {str(e)}"}))
|
|
107
|
+
return
|
|
108
|
+
|
|
109
|
+
else:
|
|
110
|
+
print(json.dumps({"success": False, "error": f"Unknown action: {action}"}))
|
|
111
|
+
return
|
|
112
|
+
|
|
113
|
+
if __name__ == "__main__":
|
|
114
|
+
try:
|
|
115
|
+
raw_args = sys.argv[1]
|
|
116
|
+
args = json.loads(raw_args)
|
|
117
|
+
run_bridge(args)
|
|
118
|
+
except Exception as e:
|
|
119
|
+
print(json.dumps({"success": False, "error": f"Python Bridge Error: {str(e)}"}))
|
package/src/toolPacks.js
ADDED
|
@@ -0,0 +1,524 @@
|
|
|
1
|
+
// Sovereign Progressive Disclosure — Capability Packs
|
|
2
|
+
//
|
|
3
|
+
// Causyne ships 69 native tools. Sending every schema on every LLM call costs
|
|
4
|
+
// ~14,700 tokens per step before the agent has done any work, and half of that
|
|
5
|
+
// is game tooling that a "rename my files" task never touches.
|
|
6
|
+
//
|
|
7
|
+
// This module does NOT remove any capability. It only controls *when* a schema
|
|
8
|
+
// enters the context window. Every tool stays reachable through three routes:
|
|
9
|
+
// 1. Intent pre-warm — routePacks() unlocks the right packs before step 1
|
|
10
|
+
// 2. tool_search — the agent discovers and unlocks any pack on demand
|
|
11
|
+
// 3. Auto-unlock recovery — calling a locked-but-real tool unlocks its pack
|
|
12
|
+
//
|
|
13
|
+
// Set config.grantAllTools = true to disable deferral entirely.
|
|
14
|
+
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
// Pack membership. Names match the `name` field of each tool schema, with dots
|
|
17
|
+
// already normalised to underscores (see tools/registry.js TOOL_DEFINITIONS).
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
|
|
20
|
+
export const CORE_TOOLS = [
|
|
21
|
+
'sysRun',
|
|
22
|
+
'sysRunBg',
|
|
23
|
+
'terminal_persistent_shell',
|
|
24
|
+
'fs_read',
|
|
25
|
+
'fs_write',
|
|
26
|
+
'fs_edit',
|
|
27
|
+
'MultiEdit',
|
|
28
|
+
'fs_list',
|
|
29
|
+
'fs_search',
|
|
30
|
+
'fs_find',
|
|
31
|
+
'fs_move',
|
|
32
|
+
'fs_delete',
|
|
33
|
+
'gitOp',
|
|
34
|
+
'code_search_ripgrep',
|
|
35
|
+
'codebase_search',
|
|
36
|
+
'code_verify_syntax',
|
|
37
|
+
'web_search',
|
|
38
|
+
'web_fetch',
|
|
39
|
+
'TodoWrite',
|
|
40
|
+
'update_plan',
|
|
41
|
+
'memory_write',
|
|
42
|
+
'fs_read_skill',
|
|
43
|
+
'skill_create',
|
|
44
|
+
'tool_search'
|
|
45
|
+
];
|
|
46
|
+
|
|
47
|
+
export const PACKS = {
|
|
48
|
+
game: [
|
|
49
|
+
// Stage 1 of the game cascade calls check_system_specs to verify the
|
|
50
|
+
// engine, so it must travel with this pack as well as with media.
|
|
51
|
+
'check_system_specs',
|
|
52
|
+
'godot_act',
|
|
53
|
+
'game_build_html5',
|
|
54
|
+
'game_asset_fetch',
|
|
55
|
+
'game_asset_harvest',
|
|
56
|
+
'game_lore_forge',
|
|
57
|
+
'game_dialogue_tree_gen',
|
|
58
|
+
'game_quest_arc_builder',
|
|
59
|
+
'game_animation_rig',
|
|
60
|
+
'game_ai_behavior_tree',
|
|
61
|
+
'game_cinematic_sequencer',
|
|
62
|
+
'game_audio_synth',
|
|
63
|
+
'game_vfx_emitter_gen',
|
|
64
|
+
'game_shader_forge',
|
|
65
|
+
'game_scene_build',
|
|
66
|
+
'game_entity_spawner',
|
|
67
|
+
'game_tilemap_gen',
|
|
68
|
+
'game_ui_hud_builder',
|
|
69
|
+
'game_economy_balancer',
|
|
70
|
+
'game_data_forge',
|
|
71
|
+
'game_web_runtime_inspector',
|
|
72
|
+
'game_canvas_audit'
|
|
73
|
+
],
|
|
74
|
+
web: [
|
|
75
|
+
'browser_act',
|
|
76
|
+
'screenshot',
|
|
77
|
+
'vision_inspect_ui',
|
|
78
|
+
'view_image',
|
|
79
|
+
'astryx_oracle'
|
|
80
|
+
],
|
|
81
|
+
media: [
|
|
82
|
+
'generate_media_via_api',
|
|
83
|
+
'execute_procedural_media',
|
|
84
|
+
'check_system_specs',
|
|
85
|
+
'manage_local_dependencies',
|
|
86
|
+
'blender_act',
|
|
87
|
+
'resolve_act',
|
|
88
|
+
'palmier_act'
|
|
89
|
+
],
|
|
90
|
+
system: [
|
|
91
|
+
// Channel B of the Three-Channel Doctrine: reading the screen as structured
|
|
92
|
+
// text instead of pixels. Lives here rather than in core because most tasks
|
|
93
|
+
// never touch a GUI, and tool_search brings it in the moment one does.
|
|
94
|
+
'ax_snapshot',
|
|
95
|
+
// Channel C. Ships beside its observer on purpose: acting on a screen you
|
|
96
|
+
// have not read is how an agent clicks the wrong button confidently.
|
|
97
|
+
'desktop_act',
|
|
98
|
+
'process_list',
|
|
99
|
+
'proc_term',
|
|
100
|
+
'archive',
|
|
101
|
+
'clipboard',
|
|
102
|
+
'desktop_open',
|
|
103
|
+
'printer_print',
|
|
104
|
+
'printer_list_printers',
|
|
105
|
+
'printer_get_status'
|
|
106
|
+
],
|
|
107
|
+
advanced: [
|
|
108
|
+
'tool_forge',
|
|
109
|
+
'agent_subagent_orchestrate',
|
|
110
|
+
'code_search_ast',
|
|
111
|
+
'code_list_symbols',
|
|
112
|
+
'pdf_read'
|
|
113
|
+
]
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
export const PACK_NAMES = Object.keys(PACKS);
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* The core tools that ship in EVERY request on a provider with no native
|
|
120
|
+
* schema deferral. The rest of CORE_TOOLS is withheld until the model asks for
|
|
121
|
+
* it with `tool_search`, exactly as a capability pack is.
|
|
122
|
+
*
|
|
123
|
+
* WHY: Anthropic can hold schemas server-side (`defer_loading` +
|
|
124
|
+
* `tool_search_tool_regex`), so on Claude the full core costs nothing to
|
|
125
|
+
* advertise. That is one provider out of eleven. On OpenAI, Gemini, DeepSeek,
|
|
126
|
+
* Qwen, Muse, xAI, Moonshot, Ollama and the two BYOK paths, all 24 core
|
|
127
|
+
* schemas were serialised into every single request — 3,341 tokens, of which a
|
|
128
|
+
* typical turn calls two.
|
|
129
|
+
*
|
|
130
|
+
* WHAT IS IN, AND WHY EXACTLY THESE: read, write, edit, list and search cover
|
|
131
|
+
* every file operation a first turn can need; `sysRun` is the escape hatch that
|
|
132
|
+
* can reach anything the other seven cannot; `TodoWrite` is how a multi-step
|
|
133
|
+
* task announces its plan on step one; `tool_search` is the door to the other
|
|
134
|
+
* 62. With this set the agent is never stuck — worst case it spends one call
|
|
135
|
+
* discovering the tool it wants, and the tool it discovers stays loaded for the
|
|
136
|
+
* rest of the task.
|
|
137
|
+
*
|
|
138
|
+
* WHAT WITHHOLDING DOES NOT DO: it does not remove capability. `resolveTool()`
|
|
139
|
+
* still resolves a withheld core tool by name, so a model that calls one from
|
|
140
|
+
* memory simply gets it. Only the schema is absent, never the tool.
|
|
141
|
+
*/
|
|
142
|
+
export const RESIDENT_TOOLS = [
|
|
143
|
+
'fs_read',
|
|
144
|
+
'fs_write',
|
|
145
|
+
'fs_edit',
|
|
146
|
+
'fs_list',
|
|
147
|
+
'fs_search',
|
|
148
|
+
'sysRun',
|
|
149
|
+
'TodoWrite',
|
|
150
|
+
'tool_search'
|
|
151
|
+
];
|
|
152
|
+
|
|
153
|
+
const RESIDENT_TOOL_SET = new Set(RESIDENT_TOOLS);
|
|
154
|
+
|
|
155
|
+
/** True when this core tool ships in every request even without native deferral. */
|
|
156
|
+
export function isResidentTool(toolName) {
|
|
157
|
+
return RESIDENT_TOOL_SET.has(toolName);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// A tool may legitimately belong to more than one pack — check_system_specs is
|
|
161
|
+
// Stage 1 of the game cascade and Stage 2 of the media hierarchy — so
|
|
162
|
+
// membership is a set, not a single value.
|
|
163
|
+
const TOOL_TO_PACKS = (() => {
|
|
164
|
+
const map = new Map();
|
|
165
|
+
for (const packName of PACK_NAMES) {
|
|
166
|
+
for (const toolName of PACKS[packName]) {
|
|
167
|
+
if (!map.has(toolName)) map.set(toolName, new Set());
|
|
168
|
+
map.get(toolName).add(packName);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return map;
|
|
172
|
+
})();
|
|
173
|
+
|
|
174
|
+
const CORE_TOOL_SET = new Set(CORE_TOOLS);
|
|
175
|
+
|
|
176
|
+
/** Every pack a tool belongs to. Empty for core and forged tools. */
|
|
177
|
+
export function packsForTool(toolName) {
|
|
178
|
+
return TOOL_TO_PACKS.get(toolName) || null;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/** Primary pack for a tool, or 'core' if it is always loaded. */
|
|
182
|
+
export function packForTool(toolName) {
|
|
183
|
+
if (CORE_TOOL_SET.has(toolName)) return 'core';
|
|
184
|
+
const packs = TOOL_TO_PACKS.get(toolName);
|
|
185
|
+
return packs ? [...packs][0] : null;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export function isCoreTool(toolName) {
|
|
189
|
+
return CORE_TOOL_SET.has(toolName);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// ---------------------------------------------------------------------------
|
|
193
|
+
// Pack playbooks. These were previously hardcoded into the always-on
|
|
194
|
+
// SYSTEM_PROMPT, costing every task ~2,000 tokens of instructions about game
|
|
195
|
+
// cascades and media hierarchies it would never use. They now travel with their
|
|
196
|
+
// pack, so they arrive exactly when they become relevant.
|
|
197
|
+
// ---------------------------------------------------------------------------
|
|
198
|
+
|
|
199
|
+
export const PACK_PLAYBOOKS = {
|
|
200
|
+
web: `# FRONTEND ENGINEERING MANDATE (CREATIVE DIVERSITY ENGINE)
|
|
201
|
+
When building websites, UIs, dashboards, or web applications, follow this design system hierarchy:
|
|
202
|
+
## Design System Selection
|
|
203
|
+
1. **If the user specifies a design system** (Tailwind, Material-UI, Astryx, etc.) — use it without question.
|
|
204
|
+
2. **If the project already has a design system installed** (detected via package.json) — use the existing one. Never mix systems.
|
|
205
|
+
3. **If building from scratch with no preference stated** — You have CREATIVE FREEDOM. Intelligently choose the approach that best fits the project's personality and user intent:
|
|
206
|
+
- **Astryx (@astryxdesign/core)**: Use the 'astryx_oracle' tool for docs. Best for enterprise dashboards, SaaS products, and design-system-heavy projects. If you choose Astryx, never hallucinate props — always query the oracle first.
|
|
207
|
+
- **Tailwind CSS**: Best for rapid prototyping, marketing sites, and projects needing maximum customization speed.
|
|
208
|
+
- **Vanilla CSS**: Best for artistic, portfolio, and showcase sites where every pixel is intentional.
|
|
209
|
+
- **CSS Modules / Styled Components**: Best for React component libraries and design-token-driven architectures.
|
|
210
|
+
## ANTI-AI-SLOP DIRECTIVE (MANDATORY)
|
|
211
|
+
You MUST produce visually UNIQUE output on every project. Specifically:
|
|
212
|
+
- **BANNED**: Purple-to-blue gradients as the primary color scheme. This is the #1 AI slop signature.
|
|
213
|
+
- **BANNED**: Generic hero sections with centered text + gradient background + "Get Started" button.
|
|
214
|
+
- **REQUIRED**: Before writing any CSS, internally decide on a SPECIFIC design movement to draw from. Examples: Swiss/International Style, Brutalism, Art Deco, Japanese Minimalism, Neomorphism, Glassmorphism, Memphis Design, Bauhaus, Editorial/Magazine, Retro-Futurism, Scandinavian Minimal. Commit to one. Don't blend 5 styles into mush.
|
|
215
|
+
- **REQUIRED**: Choose a curated, harmonious color palette (NOT random defaults). Use HSL for precision. Reference real-world brands known for outstanding design (Stripe's clean whites, Linear's deep darks, Notion's warm neutrals, Vercel's stark monochrome).
|
|
216
|
+
- **REQUIRED**: Use modern web fonts (Inter, Outfit, Space Grotesk, JetBrains Mono, etc.) — NEVER browser defaults.
|
|
217
|
+
- **REQUIRED**: After building, use 'screenshot' or 'browser_act' to VISUALLY VERIFY your work. If it looks like every other AI-generated site, tear it down and rebuild with a different approach.
|
|
218
|
+
- **REQUIRED**: Once the design is finished, call 'memory_write' with the creativePattern argument (project, designApproach, colorPalette, fonts). This is what lets the next project deliberately differ from this one instead of drifting back into the same house style.
|
|
219
|
+
- **ENFORCED, NOT ADVISORY**: every HTML/CSS file you write is read back and scored by an automatic gate before the task can finish (src/slopDetector.js). It looks for the stock gradient hexes, purple-to-blue ramps, placeholder marketing copy, emoji used as icons, default-only typography, the centered-hero/3-cards/"Get Started" skeleton and the stock soft shadow. Score too high and you will be sent back to rebuild with a named design movement. Design it properly the first time; the gate is not fooled by swapping one gradient for another.`,
|
|
220
|
+
|
|
221
|
+
media: `# Media Generation Protocol (Sovereign 5-Stage Hierarchy & Seamless Consent Routing)
|
|
222
|
+
When the user asks you to generate images, audio, music, video, or any creative media, you MUST navigate this exact 5-Stage priority chain:
|
|
223
|
+
|
|
224
|
+
## Stage 1: Specialized Paid APIs (Primary / Auto-Router)
|
|
225
|
+
Always attempt calling \`generate_media_via_api\` FIRST.
|
|
226
|
+
- **Capabilities**: Auto-routes to Gemini Veo 2 / Imagen 3, OpenAI DALL-E 3 / Sora 2 / TTS, or Qwen Wan based on configured keys.
|
|
227
|
+
- **Interactive Pre-Flight Consent**: \`generate_media_via_api\` will automatically show exact Cost Estimation ($) and Token Usage Estimation (~Equivalent MEU Tokens) to the user before spending credits.
|
|
228
|
+
- **Seamless Denial Routing**: If the user denies or rejects the cost modal (\`approved: false\`) OR if no paid API keys exist, do NOT crash or stop. Immediately transition to Stage 2.
|
|
229
|
+
|
|
230
|
+
## Stage 2: Local AI Models / Binaries (Mode B & C — First Fallback)
|
|
231
|
+
When Stage 1 is denied or unconfigured, you MUST evaluate local processing on the user's PC:
|
|
232
|
+
1. **Mandatory Gatekeeper**: Call \`check_system_specs\` FIRST right now to verify hardware.
|
|
233
|
+
2. **Eligibility & Action**: If RAM >= 8GB and Free Disk > 10GB, use \`manage_local_ai_dependencies\` (\`pipInst\` or \`fetchBin\`) + \`sysRun\` to run:
|
|
234
|
+
- **Audio / Voice / Music**: Kokoro TTS, XTTS, MusicGen (\`pipInst\`), or Whisper (\`whisper.cpp\` / \`bark.cpp\`).
|
|
235
|
+
- **Image / Art**: Stable Diffusion via \`diffusers\` or \`stable-diffusion.cpp\`.
|
|
236
|
+
3. **Download Consent**: Present exact model/binary size to the user before downloading multi-GB files.
|
|
237
|
+
4. **Seamless Denial Routing**: If \`check_system_specs\` shows RAM < 8GB OR the user denies multi-GB local downloads, immediately transition to Stage 3.
|
|
238
|
+
|
|
239
|
+
## Stage 3: Free Cloud APIs / Pollinations.ai (Mode D — Second Fallback)
|
|
240
|
+
When Stage 2 is impossible or denied, fall back to free cloud APIs via \`generate_media_via_api\` (\`provider: 'pollinations'\`).
|
|
241
|
+
- **Capabilities**: High-quality images (\`flux\`, \`turbo\`) and audio TTS (\`nova\`, \`alloy\`) at $0 Cost and 0 MB local storage.
|
|
242
|
+
- **Seamless Denial/Failure Routing**: If Pollinations fails (\`HTTP 500\`) OR does not natively support the format (e.g., instrumental music tracks or complex video animations), immediately transition to Stage 4.
|
|
243
|
+
|
|
244
|
+
## Stage 4: Targeted Web Search & Asset Retrieval (Third Fallback)
|
|
245
|
+
When Stage 3 fails or does not support the format:
|
|
246
|
+
- Use \`web_search\` + \`web_fetch\` to search the internet for royalty-free stock videos, public domain images, sound effects, or instrumental background music tracks matching the user's exact intent and prompt. Download and verify the asset locally.
|
|
247
|
+
- **Seamless Failure Routing**: If no satisfactory asset can be retrieved online, immediately transition to Stage 5.
|
|
248
|
+
|
|
249
|
+
## Stage 5: Sandboxed Procedural Code Generation (Mode A — Ultimate Fallback)
|
|
250
|
+
When all previous stages are unavailable or fail, generate the media procedurally from scratch using \`execute_procedural_media\`:
|
|
251
|
+
- **Image / Art**: Write SVG vector graphics or HTML5 Canvas scripts.
|
|
252
|
+
- **Video / Animation**: Write HTML5 Canvas animation scripts that capture frames to video, or Python mathematical video scripts (\`matplotlib.animation\` / \`cv2\`). If frames need encoding and Blender is present, \`blender_act\` -> \`render_animation\` encodes them without any external binary; never conclude from a failed \`which ffmpeg\` that encoding is impossible.
|
|
253
|
+
- **Audio / Music**: Write mathematical Python scripts (\`numpy\` + \`scipy.io.wavfile\` or \`wave\`) generating custom waveforms, chiptune melodies, or sound effects.
|
|
254
|
+
|
|
255
|
+
## CRITICAL MULTIMEDIA MANDATE:
|
|
256
|
+
Never stop or say "I cannot generate video/music" without traversing this entire 5-Stage hierarchy from Stage 1 down to Stage 5! Every stage denial (\`approved: false\`) is a signal to immediately trigger the next stage.
|
|
257
|
+
# BLENDER / 3D MANDATE — READ BEFORE ANY blender_act CALL
|
|
258
|
+
|
|
259
|
+
THE ONE RULE THAT DECIDES WHETHER THE RESULT IS GOOD:
|
|
260
|
+
**Use the smart actions. Do NOT write raw bpy Python for anything they cover.**
|
|
261
|
+
\`smartGeometry\`, \`smartMaterial\`, \`setupStudioLighting\`, \`cinematicAtmosphere\`
|
|
262
|
+
and \`autoFrameCamera\` already carry the craft — bevel widths, subdivision,
|
|
263
|
+
three-point key/fill/rim ratios, volumetric fog, a 65mm lens at a studio angle.
|
|
264
|
+
Hand-written bpy re-derives all of that badly and is why AI 3D looks like AI 3D:
|
|
265
|
+
default grey material, one flat lamp, camera at the origin. \`executePython\` is
|
|
266
|
+
for the gaps between these, never a replacement for them.
|
|
267
|
+
|
|
268
|
+
## Order of operations — do not reorder, do not skip
|
|
269
|
+
|
|
270
|
+
1. Verify the local Blender binary and use \`runHeadless\` for automation.
|
|
271
|
+
2. \`clearScene\`. Blender starts with a cube, a lamp and a camera. Shipping the
|
|
272
|
+
default cube in frame is the single most common failure.
|
|
273
|
+
3. Geometry via \`smartGeometry\`. Build the silhouette first and only then the
|
|
274
|
+
detail; a shape that does not read in a 64px thumbnail will not read at 4K.
|
|
275
|
+
4. \`smartMaterial\` on EVERY visible object. Untouched objects render as default
|
|
276
|
+
grey plastic, and one grey object in an otherwise dressed scene is what makes
|
|
277
|
+
a render read as unfinished.
|
|
278
|
+
5. \`setupStudioLighting\`, then \`cinematicAtmosphere\`. Lighting before atmosphere:
|
|
279
|
+
fog scatters the lights you have, so adding it first means tuning blind.
|
|
280
|
+
6. \`autoFrameCamera\`. Never leave the camera where Blender put it.
|
|
281
|
+
7. LOOK AT IT. Produce a single \`renderFrame\` at low samples, then
|
|
282
|
+
\`view_image\` or \`vision_inspect_ui\`. **A render you
|
|
283
|
+
have not looked at is not a finished render.** If it reads as flat, grey or
|
|
284
|
+
empty, fix it and look again — that loop is the whole difference.
|
|
285
|
+
8. Only now \`renderAnimation\`.
|
|
286
|
+
|
|
287
|
+
## Cinematic defaults that are not negotiable
|
|
288
|
+
|
|
289
|
+
- **Never one light.** \`setupStudioLighting\` gives key/fill/rim; a single lamp is
|
|
290
|
+
the signature of an unfinished scene.
|
|
291
|
+
- **Never the default camera angle.** Slightly above eye line, subject off-centre.
|
|
292
|
+
- **Motion must be motivated.** An 8-second shot is ONE move — a slow orbit, a
|
|
293
|
+
push-in, or a rise. Three moves in eight seconds reads as a screensaver.
|
|
294
|
+
- **Frame rate and length are arithmetic, so state them.** 8s at 24fps is frames
|
|
295
|
+
1-192. Set the range explicitly; do not leave Blender's 250-frame default.
|
|
296
|
+
- **Render settings:** EEVEE for anything under a minute of work — Cycles at
|
|
297
|
+
default samples on a laptop is how a task burns its whole budget on one frame.
|
|
298
|
+
|
|
299
|
+
## Never infer installation from PATH alone
|
|
300
|
+
|
|
301
|
+
Do NOT run \`which blender\`. It fails on macOS for every ordinary .app install
|
|
302
|
+
because nothing is symlinked onto PATH — Blender can be sitting in /Applications
|
|
303
|
+
and \`which\` will still say "command not found". Acting on that has already cost
|
|
304
|
+
a real user a multi-hundred-megabyte re-download of software they already had.
|
|
305
|
+
|
|
306
|
+
**The same trap applies to every other tool, and \`ffmpeg\` is the one you will
|
|
307
|
+
reach for next.** \`which ffmpeg\` failing does NOT mean this machine cannot
|
|
308
|
+
encode video. It usually means the encoder is bundled inside an application
|
|
309
|
+
rather than installed on PATH.
|
|
310
|
+
|
|
311
|
+
## You already have an encoder: Blender is one
|
|
312
|
+
|
|
313
|
+
Blender links FFmpeg internally. If you can render frames, you can encode video
|
|
314
|
+
— with no external binary, no install, and no PATH lookup.
|
|
315
|
+
|
|
316
|
+
Use \`blender_act\` with the \`render_animation\` action and an \`.mp4\` target. It
|
|
317
|
+
sets \`image_settings.file_format = 'FFMPEG'\` with an H.264/MPEG4 container, and
|
|
318
|
+
it ALREADY falls back to a PNG sequence plus a probed external encoder if the
|
|
319
|
+
direct path fails. Hand-writing an encode script and shelling out to \`ffmpeg\`
|
|
320
|
+
re-solves a solved problem and, on a machine without it on PATH, fails where the
|
|
321
|
+
tool would have succeeded.
|
|
322
|
+
|
|
323
|
+
Check the exact API against the running build before writing Python by hand —
|
|
324
|
+
Blender renames render and sequencer attributes between major versions, and a
|
|
325
|
+
script written from memory for an older release will exit non-zero.
|
|
326
|
+
|
|
327
|
+
Only when the Blender tool's local executable check reports no valid binary is
|
|
328
|
+
Blender genuinely missing. Then say so plainly, offer the two options — install it, or produce the shot
|
|
329
|
+
with \`execute_procedural_media\` — and let the user choose. Never start a large
|
|
330
|
+
download on your own initiative.
|
|
331
|
+
`,
|
|
332
|
+
|
|
333
|
+
game: `# Sovereign Game Development Cascade & Enforcement Engine
|
|
334
|
+
When the user asks you to build, create, test, expand, or develop ANY game, you MUST strictly follow this mandatory 7-stage production methodology using specialized game tools. YOU MUST NOT SKIP STAGES.
|
|
335
|
+
**CRITICAL MANDATE**: You are building a **FULL PRODUCTION GAME**. It is completely unacceptable to finish a game in under 50-100 steps. A full game requires multiple levels, complex AI states, numerous sound effects, shaders, and rich tilemaps. You MUST iterate heavily and expand the scope to reach production scale.
|
|
336
|
+
|
|
337
|
+
1. **Stage 1 (Engine Verification)**: Run \`check_system_specs\` (\`engine: 'godot'\`). If valid, use \`godot_act\` for project creation/validation.
|
|
338
|
+
2. **Stage 2 (Narrative & Worldbuilding)**: Use \`game_lore_forge\`, \`game_dialogue_tree_gen\`, and \`game_quest_arc_builder\`. Expand this stage massively.
|
|
339
|
+
3. **Stage 3 (Character Rigging & AI)**: Use \`game_animation_rig\`, \`game_ai_behavior_tree\`, and \`game_cinematic_sequencer\`. Create 5+ enemy types.
|
|
340
|
+
4. **Stage 4 (Harvesting, Audio & VFX)**: Use \`game_asset_harvest\`, \`game_audio_synth\`, and \`game_vfx_emitter_gen\`.
|
|
341
|
+
5. **Stage 5 (Shaders, Scenes & Spawners)**: Use \`game_shader_forge\`, \`game_scene_build\`, and \`game_entity_spawner\`. Design at least 3 sprawling levels.
|
|
342
|
+
6. **Stage 6 (Maps, UI & Economy)**: Use \`game_tilemap_gen\`, \`game_ui_hud_builder\`, and \`game_economy_balancer\`.
|
|
343
|
+
7. **Stage 7 (Assembly & Verification)**: If building a browser/WebGL game, invoke \`game_build_html5\`. **CRITICAL**: You MUST NOT inject 200+ lines of monolithic physics/logic inside \`game_build_html5.customScript\` until you have modularly completed Stages 1-6. After Assembly, you MUST execute \`game_web_runtime_inspector\` and \`game_canvas_audit\` to verify runtime integrity (FPS >= 30, no syntax errors, visual canvas rendering) before declaring Task completed.`
|
|
344
|
+
};
|
|
345
|
+
|
|
346
|
+
// ---------------------------------------------------------------------------
|
|
347
|
+
// Intent routing.
|
|
348
|
+
//
|
|
349
|
+
// The previous implementation used bare substring matching, which produced
|
|
350
|
+
// catastrophic false positives: 'ui' matched "build", "quick" and
|
|
351
|
+
// "requirements"; 'race' matched "trace". Those false positives triggered
|
|
352
|
+
// completion-blocking guards that forced dozens of extra LLM round trips on
|
|
353
|
+
// tasks that had nothing to do with games or web UI.
|
|
354
|
+
//
|
|
355
|
+
// Every matcher below is anchored on word boundaries and tested against the
|
|
356
|
+
// raw prompt only.
|
|
357
|
+
// ---------------------------------------------------------------------------
|
|
358
|
+
|
|
359
|
+
const GAME_INTENT = /\b(game|games|gamedev|permainan|godot|unity|unreal|rpg|platformer|roguelike|arcade|sprite|spritesheet|tilemap|voxel|minecraft|aetheria|voxellia|nes|snes|gameplay|player character|level design|boss fight)\b|\.(tscn|gd)\b/i;
|
|
360
|
+
|
|
361
|
+
const WEB_INTENT = /\b(web|webpage|website|situs|frontend|front-end|landing page|homepage|dashboard|portfolio|html|css|scss|tailwind|bootstrap|react|vue|svelte|angular|next\.?js|nuxt|astro|ui|ux|user interface|web app|webapp|spa|dom|responsive)\b/i;
|
|
362
|
+
|
|
363
|
+
const MEDIA_INTENT = /\b(image|images|picture|photo|gambar|render|3d model|blender|animation|animate|video|movie|film|klip|audio|sound|sfx|music|musik|song|lagu|voice|suara|tts|text.to.speech|narration|podcast|thumbnail|poster|illustration|logo)\b/i;
|
|
364
|
+
|
|
365
|
+
const SYSTEM_INTENT = /\b(process|processes|pid|kill|port|zip|unzip|tar|archive|compress|extract|clipboard|copy to clipboard|print|printer|cetak|open in browser|launch app)\b/i;
|
|
366
|
+
|
|
367
|
+
const ADVANCED_INTENT = /\b(pdf|forge a tool|custom tool|new tool|subagent|sub-agent|parallel agent|swarm|ast|symbols|refactor across)\b/i;
|
|
368
|
+
|
|
369
|
+
const INTENT_MATCHERS = {
|
|
370
|
+
game: GAME_INTENT,
|
|
371
|
+
web: WEB_INTENT,
|
|
372
|
+
media: MEDIA_INTENT,
|
|
373
|
+
system: SYSTEM_INTENT,
|
|
374
|
+
advanced: ADVANCED_INTENT
|
|
375
|
+
};
|
|
376
|
+
|
|
377
|
+
/** True when the prompt genuinely describes game development work. */
|
|
378
|
+
export function isGameIntent(prompt) {
|
|
379
|
+
return GAME_INTENT.test(prompt || '');
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/** True when the prompt genuinely describes web/UI work. */
|
|
383
|
+
export function isWebIntent(prompt) {
|
|
384
|
+
return WEB_INTENT.test(prompt || '');
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* Decide which packs to unlock before the first LLM call, so the common case
|
|
389
|
+
* costs zero discovery round trips.
|
|
390
|
+
*
|
|
391
|
+
* @param {string} prompt The user's task text.
|
|
392
|
+
* @param {object} workspaceContext Optional perception output; its detected
|
|
393
|
+
* frameworks and files are strong signals.
|
|
394
|
+
* @returns {string[]} pack names to unlock
|
|
395
|
+
*/
|
|
396
|
+
export function routePacks(prompt, workspaceContext = null) {
|
|
397
|
+
const unlocked = new Set();
|
|
398
|
+
const text = prompt || '';
|
|
399
|
+
|
|
400
|
+
for (const packName of PACK_NAMES) {
|
|
401
|
+
if (INTENT_MATCHERS[packName].test(text)) {
|
|
402
|
+
unlocked.add(packName);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// Workspace signals. A Godot project on disk is far more reliable evidence of
|
|
407
|
+
// game work than any keyword, and a detected web framework means the agent
|
|
408
|
+
// will eventually need to look at what it built.
|
|
409
|
+
if (workspaceContext) {
|
|
410
|
+
const signals = [
|
|
411
|
+
workspaceContext.framework,
|
|
412
|
+
workspaceContext.projectType,
|
|
413
|
+
workspaceContext.designSystem,
|
|
414
|
+
Array.isArray(workspaceContext.keyFiles) ? workspaceContext.keyFiles.join(' ') : ''
|
|
415
|
+
]
|
|
416
|
+
.filter(Boolean)
|
|
417
|
+
.join(' ')
|
|
418
|
+
.toLowerCase();
|
|
419
|
+
|
|
420
|
+
if (/godot|project\.godot|unity|\.tscn/.test(signals)) unlocked.add('game');
|
|
421
|
+
if (/react|vue|svelte|next|nuxt|astro|angular|tailwind|vite|html/.test(signals)) unlocked.add('web');
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
return [...unlocked];
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Resolve the tool schemas that should enter the context window.
|
|
429
|
+
* Core tools always load; pack tools load only once their pack is unlocked.
|
|
430
|
+
*
|
|
431
|
+
* Ordering is APPEND-ONLY and this matters a great deal for cost. Every
|
|
432
|
+
* provider's prompt cache binds on an identical prefix, and tool definitions
|
|
433
|
+
* sit at the very front of that prefix — so if unlocking a pack mid-task
|
|
434
|
+
* reshuffles the array, the cache is invalidated from the first changed byte
|
|
435
|
+
* onward, taking the system prompt and the whole message history with it.
|
|
436
|
+
* Sorting pack tools alphabetically did exactly that: unlocking `system`
|
|
437
|
+
* inserted `archive` ahead of `astryx_oracle` and truncated the stable prefix
|
|
438
|
+
* to 82%. Ordering by unlock sequence instead keeps 100% of the previously
|
|
439
|
+
* cached prefix intact and appends only the new tail.
|
|
440
|
+
*
|
|
441
|
+
* @param {Array} allDefinitions Full TOOL_DEFINITIONS list.
|
|
442
|
+
* @param {Set} unlockedPacks Pack names unlocked for this task.
|
|
443
|
+
* @param {Set} unlockedTools Individually unlocked tool names.
|
|
444
|
+
* @param {Array} unlockOrder Pack names in the order they were unlocked.
|
|
445
|
+
* @returns {Array} filtered definitions, deterministically ordered
|
|
446
|
+
*/
|
|
447
|
+
export function resolveActiveTools(allDefinitions, unlockedPacks, unlockedTools, unlockOrder = null, options = {}) {
|
|
448
|
+
const packs = unlockedPacks || new Set();
|
|
449
|
+
const tools = unlockedTools || new Set();
|
|
450
|
+
// Providers with native schema deferral (Anthropic) leave this off — server
|
|
451
|
+
// side deferral is strictly better, since it costs no discovery round trip.
|
|
452
|
+
const residentOnly = options.residentOnly === true;
|
|
453
|
+
|
|
454
|
+
const active = allDefinitions.filter(def => {
|
|
455
|
+
if (isCoreTool(def.name)) {
|
|
456
|
+
if (!residentOnly) return true;
|
|
457
|
+
return isResidentTool(def.name) || tools.has(def.name);
|
|
458
|
+
}
|
|
459
|
+
if (tools.has(def.name)) return true;
|
|
460
|
+
const memberOf = packsForTool(def.name);
|
|
461
|
+
// A tool with no declared pack is a forged/custom tool: always available,
|
|
462
|
+
// because the user explicitly created it for this machine.
|
|
463
|
+
if (!memberOf) return true;
|
|
464
|
+
for (const pack of memberOf) {
|
|
465
|
+
if (packs.has(pack)) return true;
|
|
466
|
+
}
|
|
467
|
+
return false;
|
|
468
|
+
});
|
|
469
|
+
|
|
470
|
+
// The stable head of the array. Without residentOnly that is the whole core;
|
|
471
|
+
// with it, only the resident subset — and that distinction matters for the
|
|
472
|
+
// prompt cache, not just for token count.
|
|
473
|
+
//
|
|
474
|
+
// A core tool unlocked mid-task must NOT be slotted back into its CORE_TOOLS
|
|
475
|
+
// position: that inserts into the middle of the array and invalidates the
|
|
476
|
+
// cached prefix from that point on, every time. It is appended to the tail
|
|
477
|
+
// below instead, so the head stays byte-identical for the whole task.
|
|
478
|
+
const isHead = (name) => !residentOnly || isResidentTool(name);
|
|
479
|
+
const coreFirst = active.filter(d => isCoreTool(d.name) && isHead(d.name));
|
|
480
|
+
coreFirst.sort((a, b) => CORE_TOOLS.indexOf(a.name) - CORE_TOOLS.indexOf(b.name));
|
|
481
|
+
|
|
482
|
+
// Pack tools grouped by unlock sequence, alphabetical only within a group so
|
|
483
|
+
// the tail added by any single unlock is itself deterministic.
|
|
484
|
+
const sequence = Array.isArray(unlockOrder) && unlockOrder.length > 0
|
|
485
|
+
? unlockOrder
|
|
486
|
+
: [...packs];
|
|
487
|
+
const rankOfPack = new Map(sequence.map((name, index) => [name, index]));
|
|
488
|
+
|
|
489
|
+
const rankOf = (def) => {
|
|
490
|
+
// A non-resident core tool the model discovered via tool_search. Ranked
|
|
491
|
+
// ahead of every pack so the tail stays grouped, but behind the fixed head.
|
|
492
|
+
if (isCoreTool(def.name)) return -1;
|
|
493
|
+
const memberOf = packsForTool(def.name);
|
|
494
|
+
if (!memberOf) return Number.MAX_SAFE_INTEGER; // forged tools last
|
|
495
|
+
let best = Number.MAX_SAFE_INTEGER;
|
|
496
|
+
for (const pack of memberOf) {
|
|
497
|
+
const rank = rankOfPack.get(pack);
|
|
498
|
+
if (rank !== undefined && rank < best) best = rank;
|
|
499
|
+
}
|
|
500
|
+
return best;
|
|
501
|
+
};
|
|
502
|
+
|
|
503
|
+
const rest = active.filter(d => !isCoreTool(d.name) || !isHead(d.name));
|
|
504
|
+
rest.sort((a, b) => {
|
|
505
|
+
const diff = rankOf(a) - rankOf(b);
|
|
506
|
+
return diff !== 0 ? diff : a.name.localeCompare(b.name);
|
|
507
|
+
});
|
|
508
|
+
|
|
509
|
+
return [...coreFirst, ...rest];
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
/** Human-readable catalogue injected into the system prompt so the model knows what it can unlock. */
|
|
513
|
+
export function getPackCatalogue(unlockedPacks) {
|
|
514
|
+
const packs = unlockedPacks || new Set();
|
|
515
|
+
const lines = PACK_NAMES.map(name => {
|
|
516
|
+
const state = packs.has(name) ? 'LOADED' : 'available';
|
|
517
|
+
return `- ${name} (${PACKS[name].length} tools, ${state})`;
|
|
518
|
+
});
|
|
519
|
+
|
|
520
|
+
return `# EXTENDED CAPABILITY PACKS
|
|
521
|
+
Beyond the tools currently in your context you have access to specialised capability packs. Nothing is disabled — packs load on demand to keep your context focused.
|
|
522
|
+
${lines.join('\n')}
|
|
523
|
+
To load a pack, call \`tool_search\` with a query describing what you need (for example "godot scene", "generate music", "kill process on port"). The matching tool schemas become available immediately on your next turn. Never claim a capability is missing without searching first.`;
|
|
524
|
+
}
|