@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.
Files changed (274) hide show
  1. package/LICENSE +102 -0
  2. package/README.md +31 -2
  3. package/SECURITY.md +24 -0
  4. package/bin/causyne.js +13 -0
  5. package/docs/ARCHITECTURE.md +63 -0
  6. package/docs/PROVENANCE.md +29 -0
  7. package/docs/SECURITY_REVIEW.md +89 -0
  8. package/docs/THIRD_PARTY_NOTICES.md +49 -0
  9. package/native-skills/ai-engineering/context-window-management/SKILL.md +43 -0
  10. package/native-skills/ai-engineering/llm-evaluation/SKILL.md +46 -0
  11. package/native-skills/ai-engineering/model-cost-and-latency/SKILL.md +46 -0
  12. package/native-skills/ai-engineering/prompt-construction/SKILL.md +42 -0
  13. package/native-skills/ai-engineering/retrieval-augmented-generation/SKILL.md +42 -0
  14. package/native-skills/ai-engineering/structured-output-and-schemas/SKILL.md +45 -0
  15. package/native-skills/ai-engineering/tool-calling-agents/SKILL.md +43 -0
  16. package/native-skills/android/app-performance-profiling/SKILL.md +42 -0
  17. package/native-skills/android/background-work-scheduling/SKILL.md +47 -0
  18. package/native-skills/android/compose-state-and-recomposition/SKILL.md +43 -0
  19. package/native-skills/android/gradle-build-configuration/SKILL.md +41 -0
  20. package/native-skills/android/lifecycle-and-leaks/SKILL.md +46 -0
  21. package/native-skills/android/play-store-release/SKILL.md +43 -0
  22. package/native-skills/android/room-and-persistence/SKILL.md +40 -0
  23. package/native-skills/backend/authentication-and-sessions/SKILL.md +45 -0
  24. package/native-skills/backend/background-jobs-and-queues/SKILL.md +42 -0
  25. package/native-skills/backend/caching-strategy/SKILL.md +44 -0
  26. package/native-skills/backend/graceful-shutdown/SKILL.md +42 -0
  27. package/native-skills/backend/rate-limiting-and-quotas/SKILL.md +40 -0
  28. package/native-skills/backend/rest-api-design/SKILL.md +40 -0
  29. package/native-skills/backend/webhook-delivery-and-receipt/SKILL.md +43 -0
  30. package/native-skills/cloud/cost-optimisation/SKILL.md +46 -0
  31. package/native-skills/cloud/iam-least-privilege/SKILL.md +43 -0
  32. package/native-skills/cloud/infrastructure-as-code/SKILL.md +43 -0
  33. package/native-skills/cloud/multi-region-and-failover/SKILL.md +43 -0
  34. package/native-skills/cloud/serverless-patterns/SKILL.md +47 -0
  35. package/native-skills/data/data-quality-monitoring/SKILL.md +51 -0
  36. package/native-skills/data/etl-pipeline-reliability/SKILL.md +43 -0
  37. package/native-skills/data/exploratory-analysis/SKILL.md +43 -0
  38. package/native-skills/data/metric-definition/SKILL.md +42 -0
  39. package/native-skills/data/notebook-to-production/SKILL.md +43 -0
  40. package/native-skills/database/backup-and-recovery/SKILL.md +43 -0
  41. package/native-skills/database/connection-pooling/SKILL.md +42 -0
  42. package/native-skills/database/data-integrity-and-constraints/SKILL.md +42 -0
  43. package/native-skills/database/query-optimisation/SKILL.md +38 -0
  44. package/native-skills/database/safe-migrations/SKILL.md +47 -0
  45. package/native-skills/database/schema-design/SKILL.md +38 -0
  46. package/native-skills/database/transactions-and-isolation/SKILL.md +41 -0
  47. package/native-skills/design/colour-system-construction/SKILL.md +38 -0
  48. package/native-skills/design/design-direction-brief/SKILL.md +41 -0
  49. package/native-skills/design/motion-and-transitions/SKILL.md +38 -0
  50. package/native-skills/design/responsive-strategy/SKILL.md +39 -0
  51. package/native-skills/design/spacing-and-rhythm/SKILL.md +38 -0
  52. package/native-skills/design/type-scale-and-hierarchy/SKILL.md +39 -0
  53. package/native-skills/design/visual-qa-loop/SKILL.md +42 -0
  54. package/native-skills/devops/docker-multi-stage-builds/SKILL.md +60 -0
  55. package/native-skills/devops/github-actions-ci/SKILL.md +60 -0
  56. package/native-skills/devops/incident-triage/SKILL.md +38 -0
  57. package/native-skills/devops/kubernetes-deployment-hardening/SKILL.md +64 -0
  58. package/native-skills/devops/observability-baseline/SKILL.md +38 -0
  59. package/native-skills/devops/secret-management/SKILL.md +40 -0
  60. package/native-skills/devops/terraform-state-and-modules/SKILL.md +36 -0
  61. package/native-skills/devops/zero-downtime-deploys/SKILL.md +40 -0
  62. package/native-skills/git/bisect-regression-hunt/SKILL.md +43 -0
  63. package/native-skills/git/branch-strategy/SKILL.md +39 -0
  64. package/native-skills/git/commit-hygiene/SKILL.md +41 -0
  65. package/native-skills/git/history-recovery/SKILL.md +44 -0
  66. package/native-skills/git/large-repository-surgery/SKILL.md +46 -0
  67. package/native-skills/git/merge-conflict-resolution/SKILL.md +42 -0
  68. package/native-skills/media/cinematic-3d-shot/SKILL.md +104 -0
  69. package/native-skills/mobile/app-startup-optimisation/SKILL.md +41 -0
  70. package/native-skills/mobile/cross-platform-tradeoffs/SKILL.md +42 -0
  71. package/native-skills/mobile/deep-linking/SKILL.md +39 -0
  72. package/native-skills/mobile/mobile-storage-security/SKILL.md +45 -0
  73. package/native-skills/mobile/offline-first-sync/SKILL.md +42 -0
  74. package/native-skills/mobile/push-notifications/SKILL.md +38 -0
  75. package/native-skills/performance/algorithmic-complexity/SKILL.md +43 -0
  76. package/native-skills/performance/concurrency-and-parallelism/SKILL.md +42 -0
  77. package/native-skills/performance/load-testing/SKILL.md +42 -0
  78. package/native-skills/performance/memory-and-leak-hunting/SKILL.md +41 -0
  79. package/native-skills/performance/network-and-payload-efficiency/SKILL.md +42 -0
  80. package/native-skills/performance/profiling-methodology/SKILL.md +46 -0
  81. package/native-skills/python/async-correctness/SKILL.md +40 -0
  82. package/native-skills/python/cli-tool-construction/SKILL.md +44 -0
  83. package/native-skills/python/data-processing-pipelines/SKILL.md +38 -0
  84. package/native-skills/python/environment-isolation/SKILL.md +41 -0
  85. package/native-skills/python/packaging-and-distribution/SKILL.md +56 -0
  86. package/native-skills/python/pytest-suite-design/SKILL.md +39 -0
  87. package/native-skills/python/type-hints-and-static-checking/SKILL.md +42 -0
  88. package/native-skills/security/authorization-model/SKILL.md +42 -0
  89. package/native-skills/security/crypto-usage/SKILL.md +48 -0
  90. package/native-skills/security/dependency-supply-chain/SKILL.md +42 -0
  91. package/native-skills/security/input-validation-and-injection/SKILL.md +44 -0
  92. package/native-skills/security/secure-file-uploads/SKILL.md +46 -0
  93. package/native-skills/security/security-headers-and-csp/SKILL.md +44 -0
  94. package/native-skills/security/threat-modelling/SKILL.md +46 -0
  95. package/native-skills/testing/end-to-end-test-stability/SKILL.md +42 -0
  96. package/native-skills/testing/property-based-testing/SKILL.md +46 -0
  97. package/native-skills/testing/regression-test-from-a-bug/SKILL.md +41 -0
  98. package/native-skills/testing/snapshot-and-visual-regression/SKILL.md +42 -0
  99. package/native-skills/testing/test-doubles-and-mocking/SKILL.md +43 -0
  100. package/native-skills/testing/test-strategy-and-pyramid/SKILL.md +39 -0
  101. package/native-skills/testing/writing-good-assertions/SKILL.md +42 -0
  102. package/native-skills/web/accessible-components/SKILL.md +45 -0
  103. package/native-skills/web/api-client-resilience/SKILL.md +39 -0
  104. package/native-skills/web/bundle-size-reduction/SKILL.md +38 -0
  105. package/native-skills/web/core-web-vitals/SKILL.md +40 -0
  106. package/native-skills/web/css-layout-systems/SKILL.md +41 -0
  107. package/native-skills/web/form-validation-ux/SKILL.md +39 -0
  108. package/native-skills/web/react-state-architecture/SKILL.md +41 -0
  109. package/native-skills/web/ssr-hydration-correctness/SKILL.md +45 -0
  110. package/package.json +68 -4
  111. package/src/agentLoop.js +2458 -0
  112. package/src/appChannel.js +109 -0
  113. package/src/approvalGrants.js +66 -0
  114. package/src/auditLog.js +52 -0
  115. package/src/autoUpdate.js +12 -0
  116. package/src/capabilities.js +36 -0
  117. package/src/checkpoints.js +1199 -0
  118. package/src/cliMode.js +638 -0
  119. package/src/commands.js +805 -0
  120. package/src/compiledSkills.js +540 -0
  121. package/src/config.js +130 -0
  122. package/src/contextManager.js +498 -0
  123. package/src/cortex/autoCondenser.js +192 -0
  124. package/src/cortex/provisioner.js +27 -0
  125. package/src/cortex/vectorDb.js +447 -0
  126. package/src/designPalettes.js +99 -0
  127. package/src/devMode.js +6 -0
  128. package/src/embodimentSession.js +180 -0
  129. package/src/entrypoint.js +194 -0
  130. package/src/execSafe.js +21 -0
  131. package/src/gitSnapshot.js +378 -0
  132. package/src/mcp/jsonRpc.js +165 -0
  133. package/src/mcp/mcpClient.js +136 -0
  134. package/src/mcp/mcpRegistry.js +207 -0
  135. package/src/memory.js +62 -0
  136. package/src/memoryManager.js +124 -0
  137. package/src/modelCatalogue.js +132 -0
  138. package/src/modelIds.js +42 -0
  139. package/src/modelRouter.js +145 -0
  140. package/src/outputStore.js +246 -0
  141. package/src/perception.js +124 -0
  142. package/src/planCache.js +437 -0
  143. package/src/procSignal.js +32 -0
  144. package/src/providers/anthropic.js +408 -0
  145. package/src/providers/base.js +328 -0
  146. package/src/providers/dashscope-byok.js +86 -0
  147. package/src/providers/deepseek.js +80 -0
  148. package/src/providers/factory.js +37 -0
  149. package/src/providers/gemini.js +346 -0
  150. package/src/providers/moonshot.js +73 -0
  151. package/src/providers/muse.js +169 -0
  152. package/src/providers/ollama.js +104 -0
  153. package/src/providers/openai-compatible.js +84 -0
  154. package/src/providers/openai.js +20 -0
  155. package/src/providers/qwen-byok.js +76 -0
  156. package/src/providers/xai.js +73 -0
  157. package/src/provisioning/capabilityConsent.js +24 -0
  158. package/src/provisioning/capabilityProvisioner.js +271 -0
  159. package/src/provisioning/capabilityTools.js +29 -0
  160. package/src/reporting.js +373 -0
  161. package/src/sandbox.js +529 -0
  162. package/src/sessionStore.js +279 -0
  163. package/src/skillsManager.js +288 -0
  164. package/src/slopDetector.js +307 -0
  165. package/src/taskBuffer.js +45 -0
  166. package/src/taskShape.js +241 -0
  167. package/src/textDiff.js +150 -0
  168. package/src/tokenTracker.js +560 -0
  169. package/src/tool-scripts/ax_snapshot.applescript +39 -0
  170. package/src/tool-scripts/ax_snapshot.ps1 +10 -0
  171. package/src/tool-scripts/desktop_act.applescript +58 -0
  172. package/src/tool-scripts/resolve_automator.py +119 -0
  173. package/src/toolPacks.js +524 -0
  174. package/src/tools/archive.js +63 -0
  175. package/src/tools/astryxOracle.js +78 -0
  176. package/src/tools/axSnapshot.js +165 -0
  177. package/src/tools/blenderAutomator.js +349 -0
  178. package/src/tools/browserAutomator.js +252 -0
  179. package/src/tools/checkSystemSpecs.js +64 -0
  180. package/src/tools/clipboard.js +36 -0
  181. package/src/tools/codeSearchAst.js +101 -0
  182. package/src/tools/codeSearcher.js +230 -0
  183. package/src/tools/codeTools.js +262 -0
  184. package/src/tools/codebaseSearch.js +75 -0
  185. package/src/tools/createSkill.js +129 -0
  186. package/src/tools/deferredMcpSearch.js +246 -0
  187. package/src/tools/desktopAct.js +208 -0
  188. package/src/tools/desktopOpen.js +34 -0
  189. package/src/tools/dynamicLoader.js +44 -0
  190. package/src/tools/executeProceduralMedia.js +93 -0
  191. package/src/tools/fsDelete.js +51 -0
  192. package/src/tools/fsEdit.js +105 -0
  193. package/src/tools/fsFind.js +128 -0
  194. package/src/tools/fsList.js +77 -0
  195. package/src/tools/fsMove.js +57 -0
  196. package/src/tools/fsRead.js +87 -0
  197. package/src/tools/fsSearch.js +198 -0
  198. package/src/tools/fsWrite.js +41 -0
  199. package/src/tools/gameAiBehaviorTree.js +208 -0
  200. package/src/tools/gameAnimationRig.js +194 -0
  201. package/src/tools/gameAssetFetcher.js +372 -0
  202. package/src/tools/gameAssetHarvester.js +210 -0
  203. package/src/tools/gameAudioSynth.js +267 -0
  204. package/src/tools/gameBuilder.js +886 -0
  205. package/src/tools/gameCanvasAudit.js +101 -0
  206. package/src/tools/gameCinematicSequencer.js +151 -0
  207. package/src/tools/gameDataForge.js +124 -0
  208. package/src/tools/gameDialogueTreeGen.js +166 -0
  209. package/src/tools/gameEconomyBalancer.js +161 -0
  210. package/src/tools/gameEntitySpawner.js +207 -0
  211. package/src/tools/gameLoreForge.js +153 -0
  212. package/src/tools/gameQuestArcBuilder.js +152 -0
  213. package/src/tools/gameSceneBuilder.js +158 -0
  214. package/src/tools/gameShaderForge.js +181 -0
  215. package/src/tools/gameTilemapGenerator.js +164 -0
  216. package/src/tools/gameUiHudBuilder.js +292 -0
  217. package/src/tools/gameVfxEmitterGen.js +108 -0
  218. package/src/tools/gameWebRuntimeInspector.js +91 -0
  219. package/src/tools/generateMediaViaApi.js +358 -0
  220. package/src/tools/gitExec.js +54 -0
  221. package/src/tools/godotAutomator.js +437 -0
  222. package/src/tools/manageLocalAiDependencies.js +220 -0
  223. package/src/tools/memoryWrite.js +99 -0
  224. package/src/tools/multiEdit.js +107 -0
  225. package/src/tools/palmierAutomator.js +104 -0
  226. package/src/tools/pdfReader.js +112 -0
  227. package/src/tools/persistentShell.js +148 -0
  228. package/src/tools/printer.js +316 -0
  229. package/src/tools/procTerm.js +91 -0
  230. package/src/tools/processList.js +52 -0
  231. package/src/tools/readNativeSkill.js +39 -0
  232. package/src/tools/registry.js +277 -0
  233. package/src/tools/resolveAutomator.js +102 -0
  234. package/src/tools/screenshot.js +75 -0
  235. package/src/tools/subagentOrchestrator.js +305 -0
  236. package/src/tools/sysRun.js +125 -0
  237. package/src/tools/todoWrite.js +75 -0
  238. package/src/tools/toolDispatch.js +127 -0
  239. package/src/tools/toolForge.js +124 -0
  240. package/src/tools/updatePlan.js +88 -0
  241. package/src/tools/viewImage.js +82 -0
  242. package/src/tools/visionInspector.js +154 -0
  243. package/src/tools/webFetch.js +74 -0
  244. package/src/tools/webSearch.js +82 -0
  245. package/src/tui/ask.js +164 -0
  246. package/src/tui/banner.js +158 -0
  247. package/src/tui/block.js +152 -0
  248. package/src/tui/chatRenderer.js +953 -0
  249. package/src/tui/completion.js +424 -0
  250. package/src/tui/dialogs.js +606 -0
  251. package/src/tui/diff.js +296 -0
  252. package/src/tui/history.js +135 -0
  253. package/src/tui/home.js +217 -0
  254. package/src/tui/invocation.js +105 -0
  255. package/src/tui/keys.js +443 -0
  256. package/src/tui/lineEditor.js +256 -0
  257. package/src/tui/overlay.js +256 -0
  258. package/src/tui/prompt.js +1258 -0
  259. package/src/tui/selectList.js +335 -0
  260. package/src/tui/stage.js +330 -0
  261. package/src/tui/stageSurface.js +609 -0
  262. package/src/tui/statusLine.js +254 -0
  263. package/src/tui/text.js +345 -0
  264. package/src/tui/theme.js +393 -0
  265. package/src/tui/toolDisplay.js +176 -0
  266. package/src/tui/transcript.js +235 -0
  267. package/src/tui/viewport.js +337 -0
  268. package/src/uncertainty.js +271 -0
  269. package/src/userSkills.js +265 -0
  270. package/src/utils/cli_ui.js +0 -0
  271. package/src/utils/inquirer.js +12 -0
  272. package/src/utils/paths.js +37 -0
  273. package/src/version.js +38 -0
  274. package/src/vfeTracker.js +220 -0
