@hoilab/ada-cli 0.84.21 → 0.84.22
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 +20 -0
- package/README.es.md +163 -0
- package/README.md +99 -652
- package/dist/cli/args.d.ts +3 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +11 -0
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/file-processor.d.ts.map +1 -1
- package/dist/cli/file-processor.js +2 -1
- package/dist/cli/file-processor.js.map +1 -1
- package/dist/cli/home-screen.d.ts.map +1 -1
- package/dist/cli/home-screen.js +2 -2
- package/dist/cli/home-screen.js.map +1 -1
- package/dist/cli/startup-ui.d.ts.map +1 -1
- package/dist/cli/startup-ui.js +9 -3
- package/dist/cli/startup-ui.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +2 -1
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session.d.ts +57 -7
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +449 -73
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +4 -3
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/core/compaction/branch-summarization.js +3 -0
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts +4 -3
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +41 -32
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/defaults.d.ts +1 -0
- package/dist/core/defaults.d.ts.map +1 -1
- package/dist/core/defaults.js +9 -0
- package/dist/core/defaults.js.map +1 -1
- package/dist/core/engine-personality.d.ts +12 -0
- package/dist/core/engine-personality.d.ts.map +1 -0
- package/dist/core/engine-personality.js +53 -0
- package/dist/core/engine-personality.js.map +1 -0
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +10 -5
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/types.d.ts +23 -4
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +2 -1
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/memory-engine/audit-export.d.ts +54 -0
- package/dist/core/memory-engine/audit-export.d.ts.map +1 -0
- package/dist/core/memory-engine/audit-export.js +85 -0
- package/dist/core/memory-engine/audit-export.js.map +1 -0
- package/dist/core/memory-engine/audit.d.ts.map +1 -1
- package/dist/core/memory-engine/audit.js +7 -8
- package/dist/core/memory-engine/audit.js.map +1 -1
- package/dist/core/memory-engine/engine.d.ts +2 -3
- package/dist/core/memory-engine/engine.d.ts.map +1 -1
- package/dist/core/memory-engine/engine.js +148 -50
- package/dist/core/memory-engine/engine.js.map +1 -1
- package/dist/core/memory-engine/inverted-index.d.ts.map +1 -1
- package/dist/core/memory-engine/inverted-index.js +67 -10
- package/dist/core/memory-engine/inverted-index.js.map +1 -1
- package/dist/core/memory-engine/keychain.d.ts.map +1 -1
- package/dist/core/memory-engine/keychain.js +1 -6
- package/dist/core/memory-engine/keychain.js.map +1 -1
- package/dist/core/memory-engine/observation-store.d.ts +1 -0
- package/dist/core/memory-engine/observation-store.d.ts.map +1 -1
- package/dist/core/memory-engine/observation-store.js +37 -8
- package/dist/core/memory-engine/observation-store.js.map +1 -1
- package/dist/core/memory-engine/scanner.d.ts.map +1 -1
- package/dist/core/memory-engine/scanner.js +25 -5
- package/dist/core/memory-engine/scanner.js.map +1 -1
- package/dist/core/memory-engine/security.d.ts.map +1 -1
- package/dist/core/memory-engine/security.js +131 -23
- package/dist/core/memory-engine/security.js.map +1 -1
- package/dist/core/memory-engine/session-indexer.d.ts.map +1 -1
- package/dist/core/memory-engine/session-indexer.js +8 -2
- package/dist/core/memory-engine/session-indexer.js.map +1 -1
- package/dist/core/memory-engine/tools.d.ts +2 -2
- package/dist/core/memory-engine/tools.d.ts.map +1 -1
- package/dist/core/memory-engine/tools.js +14 -7
- package/dist/core/memory-engine/tools.js.map +1 -1
- package/dist/core/memory-engine/vault.d.ts.map +1 -1
- package/dist/core/memory-engine/vault.js +2 -2
- package/dist/core/memory-engine/vault.js.map +1 -1
- package/dist/core/model-config.d.ts.map +1 -1
- package/dist/core/model-config.js +2 -1
- package/dist/core/model-config.js.map +1 -1
- package/dist/core/model-resolver.d.ts +1 -0
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +12 -6
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/models-store.d.ts.map +1 -1
- package/dist/core/models-store.js +2 -1
- package/dist/core/models-store.js.map +1 -1
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +11 -6
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/pi-manifest.d.ts.map +1 -1
- package/dist/core/pi-manifest.js +2 -1
- package/dist/core/pi-manifest.js.map +1 -1
- package/dist/core/prompt-optimizer.d.ts +53 -0
- package/dist/core/prompt-optimizer.d.ts.map +1 -0
- package/dist/core/prompt-optimizer.js +138 -0
- package/dist/core/prompt-optimizer.js.map +1 -0
- package/dist/core/provider-attribution.d.ts.map +1 -1
- package/dist/core/provider-attribution.js +1 -1
- package/dist/core/provider-attribution.js.map +1 -1
- package/dist/core/remote-catalog-provider.d.ts.map +1 -1
- package/dist/core/remote-catalog-provider.js +2 -1
- package/dist/core/remote-catalog-provider.js.map +1 -1
- package/dist/core/resource-loader.d.ts +50 -0
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +233 -7
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/sdk.d.ts +8 -0
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +11 -1
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +2 -1
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-diagnostics.d.ts +9 -0
- package/dist/core/settings-diagnostics.d.ts.map +1 -0
- package/dist/core/settings-diagnostics.js +21 -0
- package/dist/core/settings-diagnostics.js.map +1 -0
- package/dist/core/settings-manager.d.ts +52 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +204 -10
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +51 -33
- package/dist/core/skills.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +2 -1
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/tools/edit-diff.d.ts +0 -5
- package/dist/core/tools/edit-diff.d.ts.map +1 -1
- package/dist/core/tools/edit-diff.js +2 -5
- package/dist/core/tools/edit-diff.js.map +1 -1
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +20 -4
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +2 -2
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/project-memory-tool.d.ts.map +1 -1
- package/dist/core/tools/project-memory-tool.js +4 -1
- package/dist/core/tools/project-memory-tool.js.map +1 -1
- package/dist/core/trust-manager.d.ts.map +1 -1
- package/dist/core/trust-manager.js +2 -1
- package/dist/core/trust-manager.js.map +1 -1
- package/dist/core/workflows/agent-runner.d.ts +86 -0
- package/dist/core/workflows/agent-runner.d.ts.map +1 -0
- package/dist/core/workflows/agent-runner.js +225 -0
- package/dist/core/workflows/agent-runner.js.map +1 -0
- package/dist/core/workflows/builtins.d.ts +41 -0
- package/dist/core/workflows/builtins.d.ts.map +1 -0
- package/dist/core/workflows/builtins.js +282 -0
- package/dist/core/workflows/builtins.js.map +1 -0
- package/dist/core/workflows/goal-engine/engine.d.ts +134 -0
- package/dist/core/workflows/goal-engine/engine.d.ts.map +1 -0
- package/dist/core/workflows/goal-engine/engine.js +462 -0
- package/dist/core/workflows/goal-engine/engine.js.map +1 -0
- package/dist/core/workflows/goal-engine/errors.d.ts +7 -0
- package/dist/core/workflows/goal-engine/errors.d.ts.map +1 -0
- package/dist/core/workflows/goal-engine/errors.js +9 -0
- package/dist/core/workflows/goal-engine/errors.js.map +1 -0
- package/dist/core/workflows/goal-engine/index.d.ts +13 -0
- package/dist/core/workflows/goal-engine/index.d.ts.map +1 -0
- package/dist/core/workflows/goal-engine/index.js +8 -0
- package/dist/core/workflows/goal-engine/index.js.map +1 -0
- package/dist/core/workflows/goal-engine/persistence.d.ts +31 -0
- package/dist/core/workflows/goal-engine/persistence.d.ts.map +1 -0
- package/dist/core/workflows/goal-engine/persistence.js +145 -0
- package/dist/core/workflows/goal-engine/persistence.js.map +1 -0
- package/dist/core/workflows/goal-engine/prompts.d.ts +37 -0
- package/dist/core/workflows/goal-engine/prompts.d.ts.map +1 -0
- package/dist/core/workflows/goal-engine/prompts.js +131 -0
- package/dist/core/workflows/goal-engine/prompts.js.map +1 -0
- package/dist/core/workflows/goal-engine/state.d.ts +41 -0
- package/dist/core/workflows/goal-engine/state.d.ts.map +1 -0
- package/dist/core/workflows/goal-engine/state.js +397 -0
- package/dist/core/workflows/goal-engine/state.js.map +1 -0
- package/dist/core/workflows/goal-engine/tools.d.ts +31 -0
- package/dist/core/workflows/goal-engine/tools.d.ts.map +1 -0
- package/dist/core/workflows/goal-engine/tools.js +211 -0
- package/dist/core/workflows/goal-engine/tools.js.map +1 -0
- package/dist/core/workflows/goal-engine/types.d.ts +286 -0
- package/dist/core/workflows/goal-engine/types.d.ts.map +1 -0
- package/dist/core/workflows/goal-engine/types.js +17 -0
- package/dist/core/workflows/goal-engine/types.js.map +1 -0
- package/dist/core/workflows/goal-engine/worktree-fingerprint.d.ts +23 -0
- package/dist/core/workflows/goal-engine/worktree-fingerprint.d.ts.map +1 -0
- package/dist/core/workflows/goal-engine/worktree-fingerprint.js +72 -0
- package/dist/core/workflows/goal-engine/worktree-fingerprint.js.map +1 -0
- package/dist/core/workflows/graph-sync.d.ts +67 -0
- package/dist/core/workflows/graph-sync.d.ts.map +1 -0
- package/dist/core/workflows/graph-sync.js +188 -0
- package/dist/core/workflows/graph-sync.js.map +1 -0
- package/dist/core/workflows/graph.d.ts +143 -0
- package/dist/core/workflows/graph.d.ts.map +1 -0
- package/dist/core/workflows/graph.js +319 -0
- package/dist/core/workflows/graph.js.map +1 -0
- package/dist/core/workflows/index.d.ts +18 -0
- package/dist/core/workflows/index.d.ts.map +1 -0
- package/dist/core/workflows/index.js +14 -0
- package/dist/core/workflows/index.js.map +1 -0
- package/dist/core/workflows/journal.d.ts +68 -0
- package/dist/core/workflows/journal.d.ts.map +1 -0
- package/dist/core/workflows/journal.js +83 -0
- package/dist/core/workflows/journal.js.map +1 -0
- package/dist/core/workflows/manager.d.ts +112 -0
- package/dist/core/workflows/manager.d.ts.map +1 -0
- package/dist/core/workflows/manager.js +327 -0
- package/dist/core/workflows/manager.js.map +1 -0
- package/dist/core/workflows/resolve-script.d.ts +35 -0
- package/dist/core/workflows/resolve-script.d.ts.map +1 -0
- package/dist/core/workflows/resolve-script.js +66 -0
- package/dist/core/workflows/resolve-script.js.map +1 -0
- package/dist/core/workflows/runtime.d.ts +49 -0
- package/dist/core/workflows/runtime.d.ts.map +1 -0
- package/dist/core/workflows/runtime.js +301 -0
- package/dist/core/workflows/runtime.js.map +1 -0
- package/dist/core/workflows/shared-store.d.ts +31 -0
- package/dist/core/workflows/shared-store.d.ts.map +1 -0
- package/dist/core/workflows/shared-store.js +80 -0
- package/dist/core/workflows/shared-store.js.map +1 -0
- package/dist/core/workflows/subagent-host.d.ts +50 -0
- package/dist/core/workflows/subagent-host.d.ts.map +1 -0
- package/dist/core/workflows/subagent-host.js +225 -0
- package/dist/core/workflows/subagent-host.js.map +1 -0
- package/dist/core/workflows/tool-workflow.d.ts +22 -0
- package/dist/core/workflows/tool-workflow.d.ts.map +1 -0
- package/dist/core/workflows/tool-workflow.js +120 -0
- package/dist/core/workflows/tool-workflow.js.map +1 -0
- package/dist/core/workflows/types.d.ts +142 -0
- package/dist/core/workflows/types.d.ts.map +1 -0
- package/dist/core/workflows/types.js +26 -0
- package/dist/core/workflows/types.js.map +1 -0
- package/dist/core/workflows/worktree.d.ts +42 -0
- package/dist/core/workflows/worktree.d.ts.map +1 -0
- package/dist/core/workflows/worktree.js +107 -0
- package/dist/core/workflows/worktree.js.map +1 -0
- package/dist/extensions/llama/index.d.ts.map +1 -1
- package/dist/extensions/llama/index.js +2 -0
- package/dist/extensions/llama/index.js.map +1 -1
- package/dist/extensions/llama/provider.d.ts.map +1 -1
- package/dist/extensions/llama/provider.js +6 -2
- package/dist/extensions/llama/provider.js.map +1 -1
- package/dist/index.d.ts +16 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -11
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts +4 -0
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +20 -15
- package/dist/main.js.map +1 -1
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js +4 -3
- package/dist/migrations.js.map +1 -1
- package/dist/modes/interactive/components/home-screen.d.ts.map +1 -1
- package/dist/modes/interactive/components/home-screen.js +2 -2
- package/dist/modes/interactive/components/home-screen.js.map +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts +2 -3
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js +16 -6
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/components/prompt-optimization.d.ts +16 -0
- package/dist/modes/interactive/components/prompt-optimization.d.ts.map +1 -0
- package/dist/modes/interactive/components/prompt-optimization.js +46 -0
- package/dist/modes/interactive/components/prompt-optimization.js.map +1 -0
- package/dist/modes/interactive/components/settings-selector.d.ts +19 -1
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +247 -46
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-submenu.d.ts +72 -0
- package/dist/modes/interactive/components/settings-submenu.d.ts.map +1 -0
- package/dist/modes/interactive/components/settings-submenu.js +165 -0
- package/dist/modes/interactive/components/settings-submenu.js.map +1 -0
- package/dist/modes/interactive/components/thinking-selector.d.ts +8 -3
- package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.js +29 -3
- package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
- package/dist/modes/interactive/external-editor.d.ts.map +1 -1
- package/dist/modes/interactive/external-editor.js +2 -1
- package/dist/modes/interactive/external-editor.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +24 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +677 -34
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +4 -3
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/json-event.d.ts +16 -13
- package/dist/modes/json-event.d.ts.map +1 -1
- package/dist/modes/json-event.js +20 -6
- package/dist/modes/json-event.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +173 -0
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +29 -0
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/package-manager-cli.d.ts.map +1 -1
- package/dist/package-manager-cli.js +1 -1
- package/dist/package-manager-cli.js.map +1 -1
- package/dist/skills/ada-engine/SKILL.md +153 -0
- package/dist/utils/frontmatter.d.ts.map +1 -1
- package/dist/utils/frontmatter.js +2 -1
- package/dist/utils/frontmatter.js.map +1 -1
- package/dist/utils/management-http.d.ts +5 -3
- package/dist/utils/management-http.d.ts.map +1 -1
- package/dist/utils/management-http.js +14 -10
- package/dist/utils/management-http.js.map +1 -1
- package/dist/utils/text.d.ts +8 -0
- package/dist/utils/text.d.ts.map +1 -0
- package/dist/utils/text.js +9 -0
- package/dist/utils/text.js.map +1 -0
- package/docs/compaction.md +15 -0
- package/docs/custom-provider.md +5 -2
- package/docs/extensions.md +11 -2
- package/docs/json.md +7 -2
- package/docs/llama-cpp.md +2 -0
- package/docs/models.md +8 -2
- package/docs/rpc.md +9 -3
- package/docs/settings.md +2 -2
- package/docs/skills.md +4 -3
- package/examples/extensions/border-status-editor.ts +1 -1
- package/examples/extensions/git-checkpoint.ts +2 -2
- package/examples/extensions/notify.ts +3 -1
- package/examples/extensions/subagent/README.md +1 -1
- package/examples/extensions/subagent/index.ts +6 -1
- package/examples/extensions/titlebar-spinner.ts +1 -1
- package/examples/rpc-extension-ui.ts +1 -1
- package/examples/sdk/06-extensions.ts +1 -1
- package/examples/sdk/README.md +1 -1
- package/npm-shrinkwrap.json +2 -12
- package/package.json +3 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-script.js","sourceRoot":"","sources":["../../../src/core/workflows/resolve-script.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EACN,2BAA2B,EAC3B,wBAAwB,EACxB,0BAA0B,EAC1B,8BAA8B,EAC9B,0BAA0B,GAC1B,MAAM,eAAe,CAAC;AAavB,wDAAwD;AACxD,MAAM,UAAU,4BAA4B,CAAC,IAAY,EAAiB;IACzE,QAAQ,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;QAC/C,KAAK,eAAe;YACnB,OAAO,0BAA0B,CAAC,EAAE,CAAC,CAAC;QACvC,KAAK,aAAa;YACjB,OAAO,wBAAwB,CAAC,EAAE,CAAC,CAAC;QACrC,KAAK,eAAe;YACnB,OAAO,0BAA0B,EAAE,CAAC;QACrC,KAAK,gBAAgB;YACpB,OAAO,2BAA2B,CAAC,EAAE,CAAC,CAAC;QACxC,KAAK,mBAAmB;YACvB,OAAO,8BAA8B,CAAC,EAAE,CAAC,CAAC;QAC3C;YACC,OAAO,IAAI,CAAC;IACd,CAAC;AAAA,CACD;AAED;;;GAGG;AACH,MAAM,UAAU,2BAA2B,CAAC,QAAgB,EAAE,IAAY,EAAgC;IACzG,MAAM,OAAO,GAAG,4BAA4B,CAAC,IAAI,CAAC,CAAC;IACnD,IAAI,OAAO;QAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;IAExG,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC,CAAC;IAClD,KAAK,MAAM,GAAG,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC;QACxC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,WAAW,EAAE,GAAG,IAAI,IAAI,GAAG,EAAE,CAAC,CAAC;QAC/D,IAAI,CAAC;YACJ,MAAM,MAAM,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YAC/C,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;QAChE,CAAC;QAAC,MAAM,CAAC;YACR,uBAAsB;QACvB,CAAC;IACF,CAAC;IACD,OAAO,IAAI,CAAC;AAAA,CACZ;AAED,wEAAwE;AACxE,MAAM,UAAU,uBAAuB,CAAC,QAAgB,EAA6C;IACpG,IAAI,CAAC;QACJ,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;QACxC,OAAO,WAAW,CAAC,GAAG,CAAC;aACrB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;aAChE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACrF,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,EAAE,CAAC;IACX,CAAC;AAAA,CACD","sourcesContent":["/**\n * Resolución de scripts de workflow POR NOMBRE (§16.1).\n *\n * Orden de resolución:\n * 1. Builtin versionado con el SDK (deep_research, code_review, …).\n * 2. Script guardado por el usuario: <agentDir>/workflows/<name>.js\n * (cualquier JS con la API del runtime: agent/parallel/pipeline/phase/\n * store/checkpoint/args/cwd/runId/log — scripts DINÁMICOS completos).\n *\n * Un solo punto de verdad para CLI (/workflow), RPC (desktop), la tool\n * `workflow` del agente y el SDK.\n */\n\nimport { readdirSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport {\n\tgenerateCodebaseAuditScript,\n\tgenerateCodeReviewScript,\n\tgenerateDeepResearchScript,\n\tgenerateMultiPerspectiveScript,\n\tgenerateProductBuildScript,\n} from \"./builtins.ts\";\n\nexport interface ResolveWorkflowResult {\n\t/** Fuente del script: \"builtin\" | \"user-script\". */\n\tsource: \"builtin\" | \"user-script\";\n\t/** Nombre canónico (el del archivo o el builtin). */\n\tname: string;\n\t/** Contenido del script listo para runWorkflow. */\n\tscript: string;\n\t/** Ruta del archivo si es user-script. */\n\tfilePath?: string;\n}\n\n/** Resuelve un builtin por nombre; null si no lo es. */\nexport function resolveBuiltinWorkflowScript(name: string): string | null {\n\tswitch (name.replace(/-/g, \"_\").toLowerCase()) {\n\t\tcase \"deep_research\":\n\t\t\treturn generateDeepResearchScript({});\n\t\tcase \"code_review\":\n\t\t\treturn generateCodeReviewScript({});\n\t\tcase \"product_build\":\n\t\t\treturn generateProductBuildScript();\n\t\tcase \"codebase_audit\":\n\t\t\treturn generateCodebaseAuditScript({});\n\t\tcase \"multi_perspective\":\n\t\t\treturn generateMultiPerspectiveScript({});\n\t\tdefault:\n\t\t\treturn null;\n\t}\n}\n\n/**\n * Resuelve un workflow por nombre: builtin primero, luego script guardado en\n * <agentDir>/workflows/<name>.js (extensiones .js/.mjs/.cjs aceptadas).\n */\nexport function resolveWorkflowScriptByName(agentDir: string, name: string): ResolveWorkflowResult | null {\n\tconst builtin = resolveBuiltinWorkflowScript(name);\n\tif (builtin) return { source: \"builtin\", name: name.replace(/-/g, \"_\").toLowerCase(), script: builtin };\n\n\tconst base = name.replace(/\\.(js|mjs|cjs)$/i, \"\");\n\tfor (const ext of [\"js\", \"mjs\", \"cjs\"]) {\n\t\tconst filePath = join(agentDir, \"workflows\", `${base}.${ext}`);\n\t\ttry {\n\t\t\tconst script = readFileSync(filePath, \"utf-8\");\n\t\t\treturn { source: \"user-script\", name: base, script, filePath };\n\t\t} catch {\n\t\t\t// siguiente extensión\n\t\t}\n\t}\n\treturn null;\n}\n\n/** Lista scripts del usuario guardados en <agentDir>/workflows/*.js. */\nexport function listUserWorkflowScripts(agentDir: string): Array<{ name: string; filePath: string }> {\n\ttry {\n\t\tconst dir = join(agentDir, \"workflows\");\n\t\treturn readdirSync(dir)\n\t\t\t.filter((f) => /\\.(js|mjs|cjs)$/.test(f) && !f.endsWith(\".json\"))\n\t\t\t.map((f) => ({ name: f.replace(/\\.(js|mjs|cjs)$/i, \"\"), filePath: join(dir, f) }));\n\t} catch {\n\t\treturn [];\n\t}\n}\n"]}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workflow runtime — ejecuta scripts de workflow en un sandbox vm.
|
|
3
|
+
*
|
|
4
|
+
* El script es un módulo ESM con `export const meta = {...}` y el cuerpo
|
|
5
|
+
* (async). El vm recibe SOLO la API del workflow (agent/parallel/pipeline/
|
|
6
|
+
* store/phase/checkpoint/args/cwd/runId/log) — sin process/require/fs/fetch
|
|
7
|
+
* (sandbox; la red solo via tools de agente). Determinismo: Math.random y
|
|
8
|
+
* Date.now se neutralizan en el realm (resume estable). No se inyectan host
|
|
9
|
+
* built-ins (su .constructor sería el host Function — bypass del guard).
|
|
10
|
+
*/
|
|
11
|
+
import { agentIdentityHash, type CreateSubagentSession } from "./agent-runner.ts";
|
|
12
|
+
import { type WorkflowErrorCode, type WorkflowLimits, type WorkflowMeta, type WorkflowRunResult } from "./types.ts";
|
|
13
|
+
export interface WorkflowRuntimeOptions {
|
|
14
|
+
cwd: string;
|
|
15
|
+
agentDir: string;
|
|
16
|
+
createSession: CreateSubagentSession;
|
|
17
|
+
limits?: Partial<WorkflowLimits>;
|
|
18
|
+
resumeJournal?: Map<string, JournalEntryLike>;
|
|
19
|
+
onAgentStart?: (index: number, label: string, phase: string | undefined) => void;
|
|
20
|
+
onAgentEnd?: (index: number, label: string, result: unknown, usage: unknown) => void;
|
|
21
|
+
onPhase?: (title: string) => void;
|
|
22
|
+
onLog?: (message: string) => void;
|
|
23
|
+
onTokenUsage?: (usage: unknown) => void;
|
|
24
|
+
confirm?: (prompt: string, options: unknown) => Promise<unknown>;
|
|
25
|
+
args?: Record<string, unknown>;
|
|
26
|
+
signal?: AbortSignal;
|
|
27
|
+
/** runId fijo para resume (mismo run). Default: generado. */
|
|
28
|
+
runId?: string;
|
|
29
|
+
}
|
|
30
|
+
export interface JournalEntryLike {
|
|
31
|
+
hash: string;
|
|
32
|
+
result: unknown;
|
|
33
|
+
storeDelta?: Record<string, unknown>;
|
|
34
|
+
}
|
|
35
|
+
/** Limiter de concurrencia (semáforo simple). */
|
|
36
|
+
export declare function createLimiter(maxConcurrent: number): <T>(fn: () => Promise<T>) => Promise<T>;
|
|
37
|
+
/**
|
|
38
|
+
* Extrae `export const meta = {...}` del script: devuelve { meta, body }.
|
|
39
|
+
* Fallo con WORKFLOW_INVALID_SCRIPT si no hay meta o el JS no balancea.
|
|
40
|
+
*/
|
|
41
|
+
export declare function parseWorkflowScript(script: string): {
|
|
42
|
+
meta: WorkflowMeta;
|
|
43
|
+
body: string;
|
|
44
|
+
};
|
|
45
|
+
export declare function runWorkflow<T = unknown>(script: string, options: WorkflowRuntimeOptions): Promise<WorkflowRunResult<T>>;
|
|
46
|
+
/** Re-export del hash para journaling externo. */
|
|
47
|
+
export { agentIdentityHash };
|
|
48
|
+
export type { WorkflowErrorCode };
|
|
49
|
+
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../src/core/workflows/runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,EAAe,iBAAiB,EAAE,KAAK,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAE/F,OAAO,EAIN,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACtB,MAAM,YAAY,CAAC;AAUpB,MAAM,WAAW,sBAAsB;IACtC,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,qBAAqB,CAAC;IACrC,MAAM,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IACjC,aAAa,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAC9C,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IACjF,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACrF,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACxC,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACjE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,6DAA6D;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACrC;AAED,kDAAiD;AACjD,wBAAgB,aAAa,CAAC,aAAa,EAAE,MAAM,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAe5F;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CA8DxF;AAED,wBAAsB,WAAW,CAAC,CAAC,GAAG,OAAO,EAC5C,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,sBAAsB,GAC7B,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAoO/B;AAED,kDAAkD;AAClD,OAAO,EAAE,iBAAiB,EAAE,CAAC;AAC7B,YAAY,EAAE,iBAAiB,EAAE,CAAC","sourcesContent":["/**\n * Workflow runtime — ejecuta scripts de workflow en un sandbox vm.\n *\n * El script es un módulo ESM con `export const meta = {...}` y el cuerpo\n * (async). El vm recibe SOLO la API del workflow (agent/parallel/pipeline/\n * store/phase/checkpoint/args/cwd/runId/log) — sin process/require/fs/fetch\n * (sandbox; la red solo via tools de agente). Determinismo: Math.random y\n * Date.now se neutralizan en el realm (resume estable). No se inyectan host\n * built-ins (su .constructor sería el host Function — bypass del guard).\n */\n\nimport vm from \"node:vm\";\nimport type { TSchema } from \"typebox\";\nimport { AgentRunner, agentIdentityHash, type CreateSubagentSession } from \"./agent-runner.ts\";\nimport { SharedStore } from \"./shared-store.ts\";\nimport {\n\tDEFAULT_WORKFLOW_LIMITS,\n\ttype WorkflowApi,\n\tWorkflowError,\n\ttype WorkflowErrorCode,\n\ttype WorkflowLimits,\n\ttype WorkflowMeta,\n\ttype WorkflowRunResult,\n} from \"./types.ts\";\n\nconst _DETERMINISM_PRELUDE = `\n Math.random = () => { throw new Error(\"Math.random is disabled for workflow determinism\"); };\n Date.now = () => { throw new Error(\"Date.now is disabled for workflow determinism\"); };\n (globalThis as any).__adaWorkflowTime = 0;\n`;\n\nconst HOST_BUILTIN_BLOCKLIST = /require\\s*\\(|process\\s*\\.|global\\s*\\.\\s*process|import\\s*\\(/;\n\nexport interface WorkflowRuntimeOptions {\n\tcwd: string;\n\tagentDir: string;\n\tcreateSession: CreateSubagentSession;\n\tlimits?: Partial<WorkflowLimits>;\n\tresumeJournal?: Map<string, JournalEntryLike>;\n\tonAgentStart?: (index: number, label: string, phase: string | undefined) => void;\n\tonAgentEnd?: (index: number, label: string, result: unknown, usage: unknown) => void;\n\tonPhase?: (title: string) => void;\n\tonLog?: (message: string) => void;\n\tonTokenUsage?: (usage: unknown) => void;\n\tconfirm?: (prompt: string, options: unknown) => Promise<unknown>;\n\targs?: Record<string, unknown>;\n\tsignal?: AbortSignal;\n\t/** runId fijo para resume (mismo run). Default: generado. */\n\trunId?: string;\n}\n\nexport interface JournalEntryLike {\n\thash: string;\n\tresult: unknown;\n\tstoreDelta?: Record<string, unknown>;\n}\n\n/** Limiter de concurrencia (semáforo simple). */\nexport function createLimiter(maxConcurrent: number): <T>(fn: () => Promise<T>) => Promise<T> {\n\tlet active = 0;\n\tconst queue: Array<() => void> = [];\n\treturn async <T>(fn: () => Promise<T>): Promise<T> => {\n\t\tif (active >= maxConcurrent) {\n\t\t\tawait new Promise<void>((resolve) => queue.push(resolve));\n\t\t}\n\t\tactive++;\n\t\ttry {\n\t\t\treturn await fn();\n\t\t} finally {\n\t\t\tactive--;\n\t\t\tqueue.shift()?.();\n\t\t}\n\t};\n}\n\n/**\n * Extrae `export const meta = {...}` del script: devuelve { meta, body }.\n * Fallo con WORKFLOW_INVALID_SCRIPT si no hay meta o el JS no balancea.\n */\nexport function parseWorkflowScript(script: string): { meta: WorkflowMeta; body: string } {\n\tif (HOST_BUILTIN_BLOCKLIST.test(script)) {\n\t\tthrow new WorkflowError(\n\t\t\t\"WORKFLOW_INVALID_SCRIPT\",\n\t\t\t\"Script contains forbidden host access (require/process/import) — workflows run sandboxed\",\n\t\t\t{ recoverable: false },\n\t\t);\n\t}\n\tconst match = /export\\s+const\\s+meta\\s*=\\s*({)/m.exec(script);\n\tif (!match) {\n\t\tthrow new WorkflowError(\"WORKFLOW_INVALID_SCRIPT\", \"Script must export `const meta = {...}`\", {\n\t\t\trecoverable: false,\n\t\t});\n\t}\n\t// Extraer el objeto JSON con llaves balanceadas (el regex no-greedy falla con objetos anidados).\n\tconst start = match.index + match[0].length - 1;\n\tlet depth = 0;\n\tlet end = -1;\n\tlet inString = false;\n\tlet escaped = false;\n\tfor (let i = start; i < script.length; i++) {\n\t\tconst ch = script[i];\n\t\tif (inString) {\n\t\t\tif (escaped) escaped = false;\n\t\t\telse if (ch === \"\\\\\") escaped = true;\n\t\t\telse if (ch === '\"') inString = false;\n\t\t\tcontinue;\n\t\t}\n\t\tif (ch === '\"') inString = true;\n\t\telse if (ch === \"{\") depth++;\n\t\telse if (ch === \"}\") {\n\t\t\tdepth--;\n\t\t\tif (depth === 0) {\n\t\t\t\tend = i;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\tif (end === -1) {\n\t\tthrow new WorkflowError(\"WORKFLOW_INVALID_SCRIPT\", \"meta object is not closed\", { recoverable: false });\n\t}\n\tconst metaSource = script.slice(start, end + 1);\n\tlet meta: WorkflowMeta;\n\ttry {\n\t\tmeta = JSON.parse(metaSource) as WorkflowMeta;\n\t} catch {\n\t\tthrow new WorkflowError(\n\t\t\t\"WORKFLOW_INVALID_SCRIPT\",\n\t\t\t\"meta is not valid JSON — use plain JSON (no functions/comments)\",\n\t\t\t{\n\t\t\t\trecoverable: false,\n\t\t\t},\n\t\t);\n\t}\n\tif (!meta.name || !meta.description) {\n\t\tthrow new WorkflowError(\"WORKFLOW_INVALID_SCRIPT\", \"meta requires name and description\", { recoverable: false });\n\t}\n\tconst body = script.slice(end + 1).trim();\n\tif (!body) {\n\t\tthrow new WorkflowError(\"WORKFLOW_INVALID_SCRIPT\", \"Script has no body\", { recoverable: false });\n\t}\n\treturn { meta, body };\n}\n\nexport async function runWorkflow<T = unknown>(\n\tscript: string,\n\toptions: WorkflowRuntimeOptions,\n): Promise<WorkflowRunResult<T>> {\n\tconst limits: WorkflowLimits = { ...DEFAULT_WORKFLOW_LIMITS, ...options.limits };\n\tconst { meta, body } = parseWorkflowScript(script);\n\n\tconst runId = options.runId ?? `wf-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;\n\tconst store = new SharedStore();\n\tconst agentCounter = { count: 0 };\n\tconst limiter = createLimiter(limits.maxConcurrency);\n\tconst runner = new AgentRunner({\n\t\tagentDir: options.agentDir,\n\t\tcreateSession: options.createSession,\n\t\tlimiter,\n\t\tagentCounter,\n\t\tmaxAgents: limits.maxAgentsPerRun,\n\t\tretries: limits.maxRetries,\n\t\tagentTimeoutMs: limits.agentTimeoutMs,\n\t});\n\n\tconst logs: string[] = [];\n\tconst phases: string[] = [];\n\tlet callIndex = 0;\n\tconst tokenUsage = { input: 0, output: 0, total: 0, cost: 0, cacheRead: 0, cacheWrite: 0 };\n\tconst started = Date.now();\n\n\tconst log = (message: string) => {\n\t\tlogs.push(message);\n\t\toptions.onLog?.(message);\n\t};\n\n\tconst agent = async <_TSchemaDef extends TSchema | undefined = undefined>(\n\t\tagentOptions: Parameters<WorkflowApi[\"agent\"]>[0],\n\t) => {\n\t\tconst index = callIndex++;\n\t\toptions.onAgentStart?.(index, agentOptions.label ?? `agent-${index}`, agentOptions.phase);\n\n\t\tconst journalKey = `${runId}:${index}`;\n\t\tconst identityHash = agentIdentityHash({\n\t\t\tprompt: agentOptions.prompt,\n\t\t\tmodel: agentOptions.model,\n\t\t\ttier: agentOptions.tier,\n\t\t\tphase: agentOptions.phase,\n\t\t\tstableKey: agentOptions.stableKey,\n\t\t\tschema: agentOptions.schema,\n\t\t});\n\t\tconst cached = options.resumeJournal?.get(journalKey);\n\t\tif (cached && cached.hash === identityHash) {\n\t\t\tif (cached.storeDelta) store.applyDelta(cached.storeDelta);\n\t\t\toptions.onAgentEnd?.(index, agentOptions.label ?? `agent-${index}`, cached.result, { cached: true });\n\t\t\treturn cached.result;\n\t\t}\n\n\t\tconst result = await runner.run({\n\t\t\t...agentOptions,\n\t\t\t// Determinista: un resume reencuentra el mismo worktree.\n\t\t\tisolationKey: journalKey.replace(\":\", \"-\"),\n\t\t\tcwd: agentOptions.cwd ?? options.cwd,\n\t\t});\n\t\tif (result === null) return null;\n\n\t\ttokenUsage.input += result.usage.input;\n\t\ttokenUsage.output += result.usage.output;\n\t\ttokenUsage.total += result.usage.total;\n\t\ttokenUsage.cost += result.usage.cost;\n\t\ttokenUsage.cacheRead += result.usage.cacheRead ?? 0;\n\t\ttokenUsage.cacheWrite += result.usage.cacheWrite ?? 0;\n\n\t\toptions.onAgentEnd?.(index, agentOptions.label ?? `agent-${index}`, result.result, result.usage);\n\t\treturn result.result;\n\t};\n\n\tconst parallel = async <R>(fns: Array<() => Promise<R>>): Promise<Array<Awaited<R>>> => {\n\t\treturn Promise.all(fns.map((fn) => fn()));\n\t};\n\n\tconst pipeline = async <R>(fns: Array<(prev?: Awaited<R>) => Promise<R>>): Promise<Awaited<R>> => {\n\t\tlet prev: Awaited<R> | undefined;\n\t\tfor (const fn of fns) {\n\t\t\tprev = await fn(prev);\n\t\t}\n\t\treturn prev as Awaited<R>;\n\t};\n\n\tconst phase = (title: string, detail?: string) => {\n\t\tphases.push(title);\n\t\toptions.onPhase?.(title);\n\t\tif (detail) log(`phase ${title}: ${detail}`);\n\t};\n\n\tconst checkpoint = async <T>(\n\t\tpromptText: string,\n\t\tcheckpointOptions?: {\n\t\t\tdefault?: unknown;\n\t\t\theadless?: \"default\" | \"abort\";\n\t\t\tkind?: \"confirm\" | \"input\" | \"select\";\n\t\t\tchoices?: string[];\n\t\t},\n\t) => {\n\t\tif (options.confirm) {\n\t\t\treturn (await options.confirm(promptText, checkpointOptions)) as T;\n\t\t}\n\t\tif (checkpointOptions?.headless === \"abort\") {\n\t\t\tthrow new WorkflowError(\n\t\t\t\t\"WORKFLOW_ABORTED\",\n\t\t\t\t`checkpoint \"${promptText}\" needs human input but none is available`,\n\t\t\t\t{\n\t\t\t\t\trecoverable: false,\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\t\treturn (checkpointOptions?.default ?? true) as T;\n\t};\n\n\tconst api: WorkflowApi = {\n\t\tagent,\n\t\tparallel,\n\t\tpipeline,\n\t\tphase,\n\t\tstore: {\n\t\t\tput: (k, v) => store.put(k, v),\n\t\t\tget: <U>(k: string) => store.get<U>(k),\n\t\t\thas: (k) => store.has(k),\n\t\t\tdelete: (k) => store.delete(k),\n\t\t\tentries: () => store.entries(),\n\t\t},\n\t\tcheckpoint,\n\t\targs: options.args ?? {},\n\t\tcwd: options.cwd ?? process.cwd(),\n\t\trunId,\n\t\tlog,\n\t};\n\n\tconst context = vm.createContext({\n\t\t...api,\n\t\tObject,\n\t\tArray,\n\t\tJSON,\n\t\tMath: {\n\t\t\t...Math,\n\t\t\trandom: () => {\n\t\t\t\tthrow new Error(\"Math.random disabled\");\n\t\t\t},\n\t\t},\n\t\tDate: { ...Date, now: () => started },\n\t\tPromise,\n\t\tSet,\n\t\tMap,\n\t\tError,\n\t\tString,\n\t\tNumber,\n\t\tBoolean,\n\t\tconsole: {\n\t\t\tlog,\n\t\t\tinfo: log,\n\t\t\twarn: (m: unknown) => log(`[warn] ${String(m)}`),\n\t\t\terror: (m: unknown) => log(`[error] ${String(m)}`),\n\t\t},\n\t\t// Timers: necesarios para esperas cooperativas en scripts (no son acceso\n\t\t// a host — solo programan la cola del event loop).\n\t\tsetTimeout,\n\t\tclearTimeout,\n\t\tsetInterval,\n\t\tclearInterval,\n\t});\n\n\tconst wrapped = `(async () => {\\n${body}\\n})()`;\n\n\tconst scriptTimeout = new Promise<never>((_resolve, reject) => {\n\t\tsetTimeout(() => {\n\t\t\treject(\n\t\t\t\tnew WorkflowError(\"WORKFLOW_SCRIPT_TIMEOUT\", \"Workflow script exceeded its timeout\", {\n\t\t\t\t\trecoverable: false,\n\t\t\t\t}),\n\t\t\t);\n\t\t}, limits.scriptTimeoutMs);\n\t});\n\n\tlet aborted = false;\n\tif (options.signal?.aborted) {\n\t\taborted = true;\n\t} else if (options.signal) {\n\t\toptions.signal.addEventListener(\n\t\t\t\"abort\",\n\t\t\t() => {\n\t\t\t\taborted = true;\n\t\t\t},\n\t\t\t{ once: true },\n\t\t);\n\t}\n\n\t// Notificador de abort: interrumpe el race (≤25ms). El interval se limpia\n\t// SIEMPRE en el finally, así ninguna promesa queda viva tras el run.\n\t// Abort mediante sentinel (nunca rechazo → nunca unhandled).\n\t// El interval se limpia SIEMPRE en el finally.\n\tconst ABORT_SENTINEL = Symbol(\"abort\");\n\tlet abortTimer: ReturnType<typeof setInterval> | undefined;\n\tconst abortNotifier = new Promise<unknown>((resolve) => {\n\t\tabortTimer = setInterval(() => {\n\t\t\tif (aborted) {\n\t\t\t\tclearInterval(abortTimer);\n\t\t\t\tresolve(ABORT_SENTINEL);\n\t\t\t}\n\t\t}, 25);\n\t});\n\n\ttry {\n\t\tconst result = await Promise.race([\n\t\t\tnew vm.Script(wrapped, { filename: `${meta.name || \"workflow\"}.js` }).runInContext(context),\n\t\t\tscriptTimeout,\n\t\t\tabortNotifier,\n\t\t]);\n\t\tif (result === ABORT_SENTINEL) {\n\t\t\tthrow new WorkflowError(\"WORKFLOW_ABORTED\", \"Workflow aborted\", { recoverable: false });\n\t\t}\n\n\t\toptions.onTokenUsage?.(tokenUsage);\n\t\treturn {\n\t\t\tmeta,\n\t\t\tresult: result as T,\n\t\t\tlogs,\n\t\t\tphases,\n\t\t\tagentCount: agentCounter.count,\n\t\t\tdurationMs: Date.now() - started,\n\t\t\trunId,\n\t\t\ttokenUsage,\n\t\t};\n\t} finally {\n\t\tif (abortTimer) clearInterval(abortTimer);\n\t}\n}\n\n/** Re-export del hash para journaling externo. */\nexport { agentIdentityHash };\nexport type { WorkflowErrorCode };\n"]}
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workflow runtime — ejecuta scripts de workflow en un sandbox vm.
|
|
3
|
+
*
|
|
4
|
+
* El script es un módulo ESM con `export const meta = {...}` y el cuerpo
|
|
5
|
+
* (async). El vm recibe SOLO la API del workflow (agent/parallel/pipeline/
|
|
6
|
+
* store/phase/checkpoint/args/cwd/runId/log) — sin process/require/fs/fetch
|
|
7
|
+
* (sandbox; la red solo via tools de agente). Determinismo: Math.random y
|
|
8
|
+
* Date.now se neutralizan en el realm (resume estable). No se inyectan host
|
|
9
|
+
* built-ins (su .constructor sería el host Function — bypass del guard).
|
|
10
|
+
*/
|
|
11
|
+
import vm from "node:vm";
|
|
12
|
+
import { AgentRunner, agentIdentityHash } from "./agent-runner.js";
|
|
13
|
+
import { SharedStore } from "./shared-store.js";
|
|
14
|
+
import { DEFAULT_WORKFLOW_LIMITS, WorkflowError, } from "./types.js";
|
|
15
|
+
const _DETERMINISM_PRELUDE = `
|
|
16
|
+
Math.random = () => { throw new Error("Math.random is disabled for workflow determinism"); };
|
|
17
|
+
Date.now = () => { throw new Error("Date.now is disabled for workflow determinism"); };
|
|
18
|
+
(globalThis as any).__adaWorkflowTime = 0;
|
|
19
|
+
`;
|
|
20
|
+
const HOST_BUILTIN_BLOCKLIST = /require\s*\(|process\s*\.|global\s*\.\s*process|import\s*\(/;
|
|
21
|
+
/** Limiter de concurrencia (semáforo simple). */
|
|
22
|
+
export function createLimiter(maxConcurrent) {
|
|
23
|
+
let active = 0;
|
|
24
|
+
const queue = [];
|
|
25
|
+
return async (fn) => {
|
|
26
|
+
if (active >= maxConcurrent) {
|
|
27
|
+
await new Promise((resolve) => queue.push(resolve));
|
|
28
|
+
}
|
|
29
|
+
active++;
|
|
30
|
+
try {
|
|
31
|
+
return await fn();
|
|
32
|
+
}
|
|
33
|
+
finally {
|
|
34
|
+
active--;
|
|
35
|
+
queue.shift()?.();
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Extrae `export const meta = {...}` del script: devuelve { meta, body }.
|
|
41
|
+
* Fallo con WORKFLOW_INVALID_SCRIPT si no hay meta o el JS no balancea.
|
|
42
|
+
*/
|
|
43
|
+
export function parseWorkflowScript(script) {
|
|
44
|
+
if (HOST_BUILTIN_BLOCKLIST.test(script)) {
|
|
45
|
+
throw new WorkflowError("WORKFLOW_INVALID_SCRIPT", "Script contains forbidden host access (require/process/import) — workflows run sandboxed", { recoverable: false });
|
|
46
|
+
}
|
|
47
|
+
const match = /export\s+const\s+meta\s*=\s*({)/m.exec(script);
|
|
48
|
+
if (!match) {
|
|
49
|
+
throw new WorkflowError("WORKFLOW_INVALID_SCRIPT", "Script must export `const meta = {...}`", {
|
|
50
|
+
recoverable: false,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
// Extraer el objeto JSON con llaves balanceadas (el regex no-greedy falla con objetos anidados).
|
|
54
|
+
const start = match.index + match[0].length - 1;
|
|
55
|
+
let depth = 0;
|
|
56
|
+
let end = -1;
|
|
57
|
+
let inString = false;
|
|
58
|
+
let escaped = false;
|
|
59
|
+
for (let i = start; i < script.length; i++) {
|
|
60
|
+
const ch = script[i];
|
|
61
|
+
if (inString) {
|
|
62
|
+
if (escaped)
|
|
63
|
+
escaped = false;
|
|
64
|
+
else if (ch === "\\")
|
|
65
|
+
escaped = true;
|
|
66
|
+
else if (ch === '"')
|
|
67
|
+
inString = false;
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
if (ch === '"')
|
|
71
|
+
inString = true;
|
|
72
|
+
else if (ch === "{")
|
|
73
|
+
depth++;
|
|
74
|
+
else if (ch === "}") {
|
|
75
|
+
depth--;
|
|
76
|
+
if (depth === 0) {
|
|
77
|
+
end = i;
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
if (end === -1) {
|
|
83
|
+
throw new WorkflowError("WORKFLOW_INVALID_SCRIPT", "meta object is not closed", { recoverable: false });
|
|
84
|
+
}
|
|
85
|
+
const metaSource = script.slice(start, end + 1);
|
|
86
|
+
let meta;
|
|
87
|
+
try {
|
|
88
|
+
meta = JSON.parse(metaSource);
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
throw new WorkflowError("WORKFLOW_INVALID_SCRIPT", "meta is not valid JSON — use plain JSON (no functions/comments)", {
|
|
92
|
+
recoverable: false,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
if (!meta.name || !meta.description) {
|
|
96
|
+
throw new WorkflowError("WORKFLOW_INVALID_SCRIPT", "meta requires name and description", { recoverable: false });
|
|
97
|
+
}
|
|
98
|
+
const body = script.slice(end + 1).trim();
|
|
99
|
+
if (!body) {
|
|
100
|
+
throw new WorkflowError("WORKFLOW_INVALID_SCRIPT", "Script has no body", { recoverable: false });
|
|
101
|
+
}
|
|
102
|
+
return { meta, body };
|
|
103
|
+
}
|
|
104
|
+
export async function runWorkflow(script, options) {
|
|
105
|
+
const limits = { ...DEFAULT_WORKFLOW_LIMITS, ...options.limits };
|
|
106
|
+
const { meta, body } = parseWorkflowScript(script);
|
|
107
|
+
const runId = options.runId ?? `wf-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
108
|
+
const store = new SharedStore();
|
|
109
|
+
const agentCounter = { count: 0 };
|
|
110
|
+
const limiter = createLimiter(limits.maxConcurrency);
|
|
111
|
+
const runner = new AgentRunner({
|
|
112
|
+
agentDir: options.agentDir,
|
|
113
|
+
createSession: options.createSession,
|
|
114
|
+
limiter,
|
|
115
|
+
agentCounter,
|
|
116
|
+
maxAgents: limits.maxAgentsPerRun,
|
|
117
|
+
retries: limits.maxRetries,
|
|
118
|
+
agentTimeoutMs: limits.agentTimeoutMs,
|
|
119
|
+
});
|
|
120
|
+
const logs = [];
|
|
121
|
+
const phases = [];
|
|
122
|
+
let callIndex = 0;
|
|
123
|
+
const tokenUsage = { input: 0, output: 0, total: 0, cost: 0, cacheRead: 0, cacheWrite: 0 };
|
|
124
|
+
const started = Date.now();
|
|
125
|
+
const log = (message) => {
|
|
126
|
+
logs.push(message);
|
|
127
|
+
options.onLog?.(message);
|
|
128
|
+
};
|
|
129
|
+
const agent = async (agentOptions) => {
|
|
130
|
+
const index = callIndex++;
|
|
131
|
+
options.onAgentStart?.(index, agentOptions.label ?? `agent-${index}`, agentOptions.phase);
|
|
132
|
+
const journalKey = `${runId}:${index}`;
|
|
133
|
+
const identityHash = agentIdentityHash({
|
|
134
|
+
prompt: agentOptions.prompt,
|
|
135
|
+
model: agentOptions.model,
|
|
136
|
+
tier: agentOptions.tier,
|
|
137
|
+
phase: agentOptions.phase,
|
|
138
|
+
stableKey: agentOptions.stableKey,
|
|
139
|
+
schema: agentOptions.schema,
|
|
140
|
+
});
|
|
141
|
+
const cached = options.resumeJournal?.get(journalKey);
|
|
142
|
+
if (cached && cached.hash === identityHash) {
|
|
143
|
+
if (cached.storeDelta)
|
|
144
|
+
store.applyDelta(cached.storeDelta);
|
|
145
|
+
options.onAgentEnd?.(index, agentOptions.label ?? `agent-${index}`, cached.result, { cached: true });
|
|
146
|
+
return cached.result;
|
|
147
|
+
}
|
|
148
|
+
const result = await runner.run({
|
|
149
|
+
...agentOptions,
|
|
150
|
+
// Determinista: un resume reencuentra el mismo worktree.
|
|
151
|
+
isolationKey: journalKey.replace(":", "-"),
|
|
152
|
+
cwd: agentOptions.cwd ?? options.cwd,
|
|
153
|
+
});
|
|
154
|
+
if (result === null)
|
|
155
|
+
return null;
|
|
156
|
+
tokenUsage.input += result.usage.input;
|
|
157
|
+
tokenUsage.output += result.usage.output;
|
|
158
|
+
tokenUsage.total += result.usage.total;
|
|
159
|
+
tokenUsage.cost += result.usage.cost;
|
|
160
|
+
tokenUsage.cacheRead += result.usage.cacheRead ?? 0;
|
|
161
|
+
tokenUsage.cacheWrite += result.usage.cacheWrite ?? 0;
|
|
162
|
+
options.onAgentEnd?.(index, agentOptions.label ?? `agent-${index}`, result.result, result.usage);
|
|
163
|
+
return result.result;
|
|
164
|
+
};
|
|
165
|
+
const parallel = async (fns) => {
|
|
166
|
+
return Promise.all(fns.map((fn) => fn()));
|
|
167
|
+
};
|
|
168
|
+
const pipeline = async (fns) => {
|
|
169
|
+
let prev;
|
|
170
|
+
for (const fn of fns) {
|
|
171
|
+
prev = await fn(prev);
|
|
172
|
+
}
|
|
173
|
+
return prev;
|
|
174
|
+
};
|
|
175
|
+
const phase = (title, detail) => {
|
|
176
|
+
phases.push(title);
|
|
177
|
+
options.onPhase?.(title);
|
|
178
|
+
if (detail)
|
|
179
|
+
log(`phase ${title}: ${detail}`);
|
|
180
|
+
};
|
|
181
|
+
const checkpoint = async (promptText, checkpointOptions) => {
|
|
182
|
+
if (options.confirm) {
|
|
183
|
+
return (await options.confirm(promptText, checkpointOptions));
|
|
184
|
+
}
|
|
185
|
+
if (checkpointOptions?.headless === "abort") {
|
|
186
|
+
throw new WorkflowError("WORKFLOW_ABORTED", `checkpoint "${promptText}" needs human input but none is available`, {
|
|
187
|
+
recoverable: false,
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
return (checkpointOptions?.default ?? true);
|
|
191
|
+
};
|
|
192
|
+
const api = {
|
|
193
|
+
agent,
|
|
194
|
+
parallel,
|
|
195
|
+
pipeline,
|
|
196
|
+
phase,
|
|
197
|
+
store: {
|
|
198
|
+
put: (k, v) => store.put(k, v),
|
|
199
|
+
get: (k) => store.get(k),
|
|
200
|
+
has: (k) => store.has(k),
|
|
201
|
+
delete: (k) => store.delete(k),
|
|
202
|
+
entries: () => store.entries(),
|
|
203
|
+
},
|
|
204
|
+
checkpoint,
|
|
205
|
+
args: options.args ?? {},
|
|
206
|
+
cwd: options.cwd ?? process.cwd(),
|
|
207
|
+
runId,
|
|
208
|
+
log,
|
|
209
|
+
};
|
|
210
|
+
const context = vm.createContext({
|
|
211
|
+
...api,
|
|
212
|
+
Object,
|
|
213
|
+
Array,
|
|
214
|
+
JSON,
|
|
215
|
+
Math: {
|
|
216
|
+
...Math,
|
|
217
|
+
random: () => {
|
|
218
|
+
throw new Error("Math.random disabled");
|
|
219
|
+
},
|
|
220
|
+
},
|
|
221
|
+
Date: { ...Date, now: () => started },
|
|
222
|
+
Promise,
|
|
223
|
+
Set,
|
|
224
|
+
Map,
|
|
225
|
+
Error,
|
|
226
|
+
String,
|
|
227
|
+
Number,
|
|
228
|
+
Boolean,
|
|
229
|
+
console: {
|
|
230
|
+
log,
|
|
231
|
+
info: log,
|
|
232
|
+
warn: (m) => log(`[warn] ${String(m)}`),
|
|
233
|
+
error: (m) => log(`[error] ${String(m)}`),
|
|
234
|
+
},
|
|
235
|
+
// Timers: necesarios para esperas cooperativas en scripts (no son acceso
|
|
236
|
+
// a host — solo programan la cola del event loop).
|
|
237
|
+
setTimeout,
|
|
238
|
+
clearTimeout,
|
|
239
|
+
setInterval,
|
|
240
|
+
clearInterval,
|
|
241
|
+
});
|
|
242
|
+
const wrapped = `(async () => {\n${body}\n})()`;
|
|
243
|
+
const scriptTimeout = new Promise((_resolve, reject) => {
|
|
244
|
+
setTimeout(() => {
|
|
245
|
+
reject(new WorkflowError("WORKFLOW_SCRIPT_TIMEOUT", "Workflow script exceeded its timeout", {
|
|
246
|
+
recoverable: false,
|
|
247
|
+
}));
|
|
248
|
+
}, limits.scriptTimeoutMs);
|
|
249
|
+
});
|
|
250
|
+
let aborted = false;
|
|
251
|
+
if (options.signal?.aborted) {
|
|
252
|
+
aborted = true;
|
|
253
|
+
}
|
|
254
|
+
else if (options.signal) {
|
|
255
|
+
options.signal.addEventListener("abort", () => {
|
|
256
|
+
aborted = true;
|
|
257
|
+
}, { once: true });
|
|
258
|
+
}
|
|
259
|
+
// Notificador de abort: interrumpe el race (≤25ms). El interval se limpia
|
|
260
|
+
// SIEMPRE en el finally, así ninguna promesa queda viva tras el run.
|
|
261
|
+
// Abort mediante sentinel (nunca rechazo → nunca unhandled).
|
|
262
|
+
// El interval se limpia SIEMPRE en el finally.
|
|
263
|
+
const ABORT_SENTINEL = Symbol("abort");
|
|
264
|
+
let abortTimer;
|
|
265
|
+
const abortNotifier = new Promise((resolve) => {
|
|
266
|
+
abortTimer = setInterval(() => {
|
|
267
|
+
if (aborted) {
|
|
268
|
+
clearInterval(abortTimer);
|
|
269
|
+
resolve(ABORT_SENTINEL);
|
|
270
|
+
}
|
|
271
|
+
}, 25);
|
|
272
|
+
});
|
|
273
|
+
try {
|
|
274
|
+
const result = await Promise.race([
|
|
275
|
+
new vm.Script(wrapped, { filename: `${meta.name || "workflow"}.js` }).runInContext(context),
|
|
276
|
+
scriptTimeout,
|
|
277
|
+
abortNotifier,
|
|
278
|
+
]);
|
|
279
|
+
if (result === ABORT_SENTINEL) {
|
|
280
|
+
throw new WorkflowError("WORKFLOW_ABORTED", "Workflow aborted", { recoverable: false });
|
|
281
|
+
}
|
|
282
|
+
options.onTokenUsage?.(tokenUsage);
|
|
283
|
+
return {
|
|
284
|
+
meta,
|
|
285
|
+
result: result,
|
|
286
|
+
logs,
|
|
287
|
+
phases,
|
|
288
|
+
agentCount: agentCounter.count,
|
|
289
|
+
durationMs: Date.now() - started,
|
|
290
|
+
runId,
|
|
291
|
+
tokenUsage,
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
finally {
|
|
295
|
+
if (abortTimer)
|
|
296
|
+
clearInterval(abortTimer);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
/** Re-export del hash para journaling externo. */
|
|
300
|
+
export { agentIdentityHash };
|
|
301
|
+
//# sourceMappingURL=runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../../src/core/workflows/runtime.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Workflow runtime — ejecuta scripts de workflow en un sandbox vm.\n *\n * El script es un módulo ESM con `export const meta = {...}` y el cuerpo\n * (async). El vm recibe SOLO la API del workflow (agent/parallel/pipeline/\n * store/phase/checkpoint/args/cwd/runId/log) — sin process/require/fs/fetch\n * (sandbox; la red solo via tools de agente). Determinismo: Math.random y\n * Date.now se neutralizan en el realm (resume estable). No se inyectan host\n * built-ins (su .constructor sería el host Function — bypass del guard).\n */\n\nimport vm from \"node:vm\";\nimport type { TSchema } from \"typebox\";\nimport { AgentRunner, agentIdentityHash, type CreateSubagentSession } from \"./agent-runner.ts\";\nimport { SharedStore } from \"./shared-store.ts\";\nimport {\n\tDEFAULT_WORKFLOW_LIMITS,\n\ttype WorkflowApi,\n\tWorkflowError,\n\ttype WorkflowErrorCode,\n\ttype WorkflowLimits,\n\ttype WorkflowMeta,\n\ttype WorkflowRunResult,\n} from \"./types.ts\";\n\nconst _DETERMINISM_PRELUDE = `\n Math.random = () => { throw new Error(\"Math.random is disabled for workflow determinism\"); };\n Date.now = () => { throw new Error(\"Date.now is disabled for workflow determinism\"); };\n (globalThis as any).__adaWorkflowTime = 0;\n`;\n\nconst HOST_BUILTIN_BLOCKLIST = /require\\s*\\(|process\\s*\\.|global\\s*\\.\\s*process|import\\s*\\(/;\n\nexport interface WorkflowRuntimeOptions {\n\tcwd: string;\n\tagentDir: string;\n\tcreateSession: CreateSubagentSession;\n\tlimits?: Partial<WorkflowLimits>;\n\tresumeJournal?: Map<string, JournalEntryLike>;\n\tonAgentStart?: (index: number, label: string, phase: string | undefined) => void;\n\tonAgentEnd?: (index: number, label: string, result: unknown, usage: unknown) => void;\n\tonPhase?: (title: string) => void;\n\tonLog?: (message: string) => void;\n\tonTokenUsage?: (usage: unknown) => void;\n\tconfirm?: (prompt: string, options: unknown) => Promise<unknown>;\n\targs?: Record<string, unknown>;\n\tsignal?: AbortSignal;\n\t/** runId fijo para resume (mismo run). Default: generado. */\n\trunId?: string;\n}\n\nexport interface JournalEntryLike {\n\thash: string;\n\tresult: unknown;\n\tstoreDelta?: Record<string, unknown>;\n}\n\n/** Limiter de concurrencia (semáforo simple). */\nexport function createLimiter(maxConcurrent: number): <T>(fn: () => Promise<T>) => Promise<T> {\n\tlet active = 0;\n\tconst queue: Array<() => void> = [];\n\treturn async <T>(fn: () => Promise<T>): Promise<T> => {\n\t\tif (active >= maxConcurrent) {\n\t\t\tawait new Promise<void>((resolve) => queue.push(resolve));\n\t\t}\n\t\tactive++;\n\t\ttry {\n\t\t\treturn await fn();\n\t\t} finally {\n\t\t\tactive--;\n\t\t\tqueue.shift()?.();\n\t\t}\n\t};\n}\n\n/**\n * Extrae `export const meta = {...}` del script: devuelve { meta, body }.\n * Fallo con WORKFLOW_INVALID_SCRIPT si no hay meta o el JS no balancea.\n */\nexport function parseWorkflowScript(script: string): { meta: WorkflowMeta; body: string } {\n\tif (HOST_BUILTIN_BLOCKLIST.test(script)) {\n\t\tthrow new WorkflowError(\n\t\t\t\"WORKFLOW_INVALID_SCRIPT\",\n\t\t\t\"Script contains forbidden host access (require/process/import) — workflows run sandboxed\",\n\t\t\t{ recoverable: false },\n\t\t);\n\t}\n\tconst match = /export\\s+const\\s+meta\\s*=\\s*({)/m.exec(script);\n\tif (!match) {\n\t\tthrow new WorkflowError(\"WORKFLOW_INVALID_SCRIPT\", \"Script must export `const meta = {...}`\", {\n\t\t\trecoverable: false,\n\t\t});\n\t}\n\t// Extraer el objeto JSON con llaves balanceadas (el regex no-greedy falla con objetos anidados).\n\tconst start = match.index + match[0].length - 1;\n\tlet depth = 0;\n\tlet end = -1;\n\tlet inString = false;\n\tlet escaped = false;\n\tfor (let i = start; i < script.length; i++) {\n\t\tconst ch = script[i];\n\t\tif (inString) {\n\t\t\tif (escaped) escaped = false;\n\t\t\telse if (ch === \"\\\\\") escaped = true;\n\t\t\telse if (ch === '\"') inString = false;\n\t\t\tcontinue;\n\t\t}\n\t\tif (ch === '\"') inString = true;\n\t\telse if (ch === \"{\") depth++;\n\t\telse if (ch === \"}\") {\n\t\t\tdepth--;\n\t\t\tif (depth === 0) {\n\t\t\t\tend = i;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\tif (end === -1) {\n\t\tthrow new WorkflowError(\"WORKFLOW_INVALID_SCRIPT\", \"meta object is not closed\", { recoverable: false });\n\t}\n\tconst metaSource = script.slice(start, end + 1);\n\tlet meta: WorkflowMeta;\n\ttry {\n\t\tmeta = JSON.parse(metaSource) as WorkflowMeta;\n\t} catch {\n\t\tthrow new WorkflowError(\n\t\t\t\"WORKFLOW_INVALID_SCRIPT\",\n\t\t\t\"meta is not valid JSON — use plain JSON (no functions/comments)\",\n\t\t\t{\n\t\t\t\trecoverable: false,\n\t\t\t},\n\t\t);\n\t}\n\tif (!meta.name || !meta.description) {\n\t\tthrow new WorkflowError(\"WORKFLOW_INVALID_SCRIPT\", \"meta requires name and description\", { recoverable: false });\n\t}\n\tconst body = script.slice(end + 1).trim();\n\tif (!body) {\n\t\tthrow new WorkflowError(\"WORKFLOW_INVALID_SCRIPT\", \"Script has no body\", { recoverable: false });\n\t}\n\treturn { meta, body };\n}\n\nexport async function runWorkflow<T = unknown>(\n\tscript: string,\n\toptions: WorkflowRuntimeOptions,\n): Promise<WorkflowRunResult<T>> {\n\tconst limits: WorkflowLimits = { ...DEFAULT_WORKFLOW_LIMITS, ...options.limits };\n\tconst { meta, body } = parseWorkflowScript(script);\n\n\tconst runId = options.runId ?? `wf-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;\n\tconst store = new SharedStore();\n\tconst agentCounter = { count: 0 };\n\tconst limiter = createLimiter(limits.maxConcurrency);\n\tconst runner = new AgentRunner({\n\t\tagentDir: options.agentDir,\n\t\tcreateSession: options.createSession,\n\t\tlimiter,\n\t\tagentCounter,\n\t\tmaxAgents: limits.maxAgentsPerRun,\n\t\tretries: limits.maxRetries,\n\t\tagentTimeoutMs: limits.agentTimeoutMs,\n\t});\n\n\tconst logs: string[] = [];\n\tconst phases: string[] = [];\n\tlet callIndex = 0;\n\tconst tokenUsage = { input: 0, output: 0, total: 0, cost: 0, cacheRead: 0, cacheWrite: 0 };\n\tconst started = Date.now();\n\n\tconst log = (message: string) => {\n\t\tlogs.push(message);\n\t\toptions.onLog?.(message);\n\t};\n\n\tconst agent = async <_TSchemaDef extends TSchema | undefined = undefined>(\n\t\tagentOptions: Parameters<WorkflowApi[\"agent\"]>[0],\n\t) => {\n\t\tconst index = callIndex++;\n\t\toptions.onAgentStart?.(index, agentOptions.label ?? `agent-${index}`, agentOptions.phase);\n\n\t\tconst journalKey = `${runId}:${index}`;\n\t\tconst identityHash = agentIdentityHash({\n\t\t\tprompt: agentOptions.prompt,\n\t\t\tmodel: agentOptions.model,\n\t\t\ttier: agentOptions.tier,\n\t\t\tphase: agentOptions.phase,\n\t\t\tstableKey: agentOptions.stableKey,\n\t\t\tschema: agentOptions.schema,\n\t\t});\n\t\tconst cached = options.resumeJournal?.get(journalKey);\n\t\tif (cached && cached.hash === identityHash) {\n\t\t\tif (cached.storeDelta) store.applyDelta(cached.storeDelta);\n\t\t\toptions.onAgentEnd?.(index, agentOptions.label ?? `agent-${index}`, cached.result, { cached: true });\n\t\t\treturn cached.result;\n\t\t}\n\n\t\tconst result = await runner.run({\n\t\t\t...agentOptions,\n\t\t\t// Determinista: un resume reencuentra el mismo worktree.\n\t\t\tisolationKey: journalKey.replace(\":\", \"-\"),\n\t\t\tcwd: agentOptions.cwd ?? options.cwd,\n\t\t});\n\t\tif (result === null) return null;\n\n\t\ttokenUsage.input += result.usage.input;\n\t\ttokenUsage.output += result.usage.output;\n\t\ttokenUsage.total += result.usage.total;\n\t\ttokenUsage.cost += result.usage.cost;\n\t\ttokenUsage.cacheRead += result.usage.cacheRead ?? 0;\n\t\ttokenUsage.cacheWrite += result.usage.cacheWrite ?? 0;\n\n\t\toptions.onAgentEnd?.(index, agentOptions.label ?? `agent-${index}`, result.result, result.usage);\n\t\treturn result.result;\n\t};\n\n\tconst parallel = async <R>(fns: Array<() => Promise<R>>): Promise<Array<Awaited<R>>> => {\n\t\treturn Promise.all(fns.map((fn) => fn()));\n\t};\n\n\tconst pipeline = async <R>(fns: Array<(prev?: Awaited<R>) => Promise<R>>): Promise<Awaited<R>> => {\n\t\tlet prev: Awaited<R> | undefined;\n\t\tfor (const fn of fns) {\n\t\t\tprev = await fn(prev);\n\t\t}\n\t\treturn prev as Awaited<R>;\n\t};\n\n\tconst phase = (title: string, detail?: string) => {\n\t\tphases.push(title);\n\t\toptions.onPhase?.(title);\n\t\tif (detail) log(`phase ${title}: ${detail}`);\n\t};\n\n\tconst checkpoint = async <T>(\n\t\tpromptText: string,\n\t\tcheckpointOptions?: {\n\t\t\tdefault?: unknown;\n\t\t\theadless?: \"default\" | \"abort\";\n\t\t\tkind?: \"confirm\" | \"input\" | \"select\";\n\t\t\tchoices?: string[];\n\t\t},\n\t) => {\n\t\tif (options.confirm) {\n\t\t\treturn (await options.confirm(promptText, checkpointOptions)) as T;\n\t\t}\n\t\tif (checkpointOptions?.headless === \"abort\") {\n\t\t\tthrow new WorkflowError(\n\t\t\t\t\"WORKFLOW_ABORTED\",\n\t\t\t\t`checkpoint \"${promptText}\" needs human input but none is available`,\n\t\t\t\t{\n\t\t\t\t\trecoverable: false,\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\t\treturn (checkpointOptions?.default ?? true) as T;\n\t};\n\n\tconst api: WorkflowApi = {\n\t\tagent,\n\t\tparallel,\n\t\tpipeline,\n\t\tphase,\n\t\tstore: {\n\t\t\tput: (k, v) => store.put(k, v),\n\t\t\tget: <U>(k: string) => store.get<U>(k),\n\t\t\thas: (k) => store.has(k),\n\t\t\tdelete: (k) => store.delete(k),\n\t\t\tentries: () => store.entries(),\n\t\t},\n\t\tcheckpoint,\n\t\targs: options.args ?? {},\n\t\tcwd: options.cwd ?? process.cwd(),\n\t\trunId,\n\t\tlog,\n\t};\n\n\tconst context = vm.createContext({\n\t\t...api,\n\t\tObject,\n\t\tArray,\n\t\tJSON,\n\t\tMath: {\n\t\t\t...Math,\n\t\t\trandom: () => {\n\t\t\t\tthrow new Error(\"Math.random disabled\");\n\t\t\t},\n\t\t},\n\t\tDate: { ...Date, now: () => started },\n\t\tPromise,\n\t\tSet,\n\t\tMap,\n\t\tError,\n\t\tString,\n\t\tNumber,\n\t\tBoolean,\n\t\tconsole: {\n\t\t\tlog,\n\t\t\tinfo: log,\n\t\t\twarn: (m: unknown) => log(`[warn] ${String(m)}`),\n\t\t\terror: (m: unknown) => log(`[error] ${String(m)}`),\n\t\t},\n\t\t// Timers: necesarios para esperas cooperativas en scripts (no son acceso\n\t\t// a host — solo programan la cola del event loop).\n\t\tsetTimeout,\n\t\tclearTimeout,\n\t\tsetInterval,\n\t\tclearInterval,\n\t});\n\n\tconst wrapped = `(async () => {\\n${body}\\n})()`;\n\n\tconst scriptTimeout = new Promise<never>((_resolve, reject) => {\n\t\tsetTimeout(() => {\n\t\t\treject(\n\t\t\t\tnew WorkflowError(\"WORKFLOW_SCRIPT_TIMEOUT\", \"Workflow script exceeded its timeout\", {\n\t\t\t\t\trecoverable: false,\n\t\t\t\t}),\n\t\t\t);\n\t\t}, limits.scriptTimeoutMs);\n\t});\n\n\tlet aborted = false;\n\tif (options.signal?.aborted) {\n\t\taborted = true;\n\t} else if (options.signal) {\n\t\toptions.signal.addEventListener(\n\t\t\t\"abort\",\n\t\t\t() => {\n\t\t\t\taborted = true;\n\t\t\t},\n\t\t\t{ once: true },\n\t\t);\n\t}\n\n\t// Notificador de abort: interrumpe el race (≤25ms). El interval se limpia\n\t// SIEMPRE en el finally, así ninguna promesa queda viva tras el run.\n\t// Abort mediante sentinel (nunca rechazo → nunca unhandled).\n\t// El interval se limpia SIEMPRE en el finally.\n\tconst ABORT_SENTINEL = Symbol(\"abort\");\n\tlet abortTimer: ReturnType<typeof setInterval> | undefined;\n\tconst abortNotifier = new Promise<unknown>((resolve) => {\n\t\tabortTimer = setInterval(() => {\n\t\t\tif (aborted) {\n\t\t\t\tclearInterval(abortTimer);\n\t\t\t\tresolve(ABORT_SENTINEL);\n\t\t\t}\n\t\t}, 25);\n\t});\n\n\ttry {\n\t\tconst result = await Promise.race([\n\t\t\tnew vm.Script(wrapped, { filename: `${meta.name || \"workflow\"}.js` }).runInContext(context),\n\t\t\tscriptTimeout,\n\t\t\tabortNotifier,\n\t\t]);\n\t\tif (result === ABORT_SENTINEL) {\n\t\t\tthrow new WorkflowError(\"WORKFLOW_ABORTED\", \"Workflow aborted\", { recoverable: false });\n\t\t}\n\n\t\toptions.onTokenUsage?.(tokenUsage);\n\t\treturn {\n\t\t\tmeta,\n\t\t\tresult: result as T,\n\t\t\tlogs,\n\t\t\tphases,\n\t\t\tagentCount: agentCounter.count,\n\t\t\tdurationMs: Date.now() - started,\n\t\t\trunId,\n\t\t\ttokenUsage,\n\t\t};\n\t} finally {\n\t\tif (abortTimer) clearInterval(abortTimer);\n\t}\n}\n\n/** Re-export del hash para journaling externo. */\nexport { agentIdentityHash };\nexport type { WorkflowErrorCode };\n"]}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SharedStore — KV en memoria compartido entre los subagentes de un run.
|
|
3
|
+
*
|
|
4
|
+
* Cada agente escribe deltas (`trackPut` con deltaKey `${runId}:${callIndex}`)
|
|
5
|
+
* que se journalizan; en resume se re-aplican en orden callSeq. Los valores
|
|
6
|
+
* previos se shadowean para rollback de retries fallidos (patrón
|
|
7
|
+
* pi-dynamic-workflows).
|
|
8
|
+
*/
|
|
9
|
+
export declare class SharedStore {
|
|
10
|
+
private readonly map;
|
|
11
|
+
private readonly agentDeltas;
|
|
12
|
+
private readonly priorValues;
|
|
13
|
+
put(key: string, value: unknown): void;
|
|
14
|
+
get<T = unknown>(key: string): T | undefined;
|
|
15
|
+
has(key: string): boolean;
|
|
16
|
+
delete(key: string): boolean;
|
|
17
|
+
entries(): Array<[string, unknown]>;
|
|
18
|
+
/**
|
|
19
|
+
* Escribe y registra el delta para `deltaKey` (run-unique).
|
|
20
|
+
* Shadowea el valor previo solo la primera vez dentro de la ventana.
|
|
21
|
+
*/
|
|
22
|
+
trackPut(key: string, value: unknown, deltaKey: string): void;
|
|
23
|
+
/** Delta consolidado para journalizar (el agente terminó). */
|
|
24
|
+
commitDelta(deltaKey: string): Record<string, unknown>;
|
|
25
|
+
/** Rollback de las escrituras de un retry fallido. */
|
|
26
|
+
discardDelta(deltaKey: string): void;
|
|
27
|
+
/** Replay aditivo de deltas en orden callSeq (resume). */
|
|
28
|
+
applyDelta(delta: Record<string, unknown>): void;
|
|
29
|
+
get size(): number;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=shared-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared-store.d.ts","sourceRoot":"","sources":["../../../src/core/workflows/shared-store.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,qBAAa,WAAW;IACvB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAA8B;IAClD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA8C;IAC1E,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAwE;IAEpG,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAErC;IAED,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,CAE3C;IAED,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAExB;IAED,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAE3B;IAED,OAAO,IAAI,KAAK,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAElC;IAED;;;OAGG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAmB5D;IAED,+DAA8D;IAC9D,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAKrD;IAED,sDAAsD;IACtD,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAUnC;IAED,0DAA0D;IAC1D,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAI/C;IAED,IAAI,IAAI,IAAI,MAAM,CAEjB;CACD","sourcesContent":["/**\n * SharedStore — KV en memoria compartido entre los subagentes de un run.\n *\n * Cada agente escribe deltas (`trackPut` con deltaKey `${runId}:${callIndex}`)\n * que se journalizan; en resume se re-aplican en orden callSeq. Los valores\n * previos se shadowean para rollback de retries fallidos (patrón\n * pi-dynamic-workflows).\n */\n\nexport class SharedStore {\n\tprivate readonly map = new Map<string, unknown>();\n\tprivate readonly agentDeltas = new Map<string, Record<string, unknown>>();\n\tprivate readonly priorValues = new Map<string, Map<string, { existed: boolean; value: unknown }>>();\n\n\tput(key: string, value: unknown): void {\n\t\tthis.map.set(key, value);\n\t}\n\n\tget<T = unknown>(key: string): T | undefined {\n\t\treturn this.map.get(key) as T | undefined;\n\t}\n\n\thas(key: string): boolean {\n\t\treturn this.map.has(key);\n\t}\n\n\tdelete(key: string): boolean {\n\t\treturn this.map.delete(key);\n\t}\n\n\tentries(): Array<[string, unknown]> {\n\t\treturn [...this.map.entries()];\n\t}\n\n\t/**\n\t * Escribe y registra el delta para `deltaKey` (run-unique).\n\t * Shadowea el valor previo solo la primera vez dentro de la ventana.\n\t */\n\ttrackPut(key: string, value: unknown, deltaKey: string): void {\n\t\tlet priors = this.priorValues.get(deltaKey);\n\t\tif (!priors) {\n\t\t\tpriors = new Map();\n\t\t\tthis.priorValues.set(deltaKey, priors);\n\t\t}\n\t\tif (!priors.has(key)) {\n\t\t\tpriors.set(\n\t\t\t\tkey,\n\t\t\t\tthis.map.has(key) ? { existed: true, value: this.map.get(key) } : { existed: false, value: undefined },\n\t\t\t);\n\t\t}\n\t\tthis.map.set(key, value);\n\t\tlet delta = this.agentDeltas.get(deltaKey);\n\t\tif (!delta) {\n\t\t\tdelta = {};\n\t\t\tthis.agentDeltas.set(deltaKey, delta);\n\t\t}\n\t\tdelta[key] = value;\n\t}\n\n\t/** Delta consolidado para journalizar (el agente terminó). */\n\tcommitDelta(deltaKey: string): Record<string, unknown> {\n\t\tconst delta = this.agentDeltas.get(deltaKey) ?? {};\n\t\tthis.agentDeltas.delete(deltaKey);\n\t\tthis.priorValues.delete(deltaKey);\n\t\treturn delta;\n\t}\n\n\t/** Rollback de las escrituras de un retry fallido. */\n\tdiscardDelta(deltaKey: string): void {\n\t\tconst priors = this.priorValues.get(deltaKey);\n\t\tif (priors) {\n\t\t\tfor (const [key, prior] of priors) {\n\t\t\t\tif (prior.existed) this.map.set(key, prior.value);\n\t\t\t\telse this.map.delete(key);\n\t\t\t}\n\t\t}\n\t\tthis.agentDeltas.delete(deltaKey);\n\t\tthis.priorValues.delete(deltaKey);\n\t}\n\n\t/** Replay aditivo de deltas en orden callSeq (resume). */\n\tapplyDelta(delta: Record<string, unknown>): void {\n\t\tfor (const [key, value] of Object.entries(delta)) {\n\t\t\tthis.map.set(key, value);\n\t\t}\n\t}\n\n\tget size(): number {\n\t\treturn this.map.size;\n\t}\n}\n"]}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SharedStore — KV en memoria compartido entre los subagentes de un run.
|
|
3
|
+
*
|
|
4
|
+
* Cada agente escribe deltas (`trackPut` con deltaKey `${runId}:${callIndex}`)
|
|
5
|
+
* que se journalizan; en resume se re-aplican en orden callSeq. Los valores
|
|
6
|
+
* previos se shadowean para rollback de retries fallidos (patrón
|
|
7
|
+
* pi-dynamic-workflows).
|
|
8
|
+
*/
|
|
9
|
+
export class SharedStore {
|
|
10
|
+
map = new Map();
|
|
11
|
+
agentDeltas = new Map();
|
|
12
|
+
priorValues = new Map();
|
|
13
|
+
put(key, value) {
|
|
14
|
+
this.map.set(key, value);
|
|
15
|
+
}
|
|
16
|
+
get(key) {
|
|
17
|
+
return this.map.get(key);
|
|
18
|
+
}
|
|
19
|
+
has(key) {
|
|
20
|
+
return this.map.has(key);
|
|
21
|
+
}
|
|
22
|
+
delete(key) {
|
|
23
|
+
return this.map.delete(key);
|
|
24
|
+
}
|
|
25
|
+
entries() {
|
|
26
|
+
return [...this.map.entries()];
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Escribe y registra el delta para `deltaKey` (run-unique).
|
|
30
|
+
* Shadowea el valor previo solo la primera vez dentro de la ventana.
|
|
31
|
+
*/
|
|
32
|
+
trackPut(key, value, deltaKey) {
|
|
33
|
+
let priors = this.priorValues.get(deltaKey);
|
|
34
|
+
if (!priors) {
|
|
35
|
+
priors = new Map();
|
|
36
|
+
this.priorValues.set(deltaKey, priors);
|
|
37
|
+
}
|
|
38
|
+
if (!priors.has(key)) {
|
|
39
|
+
priors.set(key, this.map.has(key) ? { existed: true, value: this.map.get(key) } : { existed: false, value: undefined });
|
|
40
|
+
}
|
|
41
|
+
this.map.set(key, value);
|
|
42
|
+
let delta = this.agentDeltas.get(deltaKey);
|
|
43
|
+
if (!delta) {
|
|
44
|
+
delta = {};
|
|
45
|
+
this.agentDeltas.set(deltaKey, delta);
|
|
46
|
+
}
|
|
47
|
+
delta[key] = value;
|
|
48
|
+
}
|
|
49
|
+
/** Delta consolidado para journalizar (el agente terminó). */
|
|
50
|
+
commitDelta(deltaKey) {
|
|
51
|
+
const delta = this.agentDeltas.get(deltaKey) ?? {};
|
|
52
|
+
this.agentDeltas.delete(deltaKey);
|
|
53
|
+
this.priorValues.delete(deltaKey);
|
|
54
|
+
return delta;
|
|
55
|
+
}
|
|
56
|
+
/** Rollback de las escrituras de un retry fallido. */
|
|
57
|
+
discardDelta(deltaKey) {
|
|
58
|
+
const priors = this.priorValues.get(deltaKey);
|
|
59
|
+
if (priors) {
|
|
60
|
+
for (const [key, prior] of priors) {
|
|
61
|
+
if (prior.existed)
|
|
62
|
+
this.map.set(key, prior.value);
|
|
63
|
+
else
|
|
64
|
+
this.map.delete(key);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
this.agentDeltas.delete(deltaKey);
|
|
68
|
+
this.priorValues.delete(deltaKey);
|
|
69
|
+
}
|
|
70
|
+
/** Replay aditivo de deltas en orden callSeq (resume). */
|
|
71
|
+
applyDelta(delta) {
|
|
72
|
+
for (const [key, value] of Object.entries(delta)) {
|
|
73
|
+
this.map.set(key, value);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
get size() {
|
|
77
|
+
return this.map.size;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=shared-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared-store.js","sourceRoot":"","sources":["../../../src/core/workflows/shared-store.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * SharedStore — KV en memoria compartido entre los subagentes de un run.\n *\n * Cada agente escribe deltas (`trackPut` con deltaKey `${runId}:${callIndex}`)\n * que se journalizan; en resume se re-aplican en orden callSeq. Los valores\n * previos se shadowean para rollback de retries fallidos (patrón\n * pi-dynamic-workflows).\n */\n\nexport class SharedStore {\n\tprivate readonly map = new Map<string, unknown>();\n\tprivate readonly agentDeltas = new Map<string, Record<string, unknown>>();\n\tprivate readonly priorValues = new Map<string, Map<string, { existed: boolean; value: unknown }>>();\n\n\tput(key: string, value: unknown): void {\n\t\tthis.map.set(key, value);\n\t}\n\n\tget<T = unknown>(key: string): T | undefined {\n\t\treturn this.map.get(key) as T | undefined;\n\t}\n\n\thas(key: string): boolean {\n\t\treturn this.map.has(key);\n\t}\n\n\tdelete(key: string): boolean {\n\t\treturn this.map.delete(key);\n\t}\n\n\tentries(): Array<[string, unknown]> {\n\t\treturn [...this.map.entries()];\n\t}\n\n\t/**\n\t * Escribe y registra el delta para `deltaKey` (run-unique).\n\t * Shadowea el valor previo solo la primera vez dentro de la ventana.\n\t */\n\ttrackPut(key: string, value: unknown, deltaKey: string): void {\n\t\tlet priors = this.priorValues.get(deltaKey);\n\t\tif (!priors) {\n\t\t\tpriors = new Map();\n\t\t\tthis.priorValues.set(deltaKey, priors);\n\t\t}\n\t\tif (!priors.has(key)) {\n\t\t\tpriors.set(\n\t\t\t\tkey,\n\t\t\t\tthis.map.has(key) ? { existed: true, value: this.map.get(key) } : { existed: false, value: undefined },\n\t\t\t);\n\t\t}\n\t\tthis.map.set(key, value);\n\t\tlet delta = this.agentDeltas.get(deltaKey);\n\t\tif (!delta) {\n\t\t\tdelta = {};\n\t\t\tthis.agentDeltas.set(deltaKey, delta);\n\t\t}\n\t\tdelta[key] = value;\n\t}\n\n\t/** Delta consolidado para journalizar (el agente terminó). */\n\tcommitDelta(deltaKey: string): Record<string, unknown> {\n\t\tconst delta = this.agentDeltas.get(deltaKey) ?? {};\n\t\tthis.agentDeltas.delete(deltaKey);\n\t\tthis.priorValues.delete(deltaKey);\n\t\treturn delta;\n\t}\n\n\t/** Rollback de las escrituras de un retry fallido. */\n\tdiscardDelta(deltaKey: string): void {\n\t\tconst priors = this.priorValues.get(deltaKey);\n\t\tif (priors) {\n\t\t\tfor (const [key, prior] of priors) {\n\t\t\t\tif (prior.existed) this.map.set(key, prior.value);\n\t\t\t\telse this.map.delete(key);\n\t\t\t}\n\t\t}\n\t\tthis.agentDeltas.delete(deltaKey);\n\t\tthis.priorValues.delete(deltaKey);\n\t}\n\n\t/** Replay aditivo de deltas en orden callSeq (resume). */\n\tapplyDelta(delta: Record<string, unknown>): void {\n\t\tfor (const [key, value] of Object.entries(delta)) {\n\t\t\tthis.map.set(key, value);\n\t\t}\n\t}\n\n\tget size(): number {\n\t\treturn this.map.size;\n\t}\n}\n"]}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SubagentHost — subagente de producción: crea una sesión real del SDK
|
|
3
|
+
* (createAgentSession) con el modelo resuelto, tools configuradas y límites.
|
|
4
|
+
*
|
|
5
|
+
* El subagente comparte el mismo runtime (memoria/vault/redacción) porque
|
|
6
|
+
* createAgentSession construye un DefaultResourceLoader con el mismo agentDir
|
|
7
|
+
* y el SettingsManager compartido → los subagentes heredan la memoria, el
|
|
8
|
+
* vault (@vault:) y la censura de secretos (adversarial §17).
|
|
9
|
+
*
|
|
10
|
+
* NOTA (seguridad, fairy-tales): los subagentes usan un agentDir PROPIO
|
|
11
|
+
* efímero cuando se pide aislamiento (nada de extensiones/paquetes dentro);
|
|
12
|
+
* las guardas del engine se re-inyectan explícitamente.
|
|
13
|
+
*/
|
|
14
|
+
import type { Model } from "@earendil-works/pi-ai";
|
|
15
|
+
import type { ToolDefinition } from "../extensions/types.ts";
|
|
16
|
+
import type { SubagentSession } from "./agent-runner.ts";
|
|
17
|
+
export interface CreateSubagentSessionOptions {
|
|
18
|
+
cwd: string;
|
|
19
|
+
agentDir: string;
|
|
20
|
+
modelSpec?: string;
|
|
21
|
+
tools?: string[];
|
|
22
|
+
customTools?: ToolDefinition[];
|
|
23
|
+
sessionName?: string;
|
|
24
|
+
instructions?: string;
|
|
25
|
+
/** Modelo de la sesión principal: los subagentes lo HEREDAN por defecto. */
|
|
26
|
+
hostModel?: {
|
|
27
|
+
provider: string;
|
|
28
|
+
modelId: string;
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Crea un subagente real. Devuelve la sesión con su disposición y el usage.
|
|
33
|
+
*/
|
|
34
|
+
export declare function createSubagentSession(options: CreateSubagentSessionOptions): Promise<SubagentSession>;
|
|
35
|
+
/** Thinking level del tier (workflows.models.<tier>Thinking); undefined = default. */
|
|
36
|
+
export declare function thinkingForTier(agentDir: string, tier: "cheap" | "main" | "judge"): string | undefined;
|
|
37
|
+
/**
|
|
38
|
+
* Resuelve el modelSpec de un subagente a un Model concreto.
|
|
39
|
+
* - "tier:cheap" → cascada:
|
|
40
|
+
* 1. workflows.models.cheap ("provider/model" directo)
|
|
41
|
+
* 2. workflows.models.cheapCandidates (lista del usuario, en orden)
|
|
42
|
+
* 3. DISCOVERY DINÁMICO: el modelo más barato con coste declarado de los
|
|
43
|
+
* proveedores CONECTADOS (refleja siempre el catálogo real del SDK)
|
|
44
|
+
* 4. fallback estático curado (solo si el discovery no encontró nada)
|
|
45
|
+
* - "tier:main"/"tier:judge" → workflows.models.main/judge, si no default.
|
|
46
|
+
* - "provider/model" → directo si está autenticado.
|
|
47
|
+
* Devuelve undefined → createAgentSession usa su resolución por defecto.
|
|
48
|
+
*/
|
|
49
|
+
export declare function resolveSubagentModel(agentDir: string, spec: string | undefined): Promise<Model<any> | undefined>;
|
|
50
|
+
//# sourceMappingURL=subagent-host.d.ts.map
|