@animalabs/agent-framework 0.27.0 → 0.29.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 +145 -41
- package/dist/src/agent.d.ts +29 -2
- package/dist/src/agent.d.ts.map +1 -1
- package/dist/src/agent.js +73 -12
- package/dist/src/agent.js.map +1 -1
- package/dist/src/api/mcp-server-core.d.ts.map +1 -1
- package/dist/src/api/mcp-server-core.js +3 -12
- package/dist/src/api/mcp-server-core.js.map +1 -1
- package/dist/src/api/server.d.ts.map +1 -1
- package/dist/src/api/server.js +11 -5
- package/dist/src/api/server.js.map +1 -1
- package/dist/src/auto-continue.d.ts +5 -2
- package/dist/src/auto-continue.d.ts.map +1 -1
- package/dist/src/auto-continue.js +9 -5
- package/dist/src/auto-continue.js.map +1 -1
- package/dist/src/code-execution/isolate/runner.d.ts +7 -5
- package/dist/src/code-execution/isolate/runner.d.ts.map +1 -1
- package/dist/src/code-execution/isolate/runner.js +7 -5
- package/dist/src/code-execution/isolate/runner.js.map +1 -1
- package/dist/src/code-execution/isolate/scripts.d.ts.map +1 -1
- package/dist/src/code-execution/isolate/scripts.js +3 -2
- 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 +468 -125
- package/dist/src/framework.d.ts.map +1 -1
- package/dist/src/framework.js +3651 -1111
- package/dist/src/framework.js.map +1 -1
- package/dist/src/gate/event-gate.d.ts +133 -13
- package/dist/src/gate/event-gate.d.ts.map +1 -1
- package/dist/src/gate/event-gate.js +654 -59
- 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/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 +173 -2
- package/dist/src/gate/types.d.ts.map +1 -1
- package/dist/src/heartbeat/heartbeat.d.ts +202 -0
- package/dist/src/heartbeat/heartbeat.d.ts.map +1 -0
- package/dist/src/heartbeat/heartbeat.js +778 -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/held-writes.d.ts +3 -3
- package/dist/src/held-writes.js +3 -3
- package/dist/src/host-presentation.d.ts +170 -0
- package/dist/src/host-presentation.d.ts.map +1 -0
- package/dist/src/host-presentation.js +561 -0
- package/dist/src/host-presentation.js.map +1 -0
- package/dist/src/index.d.ts +5 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +3 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/line-reader.d.ts +4 -0
- package/dist/src/line-reader.d.ts.map +1 -0
- package/dist/src/line-reader.js +59 -0
- package/dist/src/line-reader.js.map +1 -0
- 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 +34 -6
- package/dist/src/mcpl/channel-registry.d.ts.map +1 -1
- package/dist/src/mcpl/channel-registry.js +133 -54
- package/dist/src/mcpl/channel-registry.js.map +1 -1
- package/dist/src/mcpl/conversation-router.d.ts.map +1 -1
- package/dist/src/mcpl/conversation-router.js +2 -1
- package/dist/src/mcpl/conversation-router.js.map +1 -1
- package/dist/src/mcpl/convert-block.d.ts +1 -0
- package/dist/src/mcpl/convert-block.d.ts.map +1 -1
- package/dist/src/mcpl/convert-block.js +16 -4
- package/dist/src/mcpl/convert-block.js.map +1 -1
- package/dist/src/mcpl/hook-orchestrator.d.ts.map +1 -1
- package/dist/src/mcpl/hook-orchestrator.js +4 -3
- package/dist/src/mcpl/hook-orchestrator.js.map +1 -1
- package/dist/src/mcpl/inbound-source.d.ts +29 -11
- package/dist/src/mcpl/inbound-source.d.ts.map +1 -1
- package/dist/src/mcpl/inbound-source.js +43 -70
- package/dist/src/mcpl/inbound-source.js.map +1 -1
- package/dist/src/mcpl/modern-connection.d.ts.map +1 -1
- package/dist/src/mcpl/modern-connection.js +11 -7
- package/dist/src/mcpl/modern-connection.js.map +1 -1
- package/dist/src/mcpl/protocol-family.d.ts +3 -2
- package/dist/src/mcpl/protocol-family.d.ts.map +1 -1
- package/dist/src/mcpl/protocol-family.js +25 -3
- package/dist/src/mcpl/protocol-family.js.map +1 -1
- package/dist/src/mcpl/push-handler.js +2 -2
- package/dist/src/mcpl/push-handler.js.map +1 -1
- package/dist/src/mcpl/references.d.ts +12 -40
- package/dist/src/mcpl/references.d.ts.map +1 -1
- package/dist/src/mcpl/references.js +29 -23
- package/dist/src/mcpl/references.js.map +1 -1
- package/dist/src/mcpl/server-connection.d.ts +18 -8
- package/dist/src/mcpl/server-connection.d.ts.map +1 -1
- package/dist/src/mcpl/server-connection.js +70 -30
- package/dist/src/mcpl/server-connection.js.map +1 -1
- package/dist/src/mcpl/skip-reply-wake.d.ts +25 -0
- package/dist/src/mcpl/skip-reply-wake.d.ts.map +1 -1
- package/dist/src/mcpl/skip-reply-wake.js +25 -0
- package/dist/src/mcpl/skip-reply-wake.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-presence.d.ts +66 -14
- package/dist/src/mcpl/tool-presence.d.ts.map +1 -1
- package/dist/src/mcpl/tool-presence.js +150 -80
- package/dist/src/mcpl/tool-presence.js.map +1 -1
- package/dist/src/mcpl/tool-signature.d.ts +10 -3
- package/dist/src/mcpl/tool-signature.d.ts.map +1 -1
- package/dist/src/mcpl/tool-signature.js +60 -30
- package/dist/src/mcpl/tool-signature.js.map +1 -1
- package/dist/src/mcpl/toolset-host.d.ts +88 -55
- package/dist/src/mcpl/toolset-host.d.ts.map +1 -1
- package/dist/src/mcpl/toolset-host.js +220 -111
- package/dist/src/mcpl/toolset-host.js.map +1 -1
- package/dist/src/mcpl/toolsets-module.d.ts +27 -35
- package/dist/src/mcpl/toolsets-module.d.ts.map +1 -1
- package/dist/src/mcpl/toolsets-module.js +313 -91
- package/dist/src/mcpl/toolsets-module.js.map +1 -1
- package/dist/src/mcpl/transport.d.ts +1 -1
- package/dist/src/mcpl/transport.d.ts.map +1 -1
- package/dist/src/mcpl/transport.js +16 -16
- package/dist/src/mcpl/transport.js.map +1 -1
- package/dist/src/mcpl/types.d.ts +31 -13
- 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 +10 -8
- package/dist/src/module-registry.d.ts.map +1 -1
- package/dist/src/module-registry.js +15 -9
- package/dist/src/module-registry.js.map +1 -1
- package/dist/src/modules/api/index.d.ts.map +1 -1
- package/dist/src/modules/api/index.js +4 -2
- package/dist/src/modules/api/index.js.map +1 -1
- package/dist/src/modules/discord/index.d.ts.map +1 -1
- package/dist/src/modules/discord/index.js +33 -25
- 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 +30 -17
- package/dist/src/modules/history/index.js.map +1 -1
- package/dist/src/modules/sender-name.d.ts +7 -0
- package/dist/src/modules/sender-name.d.ts.map +1 -0
- package/dist/src/modules/sender-name.js +10 -0
- package/dist/src/modules/sender-name.js.map +1 -0
- package/dist/src/modules/workspace/answers.d.ts +26 -0
- package/dist/src/modules/workspace/answers.d.ts.map +1 -0
- package/dist/src/modules/workspace/answers.js +138 -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 +3 -0
- package/dist/src/modules/workspace/direct-write.d.ts.map +1 -1
- package/dist/src/modules/workspace/direct-write.js +59 -24
- package/dist/src/modules/workspace/direct-write.js.map +1 -1
- 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 +2 -1
- package/dist/src/modules/workspace/edit-text.d.ts.map +1 -1
- package/dist/src/modules/workspace/edit-text.js +4 -2
- package/dist/src/modules/workspace/edit-text.js.map +1 -1
- package/dist/src/modules/workspace/effects.d.ts +4 -2
- package/dist/src/modules/workspace/effects.d.ts.map +1 -1
- package/dist/src/modules/workspace/effects.js +67 -50
- package/dist/src/modules/workspace/effects.js.map +1 -1
- package/dist/src/modules/workspace/index.d.ts +63 -51
- package/dist/src/modules/workspace/index.d.ts.map +1 -1
- package/dist/src/modules/workspace/index.js +980 -547
- package/dist/src/modules/workspace/index.js.map +1 -1
- package/dist/src/modules/workspace/observe.d.ts +125 -82
- package/dist/src/modules/workspace/observe.d.ts.map +1 -1
- package/dist/src/modules/workspace/observe.js +465 -241
- package/dist/src/modules/workspace/observe.js.map +1 -1
- package/dist/src/modules/workspace/read-page.d.ts.map +1 -1
- package/dist/src/modules/workspace/read-page.js +7 -1
- package/dist/src/modules/workspace/read-page.js.map +1 -1
- package/dist/src/modules/workspace/reconcile.d.ts +7 -1
- package/dist/src/modules/workspace/reconcile.d.ts.map +1 -1
- package/dist/src/modules/workspace/reconcile.js +156 -50
- package/dist/src/modules/workspace/reconcile.js.map +1 -1
- package/dist/src/modules/workspace/result-text.d.ts +1 -0
- package/dist/src/modules/workspace/result-text.d.ts.map +1 -1
- package/dist/src/modules/workspace/result-text.js.map +1 -1
- 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/types.d.ts +96 -43
- 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/notice-tags.d.ts +79 -0
- package/dist/src/notice-tags.d.ts.map +1 -0
- package/dist/src/notice-tags.js +83 -0
- package/dist/src/notice-tags.js.map +1 -0
- 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 +52 -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.js +1 -1
- package/dist/src/silent-heartbeat.d.ts +1 -53
- package/dist/src/silent-heartbeat.d.ts.map +1 -1
- package/dist/src/silent-heartbeat.js +56 -3
- package/dist/src/silent-heartbeat.js.map +1 -1
- package/dist/src/supplied-text.d.ts +35 -0
- package/dist/src/supplied-text.d.ts.map +1 -0
- package/dist/src/supplied-text.js +141 -0
- package/dist/src/supplied-text.js.map +1 -0
- package/dist/src/thinking-drops.d.ts +4 -11
- package/dist/src/thinking-drops.d.ts.map +1 -1
- package/dist/src/thinking-drops.js +7 -14
- package/dist/src/thinking-drops.js.map +1 -1
- 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 +39 -4
- package/dist/src/tool-args.js.map +1 -1
- package/dist/src/tool-image-ledger.d.ts.map +1 -1
- package/dist/src/tool-image-ledger.js +2 -1
- 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 +5 -4
- package/dist/src/tool-presentation.js.map +1 -1
- package/dist/src/tool-result-guard.d.ts +8 -4
- package/dist/src/tool-result-guard.d.ts.map +1 -1
- package/dist/src/tool-result-guard.js +23 -11
- package/dist/src/tool-result-guard.js.map +1 -1
- package/dist/src/tune-out/coordinator.d.ts +3 -2
- package/dist/src/tune-out/coordinator.d.ts.map +1 -1
- package/dist/src/tune-out/coordinator.js +24 -26
- 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 +63 -18
- package/dist/src/types/agent.d.ts.map +1 -1
- package/dist/src/types/events.d.ts +18 -8
- package/dist/src/types/events.d.ts.map +1 -1
- package/dist/src/types/framework.d.ts +58 -0
- package/dist/src/types/framework.d.ts.map +1 -1
- package/dist/src/types/module.d.ts +27 -13
- package/dist/src/types/module.d.ts.map +1 -1
- package/dist/src/types/trace.d.ts +34 -1
- package/dist/src/types/trace.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/agent.ts +76 -12
- package/src/api/mcp-server-core.ts +3 -14
- package/src/api/server.ts +11 -5
- package/src/auto-continue.ts +12 -5
- package/src/code-execution/isolate/runner.ts +7 -5
- package/src/code-execution/isolate/scripts.ts +3 -2
- package/src/cut-off-round.ts +98 -0
- package/src/framework.ts +3772 -1138
- package/src/gate/event-gate.ts +705 -60
- package/src/gate/index.ts +9 -1
- package/src/gate/reply-judge.ts +512 -0
- package/src/gate/types.ts +176 -3
- package/src/heartbeat/heartbeat.ts +843 -0
- package/src/heartbeat/reminder-time.ts +107 -0
- package/src/held-writes.ts +3 -3
- package/src/host-presentation.ts +605 -0
- package/src/index.ts +5 -1
- package/src/line-reader.ts +58 -0
- package/src/mcpl/capability-mask.ts +3 -2
- package/src/mcpl/channel-registry.ts +139 -53
- package/src/mcpl/conversation-router.ts +2 -1
- package/src/mcpl/convert-block.ts +17 -4
- package/src/mcpl/hook-orchestrator.ts +4 -3
- package/src/mcpl/inbound-source.ts +45 -70
- package/src/mcpl/modern-connection.ts +11 -7
- package/src/mcpl/protocol-family.ts +24 -3
- package/src/mcpl/push-handler.ts +2 -2
- package/src/mcpl/references.ts +31 -23
- package/src/mcpl/server-connection.ts +76 -34
- package/src/mcpl/skip-reply-wake.ts +35 -0
- package/src/mcpl/tags.ts +13 -2
- package/src/mcpl/tool-presence.ts +149 -82
- package/src/mcpl/tool-signature.ts +64 -32
- package/src/mcpl/toolset-host.ts +212 -110
- package/src/mcpl/toolsets-module.ts +277 -91
- package/src/mcpl/transport.ts +18 -14
- package/src/mcpl/types.ts +32 -13
- package/src/module-registry.ts +14 -9
- package/src/modules/api/index.ts +4 -2
- package/src/modules/discord/index.ts +37 -25
- package/src/modules/history/index.ts +30 -18
- package/src/modules/sender-name.ts +9 -0
- package/src/modules/workspace/answers.ts +151 -0
- package/src/modules/workspace/branch-intent.ts +10 -5
- package/src/modules/workspace/direct-write.ts +59 -23
- package/src/modules/workspace/disk-agreement.ts +52 -21
- package/src/modules/workspace/edit-text.ts +7 -5
- package/src/modules/workspace/effects.ts +69 -50
- package/src/modules/workspace/index.ts +966 -556
- package/src/modules/workspace/observe.ts +497 -242
- package/src/modules/workspace/read-page.ts +7 -1
- package/src/modules/workspace/reconcile.ts +184 -49
- package/src/modules/workspace/result-text.ts +2 -0
- package/src/modules/workspace/sync.ts +16 -0
- package/src/modules/workspace/types.ts +96 -43
- package/src/modules/workspace/watcher.ts +8 -3
- package/src/notice-tags.ts +84 -0
- package/src/prose-drafts.ts +4 -3
- package/src/reasoning-loss-notice.ts +64 -0
- package/src/reasoning-loss.ts +120 -0
- package/src/send-tools.ts +3 -2
- package/src/sent-rows.ts +1 -1
- package/src/silent-heartbeat.ts +4 -3
- package/src/supplied-text.ts +154 -0
- package/src/thinking-drops.ts +10 -16
- package/src/tool-args.ts +38 -4
- package/src/tool-image-ledger.ts +2 -1
- package/src/tool-presentation.ts +5 -4
- package/src/tool-result-guard.ts +26 -11
- package/src/tune-out/coordinator.ts +25 -27
- package/src/tune-out/tools.ts +4 -1
- package/src/types/agent.ts +63 -18
- package/src/types/events.ts +18 -8
- package/src/types/framework.ts +59 -0
- package/src/types/module.ts +28 -13
- package/src/types/trace.ts +36 -1
|
@@ -12,7 +12,9 @@
|
|
|
12
12
|
* - Expose synthesized tools: channel_list, channel_open, channel_close, channel_publish
|
|
13
13
|
* - Build channel context for beforeInference params
|
|
14
14
|
*/
|
|
15
|
-
import {
|
|
15
|
+
import { NOTICE_TAG } from '../notice-tags.js';
|
|
16
|
+
import { convertBlocks } from './convert-block.js';
|
|
17
|
+
import { cutToFit, markedText, markNoticeOpenings, nameToTypeBack, quotedValue, showsAsItself, suppliedValue } from '../supplied-text.js';
|
|
16
18
|
import { isDeepStrictEqual } from 'node:util';
|
|
17
19
|
import { ensureStateRegistered } from '../module-registry.js';
|
|
18
20
|
import { expandCoreTags, isMarkerTagged } from './tags.js';
|
|
@@ -22,7 +24,7 @@ import { logDetail, logValue } from './log-value.js';
|
|
|
22
24
|
import { RefusalLines } from './refusal-lines.js';
|
|
23
25
|
import { CapabilityGrant } from './capability-grant.js';
|
|
24
26
|
import { McplRequestError } from './server-connection.js';
|
|
25
|
-
import { readSkipReplyWake } from './skip-reply-wake.js';
|
|
27
|
+
import { readSkipReplyWake, skipReplyNote } from './skip-reply-wake.js';
|
|
26
28
|
import { isProseTargetToken } from './prose-grammar.js';
|
|
27
29
|
// ============================================================================
|
|
28
30
|
// Typing indicator interval (Discord typing lasts ~10s, so 7s keeps it alive)
|
|
@@ -410,20 +412,22 @@ const CHANNEL_TOOL_DEFINITIONS = [
|
|
|
410
412
|
// ============================================================================
|
|
411
413
|
// Constructor Options
|
|
412
414
|
// ============================================================================
|
|
413
|
-
/** Bound connector values for notices, logs and an outcome's reason
|
|
414
|
-
*
|
|
415
|
-
*
|
|
415
|
+
/** Bound connector values for notices, logs and an outcome's reason, on one
|
|
416
|
+
* line with their notice openings marked (suppliedValue). A PublishOutcome
|
|
417
|
+
* keeps the connector's structured data (`detail`) as the connection gives
|
|
418
|
+
* it, its strings redacted (redactedData). */
|
|
416
419
|
export function connectorText(value) {
|
|
417
420
|
let text;
|
|
418
421
|
try {
|
|
419
422
|
text = typeof value === 'string' ? value : JSON.stringify(value) ?? String(value);
|
|
420
423
|
}
|
|
421
424
|
catch {
|
|
422
|
-
return
|
|
425
|
+
return `[${NOTICE_TAG.unserializableConnectorValue}]`;
|
|
423
426
|
}
|
|
424
427
|
const limit = 2000;
|
|
425
|
-
const suffix =
|
|
426
|
-
|
|
428
|
+
const suffix = `… [${NOTICE_TAG.truncated}]`;
|
|
429
|
+
const shown = suppliedValue(text);
|
|
430
|
+
return shown.length > limit ? cutToFit(shown, limit - suffix.length) + suffix : shown;
|
|
427
431
|
}
|
|
428
432
|
/** One key per channel, its server and id: unlike joining the two with a
|
|
429
433
|
* separator, no two channels share one, whatever their ids hold. */
|
|
@@ -437,6 +441,8 @@ export function sameChannel(a, b) {
|
|
|
437
441
|
return !a && !b;
|
|
438
442
|
return a.serverId === b.serverId && a.channelId === b.channelId;
|
|
439
443
|
}
|
|
444
|
+
export const NO_CHANNEL_EXAMPLE = '#<channel>';
|
|
445
|
+
export const NO_PERSON_EXAMPLE = '@<person>';
|
|
440
446
|
/**
|
|
441
447
|
* A channel's server-qualified name, `serverId:channelId`. A name given as a
|
|
442
448
|
* string (a tool's channelId, a `>>` target, a host's call) may take this
|
|
@@ -447,11 +453,32 @@ export function sameChannel(a, b) {
|
|
|
447
453
|
export function qualifiedChannelName(ref) {
|
|
448
454
|
return `${ref.serverId}:${ref.channelId}`;
|
|
449
455
|
}
|
|
456
|
+
function markedHistory(history) {
|
|
457
|
+
return history.map((item) => {
|
|
458
|
+
if (item === null || typeof item !== 'object' || Array.isArray(item) || !('content' in item))
|
|
459
|
+
return item;
|
|
460
|
+
const { content } = item;
|
|
461
|
+
if (Array.isArray(content))
|
|
462
|
+
return { ...item, content: markNoticeOpenings(content.map(withEmbeddedTextMarked)) };
|
|
463
|
+
return typeof content === 'string' ? { ...item, content: markedText(content) } : item;
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
function withEmbeddedTextMarked(block) {
|
|
467
|
+
if (block === null || typeof block !== 'object' || block.type !== 'resource')
|
|
468
|
+
return block;
|
|
469
|
+
const { resource } = block;
|
|
470
|
+
if (resource === null || typeof resource !== 'object' || typeof resource.text !== 'string')
|
|
471
|
+
return block;
|
|
472
|
+
return { ...block, resource: { ...resource, text: markedText(resource.text) } };
|
|
473
|
+
}
|
|
450
474
|
/** A channel told apart by its id and its server, for one no string picks
|
|
451
|
-
* alone: `"b:room" on server "a"
|
|
475
|
+
* alone or whose name wouldn't show as itself: `"b:room" on server "a"`,
|
|
476
|
+
* each a JSON literal a channel tool's channelId and serverId take back
|
|
477
|
+
* (quotedValue). No input takes the whole form for a name. */
|
|
452
478
|
function channelOnServer(ref) {
|
|
453
|
-
return `${
|
|
479
|
+
return `${quotedValue(ref.channelId)} on server ${quotedValue(ref.serverId)}`;
|
|
454
480
|
}
|
|
481
|
+
const CHANNEL_ON_SERVER_AT_END = /("(?:[^"\\]|\\.)*") on server ("(?:[^"\\]|\\.)*")$/;
|
|
455
482
|
/**
|
|
456
483
|
* A failed request's words, bounded, for a reason that a caller composes.
|
|
457
484
|
* This host's own words, for a request that wasn't sent or wasn't answered
|
|
@@ -1328,7 +1355,7 @@ export class ChannelRegistry {
|
|
|
1328
1355
|
}
|
|
1329
1356
|
if (message.tags)
|
|
1330
1357
|
message.tags = expandCoreTags(message.tags);
|
|
1331
|
-
const convertedContent = message.content
|
|
1358
|
+
const convertedContent = convertBlocks(message.content, 'attachment on channel message', serverId);
|
|
1332
1359
|
if (!emptyAllowed && isVisiblyEmptyConversion(message.content, convertedContent)) {
|
|
1333
1360
|
rejectEmpty();
|
|
1334
1361
|
continue;
|
|
@@ -1342,7 +1369,8 @@ export class ChannelRegistry {
|
|
|
1342
1369
|
const incomingEntry = this.channels.get(incomingKey);
|
|
1343
1370
|
const markAccepted = (firstView = false) => {
|
|
1344
1371
|
// Non-conversational markers (a reaction added or removed, an edit, a
|
|
1345
|
-
// deletion
|
|
1372
|
+
// deletion, and a chat:system notice such as a join or the weather)
|
|
1373
|
+
// are ABOUT a message or the place, not one the agent replies to: they
|
|
1346
1374
|
// must not retarget the default publish locus or become
|
|
1347
1375
|
// `context.incoming`'s reply anchor. An edit the coalescer delivered
|
|
1348
1376
|
// as the agent's first view counts as the message it replaced.
|
|
@@ -1763,7 +1791,7 @@ export class ChannelRegistry {
|
|
|
1763
1791
|
case 'journal':
|
|
1764
1792
|
return this.handleToolJournal(input);
|
|
1765
1793
|
case 'skip_reply':
|
|
1766
|
-
return this.handleToolSkipReply(input);
|
|
1794
|
+
return this.handleToolSkipReply(input, origin?.kind === 'agent' ? origin.earlierWake : undefined);
|
|
1767
1795
|
default:
|
|
1768
1796
|
// Not every agent is given every channel tool, so the refusal points
|
|
1769
1797
|
// to the ones this agent has rather than listing them all.
|
|
@@ -1816,7 +1844,8 @@ export class ChannelRegistry {
|
|
|
1816
1844
|
// declared it inbound-only, since speech isn't posted there): a conversation
|
|
1817
1845
|
// fork's home channel, else this turn's channel (single trunk agent — item-3
|
|
1818
1846
|
// redux: its locus, else its triggering channel), else the global default
|
|
1819
|
-
// (
|
|
1847
|
+
// (a no-trigger turn's, but not a heartbeat's, whose turn takes none).
|
|
1848
|
+
// Without this, a fork
|
|
1820
1849
|
// was advertised the global locus but published somewhere else; and a trunk
|
|
1821
1850
|
// agent was told the wrong channel under concurrency.
|
|
1822
1851
|
// Each lookup is keyed on whether a name was given, not its truthiness:
|
|
@@ -3214,13 +3243,20 @@ export class ChannelRegistry {
|
|
|
3214
3243
|
* name, only where no registered channel takes that name, as a channel
|
|
3215
3244
|
* tool reads it or a `>>` target does (by label or raw id too), so the
|
|
3216
3245
|
* name can't send anything to another channel; else by its id and server.
|
|
3246
|
+
* A name that wouldn't show as itself (showsAsItself: one holding a line
|
|
3247
|
+
* break, a notice opening, a quote, a backslash or a lone surrogate, or
|
|
3248
|
+
* whitespace at its edges) is shown by its id and its server too, which
|
|
3249
|
+
* the channel tools take exactly and the prose resolver doesn't, so no name
|
|
3250
|
+
* shown can be another channel's.
|
|
3217
3251
|
*/
|
|
3218
3252
|
nameShown(ref) {
|
|
3219
3253
|
const entry = this.entryAt(ref);
|
|
3220
|
-
if (entry)
|
|
3221
|
-
|
|
3254
|
+
if (entry) {
|
|
3255
|
+
const name = this.nameFor(entry);
|
|
3256
|
+
return name !== undefined && showsAsItself(name) ? name : channelOnServer(ref);
|
|
3257
|
+
}
|
|
3222
3258
|
for (const name of [ref.channelId, qualifiedChannelName(ref)]) {
|
|
3223
|
-
if (this.entriesNamed(name).length === 0 && !('channelId' in this.resolveProseTarget(name)))
|
|
3259
|
+
if (showsAsItself(name) && this.entriesNamed(name).length === 0 && !('channelId' in this.resolveProseTarget(name)))
|
|
3224
3260
|
return name;
|
|
3225
3261
|
}
|
|
3226
3262
|
return channelOnServer(ref);
|
|
@@ -3257,7 +3293,7 @@ export class ChannelRegistry {
|
|
|
3257
3293
|
tuneOutEndText(entry, tool) {
|
|
3258
3294
|
const close = tool === 'channel_close';
|
|
3259
3295
|
return this.nameFor(entry) !== undefined
|
|
3260
|
-
? `Call tune_out with channelId ${this.
|
|
3296
|
+
? `Call tune_out with channelId ${quotedValue(this.nameFor(entry))} and mode "cancel" for it to resume normal ` +
|
|
3261
3297
|
`attention; cancelling delivers the diverted backlog${close ? ', and channel_close closes it after that.' : '.'}`
|
|
3262
3298
|
: 'No channelId names it alone, so tune_out can\'t cancel it: its tune-out ends by itself when its duration ' +
|
|
3263
3299
|
'runs out, or at the first wake past its wake budget, and its backlog is delivered then.' +
|
|
@@ -3269,7 +3305,7 @@ export class ChannelRegistry {
|
|
|
3269
3305
|
*/
|
|
3270
3306
|
quotedShown(ref) {
|
|
3271
3307
|
const shown = this.nameShown(ref);
|
|
3272
|
-
return shown === channelOnServer(ref) ? shown :
|
|
3308
|
+
return shown === channelOnServer(ref) ? shown : quotedValue(shown);
|
|
3273
3309
|
}
|
|
3274
3310
|
/**
|
|
3275
3311
|
* The string that names exactly this entry by entriesNamed: its id when no
|
|
@@ -3302,7 +3338,7 @@ export class ChannelRegistry {
|
|
|
3302
3338
|
const nothing = opts.nothing ?? 'nothing ran';
|
|
3303
3339
|
const names = entries.map((e) => this.nameFor(e));
|
|
3304
3340
|
if (names.every((n) => n !== undefined)) {
|
|
3305
|
-
const listed = names.map((n) =>
|
|
3341
|
+
const listed = names.map((n) => quotedValue(n)).join(', ');
|
|
3306
3342
|
const servers = [...new Set(entries.map((e) => JSON.stringify(e.serverId)))];
|
|
3307
3343
|
// One server's two channels can answer to one name too, as `s`'s
|
|
3308
3344
|
// `s:room` and `room` both do to `s:room`; its server picks neither.
|
|
@@ -3324,8 +3360,8 @@ export class ChannelRegistry {
|
|
|
3324
3360
|
if (own === undefined && !opts.takesServerId)
|
|
3325
3361
|
return `- ${where}: no channelId reaches it alone.`;
|
|
3326
3362
|
return own !== undefined
|
|
3327
|
-
? `- ${where}: call again with channelId ${
|
|
3328
|
-
: `- ${where}: call again with channelId ${
|
|
3363
|
+
? `- ${where}: call again with channelId ${quotedValue(own)}.`
|
|
3364
|
+
: `- ${where}: call again with channelId ${quotedValue(e.descriptor.id)} and serverId ${JSON.stringify(e.serverId)}.`;
|
|
3329
3365
|
});
|
|
3330
3366
|
const count = entries.length === 2 ? 'either of two channels' : `any of ${entries.length} channels`;
|
|
3331
3367
|
return `Channel ${JSON.stringify(name)} could mean ${count}, so ${nothing}:\n${lines.join('\n')}`;
|
|
@@ -3363,7 +3399,7 @@ export class ChannelRegistry {
|
|
|
3363
3399
|
if (!alone)
|
|
3364
3400
|
return 'channel_list shows the channels and their servers.';
|
|
3365
3401
|
const one = named[0];
|
|
3366
|
-
const names = `${JSON.stringify(channelId)} alone names channel ${
|
|
3402
|
+
const names = `${JSON.stringify(channelId)} alone names channel ${quotedValue(one.descriptor.id)} on server `
|
|
3367
3403
|
+ JSON.stringify(one.serverId);
|
|
3368
3404
|
return takesServerId ? `${names}: for that one, call again with serverId left out.` : `${names}.`;
|
|
3369
3405
|
}
|
|
@@ -3375,7 +3411,7 @@ export class ChannelRegistry {
|
|
|
3375
3411
|
const places = elsewhere.map((e) => {
|
|
3376
3412
|
const at = `on server ${JSON.stringify(e.serverId)}`;
|
|
3377
3413
|
const name = this.nameFor(e);
|
|
3378
|
-
return name === undefined ? `${at} (no channelId reaches it alone)` : `${at} as ${
|
|
3414
|
+
return name === undefined ? `${at} (no channelId reaches it alone)` : `${at} as ${quotedValue(name)}`;
|
|
3379
3415
|
});
|
|
3380
3416
|
return `It's ${places.length === 1 ? places[0] : `${places.slice(0, -1).join(', ')} and ${places.at(-1)}`}.`;
|
|
3381
3417
|
}
|
|
@@ -3638,19 +3674,22 @@ export class ChannelRegistry {
|
|
|
3638
3674
|
* before any other spelling (ownChannelNamed).
|
|
3639
3675
|
*/
|
|
3640
3676
|
resolveProseTarget(spec, opts) {
|
|
3641
|
-
const
|
|
3677
|
+
const name = spec.trim();
|
|
3678
|
+
if (name === NO_CHANNEL_EXAMPLE || name === NO_PERSON_EXAMPLE)
|
|
3679
|
+
return { error: `${name} is the example's placeholder: write the name it stands for in its place` };
|
|
3680
|
+
const own = this.ownChannelNamed(name, opts?.own);
|
|
3642
3681
|
let resolved;
|
|
3643
3682
|
if (own === undefined) {
|
|
3644
|
-
resolved = this.resolveTargetByName(
|
|
3683
|
+
resolved = this.resolveTargetByName(name);
|
|
3645
3684
|
}
|
|
3646
3685
|
else if ('neither' in own) {
|
|
3647
|
-
resolved = { error: `"${
|
|
3686
|
+
resolved = { error: `"${name}" is the id of this turn's channels on more than one server`, candidates: this.ownCandidates(own.neither).map((c) => c.prose) };
|
|
3648
3687
|
}
|
|
3649
3688
|
else {
|
|
3650
3689
|
const entry = this.entryAt(own.channel);
|
|
3651
3690
|
resolved = entry
|
|
3652
3691
|
? { channelId: entry.descriptor.id, serverId: entry.serverId, label: entry.descriptor.label }
|
|
3653
|
-
: { error: `${this.ownChannelGoneText(
|
|
3692
|
+
: { error: `${this.ownChannelGoneText(name, own.channel)}, and nothing can be sent there until that server registers it again` };
|
|
3654
3693
|
}
|
|
3655
3694
|
if (!opts?.forSpeech || 'error' in resolved)
|
|
3656
3695
|
return resolved;
|
|
@@ -3703,7 +3742,7 @@ export class ChannelRegistry {
|
|
|
3703
3742
|
return undefined;
|
|
3704
3743
|
if ('neither' in mine) {
|
|
3705
3744
|
const done = tool === 'publish' ? 'was posted' : tool === 'deliver' ? 'was delivered' : 'ran';
|
|
3706
|
-
return { error: this.ownNeitherRefusal(name, mine.neither, done) };
|
|
3745
|
+
return { error: this.ownNeitherRefusal(name, mine.neither, done, false) };
|
|
3707
3746
|
}
|
|
3708
3747
|
return this.entryAt(mine.channel) ? { channel: mine.channel } : { error: this.ownChannelGoneRefusal(name, mine.channel, tool) };
|
|
3709
3748
|
}
|
|
@@ -3720,32 +3759,73 @@ export class ChannelRegistry {
|
|
|
3720
3759
|
/**
|
|
3721
3760
|
* The turn's channels a name means neither of (ownChannelNamed), each by a
|
|
3722
3761
|
* string that reaches it outside the turn's rule: its server-qualified
|
|
3723
|
-
* name, where that picks it alone, since its id is the name refused.
|
|
3724
|
-
*
|
|
3725
|
-
*
|
|
3762
|
+
* name, where that picks it alone, since its id is the name refused. `text`
|
|
3763
|
+
* is that name, which a refusal writes as JSON; `prose`, which a `>>`
|
|
3764
|
+
* target reads, is that name where it shows as itself, else its id and
|
|
3765
|
+
* server. One no string picks alone, and one its server no longer
|
|
3766
|
+
* registers, are named by id and server in both, saying so. `reaches` says
|
|
3767
|
+
* which a name reaches.
|
|
3726
3768
|
*/
|
|
3727
3769
|
ownCandidates(channels) {
|
|
3728
3770
|
return channels.map((c) => {
|
|
3729
3771
|
const entry = this.entryAt(c);
|
|
3730
|
-
if (!entry)
|
|
3731
|
-
|
|
3772
|
+
if (!entry) {
|
|
3773
|
+
const text = `${channelOnServer(c)} (its server no longer registers it)`;
|
|
3774
|
+
return { text, prose: text, reaches: false, byServer: false };
|
|
3775
|
+
}
|
|
3732
3776
|
const qualified = qualifiedChannelName(c);
|
|
3733
3777
|
const picked = this.entriesNamed(qualified);
|
|
3734
|
-
|
|
3735
|
-
|
|
3736
|
-
|
|
3778
|
+
if (picked.length !== 1 || picked[0] !== entry) {
|
|
3779
|
+
const text = `${channelOnServer(c)} (no channelId reaches it alone)`;
|
|
3780
|
+
return { text, prose: text, reaches: false, byServer: true };
|
|
3781
|
+
}
|
|
3782
|
+
return { text: qualified, prose: showsAsItself(qualified) ? qualified : channelOnServer(c), reaches: true, byServer: false };
|
|
3737
3783
|
});
|
|
3738
3784
|
}
|
|
3785
|
+
/**
|
|
3786
|
+
* What a refusal listing these candidates says of each one that is a
|
|
3787
|
+
* channel shown by its id and server: the channelId channel_publish reaches
|
|
3788
|
+
* it by, or that no channelId reaches it alone. That is its server-qualified
|
|
3789
|
+
* name where that picks it alone, since a bare id is what a turn's own
|
|
3790
|
+
* channels answer to first, whether or not their server still registers
|
|
3791
|
+
* them (ownChannelNamed), and else its id where that picks it alone and
|
|
3792
|
+
* isn't empty (channel_publish refuses an empty one). It leaves out a channel no
|
|
3793
|
+
* longer registered and a candidate that already says no channelId reaches
|
|
3794
|
+
* it alone, and is empty when nothing is left.
|
|
3795
|
+
*/
|
|
3796
|
+
publishRouteFor(candidates) {
|
|
3797
|
+
const parts = new Set();
|
|
3798
|
+
for (const candidate of candidates) {
|
|
3799
|
+
const shown = CHANNEL_ON_SERVER_AT_END.exec(candidate);
|
|
3800
|
+
if (!shown)
|
|
3801
|
+
continue;
|
|
3802
|
+
const ref = { channelId: JSON.parse(shown[1]), serverId: JSON.parse(shown[2]) };
|
|
3803
|
+
const entry = this.entryAt(ref);
|
|
3804
|
+
if (!entry)
|
|
3805
|
+
continue;
|
|
3806
|
+
const name = [qualifiedChannelName(ref), ref.channelId].find((n) => {
|
|
3807
|
+
const named = n === '' ? [] : this.entriesNamed(n);
|
|
3808
|
+
return named.length === 1 && named[0] === entry;
|
|
3809
|
+
});
|
|
3810
|
+
parts.add(name !== undefined
|
|
3811
|
+
? `channel_publish reaches ${channelOnServer(ref)} with channelId ${quotedValue(name)}`
|
|
3812
|
+
: `no channelId reaches ${channelOnServer(ref)} alone`);
|
|
3813
|
+
}
|
|
3814
|
+
return parts.size ? ` For a channel shown by its id and server: ${[...parts].join('; ')}.` : '';
|
|
3815
|
+
}
|
|
3739
3816
|
/** A tool's refusal of a name the turn's channels on more than one server
|
|
3740
3817
|
* answer to by their id (ownChannelNamed's neither). */
|
|
3741
|
-
ownNeitherRefusal(name, channels, done) {
|
|
3818
|
+
ownNeitherRefusal(name, channels, done, takesServer = true) {
|
|
3742
3819
|
const candidates = this.ownCandidates(channels);
|
|
3743
|
-
const named = candidates.filter((c) => c.reaches).map((c) =>
|
|
3820
|
+
const named = candidates.filter((c) => c.reaches).map((c) => quotedValue(c.text));
|
|
3744
3821
|
const pick = named.length === candidates.length ? ' Call again with channelId set to one of them.'
|
|
3745
3822
|
: named.length === 1 ? ` Call again with channelId ${named[0]}.`
|
|
3746
3823
|
: named.length > 1 ? ` Call again with channelId set to one of ${named.join(', ')}.` : '';
|
|
3747
|
-
const listed = candidates.map((c) => (c.reaches ?
|
|
3748
|
-
|
|
3824
|
+
const listed = candidates.map((c) => (c.reaches ? quotedValue(c.text) : c.text)).join(', ');
|
|
3825
|
+
const byServer = takesServer && candidates.some((c) => c.byServer)
|
|
3826
|
+
? ' For a channel shown by its id and server, call again with that channelId and that serverId.'
|
|
3827
|
+
: '';
|
|
3828
|
+
return `"${name}" is the id of this turn's channels on more than one server (${listed}), so nothing ${done}.${pick}${byServer}`;
|
|
3749
3829
|
}
|
|
3750
3830
|
resolveTargetByName(spec) {
|
|
3751
3831
|
const entries = [...this.channels.values()];
|
|
@@ -3756,7 +3836,7 @@ export class ChannelRegistry {
|
|
|
3756
3836
|
// A candidate is named by the token that picks it alone (nameFor), so
|
|
3757
3837
|
// two servers' channels with one id or one label can be told apart, or,
|
|
3758
3838
|
// where no string picks it alone, by its id and its server.
|
|
3759
|
-
const token = (e) => this.
|
|
3839
|
+
const token = (e) => this.nameShown(refOf(e));
|
|
3760
3840
|
// A DM is shown by its label, the person, where that label, given as a
|
|
3761
3841
|
// target, picks that DM. It doesn't where another channel answers to that
|
|
3762
3842
|
// label too, as two servers' DMs with one person do (a label is matched
|
|
@@ -3773,7 +3853,7 @@ export class ChannelRegistry {
|
|
|
3773
3853
|
};
|
|
3774
3854
|
const dmShown = (list) => list.map((e) => {
|
|
3775
3855
|
const label = e.descriptor.label ?? e.descriptor.id;
|
|
3776
|
-
return labelPicks(e, label) ? label : token(e);
|
|
3856
|
+
return showsAsItself(label) && labelPicks(e, label) ? label : token(e);
|
|
3777
3857
|
});
|
|
3778
3858
|
// A channel id, or its server-qualified name (entriesNamed).
|
|
3779
3859
|
const exact = this.entriesNamed(trimmed);
|
|
@@ -3878,7 +3958,7 @@ export class ChannelRegistry {
|
|
|
3878
3958
|
if (byName.length > 1) {
|
|
3879
3959
|
return {
|
|
3880
3960
|
error: `"${trimmed}" matches several channels`,
|
|
3881
|
-
candidates: byName.map((e) => `${e.descriptor.label} = ${token(e)}`),
|
|
3961
|
+
candidates: byName.map((e) => `${nameToTypeBack(e.descriptor.label ?? '')} = ${token(e)}`),
|
|
3882
3962
|
};
|
|
3883
3963
|
}
|
|
3884
3964
|
// No match: offer near-candidates (labels containing the name) so the
|
|
@@ -3886,7 +3966,7 @@ export class ChannelRegistry {
|
|
|
3886
3966
|
const near = entries
|
|
3887
3967
|
.filter((e) => norm(e.descriptor.label ?? '').includes(norm(trimmed)))
|
|
3888
3968
|
.slice(0, 5)
|
|
3889
|
-
.map((e) => `${e.descriptor.label} = ${token(e)}`);
|
|
3969
|
+
.map((e) => `${nameToTypeBack(e.descriptor.label ?? '')} = ${token(e)}`);
|
|
3890
3970
|
return { error: `no channel matches "${trimmed}"`, ...(near.length ? { candidates: near } : {}) };
|
|
3891
3971
|
}
|
|
3892
3972
|
/**
|
|
@@ -3923,7 +4003,7 @@ export class ChannelRegistry {
|
|
|
3923
4003
|
qualifiedChannelName(ref),
|
|
3924
4004
|
];
|
|
3925
4005
|
for (const c of candidates) {
|
|
3926
|
-
if (!isProseTargetToken(c) || c === '#')
|
|
4006
|
+
if (!isProseTargetToken(c) || c === '#' || !showsAsItself(c))
|
|
3927
4007
|
continue;
|
|
3928
4008
|
const r = this.resolveProseTarget(c, { forSpeech: true });
|
|
3929
4009
|
if ('channelId' in r && sameChannel(r, ref))
|
|
@@ -4191,7 +4271,7 @@ export class ChannelRegistry {
|
|
|
4191
4271
|
channelId: input.channelId,
|
|
4192
4272
|
serverId: entry.serverId,
|
|
4193
4273
|
status: alreadyDesiredOpen ? 'reconciled' : 'opened',
|
|
4194
|
-
...(result.history ? { history: result.history } : {}),
|
|
4274
|
+
...(result.history ? { history: markedHistory(result.history) } : {}),
|
|
4195
4275
|
...(result.historyTruncated ? { historyTruncated: true } : {}),
|
|
4196
4276
|
},
|
|
4197
4277
|
};
|
|
@@ -4648,13 +4728,14 @@ export class ChannelRegistry {
|
|
|
4648
4728
|
* tool, so any trailing prose this turn is NOT posted. Replaces the old
|
|
4649
4729
|
* overloaded use of `think` for staying silent.
|
|
4650
4730
|
*/
|
|
4651
|
-
handleToolSkipReply(input) {
|
|
4731
|
+
handleToolSkipReply(input, earlierWake) {
|
|
4652
4732
|
// The self-wake itself is armed by the framework (which owns the
|
|
4653
4733
|
// EventGate) BEFORE its dispatch reaches this handler, from the same
|
|
4654
4734
|
// reading, and the framework refuses a wake the host can't set before
|
|
4655
4735
|
// dispatching. A caller of this registry's handleChannelToolCall
|
|
4656
4736
|
// (AgentFramework.channels) goes past both, so its note names a wake
|
|
4657
|
-
// nothing armed.
|
|
4737
|
+
// nothing armed. The framework, which also owns the heartbeat, says
|
|
4738
|
+
// which of its wakes is due before the self-wake (`earlierWake`).
|
|
4658
4739
|
const wake = readSkipReplyWake(input);
|
|
4659
4740
|
const selfWake = wake.kind === 'wake' ? wake.seconds : undefined;
|
|
4660
4741
|
return {
|
|
@@ -4670,9 +4751,7 @@ export class ChannelRegistry {
|
|
|
4670
4751
|
// on Fable: ~60% of skip_reply result bytes were verbatim input echo).
|
|
4671
4752
|
data: {
|
|
4672
4753
|
skipped: true,
|
|
4673
|
-
note: selfWake !== undefined
|
|
4674
|
-
? `Turn ended; nothing sent. Self-wake in ~${selfWake}s unless something wakes you first.`
|
|
4675
|
-
: 'Turn ended; nothing sent.',
|
|
4754
|
+
note: skipReplyNote(selfWake, selfWake !== undefined ? earlierWake : undefined),
|
|
4676
4755
|
},
|
|
4677
4756
|
};
|
|
4678
4757
|
}
|
|
@@ -5227,7 +5306,7 @@ export class ChannelRegistry {
|
|
|
5227
5306
|
else if (own && 'neither' in own) {
|
|
5228
5307
|
if (seen)
|
|
5229
5308
|
seen.refusal = 'shared-id';
|
|
5230
|
-
return { success: false, error: this.ownNeitherRefusal(input.channelId, own.neither, 'was posted'), isError: true };
|
|
5309
|
+
return { success: false, error: this.ownNeitherRefusal(input.channelId, own.neither, 'was posted', false), isError: true };
|
|
5231
5310
|
}
|
|
5232
5311
|
else if (own) {
|
|
5233
5312
|
entry = this.entryAt(own.channel);
|
|
@@ -5264,7 +5343,7 @@ export class ChannelRegistry {
|
|
|
5264
5343
|
// channel with its id isn't where its message came from.
|
|
5265
5344
|
error: input.channelId === undefined
|
|
5266
5345
|
? serverGiven
|
|
5267
|
-
? `Server "${input.serverId}" has no channel
|
|
5346
|
+
? `Server "${input.serverId}" has no channel ${quotedValue(fallback.channelId)}, the id of the channel this call would default to, so nothing was posted.`
|
|
5268
5347
|
: `The channel this would default to, ${this.quotedShown(fallback)}, isn't registered now, so nothing was posted.`
|
|
5269
5348
|
// This tool's schema has no serverId, so one given here is a host's
|
|
5270
5349
|
// ref (publishForAgent), or one an agent added unasked, and the
|