@animalabs/agent-framework 0.23.2 → 0.24.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/README.md +212 -42
- package/dist/src/agent.d.ts +60 -9
- package/dist/src/agent.d.ts.map +1 -1
- package/dist/src/agent.js +92 -12
- package/dist/src/agent.js.map +1 -1
- package/dist/src/api/server.d.ts.map +1 -1
- package/dist/src/api/server.js +14 -12
- package/dist/src/api/server.js.map +1 -1
- package/dist/src/code-execution/engine.d.ts +177 -0
- package/dist/src/code-execution/engine.d.ts.map +1 -0
- package/dist/src/code-execution/engine.js +494 -0
- package/dist/src/code-execution/engine.js.map +1 -0
- package/dist/src/code-execution/index.d.ts +5 -10
- package/dist/src/code-execution/index.d.ts.map +1 -1
- package/dist/src/code-execution/index.js +5 -9
- package/dist/src/code-execution/index.js.map +1 -1
- package/dist/src/code-execution/isolate/calls.d.ts +114 -0
- package/dist/src/code-execution/isolate/calls.d.ts.map +1 -0
- package/dist/src/code-execution/isolate/calls.js +145 -0
- package/dist/src/code-execution/isolate/calls.js.map +1 -0
- package/dist/src/code-execution/isolate/child-entry.d.ts +2 -0
- package/dist/src/code-execution/isolate/child-entry.d.ts.map +1 -0
- package/dist/src/code-execution/isolate/child-entry.js +5 -0
- package/dist/src/code-execution/isolate/child-entry.js.map +1 -0
- package/dist/src/code-execution/isolate/child-main.d.ts +26 -0
- package/dist/src/code-execution/isolate/child-main.d.ts.map +1 -0
- package/dist/src/code-execution/isolate/child-main.js +132 -0
- package/dist/src/code-execution/isolate/child-main.js.map +1 -0
- package/dist/src/code-execution/isolate/child.d.ts +44 -0
- package/dist/src/code-execution/isolate/child.d.ts.map +1 -0
- package/dist/src/code-execution/isolate/child.js +315 -0
- package/dist/src/code-execution/isolate/child.js.map +1 -0
- package/dist/src/code-execution/isolate/frames.d.ts +80 -0
- package/dist/src/code-execution/isolate/frames.d.ts.map +1 -0
- package/dist/src/code-execution/isolate/frames.js +210 -0
- package/dist/src/code-execution/isolate/frames.js.map +1 -0
- package/dist/src/code-execution/isolate/output.d.ts +68 -0
- package/dist/src/code-execution/isolate/output.d.ts.map +1 -0
- package/dist/src/code-execution/isolate/output.js +143 -0
- package/dist/src/code-execution/isolate/output.js.map +1 -0
- package/dist/src/code-execution/isolate/prelude.d.ts +109 -0
- package/dist/src/code-execution/isolate/prelude.d.ts.map +1 -0
- package/dist/src/code-execution/isolate/prelude.js +401 -0
- package/dist/src/code-execution/isolate/prelude.js.map +1 -0
- package/dist/src/code-execution/isolate/protocol.d.ts +151 -0
- package/dist/src/code-execution/isolate/protocol.d.ts.map +1 -0
- package/dist/src/code-execution/isolate/protocol.js +150 -0
- package/dist/src/code-execution/isolate/protocol.js.map +1 -0
- package/dist/src/code-execution/isolate/render.d.ts +57 -0
- package/dist/src/code-execution/isolate/render.d.ts.map +1 -0
- package/dist/src/code-execution/isolate/render.js +214 -0
- package/dist/src/code-execution/isolate/render.js.map +1 -0
- package/dist/src/code-execution/isolate/runner.d.ts +250 -0
- package/dist/src/code-execution/isolate/runner.d.ts.map +1 -0
- package/dist/src/code-execution/isolate/runner.js +854 -0
- package/dist/src/code-execution/isolate/runner.js.map +1 -0
- package/dist/src/code-execution/isolate/scripts.d.ts +175 -0
- package/dist/src/code-execution/isolate/scripts.d.ts.map +1 -0
- package/dist/src/code-execution/isolate/scripts.js +357 -0
- package/dist/src/code-execution/isolate/scripts.js.map +1 -0
- package/dist/src/code-execution/quickjs.wasm +0 -0
- package/dist/src/code-execution/tool-definition.d.ts +93 -43
- package/dist/src/code-execution/tool-definition.d.ts.map +1 -1
- package/dist/src/code-execution/tool-definition.js +176 -142
- package/dist/src/code-execution/tool-definition.js.map +1 -1
- package/dist/src/deadline-timer.d.ts +3 -0
- package/dist/src/deadline-timer.d.ts.map +1 -1
- package/dist/src/deadline-timer.js +1 -1
- package/dist/src/deadline-timer.js.map +1 -1
- package/dist/src/framework.d.ts +1027 -440
- package/dist/src/framework.d.ts.map +1 -1
- package/dist/src/framework.js +4093 -2238
- package/dist/src/framework.js.map +1 -1
- package/dist/src/gate/event-gate.d.ts +28 -1
- package/dist/src/gate/event-gate.d.ts.map +1 -1
- package/dist/src/gate/event-gate.js +88 -10
- package/dist/src/gate/event-gate.js.map +1 -1
- package/dist/src/held-writes.d.ts +16 -3
- package/dist/src/held-writes.d.ts.map +1 -1
- package/dist/src/held-writes.js +16 -3
- package/dist/src/held-writes.js.map +1 -1
- package/dist/src/index.d.ts +6 -6
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +9 -8
- package/dist/src/index.js.map +1 -1
- package/dist/src/mcpl/channel-registry.d.ts +471 -75
- package/dist/src/mcpl/channel-registry.d.ts.map +1 -1
- package/dist/src/mcpl/channel-registry.js +1673 -337
- package/dist/src/mcpl/channel-registry.js.map +1 -1
- package/dist/src/mcpl/conversation-router.d.ts +12 -7
- package/dist/src/mcpl/conversation-router.d.ts.map +1 -1
- package/dist/src/mcpl/conversation-router.js +12 -7
- package/dist/src/mcpl/conversation-router.js.map +1 -1
- package/dist/src/mcpl/convert-block.d.ts.map +1 -1
- package/dist/src/mcpl/convert-block.js +9 -5
- package/dist/src/mcpl/convert-block.js.map +1 -1
- package/dist/src/mcpl/inbound-source.d.ts +50 -0
- package/dist/src/mcpl/inbound-source.d.ts.map +1 -1
- package/dist/src/mcpl/inbound-source.js +130 -0
- package/dist/src/mcpl/inbound-source.js.map +1 -1
- package/dist/src/mcpl/index.d.ts +2 -1
- package/dist/src/mcpl/index.d.ts.map +1 -1
- package/dist/src/mcpl/index.js +3 -2
- package/dist/src/mcpl/index.js.map +1 -1
- package/dist/src/mcpl/log-value.d.ts +6 -0
- package/dist/src/mcpl/log-value.d.ts.map +1 -1
- package/dist/src/mcpl/log-value.js +8 -0
- package/dist/src/mcpl/log-value.js.map +1 -1
- package/dist/src/mcpl/modern-connection.d.ts +15 -6
- package/dist/src/mcpl/modern-connection.d.ts.map +1 -1
- package/dist/src/mcpl/modern-connection.js +168 -53
- package/dist/src/mcpl/modern-connection.js.map +1 -1
- package/dist/src/mcpl/prose-grammar.d.ts +4 -5
- package/dist/src/mcpl/prose-grammar.d.ts.map +1 -1
- package/dist/src/mcpl/prose-grammar.js +4 -5
- package/dist/src/mcpl/prose-grammar.js.map +1 -1
- package/dist/src/mcpl/protocol-family.d.ts +97 -10
- package/dist/src/mcpl/protocol-family.d.ts.map +1 -1
- package/dist/src/mcpl/protocol-family.js +173 -16
- package/dist/src/mcpl/protocol-family.js.map +1 -1
- package/dist/src/mcpl/push-coalescer.d.ts +132 -14
- package/dist/src/mcpl/push-coalescer.d.ts.map +1 -1
- package/dist/src/mcpl/push-coalescer.js +227 -50
- package/dist/src/mcpl/push-coalescer.js.map +1 -1
- package/dist/src/mcpl/push-handler.d.ts +6 -1
- package/dist/src/mcpl/push-handler.d.ts.map +1 -1
- package/dist/src/mcpl/push-handler.js +4 -1
- package/dist/src/mcpl/push-handler.js.map +1 -1
- package/dist/src/mcpl/reference-fetcher.d.ts +2 -2
- package/dist/src/mcpl/reference-fetcher.d.ts.map +1 -1
- package/dist/src/mcpl/reference-fetcher.js +4 -4
- package/dist/src/mcpl/reference-fetcher.js.map +1 -1
- package/dist/src/mcpl/server-connection.d.ts +50 -21
- package/dist/src/mcpl/server-connection.d.ts.map +1 -1
- package/dist/src/mcpl/server-connection.js +158 -74
- package/dist/src/mcpl/server-connection.js.map +1 -1
- package/dist/src/mcpl/tags.d.ts +24 -0
- package/dist/src/mcpl/tags.d.ts.map +1 -1
- package/dist/src/mcpl/tags.js +33 -0
- package/dist/src/mcpl/tags.js.map +1 -1
- package/dist/src/mcpl/tool-result-normalize.d.ts +2 -1
- package/dist/src/mcpl/tool-result-normalize.d.ts.map +1 -1
- package/dist/src/mcpl/tool-result-normalize.js.map +1 -1
- package/dist/src/mcpl/transport.d.ts +55 -7
- package/dist/src/mcpl/transport.d.ts.map +1 -1
- package/dist/src/mcpl/transport.js +163 -34
- package/dist/src/mcpl/transport.js.map +1 -1
- package/dist/src/mcpl/types.d.ts +22 -6
- package/dist/src/mcpl/types.d.ts.map +1 -1
- package/dist/src/mcpl/types.js.map +1 -1
- package/dist/src/module-registry.d.ts +4 -2
- package/dist/src/module-registry.d.ts.map +1 -1
- package/dist/src/module-registry.js +100 -13
- package/dist/src/module-registry.js.map +1 -1
- package/dist/src/modules/discord/index.d.ts.map +1 -1
- package/dist/src/modules/discord/index.js +8 -13
- package/dist/src/modules/discord/index.js.map +1 -1
- package/dist/src/modules/history/index.d.ts.map +1 -1
- package/dist/src/modules/history/index.js +27 -4
- package/dist/src/modules/history/index.js.map +1 -1
- package/dist/src/modules/history/semantic.d.ts +15 -3
- package/dist/src/modules/history/semantic.d.ts.map +1 -1
- package/dist/src/modules/history/semantic.js +27 -5
- package/dist/src/modules/history/semantic.js.map +1 -1
- package/dist/src/modules/index.d.ts +1 -1
- package/dist/src/modules/index.d.ts.map +1 -1
- package/dist/src/modules/index.js.map +1 -1
- package/dist/src/modules/unknown-tool.d.ts +4 -1
- package/dist/src/modules/unknown-tool.d.ts.map +1 -1
- package/dist/src/modules/unknown-tool.js +4 -1
- package/dist/src/modules/unknown-tool.js.map +1 -1
- package/dist/src/modules/workspace/branch-intent.d.ts +3 -1
- package/dist/src/modules/workspace/branch-intent.d.ts.map +1 -1
- package/dist/src/modules/workspace/branch-intent.js +3 -1
- package/dist/src/modules/workspace/branch-intent.js.map +1 -1
- package/dist/src/modules/workspace/edit-plan.d.ts +265 -0
- package/dist/src/modules/workspace/edit-plan.d.ts.map +1 -0
- package/dist/src/modules/workspace/edit-plan.js +794 -0
- package/dist/src/modules/workspace/edit-plan.js.map +1 -0
- package/dist/src/modules/workspace/edit-text.d.ts +117 -0
- package/dist/src/modules/workspace/edit-text.d.ts.map +1 -0
- package/dist/src/modules/workspace/edit-text.js +584 -0
- package/dist/src/modules/workspace/edit-text.js.map +1 -0
- package/dist/src/modules/workspace/effects.d.ts +5 -4
- package/dist/src/modules/workspace/effects.d.ts.map +1 -1
- package/dist/src/modules/workspace/effects.js +78 -25
- package/dist/src/modules/workspace/effects.js.map +1 -1
- package/dist/src/modules/workspace/index.d.ts +484 -61
- package/dist/src/modules/workspace/index.d.ts.map +1 -1
- package/dist/src/modules/workspace/index.js +2173 -645
- package/dist/src/modules/workspace/index.js.map +1 -1
- package/dist/src/modules/workspace/observe.d.ts +213 -38
- package/dist/src/modules/workspace/observe.d.ts.map +1 -1
- package/dist/src/modules/workspace/observe.js +416 -36
- package/dist/src/modules/workspace/observe.js.map +1 -1
- package/dist/src/modules/workspace/reconcile.d.ts.map +1 -1
- package/dist/src/modules/workspace/reconcile.js +15 -8
- package/dist/src/modules/workspace/reconcile.js.map +1 -1
- package/dist/src/modules/workspace/text.d.ts +32 -0
- package/dist/src/modules/workspace/text.d.ts.map +1 -0
- package/dist/src/modules/workspace/text.js +67 -0
- package/dist/src/modules/workspace/text.js.map +1 -0
- package/dist/src/modules/workspace/types.d.ts +210 -6
- package/dist/src/modules/workspace/types.d.ts.map +1 -1
- package/dist/src/modules/workspace/types.js.map +1 -1
- package/dist/src/modules/workspace/watcher.d.ts +3 -2
- package/dist/src/modules/workspace/watcher.d.ts.map +1 -1
- package/dist/src/modules/workspace/watcher.js.map +1 -1
- package/dist/src/operator-log.d.ts +52 -24
- package/dist/src/operator-log.d.ts.map +1 -1
- package/dist/src/operator-log.js.map +1 -1
- package/dist/src/recovery/discord-awareness-outbox.d.ts +496 -72
- package/dist/src/recovery/discord-awareness-outbox.d.ts.map +1 -1
- package/dist/src/recovery/discord-awareness-outbox.js +1196 -289
- package/dist/src/recovery/discord-awareness-outbox.js.map +1 -1
- package/dist/src/recovery/offline-branch.d.ts +26 -1
- package/dist/src/recovery/offline-branch.d.ts.map +1 -1
- package/dist/src/recovery/offline-branch.js +164 -39
- package/dist/src/recovery/offline-branch.js.map +1 -1
- package/dist/src/recovery/recover-cli.js +23 -4
- package/dist/src/recovery/recover-cli.js.map +1 -1
- package/dist/src/send-tools.d.ts +11 -0
- package/dist/src/send-tools.d.ts.map +1 -0
- package/dist/src/send-tools.js +11 -0
- package/dist/src/send-tools.js.map +1 -0
- package/dist/src/tool-result-guard.d.ts +4 -3
- package/dist/src/tool-result-guard.d.ts.map +1 -1
- package/dist/src/tool-result-guard.js +5 -4
- package/dist/src/tool-result-guard.js.map +1 -1
- package/dist/src/tool-result-history.d.ts +1 -1
- package/dist/src/tool-result-history.js +1 -1
- package/dist/src/tune-out/coordinator.d.ts +21 -0
- package/dist/src/tune-out/coordinator.d.ts.map +1 -1
- package/dist/src/tune-out/coordinator.js +139 -37
- package/dist/src/tune-out/coordinator.js.map +1 -1
- package/dist/src/types/agent.d.ts +4 -0
- package/dist/src/types/agent.d.ts.map +1 -1
- package/dist/src/types/events.d.ts +62 -9
- package/dist/src/types/events.d.ts.map +1 -1
- package/dist/src/types/framework.d.ts +62 -58
- package/dist/src/types/framework.d.ts.map +1 -1
- package/dist/src/types/module.d.ts +40 -8
- package/dist/src/types/module.d.ts.map +1 -1
- package/dist/src/types/trace.d.ts +111 -10
- package/dist/src/types/trace.d.ts.map +1 -1
- package/dist/src/usage/types.d.ts +16 -0
- package/dist/src/usage/types.d.ts.map +1 -1
- package/dist/src/usage/usage-tracker.d.ts +14 -1
- package/dist/src/usage/usage-tracker.d.ts.map +1 -1
- package/dist/src/usage/usage-tracker.js +81 -41
- package/dist/src/usage/usage-tracker.js.map +1 -1
- package/package.json +6 -5
- package/src/agent.ts +93 -12
- package/src/api/server.ts +14 -12
- package/src/code-execution/engine.ts +595 -0
- package/src/code-execution/index.ts +5 -17
- package/src/code-execution/isolate/calls.ts +199 -0
- package/src/code-execution/isolate/child-entry.ts +5 -0
- package/src/code-execution/isolate/child-main.ts +132 -0
- package/src/code-execution/isolate/child.ts +327 -0
- package/src/code-execution/isolate/frames.ts +209 -0
- package/src/code-execution/isolate/output.ts +161 -0
- package/src/code-execution/isolate/prelude.ts +409 -0
- package/src/code-execution/isolate/protocol.ts +240 -0
- package/src/code-execution/isolate/render.ts +230 -0
- package/src/code-execution/isolate/runner.ts +911 -0
- package/src/code-execution/isolate/scripts.ts +479 -0
- package/src/code-execution/quickjs.wasm +0 -0
- package/src/code-execution/quickjs.wasm.LICENSES +149 -0
- package/src/code-execution/tool-definition.ts +236 -167
- package/src/deadline-timer.ts +1 -1
- package/src/framework.ts +4468 -2418
- package/src/gate/event-gate.ts +78 -11
- package/src/held-writes.ts +17 -3
- package/src/index.ts +30 -22
- package/src/mcpl/channel-registry.ts +1825 -368
- package/src/mcpl/conversation-router.ts +12 -7
- package/src/mcpl/convert-block.ts +9 -5
- package/src/mcpl/inbound-source.ts +131 -0
- package/src/mcpl/index.ts +4 -2
- package/src/mcpl/log-value.ts +9 -0
- package/src/mcpl/modern-connection.ts +162 -53
- package/src/mcpl/prose-grammar.ts +4 -5
- package/src/mcpl/protocol-family.ts +199 -21
- package/src/mcpl/push-coalescer.ts +306 -62
- package/src/mcpl/push-handler.ts +10 -2
- package/src/mcpl/reference-fetcher.ts +4 -4
- package/src/mcpl/server-connection.ts +180 -79
- package/src/mcpl/tags.ts +36 -0
- package/src/mcpl/tool-result-normalize.ts +2 -1
- package/src/mcpl/transport.ts +162 -33
- package/src/mcpl/types.ts +23 -6
- package/src/module-registry.ts +92 -13
- package/src/modules/discord/index.ts +8 -13
- package/src/modules/history/index.ts +25 -3
- package/src/modules/history/semantic.ts +29 -6
- package/src/modules/index.ts +1 -0
- package/src/modules/unknown-tool.ts +4 -1
- package/src/modules/workspace/branch-intent.ts +3 -1
- package/src/modules/workspace/edit-plan.ts +954 -0
- package/src/modules/workspace/edit-text.ts +618 -0
- package/src/modules/workspace/effects.ts +70 -19
- package/src/modules/workspace/index.ts +2247 -642
- package/src/modules/workspace/observe.ts +465 -56
- package/src/modules/workspace/reconcile.ts +14 -7
- package/src/modules/workspace/text.ts +68 -0
- package/src/modules/workspace/types.ts +211 -6
- package/src/modules/workspace/watcher.ts +3 -2
- package/src/operator-log.ts +47 -19
- package/src/recovery/discord-awareness-outbox.ts +1500 -356
- package/src/recovery/offline-branch.ts +189 -55
- package/src/recovery/recover-cli.ts +25 -4
- package/src/send-tools.ts +11 -0
- package/src/tool-result-guard.ts +6 -5
- package/src/tool-result-history.ts +1 -1
- package/src/tune-out/coordinator.ts +163 -42
- package/src/types/agent.ts +4 -0
- package/src/types/events.ts +62 -9
- package/src/types/framework.ts +62 -58
- package/src/types/module.ts +40 -8
- package/src/types/trace.ts +121 -15
- package/src/usage/types.ts +16 -0
- package/src/usage/usage-tracker.ts +86 -43
- package/dist/src/code-execution/py-runner.d.ts +0 -191
- package/dist/src/code-execution/py-runner.d.ts.map +0 -1
- package/dist/src/code-execution/py-runner.js +0 -655
- package/dist/src/code-execution/py-runner.js.map +0 -1
- package/dist/src/code-execution/runtime-py.d.ts +0 -50
- package/dist/src/code-execution/runtime-py.d.ts.map +0 -1
- package/dist/src/code-execution/runtime-py.js +0 -677
- package/dist/src/code-execution/runtime-py.js.map +0 -1
- package/dist/src/mcpl/prose-stream-router.d.ts +0 -88
- package/dist/src/mcpl/prose-stream-router.d.ts.map +0 -1
- package/dist/src/mcpl/prose-stream-router.js +0 -291
- package/dist/src/mcpl/prose-stream-router.js.map +0 -1
- package/src/code-execution/py-runner.ts +0 -791
- package/src/code-execution/runtime-py.ts +0 -677
- package/src/mcpl/prose-stream-router.ts +0 -268
|
@@ -0,0 +1,479 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Every agent's scripts: one kind of script, which runs in its agent's turn
|
|
3
|
+
* and, past its bound, yields with its output so far and keeps running. The
|
|
4
|
+
* agent then waits on it, stops it, or leaves it.
|
|
5
|
+
*
|
|
6
|
+
* - A left script that finishes cleanly, or that its agent stopped, says
|
|
7
|
+
* nothing; its result waits for a `wait` or a `list`, kept for the agent's
|
|
8
|
+
* newest ended scripts. One that fails, crashes or is stopped at its limit
|
|
9
|
+
* wakes its agent with its ending.
|
|
10
|
+
* - Only the primary agent's scripts outlive a turn (any agent's, when no
|
|
11
|
+
* primary agent is named). Another agent's yield says so, and at its turn's
|
|
12
|
+
* end its running scripts are stopped, as "stopped at its limit". That stop
|
|
13
|
+
* wakes no one, since the agent was told at the yield.
|
|
14
|
+
* - A turn that ends abnormally (a stream cancelled, an error, a quiesce)
|
|
15
|
+
* while a call still watches its script stops the script quietly if it
|
|
16
|
+
* hasn't returned yet; a wait it abandons leaves its script running, so a
|
|
17
|
+
* later failure still wakes the agent. A return made just before such an
|
|
18
|
+
* end counts as made, though its result is lost with the turn's.
|
|
19
|
+
* - An agent has at most `maxRunning` scripts running, and the host at most
|
|
20
|
+
* its capacity of children.
|
|
21
|
+
* - `wake_agent()` keeps today's spacing and cap: an early wake waits for its
|
|
22
|
+
* turn rather than being dropped, and past the cap it's refused. A wake
|
|
23
|
+
* still waiting for its turn when its script ends is never sent.
|
|
24
|
+
*
|
|
25
|
+
* The framework supplies what this can't know: the agent's tools now, the
|
|
26
|
+
* dispatcher a script's calls go through, and how to wake an agent.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
import { ChildCapacity, ScriptRun, type CallAnswer, type Ending, type ScriptRunOptions, type ToolAnswer } from './runner.js';
|
|
30
|
+
import type { CallSummary } from './calls.js';
|
|
31
|
+
import type { OutputBounds, OutputWindow } from './output.js';
|
|
32
|
+
import type { PreludeTool } from './prelude.js';
|
|
33
|
+
import { glimpse } from './render.js';
|
|
34
|
+
|
|
35
|
+
/** The run or wait call watching a script: its turn, which the script's calls carry, and whether one of them ended that turn. */
|
|
36
|
+
export interface ScriptWatch {
|
|
37
|
+
turnId?: number;
|
|
38
|
+
endTurn: boolean;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** What the framework keeps with a script, handed back with each of its calls. */
|
|
42
|
+
export interface ScriptCallContext {
|
|
43
|
+
/** RFC-007: what the script's calls are attributed to, its run call's origin. */
|
|
44
|
+
origin?: unknown;
|
|
45
|
+
/** The call watching the script when this call reached the host (`host.dispatch`), if one was: the call carries its turn. One the script made while watched that waited, with 16 of its calls already out, takes the watch as it stood when it went out, not when the script made it. */
|
|
46
|
+
watch?: ScriptWatch;
|
|
47
|
+
/** The call watching the script now, if one is: a result that ends the turn ends it at that call's return. Without it, `watch`. */
|
|
48
|
+
watching?(): ScriptWatch | undefined;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface ScriptsHost {
|
|
52
|
+
/** The tools a script of this agent may call now, without code_execution itself. */
|
|
53
|
+
tools(agentName: string): PreludeTool[];
|
|
54
|
+
/** The bridge: dispatch one of the script's calls as its agent's, through the ordinary dispatcher. Never rejects. */
|
|
55
|
+
dispatch(agentName: string, toolName: string, argsJson: string, context: ScriptCallContext): Promise<ToolAnswer>;
|
|
56
|
+
/** Wake the agent with this text: a script's wake_agent() payload, or a left script's ending. `label` names this wake, for a spilled copy. */
|
|
57
|
+
wake(agentName: string, scriptId: string, text: string, label: string): Promise<void>;
|
|
58
|
+
/** Whether this agent's scripts may outlive its turn. */
|
|
59
|
+
outlivesTurn(agentName: string): boolean;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface ScriptsConfig {
|
|
63
|
+
childEntry: string;
|
|
64
|
+
execPath?: string;
|
|
65
|
+
memoryMaxBytes: number;
|
|
66
|
+
maxStackBytes?: number;
|
|
67
|
+
output: OutputBounds;
|
|
68
|
+
flushMs: number;
|
|
69
|
+
/** The bound a run or wait yields at by default, and the most an agent may ask. */
|
|
70
|
+
yieldMs: number;
|
|
71
|
+
maxYieldMs: number;
|
|
72
|
+
/** A script's limit. */
|
|
73
|
+
lifetimeMs: number;
|
|
74
|
+
toolCallTimeoutMs: number;
|
|
75
|
+
stopGraceMs: number;
|
|
76
|
+
/** Scripts one agent may have running at once, yielded ones included. */
|
|
77
|
+
maxRunning: number;
|
|
78
|
+
/** Ended scripts kept per agent for a later wait or list. */
|
|
79
|
+
keepEnded: number;
|
|
80
|
+
wakeMinIntervalMs: number;
|
|
81
|
+
maxWakesPerScript: number;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** What one run, wait or stop returns. */
|
|
85
|
+
export interface ScriptReturn {
|
|
86
|
+
scriptId: string;
|
|
87
|
+
/** Still running past the bound, or ended. */
|
|
88
|
+
running: boolean;
|
|
89
|
+
/** The output since this script's previous return. */
|
|
90
|
+
output: OutputWindow;
|
|
91
|
+
/** True for the script's first return. */
|
|
92
|
+
first: boolean;
|
|
93
|
+
calls: CallSummary;
|
|
94
|
+
ending: Ending | null;
|
|
95
|
+
/** True when this agent's script will be stopped at the end of its turn unless it waits for it. */
|
|
96
|
+
stopsAtTurnEnd: boolean;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** One script in a listing. */
|
|
100
|
+
export interface ScriptListing {
|
|
101
|
+
scriptId: string;
|
|
102
|
+
running: boolean;
|
|
103
|
+
ending: Ending | null;
|
|
104
|
+
startedAt: number;
|
|
105
|
+
endedAt: number | null;
|
|
106
|
+
/** The wakes the host delivered for it. */
|
|
107
|
+
wakes: number;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
interface Script {
|
|
111
|
+
id: string;
|
|
112
|
+
agentName: string;
|
|
113
|
+
/** The code it runs. */
|
|
114
|
+
code: string;
|
|
115
|
+
run: ScriptRun;
|
|
116
|
+
context: { origin?: unknown };
|
|
117
|
+
/** The turn its run call was made in, when one was: its agent's turns end it by that. */
|
|
118
|
+
turnId: number | undefined;
|
|
119
|
+
startedAt: number;
|
|
120
|
+
endedAt: number | null;
|
|
121
|
+
/** The order its ending came in among this host's: the newest ended are those kept. */
|
|
122
|
+
endedSeq: number;
|
|
123
|
+
/** The delivery of a wake it sent that may not have reached its agent yet: its ending's notice follows it. */
|
|
124
|
+
delivering: Promise<void> | null;
|
|
125
|
+
/** The call watching it now, if one is: its ending goes there, and its calls carry its turn. */
|
|
126
|
+
watch: ScriptWatch | null;
|
|
127
|
+
/** Its ending wakes no one: it was stopped where its agent was told it would be, or never saw it. */
|
|
128
|
+
quietEnd: boolean;
|
|
129
|
+
/** Its agent has gone: nothing can wait on it or list it, so it leaves the map once it has ended. */
|
|
130
|
+
gone: boolean;
|
|
131
|
+
/** Returns made so far. */
|
|
132
|
+
returns: number;
|
|
133
|
+
/** A call watching it has returned its ending, so a notice of the ending would only repeat it. */
|
|
134
|
+
endingReturned: boolean;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/** Why a run, wait or stop couldn't be done: nothing was run or changed. */
|
|
138
|
+
export class ScriptRefusal extends Error {
|
|
139
|
+
constructor(message: string) {
|
|
140
|
+
super(message);
|
|
141
|
+
this.name = 'ScriptRefusal';
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/** The endings that wake a left script's agent: it didn't do its work, and not by its agent's choice. */
|
|
146
|
+
export function endingWakes(ending: Ending): boolean {
|
|
147
|
+
return ending.how === 'failed' || ending.how === 'crashed' || (ending.how === 'stopped' && ending.reason === 'limit');
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export class AgentScripts {
|
|
151
|
+
private readonly scripts = new Map<string, Script>();
|
|
152
|
+
/**
|
|
153
|
+
* Marks this host's script ids, so an id from before a restart, still in an
|
|
154
|
+
* agent's history, almost surely names no script of this one: four base-36
|
|
155
|
+
* characters, so about one restart in 1.7 million draws the tag of the host
|
|
156
|
+
* before it, and an old id could then name a new script of the same agent.
|
|
157
|
+
*/
|
|
158
|
+
private readonly idTag = Math.random().toString(36).slice(2, 6).padEnd(4, '0');
|
|
159
|
+
/** Every run whose child process hasn't exited, kept or not: dispose() ends any still alive. */
|
|
160
|
+
private readonly live = new Set<ScriptRun>();
|
|
161
|
+
private counter = 0;
|
|
162
|
+
private endedCounter = 0;
|
|
163
|
+
|
|
164
|
+
constructor(
|
|
165
|
+
private readonly host: ScriptsHost,
|
|
166
|
+
private readonly config: ScriptsConfig,
|
|
167
|
+
private readonly capacity: ChildCapacity,
|
|
168
|
+
) {}
|
|
169
|
+
|
|
170
|
+
/** The bound for this call: the agent's ask, capped, or the default. */
|
|
171
|
+
bound(askedMs: number | undefined): number {
|
|
172
|
+
return askedMs === undefined ? this.config.yieldMs : Math.min(askedMs, this.config.maxYieldMs);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
async run(
|
|
176
|
+
agentName: string,
|
|
177
|
+
code: string,
|
|
178
|
+
askedMs?: number,
|
|
179
|
+
options: { origin?: unknown; watch?: ScriptWatch } = {},
|
|
180
|
+
): Promise<ScriptReturn> {
|
|
181
|
+
// Listed first, so a module whose tool list throws refuses the run with nothing taken.
|
|
182
|
+
let tools: readonly PreludeTool[];
|
|
183
|
+
try {
|
|
184
|
+
tools = this.host.tools(agentName);
|
|
185
|
+
} catch (err) {
|
|
186
|
+
throw new ScriptRefusal(`The script's tools couldn't be listed: ${err instanceof Error ? err.message : String(err)}. Nothing was run.`);
|
|
187
|
+
}
|
|
188
|
+
const running = this.running(agentName);
|
|
189
|
+
if (running >= this.config.maxRunning) {
|
|
190
|
+
throw new ScriptRefusal(
|
|
191
|
+
`You have ${running} scripts running, your most. Wait for one, stop one, or let one end before you start another. Nothing was run.`,
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
if (!this.capacity.take()) {
|
|
195
|
+
throw new ScriptRefusal(
|
|
196
|
+
`This host is running ${this.capacity.running} scripts, its most. Try again once one has ended. Nothing was run.`,
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
const id = `s${++this.counter}-${this.idTag}`;
|
|
200
|
+
const script: Script = {
|
|
201
|
+
id,
|
|
202
|
+
agentName,
|
|
203
|
+
code,
|
|
204
|
+
run: null as unknown as ScriptRun,
|
|
205
|
+
context: options.origin === undefined ? {} : { origin: options.origin },
|
|
206
|
+
turnId: options.watch?.turnId,
|
|
207
|
+
startedAt: Date.now(),
|
|
208
|
+
endedAt: null,
|
|
209
|
+
endedSeq: 0,
|
|
210
|
+
delivering: null,
|
|
211
|
+
watch: options.watch ?? { endTurn: false },
|
|
212
|
+
quietEnd: false,
|
|
213
|
+
gone: false,
|
|
214
|
+
returns: 0,
|
|
215
|
+
endingReturned: false,
|
|
216
|
+
};
|
|
217
|
+
const runOptions: ScriptRunOptions = {
|
|
218
|
+
childEntry: this.config.childEntry,
|
|
219
|
+
...(this.config.execPath ? { execPath: this.config.execPath } : {}),
|
|
220
|
+
memoryMaxBytes: this.config.memoryMaxBytes,
|
|
221
|
+
...(this.config.maxStackBytes === undefined ? {} : { maxStackBytes: this.config.maxStackBytes }),
|
|
222
|
+
output: this.config.output,
|
|
223
|
+
flushMs: this.config.flushMs,
|
|
224
|
+
lifetimeMs: this.config.lifetimeMs,
|
|
225
|
+
toolCallTimeoutMs: this.config.toolCallTimeoutMs,
|
|
226
|
+
stopGraceMs: this.config.stopGraceMs,
|
|
227
|
+
wakeMinIntervalMs: this.config.wakeMinIntervalMs,
|
|
228
|
+
maxWakes: this.config.maxWakesPerScript,
|
|
229
|
+
onToolCall: (name, args) =>
|
|
230
|
+
this.host.dispatch(agentName, name, args, {
|
|
231
|
+
...script.context,
|
|
232
|
+
...(script.watch ? { watch: script.watch } : {}),
|
|
233
|
+
watching: () => script.watch ?? undefined,
|
|
234
|
+
}),
|
|
235
|
+
onWake: (payload, n) => this.wake(script, payload, n),
|
|
236
|
+
onEnd: (ending) => this.ended(script, ending),
|
|
237
|
+
};
|
|
238
|
+
script.run = new ScriptRun(runOptions);
|
|
239
|
+
const run = script.run;
|
|
240
|
+
this.live.add(run);
|
|
241
|
+
void run.exited.then(() => {
|
|
242
|
+
this.live.delete(run);
|
|
243
|
+
this.capacity.release();
|
|
244
|
+
});
|
|
245
|
+
try {
|
|
246
|
+
script.run.start(code, tools);
|
|
247
|
+
} catch (err) {
|
|
248
|
+
// Nothing was spawned, and `exited` has resolved, which frees the place.
|
|
249
|
+
throw new ScriptRefusal(`The script's process could not start: ${err instanceof Error ? err.message : String(err)}. Nothing was run.`);
|
|
250
|
+
}
|
|
251
|
+
this.scripts.set(id, script);
|
|
252
|
+
// A script that ended at its start, before it was in the map, trimmed
|
|
253
|
+
// without itself: the trim is taken again with it there.
|
|
254
|
+
this.trimEnded(agentName);
|
|
255
|
+
return this.observe(script, this.bound(askedMs), script.watch!);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
async wait(agentName: string, scriptId: string, askedMs?: number, watch: ScriptWatch = { endTurn: false }): Promise<ScriptReturn> {
|
|
259
|
+
const script = this.unwatched(this.own(agentName, scriptId));
|
|
260
|
+
script.watch = watch;
|
|
261
|
+
return this.observe(script, this.bound(askedMs), watch);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
async stop(agentName: string, scriptId: string, watch: ScriptWatch = { endTurn: false }): Promise<ScriptReturn> {
|
|
265
|
+
const script = this.unwatched(this.own(agentName, scriptId));
|
|
266
|
+
script.watch = watch;
|
|
267
|
+
// A run that has ended returns its ending to this stop: marked before the
|
|
268
|
+
// stop yields, as observe marks a wait's, so a notice whose turn comes
|
|
269
|
+
// first doesn't repeat it.
|
|
270
|
+
if (script.run.ended) script.endingReturned = true;
|
|
271
|
+
await script.run.stop('agent');
|
|
272
|
+
return this.observe(script, 0, watch);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/** The code of this agent's script by that id, as a wait or a stop would find the script; undefined when the agent has none by it. */
|
|
276
|
+
codeOf(agentName: string, scriptId: string): string | undefined {
|
|
277
|
+
const script = this.scripts.get(scriptId);
|
|
278
|
+
return script && script.agentName === agentName && !script.gone ? script.code : undefined;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
list(agentName: string): ScriptListing[] {
|
|
282
|
+
return [...this.scripts.values()]
|
|
283
|
+
.filter((s) => s.agentName === agentName && !s.gone)
|
|
284
|
+
.map((s) => ({
|
|
285
|
+
scriptId: s.id,
|
|
286
|
+
running: !s.run.ended,
|
|
287
|
+
ending: s.run.snapshot().ending,
|
|
288
|
+
startedAt: s.startedAt,
|
|
289
|
+
endedAt: s.endedAt,
|
|
290
|
+
wakes: s.run.wakesDelivered,
|
|
291
|
+
}));
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* An agent's turn ended: `turn.id`, with `turn.live` the agent's turns still
|
|
296
|
+
* live (its open turn, and the turn of the stream that holds the agent), or
|
|
297
|
+
* `'every'` when all its turns end at once (the host stopping, or a quiesce
|
|
298
|
+
* that names no turn of its own).
|
|
299
|
+
* Turns can overlap, a silent one beside an open one, so each script goes by
|
|
300
|
+
* its own turn, the one its run call was made in. A turn that ended without
|
|
301
|
+
* its calls' answers (`abandoned`) leaves its calls watching scripts with no
|
|
302
|
+
* one to answer, whatever the agent: a script that hasn't returned yet is
|
|
303
|
+
* stopped, and one that has is let go. An agent whose scripts don't outlive
|
|
304
|
+
* a turn has stopped every script whose turn isn't live, and every one
|
|
305
|
+
* started in no turn: a script lives while the turn that started it does.
|
|
306
|
+
*/
|
|
307
|
+
turnEnded(agentName: string, turn: { id: number; live: readonly number[] } | 'every', abandoned: boolean, reason?: string): void {
|
|
308
|
+
const outlives = this.host.outlivesTurn(agentName);
|
|
309
|
+
for (const script of this.scripts.values()) {
|
|
310
|
+
if (script.agentName !== agentName || script.gone || script.run.ended) continue;
|
|
311
|
+
if (abandoned && script.watch && (turn === 'every' || script.watch.turnId === turn.id)) {
|
|
312
|
+
if (script.returns === 0) {
|
|
313
|
+
this.stopQuietly(script, `its turn ended before the script returned${reason ? ` (${reason})` : ''}`);
|
|
314
|
+
continue;
|
|
315
|
+
}
|
|
316
|
+
script.watch = null;
|
|
317
|
+
}
|
|
318
|
+
if (outlives) continue;
|
|
319
|
+
if (turn !== 'every' && script.turnId !== undefined && turn.live.includes(script.turnId)) continue;
|
|
320
|
+
this.stopQuietly(script, "its agent's turn ended, and only the primary agent's scripts outlive a turn");
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* An agent that has gone, such as an ephemeral one whose run ended: its
|
|
326
|
+
* scripts are stopped, and each leaves the map once it has ended, since no
|
|
327
|
+
* later run of the agent will trim them.
|
|
328
|
+
*/
|
|
329
|
+
agentGone(agentName: string): void {
|
|
330
|
+
for (const script of [...this.scripts.values()]) {
|
|
331
|
+
if (script.agentName !== agentName || script.gone) continue;
|
|
332
|
+
if (script.run.ended) {
|
|
333
|
+
this.scripts.delete(script.id);
|
|
334
|
+
continue;
|
|
335
|
+
}
|
|
336
|
+
script.gone = true;
|
|
337
|
+
this.stopQuietly(script, 'its agent ended');
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/** Stop every running script, as the framework stops, and end any child process still alive after its script's ending. */
|
|
342
|
+
async dispose(): Promise<void> {
|
|
343
|
+
const running = [...this.scripts.values()].filter((s) => !s.run.ended);
|
|
344
|
+
for (const script of running) script.quietEnd = true;
|
|
345
|
+
await Promise.all(running.map((s) => s.run.stop('limit', 'the host stopped')));
|
|
346
|
+
await Promise.all([...this.live].map((run) => run.kill()));
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/** Running scripts of this agent, yielded ones included; not those of an earlier agent of its name that has gone, which the host's count still holds. */
|
|
350
|
+
running(agentName: string): number {
|
|
351
|
+
return [...this.scripts.values()].filter((s) => s.agentName === agentName && !s.gone && !s.run.ended).length;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/** Running scripts that no call is watching: those acting outside any turn. */
|
|
355
|
+
leftRunning(): number {
|
|
356
|
+
return [...this.scripts.values()].filter((s) => !s.run.ended && s.watch === null).length;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
private stopQuietly(script: Script, why: string): void {
|
|
360
|
+
script.quietEnd = true;
|
|
361
|
+
script.watch = null;
|
|
362
|
+
void script.run.stop('limit', why);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
private own(agentName: string, scriptId: string): Script {
|
|
366
|
+
const script = this.scripts.get(scriptId);
|
|
367
|
+
if (!script || script.agentName !== agentName || script.gone) {
|
|
368
|
+
throw new ScriptRefusal(
|
|
369
|
+
`You have no script ${JSON.stringify(scriptId)}: it isn't one of yours, it ran before this host restarted, ` +
|
|
370
|
+
`or it ended and was dropped: only your ${this.config.keepEnded} newest ended scripts are kept, and none of an earlier agent of your name that has gone. Nothing was changed.`,
|
|
371
|
+
);
|
|
372
|
+
}
|
|
373
|
+
return script;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/** A script no other call is watching now: one watching it gets its output and its ending. */
|
|
377
|
+
private unwatched(script: Script): Script {
|
|
378
|
+
if (script.watch !== null) {
|
|
379
|
+
throw new ScriptRefusal(`Another of your calls is waiting on ${script.id} now, and its result will show how the script stands. Nothing was changed.`);
|
|
380
|
+
}
|
|
381
|
+
return script;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
private async observe(script: Script, ms: number, watch: ScriptWatch): Promise<ScriptReturn> {
|
|
385
|
+
// A run that has ended returns its ending at once: marked now, so a notice
|
|
386
|
+
// whose turn comes before this return does doesn't repeat it. One that ends
|
|
387
|
+
// while this call watches it gives no notice at all (ended), so this and a
|
|
388
|
+
// stop's own, made before its stop yields, are the only marks a returned
|
|
389
|
+
// ending needs.
|
|
390
|
+
if (script.run.ended && script.watch === watch) script.endingReturned = true;
|
|
391
|
+
const snap = await script.run.wait(ms);
|
|
392
|
+
// A call whose turn was abandoned no longer watches the script: its
|
|
393
|
+
// return reaches no one, so it takes none of the output from the next.
|
|
394
|
+
const current = script.watch === watch;
|
|
395
|
+
if (current) script.watch = null;
|
|
396
|
+
if (current) script.returns += 1;
|
|
397
|
+
return {
|
|
398
|
+
scriptId: script.id,
|
|
399
|
+
running: snap.ending === null,
|
|
400
|
+
output: current ? script.run.takeOutput() : script.run.outputWindow(),
|
|
401
|
+
first: script.returns <= 1,
|
|
402
|
+
calls: snap.calls,
|
|
403
|
+
ending: snap.ending,
|
|
404
|
+
stopsAtTurnEnd: snap.ending === null && !this.host.outlivesTurn(script.agentName),
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
private ended(script: Script, ending: Ending): void {
|
|
409
|
+
script.endedAt = Date.now();
|
|
410
|
+
script.endedSeq = ++this.endedCounter;
|
|
411
|
+
if (script.gone) this.scripts.delete(script.id);
|
|
412
|
+
else this.trimEnded(script.agentName);
|
|
413
|
+
// A watched script's ending goes to the call watching it. A left one says
|
|
414
|
+
// nothing when it finished or its agent stopped it, and wakes its agent
|
|
415
|
+
// otherwise, after any wake it sent that is still being delivered: the
|
|
416
|
+
// ending is the script's last word.
|
|
417
|
+
if (script.watch || script.quietEnd || !endingWakes(ending)) return;
|
|
418
|
+
const send = (): void => {
|
|
419
|
+
// A wait or stop that took the ending while the notice waited has already given it.
|
|
420
|
+
if (script.endingReturned) return;
|
|
421
|
+
void this.host.wake(script.agentName, script.id, leftEndingText(script.id, ending), `${script.id}-ended`).catch(() => {});
|
|
422
|
+
};
|
|
423
|
+
if (script.delivering) void script.delivering.then(send);
|
|
424
|
+
else send();
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/** Send the script's `n`th wake, whose turn the run has waited for. */
|
|
428
|
+
private async wake(script: Script, payloadJson: string, n: number): Promise<CallAnswer> {
|
|
429
|
+
let delivery: Promise<void>;
|
|
430
|
+
try {
|
|
431
|
+
delivery = Promise.resolve(this.host.wake(
|
|
432
|
+
script.agentName,
|
|
433
|
+
script.id,
|
|
434
|
+
wakeText(script.id, payloadJson, n, this.config.maxWakesPerScript, Date.now() - script.startedAt),
|
|
435
|
+
`${script.id}-wake${n}`,
|
|
436
|
+
));
|
|
437
|
+
} catch (err) {
|
|
438
|
+
delivery = Promise.reject(err);
|
|
439
|
+
}
|
|
440
|
+
const done = delivery.then(() => {}, () => {});
|
|
441
|
+
script.delivering = done;
|
|
442
|
+
void done.then(() => {
|
|
443
|
+
if (script.delivering === done) script.delivering = null;
|
|
444
|
+
});
|
|
445
|
+
try {
|
|
446
|
+
await delivery;
|
|
447
|
+
return { ok: true, json: 'null' };
|
|
448
|
+
} catch (err) {
|
|
449
|
+
return {
|
|
450
|
+
ok: false,
|
|
451
|
+
json: JSON.stringify({ name: 'WakeRefused', message: `the wake couldn't be delivered: ${err instanceof Error ? err.message : String(err)}` }),
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
/** Keep only the agent's newest ended scripts, newest by the order their endings came in. */
|
|
457
|
+
private trimEnded(agentName: string): void {
|
|
458
|
+
const ended = [...this.scripts.values()]
|
|
459
|
+
.filter((s) => s.agentName === agentName && s.run.ended)
|
|
460
|
+
.sort((a, b) => a.endedSeq - b.endedSeq);
|
|
461
|
+
for (const s of ended.slice(0, Math.max(0, ended.length - this.config.keepEnded))) this.scripts.delete(s.id);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
function leftEndingText(scriptId: string, ending: Ending): string {
|
|
466
|
+
const how = ending.how === 'failed'
|
|
467
|
+
? `failed: ${ending.error.name ? `${ending.error.name}: ` : ''}${glimpse(ending.error.message, 300)}`
|
|
468
|
+
: ending.how === 'crashed'
|
|
469
|
+
? `crashed: ${ending.detail}`
|
|
470
|
+
: ending.how === 'stopped'
|
|
471
|
+
? ending.why ? `was stopped: ${ending.why}` : 'was stopped at its limit'
|
|
472
|
+
: 'ended';
|
|
473
|
+
return `[script ${scriptId}] Your script ${how}. {"action": "wait", "script_id": "${scriptId}"} gives its result.`;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
function wakeText(scriptId: string, payloadJson: string, n: number, max: number, ageMs: number): string {
|
|
477
|
+
const minutes = Math.round(ageMs / 60_000);
|
|
478
|
+
return `[script ${scriptId}] Woke you with wake_agent(), ${minutes} min after it started (wake ${n} of ${max}): ${payloadJson}`;
|
|
479
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
quickjs.wasm, code_execution's engine, is built by engine/build.sh from agent-framework's own
|
|
2
|
+
engine/interface.c and the works below, whose notices it carries.
|
|
3
|
+
|
|
4
|
+
=====================================================================================================================================================
|
|
5
|
+
QuickJS-ng v0.17.0 (commit 6d46d07d04041b40f4f49eaa7fdebe44c314c699, with any patch in engine/patches applied), https://github.com/quickjs-ng/quickjs
|
|
6
|
+
=====================================================================================================================================================
|
|
7
|
+
|
|
8
|
+
The MIT License (MIT)
|
|
9
|
+
|
|
10
|
+
Copyright (c) 2017-2026 Fabrice Bellard
|
|
11
|
+
Copyright (c) 2017-2024 Charlie Gordon
|
|
12
|
+
Copyright (c) 2023-2026 Ben Noordhuis
|
|
13
|
+
Copyright (c) 2023-2026 Saúl Ibarra Corretgé
|
|
14
|
+
|
|
15
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
16
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
17
|
+
in the Software without restriction, including without limitation the rights
|
|
18
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
19
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
20
|
+
furnished to do so, subject to the following conditions:
|
|
21
|
+
|
|
22
|
+
The above copyright notice and this permission notice shall be included in
|
|
23
|
+
all copies or substantial portions of the Software.
|
|
24
|
+
|
|
25
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
26
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
27
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
28
|
+
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
29
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
30
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
31
|
+
THE SOFTWARE.
|
|
32
|
+
|
|
33
|
+
========================================================================================
|
|
34
|
+
quickjs-wasi 3.6.2, https://github.com/vercel-labs/quickjs-wasi: the memory-limiting
|
|
35
|
+
allocator in engine/interface.c is adapted from its c/interface.c
|
|
36
|
+
========================================================================================
|
|
37
|
+
|
|
38
|
+
MIT License
|
|
39
|
+
|
|
40
|
+
Copyright (c) 2026 Vercel, Inc.
|
|
41
|
+
|
|
42
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
43
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
44
|
+
in the Software without restriction, including without limitation the rights
|
|
45
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
46
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
47
|
+
furnished to do so, subject to the following conditions:
|
|
48
|
+
|
|
49
|
+
The above copyright notice and this permission notice shall be included in all
|
|
50
|
+
copies or substantial portions of the Software.
|
|
51
|
+
|
|
52
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
53
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
54
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
55
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
56
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
57
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
58
|
+
SOFTWARE.
|
|
59
|
+
|
|
60
|
+
========================================================================================
|
|
61
|
+
wasi-libc, as wasi-sdk 32 ships it (wasi-libc 2fc32bc81b9f07f8d9525edea59bfbaf760c06d6),
|
|
62
|
+
https://github.com/WebAssembly/wasi-libc
|
|
63
|
+
========================================================================================
|
|
64
|
+
|
|
65
|
+
wasi-libc as a whole is multi-licensed under the Apache License v2.0 with LLVM Exceptions,
|
|
66
|
+
the Apache License v2.0, and the MIT License:
|
|
67
|
+
|
|
68
|
+
Permission is hereby granted, free of charge, to any
|
|
69
|
+
person obtaining a copy of this software and associated
|
|
70
|
+
documentation files (the "Software"), to deal in the
|
|
71
|
+
Software without restriction, including without
|
|
72
|
+
limitation the rights to use, copy, modify, merge,
|
|
73
|
+
publish, distribute, sublicense, and/or sell copies of
|
|
74
|
+
the Software, and to permit persons to whom the Software
|
|
75
|
+
is furnished to do so, subject to the following
|
|
76
|
+
conditions:
|
|
77
|
+
|
|
78
|
+
The above copyright notice and this permission notice
|
|
79
|
+
shall be included in all copies or substantial portions
|
|
80
|
+
of the Software.
|
|
81
|
+
|
|
82
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
|
83
|
+
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
|
84
|
+
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
85
|
+
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
|
86
|
+
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
87
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
88
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
|
89
|
+
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
90
|
+
DEALINGS IN THE SOFTWARE.
|
|
91
|
+
|
|
92
|
+
Portions of wasi-libc are derived from third-party works covered by their own licenses:
|
|
93
|
+
|
|
94
|
+
--- musl (libc-top-half/musl) ---
|
|
95
|
+
|
|
96
|
+
Copyright © 2005-2020 Rich Felker, et al.
|
|
97
|
+
|
|
98
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
99
|
+
a copy of this software and associated documentation files (the
|
|
100
|
+
"Software"), to deal in the Software without restriction, including
|
|
101
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
102
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
103
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
104
|
+
the following conditions:
|
|
105
|
+
|
|
106
|
+
The above copyright notice and this permission notice shall be
|
|
107
|
+
included in all copies or substantial portions of the Software.
|
|
108
|
+
|
|
109
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
110
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
111
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
112
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
113
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
114
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
115
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
116
|
+
|
|
117
|
+
--- cloudlibc (libc-bottom-half/cloudlibc) ---
|
|
118
|
+
|
|
119
|
+
Copyright (c) 2015-2017 Nuxi (https://nuxi.nl/) and contributors.
|
|
120
|
+
|
|
121
|
+
Redistribution and use in source and binary forms, with or without
|
|
122
|
+
modification, are permitted provided that the following conditions
|
|
123
|
+
are met:
|
|
124
|
+
1. Redistributions of source code must retain the above copyright
|
|
125
|
+
notice, this list of conditions and the following disclaimer.
|
|
126
|
+
2. Redistributions in binary form must reproduce the above copyright
|
|
127
|
+
notice, this list of conditions and the following disclaimer in the
|
|
128
|
+
documentation and/or other materials provided with the distribution.
|
|
129
|
+
|
|
130
|
+
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
131
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
132
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
133
|
+
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
134
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
135
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
136
|
+
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
137
|
+
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
138
|
+
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
139
|
+
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
140
|
+
SUCH DAMAGE.
|
|
141
|
+
|
|
142
|
+
--- dlmalloc (dlmalloc) ---
|
|
143
|
+
|
|
144
|
+
Written by Doug Lea and released to the public domain (CC0).
|
|
145
|
+
|
|
146
|
+
========================================================================================
|
|
147
|
+
LLVM compiler-rt builtins, as wasi-sdk 32 ships them: Apache License v2.0 with LLVM
|
|
148
|
+
Exceptions, whose exception lets compiled code like this module carry no notice.
|
|
149
|
+
========================================================================================
|