@animalabs/agent-framework 0.26.2 → 0.28.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 +99 -8
- package/dist/src/agent.d.ts +291 -23
- package/dist/src/agent.d.ts.map +1 -1
- package/dist/src/agent.js +596 -61
- package/dist/src/agent.js.map +1 -1
- package/dist/src/api/server.d.ts.map +1 -1
- package/dist/src/api/server.js +5 -4
- package/dist/src/api/server.js.map +1 -1
- package/dist/src/auto-continue.d.ts +34 -0
- package/dist/src/auto-continue.d.ts.map +1 -0
- package/dist/src/auto-continue.js +36 -0
- package/dist/src/auto-continue.js.map +1 -0
- package/dist/src/code-execution/isolate/scripts.d.ts +11 -0
- package/dist/src/code-execution/isolate/scripts.d.ts.map +1 -1
- package/dist/src/code-execution/isolate/scripts.js +5 -1
- package/dist/src/code-execution/isolate/scripts.js.map +1 -1
- package/dist/src/cut-off-round.d.ts +24 -0
- package/dist/src/cut-off-round.d.ts.map +1 -0
- package/dist/src/cut-off-round.js +87 -0
- package/dist/src/cut-off-round.js.map +1 -0
- package/dist/src/framework.d.ts +1038 -193
- package/dist/src/framework.d.ts.map +1 -1
- package/dist/src/framework.js +5967 -1514
- package/dist/src/framework.js.map +1 -1
- package/dist/src/gate/event-gate.d.ts +405 -46
- package/dist/src/gate/event-gate.d.ts.map +1 -1
- package/dist/src/gate/event-gate.js +2646 -399
- package/dist/src/gate/event-gate.js.map +1 -1
- package/dist/src/gate/index.d.ts +3 -2
- package/dist/src/gate/index.d.ts.map +1 -1
- package/dist/src/gate/index.js +2 -1
- package/dist/src/gate/index.js.map +1 -1
- package/dist/src/gate/recipe-reconcile.d.ts +103 -0
- package/dist/src/gate/recipe-reconcile.d.ts.map +1 -0
- package/dist/src/gate/recipe-reconcile.js +325 -0
- package/dist/src/gate/recipe-reconcile.js.map +1 -0
- package/dist/src/gate/reply-judge.d.ts +116 -0
- package/dist/src/gate/reply-judge.d.ts.map +1 -0
- package/dist/src/gate/reply-judge.js +467 -0
- package/dist/src/gate/reply-judge.js.map +1 -0
- package/dist/src/gate/types.d.ts +229 -8
- package/dist/src/gate/types.d.ts.map +1 -1
- package/dist/src/heartbeat/heartbeat.d.ts +184 -0
- package/dist/src/heartbeat/heartbeat.d.ts.map +1 -0
- package/dist/src/heartbeat/heartbeat.js +752 -0
- package/dist/src/heartbeat/heartbeat.js.map +1 -0
- package/dist/src/heartbeat/reminder-time.d.ts +5 -0
- package/dist/src/heartbeat/reminder-time.d.ts.map +1 -0
- package/dist/src/heartbeat/reminder-time.js +107 -0
- package/dist/src/heartbeat/reminder-time.js.map +1 -0
- package/dist/src/index.d.ts +10 -4
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +7 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/mcpl/capability-mask.d.ts.map +1 -1
- package/dist/src/mcpl/capability-mask.js +3 -2
- package/dist/src/mcpl/capability-mask.js.map +1 -1
- package/dist/src/mcpl/channel-registry.d.ts +433 -113
- package/dist/src/mcpl/channel-registry.d.ts.map +1 -1
- package/dist/src/mcpl/channel-registry.js +1154 -435
- package/dist/src/mcpl/channel-registry.js.map +1 -1
- package/dist/src/mcpl/conversation-router.d.ts +16 -8
- package/dist/src/mcpl/conversation-router.d.ts.map +1 -1
- package/dist/src/mcpl/conversation-router.js +29 -15
- 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 +14 -2
- package/dist/src/mcpl/convert-block.js.map +1 -1
- package/dist/src/mcpl/hook-orchestrator.d.ts +7 -1
- package/dist/src/mcpl/hook-orchestrator.d.ts.map +1 -1
- package/dist/src/mcpl/hook-orchestrator.js +32 -7
- package/dist/src/mcpl/hook-orchestrator.js.map +1 -1
- package/dist/src/mcpl/inbound-source.d.ts +26 -10
- package/dist/src/mcpl/inbound-source.d.ts.map +1 -1
- package/dist/src/mcpl/inbound-source.js +40 -69
- package/dist/src/mcpl/inbound-source.js.map +1 -1
- package/dist/src/mcpl/index.d.ts +5 -1
- package/dist/src/mcpl/index.d.ts.map +1 -1
- package/dist/src/mcpl/index.js +4 -0
- package/dist/src/mcpl/index.js.map +1 -1
- package/dist/src/mcpl/inference-router.d.ts +14 -2
- package/dist/src/mcpl/inference-router.d.ts.map +1 -1
- package/dist/src/mcpl/inference-router.js +73 -28
- package/dist/src/mcpl/inference-router.js.map +1 -1
- package/dist/src/mcpl/prose-grammar.d.ts +4 -0
- package/dist/src/mcpl/prose-grammar.d.ts.map +1 -1
- package/dist/src/mcpl/prose-grammar.js +6 -0
- package/dist/src/mcpl/prose-grammar.js.map +1 -1
- package/dist/src/mcpl/protocol-family.d.ts.map +1 -1
- package/dist/src/mcpl/protocol-family.js +3 -0
- package/dist/src/mcpl/protocol-family.js.map +1 -1
- package/dist/src/mcpl/push-coalescer.d.ts +20 -2
- package/dist/src/mcpl/push-coalescer.d.ts.map +1 -1
- package/dist/src/mcpl/push-coalescer.js +33 -11
- package/dist/src/mcpl/push-coalescer.js.map +1 -1
- package/dist/src/mcpl/reference-fetcher.d.ts +63 -42
- package/dist/src/mcpl/reference-fetcher.d.ts.map +1 -1
- package/dist/src/mcpl/reference-fetcher.js +177 -145
- package/dist/src/mcpl/reference-fetcher.js.map +1 -1
- package/dist/src/mcpl/references.d.ts +380 -46
- package/dist/src/mcpl/references.d.ts.map +1 -1
- package/dist/src/mcpl/references.js +736 -77
- package/dist/src/mcpl/references.js.map +1 -1
- package/dist/src/mcpl/server-connection.d.ts +93 -4
- package/dist/src/mcpl/server-connection.d.ts.map +1 -1
- package/dist/src/mcpl/server-connection.js +176 -11
- package/dist/src/mcpl/server-connection.js.map +1 -1
- package/dist/src/mcpl/tags.d.ts +9 -2
- package/dist/src/mcpl/tags.d.ts.map +1 -1
- package/dist/src/mcpl/tags.js +12 -2
- package/dist/src/mcpl/tags.js.map +1 -1
- package/dist/src/mcpl/tool-lifecycle.d.ts +11 -0
- package/dist/src/mcpl/tool-lifecycle.d.ts.map +1 -1
- package/dist/src/mcpl/tool-lifecycle.js +21 -0
- package/dist/src/mcpl/tool-lifecycle.js.map +1 -1
- package/dist/src/mcpl/tool-presence.d.ts +311 -0
- package/dist/src/mcpl/tool-presence.d.ts.map +1 -0
- package/dist/src/mcpl/tool-presence.js +697 -0
- package/dist/src/mcpl/tool-presence.js.map +1 -0
- package/dist/src/mcpl/tool-result-normalize.d.ts +9 -3
- package/dist/src/mcpl/tool-result-normalize.d.ts.map +1 -1
- package/dist/src/mcpl/tool-result-normalize.js +14 -6
- package/dist/src/mcpl/tool-result-normalize.js.map +1 -1
- package/dist/src/mcpl/tool-signature.d.ts +46 -0
- package/dist/src/mcpl/tool-signature.d.ts.map +1 -0
- package/dist/src/mcpl/tool-signature.js +321 -0
- package/dist/src/mcpl/tool-signature.js.map +1 -0
- package/dist/src/mcpl/toolset-host.d.ts +251 -0
- package/dist/src/mcpl/toolset-host.d.ts.map +1 -0
- package/dist/src/mcpl/toolset-host.js +720 -0
- package/dist/src/mcpl/toolset-host.js.map +1 -0
- package/dist/src/mcpl/toolsets-module.d.ts +83 -0
- package/dist/src/mcpl/toolsets-module.d.ts.map +1 -0
- package/dist/src/mcpl/toolsets-module.js +523 -0
- package/dist/src/mcpl/toolsets-module.js.map +1 -0
- package/dist/src/mcpl/transport.d.ts +2 -2
- package/dist/src/mcpl/transport.d.ts.map +1 -1
- package/dist/src/mcpl/transport.js +3 -2
- package/dist/src/mcpl/transport.js.map +1 -1
- package/dist/src/mcpl/types.d.ts +24 -2
- package/dist/src/mcpl/types.d.ts.map +1 -1
- package/dist/src/mcpl/types.js.map +1 -1
- package/dist/src/mcpl/visible-content.d.ts +7 -9
- package/dist/src/mcpl/visible-content.d.ts.map +1 -1
- package/dist/src/mcpl/visible-content.js +21 -9
- package/dist/src/mcpl/visible-content.js.map +1 -1
- package/dist/src/module-registry.d.ts +27 -9
- package/dist/src/module-registry.d.ts.map +1 -1
- package/dist/src/module-registry.js +77 -17
- package/dist/src/module-registry.js.map +1 -1
- package/dist/src/modules/discord/index.js +1 -1
- package/dist/src/modules/discord/index.js.map +1 -1
- package/dist/src/modules/history/index.d.ts +2 -1
- package/dist/src/modules/history/index.d.ts.map +1 -1
- package/dist/src/modules/history/index.js +73 -28
- package/dist/src/modules/history/index.js.map +1 -1
- package/dist/src/modules/history/semantic.d.ts +108 -6
- package/dist/src/modules/history/semantic.d.ts.map +1 -1
- package/dist/src/modules/history/semantic.js +273 -57
- package/dist/src/modules/history/semantic.js.map +1 -1
- package/dist/src/modules/workspace/answers.d.ts +22 -0
- package/dist/src/modules/workspace/answers.d.ts.map +1 -0
- package/dist/src/modules/workspace/answers.js +123 -0
- package/dist/src/modules/workspace/answers.js.map +1 -0
- package/dist/src/modules/workspace/branch-intent.d.ts +5 -3
- package/dist/src/modules/workspace/branch-intent.d.ts.map +1 -1
- package/dist/src/modules/workspace/branch-intent.js +6 -2
- package/dist/src/modules/workspace/branch-intent.js.map +1 -1
- package/dist/src/modules/workspace/direct-write.d.ts +184 -0
- package/dist/src/modules/workspace/direct-write.d.ts.map +1 -0
- package/dist/src/modules/workspace/direct-write.js +417 -0
- package/dist/src/modules/workspace/direct-write.js.map +1 -0
- package/dist/src/modules/workspace/disk-agreement.d.ts +33 -11
- package/dist/src/modules/workspace/disk-agreement.d.ts.map +1 -1
- package/dist/src/modules/workspace/disk-agreement.js +48 -17
- package/dist/src/modules/workspace/disk-agreement.js.map +1 -1
- package/dist/src/modules/workspace/edit-text.d.ts +27 -12
- package/dist/src/modules/workspace/edit-text.d.ts.map +1 -1
- package/dist/src/modules/workspace/edit-text.js +61 -29
- package/dist/src/modules/workspace/edit-text.js.map +1 -1
- package/dist/src/modules/workspace/effects.d.ts +10 -0
- package/dist/src/modules/workspace/effects.d.ts.map +1 -1
- package/dist/src/modules/workspace/effects.js +21 -14
- package/dist/src/modules/workspace/effects.js.map +1 -1
- package/dist/src/modules/workspace/index.d.ts +308 -78
- package/dist/src/modules/workspace/index.d.ts.map +1 -1
- package/dist/src/modules/workspace/index.js +2103 -720
- package/dist/src/modules/workspace/index.js.map +1 -1
- package/dist/src/modules/workspace/observe.d.ts +75 -63
- package/dist/src/modules/workspace/observe.d.ts.map +1 -1
- package/dist/src/modules/workspace/observe.js +366 -180
- package/dist/src/modules/workspace/observe.js.map +1 -1
- package/dist/src/modules/workspace/read-page.d.ts +41 -0
- package/dist/src/modules/workspace/read-page.d.ts.map +1 -0
- package/dist/src/modules/workspace/read-page.js +219 -0
- package/dist/src/modules/workspace/read-page.js.map +1 -0
- package/dist/src/modules/workspace/reconcile.d.ts.map +1 -1
- package/dist/src/modules/workspace/reconcile.js +26 -16
- package/dist/src/modules/workspace/reconcile.js.map +1 -1
- package/dist/src/modules/workspace/result-text.d.ts +68 -0
- package/dist/src/modules/workspace/result-text.d.ts.map +1 -0
- package/dist/src/modules/workspace/result-text.js +94 -0
- package/dist/src/modules/workspace/result-text.js.map +1 -0
- package/dist/src/modules/workspace/sync.d.ts +9 -0
- package/dist/src/modules/workspace/sync.d.ts.map +1 -1
- package/dist/src/modules/workspace/sync.js +14 -0
- package/dist/src/modules/workspace/sync.js.map +1 -1
- package/dist/src/modules/workspace/text.d.ts +29 -12
- package/dist/src/modules/workspace/text.d.ts.map +1 -1
- package/dist/src/modules/workspace/text.js +35 -33
- package/dist/src/modules/workspace/text.js.map +1 -1
- package/dist/src/modules/workspace/types.d.ts +137 -60
- 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.map +1 -1
- package/dist/src/modules/workspace/watcher.js +8 -3
- package/dist/src/modules/workspace/watcher.js.map +1 -1
- package/dist/src/prose-drafts.d.ts +4 -3
- package/dist/src/prose-drafts.d.ts.map +1 -1
- package/dist/src/prose-drafts.js +3 -2
- package/dist/src/prose-drafts.js.map +1 -1
- package/dist/src/reasoning-loss-notice.d.ts +23 -0
- package/dist/src/reasoning-loss-notice.d.ts.map +1 -0
- package/dist/src/reasoning-loss-notice.js +50 -0
- package/dist/src/reasoning-loss-notice.js.map +1 -0
- package/dist/src/reasoning-loss.d.ts +24 -0
- package/dist/src/reasoning-loss.d.ts.map +1 -0
- package/dist/src/reasoning-loss.js +102 -0
- package/dist/src/reasoning-loss.js.map +1 -0
- package/dist/src/send-tools.d.ts +3 -2
- package/dist/src/send-tools.d.ts.map +1 -1
- package/dist/src/send-tools.js +3 -2
- package/dist/src/send-tools.js.map +1 -1
- package/dist/src/sent-rows.d.ts +59 -0
- package/dist/src/sent-rows.d.ts.map +1 -0
- package/dist/src/sent-rows.js +145 -0
- package/dist/src/sent-rows.js.map +1 -0
- package/dist/src/silent-heartbeat.d.ts +17 -10
- package/dist/src/silent-heartbeat.d.ts.map +1 -1
- package/dist/src/silent-heartbeat.js.map +1 -1
- package/dist/src/stable-hash.d.ts +3 -0
- package/dist/src/stable-hash.d.ts.map +1 -0
- package/dist/src/stable-hash.js +15 -0
- package/dist/src/stable-hash.js.map +1 -0
- package/dist/src/stored-injections.d.ts +99 -0
- package/dist/src/stored-injections.d.ts.map +1 -0
- package/dist/src/stored-injections.js +106 -0
- package/dist/src/stored-injections.js.map +1 -0
- package/dist/src/text-as-stored.d.ts +4 -3
- package/dist/src/text-as-stored.d.ts.map +1 -1
- package/dist/src/text-as-stored.js +4 -3
- package/dist/src/text-as-stored.js.map +1 -1
- package/dist/src/thinking-drops.d.ts +74 -0
- package/dist/src/thinking-drops.d.ts.map +1 -0
- package/dist/src/thinking-drops.js +96 -0
- package/dist/src/thinking-drops.js.map +1 -0
- package/dist/src/tool-args.d.ts +12 -0
- package/dist/src/tool-args.d.ts.map +1 -1
- package/dist/src/tool-args.js +35 -1
- package/dist/src/tool-args.js.map +1 -1
- package/dist/src/tool-image-ledger.d.ts +9 -8
- package/dist/src/tool-image-ledger.d.ts.map +1 -1
- package/dist/src/tool-image-ledger.js +9 -8
- package/dist/src/tool-image-ledger.js.map +1 -1
- package/dist/src/tool-presentation.d.ts.map +1 -1
- package/dist/src/tool-presentation.js +3 -1
- package/dist/src/tool-presentation.js.map +1 -1
- package/dist/src/tool-result-guard.d.ts +12 -6
- package/dist/src/tool-result-guard.d.ts.map +1 -1
- package/dist/src/tool-result-guard.js +44 -17
- package/dist/src/tool-result-guard.js.map +1 -1
- package/dist/src/tool-result-history.d.ts +176 -24
- package/dist/src/tool-result-history.d.ts.map +1 -1
- package/dist/src/tool-result-history.js +411 -91
- package/dist/src/tool-result-history.js.map +1 -1
- package/dist/src/tune-out/coordinator.d.ts +17 -9
- package/dist/src/tune-out/coordinator.d.ts.map +1 -1
- package/dist/src/tune-out/coordinator.js +84 -37
- package/dist/src/tune-out/coordinator.js.map +1 -1
- package/dist/src/tune-out/tools.d.ts +4 -1
- package/dist/src/tune-out/tools.d.ts.map +1 -1
- package/dist/src/types/agent.d.ts +217 -7
- package/dist/src/types/agent.d.ts.map +1 -1
- package/dist/src/types/events.d.ts +33 -9
- package/dist/src/types/events.d.ts.map +1 -1
- package/dist/src/types/framework.d.ts +39 -3
- package/dist/src/types/framework.d.ts.map +1 -1
- package/dist/src/types/module.d.ts +95 -9
- package/dist/src/types/module.d.ts.map +1 -1
- package/dist/src/types/trace.d.ts +91 -3
- package/dist/src/types/trace.d.ts.map +1 -1
- package/package.json +5 -4
- package/src/agent.ts +661 -67
- package/src/api/server.ts +5 -4
- package/src/auto-continue.ts +43 -0
- package/src/code-execution/isolate/scripts.ts +11 -3
- package/src/cut-off-round.ts +98 -0
- package/src/framework.ts +6168 -1540
- package/src/gate/event-gate.ts +2895 -405
- package/src/gate/index.ts +10 -1
- package/src/gate/recipe-reconcile.ts +355 -0
- package/src/gate/reply-judge.ts +512 -0
- package/src/gate/types.ts +234 -9
- package/src/heartbeat/heartbeat.ts +804 -0
- package/src/heartbeat/reminder-time.ts +107 -0
- package/src/index.ts +11 -4
- package/src/mcpl/capability-mask.ts +3 -2
- package/src/mcpl/channel-registry.ts +1222 -468
- package/src/mcpl/conversation-router.ts +34 -16
- package/src/mcpl/convert-block.ts +14 -1
- package/src/mcpl/hook-orchestrator.ts +33 -6
- package/src/mcpl/inbound-source.ts +42 -69
- package/src/mcpl/index.ts +6 -1
- package/src/mcpl/inference-router.ts +79 -34
- package/src/mcpl/prose-grammar.ts +7 -0
- package/src/mcpl/protocol-family.ts +2 -0
- package/src/mcpl/push-coalescer.ts +51 -13
- package/src/mcpl/reference-fetcher.ts +201 -162
- package/src/mcpl/references.ts +851 -77
- package/src/mcpl/server-connection.ts +189 -11
- package/src/mcpl/tags.ts +13 -2
- package/src/mcpl/tool-lifecycle.ts +21 -0
- package/src/mcpl/tool-presence.ts +716 -0
- package/src/mcpl/tool-result-normalize.ts +18 -6
- package/src/mcpl/tool-signature.ts +316 -0
- package/src/mcpl/toolset-host.ts +727 -0
- package/src/mcpl/toolsets-module.ts +545 -0
- package/src/mcpl/transport.ts +3 -2
- package/src/mcpl/types.ts +25 -2
- package/src/mcpl/visible-content.ts +22 -9
- package/src/module-registry.ts +85 -26
- package/src/modules/discord/index.ts +1 -1
- package/src/modules/history/index.ts +70 -30
- package/src/modules/history/semantic.ts +308 -54
- package/src/modules/workspace/answers.ts +133 -0
- package/src/modules/workspace/branch-intent.ts +10 -5
- package/src/modules/workspace/direct-write.ts +460 -0
- package/src/modules/workspace/disk-agreement.ts +52 -21
- package/src/modules/workspace/edit-text.ts +84 -35
- package/src/modules/workspace/effects.ts +22 -13
- package/src/modules/workspace/index.ts +2142 -723
- package/src/modules/workspace/observe.ts +381 -177
- package/src/modules/workspace/read-page.ts +228 -0
- package/src/modules/workspace/reconcile.ts +27 -15
- package/src/modules/workspace/result-text.ts +121 -0
- package/src/modules/workspace/sync.ts +16 -0
- package/src/modules/workspace/text.ts +58 -32
- package/src/modules/workspace/types.ts +137 -60
- package/src/modules/workspace/watcher.ts +8 -3
- package/src/prose-drafts.ts +4 -3
- package/src/reasoning-loss-notice.ts +62 -0
- package/src/reasoning-loss.ts +120 -0
- package/src/send-tools.ts +3 -2
- package/src/sent-rows.ts +162 -0
- package/src/silent-heartbeat.ts +17 -10
- package/src/stable-hash.ts +14 -0
- package/src/stored-injections.ts +131 -0
- package/src/text-as-stored.ts +4 -3
- package/src/thinking-drops.ts +135 -0
- package/src/tool-args.ts +34 -1
- package/src/tool-image-ledger.ts +9 -8
- package/src/tool-presentation.ts +3 -1
- package/src/tool-result-guard.ts +45 -17
- package/src/tool-result-history.ts +471 -90
- package/src/tune-out/coordinator.ts +80 -37
- package/src/tune-out/tools.ts +4 -1
- package/src/types/agent.ts +220 -7
- package/src/types/events.ts +33 -9
- package/src/types/framework.ts +36 -3
- package/src/types/module.ts +91 -9
- package/src/types/trace.ts +94 -3
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
import { randomUUID } from 'node:crypto';
|
|
19
19
|
import type { ContentBlock } from '@animalabs/membrane';
|
|
20
20
|
import type { StoredMessage } from '@animalabs/context-manager';
|
|
21
|
-
import type { ChannelRegistry, TuneOutParams } from '../mcpl/channel-registry.js';
|
|
21
|
+
import type { ChannelRef, ChannelRegistry, TuneOutParams } from '../mcpl/channel-registry.js';
|
|
22
22
|
import type { McplServerRegistry } from '../mcpl/server-registry.js';
|
|
23
23
|
import { CapabilityGrant } from '../mcpl/capability-grant.js';
|
|
24
24
|
import { armAfter, armAt } from '../deadline-timer.js';
|
|
@@ -45,7 +45,7 @@ const CUT_MARK = " [cut to fit; the whole message is in the channel's history]";
|
|
|
45
45
|
* its transport is now where the repeat tried to open it again (`transport`,
|
|
46
46
|
* from the framework's dispatch), then how to change the settings.
|
|
47
47
|
*/
|
|
48
|
-
export function alreadyTunedOutText(
|
|
48
|
+
export function alreadyTunedOutText(shown: string, p: TuneOutParams, transport?: string): string {
|
|
49
49
|
// A duration so long its end is past what a Date can hold has no time to show.
|
|
50
50
|
const expires = p.expiresAtMs !== undefined ? new Date(p.expiresAtMs) : undefined;
|
|
51
51
|
const until = expires && Number.isFinite(expires.getTime())
|
|
@@ -53,7 +53,7 @@ export function alreadyTunedOutText(channelId: string, p: TuneOutParams, transpo
|
|
|
53
53
|
: '';
|
|
54
54
|
// A thrown error's words may end without a stop.
|
|
55
55
|
const now = transport === undefined ? '' : /[.!?]$/.test(transport) ? `${transport} ` : `${transport}. `;
|
|
56
|
-
return `Nothing changed${transport !== undefined ? ' in the tune-out' : ''}: ${JSON.stringify(
|
|
56
|
+
return `Nothing changed${transport !== undefined ? ' in the tune-out' : ''}: ${JSON.stringify(shown)} is already `
|
|
57
57
|
+ `tuned out, with cadenceSeconds ${p.cadenceSeconds}, backlogCap ${p.backlogCap} and maxWakes ${p.maxWakes}${until}. `
|
|
58
58
|
+ now
|
|
59
59
|
+ 'To change those, cancel it first with tune_out mode "cancel", which delivers its backlog to you now, then call '
|
|
@@ -113,7 +113,7 @@ export interface TuneOutFrameworkHooks {
|
|
|
113
113
|
/** Move the subconscious window anchor (never forward past active epochs). */
|
|
114
114
|
setSubconsciousAnchor: (sequence: number) => void;
|
|
115
115
|
/** True when a channel is bound to a conversation-fork agent. */
|
|
116
|
-
isForkBound: (
|
|
116
|
+
isForkBound: (channel: ChannelRef) => boolean;
|
|
117
117
|
/** Gate privileged-users list (#77: privileged authors wake, like mentions). */
|
|
118
118
|
isPrivilegedAuthor: (authorId: string | null | undefined) => boolean;
|
|
119
119
|
/** speak_in_channel master switch (recipe-side, canary-gated). */
|
|
@@ -144,6 +144,15 @@ export class TuneOutCoordinator {
|
|
|
144
144
|
return `${serverId}\0${channelId}`;
|
|
145
145
|
}
|
|
146
146
|
|
|
147
|
+
/** A channel as the resident and the subconscious are shown it
|
|
148
|
+
* (ChannelRegistry.nameShown): its id, or, where another server registers
|
|
149
|
+
* the same id, its server-qualified name, which tune_out and
|
|
150
|
+
* cancel_tuneout take back; or, for a channel no string picks alone, its
|
|
151
|
+
* id and its server. */
|
|
152
|
+
private shown(serverId: string, channelId: string): string {
|
|
153
|
+
return this.channelRegistry.nameShown({ serverId, channelId });
|
|
154
|
+
}
|
|
155
|
+
|
|
147
156
|
/** Restart cadence + expiry timers and re-anchor after a process restart. */
|
|
148
157
|
resumeActiveEpochs(): void {
|
|
149
158
|
let oldestAnchor: number | null = null;
|
|
@@ -232,17 +241,17 @@ export class TuneOutCoordinator {
|
|
|
232
241
|
+ 'whoever runs this host.',
|
|
233
242
|
};
|
|
234
243
|
}
|
|
235
|
-
if (this.hooks.isForkBound(channelId)) {
|
|
244
|
+
if (this.hooks.isForkBound({ serverId, channelId })) {
|
|
236
245
|
return {
|
|
237
246
|
ok: false,
|
|
238
|
-
error: `Nothing changed: a conversation is bound to ${JSON.stringify(channelId)}, so its messages go to that `
|
|
247
|
+
error: `Nothing changed: a conversation is bound to ${JSON.stringify(this.shown(serverId, channelId))}, so its messages go to that `
|
|
239
248
|
+ "conversation, and tune_out won't divert a channel while one is. Calling tune_out on it again won't change "
|
|
240
249
|
+ 'that until the conversation ends, which happens only once the channel has been quiet for a while. Tune '
|
|
241
250
|
+ 'out a different channel, or ask whoever runs this host if this one should be diverted.',
|
|
242
251
|
};
|
|
243
252
|
}
|
|
244
253
|
const current = this.channelRegistry.getTuneOutState(serverId, channelId);
|
|
245
|
-
if (current) return { ok: false, error: alreadyTunedOutText(channelId, current.params), alreadyTunedOut: true };
|
|
254
|
+
if (current) return { ok: false, error: alreadyTunedOutText(this.shown(serverId, channelId), current.params), alreadyTunedOut: true };
|
|
246
255
|
// A tool's input reaches here as the model wrote it, and the store can't
|
|
247
256
|
// keep a NaN or an Infinity: its append would throw after the registry
|
|
248
257
|
// had marked the channel tuned out. So each option is read as a number
|
|
@@ -328,7 +337,7 @@ export class TuneOutCoordinator {
|
|
|
328
337
|
const ended = this.channelRegistry.cancelTuneOut(serverId, channelId, 'open', source);
|
|
329
338
|
if (!ended) {
|
|
330
339
|
// Its reader is the resident's tune_out: cancel_tuneout finds the channel first.
|
|
331
|
-
return { ok: false, error: this.notTunedOut(channelId, 'you') };
|
|
340
|
+
return { ok: false, error: this.notTunedOut(this.shown(serverId, channelId), 'you') };
|
|
332
341
|
}
|
|
333
342
|
this.clearTimers(serverId, channelId);
|
|
334
343
|
this.divertedSinceInvocation.delete(this.key(serverId, channelId));
|
|
@@ -359,10 +368,12 @@ export class TuneOutCoordinator {
|
|
|
359
368
|
.join('\n');
|
|
360
369
|
return `${authorOf(m)}: ${text}`;
|
|
361
370
|
};
|
|
362
|
-
|
|
371
|
+
// The channel as the resident and the subconscious are shown it.
|
|
372
|
+
const name = this.shown(serverId, channelId);
|
|
373
|
+
const lifecycle = `[Tune-out: ${name} cancelled — ${reason}, ${ended.wakeCount} wake${ended.wakeCount === 1 ? '' : 's'}]`;
|
|
363
374
|
const render = (lines: string[], truncated: number): string => {
|
|
364
375
|
const attrs = [
|
|
365
|
-
`channel="${
|
|
376
|
+
`channel="${name}"`,
|
|
366
377
|
`messages=${backlog.length}`,
|
|
367
378
|
...(truncated > 0 ? [`truncated=${truncated} (oldest; fetch_history covers the rest)`] : []),
|
|
368
379
|
];
|
|
@@ -441,7 +452,9 @@ export class TuneOutCoordinator {
|
|
|
441
452
|
this.hooks.addMessage(
|
|
442
453
|
subName,
|
|
443
454
|
[{ type: 'text', text: subconsciousNote }],
|
|
444
|
-
|
|
455
|
+
// With its server: a conversational row whose channel the framework
|
|
456
|
+
// reads (repinChannel), where another server's channel can share the id.
|
|
457
|
+
{ kind: 'subconscious-note', channelId, serverId, epochId },
|
|
445
458
|
);
|
|
446
459
|
}
|
|
447
460
|
const primary = this.hooks.primaryName();
|
|
@@ -467,7 +480,7 @@ export class TuneOutCoordinator {
|
|
|
467
480
|
: '';
|
|
468
481
|
this.hooks.addMessage(
|
|
469
482
|
'user',
|
|
470
|
-
[{ type: 'text', text: `[Tune-out cancelled: ${channelId} — ${reason}.${truncNote}${heldNote}]` }],
|
|
483
|
+
[{ type: 'text', text: `[Tune-out cancelled: ${this.shown(serverId, channelId)} — ${reason}.${truncNote}${heldNote}]` }],
|
|
471
484
|
{ system: true, kind: 'tune-out-cancel-report', channelId },
|
|
472
485
|
subName,
|
|
473
486
|
);
|
|
@@ -481,7 +494,7 @@ export class TuneOutCoordinator {
|
|
|
481
494
|
subName,
|
|
482
495
|
);
|
|
483
496
|
}
|
|
484
|
-
this.hooks.requestInference(subName, `tune-out cancelled: ${
|
|
497
|
+
this.hooks.requestInference(subName, `tune-out cancelled: ${name}`, 'tune-out');
|
|
485
498
|
}
|
|
486
499
|
this.hooks.emitTrace({ type: 'tune-out:cancelled', serverId, channelId, epochId, reason, wakeCount: ended.wakeCount });
|
|
487
500
|
return { ok: true };
|
|
@@ -649,16 +662,17 @@ export class TuneOutCoordinator {
|
|
|
649
662
|
if (!subName) return;
|
|
650
663
|
const key = this.key(serverId, channelId);
|
|
651
664
|
|
|
665
|
+
const shown = this.shown(serverId, channelId);
|
|
652
666
|
const notice = trigger === 'wake'
|
|
653
|
-
? `[Tune-out wake: ${
|
|
654
|
-
: `[Tune-out cadence: ${
|
|
667
|
+
? `[Tune-out wake: ${shown} — ${count} addressed message${count === 1 ? '' : 's'}]`
|
|
668
|
+
: `[Tune-out cadence: ${shown} — ${count} diverted message${count === 1 ? '' : 's'} since your last look]`;
|
|
655
669
|
this.hooks.addMessage(
|
|
656
670
|
'user',
|
|
657
671
|
[{ type: 'text', text: notice }],
|
|
658
672
|
{ system: true, kind: `tune-out-${trigger}`, channelId },
|
|
659
673
|
subName,
|
|
660
674
|
);
|
|
661
|
-
this.hooks.requestInference(subName, `tune-out ${trigger}: ${
|
|
675
|
+
this.hooks.requestInference(subName, `tune-out ${trigger}: ${shown}`, 'tune-out');
|
|
662
676
|
// Counted from here only once the turn has been asked for, so a turn that
|
|
663
677
|
// throws leaves its messages for the next period's turn.
|
|
664
678
|
this.divertedSinceInvocation.set(key, 0);
|
|
@@ -740,6 +754,8 @@ export class TuneOutCoordinator {
|
|
|
740
754
|
async handleSubconsciousTool(
|
|
741
755
|
name: string,
|
|
742
756
|
input: Record<string, unknown>,
|
|
757
|
+
/** The calling turn's own channels, for a call made inside it (the framework's callOwnChannels). */
|
|
758
|
+
own: readonly ChannelRef[] = [],
|
|
743
759
|
): Promise<{ success: boolean; data?: unknown; error?: string; isError?: boolean }> {
|
|
744
760
|
switch (name) {
|
|
745
761
|
case 'deliver_summary': {
|
|
@@ -755,19 +771,48 @@ export class TuneOutCoordinator {
|
|
|
755
771
|
}
|
|
756
772
|
const subName = this.hooks.subconsciousName();
|
|
757
773
|
if (!subName) return { success: false, error: 'subconscious not configured', isError: true };
|
|
758
|
-
// Verbatim, under its own participant name, into the resident's window
|
|
774
|
+
// Verbatim, under its own participant name, into the resident's window,
|
|
775
|
+
// tagged with the channel the name means and its server, since the
|
|
776
|
+
// framework reads a conversational row's channel (repinChannel). The
|
|
777
|
+
// name means what it means to every channel tool: inside the calling
|
|
778
|
+
// turn, the id of one of the turn's own channels means that channel,
|
|
779
|
+
// refused where its server no longer registers it or the turn has
|
|
780
|
+
// channels with that id on two servers (ownChannelFor); otherwise a
|
|
781
|
+
// name several registered channels answer to is refused with them
|
|
782
|
+
// (sharedNameRefusalFor). So no row is left for a re-pin to read as
|
|
783
|
+
// another server's channel. A name no registered channel answers to
|
|
784
|
+
// is kept as given, with no server, which a re-pin reads by name when
|
|
785
|
+
// it weighs the row, as it reads any message without its server.
|
|
786
|
+
const mine = this.channelRegistry.ownChannelFor(channelId, own, 'deliver');
|
|
787
|
+
if (mine && 'error' in mine) return { success: false, error: mine.error, isError: true };
|
|
788
|
+
const shared = mine ? undefined : this.channelRegistry.sharedNameRefusalFor(channelId, 'nothing was delivered');
|
|
789
|
+
if (shared) return { success: false, error: shared, isError: true };
|
|
790
|
+
const [named] = mine ? [mine.channel] : this.channelRegistry.channelsNamed(channelId);
|
|
759
791
|
this.hooks.addMessage(subName, [{ type: 'text', text }], {
|
|
760
792
|
kind: 'subconscious-summary',
|
|
761
|
-
channelId,
|
|
793
|
+
...(named ? { channelId: named.channelId, serverId: named.serverId } : { channelId }),
|
|
762
794
|
});
|
|
763
795
|
return { success: true, data: { delivered: true } };
|
|
764
796
|
}
|
|
765
797
|
case 'cancel_tuneout': {
|
|
766
|
-
const
|
|
767
|
-
|
|
768
|
-
|
|
798
|
+
const name = String(input.channelId ?? '');
|
|
799
|
+
// The name means what it means to every channel tool, the
|
|
800
|
+
// resident's tune_out included: inside the calling turn, the id of
|
|
801
|
+
// one of the turn's own channels means that channel (ownChannelFor);
|
|
802
|
+
// otherwise a name several registered channels answer to is refused
|
|
803
|
+
// (channelsNamed), whichever of them is tuned out, never taken to be
|
|
804
|
+
// the tuned-out one.
|
|
805
|
+
const mine = this.channelRegistry.ownChannelFor(name, own);
|
|
806
|
+
if (mine && 'error' in mine) return { success: false, error: mine.error, isError: true };
|
|
807
|
+
const named = mine ? [mine.channel] : this.channelRegistry.channelsNamed(name);
|
|
808
|
+
const shared = mine ? undefined : this.channelRegistry.sharedNameRefusalFor(name);
|
|
809
|
+
if (shared) return { success: false, error: shared, isError: true };
|
|
810
|
+
const channel = named[0];
|
|
811
|
+
if (!channel || !this.channelRegistry.getTuneOutState(channel.serverId, channel.channelId)) {
|
|
812
|
+
return { success: false, error: this.notTunedOut(name, 'the resident'), isError: true };
|
|
813
|
+
}
|
|
769
814
|
const note = typeof input.text === 'string' && input.text.trim() ? input.text.trim() : undefined;
|
|
770
|
-
const result = this.cancel(
|
|
815
|
+
const result = this.cancel(channel.serverId, channel.channelId, 'subconscious', 'subconscious judgment', note);
|
|
771
816
|
return result.ok
|
|
772
817
|
? { success: true, data: { cancelled: true } }
|
|
773
818
|
: { success: false, error: result.error, isError: true };
|
|
@@ -817,7 +862,11 @@ export class TuneOutCoordinator {
|
|
|
817
862
|
if (!text) {
|
|
818
863
|
return { success: false, error: 'Nothing was posted: speak_in_channel needs the message in "text".', isError: true };
|
|
819
864
|
}
|
|
820
|
-
|
|
865
|
+
// Inside the calling turn, the id of one of the turn's own channels
|
|
866
|
+
// means that channel, as for every channel tool (ownChannelFor).
|
|
867
|
+
const mine = this.channelRegistry.ownChannelFor(channelId, own, 'publish');
|
|
868
|
+
if (mine && 'error' in mine) return { success: false, error: mine.error, isError: true };
|
|
869
|
+
return this.channelRegistry.publishForAgent(mine ? mine.channel : channelId, text, this.hooks.subconsciousName() ?? 'Subconscious');
|
|
821
870
|
}
|
|
822
871
|
default:
|
|
823
872
|
return { success: false, error: `unknown subconscious tool: ${name}`, isError: true };
|
|
@@ -825,32 +874,26 @@ export class TuneOutCoordinator {
|
|
|
825
874
|
}
|
|
826
875
|
|
|
827
876
|
/**
|
|
828
|
-
* A cancel of a channel that isn't tuned out
|
|
829
|
-
*
|
|
877
|
+
* A cancel of a channel that isn't tuned out, by the name the caller gave
|
|
878
|
+
* or knows it by: which channels are, so the next call can name one, and
|
|
879
|
+
* how a tune-out ends without one. `backlogTo`
|
|
830
880
|
* names the resident as the message's reader knows it: "you" to the
|
|
831
881
|
* resident, "the resident" to the subconscious. It speaks of connected
|
|
832
882
|
* channels because listActive reads the registered ones: removing a server
|
|
833
883
|
* drops its channels and keeps their tune-outs, so a tune-out there is in
|
|
834
|
-
* neither this list nor
|
|
835
|
-
* about it.
|
|
884
|
+
* neither this list nor the name's lookup (channelsNamed, which reads the
|
|
885
|
+
* registered channels too), and the text claims nothing about it.
|
|
836
886
|
*/
|
|
837
|
-
private notTunedOut(
|
|
838
|
-
const active = this.listActive().map((e) => JSON.stringify(e.channelId));
|
|
887
|
+
private notTunedOut(name: string, backlogTo: 'you' | 'the resident'): string {
|
|
888
|
+
const active = this.listActive().map((e) => JSON.stringify(this.shown(e.serverId, e.channelId)));
|
|
839
889
|
const opening = active.length === 0
|
|
840
890
|
? 'no connected channel is tuned out now.'
|
|
841
|
-
: `no connected channel ${JSON.stringify(
|
|
891
|
+
: `no connected channel ${JSON.stringify(name)} is tuned out. Connected channels tuned out now: `
|
|
842
892
|
+ `${active.join(', ')}.`;
|
|
843
893
|
return `Nothing was cancelled: ${opening} A tune-out also ends by itself when its duration runs out, or at the `
|
|
844
894
|
+ `first wake past its wake budget, and its backlog goes to ${backlogTo} then.`;
|
|
845
895
|
}
|
|
846
896
|
|
|
847
|
-
private findByChannel(channelId: string): { serverId: string } | null {
|
|
848
|
-
for (const entry of this.listActive()) {
|
|
849
|
-
if (entry.channelId === channelId) return { serverId: entry.serverId };
|
|
850
|
-
}
|
|
851
|
-
return null;
|
|
852
|
-
}
|
|
853
|
-
|
|
854
897
|
/** Stop all timers (framework shutdown). */
|
|
855
898
|
stop(): void {
|
|
856
899
|
for (const timer of this.cadenceTimers.values()) clearTimeout(timer);
|
package/src/tune-out/tools.ts
CHANGED
|
@@ -113,7 +113,10 @@ export interface SubconsciousConfig {
|
|
|
113
113
|
* agent-prefixed identifier.
|
|
114
114
|
*/
|
|
115
115
|
name?: string;
|
|
116
|
-
/** Model id; defaults to the primary agent's (same-model side-process).
|
|
116
|
+
/** Model id; defaults to the primary agent's (same-model side-process).
|
|
117
|
+
* Another id, compared exactly, makes the subconscious leave out the
|
|
118
|
+
* fields that describe the primary's model, its window and its thinking
|
|
119
|
+
* binding (SUBCONSCIOUS_MODEL_FIELDS); nothing here sets its own. */
|
|
117
120
|
model?: string;
|
|
118
121
|
/**
|
|
119
122
|
* The voice/criteria mode block — recipe-side and co-authored with the
|
package/src/types/agent.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { ContentBlock, YieldingStream } from '@animalabs/membrane';
|
|
|
2
2
|
import type { ContextStrategy } from '@animalabs/context-manager';
|
|
3
3
|
import type { ToolCallId, ToolResult, ToolCall } from './events.js';
|
|
4
4
|
import type { SilentHeartbeatTick } from '../silent-heartbeat.js';
|
|
5
|
+
import type { WakeLine } from '../gate/types.js';
|
|
5
6
|
|
|
6
7
|
export type SameRoundThinkTextPolicy = 'public' | 'private';
|
|
7
8
|
export type SameRoundThinkTextPolicySource =
|
|
@@ -9,6 +10,25 @@ export type SameRoundThinkTextPolicySource =
|
|
|
9
10
|
| 'recipe'
|
|
10
11
|
| 'compatibility_default';
|
|
11
12
|
|
|
13
|
+
/** What a continuation's `[continue]` row says (InferenceRequest.autoContinueRun). */
|
|
14
|
+
export interface AutoContinueRun {
|
|
15
|
+
/** How the agent stops, as the row puts it ("call skip_reply"). */
|
|
16
|
+
stop: string;
|
|
17
|
+
/** The turn before ended in words some or all of which were held, not
|
|
18
|
+
* sent, because a send in it may already have posted where they were
|
|
19
|
+
* going. */
|
|
20
|
+
heldAfterSend?: boolean;
|
|
21
|
+
/** Set by the scheduler: the continuation is the turn's only cause. */
|
|
22
|
+
sole?: boolean;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** `AgentConfig.autoContinue` as an object (`true` means `{}`). */
|
|
26
|
+
export interface AutoContinueConfig {
|
|
27
|
+
/** Continuations in a row before the agent waits for the next event:
|
|
28
|
+
* a whole number, 1 to 20. Default 3. */
|
|
29
|
+
maxConsecutive?: number;
|
|
30
|
+
}
|
|
31
|
+
|
|
12
32
|
/**
|
|
13
33
|
* Configuration for an agent.
|
|
14
34
|
*/
|
|
@@ -62,7 +82,11 @@ export interface AgentConfig {
|
|
|
62
82
|
temperature?: number;
|
|
63
83
|
|
|
64
84
|
/** Max input tokens before framework breaks a yielding stream and
|
|
65
|
-
* restarts with recompiled (compressed) context. Default: 150000.
|
|
85
|
+
* restarts with recompiled (compressed) context. Default: 150000. Not
|
|
86
|
+
* checked mid-turn for an agent whose model binds its thinking
|
|
87
|
+
* (`thinkingBinding.binds`) with `physicalWindowTokens` set: a new stream
|
|
88
|
+
* there would take the turn's own earlier reasoning out of the request, and
|
|
89
|
+
* the window projection still guards the provider's hard cap. */
|
|
66
90
|
maxStreamTokens?: number;
|
|
67
91
|
|
|
68
92
|
/**
|
|
@@ -75,7 +99,9 @@ export interface AgentConfig {
|
|
|
75
99
|
* request the provider will 400 (issue #92: a legal compile can walk past
|
|
76
100
|
* the physical window mid-turn). The projection runs once a call on the
|
|
77
101
|
* stream has reported its prompt. Unset → no projection; only the
|
|
78
|
-
* maxStreamTokens restart applies.
|
|
102
|
+
* maxStreamTokens restart applies. A value is converted to a number as a
|
|
103
|
+
* comparison converts it, so a string such as "200000" reads as its number;
|
|
104
|
+
* one whose number isn't finite, such as null, reads as unset.
|
|
79
105
|
*/
|
|
80
106
|
physicalWindowTokens?: number;
|
|
81
107
|
|
|
@@ -133,7 +159,9 @@ export interface AgentConfig {
|
|
|
133
159
|
* Extended thinking config. When `enabled: true`, the agent runs with
|
|
134
160
|
* Anthropic's native extended thinking; responses include `thinking` blocks
|
|
135
161
|
* with cryptographic signatures, and the API enforces `temperature: 1`
|
|
136
|
-
* (Membrane handles this). Omit or set `enabled: false` to disable
|
|
162
|
+
* (Membrane handles this). Omit or set `enabled: false` to disable, except
|
|
163
|
+
* on a model whose thinking is always on (Fable, Mythos), which thinks
|
|
164
|
+
* whatever this says.
|
|
137
165
|
*/
|
|
138
166
|
thinking?: {
|
|
139
167
|
enabled: boolean;
|
|
@@ -143,10 +171,109 @@ export interface AgentConfig {
|
|
|
143
171
|
/**
|
|
144
172
|
* How thinking content is returned: 'summarized' (readable summary) or
|
|
145
173
|
* 'omitted' (empty thinking field, signature only). Fable 5 / Opus 4.7+
|
|
146
|
-
* default to 'omitted' — set 'summarized' to receive thinking text.
|
|
174
|
+
* default to 'omitted' — set 'summarized' to receive thinking text. A
|
|
175
|
+
* model whose thinking is always on (Fable, Mythos) is sent a thinking
|
|
176
|
+
* config only to carry `thinkingBinding.dropBlock`, so this reaches it
|
|
177
|
+
* only with that set.
|
|
147
178
|
*/
|
|
148
179
|
display?: 'summarized' | 'omitted';
|
|
149
180
|
};
|
|
181
|
+
/**
|
|
182
|
+
* How the provider binds this agent's signed thinking to the conversation
|
|
183
|
+
* before it. A host sets it from what it knows of the agent's model and
|
|
184
|
+
* route.
|
|
185
|
+
*/
|
|
186
|
+
thinkingBinding?: {
|
|
187
|
+
/**
|
|
188
|
+
* Ask the provider to drop a signed thinking block whose earlier
|
|
189
|
+
* conversation has changed, as a fold changes it, rather than refuse the
|
|
190
|
+
* request. An account that enforces the binding otherwise answers such a
|
|
191
|
+
* request with a 400. One that doesn't decides for itself: the four
|
|
192
|
+
* accounts tried on 2026-10-18 dropped such blocks silently, so there the
|
|
193
|
+
* model sees nothing different and the report is what's new, and one
|
|
194
|
+
* that would show such a block to the model is asked to drop it instead.
|
|
195
|
+
*
|
|
196
|
+
* It's sent as `thinking.block_binding.prefix_mismatch_behavior:
|
|
197
|
+
* "drop_block"` with the `thinking-binding-controls-2026-08-01` beta,
|
|
198
|
+
* which membrane's Anthropic and Bedrock adapters carry (Bedrock's
|
|
199
|
+
* acceptance of the beta hasn't been tried). On any other adapter it does
|
|
200
|
+
* nothing, so a host should refuse it there. A thinking config the host
|
|
201
|
+
* sends itself, through `request.extra` or as `thinking` in
|
|
202
|
+
* `providerParams`, replaces the one membrane builds, control included.
|
|
203
|
+
*
|
|
204
|
+
* On a model whose thinking is always on (Fable, Mythos), membrane
|
|
205
|
+
* carries it in an adaptive thinking config whatever `thinking.enabled`
|
|
206
|
+
* says, with `thinking.display` when that's set, so such an agent's
|
|
207
|
+
* `display` takes effect only with this setting. On any other model, it
|
|
208
|
+
* goes only in the thinking config membrane sends while thinking is on.
|
|
209
|
+
* Membrane tells the first kind by its id, which names `fable` or
|
|
210
|
+
* `mythos`. Opus 5.5, Haiku 5.5, Sonnet 5.5, Sonnet 5, Fable 5 and Fable
|
|
211
|
+
* 5.1 accepted the config on 2026-10-18. Mythos hasn't been tried, and
|
|
212
|
+
* membrane notes that the family has refused thinking configs with a 400
|
|
213
|
+
* before, so for a Mythos model the setting may fail every request.
|
|
214
|
+
*
|
|
215
|
+
* On a framework turn, each call's report of the blocks the provider
|
|
216
|
+
* dropped goes to its `inference:usage` trace, and neither that call nor
|
|
217
|
+
* its stream's later calls feed the context strategy's calibration, since
|
|
218
|
+
* the provider doesn't bill a block it dropped and the strategy still
|
|
219
|
+
* counts it. After a fold, each block after the stretch it rewrote is
|
|
220
|
+
* bound to a conversation the request no longer holds. Where the context
|
|
221
|
+
* strategy still sends such a block, the provider drops it on every call
|
|
222
|
+
* until a later fold takes it out of the context, and while such blocks
|
|
223
|
+
* are sent, no stream gives a sample and the calibration keeps the value
|
|
224
|
+
* it had. A strategy that leaves that thinking out at the fold sends none
|
|
225
|
+
* to drop. The direct API carries the control too, but reads no report: it
|
|
226
|
+
* traces no usage and feeds no calibration.
|
|
227
|
+
*
|
|
228
|
+
* Default false: nothing is sent, and the account's default applies.
|
|
229
|
+
*/
|
|
230
|
+
dropBlock?: boolean;
|
|
231
|
+
/**
|
|
232
|
+
* Whether this agent's model binds its signed thinking to the
|
|
233
|
+
* conversation before it, as the host knows from its own model records.
|
|
234
|
+
* A context manager that keeps a record of what each branch sent can
|
|
235
|
+
* then leave out thinking whose earlier conversation changed before the
|
|
236
|
+
* provider sees it. Set:
|
|
237
|
+
* - each compile the agent sends tells the context manager so
|
|
238
|
+
* (`thinkingBinding`: `binds`, `dropBlock` as set here, and the agent's
|
|
239
|
+
* name as the `participant` whose replies are its own), with digests
|
|
240
|
+
* of what the request carries ahead of its messages (`identity`: the
|
|
241
|
+
* system text with its system-position injections, the tools in the
|
|
242
|
+
* order sent, the model, and the thinking config, `maxTokens`,
|
|
243
|
+
* `providerParams` and `prefillUserMessage`);
|
|
244
|
+
* - each framework stream tells the context manager which stored rows
|
|
245
|
+
* its later rounds and its last reply carried as stored
|
|
246
|
+
* (`noteRequestSent`), naming the compile it was built from, so their
|
|
247
|
+
* thinking is kept at the next compile. The direct API
|
|
248
|
+
* (`runInference`) notes nothing, so each of its replies' thinking is
|
|
249
|
+
* left out at the compile after it's stored;
|
|
250
|
+
* - with `physicalWindowTokens` set too, `maxStreamTokens` no longer
|
|
251
|
+
* starts a new stream mid-turn, since the new stream's compile can take
|
|
252
|
+
* the turn's earlier reasoning out of the request;
|
|
253
|
+
* - with `dropBlock` set too, where a compile reports where the branch's
|
|
254
|
+
* record began (`thinkingRecordedAfter`), a block the provider drops
|
|
255
|
+
* that the record doesn't account for raises the
|
|
256
|
+
* `thinking-binding-loss` ops alert, once per incident and again if a
|
|
257
|
+
* call drops more. The provider reports drops only on a request that
|
|
258
|
+
* carries the drop control; without it, such a block is refused;
|
|
259
|
+
* - the agent is told, in a `[reasoning] <agent>:` system notice of kind
|
|
260
|
+
* `reasoning-loss` stored for it as the framework's other notices are,
|
|
261
|
+
* when a committing compile leaves out a stored reply's reasoning at a
|
|
262
|
+
* change of the request's head, at a branch's first compile, or in a
|
|
263
|
+
* fold or other change to an earlier message that takes a reply of the
|
|
264
|
+
* current turn, and, with `dropBlock` set too, when the provider drops
|
|
265
|
+
* blocks it can place as the agent's stored replies or the stream's
|
|
266
|
+
* rounds, once per incident and again when a call drops more. The
|
|
267
|
+
* framework hears compiles through `Agent.onThinkingStrip` from the
|
|
268
|
+
* agent's first stream on, unless a host has set its own, so an agent
|
|
269
|
+
* driven only through the direct API is never told.
|
|
270
|
+
* The record and the notes
|
|
271
|
+
* vouch for requests as agent-framework hands them to membrane, so a
|
|
272
|
+
* membrane `beforeRequest` hook that changes a request must change every
|
|
273
|
+
* request alike. Default false: compiles and streams are as they were.
|
|
274
|
+
*/
|
|
275
|
+
binds?: boolean;
|
|
276
|
+
};
|
|
150
277
|
/**
|
|
151
278
|
* How to handle a model content-policy refusal (`stop_reason: refusal`).
|
|
152
279
|
* When `autoRewind` is on, a refused turn triggers an automatic rewind: the
|
|
@@ -219,6 +346,34 @@ export interface AgentConfig {
|
|
|
219
346
|
*/
|
|
220
347
|
toolWrapperProseGuard?: boolean;
|
|
221
348
|
|
|
349
|
+
/**
|
|
350
|
+
* Continue on the agent's own turn ending (off when left out): a turn the
|
|
351
|
+
* model ends itself (stop reason `end_turn` or `stop_sequence`), whether
|
|
352
|
+
* its last response is prose or empty, is followed by another turn,
|
|
353
|
+
* instead of a pause until the next event. A turn ended through
|
|
354
|
+
* `skip_reply` (or another tool that ends the turn, such as `sleep`), or
|
|
355
|
+
* whose last prose envelope is `>>skip_reply` (explicit) or `>>>skip_reply`
|
|
356
|
+
* (hybrid), pauses as usual. So does one whose closing prose bounced (the
|
|
357
|
+
* bounce and its cap answer it), and an agent offered no way to stop
|
|
358
|
+
* (locus or disabled mode without an offered `skip_reply`).
|
|
359
|
+
*
|
|
360
|
+
* As the next turn starts, a short `[continue]` system row naming the agent
|
|
361
|
+
* joins the window: another turn starts, how to stop, and that unmarked
|
|
362
|
+
* words are sent as usual; on the last continuation of a run, that the
|
|
363
|
+
* agent waits for the next event after it. It's written only when the
|
|
364
|
+
* continuation is that turn's whole cause: a message batched with it makes
|
|
365
|
+
* it that message's turn, with no row, in the message's channel. Otherwise
|
|
366
|
+
* the next turn keeps the turn's locus (locus and hybrid modes). At most
|
|
367
|
+
* `maxConsecutive` (default 3) continuations run in a row: the count
|
|
368
|
+
* starts again when a turn starts with a cause of its own (a message, a
|
|
369
|
+
* timer, a heartbeat that isn't a silent tick) or a tool ends one. Silent
|
|
370
|
+
* heartbeat ticks, refusals, `max_tokens` cut-offs, the stall guard's
|
|
371
|
+
* ends, ephemeral runs, conversation forks and a quiesce never continue. A
|
|
372
|
+
* ` !` continuation the turn asked for runs instead, and counts toward
|
|
373
|
+
* nothing. See docs/auto-continue.md.
|
|
374
|
+
*/
|
|
375
|
+
autoContinue?: boolean | AutoContinueConfig;
|
|
376
|
+
|
|
222
377
|
/**
|
|
223
378
|
* Clock rows (off when left out): when a boundary of this interval on the
|
|
224
379
|
* agent's local wall clock (counted from local midnight, in the
|
|
@@ -399,10 +554,22 @@ export interface InferenceRequest {
|
|
|
399
554
|
* all of them without materializing content, the turn has no cause left
|
|
400
555
|
* and does not run. */
|
|
401
556
|
coalescingBatchSubjects?: string[];
|
|
402
|
-
/** Host-owned: this wake's sole cause is
|
|
403
|
-
* coalesced render placed in its
|
|
404
|
-
*
|
|
557
|
+
/** Host-owned: this wake's sole cause is this write, deferred for its
|
|
558
|
+
* agent while a turn was alive: a coalesced render placed in its queue
|
|
559
|
+
* (wakeToRead), or a message, notice or event whose wake was queued with
|
|
560
|
+
* it. Once a request that carried the write was answered and, for a wake
|
|
561
|
+
* that carries a channel and isn't marked `ambient`, the agent has since
|
|
562
|
+
* published into that channel having read it, or once the write is in
|
|
563
|
+
* neither the agent's queue nor its store's current branch, the wake
|
|
564
|
+
* starts no turn. */
|
|
405
565
|
readsDeferredWrite?: string;
|
|
566
|
+
/** Host-owned: this wake's sole cause is this message, stored in its
|
|
567
|
+
* agent's store as it arrived, not deferred (its row's id). Once a
|
|
568
|
+
* request that carried the message was answered and, for a wake that
|
|
569
|
+
* carries a channel and isn't marked `ambient`, the agent has since
|
|
570
|
+
* published into that channel having read it, or once the message isn't
|
|
571
|
+
* on its store's current branch, the wake starts no turn. */
|
|
572
|
+
readsStoredMessage?: string;
|
|
406
573
|
agentName: string;
|
|
407
574
|
reason: string;
|
|
408
575
|
source: string;
|
|
@@ -418,6 +585,25 @@ export interface InferenceRequest {
|
|
|
418
585
|
* ephemeral run's (a subagent's), which takes no global fallback.
|
|
419
586
|
*/
|
|
420
587
|
channelId?: string;
|
|
588
|
+
/**
|
|
589
|
+
* The server of `channelId`'s channel. MCPL requires a channel id to be
|
|
590
|
+
* unique only within one server's connection (§14.2), so where two
|
|
591
|
+
* servers register the same id only the pair names one channel. The
|
|
592
|
+
* framework's own wakes set it beside `channelId`. A host's request that
|
|
593
|
+
* gives `channelId` alone names the one channel that id, or its
|
|
594
|
+
* server-qualified name (`serverId:channelId`), means; one that two
|
|
595
|
+
* servers' channels answer to names none, and the turn's speech has no
|
|
596
|
+
* channel of its own.
|
|
597
|
+
*/
|
|
598
|
+
channelServerId?: string;
|
|
599
|
+
/**
|
|
600
|
+
* Framework-set: this wake carries an autoContinue continuation
|
|
601
|
+
* (AgentConfig.autoContinue), with what its `[continue]` row says. The
|
|
602
|
+
* scheduler keeps the mark on the turn's trigger only when the
|
|
603
|
+
* continuation is that turn's whole cause, and the turn writes the row as
|
|
604
|
+
* it starts. Hosts don't set it.
|
|
605
|
+
*/
|
|
606
|
+
autoContinueRun?: AutoContinueRun;
|
|
421
607
|
/**
|
|
422
608
|
* True when the triggering message explicitly addressed the agent (mention,
|
|
423
609
|
* reply-to-bot, DM — `chat:addressed` in MCPL RFC-001 terms). When a wake
|
|
@@ -426,6 +612,27 @@ export interface InferenceRequest {
|
|
|
426
612
|
* not capture the agent's voice just by being newest.
|
|
427
613
|
*/
|
|
428
614
|
addressed?: boolean;
|
|
615
|
+
/**
|
|
616
|
+
* Host-owned: true when the triggering message's server marked it ambient
|
|
617
|
+
* (`chat:ambient`). A coalesced push's wake carries it only to read a
|
|
618
|
+
* render, and only when every notice the render stands for was. Such a
|
|
619
|
+
* message asked nothing of the agent, so a wake for it that carries
|
|
620
|
+
* `readsDeferredWrite` or `readsStoredMessage` is dropped once a request
|
|
621
|
+
* that carried the message was answered, with no publish asked of the
|
|
622
|
+
* agent. A message with neither tag is in doubt, and is judged as an
|
|
623
|
+
* addressed one.
|
|
624
|
+
*/
|
|
625
|
+
ambient?: true;
|
|
626
|
+
/**
|
|
627
|
+
* Host-owned: true when the triggering message's server marked it a
|
|
628
|
+
* `chat:system` notice (RFC-001 rev 3): an event about the place, such as
|
|
629
|
+
* a join or the weather changing, not something anyone said. Such a wake
|
|
630
|
+
* names no channel for its turn's plain speech, though it carries
|
|
631
|
+
* `channelId`: a turn it starts alone resolves its locus as a heartbeat's
|
|
632
|
+
* does. Like an ambient one, a wake to read it is done once read. Never
|
|
633
|
+
* set on a coalesced render's wake, which may fold messages too.
|
|
634
|
+
*/
|
|
635
|
+
systemNotice?: true;
|
|
429
636
|
/**
|
|
430
637
|
* Who spoke the message that triggered this inference, as an adapter-
|
|
431
638
|
* namespaced opaque id (`<serverId>:user:<authorId>`) — never a display
|
|
@@ -446,6 +653,12 @@ export interface InferenceRequest {
|
|
|
446
653
|
wakeChannelId?: string;
|
|
447
654
|
/** Timestamp of the event the wake provenance was taken from (ms). */
|
|
448
655
|
wakeAt?: number;
|
|
656
|
+
/** Batched-wake lines the gate handed to this wake rather than wrote
|
|
657
|
+
* (WakeLine), decided by a fresh start of its turn as WakeLine says: each
|
|
658
|
+
* written once into the window it names, or left for a later fresh start
|
|
659
|
+
* of the same wake. A retry, or a start that resumes a logical turn,
|
|
660
|
+
* decides none. */
|
|
661
|
+
wakeLines?: WakeLine[];
|
|
449
662
|
/** Suppress every automatic plain-prose delivery for this logical turn.
|
|
450
663
|
* Explicit tool calls remain available. Used by authenticated silent wakes. */
|
|
451
664
|
suppressProse?: boolean;
|
package/src/types/events.ts
CHANGED
|
@@ -194,19 +194,34 @@ export interface ToolResult {
|
|
|
194
194
|
* it reads the result's error text, if any.
|
|
195
195
|
*/
|
|
196
196
|
data?: unknown;
|
|
197
|
+
/**
|
|
198
|
+
* Whether `data` is a protocol result's content: an array in which every
|
|
199
|
+
* element is a content block, of a type this host can show or not. The
|
|
200
|
+
* framework sets it on an MCPL tool's result, and a module that returns a
|
|
201
|
+
* content array can set it too. When it's set, each element reaches the
|
|
202
|
+
* model as itself, as a reference's stub, or as a marker saying what it was
|
|
203
|
+
* and why it isn't shown, never as JSON. When it isn't, an array counts as
|
|
204
|
+
* content only when every element is a block of one of MCP's types (text,
|
|
205
|
+
* image, audio, resource, resource_link), and any other array is data,
|
|
206
|
+
* written as JSON.
|
|
207
|
+
*/
|
|
208
|
+
dataIsContent?: boolean;
|
|
197
209
|
/** Error message (if failure) */
|
|
198
210
|
error?: string;
|
|
199
211
|
/** Whether this was an error (for LLM) */
|
|
200
212
|
isError?: boolean;
|
|
201
213
|
/**
|
|
202
|
-
* The
|
|
203
|
-
*
|
|
204
|
-
*
|
|
205
|
-
*
|
|
206
|
-
*
|
|
207
|
-
*
|
|
208
|
-
*
|
|
209
|
-
*
|
|
214
|
+
* The call was refused before it opened, RFC-007's refusal, so nothing ran
|
|
215
|
+
* and the call certainly had no effect. The dispatcher's path, the model's
|
|
216
|
+
* calls and a script's, sets it: the caller may not use the tool
|
|
217
|
+
* (allowedTools), a `skip_reply` wake was refused, the call's MCPL server is
|
|
218
|
+
* absent or still connecting, the host's policy for that server denies the
|
|
219
|
+
* tool, or a fork reached outside its channel. RFC-007's lifecycle refuses
|
|
220
|
+
* the call from the same place, so observers see no events for it. The
|
|
221
|
+
* framework also sets it on the result it stores for each call in the last
|
|
222
|
+
* round of a response the output limit cut off: such a call was never
|
|
223
|
+
* dispatched or opened, and its result goes into the context with the reply,
|
|
224
|
+
* not through a tool-result event. A check made after the call opened, such as a module's
|
|
210
225
|
* answer for a name it has no tool for or arguments that don't fit a
|
|
211
226
|
* schema, is a failure whose text says nothing was done, as is an MCPL
|
|
212
227
|
* request that couldn't be written. A programmatic call (`executeToolCall`,
|
|
@@ -258,6 +273,13 @@ export interface ToolCall {
|
|
|
258
273
|
name: string;
|
|
259
274
|
/** Tool input */
|
|
260
275
|
input: unknown;
|
|
276
|
+
/**
|
|
277
|
+
* membrane's marker (ToolUseContent.unparseableInput), present when `input`
|
|
278
|
+
* isn't the model's arguments. The framework refuses such a call without
|
|
279
|
+
* running it, except one whose text is JSON `null`, which runs as a call
|
|
280
|
+
* with no arguments.
|
|
281
|
+
*/
|
|
282
|
+
unparseableInput?: string;
|
|
261
283
|
/** The agent that made this tool call. Set by the framework dispatch layer. */
|
|
262
284
|
callerAgentName?: string;
|
|
263
285
|
/**
|
|
@@ -311,7 +333,9 @@ export interface ToolCall {
|
|
|
311
333
|
* read_image tool passes a model's call to the workspace without it; and a
|
|
312
334
|
* utility run through `utils` carries what its `utils` call carried.
|
|
313
335
|
* Without it, a module holds its answer to a bound of its own, if any: the
|
|
314
|
-
* workspace's
|
|
336
|
+
* workspace's `edit` and `edit_many` answers hold to the house default,
|
|
337
|
+
* 24,000, and a `read` holds its page to its line limit alone, with every
|
|
338
|
+
* line whole, since such a caller takes the data itself.
|
|
315
339
|
*/
|
|
316
340
|
resultMaxChars?: number;
|
|
317
341
|
}
|