@desplega.ai/agent-swarm 1.158.0 → 1.159.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{acp-adapter-xaq4n6pc.js → acp-adapter-qhch0n2v.js} +1 -1
- package/dist/{actions-p9hz5yat.js → actions-dtsh1mfb.js} +33 -29
- package/dist/{anthropic-messages-51pz26qe.js → anthropic-messages-f2h06k64.js} +8 -3
- package/dist/{app-g26wdcz6.js → app-y1b9srva.js} +10 -9
- package/dist/{assistant-wydfqkb3.js → assistant-31hwy5xj.js} +34 -30
- package/dist/{azure-openai-responses-8gksqtmz.js → azure-openai-responses-0k1mfax5.js} +12 -13
- package/dist/{boot-reembed-se8zmdcp.js → boot-reembed-48d2qpkt.js} +11 -11
- package/dist/{boot-reembed-g5ckg9yb.js → boot-reembed-w0bryhkr.js} +12 -12
- package/dist/{boot-scrub-logs-wfxqan61.js → boot-scrub-logs-t65wbrn7.js} +9 -8
- package/dist/{boot-seeds-s3q01xj3.js → boot-seeds-h7c32hvm.js} +12 -11
- package/dist/{claude-adapter-tv2x4f36.js → claude-adapter-1t6611ne.js} +26 -21
- package/dist/{claude-managed-adapter-41b2s7fd.js → claude-managed-adapter-werp659j.js} +4 -2
- package/dist/{claude-managed-setup-60g8aazx.js → claude-managed-setup-y6rdgbc1.js} +11 -2
- package/dist/claude-sdk-session-zhkyk8yw.js +29319 -0
- package/dist/{cli-vj6h9kc2.js → cli-0m7wct0d.js} +59 -1
- package/dist/{cli-wscdvcqz.js → cli-0n2e4x49.js} +1 -1
- package/dist/cli-0xqde53b.js +176 -0
- package/dist/{cli-xberxa1r.js → cli-10ym38qc.js} +2 -2
- package/dist/{cli-5b6b62tz.js → cli-13hw4z91.js} +1 -1
- package/dist/{cli-rqz8qbw7.js → cli-20035trh.js} +50 -18
- package/dist/{cli-k0g1sjzm.js → cli-31nkw3g3.js} +3 -3
- package/dist/cli-3gvrr8vj.js +1422 -0
- package/dist/{cli-c07r9a2m.js → cli-48527fpw.js} +9 -8
- package/dist/{cli-24k806sc.js → cli-4aj25szq.js} +2 -2
- package/dist/{cli-7gtvvpbh.js → cli-4tvgz99m.js} +7 -7
- package/dist/cli-503ya656.js +455 -0
- package/dist/{cli-cw9zck8j.js → cli-5f2hq128.js} +8 -4
- package/dist/{cli-s8eet254.js → cli-68bmme5p.js} +11078 -27833
- package/dist/{cli-ftfvggzx.js → cli-79aq9cgb.js} +794 -563
- package/dist/cli-7cxw8b60.js +14910 -0
- package/dist/cli-7kyk9jr3.js +22 -0
- package/dist/cli-7zttzetj.js +324 -0
- package/dist/{cli-y95wp3tg.js → cli-96qd5psa.js} +1 -1
- package/dist/{cli-g8djp6qe.js → cli-9yg65c1j.js} +22 -0
- package/dist/{cli-3gmcwfyx.js → cli-ardpzhjm.js} +5 -5
- package/dist/{cli-7s3syk22.js → cli-b6thtzac.js} +5 -5
- package/dist/{cli-00w2c66p.js → cli-bgv70kym.js} +13 -2
- package/dist/{cli-j55n64b6.js → cli-bv0a38v9.js} +163 -44
- package/dist/cli-ca2w7zv7.js +115 -0
- package/dist/cli-cpvsaqsw.js +333 -0
- package/dist/cli-cygyqj3b.js +754 -0
- package/dist/{cli-x24pshtq.js → cli-dvjpkkjd.js} +6 -6
- package/dist/{cli-5d10vd2m.js → cli-e0ndxhtk.js} +4 -4
- package/dist/{cli-4198qc9v.js → cli-e4xnc0qp.js} +15 -3
- package/dist/{cli-rjehvrts.js → cli-eg7cdg68.js} +8 -8
- package/dist/cli-ejpygnqz.js +3815 -0
- package/dist/{cli-fgqxwrpv.js → cli-fjtp3463.js} +1631 -127
- package/dist/{cli-zt1227k1.js → cli-fkqhbg8g.js} +5 -3
- package/dist/{cli-47m6dkd3.js → cli-g9df2m37.js} +409 -168
- package/dist/cli-gzyh0j0g.js +8455 -0
- package/dist/cli-hgqfttfc.js +183 -0
- package/dist/cli-hj65wsts.js +17755 -0
- package/dist/cli-j9z8mfx3.js +476 -0
- package/dist/{cli-aehm1rbq.js → cli-kc3dp84d.js} +1135 -61
- package/dist/{cli-h38x0qhg.js → cli-kdnehe0t.js} +4 -3
- package/dist/{cli-20cj37vt.js → cli-m4excttz.js} +136 -2216
- package/dist/{cli-8qmme6vd.js → cli-mg24hkt4.js} +2 -2
- package/dist/{cli-xhaeg2nc.js → cli-mzkqpxee.js} +1 -1
- package/dist/{cli-q67y4wzm.js → cli-phsaj4xq.js} +24 -2
- package/dist/{cli-pw9rj5t9.js → cli-pqetb83f.js} +1 -176
- package/dist/{cli-rj19hc34.js → cli-qjxy52w7.js} +1 -1
- package/dist/{cli-53sz8gkz.js → cli-qv4jv8bx.js} +1 -1
- package/dist/cli-qvnnx4ct.js +1051 -0
- package/dist/cli-rb9m6rpe.js +4980 -0
- package/dist/{cli-tt9k8r35.js → cli-rfezr056.js} +476 -909
- package/dist/{cli-ggm92wcn.js → cli-rgjprct3.js} +1 -0
- package/dist/{cli-9httdpyq.js → cli-rrqmqr1s.js} +1 -1
- package/dist/cli-rykfmgwg.js +102 -0
- package/dist/{cli-eetrvv91.js → cli-t3p77qk1.js} +1 -1
- package/dist/{cli-68w09sjw.js → cli-vn0qv9cj.js} +25 -88
- package/dist/{cli-987hg0aa.js → cli-vwbbaecp.js} +2 -2
- package/dist/cli-wd9hz40d.js +69 -0
- package/dist/{cli-j57qkrpq.js → cli-wgjx0q33.js} +13 -13
- package/dist/cli-xgpf00sk.js +2149 -0
- package/dist/{cli-mcnhgnn1.js → cli-ykk5jaax.js} +184 -26
- package/dist/{cli-aky8tctm.js → cli-z9x0sh1t.js} +3 -3
- package/dist/{cli-1hkrch3k.js → cli-zw65mab6.js} +5 -5
- package/dist/cli.js +38 -29
- package/dist/cloudflare-workers-ai-system-one-1sg586qv.js +46 -0
- package/dist/{codex-adapter-cnm8wk11.js → codex-adapter-jqfqqa21.js} +21 -14
- package/dist/{codex-hook-9hptmdhj.js → codex-hook-5eys3dya.js} +2 -2
- package/dist/{codex-session-runner-gfg547zj.js → codex-session-runner-zd341dsm.js} +21 -14
- package/dist/{commands-e3bn0p75.js → commands-vfsysz4s.js} +9 -8
- package/dist/{db-03v9kzr2.js → db-s3znhvbn.js} +15 -10
- package/dist/{dispatcher-nrmg8yht.js → dispatcher-5xn0c7rf.js} +32 -28
- package/dist/{dsh-adapter-k03nfqa6.js → dsh-adapter-894mgfvs.js} +3 -3
- package/dist/{e2b-93x1k0j5.js → e2b-ez07znam.js} +4 -3
- package/dist/execute-71ysgv35.js +965 -0
- package/dist/{google-generative-ai-bxmv50nc.js → google-generative-ai-1nfcdphp.js} +5 -4
- package/dist/{google-vertex-809af514.js → google-vertex-1tqcd7b1.js} +5 -4
- package/dist/{handlers-aqcedbyb.js → handlers-5w4jwycr.js} +35 -31
- package/dist/{hook-7vkskkre.js → hook-853bxrr6.js} +16 -13
- package/dist/{hook-ybvmrmhq.js → hook-z0hbxj85.js} +16 -13
- package/dist/{http-2eqa8t24.js → http-akc3wy3m.js} +600 -123
- package/dist/{index-f6cryxwe.js → index-4a5njnm1.js} +2 -59
- package/dist/{index-a3vn96n8.js → index-5sz16ksh.js} +187 -47
- package/dist/{index-c6zsv1bd.js → index-bjmjh9h4.js} +11 -11
- package/dist/{index-chgdkq36.js → index-cd151qkq.js} +32 -28
- package/dist/{index-x71bvq0p.js → index-k661dzzr.js} +33 -29
- package/dist/{index-1yks3qcr.js → index-ttpbhnjg.js} +32 -28
- package/dist/{keepalive-vtkf5n99.js → keepalive-8p9rpvz5.js} +11 -10
- package/dist/{lead-h3sp357x.js → lead-jp69z5h3.js} +49 -45
- package/dist/llama-cpp-classify-t2tccams.js +335 -0
- package/dist/{maintenance-jzeqtk3q.js → maintenance-fwx4ev0k.js} +12 -12
- package/dist/{mistral-conversations-zx0kn554.js → mistral-conversations-bhvwqcnk.js} +14 -17
- package/dist/{oauth-refresh-sweep-qp3dzmdp.js → oauth-refresh-sweep-cwcq1ctx.js} +10 -9
- package/dist/{onboard-tmsp0qbz.js → onboard-2b4q0t84.js} +6 -5
- package/dist/{openai-codex-responses-4vjqzvjp.js → openai-codex-responses-nekthgks.js} +21 -8
- package/dist/{openai-completions-9hjrqbw8.js → openai-completions-hxtzwj0s.js} +8 -11
- package/dist/{openai-responses-7b1pn0xt.js → openai-responses-w4r118w7.js} +22 -17
- package/dist/{opencode-adapter-x6x2da1z.js → opencode-adapter-zz7xvjj6.js} +6 -4
- package/dist/{openrouter-images-9f9ek4rw.js → openrouter-images-b6sqqjgn.js} +4 -6
- package/dist/{otel-impl-9mz73q65.js → otel-impl-g8rs4vwr.js} +1 -1
- package/dist/{pi-messages-txpjj39q.js → pi-messages-vxdt8v7j.js} +2 -1
- package/dist/{pi-mono-adapter-m6dvv0dz.js → pi-mono-adapter-n0me28wt.js} +29 -17
- package/dist/pricing-refresh-0v77385v.js +39 -0
- package/dist/{rbac-roles-c9wqz83x.js → rbac-roles-krjyazbj.js} +10 -9
- package/dist/{render-v2-gryrh9h8.js → render-v2-3wjsp9aw.js} +10 -9
- package/dist/runtime-ktjysacx.js +24 -0
- package/dist/{setup-q9720bt6.js → setup-yeqryke6.js} +6 -5
- package/dist/typesafe-system-one-96960jxp.js +27 -0
- package/dist/{virtual-modules-3htpgn8x.js → virtual-modules-dzdeq1sf.js} +21 -13
- package/dist/{work-objects-b76x7deb.js → work-objects-3pakpkw0.js} +35 -31
- package/dist/{worker-6vrxbv41.js → worker-85testgj.js} +49 -45
- package/openapi.json +863 -14
- package/package.json +9 -8
- package/src/be/db/agents.ts +20 -0
- package/src/be/db/tasks/human-free.ts +442 -0
- package/src/be/db/tasks/read.ts +56 -1
- package/src/be/db/tasks/write.ts +107 -11
- package/src/be/db.ts +89 -165
- package/src/be/harness-model-support.ts +182 -0
- package/src/be/human-free-drain.ts +67 -0
- package/src/be/migrations/182_task_human_free_flag.sql +63 -0
- package/src/be/migrations/183_human_free_reclassify_queue.sql +25 -0
- package/src/be/migrations/184_model_catalog.sql +120 -0
- package/src/be/model-catalog-store.ts +644 -0
- package/src/be/model-tier-keys.ts +31 -0
- package/src/be/model-tier-resolution.ts +489 -0
- package/src/be/model-validation.ts +112 -0
- package/src/be/models-catalog.ts +61 -7
- package/src/be/modelsdev-cache.json +82 -0
- package/src/be/modelsdev-cache.ts +2 -0
- package/src/be/pricing-refresh.ts +154 -12
- package/src/be/scripts/typecheck.ts +15 -0
- package/src/be/seed-scripts/catalog/task-failure-audit.ts +61 -9
- package/src/be/swarm-config-guard.ts +6 -0
- package/src/cli.tsx +10 -0
- package/src/commands/claude-managed-setup.ts +3 -1
- package/src/commands/runner.ts +76 -2
- package/src/extensions/contract-types.generated.ts +1 -1
- package/src/heartbeat/heartbeat.ts +64 -15
- package/src/heartbeat/templates.ts +2 -2
- package/src/http/agents.ts +49 -1
- package/src/http/index.ts +8 -0
- package/src/http/models-catalog.ts +357 -8
- package/src/http/poll.ts +45 -2
- package/src/http/schedules.ts +36 -6
- package/src/http/session-data.ts +2 -5
- package/src/http/stats.ts +6 -8
- package/src/http/tasks.ts +26 -1
- package/src/http/usage-cache.ts +56 -15
- package/src/http/workflows.ts +35 -8
- package/src/prompts/session-templates.ts +1 -0
- package/src/providers/claude-managed-models.ts +47 -161
- package/src/providers/codex-adapter.ts +4 -4
- package/src/providers/codex-models.ts +65 -198
- package/src/providers/reasoning-effort.ts +44 -140
- package/src/rbac/legacy-policy.ts +25 -0
- package/src/rbac/permissions.ts +10 -0
- package/src/scripts-runtime/sdk-allowlist.ts +4 -0
- package/src/scripts-runtime/types/stdlib.d.ts +15 -0
- package/src/scripts-runtime/types/swarm-extension.d.ts +3 -0
- package/src/scripts-runtime/types/swarm-sdk.d.ts +15 -0
- package/src/server.ts +6 -0
- package/src/slack/message-text.ts +56 -2
- package/src/slack/thread-buffer.ts +10 -2
- package/src/tests/agents-list-model-display.test.ts +4 -6
- package/src/tests/base-prompt.test.ts +3 -0
- package/src/tests/claude-adapter.test.ts +10 -0
- package/src/tests/claude-managed-adapter.test.ts +12 -18
- package/src/tests/codex-adapter.test.ts +2 -1
- package/src/tests/codex-gpt6-release.test.ts +66 -5
- package/src/tests/context-window.test.ts +7 -5
- package/src/tests/db-extraction-contract.test.ts +1 -0
- package/src/tests/db-task-read-contract.test.ts +5 -1
- package/src/tests/db-task-write-contract.test.ts +4 -1
- package/src/tests/docs-index-footprint.test.js +3 -3
- package/src/tests/explicit-model-validation.test.ts +332 -0
- package/src/tests/harness-model-support.test.ts +374 -0
- package/src/tests/heartbeat-checklist-config.test.ts +71 -0
- package/src/tests/heartbeat-checklist.test.ts +4 -2
- package/src/tests/heartbeat-orphan-resume.test.ts +48 -0
- package/src/tests/human-free-flag.test.ts +279 -0
- package/src/tests/human-free-oracle.ts +57 -0
- package/src/tests/human-free-reclassify.test.ts +669 -0
- package/src/tests/migration-046-budgets.test.ts +3 -3
- package/src/tests/model-catalog-migration.test.ts +134 -0
- package/src/tests/model-catalog-table.test.ts +249 -0
- package/src/tests/model-catalog-write-access.test.ts +387 -0
- package/src/tests/model-tier-resolution.test.ts +519 -0
- package/src/tests/models-catalog.test.ts +1 -1
- package/src/tests/multi-runtime-enabled-stats.test.ts +65 -1
- package/src/tests/package-publish.test.ts +137 -36
- package/src/tests/pricing-routes.test.ts +2 -2
- package/src/tests/rbac-engine.test.ts +42 -2
- package/src/tests/reasoning-effort.test.ts +109 -0
- package/src/tests/refresh-modelsdev-carryforward.test.ts +5 -5
- package/src/tests/runtime-model-catalog.test.ts +86 -0
- package/src/tests/script-connections.test.ts +5 -0
- package/src/tests/seed-scripts.test.ts +89 -0
- package/src/tests/session-costs.test.ts +14 -11
- package/src/tests/slack-message-text.test.ts +101 -0
- package/src/tests/slack-thread-buffer-context.test.ts +93 -0
- package/src/tests/task-cascade-fail.test.ts +148 -2
- package/src/tests/tool-annotations.test.ts +1 -1
- package/src/tests/usage-cache.test.ts +166 -0
- package/src/tests/workflow-executors.test.ts +5 -2
- package/src/tests/workflow-system-one-decision-review.test.ts +1021 -0
- package/src/tests/workflow-system-one-decision-save-warnings.test.ts +365 -0
- package/src/tests/workflow-system-one-decision.test.ts +2063 -0
- package/src/tools/model-catalog/index.ts +137 -0
- package/src/tools/schedules/create-schedule.ts +16 -1
- package/src/tools/schedules/patch-schedule.ts +17 -0
- package/src/tools/schedules/update-schedule.ts +17 -0
- package/src/tools/send-task.ts +14 -0
- package/src/tools/task-action.ts +12 -0
- package/src/tools/tool-config.ts +3 -1
- package/src/tools/workflows/create-workflow.ts +9 -2
- package/src/tools/workflows/patch-workflow-node.ts +17 -7
- package/src/tools/workflows/patch-workflow.ts +9 -2
- package/src/tools/workflows/update-workflow.ts +9 -2
- package/src/types.ts +30 -1
- package/src/utils/context-window.ts +47 -53
- package/src/utils/harness-cli-version.ts +115 -0
- package/src/utils/harness-model-error.ts +33 -0
- package/src/utils/runtime-model-catalog.ts +137 -0
- package/src/workflows/approval-resolution.ts +39 -0
- package/src/workflows/definition.ts +7 -0
- package/src/workflows/engine.ts +69 -1
- package/src/workflows/executors/agent-task.ts +9 -0
- package/src/workflows/executors/base.ts +53 -0
- package/src/workflows/executors/human-in-the-loop.ts +8 -8
- package/src/workflows/executors/index.ts +1 -0
- package/src/workflows/executors/registry.ts +2 -0
- package/src/workflows/executors/system-one-decision.ts +1232 -0
- package/src/workflows/executors/system-one-providers.ts +301 -0
- package/src/workflows/executors/workflow-llm.ts +13 -1
- package/src/workflows/readiness.ts +86 -0
- package/src/workflows/recovery.ts +12 -12
- package/src/workflows/resume.ts +23 -9
- package/templates/schedules/daily-blocker-digest/content.md +4 -5
- package/templates/skills/agent-browser/SKILL.md +6 -5
- package/templates/skills/agent-browser/content.md +6 -5
- package/templates/skills/heartbeat-runbook/config.json +1 -1
- package/templates/skills/heartbeat-runbook/content.md +2 -2
- package/templates/skills/swarm-scripts/SKILL.md +1 -1
- package/templates/skills/swarm-scripts/content.md +1 -1
- package/templates/skills/workflow-iterate/content.md +81 -1
- package/templates/workflows/claude-code-changelog-watch/content.md +2 -0
- package/templates/workflows/pr-review-status-sweep/content.md +2 -0
- package/dist/claude-sdk-session-t442qz6f.js +0 -39108
- package/dist/cli-0xjkj1j7.js +0 -61
- package/dist/cli-65hjmev5.js +0 -1141
- package/dist/cli-aw1jwp1r.js +0 -14075
- package/dist/cli-h967nb6r.js +0 -6603
- package/dist/cli-vapyk8sw.js +0 -20
- package/dist/cli-ws6rqycm.js +0 -247
- package/dist/pricing-refresh-v1cbr9te.js +0 -27
- package/src/providers/modelsdev-reasoning.json +0 -6453
- package/dist/{codex-login-x3jk4etn.js → codex-login-he9vrn90.js} +3 -3
- package/dist/{index-f24115ge.js → index-2wsdsnmm.js} +3 -3
|
@@ -0,0 +1,965 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Bm25Ranker,
|
|
3
|
+
CODEMODE_STORE_ENTRY_TYPE,
|
|
4
|
+
DEFAULT_TOOL_SEARCH_LIMIT,
|
|
5
|
+
MODEL_GLOBAL_DECLARATIONS,
|
|
6
|
+
combineUsage,
|
|
7
|
+
createToolSearchDocument,
|
|
8
|
+
getCodemodeCallableTools,
|
|
9
|
+
parseCodemodeSource,
|
|
10
|
+
renderToolSample,
|
|
11
|
+
toCodemodeDeclaration,
|
|
12
|
+
toCodemodeIdentifier
|
|
13
|
+
} from "./cli-qvnnx4ct.js";
|
|
14
|
+
import {
|
|
15
|
+
getCodemodeWorkerUrl,
|
|
16
|
+
getQuickJSWasmPath
|
|
17
|
+
} from "./cli-hj65wsts.js";
|
|
18
|
+
import"./cli-5bfdm1ah.js";
|
|
19
|
+
import"./cli-0m7wct0d.js";
|
|
20
|
+
import"./cli-rb9m6rpe.js";
|
|
21
|
+
import"./cli-pqetb83f.js";
|
|
22
|
+
import"./cli-bc05qbss.js";
|
|
23
|
+
|
|
24
|
+
// node_modules/@earendil-works/pi-coding-agent/dist/extensions/codemode/execute.js
|
|
25
|
+
import { randomBytes } from "node:crypto";
|
|
26
|
+
import { writeFile } from "node:fs/promises";
|
|
27
|
+
import { tmpdir } from "node:os";
|
|
28
|
+
import { join } from "node:path";
|
|
29
|
+
// node_modules/@earendil-works/pi-codemode/dist/runtime/host.js
|
|
30
|
+
import { Worker } from "node:worker_threads";
|
|
31
|
+
|
|
32
|
+
// node_modules/@earendil-works/pi-codemode/dist/wasm.js
|
|
33
|
+
import { readFile } from "node:fs/promises";
|
|
34
|
+
import { createRequire } from "node:module";
|
|
35
|
+
var modules = new Map;
|
|
36
|
+
function loadQuickJSWasm(path) {
|
|
37
|
+
const resolved = path ?? createRequire(import.meta.url).resolve("quickjs-wasi/quickjs.wasm");
|
|
38
|
+
let module = modules.get(resolved);
|
|
39
|
+
if (!module) {
|
|
40
|
+
const { WebAssembly } = globalThis;
|
|
41
|
+
module = readFile(resolved).then((bytes) => WebAssembly.compile(bytes)).catch((error) => {
|
|
42
|
+
modules.delete(resolved);
|
|
43
|
+
throw error;
|
|
44
|
+
});
|
|
45
|
+
modules.set(resolved, module);
|
|
46
|
+
}
|
|
47
|
+
return module;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// node_modules/@earendil-works/pi-codemode/dist/runtime/protocol.js
|
|
51
|
+
function isWorkerToHostMessage(value) {
|
|
52
|
+
if (typeof value !== "object" || value === null)
|
|
53
|
+
return false;
|
|
54
|
+
const type = value.type;
|
|
55
|
+
return type === "call" || type === "output" || type === "done" || type === "crash";
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// node_modules/@earendil-works/pi-codemode/dist/runtime/host.js
|
|
59
|
+
var DEFAULT_TIMEOUT_MS = 300000;
|
|
60
|
+
var IDENTIFIER = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
|
|
61
|
+
var RESERVED_GLOBALS = new Set([
|
|
62
|
+
"tools",
|
|
63
|
+
"ALL_TOOLS",
|
|
64
|
+
"console",
|
|
65
|
+
"text",
|
|
66
|
+
"image",
|
|
67
|
+
"exit",
|
|
68
|
+
"globalThis",
|
|
69
|
+
"store",
|
|
70
|
+
"load"
|
|
71
|
+
]);
|
|
72
|
+
function errorMessage(error) {
|
|
73
|
+
return error instanceof Error ? error.message : String(error);
|
|
74
|
+
}
|
|
75
|
+
function serializeStore(store) {
|
|
76
|
+
const serialized = {};
|
|
77
|
+
for (const [key, value] of Object.entries(store ?? {})) {
|
|
78
|
+
const json = JSON.stringify(value);
|
|
79
|
+
if (json !== undefined)
|
|
80
|
+
serialized[key] = json;
|
|
81
|
+
}
|
|
82
|
+
return serialized;
|
|
83
|
+
}
|
|
84
|
+
function parseStoreWrites(json) {
|
|
85
|
+
const writes = { set: {}, delete: [] };
|
|
86
|
+
for (const [key, value] of JSON.parse(json)) {
|
|
87
|
+
if (value === undefined)
|
|
88
|
+
writes.delete.push(key);
|
|
89
|
+
else
|
|
90
|
+
writes.set[key] = JSON.parse(value);
|
|
91
|
+
}
|
|
92
|
+
return writes;
|
|
93
|
+
}
|
|
94
|
+
function defaultWorkerUrl() {
|
|
95
|
+
return new URL(import.meta.url.endsWith(".ts") ? "./worker.ts" : "./worker.js", import.meta.url);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
class Execution {
|
|
99
|
+
promise;
|
|
100
|
+
resolveResult;
|
|
101
|
+
worker;
|
|
102
|
+
interrupt = new SharedArrayBuffer(4);
|
|
103
|
+
tools;
|
|
104
|
+
globals;
|
|
105
|
+
signal;
|
|
106
|
+
timer;
|
|
107
|
+
output = [];
|
|
108
|
+
calls = [];
|
|
109
|
+
pending = new Map;
|
|
110
|
+
finished = false;
|
|
111
|
+
constructor(options) {
|
|
112
|
+
this.promise = new Promise((resolve) => {
|
|
113
|
+
this.resolveResult = resolve;
|
|
114
|
+
});
|
|
115
|
+
this.tools = options.tools;
|
|
116
|
+
this.globals = options.globals;
|
|
117
|
+
this.signal = options.signal;
|
|
118
|
+
if (Number.isFinite(options.timeoutMs)) {
|
|
119
|
+
this.timer = setTimeout(() => {
|
|
120
|
+
this.finish({ kind: "timeout", message: `Execution timed out after ${options.timeoutMs} ms` });
|
|
121
|
+
}, options.timeoutMs);
|
|
122
|
+
}
|
|
123
|
+
if (options.signal) {
|
|
124
|
+
if (options.signal.aborted) {
|
|
125
|
+
this.onAbort();
|
|
126
|
+
} else {
|
|
127
|
+
options.signal.addEventListener("abort", this.onAbort, { once: true });
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
options.wasm.then((wasm) => this.start(options, wasm), (error) => {
|
|
131
|
+
this.finish({ kind: "sandbox", message: `Failed to load QuickJS: ${errorMessage(error)}` });
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
abort(message) {
|
|
135
|
+
this.finish({ kind: "aborted", message });
|
|
136
|
+
return this.promise;
|
|
137
|
+
}
|
|
138
|
+
start(options, wasm) {
|
|
139
|
+
if (this.finished)
|
|
140
|
+
return;
|
|
141
|
+
const workerData = {
|
|
142
|
+
code: options.code,
|
|
143
|
+
tools: [...options.tools.values()].map((tool) => ({
|
|
144
|
+
name: tool.name,
|
|
145
|
+
jsName: toCodemodeIdentifier(tool.name),
|
|
146
|
+
description: tool.description ?? ""
|
|
147
|
+
})),
|
|
148
|
+
globals: [...options.globals.values()].map((global) => ({
|
|
149
|
+
name: global.name,
|
|
150
|
+
spread: global.spread === true
|
|
151
|
+
})),
|
|
152
|
+
wasm,
|
|
153
|
+
memoryLimitBytes: options.memoryLimitBytes,
|
|
154
|
+
store: options.store,
|
|
155
|
+
interrupt: this.interrupt
|
|
156
|
+
};
|
|
157
|
+
let worker;
|
|
158
|
+
try {
|
|
159
|
+
worker = new Worker(options.workerUrl, { workerData });
|
|
160
|
+
} catch (error) {
|
|
161
|
+
this.finish({ kind: "sandbox", message: `Failed to start worker: ${errorMessage(error)}` });
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
this.worker = worker;
|
|
165
|
+
worker.on("message", (message) => this.handleMessage(message));
|
|
166
|
+
worker.on("error", (error) => {
|
|
167
|
+
this.finish({
|
|
168
|
+
kind: "sandbox",
|
|
169
|
+
name: error instanceof Error ? error.name : undefined,
|
|
170
|
+
message: errorMessage(error)
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
worker.on("exit", (code) => {
|
|
174
|
+
this.finish({ kind: "sandbox", message: `Worker exited with code ${code} before the script settled` });
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
onAbort = () => {
|
|
178
|
+
const reason = this.signal?.reason;
|
|
179
|
+
this.finish({ kind: "aborted", message: reason instanceof Error ? reason.message : "Execution aborted" });
|
|
180
|
+
};
|
|
181
|
+
post(message) {
|
|
182
|
+
this.worker?.postMessage(message);
|
|
183
|
+
}
|
|
184
|
+
handleMessage(message) {
|
|
185
|
+
if (this.finished || !isWorkerToHostMessage(message))
|
|
186
|
+
return;
|
|
187
|
+
switch (message.type) {
|
|
188
|
+
case "output":
|
|
189
|
+
this.output.push(message.item);
|
|
190
|
+
break;
|
|
191
|
+
case "call":
|
|
192
|
+
this.handleCall(message);
|
|
193
|
+
break;
|
|
194
|
+
case "done":
|
|
195
|
+
this.handleDone(message);
|
|
196
|
+
break;
|
|
197
|
+
case "crash":
|
|
198
|
+
this.finish({ kind: "sandbox", message: message.message });
|
|
199
|
+
break;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
handleDone(message) {
|
|
203
|
+
if (!message.ok) {
|
|
204
|
+
const parsed = JSON.parse(message.error);
|
|
205
|
+
this.finish({ kind: "script", ...parsed });
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
this.finish(undefined, message.value === undefined ? undefined : JSON.parse(message.value), message.writes);
|
|
209
|
+
}
|
|
210
|
+
async handleCall(message) {
|
|
211
|
+
const { id, name } = message;
|
|
212
|
+
const isTool = message.target === "tool";
|
|
213
|
+
const record = isTool ? { name, status: "cancelled", durationMs: 0 } : undefined;
|
|
214
|
+
if (record)
|
|
215
|
+
this.calls.push(record);
|
|
216
|
+
const pending = { record, startedAt: performance.now(), controller: new AbortController };
|
|
217
|
+
this.pending.set(id, pending);
|
|
218
|
+
let status;
|
|
219
|
+
let reply;
|
|
220
|
+
try {
|
|
221
|
+
const tool = (isTool ? this.tools : this.globals).get(name);
|
|
222
|
+
if (!tool)
|
|
223
|
+
throw new Error(`Unknown ${isTool ? "tool" : "global"} "${name}"`);
|
|
224
|
+
const args = message.args === undefined ? undefined : JSON.parse(message.args);
|
|
225
|
+
const value = await tool.execute(args, { signal: pending.controller.signal });
|
|
226
|
+
reply = { type: "result", id, ok: true, payload: value === undefined ? undefined : JSON.stringify(value) };
|
|
227
|
+
status = "ok";
|
|
228
|
+
} catch (error) {
|
|
229
|
+
reply = { type: "result", id, ok: false, payload: errorMessage(error) };
|
|
230
|
+
status = "error";
|
|
231
|
+
}
|
|
232
|
+
if (!this.pending.delete(id))
|
|
233
|
+
return;
|
|
234
|
+
if (record) {
|
|
235
|
+
record.status = status;
|
|
236
|
+
record.durationMs = performance.now() - pending.startedAt;
|
|
237
|
+
}
|
|
238
|
+
this.post(reply);
|
|
239
|
+
}
|
|
240
|
+
finish(error, value, writes) {
|
|
241
|
+
if (this.finished)
|
|
242
|
+
return;
|
|
243
|
+
this.finished = true;
|
|
244
|
+
clearTimeout(this.timer);
|
|
245
|
+
this.signal?.removeEventListener("abort", this.onAbort);
|
|
246
|
+
const now = performance.now();
|
|
247
|
+
for (const pending of this.pending.values()) {
|
|
248
|
+
if (pending.record)
|
|
249
|
+
pending.record.durationMs = now - pending.startedAt;
|
|
250
|
+
pending.controller.abort();
|
|
251
|
+
}
|
|
252
|
+
this.pending.clear();
|
|
253
|
+
const result = error ? { ok: false, error, output: this.output, calls: this.calls } : {
|
|
254
|
+
ok: true,
|
|
255
|
+
value,
|
|
256
|
+
output: this.output,
|
|
257
|
+
calls: this.calls,
|
|
258
|
+
storeWrites: writes === undefined ? { set: {}, delete: [] } : parseStoreWrites(writes)
|
|
259
|
+
};
|
|
260
|
+
if (!this.worker) {
|
|
261
|
+
this.resolveResult(result);
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
Atomics.store(new Int32Array(this.interrupt), 0, 1);
|
|
265
|
+
this.worker.terminate().catch(() => {
|
|
266
|
+
return;
|
|
267
|
+
}).then(() => this.resolveResult(result));
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
class CodemodeSandbox {
|
|
272
|
+
toolsByName = new Map;
|
|
273
|
+
globalsByName = new Map;
|
|
274
|
+
timeoutMs;
|
|
275
|
+
memoryLimitBytes;
|
|
276
|
+
wasm;
|
|
277
|
+
workerUrl;
|
|
278
|
+
running = new Set;
|
|
279
|
+
closed = false;
|
|
280
|
+
constructor(options = {}) {
|
|
281
|
+
this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
282
|
+
this.memoryLimitBytes = options.memoryLimitBytes;
|
|
283
|
+
this.wasm = options.wasm;
|
|
284
|
+
this.workerUrl = options.workerUrl ?? defaultWorkerUrl();
|
|
285
|
+
for (const tool of options.tools ?? [])
|
|
286
|
+
this.registerTool(tool);
|
|
287
|
+
const namespaces = new Set;
|
|
288
|
+
for (const global of options.globals ?? []) {
|
|
289
|
+
const parts = global.name.split(".");
|
|
290
|
+
if (parts.length > 2 || !parts.every((part) => IDENTIFIER.test(part)) || RESERVED_GLOBALS.has(parts[0])) {
|
|
291
|
+
throw new Error(`Invalid global name "${global.name}"`);
|
|
292
|
+
}
|
|
293
|
+
if (this.globalsByName.has(global.name))
|
|
294
|
+
throw new Error(`Global "${global.name}" is already registered`);
|
|
295
|
+
if (parts.length === 2)
|
|
296
|
+
namespaces.add(parts[0]);
|
|
297
|
+
this.globalsByName.set(global.name, global);
|
|
298
|
+
}
|
|
299
|
+
for (const name of namespaces) {
|
|
300
|
+
if (this.globalsByName.has(name))
|
|
301
|
+
throw new Error(`Global "${name}" conflicts with the namespace "${name}"`);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
registerTool(tool) {
|
|
305
|
+
if (this.toolsByName.has(tool.name))
|
|
306
|
+
throw new Error(`Tool "${tool.name}" is already registered`);
|
|
307
|
+
this.toolsByName.set(tool.name, tool);
|
|
308
|
+
}
|
|
309
|
+
unregisterTool(name) {
|
|
310
|
+
return this.toolsByName.delete(name);
|
|
311
|
+
}
|
|
312
|
+
get tools() {
|
|
313
|
+
return [...this.toolsByName.values()];
|
|
314
|
+
}
|
|
315
|
+
get globals() {
|
|
316
|
+
return [...this.globalsByName.values()];
|
|
317
|
+
}
|
|
318
|
+
execute(code, options = {}) {
|
|
319
|
+
if (this.closed)
|
|
320
|
+
return Promise.reject(new Error("Sandbox is closed"));
|
|
321
|
+
const execution = new Execution({
|
|
322
|
+
code,
|
|
323
|
+
tools: new Map(this.toolsByName),
|
|
324
|
+
globals: this.globalsByName,
|
|
325
|
+
timeoutMs: options.timeoutMs ?? this.timeoutMs,
|
|
326
|
+
signal: options.signal,
|
|
327
|
+
memoryLimitBytes: this.memoryLimitBytes,
|
|
328
|
+
store: serializeStore(options.store),
|
|
329
|
+
wasm: this.wasm === undefined ? loadQuickJSWasm() : Promise.resolve(this.wasm),
|
|
330
|
+
workerUrl: this.workerUrl
|
|
331
|
+
});
|
|
332
|
+
this.running.add(execution);
|
|
333
|
+
return execution.promise.finally(() => this.running.delete(execution));
|
|
334
|
+
}
|
|
335
|
+
async close() {
|
|
336
|
+
this.closed = true;
|
|
337
|
+
await Promise.all([...this.running].map((execution) => execution.abort("Sandbox closed")));
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
// node_modules/@earendil-works/pi-codemode/dist/runtime/prelude-source.js
|
|
341
|
+
var MAX_STORE_VALUE_CHARS = 256 * 1024;
|
|
342
|
+
var MAX_STORE_TOTAL_CHARS = 1024 * 1024;
|
|
343
|
+
var IMAGE_HELPER_EXPECTS = "image expects a non-empty image URL string, an object with image_url, or a raw MCP image block";
|
|
344
|
+
var PRELUDE_SOURCE = `(function (bridge, toolsJson, globalsJson, storeJson) {
|
|
345
|
+
"use strict";
|
|
346
|
+
const stringify = JSON.stringify;
|
|
347
|
+
const parse = JSON.parse;
|
|
348
|
+
const promiseThen = Promise.prototype.then;
|
|
349
|
+
const ErrorCtor = Error;
|
|
350
|
+
const TypeErrorCtor = TypeError;
|
|
351
|
+
const pending = new Map();
|
|
352
|
+
let nextId = 1;
|
|
353
|
+
let finished = false;
|
|
354
|
+
// Thrown by exit() to unwind the script after it already reported success.
|
|
355
|
+
const EXIT = Object.freeze({});
|
|
356
|
+
|
|
357
|
+
function done(ok, payload, writes) {
|
|
358
|
+
if (finished) return;
|
|
359
|
+
finished = true;
|
|
360
|
+
bridge("done", ok, payload, writes);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
function serialize(value) {
|
|
364
|
+
return value === undefined ? undefined : stringify(value);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// QuickJS stacks list frames only. Prefix "Name: message" like V8 so the
|
|
368
|
+
// text reads the same as a Node error, and drop this prelude's frames.
|
|
369
|
+
function errorText(error) {
|
|
370
|
+
const head = error.message ? error.name + ": " + error.message : String(error.name);
|
|
371
|
+
const frames =
|
|
372
|
+
typeof error.stack === "string"
|
|
373
|
+
? error.stack.split("\\n").filter((line) => line.trim() && !line.includes("codemode-prelude.js"))
|
|
374
|
+
: [];
|
|
375
|
+
return [head, ...frames].join("\\n");
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
function format(value) {
|
|
379
|
+
if (typeof value === "string") return value;
|
|
380
|
+
if (value instanceof ErrorCtor) return errorText(value);
|
|
381
|
+
try {
|
|
382
|
+
const json = stringify(value);
|
|
383
|
+
return json === undefined ? String(value) : json;
|
|
384
|
+
} catch {
|
|
385
|
+
return String(value);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
function describeError(error) {
|
|
390
|
+
if (error instanceof ErrorCtor) {
|
|
391
|
+
return stringify({ name: error.name, message: error.message, stack: errorText(error) });
|
|
392
|
+
}
|
|
393
|
+
return stringify({ message: format(error) });
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
function caller(kind, name, spread) {
|
|
397
|
+
return (...args) =>
|
|
398
|
+
new Promise((resolve, reject) => {
|
|
399
|
+
let json;
|
|
400
|
+
try {
|
|
401
|
+
json = serialize(spread ? args : args[0]);
|
|
402
|
+
} catch (error) {
|
|
403
|
+
reject(error);
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
const id = nextId++;
|
|
407
|
+
pending.set(id, { resolve, reject });
|
|
408
|
+
bridge(kind, id, name, json);
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
const tools = Object.create(null);
|
|
413
|
+
const allTools = [];
|
|
414
|
+
for (const { name, jsName, description } of parse(toolsJson)) {
|
|
415
|
+
const fn = caller("call", name);
|
|
416
|
+
// The first tool wins when two names normalize to the same identifier.
|
|
417
|
+
if (!(jsName in tools)) {
|
|
418
|
+
tools[jsName] = fn;
|
|
419
|
+
allTools.push(Object.freeze({ name: jsName, description }));
|
|
420
|
+
}
|
|
421
|
+
if (!(name in tools)) tools[name] = fn;
|
|
422
|
+
}
|
|
423
|
+
Object.freeze(tools);
|
|
424
|
+
Object.freeze(allTools);
|
|
425
|
+
|
|
426
|
+
const namespaces = new Map();
|
|
427
|
+
for (const { name, spread } of parse(globalsJson)) {
|
|
428
|
+
const fn = caller("global", name, spread);
|
|
429
|
+
const dot = name.indexOf(".");
|
|
430
|
+
if (dot === -1) {
|
|
431
|
+
Object.defineProperty(globalThis, name, { value: fn, enumerable: true });
|
|
432
|
+
continue;
|
|
433
|
+
}
|
|
434
|
+
const namespace = name.slice(0, dot);
|
|
435
|
+
if (!namespaces.has(namespace)) namespaces.set(namespace, Object.create(null));
|
|
436
|
+
namespaces.get(namespace)[name.slice(dot + 1)] = fn;
|
|
437
|
+
}
|
|
438
|
+
for (const [namespace, members] of namespaces) {
|
|
439
|
+
Object.defineProperty(globalThis, namespace, { value: Object.freeze(members), enumerable: true });
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
// key -> JSON text. Sizes count key and JSON characters.
|
|
443
|
+
const stored = new Map(Object.entries(parse(storeJson)));
|
|
444
|
+
const writes = new Map();
|
|
445
|
+
let storedChars = 0;
|
|
446
|
+
for (const [key, json] of stored) storedChars += key.length + json.length;
|
|
447
|
+
|
|
448
|
+
function checkKey(name, key) {
|
|
449
|
+
if (typeof key !== "string") throw new TypeError(name + "() key must be a string");
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
function store(key, value) {
|
|
453
|
+
checkKey("store", key);
|
|
454
|
+
const previous = stored.has(key) ? key.length + stored.get(key).length : 0;
|
|
455
|
+
if (value === undefined) {
|
|
456
|
+
stored.delete(key);
|
|
457
|
+
storedChars -= previous;
|
|
458
|
+
writes.set(key, undefined);
|
|
459
|
+
return;
|
|
460
|
+
}
|
|
461
|
+
let json;
|
|
462
|
+
try {
|
|
463
|
+
json = stringify(value);
|
|
464
|
+
} catch (error) {
|
|
465
|
+
throw new TypeError("store(" + stringify(key) + ") value is not JSON-serializable: " + format(error));
|
|
466
|
+
}
|
|
467
|
+
if (json === undefined) {
|
|
468
|
+
throw new TypeError("store(" + stringify(key) + ") value is not JSON-serializable");
|
|
469
|
+
}
|
|
470
|
+
if (json.length > ${MAX_STORE_VALUE_CHARS}) {
|
|
471
|
+
throw new RangeError("store(" + stringify(key) + ") value exceeds ${MAX_STORE_VALUE_CHARS} characters of JSON");
|
|
472
|
+
}
|
|
473
|
+
const next = storedChars - previous + key.length + json.length;
|
|
474
|
+
if (next > ${MAX_STORE_TOTAL_CHARS}) {
|
|
475
|
+
throw new RangeError("store is full: stored values would exceed ${MAX_STORE_TOTAL_CHARS} characters of JSON");
|
|
476
|
+
}
|
|
477
|
+
stored.set(key, json);
|
|
478
|
+
storedChars = next;
|
|
479
|
+
writes.set(key, json);
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
function load(key) {
|
|
483
|
+
checkKey("load", key);
|
|
484
|
+
const json = stored.get(key);
|
|
485
|
+
return json === undefined ? undefined : parse(json);
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
function serializeWrites() {
|
|
489
|
+
const entries = [];
|
|
490
|
+
for (const [key, json] of writes) entries.push(json === undefined ? [key] : [key, json]);
|
|
491
|
+
return stringify(entries);
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
Object.defineProperty(globalThis, "store", { value: store, enumerable: true });
|
|
495
|
+
Object.defineProperty(globalThis, "load", { value: load, enumerable: true });
|
|
496
|
+
|
|
497
|
+
// Primitives become their string form, everything else JSON.
|
|
498
|
+
function outputText(value) {
|
|
499
|
+
if (value === undefined || value === null || typeof value !== "object" && typeof value !== "function") {
|
|
500
|
+
return String(value);
|
|
501
|
+
}
|
|
502
|
+
const json = stringify(value);
|
|
503
|
+
return json === undefined ? String(value) : json;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
function text(value) {
|
|
507
|
+
let rendered;
|
|
508
|
+
try {
|
|
509
|
+
rendered = outputText(value);
|
|
510
|
+
} catch (error) {
|
|
511
|
+
throw new TypeErrorCtor(error instanceof ErrorCtor ? error.message : String(error));
|
|
512
|
+
}
|
|
513
|
+
if (!finished) bridge("output", "text", rendered);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
function imageUrl(value) {
|
|
517
|
+
if (typeof value === "string") return value;
|
|
518
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
519
|
+
throw new TypeErrorCtor(${JSON.stringify(IMAGE_HELPER_EXPECTS)});
|
|
520
|
+
}
|
|
521
|
+
if (value.image_url !== undefined) {
|
|
522
|
+
if (typeof value.image_url !== "string") throw new TypeErrorCtor(${JSON.stringify(IMAGE_HELPER_EXPECTS)});
|
|
523
|
+
return value.image_url;
|
|
524
|
+
}
|
|
525
|
+
if (typeof value.type !== "string") throw new TypeErrorCtor(${JSON.stringify(IMAGE_HELPER_EXPECTS)});
|
|
526
|
+
if (value.type !== "image") {
|
|
527
|
+
throw new TypeErrorCtor('image only accepts MCP image blocks, got "' + value.type + '"');
|
|
528
|
+
}
|
|
529
|
+
if (typeof value.data !== "string" || value.data === "") throw new TypeErrorCtor("image expected MCP image data");
|
|
530
|
+
if (value.data.toLowerCase().startsWith("data:")) return value.data;
|
|
531
|
+
const mimeType = typeof value.mimeType === "string" && value.mimeType ? value.mimeType : "application/octet-stream";
|
|
532
|
+
return "data:" + mimeType + ";base64," + value.data;
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
function image(value) {
|
|
536
|
+
const url = imageUrl(value);
|
|
537
|
+
if (url === "") throw new TypeErrorCtor(${JSON.stringify(IMAGE_HELPER_EXPECTS)});
|
|
538
|
+
const colon = url.indexOf(":");
|
|
539
|
+
const scheme = colon === -1 ? "" : url.slice(0, colon).toLowerCase();
|
|
540
|
+
if (scheme === "http" || scheme === "https") {
|
|
541
|
+
throw new TypeErrorCtor("remote image URLs are not supported in tool outputs. Pass a base64 data URI instead");
|
|
542
|
+
}
|
|
543
|
+
const comma = url.indexOf(",");
|
|
544
|
+
const header = comma === -1 ? [] : url.slice(colon + 1, comma).split(";");
|
|
545
|
+
if (scheme !== "data" || comma === -1 || header.slice(1).every((part) => part.toLowerCase() !== "base64")) {
|
|
546
|
+
throw new TypeErrorCtor("invalid image output. Pass a base64 data URI instead");
|
|
547
|
+
}
|
|
548
|
+
if (!finished) bridge("output", "image", url.slice(comma + 1), header[0] || "application/octet-stream");
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
function exit() {
|
|
552
|
+
let writesJson;
|
|
553
|
+
try {
|
|
554
|
+
writesJson = serializeWrites();
|
|
555
|
+
} catch (error) {
|
|
556
|
+
done(false, describeError(error));
|
|
557
|
+
throw EXIT;
|
|
558
|
+
}
|
|
559
|
+
done(true, undefined, writesJson);
|
|
560
|
+
throw EXIT;
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
const console = {};
|
|
564
|
+
for (const level of ["log", "info", "warn", "error", "debug"]) {
|
|
565
|
+
console[level] = (...args) => {
|
|
566
|
+
if (!finished) bridge("output", "text", args.map(format).join(" "));
|
|
567
|
+
};
|
|
568
|
+
}
|
|
569
|
+
Object.freeze(console);
|
|
570
|
+
|
|
571
|
+
Object.defineProperty(globalThis, "tools", { value: tools, enumerable: true });
|
|
572
|
+
Object.defineProperty(globalThis, "ALL_TOOLS", { value: allTools, enumerable: true });
|
|
573
|
+
Object.defineProperty(globalThis, "console", { value: console, enumerable: true });
|
|
574
|
+
Object.defineProperty(globalThis, "text", { value: text, enumerable: true });
|
|
575
|
+
Object.defineProperty(globalThis, "image", { value: image, enumerable: true });
|
|
576
|
+
Object.defineProperty(globalThis, "exit", { value: exit, enumerable: true });
|
|
577
|
+
|
|
578
|
+
return {
|
|
579
|
+
settle(id, ok, payload) {
|
|
580
|
+
const entry = pending.get(id);
|
|
581
|
+
if (!entry) return;
|
|
582
|
+
pending.delete(id);
|
|
583
|
+
if (!ok) {
|
|
584
|
+
entry.reject(new ErrorCtor(payload));
|
|
585
|
+
return;
|
|
586
|
+
}
|
|
587
|
+
let value;
|
|
588
|
+
try {
|
|
589
|
+
value = payload === undefined ? undefined : parse(payload);
|
|
590
|
+
} catch (error) {
|
|
591
|
+
entry.reject(error);
|
|
592
|
+
return;
|
|
593
|
+
}
|
|
594
|
+
entry.resolve(value);
|
|
595
|
+
},
|
|
596
|
+
run(fn) {
|
|
597
|
+
let promise;
|
|
598
|
+
try {
|
|
599
|
+
promise = fn(tools, console);
|
|
600
|
+
} catch (error) {
|
|
601
|
+
done(false, describeError(error));
|
|
602
|
+
return;
|
|
603
|
+
}
|
|
604
|
+
promiseThen.call(
|
|
605
|
+
promise,
|
|
606
|
+
(value) => {
|
|
607
|
+
let json;
|
|
608
|
+
try {
|
|
609
|
+
json = serialize(value);
|
|
610
|
+
} catch (error) {
|
|
611
|
+
done(false, describeError(error));
|
|
612
|
+
return;
|
|
613
|
+
}
|
|
614
|
+
done(true, json, serializeWrites());
|
|
615
|
+
},
|
|
616
|
+
(error) => {
|
|
617
|
+
done(false, describeError(error));
|
|
618
|
+
},
|
|
619
|
+
);
|
|
620
|
+
},
|
|
621
|
+
stalled() {
|
|
622
|
+
if (finished || pending.size > 0) return false;
|
|
623
|
+
done(
|
|
624
|
+
false,
|
|
625
|
+
stringify({
|
|
626
|
+
name: "Error",
|
|
627
|
+
message:
|
|
628
|
+
"The script is waiting on a promise that can never settle: no tool call is pending, and timers do not exist here.",
|
|
629
|
+
}),
|
|
630
|
+
);
|
|
631
|
+
return true;
|
|
632
|
+
},
|
|
633
|
+
};
|
|
634
|
+
})`;
|
|
635
|
+
// node_modules/@earendil-works/pi-coding-agent/dist/extensions/codemode/execute.js
|
|
636
|
+
var ARGS_PREVIEW_CHARS = 200;
|
|
637
|
+
var ERROR_PREVIEW_CHARS = 500;
|
|
638
|
+
var MAX_CONCURRENT_MODEL_CALLS = 4;
|
|
639
|
+
var CODEMODE_MEMORY_LIMIT_BYTES = 256 * 1024 * 1024;
|
|
640
|
+
var MODEL_TYPES = new Set(["chat", "image", "classifier"]);
|
|
641
|
+
function truncateText(text, maxChars) {
|
|
642
|
+
return text.length > maxChars ? `${text.slice(0, maxChars - 3)}...` : text;
|
|
643
|
+
}
|
|
644
|
+
function previewArgs(args) {
|
|
645
|
+
if (args === undefined)
|
|
646
|
+
return "";
|
|
647
|
+
try {
|
|
648
|
+
return truncateText(JSON.stringify(args) ?? "", ARGS_PREVIEW_CHARS);
|
|
649
|
+
} catch {
|
|
650
|
+
return "";
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
function textOf(result) {
|
|
654
|
+
return (result.content ?? []).filter((block) => block.type === "text").map((block) => block.text).join(`
|
|
655
|
+
`);
|
|
656
|
+
}
|
|
657
|
+
function toModelType(value) {
|
|
658
|
+
if (typeof value === "string" && MODEL_TYPES.has(value))
|
|
659
|
+
return value;
|
|
660
|
+
throw new Error(`Unknown model type ${JSON.stringify(value)}. Use "chat", "image", or "classifier".`);
|
|
661
|
+
}
|
|
662
|
+
function toProvider(value) {
|
|
663
|
+
if (value === undefined || value === null)
|
|
664
|
+
return;
|
|
665
|
+
if (typeof value !== "string")
|
|
666
|
+
throw new Error("provider must be a string");
|
|
667
|
+
return value;
|
|
668
|
+
}
|
|
669
|
+
function toModelInfo(model) {
|
|
670
|
+
const info = { ...model };
|
|
671
|
+
delete info.headers;
|
|
672
|
+
return info;
|
|
673
|
+
}
|
|
674
|
+
function createLimiter(limit) {
|
|
675
|
+
let active = 0;
|
|
676
|
+
const waiting = [];
|
|
677
|
+
return async (run) => {
|
|
678
|
+
if (active >= limit)
|
|
679
|
+
await new Promise((resolve) => waiting.push(resolve));
|
|
680
|
+
active++;
|
|
681
|
+
try {
|
|
682
|
+
return await run();
|
|
683
|
+
} finally {
|
|
684
|
+
active--;
|
|
685
|
+
waiting.shift()?.();
|
|
686
|
+
}
|
|
687
|
+
};
|
|
688
|
+
}
|
|
689
|
+
function isStoreEntryData(data) {
|
|
690
|
+
if (typeof data !== "object" || data === null)
|
|
691
|
+
return false;
|
|
692
|
+
const { set, delete: deleted } = data;
|
|
693
|
+
return typeof set === "object" && set !== null && Array.isArray(deleted) && deleted.every((key) => typeof key === "string");
|
|
694
|
+
}
|
|
695
|
+
function readCodemodeStore(branch) {
|
|
696
|
+
const store = new Map;
|
|
697
|
+
for (const entry of branch) {
|
|
698
|
+
if (entry.type !== "custom" || entry.customType !== CODEMODE_STORE_ENTRY_TYPE || !isStoreEntryData(entry.data)) {
|
|
699
|
+
continue;
|
|
700
|
+
}
|
|
701
|
+
for (const key of entry.data.delete)
|
|
702
|
+
store.delete(key);
|
|
703
|
+
for (const [key, value] of Object.entries(entry.data.set))
|
|
704
|
+
store.set(key, value);
|
|
705
|
+
}
|
|
706
|
+
return Object.fromEntries(store);
|
|
707
|
+
}
|
|
708
|
+
var DEFAULT_MAX_OUTPUT_TOKENS = 1e4;
|
|
709
|
+
var CHARS_PER_TOKEN = 4;
|
|
710
|
+
function valueText(value) {
|
|
711
|
+
if (typeof value === "string")
|
|
712
|
+
return value;
|
|
713
|
+
return JSON.stringify(value) ?? String(value);
|
|
714
|
+
}
|
|
715
|
+
function formatCallSummary(calls) {
|
|
716
|
+
if (calls.length === 0)
|
|
717
|
+
return "No tool calls were made.";
|
|
718
|
+
return `Tool calls made before the failure (they are not undone): ${calls.map((call) => `${call.name} (${call.status})`).join(", ")}`;
|
|
719
|
+
}
|
|
720
|
+
function formatError(result, calls) {
|
|
721
|
+
const { error } = result;
|
|
722
|
+
const head = error.kind === "script" ? error.stack ?? `${error.name ?? "Error"}: ${error.message}` : error.kind === "timeout" ? `Script timed out: ${error.message}` : error.kind === "aborted" ? `Script aborted: ${error.message}` : `Script sandbox failed: ${error.message}`;
|
|
723
|
+
return `${head}
|
|
724
|
+
|
|
725
|
+
${formatCallSummary(calls)}`;
|
|
726
|
+
}
|
|
727
|
+
async function spillOutput(text) {
|
|
728
|
+
const path = join(tmpdir(), `pi-codemode-${randomBytes(8).toString("hex")}.txt`);
|
|
729
|
+
try {
|
|
730
|
+
await writeFile(path, text);
|
|
731
|
+
return { path };
|
|
732
|
+
} catch (error) {
|
|
733
|
+
return { error: error instanceof Error ? error.message : String(error) };
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
async function truncateOutput(items, maxTokens) {
|
|
737
|
+
const texts = items.filter((item) => item.type === "text").map((item) => item.text);
|
|
738
|
+
const combined = texts.join(`
|
|
739
|
+
`);
|
|
740
|
+
const budget = maxTokens * CHARS_PER_TOKEN;
|
|
741
|
+
if (texts.length === 0 || combined.length <= budget)
|
|
742
|
+
return { items };
|
|
743
|
+
const headChars = Math.floor(budget / 2);
|
|
744
|
+
const tailChars = budget - headChars;
|
|
745
|
+
const removed = combined.length - headChars - tailChars;
|
|
746
|
+
const head = combined.slice(0, headChars);
|
|
747
|
+
const tail = tailChars > 0 ? combined.slice(-tailChars) : "";
|
|
748
|
+
let text = `Warning: truncated output (original token count: ${Math.ceil(combined.length / CHARS_PER_TOKEN)})
|
|
749
|
+
Total output lines: ${combined.split(`
|
|
750
|
+
`).length}
|
|
751
|
+
|
|
752
|
+
${head}…${Math.ceil(removed / CHARS_PER_TOKEN)} tokens truncated…${tail}`;
|
|
753
|
+
const spilled = await spillOutput(combined);
|
|
754
|
+
text += "path" in spilled ? `
|
|
755
|
+
|
|
756
|
+
[Full output: ${spilled.path} (read with offset/limit)]` : `
|
|
757
|
+
|
|
758
|
+
[Could not save the full output: ${spilled.error}]`;
|
|
759
|
+
return {
|
|
760
|
+
items: [{ type: "text", text }, ...items.filter((item) => item.type === "image")],
|
|
761
|
+
..."path" in spilled ? { fullOutputPath: spilled.path } : {}
|
|
762
|
+
};
|
|
763
|
+
}
|
|
764
|
+
function toScriptValue(tool, outcome) {
|
|
765
|
+
const { result } = outcome;
|
|
766
|
+
if (tool.outputSchema && result.structuredContent !== undefined)
|
|
767
|
+
return result.structuredContent;
|
|
768
|
+
const text = textOf(result);
|
|
769
|
+
if (outcome.isError)
|
|
770
|
+
throw new Error(text || `Tool "${tool.name}" failed`);
|
|
771
|
+
return text;
|
|
772
|
+
}
|
|
773
|
+
async function executeCodemode(toolCallId, input, signal, onUpdate, ctx, options = {}) {
|
|
774
|
+
const startedAt = performance.now();
|
|
775
|
+
const { code, options: sourceOptions } = parseCodemodeSource(input.code);
|
|
776
|
+
const calls = [];
|
|
777
|
+
let modelUsage;
|
|
778
|
+
const addModelUsage = (usage) => {
|
|
779
|
+
modelUsage = modelUsage ? combineUsage(modelUsage, usage) : usage;
|
|
780
|
+
};
|
|
781
|
+
const snapshot = () => ({ calls: calls.map((call) => ({ ...call })) });
|
|
782
|
+
const publish = () => onUpdate?.({ content: [], details: snapshot() });
|
|
783
|
+
const callable = ctx ? getCodemodeCallableTools(ctx.tools) : [];
|
|
784
|
+
const samples = new Map(callable.map((tool) => [tool.name, renderToolSample(toCodemodeDeclaration(tool))]));
|
|
785
|
+
const sandboxTools = callable.map((tool) => ({
|
|
786
|
+
name: tool.name,
|
|
787
|
+
description: samples.get(tool.name),
|
|
788
|
+
execute: async (args, { signal: callSignal }) => {
|
|
789
|
+
const record = {
|
|
790
|
+
id: `${toolCallId}/?`,
|
|
791
|
+
name: tool.name,
|
|
792
|
+
args: previewArgs(args),
|
|
793
|
+
status: "running"
|
|
794
|
+
};
|
|
795
|
+
calls.push(record);
|
|
796
|
+
publish();
|
|
797
|
+
const callStartedAt = performance.now();
|
|
798
|
+
if (!ctx)
|
|
799
|
+
throw new Error("Tool calls need a session");
|
|
800
|
+
const outcome = await ctx.executeTool(tool.name, args, { signal: callSignal });
|
|
801
|
+
record.id = outcome.toolCall.id;
|
|
802
|
+
record.durationMs = performance.now() - callStartedAt;
|
|
803
|
+
if (outcome.isError) {
|
|
804
|
+
record.status = callSignal.aborted ? "cancelled" : "error";
|
|
805
|
+
record.error = truncateText(textOf(outcome.result) || `Tool "${tool.name}" failed`, ERROR_PREVIEW_CHARS);
|
|
806
|
+
} else {
|
|
807
|
+
record.status = "ok";
|
|
808
|
+
}
|
|
809
|
+
publish();
|
|
810
|
+
return toScriptValue(tool, outcome);
|
|
811
|
+
}
|
|
812
|
+
}));
|
|
813
|
+
const sandbox = new CodemodeSandbox({
|
|
814
|
+
tools: sandboxTools,
|
|
815
|
+
globals: [
|
|
816
|
+
...createDiscoveryGlobals(callable, samples, options),
|
|
817
|
+
...options.models && ctx ? createModelGlobals(ctx.modelRegistry, toolCallId, calls, publish, addModelUsage) : []
|
|
818
|
+
],
|
|
819
|
+
timeoutMs: sourceOptions.timeoutMs ?? Number.POSITIVE_INFINITY,
|
|
820
|
+
memoryLimitBytes: CODEMODE_MEMORY_LIMIT_BYTES,
|
|
821
|
+
wasm: loadQuickJSWasm(getQuickJSWasmPath()),
|
|
822
|
+
workerUrl: getCodemodeWorkerUrl()
|
|
823
|
+
});
|
|
824
|
+
let result;
|
|
825
|
+
try {
|
|
826
|
+
const store = ctx ? readCodemodeStore(ctx.sessionManager.getBranch()) : {};
|
|
827
|
+
result = await sandbox.execute(code, { signal, store });
|
|
828
|
+
} finally {
|
|
829
|
+
await sandbox.close();
|
|
830
|
+
}
|
|
831
|
+
for (const call of calls) {
|
|
832
|
+
if (call.status === "running")
|
|
833
|
+
call.status = "cancelled";
|
|
834
|
+
}
|
|
835
|
+
const items = result.output.map((item) => item.type === "text" ? { type: "text", text: item.text } : item);
|
|
836
|
+
if (result.ok) {
|
|
837
|
+
const { set, delete: deleted } = result.storeWrites;
|
|
838
|
+
if (Object.keys(set).length > 0 || deleted.length > 0) {
|
|
839
|
+
options.appendEntry?.(CODEMODE_STORE_ENTRY_TYPE, { set, delete: deleted });
|
|
840
|
+
}
|
|
841
|
+
if (result.value !== undefined)
|
|
842
|
+
items.push({ type: "text", text: valueText(result.value) });
|
|
843
|
+
} else {
|
|
844
|
+
items.push({ type: "text", text: `Script error:
|
|
845
|
+
${formatError(result, calls)}` });
|
|
846
|
+
}
|
|
847
|
+
const truncated = await truncateOutput(items, sourceOptions.maxOutputTokens ?? DEFAULT_MAX_OUTPUT_TOKENS);
|
|
848
|
+
const wallTime = ((performance.now() - startedAt) / 1000).toFixed(1);
|
|
849
|
+
const header = `${result.ok ? "Script completed" : "Script failed"}
|
|
850
|
+
Wall time ${wallTime} seconds
|
|
851
|
+
Output:
|
|
852
|
+
`;
|
|
853
|
+
const details = snapshot();
|
|
854
|
+
if (truncated.fullOutputPath)
|
|
855
|
+
details.fullOutputPath = truncated.fullOutputPath;
|
|
856
|
+
return {
|
|
857
|
+
content: [{ type: "text", text: header }, ...truncated.items],
|
|
858
|
+
details,
|
|
859
|
+
...modelUsage ? { usage: modelUsage } : {},
|
|
860
|
+
...result.ok ? {} : { isError: true }
|
|
861
|
+
};
|
|
862
|
+
}
|
|
863
|
+
function createDiscoveryGlobals(tools, samples, options) {
|
|
864
|
+
const ranker = new Bm25Ranker;
|
|
865
|
+
const entry = (name) => ({ name: toCodemodeIdentifier(name), description: samples.get(name) ?? "" });
|
|
866
|
+
return [
|
|
867
|
+
{
|
|
868
|
+
name: "searchTools",
|
|
869
|
+
spread: true,
|
|
870
|
+
execute: (args) => {
|
|
871
|
+
const [query, searchOptions] = args;
|
|
872
|
+
if (typeof query !== "string")
|
|
873
|
+
throw new Error("searchTools() expects a query string");
|
|
874
|
+
const limit = searchOptions?.limit ?? DEFAULT_TOOL_SEARCH_LIMIT;
|
|
875
|
+
if (typeof limit !== "number" || !Number.isInteger(limit) || limit <= 0) {
|
|
876
|
+
throw new Error("searchTools() limit must be a positive integer");
|
|
877
|
+
}
|
|
878
|
+
const namespace = searchOptions?.namespace;
|
|
879
|
+
if (namespace !== undefined && namespace !== null && typeof namespace !== "string") {
|
|
880
|
+
throw new Error("searchTools() namespace must be a string");
|
|
881
|
+
}
|
|
882
|
+
const documents = tools.flatMap((tool) => {
|
|
883
|
+
const toolNamespace = options.getToolNamespace?.(tool.name);
|
|
884
|
+
if (namespace && toolNamespace?.name !== namespace)
|
|
885
|
+
return [];
|
|
886
|
+
return [createToolSearchDocument(tool, toolNamespace)];
|
|
887
|
+
});
|
|
888
|
+
return ranker.rank(query, documents, limit).map((match) => entry(match.name));
|
|
889
|
+
}
|
|
890
|
+
},
|
|
891
|
+
{
|
|
892
|
+
name: "describeTool",
|
|
893
|
+
spread: true,
|
|
894
|
+
execute: (args) => {
|
|
895
|
+
const [name] = args;
|
|
896
|
+
if (typeof name !== "string")
|
|
897
|
+
throw new Error("describeTool() expects a tool name");
|
|
898
|
+
const tool = tools.find((candidate) => candidate.name === name || toCodemodeIdentifier(candidate.name) === name);
|
|
899
|
+
return tool ? samples.get(tool.name) : undefined;
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
];
|
|
903
|
+
}
|
|
904
|
+
function createModelGlobals(models, toolCallId, calls, publish, addUsage) {
|
|
905
|
+
const limit = createLimiter(MAX_CONCURRENT_MODEL_CALLS);
|
|
906
|
+
let classifyCount = 0;
|
|
907
|
+
const implementations = {
|
|
908
|
+
"models.getModelsOfType": (args) => {
|
|
909
|
+
const [type, provider] = args;
|
|
910
|
+
return models.getModelsOfType(toModelType(type), toProvider(provider)).map(toModelInfo);
|
|
911
|
+
},
|
|
912
|
+
"models.getAvailableOfType": async (args, { signal }) => {
|
|
913
|
+
const [type, provider] = args;
|
|
914
|
+
const available = await models.getAvailableOfType(toModelType(type), toProvider(provider), { signal });
|
|
915
|
+
return available.map(toModelInfo);
|
|
916
|
+
},
|
|
917
|
+
"models.getModelOfType": (args) => {
|
|
918
|
+
const [type, provider, id] = args;
|
|
919
|
+
if (typeof provider !== "string" || typeof id !== "string") {
|
|
920
|
+
throw new Error("models.getModelOfType() expects a type, a provider, and an id");
|
|
921
|
+
}
|
|
922
|
+
const model = models.getModelOfType(toModelType(type), provider, id);
|
|
923
|
+
return model === undefined ? undefined : toModelInfo(model);
|
|
924
|
+
},
|
|
925
|
+
"models.classify": async (args, { signal }) => {
|
|
926
|
+
const [model, context] = args;
|
|
927
|
+
const ref = model;
|
|
928
|
+
if (typeof ref !== "object" || ref === null || typeof ref.provider !== "string" || typeof ref.id !== "string") {
|
|
929
|
+
throw new Error("models.classify() expects a model from models.getModelOfType() or models.getAvailableOfType()");
|
|
930
|
+
}
|
|
931
|
+
const resolved = models.getModelOfType("classifier", ref.provider, ref.id);
|
|
932
|
+
if (!resolved)
|
|
933
|
+
throw new Error(`Unknown classifier model "${ref.provider}/${ref.id}"`);
|
|
934
|
+
const record = {
|
|
935
|
+
id: `${toolCallId}/models.classify/${++classifyCount}`,
|
|
936
|
+
name: "models.classify",
|
|
937
|
+
args: `${resolved.provider}/${resolved.id}`,
|
|
938
|
+
status: "running"
|
|
939
|
+
};
|
|
940
|
+
calls.push(record);
|
|
941
|
+
publish();
|
|
942
|
+
const startedAt = performance.now();
|
|
943
|
+
const result = await limit(() => models.classify(resolved, context, { signal }));
|
|
944
|
+
record.durationMs = performance.now() - startedAt;
|
|
945
|
+
record.status = result.stopReason === "stop" ? "ok" : result.stopReason === "aborted" ? "cancelled" : "error";
|
|
946
|
+
if (result.errorMessage)
|
|
947
|
+
record.error = truncateText(result.errorMessage, ERROR_PREVIEW_CHARS);
|
|
948
|
+
if (result.usage) {
|
|
949
|
+
record.cost = result.usage.cost.total;
|
|
950
|
+
addUsage(result.usage);
|
|
951
|
+
}
|
|
952
|
+
publish();
|
|
953
|
+
return result;
|
|
954
|
+
}
|
|
955
|
+
};
|
|
956
|
+
return MODEL_GLOBAL_DECLARATIONS.map((declaration) => ({
|
|
957
|
+
name: declaration.name,
|
|
958
|
+
spread: true,
|
|
959
|
+
execute: implementations[declaration.name]
|
|
960
|
+
}));
|
|
961
|
+
}
|
|
962
|
+
export {
|
|
963
|
+
executeCodemode,
|
|
964
|
+
readCodemodeStore
|
|
965
|
+
};
|