@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
|
@@ -16,10 +16,10 @@
|
|
|
16
16
|
* - Everything else is left unrouted and dropped by the framework — the
|
|
17
17
|
* trunk is a dormant template, not a listener.
|
|
18
18
|
*
|
|
19
|
-
* Bindings expire after an idle TTL. Expiry
|
|
20
|
-
* fork (see framework wiring)
|
|
21
|
-
* that channel spawns a *fresh* fork (generation + 1) from the
|
|
22
|
-
* trunk, so handbook/template updates propagate between engagements.
|
|
19
|
+
* Bindings expire after an idle TTL. Expiry unbinds the channel and runs a
|
|
20
|
+
* final closure turn on the fork (see framework wiring); the next qualifying
|
|
21
|
+
* message on that channel spawns a *fresh* fork (generation + 1) from the
|
|
22
|
+
* current trunk, so handbook/template updates propagate between engagements.
|
|
23
23
|
*
|
|
24
24
|
* The binding table is in-memory — bindings are re-established by the next
|
|
25
25
|
* qualifying message after a restart. The generation counters, by contrast,
|
|
@@ -264,8 +264,10 @@ export class ConversationRouter {
|
|
|
264
264
|
return Array.from(this.bindings.values());
|
|
265
265
|
}
|
|
266
266
|
|
|
267
|
-
/** Bindings whose idle TTL has elapsed. Does not unbind
|
|
268
|
-
*
|
|
267
|
+
/** Bindings whose idle TTL has elapsed. Does not unbind: the framework
|
|
268
|
+
* unbinds each one first, so the channel's next message goes to a newer
|
|
269
|
+
* fork, or nowhere, and then runs the old fork's closure turn
|
|
270
|
+
* (sweepExpiredConversations). */
|
|
269
271
|
expired(now = Date.now()): ConversationBinding[] {
|
|
270
272
|
const ttl = this.idleTtlMs;
|
|
271
273
|
return this.getBindings().filter((b) => now - b.lastActivity >= ttl);
|
|
@@ -301,7 +303,10 @@ export class ConversationRouter {
|
|
|
301
303
|
return Object.fromEntries(this.generations);
|
|
302
304
|
}
|
|
303
305
|
|
|
304
|
-
/**
|
|
306
|
+
/** Raise each channel's engagement counter to at least the given
|
|
307
|
+
* generation, never lowering one: the persisted counters at startup (see
|
|
308
|
+
* exportGenerations), or a spawn's generation whose fork ended before the
|
|
309
|
+
* spawn could bind it. */
|
|
305
310
|
hydrateGenerations(generations: Record<string, number>): void {
|
|
306
311
|
for (const [channelId, generation] of Object.entries(generations)) {
|
|
307
312
|
if (typeof generation === 'number' && generation > (this.generations.get(channelId) ?? 0)) {
|
|
@@ -43,9 +43,12 @@ export function convertBlock(block: McplContentBlock, provenance: string, server
|
|
|
43
43
|
// closed, withhold the data (checked BEFORE the data branch).
|
|
44
44
|
return { type: 'text', text: INLINE_WITHHELD_TEXT };
|
|
45
45
|
}
|
|
46
|
-
if (isFilledString(block.uri) && block.disposition) {
|
|
46
|
+
if (isFilledString(block.uri) && block.disposition !== undefined) {
|
|
47
47
|
// RFC-005 uri-form media with a disposition claim: stub, do not
|
|
48
|
-
// hand the URI to the provider or inline it.
|
|
48
|
+
// hand the URI to the provider or inline it. Any disposition given
|
|
49
|
+
// is a claim, one the reference rejects included, as classifyBlock
|
|
50
|
+
// and isInlineContradiction read it: a falsy one such as 0, false
|
|
51
|
+
// or '' stubs too, rather than sending the URI as the image's source.
|
|
49
52
|
return { type: 'text', text: referenceStubOrNull(block, provenance, serverId) ?? '[reference]' };
|
|
50
53
|
}
|
|
51
54
|
if (isFilledString(block.data) && isFilledString(block.mimeType)) {
|
|
@@ -68,9 +71,10 @@ export function convertBlock(block: McplContentBlock, provenance: string, server
|
|
|
68
71
|
// closed, withhold the data (checked BEFORE the data branch).
|
|
69
72
|
return { type: 'text', text: INLINE_WITHHELD_TEXT };
|
|
70
73
|
}
|
|
71
|
-
if (isFilledString(block.uri) && block.disposition) {
|
|
72
|
-
// RFC-005 uri-form media with a disposition claim
|
|
73
|
-
//
|
|
74
|
+
if (isFilledString(block.uri) && block.disposition !== undefined) {
|
|
75
|
+
// RFC-005 uri-form media with a disposition claim, a falsy one
|
|
76
|
+
// included, as for an image (above): stub, do not hand the URI to
|
|
77
|
+
// the provider or inline it.
|
|
74
78
|
return { type: 'text', text: referenceStubOrNull(block, provenance, serverId) ?? '[reference]' };
|
|
75
79
|
}
|
|
76
80
|
if (isFilledString(block.data) && isFilledString(block.mimeType)) {
|
|
@@ -21,6 +21,8 @@
|
|
|
21
21
|
* key: `eventId` is present only when the producer supplied one.
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
|
+
import { createHash } from 'node:crypto';
|
|
25
|
+
|
|
24
26
|
/** The MCPL admission lane that accepted an item. Its contract decides what
|
|
25
27
|
* an `eventId` is worth: `push/event` deduplicates by eventId, and RFC-006
|
|
26
28
|
* coalesced admission (`coalesced: true`) guarantees stable retries and
|
|
@@ -154,3 +156,132 @@ export function conversationKey(source: InboundSource): string | undefined {
|
|
|
154
156
|
if (source.kind === 'surface') return JSON.stringify(['surface', source.surface]);
|
|
155
157
|
return undefined;
|
|
156
158
|
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* JSON with object keys sorted at every level, written as the store's append
|
|
162
|
+
* keeps a value (its native UTF-8 write, which the real-store digest table
|
|
163
|
+
* checks): an `undefined` object entry is dropped; a string is well-formed
|
|
164
|
+
* (each lone surrogate comes back as U+FFFD); and an entry whose key isn't
|
|
165
|
+
* well-formed is dropped (the store doesn't keep it). An `undefined` array
|
|
166
|
+
* element is written as `null`, as JSON writes it: the store's append
|
|
167
|
+
* refuses a body holding one, so no stored copy does. So a value
|
|
168
|
+
* hashes alike however its keys were ordered (content read back from the
|
|
169
|
+
* store has them in a different order than it was written), and alike
|
|
170
|
+
* before and after the store. editMessage writes JSON instead, so an edited
|
|
171
|
+
* copy can keep what an append wouldn't; it has changed anyway.
|
|
172
|
+
*
|
|
173
|
+
* It expects JSON-shaped values, as the MCPL lanes deliver them (parsed from
|
|
174
|
+
* JSON). Any other object is written by its own enumerable entries, unlike
|
|
175
|
+
* JSON.stringify: a Date becomes `{}`, as the store's own write keeps it, but
|
|
176
|
+
* a deferred write recovered from its JSON file brings it back as a string.
|
|
177
|
+
*
|
|
178
|
+
* sourceBodyDigest's serializer, kept out of the package API: serialization
|
|
179
|
+
* and framing both stay inside sourceBodyDigest, so consumers don't
|
|
180
|
+
* duplicate either (`canonicalJson(blocks)` alone hashes differently).
|
|
181
|
+
*/
|
|
182
|
+
export function canonicalJson(value: unknown): string {
|
|
183
|
+
if (Array.isArray(value)) return `[${value.map(canonicalJson).join(',')}]`;
|
|
184
|
+
if (value && typeof value === 'object') {
|
|
185
|
+
const entries = Object.entries(value as Record<string, unknown>)
|
|
186
|
+
.filter(([k, v]) => v !== undefined && k.isWellFormed())
|
|
187
|
+
.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0));
|
|
188
|
+
return `{${entries.map(([k, v]) => `${JSON.stringify(k)}:${canonicalJson(v)}`).join(',')}}`;
|
|
189
|
+
}
|
|
190
|
+
if (typeof value === 'string') return JSON.stringify(value.toWellFormed());
|
|
191
|
+
return JSON.stringify(value) ?? 'null';
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* A block as the store hands it back. Context-manager keeps inline media as
|
|
196
|
+
* blobs (blob-manager.ts): an image whose source isn't a URL, and every
|
|
197
|
+
* document, audio or video block, comes back as `{ type, source: { type:
|
|
198
|
+
* 'base64', data, mediaType } }` and nothing else, its data re-encoded from
|
|
199
|
+
* the decoded bytes, and an image's media type taken from its bytes'
|
|
200
|
+
* signature where they have one. Any other block comes back as it was given,
|
|
201
|
+
* except a store-internal `blob_ref` from an unresolved read, which resolves
|
|
202
|
+
* to inline media by default. It is digested as given here, so an unresolved
|
|
203
|
+
* read and its resolved form differ. Context-manager refuses caller-supplied
|
|
204
|
+
* blob_ref writes; the MCPL lanes never store one.
|
|
205
|
+
*/
|
|
206
|
+
function storedBlock(block: unknown): unknown {
|
|
207
|
+
const media = block as { type?: unknown; source?: { type?: unknown; data?: unknown; mediaType?: unknown } } | null;
|
|
208
|
+
const blob = media?.type === 'image'
|
|
209
|
+
? media.source?.type !== 'url'
|
|
210
|
+
: media?.type === 'document' || media?.type === 'audio' || media?.type === 'video';
|
|
211
|
+
const source = media?.source;
|
|
212
|
+
if (!blob || typeof source?.data !== 'string') return block;
|
|
213
|
+
const data = canonicalBase64(source.data);
|
|
214
|
+
const mediaType = media!.type === 'image'
|
|
215
|
+
? sniffRasterImageMediaType(Buffer.from(data.slice(0, 32), 'base64')) ?? source.mediaType
|
|
216
|
+
: source.mediaType;
|
|
217
|
+
return { type: media!.type, source: { type: 'base64', data, mediaType } };
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Base64 as the store writes it back from the decoded bytes: padded, with no
|
|
222
|
+
* whitespace, the standard alphabet and zero unused bits. Data already in
|
|
223
|
+
* that form, as every stored copy's is, is returned without decoding it all.
|
|
224
|
+
*/
|
|
225
|
+
function canonicalBase64(data: string): string {
|
|
226
|
+
if (data.length % 4 === 0 && /^[A-Za-z0-9+/]*={0,2}$/.test(data)) {
|
|
227
|
+
const last = data.slice(-4);
|
|
228
|
+
if (Buffer.from(last, 'base64').toString('base64') === last) return data;
|
|
229
|
+
}
|
|
230
|
+
return Buffer.from(data, 'base64').toString('base64');
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* The store's own test for raster image types with an unambiguous byte
|
|
235
|
+
* signature, copied from context-manager's blob-manager.ts (it isn't
|
|
236
|
+
* exported): the store relabels an image whose bytes match one of these.
|
|
237
|
+
*/
|
|
238
|
+
function sniffRasterImageMediaType(bytes: Uint8Array): string | null {
|
|
239
|
+
if (bytes.length >= 8 &&
|
|
240
|
+
bytes[0] === 0x89 && bytes[1] === 0x50 && bytes[2] === 0x4e && bytes[3] === 0x47 &&
|
|
241
|
+
bytes[4] === 0x0d && bytes[5] === 0x0a && bytes[6] === 0x1a && bytes[7] === 0x0a) {
|
|
242
|
+
return 'image/png';
|
|
243
|
+
}
|
|
244
|
+
if (bytes.length >= 3 && bytes[0] === 0xff && bytes[1] === 0xd8 && bytes[2] === 0xff) {
|
|
245
|
+
return 'image/jpeg';
|
|
246
|
+
}
|
|
247
|
+
if (bytes.length >= 6) {
|
|
248
|
+
const signature = Buffer.from(bytes.subarray(0, 6)).toString('ascii');
|
|
249
|
+
if (signature === 'GIF87a' || signature === 'GIF89a') return 'image/gif';
|
|
250
|
+
}
|
|
251
|
+
if (bytes.length >= 12 &&
|
|
252
|
+
Buffer.from(bytes.subarray(0, 4)).toString('ascii') === 'RIFF' &&
|
|
253
|
+
Buffer.from(bytes.subarray(8, 12)).toString('ascii') === 'WEBP') {
|
|
254
|
+
return 'image/webp';
|
|
255
|
+
}
|
|
256
|
+
return null;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* The version identity of a delivered body (agreed with the receipts lane,
|
|
261
|
+
* room-220 #46752–#47210): SHA-256 hex of `canonicalJson([blocks])` over the
|
|
262
|
+
* ContentBlock[] the framework stores for the body — after MCPL conversion,
|
|
263
|
+
* before any host decoration is added and before storage shards it — with
|
|
264
|
+
* each block as the store keeps it (storedBlock, canonicalJson). So a body
|
|
265
|
+
* hashes alike as delivered, as handed to storage, and as read back from
|
|
266
|
+
* the store. The one-element array keeps the framing an undecorated,
|
|
267
|
+
* unsharded stored copy has always hashed to, so a stamped copy and an
|
|
268
|
+
* older copy of the same body share a version.
|
|
269
|
+
*
|
|
270
|
+
* Ingestion stamps it as `metadata.sourceBodyDigest`, and the same function
|
|
271
|
+
* over exactly the blocks handed to storage (decorations included) as
|
|
272
|
+
* `metadata.storedBodyDigest`, on both MCPL lanes. Both live outside the
|
|
273
|
+
* frozen admission envelope: they describe the body actually delivered (a
|
|
274
|
+
* materialization, a correction), not the admission. Neither proves later
|
|
275
|
+
* presence or completeness; an unsharded stored copy that no longer hashes
|
|
276
|
+
* to its storedBodyDigest was changed after delivery (editMessage keeps
|
|
277
|
+
* metadata). A body the store shards carries the whole body's two digests
|
|
278
|
+
* on every shard, and no shard hashes to them. Check a copy read back with
|
|
279
|
+
* its blobs resolved (getAllMessages, getMessage, or getMessageWindow
|
|
280
|
+
* without `resolveBlobs: false`): a blob reference never matches.
|
|
281
|
+
*
|
|
282
|
+
* Exported from the package root, so a consumer checks a copy against either
|
|
283
|
+
* field with this same function rather than a copy of it.
|
|
284
|
+
*/
|
|
285
|
+
export function sourceBodyDigest(blocks: readonly unknown[]): string {
|
|
286
|
+
return createHash('sha256').update(canonicalJson([blocks.map(storedBlock)])).digest('hex');
|
|
287
|
+
}
|
package/src/mcpl/index.ts
CHANGED
|
@@ -171,9 +171,11 @@ export { InferenceRouter } from './inference-router.js';
|
|
|
171
171
|
|
|
172
172
|
// Channel registry (channel lifecycle, incoming messages, synthesized tools)
|
|
173
173
|
export { ChannelRegistry } from './channel-registry.js';
|
|
174
|
+
export type { PublishRefusalReason } from './channel-registry.js';
|
|
174
175
|
|
|
175
|
-
// Inbound source envelope: where each accepted item came from, stamped once
|
|
176
|
-
|
|
176
|
+
// Inbound source envelope: where each accepted item came from, stamped once;
|
|
177
|
+
// and the digest of a delivered or stored body
|
|
178
|
+
export { INBOUND_SOURCE_KEY, readInboundSource, conversationKey, sourceBodyDigest } from './inbound-source.js';
|
|
177
179
|
export type {
|
|
178
180
|
InboundSource,
|
|
179
181
|
InboundChannelSource,
|
package/src/mcpl/log-value.ts
CHANGED
|
@@ -55,6 +55,15 @@ export function logValueRedacted(value: unknown, redact: (text: string) => strin
|
|
|
55
55
|
return printed(redact(textOf(value)), FIELD);
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
/**
|
|
59
|
+
* A JSON-RPC error answer's code as a log line prints it: a number, as
|
|
60
|
+
* JSON-RPC says a code is, as logValue prints it; any other JSON value a
|
|
61
|
+
* server sends there redacted (logValueRedacted), since the server wrote it.
|
|
62
|
+
*/
|
|
63
|
+
export function loggedCode(code: unknown, redact: (text: string) => string): string {
|
|
64
|
+
return typeof code === 'number' ? logValue(code) : logValueRedacted(code, redact);
|
|
65
|
+
}
|
|
66
|
+
|
|
58
67
|
/**
|
|
59
68
|
* The host's own message, as the free text that ends a log line after its
|
|
60
69
|
* fields: `reason=coalesce-invalid field=payload.content: "content must be an
|