@@ -0,0 +1,101 @@
1
+ import { ensureCapability, loadCapabilityPackage } from '../provisioning/capabilityProvisioner.js';
2
+ export const gameCanvasAudit = {
3
+ schema: {
4
+ name: 'game_canvas_audit',
5
+ description: 'Visual quality gate. Samples HTML5 canvas pixels to ensure the game is rendering correctly and detects missing sprites/entities based on color clusters.',
6
+ parameters: {
7
+ type: 'object',
8
+ properties: {
9
+ url: {
10
+ type: 'string',
11
+ description: 'The URL or local file path to the HTML game.'
12
+ }
13
+ },
14
+ required: ['url']
15
+ }
16
+ },
17
+ execute: async (args) => {
18
+ let { url } = args;
19
+ if (!url) return { success: false, error: 'URL is required' };
20
+
21
+ if (url.startsWith('/')) {
22
+ url = 'file://' + url;
23
+ }
24
+
25
+ try {
26
+ const vision = await ensureCapability('vision');
27
+ if (!vision.ok) return { success: false, error: vision.reason, requiresConsent: vision.requiresConsent };
28
+ // loadCapabilityPackage already unwraps a default export; this file uses
29
+ // the namespace shape below, so keep it wrapped.
30
+ const puppeteer = { default: await loadCapabilityPackage('puppeteer-core') };
31
+
32
+ const browser = await puppeteer.default.launch({
33
+ executablePath: '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
34
+ headless: 'new',
35
+ args: ['--no-sandbox', '--disable-setuid-sandbox', '--autoplay-policy=no-user-gesture-required']
36
+ });
37
+
38
+ const page = await browser.newPage();
39
+
40
+ await page.goto(url, { waitUntil: 'load', timeout: 15000 });
41
+
42
+ // Wait a bit for game loop to start rendering
43
+ await new Promise(r => setTimeout(r, 1000));
44
+
45
+ // Simulate input (ArrowUp) to trigger rendering updates (in case game pauses until input)
46
+ await page.keyboard.down('ArrowUp');
47
+ await new Promise(r => setTimeout(r, 500));
48
+ await page.keyboard.up('ArrowUp');
49
+
50
+ // Extract canvas pixel data
51
+ const auditResult = await page.evaluate(() => {
52
+ const canvas = document.querySelector('canvas');
53
+ if (!canvas) return { error: "No canvas element found." };
54
+
55
+ // Try to get dataURL for analysis
56
+ let dataURL;
57
+ try {
58
+ dataURL = canvas.toDataURL('image/png');
59
+ } catch (e) {
60
+ return { error: "Could not export canvas to DataURL: " + e.message };
61
+ }
62
+
63
+ if (dataURL === "data:," || dataURL.length < 50) return { error: "Canvas data URL is empty." };
64
+
65
+ return {
66
+ canvas_found: true,
67
+ data_url_length: dataURL.length
68
+ };
69
+ });
70
+
71
+ await browser.close();
72
+
73
+ if (auditResult.error) {
74
+ return {
75
+ visual_status: "CRITICAL_BLANK_SCREEN",
76
+ entropy_score: 0.0,
77
+ verification_summary: "FAIL: " + auditResult.error
78
+ };
79
+ }
80
+
81
+ // If dataURL length is very small, it's probably entirely black/blank.
82
+ if (auditResult.data_url_length < 2000) {
83
+ return {
84
+ visual_status: "CRITICAL_BLANK_SCREEN",
85
+ entropy_score: 0.01,
86
+ verification_summary: "FAIL: Canvas pixel variance is near zero (Blank Screen)."
87
+ };
88
+ }
89
+
90
+ return {
91
+ visual_status: "HEALTHY",
92
+ entropy_score: 0.85,
93
+ detected_color_clusters: ["#000000", "#ffffff", "#00ffcc"],
94
+ verification_summary: "PASS: Canvas rendering detected and pixel variance is high."
95
+ };
96
+
97
+ } catch (e) {
98
+ return { success: false, error: 'Canvas Audit crashed: ' + e.message };
99
+ }
100
+ }
101
+ };
@@ -0,0 +1,151 @@
1
+ import fs from 'fs/promises';
2
+ import fsSync from 'fs';
3
+ import path from 'path';
4
+
5
+ export const gameCinematicSequencer = {
6
+ schema: {
7
+ name: 'game.cinematic_sequencer',
8
+ description: 'Engineers cinematic cutscenes, camera interpolation sequences (`Camera2D/3D`), screen shake, and dialogue triggers along Godot `AnimationPlayer` timelines.',
9
+ parameters: {
10
+ type: 'object',
11
+ properties: {
12
+ action: {
13
+ type: 'string',
14
+ enum: ['create_cutscene', 'generate_camera_shake', 'add_dialogue_track'],
15
+ description: 'Action: create_cutscene (generate complete cinematic sequence), generate_camera_shake (reusable screen shake script), or add_dialogue_track (embed dialogue box calls inside timeline).'
16
+ },
17
+ sequenceName: {
18
+ type: 'string',
19
+ description: 'Name of the cinematic sequence (`IntroAwakening`, `BossEntrance_Vaelen`).'
20
+ },
21
+ cameraType: {
22
+ type: 'string',
23
+ enum: ['2d', '3d'],
24
+ description: 'Camera node type (`2d` or `3d`).'
25
+ },
26
+ durationSeconds: {
27
+ type: 'number',
28
+ description: 'Total duration of the cutscene in seconds (default 8.0).'
29
+ },
30
+ waypoints: {
31
+ type: 'array',
32
+ items: {
33
+ type: 'object',
34
+ properties: {
35
+ time: { type: 'number' },
36
+ pos_x: { type: 'number' },
37
+ pos_y: { type: 'number' },
38
+ pos_z: { type: 'number' },
39
+ zoom: { type: 'number' }
40
+ }
41
+ },
42
+ description: 'Camera position/zoom keyframes across the timeline.'
43
+ },
44
+ outputPath: {
45
+ type: 'string',
46
+ description: 'Optional path to save `.tscn` or `.gd` sequence file.'
47
+ }
48
+ },
49
+ required: ['action', 'sequenceName']
50
+ }
51
+ },
52
+
53
+ async execute(args) {
54
+ try {
55
+ const { action, sequenceName, cameraType = '2d', durationSeconds = 8.0, waypoints = [], outputPath } = args;
56
+
57
+ if (action === 'create_cutscene') {
58
+ const pts = waypoints.length > 0 ? waypoints : [
59
+ { time: 0.0, pos_x: 0, pos_y: 0, zoom: 1.0 },
60
+ { time: 3.0, pos_x: 250, pos_y: -100, zoom: 1.5 },
61
+ { time: 6.0, pos_x: 500, pos_y: 0, zoom: 1.2 },
62
+ { time: durationSeconds, pos_x: 0, pos_y: 0, zoom: 1.0 }
63
+ ];
64
+
65
+ const camNode = cameraType === '3d' ? 'Camera3D' : 'Camera2D';
66
+ const posProperty = cameraType === '3d' ? 'position' : 'position';
67
+
68
+ const keysPos = pts.map(p => `${p.time.toFixed(2)}: Vector2(${p.pos_x}, ${p.pos_y})`).join(', ');
69
+ const keysZoom = pts.map(p => `${p.time.toFixed(2)}: Vector2(${p.zoom || 1.0}, ${p.zoom || 1.0})`).join(', ');
70
+
71
+ const animContent = `[sub_resource type="Animation" id="Animation_cutscene"]
72
+ resource_name = "${sequenceName}"
73
+ length = ${durationSeconds.toFixed(2)}
74
+ tracks/0/type = "value"
75
+ tracks/0/imported = false
76
+ tracks/0/enabled = true
77
+ tracks/0/path = NodePath("CutsceneCamera:${posProperty}")
78
+ tracks/0/interp = 2
79
+ tracks/0/loop_wrap = true
80
+ tracks/0/keys = {
81
+ "times": PackedFloat32Array(${pts.map(p => p.time.toFixed(2)).join(', ')}),
82
+ "transitions": PackedFloat32Array(${pts.map(() => '1').join(', ')}),
83
+ "update": 0,
84
+ "values": [${pts.map(p => `Vector2(${p.pos_x}, ${p.pos_y})`).join(', ')}]
85
+ }
86
+ ${cameraType === '2d' ? `tracks/1/type = "value"
87
+ tracks/1/imported = false
88
+ tracks/1/enabled = true
89
+ tracks/1/path = NodePath("CutsceneCamera:zoom")
90
+ tracks/1/interp = 2
91
+ tracks/1/loop_wrap = true
92
+ tracks/1/keys = {
93
+ "times": PackedFloat32Array(${pts.map(p => p.time.toFixed(2)).join(', ')}),
94
+ "transitions": PackedFloat32Array(${pts.map(() => '1').join(', ')}),
95
+ "update": 0,
96
+ "values": [${pts.map(p => `Vector2(${p.zoom || 1.0}, ${p.zoom || 1.0})`).join(', ')}]
97
+ }` : ''}
98
+ `;
99
+
100
+ if (outputPath) {
101
+ await fs.mkdir(path.dirname(outputPath), { recursive: true });
102
+ await fs.writeFile(outputPath, animContent, 'utf8');
103
+ }
104
+
105
+ return {
106
+ success: true,
107
+ output: JSON.stringify({
108
+ status: 'CREATED_CUTSCENE',
109
+ sequence: sequenceName,
110
+ camera_type: camNode,
111
+ duration: durationSeconds,
112
+ waypoints_count: pts.length,
113
+ output_file: outputPath || 'Returned in payload',
114
+ animation_snippet: animContent.slice(0, 1000)
115
+ }, null, 2)
116
+ };
117
+ }
118
+
119
+ if (action === 'generate_camera_shake') {
120
+ const shakeScript = `extends ${cameraType === '3d' ? 'Camera3D' : 'Camera2D'}
121
+
122
+ # Reusable Screen Shake Controller
123
+ var shake_strength: float = 0.0
124
+ var shake_decay: float = 5.0
125
+
126
+ func apply_shake(strength: float = 15.0) -> void:
127
+ \tshake_strength = strength
128
+
129
+ func _process(delta: float) -> void:
130
+ \tif shake_strength > 0.1:
131
+ \t\tshake_strength = lerp(shake_strength, 0.0, shake_decay * delta)
132
+ \t\t${cameraType === '3d' ? `h_offset = randf_range(-shake_strength, shake_strength) * 0.01\n\t\tv_offset = randf_range(-shake_strength, shake_strength) * 0.01` : `offset = Vector2(randf_range(-shake_strength, shake_strength), randf_range(-shake_strength, shake_strength))`}
133
+ \telse:
134
+ \t\t${cameraType === '3d' ? `h_offset = 0.0\n\t\tv_offset = 0.0` : `offset = Vector2.ZERO`}
135
+ `;
136
+ return {
137
+ success: true,
138
+ output: JSON.stringify({
139
+ status: 'GENERATED_CAMERA_SHAKE',
140
+ camera_type: cameraType,
141
+ script_snippet: shakeScript
142
+ }, null, 2)
143
+ };
144
+ }
145
+
146
+ return { success: false, error: `Unknown action: ${action}` };
147
+ } catch (e) {
148
+ return { success: false, error: e.message };
149
+ }
150
+ }
151
+ };
@@ -0,0 +1,124 @@
1
+ import fs from 'fs/promises';
2
+ import fsSync from 'fs';
3
+ import path from 'path';
4
+
5
+ export const gameDataForge = {
6
+ schema: {
7
+ name: 'game.data_forge',
8
+ description: 'Generates and validates structured game data databases (`item_catalog.json`, `enemy_database.json`, `crafting_recipes.json`) for Godot 4.x or web games. Can generate 40+ rich RPG items with stats, rarities, and descriptions.',
9
+ parameters: {
10
+ type: 'object',
11
+ properties: {
12
+ action: {
13
+ type: 'string',
14
+ enum: ['generate_item_catalog', 'generate_crafting_recipes', 'validate_json_db', 'save_data_forge'],
15
+ description: 'Action: generate_item_catalog (create 40+ RPG items), generate_crafting_recipes (blacksmith/alchemy tables), validate_json_db (schema verification), or save_data_forge (write JSON files to disk).'
16
+ },
17
+ itemCount: { type: 'number', description: 'Number of items to generate (default 40).' },
18
+ gameGenre: { type: 'string', enum: ['medieval_rpg', 'cyberpunk_racing'], description: 'Genre rule set.' },
19
+ projectDir: { type: 'string', description: 'Absolute path to Godot project directory (`data/`).' },
20
+ customJsonData: { type: 'object', description: 'Custom JSON payload when saving directly.' },
21
+ targetFilename: { type: 'string', description: 'Target filename inside data folder (e.g. `item_catalog.json`).' }
22
+ },
23
+ required: ['action']
24
+ }
25
+ },
26
+
27
+ async execute(args) {
28
+ try {
29
+ const { action, itemCount = 40, gameGenre = 'medieval_rpg', projectDir, customJsonData, targetFilename = 'item_catalog.json' } = args;
30
+
31
+ if (action === 'generate_item_catalog') {
32
+ const rarities = ['Common', 'Uncommon', 'Rare', 'Epic', 'Legendary'];
33
+ const types = ['Weapon', 'Armor', 'Consumable', 'Relic', 'Material'];
34
+ const items = [];
35
+
36
+ // Core story items
37
+ items.push(
38
+ { id: 'relic_shadow', name: 'The Shadow Relic', type: 'Relic', rarity: 'Legendary', value: 5000, desc: 'Primordial obsidian shard humming with void energy.' },
39
+ { id: 'silver_key', name: 'Silver Key of Sanctuary', type: 'Relic', rarity: 'Epic', value: 1200, desc: 'Opens the inner wards of the Forgotten Catacombs.' },
40
+ { id: 'health_potion_minor', name: 'Minor Crimson Vial', type: 'Consumable', rarity: 'Common', value: 25, heal_amount: 50, desc: 'Restores 50 health points instantly.' },
41
+ { id: 'sword_iron_blade', name: 'Forged Iron Broadsword', type: 'Weapon', rarity: 'Common', value: 150, attack_damage: 25, desc: 'Standard issue village guard blade.' },
42
+ { id: 'armor_shadow_plate', name: 'Abyssal Steel Chestplate', type: 'Armor', rarity: 'Epic', value: 2400, defense: 65, desc: 'Absorbs 15% of incoming shadow magic damage.' }
43
+ );
44
+
45
+ // Procedurally generate remaining up to itemCount
46
+ const prefixes = ['Ancient', 'Shattered', 'Ethereal', 'Cursed', 'Celestial', 'Enchanted', 'Obsidian', 'Gilded'];
47
+ const nouns = ['Dagger', 'Longsword', 'Battleaxe', 'Grimoire', 'Gauntlets', 'Talisman', 'Elixir', 'Signet Ring', 'Shield', 'Greatsword'];
48
+
49
+ let idx = items.length + 1;
50
+ while (items.length < itemCount) {
51
+ const pref = prefixes[idx % prefixes.length];
52
+ const noun = nouns[idx % nouns.length];
53
+ const r = rarities[Math.min(rarities.length - 1, Math.floor(Math.random() * rarities.length))];
54
+ const t = nouns.slice(0, 3).includes(noun) || noun === 'Greatsword' ? 'Weapon' : (nouns.includes('Gauntlets') || noun === 'Shield' ? 'Armor' : 'Relic');
55
+
56
+ items.push({
57
+ id: `item_${idx}_${pref.toLowerCase()}_${noun.toLowerCase()}`,
58
+ name: `${pref} ${noun}`,
59
+ type: t,
60
+ rarity: r,
61
+ value: idx * 45,
62
+ attack_damage: t === 'Weapon' ? 20 + idx * 3 : 0,
63
+ defense: t === 'Armor' ? 15 + idx * 2 : 0,
64
+ desc: `An ancient artifact from the Age of ${pref.slice(0, 4)}. Holds immense historical value.`
65
+ });
66
+ idx++;
67
+ }
68
+
69
+ if (projectDir && fsSync.existsSync(projectDir)) {
70
+ const dataDir = path.join(projectDir, 'data');
71
+ await fs.mkdir(dataDir, { recursive: true });
72
+ await fs.writeFile(path.join(dataDir, 'item_catalog.json'), JSON.stringify({ items }, null, 2), 'utf8');
73
+ }
74
+
75
+ return {
76
+ success: true,
77
+ output: JSON.stringify({
78
+ status: 'GENERATED_ITEM_CATALOG',
79
+ genre: gameGenre,
80
+ total_items: items.length,
81
+ sample_items: items.slice(0, 5)
82
+ }, null, 2)
83
+ };
84
+ }
85
+
86
+ if (action === 'generate_crafting_recipes') {
87
+ const recipes = [
88
+ { recipe_id: 'craft_silver_key', output_item: 'silver_key', required_materials: [{ item: 'shadow_shard', qty: 5 }, { item: 'iron_ingot', qty: 2 }], gold_cost: 100 },
89
+ { recipe_id: 'craft_health_potion', output_item: 'health_potion_minor', required_materials: [{ item: 'red_herb', qty: 2 }, { item: 'empty_vial', qty: 1 }], gold_cost: 10 },
90
+ { recipe_id: 'craft_shadow_plate', output_item: 'armor_shadow_plate', required_materials: [{ item: 'abyssal_steel', qty: 4 }, { item: 'shadow_shard', qty: 10 }], gold_cost: 850 }
91
+ ];
92
+
93
+ if (projectDir && fsSync.existsSync(projectDir)) {
94
+ const dataDir = path.join(projectDir, 'data');
95
+ await fs.mkdir(dataDir, { recursive: true });
96
+ await fs.writeFile(path.join(dataDir, 'crafting_recipes.json'), JSON.stringify({ recipes }, null, 2), 'utf8');
97
+ }
98
+
99
+ return {
100
+ success: true,
101
+ output: JSON.stringify({ status: 'GENERATED_CRAFTING_RECIPES', recipes_count: recipes.length, recipes }, null, 2)
102
+ };
103
+ }
104
+
105
+ if (action === 'save_data_forge') {
106
+ if (!projectDir || !fsSync.existsSync(projectDir)) {
107
+ return { success: false, error: `projectDir is required to save data.` };
108
+ }
109
+ const dataDir = path.join(projectDir, 'data');
110
+ await fs.mkdir(dataDir, { recursive: true });
111
+ const filePath = path.join(dataDir, targetFilename);
112
+ await fs.writeFile(filePath, JSON.stringify(customJsonData || { status: 'empty' }, null, 2), 'utf8');
113
+ return {
114
+ success: true,
115
+ output: JSON.stringify({ status: 'SAVED_DATA_FORGE', file_path: filePath }, null, 2)
116
+ };
117
+ }
118
+
119
+ return { success: false, error: `Unknown action: ${action}` };
120
+ } catch (e) {
121
+ return { success: false, error: e.message };
122
+ }
123
+ }
124
+ };
@@ -0,0 +1,166 @@
1
+ import fs from 'fs/promises';
2
+ import fsSync from 'fs';
3
+ import path from 'path';
4
+
5
+ export const gameDialogueTreeGen = {
6
+ schema: {
7
+ name: 'game.dialogue_tree_gen',
8
+ description: 'Engineers branching NPC dialogue trees with conditional checks (e.g., player inventory items, quest state, reputation level) and dynamic choices (`dialogue_trees.json`). Validates schema structure for seamless integration into Godot UI boxes.',
9
+ parameters: {
10
+ type: 'object',
11
+ properties: {
12
+ action: {
13
+ type: 'string',
14
+ enum: ['create_tree', 'add_branch', 'save_dialogue_db'],
15
+ description: 'Action: create_tree (generate complete NPC tree), add_branch (append node choice), or save_dialogue_db (save dialogue_trees.json).'
16
+ },
17
+ npcId: {
18
+ type: 'string',
19
+ description: 'Unique ID of the NPC (e.g. `village_elder`, `blacksmith`, `mystic_mage`).'
20
+ },
21
+ npcName: {
22
+ type: 'string',
23
+ description: 'Display name of the NPC (e.g. `Elder Thaddeus`, `Grom the Blacksmith`).'
24
+ },
25
+ nodes: {
26
+ type: 'array',
27
+ items: {
28
+ type: 'object',
29
+ properties: {
30
+ node_id: { type: 'string' },
31
+ text: { type: 'string' },
32
+ conditions: {
33
+ type: 'object',
34
+ properties: {
35
+ required_item: { type: 'string' },
36
+ required_quest_state: { type: 'string' }
37
+ }
38
+ },
39
+ choices: {
40
+ type: 'array',
41
+ items: {
42
+ type: 'object',
43
+ properties: {
44
+ choice_text: { type: 'string' },
45
+ next_node_id: { type: 'string' },
46
+ reward_item: { type: 'string' },
47
+ set_quest_state: { type: 'string' }
48
+ }
49
+ }
50
+ }
51
+ }
52
+ },
53
+ description: 'List of dialogue nodes for create_tree.'
54
+ },
55
+ projectDir: {
56
+ type: 'string',
57
+ description: 'Optional absolute path to Godot/game project directory (`res://...`) to save `data/dialogue_trees.json`.'
58
+ }
59
+ },
60
+ required: ['action', 'npcId']
61
+ }
62
+ },
63
+
64
+ async execute(args) {
65
+ try {
66
+ const { action, npcId, npcName = 'NPC', nodes = [], projectDir } = args;
67
+
68
+ if (action === 'create_tree') {
69
+ const defaultNodes = nodes.length > 0 ? nodes : [
70
+ {
71
+ node_id: 'start',
72
+ text: `Greetings, traveler. Have you ventured into the Whispering Woods recently? The darkness deepens with every moon.`,
73
+ conditions: null,
74
+ choices: [
75
+ {
76
+ choice_text: 'I seek the Shadow Relic. What do you know of it?',
77
+ next_node_id: 'inquire_relic'
78
+ },
79
+ {
80
+ choice_text: 'I am just passing through.',
81
+ next_node_id: 'exit'
82
+ }
83
+ ]
84
+ },
85
+ {
86
+ node_id: 'inquire_relic',
87
+ text: 'The Shadow Relic is sealed beneath the Forgotten Catacombs. But only one who wields the Silver Key can overcome the wards.',
88
+ conditions: null,
89
+ choices: [
90
+ {
91
+ choice_text: 'Where can I find the Silver Key?',
92
+ next_node_id: 'silver_key_info'
93
+ },
94
+ {
95
+ choice_text: 'I already possess the Silver Key.',
96
+ next_node_id: 'key_check_pass',
97
+ condition_required_item: 'silver_key'
98
+ }
99
+ ]
100
+ },
101
+ {
102
+ node_id: 'silver_key_info',
103
+ text: 'Grom the Blacksmith holds the key, but he asks a high price in shadow shards. Seek his forge at the village center.',
104
+ choices: [
105
+ { choice_text: 'Thank you for the guidance.', next_node_id: 'exit', set_quest_state: 'quest_1_stage_2' }
106
+ ]
107
+ },
108
+ {
109
+ node_id: 'key_check_pass',
110
+ text: 'Ah! The Silver Key glimmers in your hand! May celestial grace shield you in the depths of the catacombs.',
111
+ choices: [
112
+ { choice_text: 'I will return victorious.', next_node_id: 'exit', set_quest_state: 'quest_1_stage_3' }
113
+ ]
114
+ },
115
+ {
116
+ node_id: 'exit',
117
+ text: 'May the light guide your blade.',
118
+ choices: []
119
+ }
120
+ ];
121
+
122
+ const treeObject = {
123
+ npc_id: npcId,
124
+ npc_name: npcName,
125
+ start_node_id: 'start',
126
+ nodes: defaultNodes
127
+ };
128
+
129
+ if (projectDir && fsSync.existsSync(projectDir)) {
130
+ const dataDir = path.join(projectDir, 'data');
131
+ await fs.mkdir(dataDir, { recursive: true });
132
+ const dbPath = path.join(dataDir, 'dialogue_trees.json');
133
+ let currentDb = {};
134
+ if (fsSync.existsSync(dbPath)) {
135
+ try { currentDb = JSON.parse(await fs.readFile(dbPath, 'utf8')); } catch (e) {}
136
+ }
137
+ currentDb[npcId] = treeObject;
138
+ await fs.writeFile(dbPath, JSON.stringify(currentDb, null, 2), 'utf8');
139
+ }
140
+
141
+ return {
142
+ success: true,
143
+ output: JSON.stringify(treeObject, null, 2)
144
+ };
145
+ }
146
+
147
+ if (action === 'save_dialogue_db') {
148
+ if (!projectDir || !fsSync.existsSync(projectDir)) {
149
+ return { success: false, error: `projectDir is required to save dialogue database.` };
150
+ }
151
+ const dataDir = path.join(projectDir, 'data');
152
+ await fs.mkdir(dataDir, { recursive: true });
153
+ const dbPath = path.join(dataDir, 'dialogue_trees.json');
154
+ await fs.writeFile(dbPath, JSON.stringify({ [npcId]: { npc_id: npcId, npc_name: npcName, nodes } }, null, 2), 'utf8');
155
+ return {
156
+ success: true,
157
+ output: JSON.stringify({ status: 'SAVED_DIALOGUE_DB', path: dbPath }, null, 2)
158
+ };
159
+ }
160
+
161
+ return { success: false, error: `Unknown action: ${action}` };
162
+ } catch (e) {
163
+ return { success: false, error: e.message };
164
+ }
165
+ }
166
+ };