@animalabs/agent-framework 0.32.0 → 0.33.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 +204 -14
- package/dist/src/admission/admit.d.ts +18 -0
- package/dist/src/admission/admit.d.ts.map +1 -1
- package/dist/src/admission/admit.js +16 -3
- package/dist/src/admission/admit.js.map +1 -1
- package/dist/src/agent.d.ts +185 -78
- package/dist/src/agent.d.ts.map +1 -1
- package/dist/src/agent.js +279 -102
- 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 +50 -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 +4 -20
- package/dist/src/api/server.js.map +1 -1
- package/dist/src/code-execution/isolate/scripts.d.ts +12 -8
- package/dist/src/code-execution/isolate/scripts.d.ts.map +1 -1
- package/dist/src/code-execution/isolate/scripts.js +24 -0
- package/dist/src/code-execution/isolate/scripts.js.map +1 -1
- package/dist/src/config-checks.d.ts +7 -0
- package/dist/src/config-checks.d.ts.map +1 -1
- package/dist/src/config-checks.js +14 -0
- package/dist/src/config-checks.js.map +1 -1
- package/dist/src/context-manager-errors.d.ts +25 -0
- package/dist/src/context-manager-errors.d.ts.map +1 -0
- package/dist/src/context-manager-errors.js +31 -0
- package/dist/src/context-manager-errors.js.map +1 -0
- package/dist/src/context-options.d.ts +67 -0
- package/dist/src/context-options.d.ts.map +1 -0
- package/dist/src/context-options.js +85 -0
- package/dist/src/context-options.js.map +1 -0
- package/dist/src/deferred-import.d.ts +93 -0
- package/dist/src/deferred-import.d.ts.map +1 -0
- package/dist/src/deferred-import.js +177 -0
- package/dist/src/deferred-import.js.map +1 -0
- package/dist/src/dendrite/audience.d.ts +223 -0
- package/dist/src/dendrite/audience.d.ts.map +1 -0
- package/dist/src/dendrite/audience.js +202 -0
- package/dist/src/dendrite/audience.js.map +1 -0
- package/dist/src/dendrite/index.d.ts +5 -3
- package/dist/src/dendrite/index.d.ts.map +1 -1
- package/dist/src/dendrite/index.js +2 -1
- package/dist/src/dendrite/index.js.map +1 -1
- package/dist/src/dendrite/presets.d.ts +10 -5
- package/dist/src/dendrite/presets.d.ts.map +1 -1
- package/dist/src/dendrite/presets.js +17 -5
- package/dist/src/dendrite/presets.js.map +1 -1
- package/dist/src/dendrite/registry.d.ts +62 -7
- package/dist/src/dendrite/registry.d.ts.map +1 -1
- package/dist/src/dendrite/registry.js +179 -10
- package/dist/src/dendrite/registry.js.map +1 -1
- package/dist/src/dendrite/types.d.ts +91 -8
- package/dist/src/dendrite/types.d.ts.map +1 -1
- package/dist/src/foreign-rounds.d.ts +69 -0
- package/dist/src/foreign-rounds.d.ts.map +1 -0
- package/dist/src/foreign-rounds.js +152 -0
- package/dist/src/foreign-rounds.js.map +1 -0
- package/dist/src/framework.d.ts +1976 -818
- package/dist/src/framework.d.ts.map +1 -1
- package/dist/src/framework.js +7566 -3422
- package/dist/src/framework.js.map +1 -1
- package/dist/src/gate/event-gate.d.ts +85 -15
- package/dist/src/gate/event-gate.d.ts.map +1 -1
- package/dist/src/gate/event-gate.js +421 -47
- package/dist/src/gate/event-gate.js.map +1 -1
- package/dist/src/gate/index.d.ts +1 -1
- package/dist/src/gate/index.d.ts.map +1 -1
- package/dist/src/gate/index.js.map +1 -1
- package/dist/src/gate/rule-scope.d.ts +30 -0
- package/dist/src/gate/rule-scope.d.ts.map +1 -0
- package/dist/src/gate/rule-scope.js +41 -0
- package/dist/src/gate/rule-scope.js.map +1 -0
- package/dist/src/gate/suppress-script-worker.d.ts +2 -0
- package/dist/src/gate/suppress-script-worker.d.ts.map +1 -0
- package/dist/src/gate/suppress-script-worker.js +103 -0
- package/dist/src/gate/suppress-script-worker.js.map +1 -0
- package/dist/src/gate/suppress-scripts.d.ts +105 -0
- package/dist/src/gate/suppress-scripts.d.ts.map +1 -0
- package/dist/src/gate/suppress-scripts.js +403 -0
- package/dist/src/gate/suppress-scripts.js.map +1 -0
- package/dist/src/gate/suppression-review.d.ts +143 -0
- package/dist/src/gate/suppression-review.d.ts.map +1 -0
- package/dist/src/gate/suppression-review.js +463 -0
- package/dist/src/gate/suppression-review.js.map +1 -0
- package/dist/src/gate/suppression-stats.d.ts +125 -0
- package/dist/src/gate/suppression-stats.d.ts.map +1 -0
- package/dist/src/gate/suppression-stats.js +214 -0
- package/dist/src/gate/suppression-stats.js.map +1 -0
- package/dist/src/gate/types.d.ts +135 -7
- package/dist/src/gate/types.d.ts.map +1 -1
- package/dist/src/gate/wake-onboarding.d.ts +119 -0
- package/dist/src/gate/wake-onboarding.d.ts.map +1 -0
- package/dist/src/gate/wake-onboarding.js +277 -0
- package/dist/src/gate/wake-onboarding.js.map +1 -0
- package/dist/src/held-writes.d.ts +31 -23
- package/dist/src/held-writes.d.ts.map +1 -1
- package/dist/src/held-writes.js +44 -59
- package/dist/src/held-writes.js.map +1 -1
- package/dist/src/index.d.ts +5 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +3 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/jsonrpc-envelope.d.ts +69 -0
- package/dist/src/jsonrpc-envelope.d.ts.map +1 -0
- package/dist/src/jsonrpc-envelope.js +66 -0
- package/dist/src/jsonrpc-envelope.js.map +1 -0
- package/dist/src/mcpl/channel-registry.d.ts +131 -15
- package/dist/src/mcpl/channel-registry.d.ts.map +1 -1
- package/dist/src/mcpl/channel-registry.js +290 -46
- package/dist/src/mcpl/channel-registry.js.map +1 -1
- package/dist/src/mcpl/checkpoint-manager.d.ts +2 -4
- package/dist/src/mcpl/checkpoint-manager.d.ts.map +1 -1
- package/dist/src/mcpl/checkpoint-manager.js.map +1 -1
- package/dist/src/mcpl/feature-set-manager.d.ts +2 -4
- package/dist/src/mcpl/feature-set-manager.d.ts.map +1 -1
- package/dist/src/mcpl/feature-set-manager.js.map +1 -1
- package/dist/src/mcpl/inbound-source.d.ts +2 -1
- package/dist/src/mcpl/inbound-source.d.ts.map +1 -1
- package/dist/src/mcpl/inbound-source.js +2 -1
- package/dist/src/mcpl/inbound-source.js.map +1 -1
- package/dist/src/mcpl/inference-router.d.ts +6 -6
- package/dist/src/mcpl/inference-router.d.ts.map +1 -1
- package/dist/src/mcpl/inference-router.js.map +1 -1
- package/dist/src/mcpl/push-coalescer.d.ts +132 -22
- package/dist/src/mcpl/push-coalescer.d.ts.map +1 -1
- package/dist/src/mcpl/push-coalescer.js +105 -15
- package/dist/src/mcpl/push-coalescer.js.map +1 -1
- package/dist/src/mcpl/push-handler.d.ts +9 -7
- package/dist/src/mcpl/push-handler.d.ts.map +1 -1
- package/dist/src/mcpl/push-handler.js.map +1 -1
- package/dist/src/mcpl/server-connection.d.ts +13 -10
- package/dist/src/mcpl/server-connection.d.ts.map +1 -1
- package/dist/src/mcpl/server-connection.js +134 -56
- package/dist/src/mcpl/server-connection.js.map +1 -1
- package/dist/src/mcpl/tool-classes.d.ts.map +1 -1
- package/dist/src/mcpl/tool-classes.js +3 -0
- package/dist/src/mcpl/tool-classes.js.map +1 -1
- package/dist/src/mcpl/types.d.ts +8 -2
- 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 +24 -1
- package/dist/src/module-registry.d.ts.map +1 -1
- package/dist/src/module-registry.js +68 -18
- package/dist/src/module-registry.js.map +1 -1
- package/dist/src/modules/discord/index.d.ts +45 -8
- package/dist/src/modules/discord/index.d.ts.map +1 -1
- package/dist/src/modules/discord/index.js +237 -86
- package/dist/src/modules/discord/index.js.map +1 -1
- package/dist/src/modules/history/index.d.ts +59 -0
- package/dist/src/modules/history/index.d.ts.map +1 -1
- package/dist/src/modules/history/index.js +432 -67
- package/dist/src/modules/history/index.js.map +1 -1
- package/dist/src/modules/history/semantic.d.ts +6 -5
- package/dist/src/modules/history/semantic.d.ts.map +1 -1
- package/dist/src/modules/history/semantic.js +15 -22
- package/dist/src/modules/history/semantic.js.map +1 -1
- package/dist/src/modules/workspace/disk-agreement.d.ts +1 -1
- package/dist/src/modules/workspace/disk-agreement.js +1 -1
- package/dist/src/modules/workspace/index.d.ts +28 -7
- package/dist/src/modules/workspace/index.d.ts.map +1 -1
- package/dist/src/modules/workspace/index.js +76 -22
- package/dist/src/modules/workspace/index.js.map +1 -1
- package/dist/src/notice-tags.d.ts +10 -1
- package/dist/src/notice-tags.d.ts.map +1 -1
- package/dist/src/notice-tags.js +10 -1
- package/dist/src/notice-tags.js.map +1 -1
- package/dist/src/operator-log.d.ts +36 -3
- package/dist/src/operator-log.d.ts.map +1 -1
- package/dist/src/operator-log.js +2 -2
- package/dist/src/operator-log.js.map +1 -1
- package/dist/src/presentation.d.ts +746 -0
- package/dist/src/presentation.d.ts.map +1 -0
- package/dist/src/presentation.js +1435 -0
- package/dist/src/presentation.js.map +1 -0
- package/dist/src/prose-drafts.d.ts +15 -11
- package/dist/src/prose-drafts.d.ts.map +1 -1
- package/dist/src/prose-drafts.js +16 -12
- package/dist/src/prose-drafts.js.map +1 -1
- package/dist/src/read-marks.d.ts +192 -0
- package/dist/src/read-marks.d.ts.map +1 -0
- package/dist/src/read-marks.js +242 -0
- package/dist/src/read-marks.js.map +1 -0
- package/dist/src/recovery/offline-branch.d.ts +91 -6
- package/dist/src/recovery/offline-branch.d.ts.map +1 -1
- package/dist/src/recovery/offline-branch.js +273 -29
- package/dist/src/recovery/offline-branch.js.map +1 -1
- package/dist/src/recovery/recover-cli.js +22 -3
- package/dist/src/recovery/recover-cli.js.map +1 -1
- package/dist/src/send-tools.d.ts +5 -9
- package/dist/src/send-tools.d.ts.map +1 -1
- package/dist/src/send-tools.js +40 -7
- package/dist/src/send-tools.js.map +1 -1
- package/dist/src/stored-injections.d.ts +2 -2
- package/dist/src/stored-injections.js +2 -2
- package/dist/src/stored-removal.d.ts +17 -4
- package/dist/src/stored-removal.d.ts.map +1 -1
- package/dist/src/stored-removal.js +29 -5
- package/dist/src/stored-removal.js.map +1 -1
- package/dist/src/tool-result-guard.d.ts +12 -1
- package/dist/src/tool-result-guard.d.ts.map +1 -1
- package/dist/src/tool-result-guard.js +42 -8
- package/dist/src/tool-result-guard.js.map +1 -1
- package/dist/src/tune-out/coordinator.d.ts +1159 -79
- package/dist/src/tune-out/coordinator.d.ts.map +1 -1
- package/dist/src/tune-out/coordinator.js +3709 -363
- package/dist/src/tune-out/coordinator.js.map +1 -1
- package/dist/src/tune-out/tools.d.ts +114 -17
- package/dist/src/tune-out/tools.d.ts.map +1 -1
- package/dist/src/tune-out/tools.js +87 -27
- package/dist/src/tune-out/tools.js.map +1 -1
- package/dist/src/tune-out/window-anchor.d.ts +143 -0
- package/dist/src/tune-out/window-anchor.d.ts.map +1 -0
- package/dist/src/tune-out/window-anchor.js +202 -0
- package/dist/src/tune-out/window-anchor.js.map +1 -0
- package/dist/src/types/agent.d.ts +82 -20
- package/dist/src/types/agent.d.ts.map +1 -1
- package/dist/src/types/events.d.ts +2 -0
- package/dist/src/types/events.d.ts.map +1 -1
- package/dist/src/types/framework.d.ts +32 -12
- package/dist/src/types/framework.d.ts.map +1 -1
- package/dist/src/types/module.d.ts +180 -69
- package/dist/src/types/module.d.ts.map +1 -1
- package/dist/src/types/trace.d.ts +510 -36
- package/dist/src/types/trace.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/admission/admit.ts +32 -3
- package/src/agent.ts +323 -120
- package/src/api/mcp-server-core.ts +54 -17
- package/src/api/server.ts +4 -23
- package/src/code-execution/isolate/scripts.ts +28 -3
- package/src/config-checks.ts +14 -0
- package/src/context-manager-errors.ts +37 -0
- package/src/context-options.ts +96 -0
- package/src/deferred-import.ts +239 -0
- package/src/dendrite/audience.ts +315 -0
- package/src/dendrite/index.ts +14 -2
- package/src/dendrite/presets.ts +18 -6
- package/src/dendrite/registry.ts +209 -12
- package/src/dendrite/types.ts +92 -8
- package/src/foreign-rounds.ts +199 -0
- package/src/framework.ts +7804 -3546
- package/src/gate/event-gate.ts +428 -65
- package/src/gate/index.ts +3 -0
- package/src/gate/rule-scope.ts +45 -0
- package/src/gate/suppress-script-worker.ts +89 -0
- package/src/gate/suppress-scripts.ts +414 -0
- package/src/gate/suppression-review.ts +517 -0
- package/src/gate/suppression-stats.ts +314 -0
- package/src/gate/types.ts +141 -7
- package/src/gate/wake-onboarding.ts +309 -0
- package/src/held-writes.ts +49 -60
- package/src/index.ts +9 -2
- package/src/jsonrpc-envelope.ts +81 -0
- package/src/mcpl/channel-registry.ts +353 -85
- package/src/mcpl/checkpoint-manager.ts +3 -2
- package/src/mcpl/feature-set-manager.ts +2 -1
- package/src/mcpl/inbound-source.ts +2 -1
- package/src/mcpl/inference-router.ts +7 -4
- package/src/mcpl/push-coalescer.ts +193 -34
- package/src/mcpl/push-handler.ts +10 -5
- package/src/mcpl/server-connection.ts +141 -60
- package/src/mcpl/tool-classes.ts +3 -0
- package/src/mcpl/types.ts +8 -2
- package/src/module-registry.ts +73 -17
- package/src/modules/discord/index.ts +229 -81
- package/src/modules/history/index.ts +439 -70
- package/src/modules/history/semantic.ts +15 -21
- package/src/modules/workspace/disk-agreement.ts +1 -1
- package/src/modules/workspace/index.ts +85 -23
- package/src/notice-tags.ts +10 -1
- package/src/operator-log.ts +36 -3
- package/src/presentation.ts +1676 -0
- package/src/prose-drafts.ts +16 -12
- package/src/read-marks.ts +328 -0
- package/src/recovery/offline-branch.ts +346 -32
- package/src/recovery/recover-cli.ts +21 -3
- package/src/send-tools.ts +40 -7
- package/src/stored-injections.ts +2 -2
- package/src/stored-removal.ts +31 -7
- package/src/tool-result-guard.ts +41 -7
- package/src/tune-out/coordinator.ts +4089 -457
- package/src/tune-out/tools.ts +160 -43
- package/src/tune-out/window-anchor.ts +277 -0
- package/src/types/agent.ts +86 -20
- package/src/types/events.ts +2 -0
- package/src/types/framework.ts +32 -12
- package/src/types/module.ts +181 -68
- package/src/types/trace.ts +542 -40
|
@@ -15,14 +15,14 @@
|
|
|
15
15
|
* its creation time is the only monotonic signal). Both watermarks are
|
|
16
16
|
* kept in the module's state, which follows the store's branches, so each
|
|
17
17
|
* branch sends its own messages and summaries. A branch made at an earlier
|
|
18
|
-
* point, as
|
|
19
|
-
* so a summary is keyed `sum:<id>@<created>`.
|
|
18
|
+
* point, as a rollback makes one, mints summary ids its parent already
|
|
19
|
+
* used, so a summary is keyed `sum:<id>@<created>`.
|
|
20
20
|
*
|
|
21
21
|
* What gets embedded per message: text blocks verbatim, plus the string
|
|
22
22
|
* arguments of the agent's private-prose tools (think / journal / skip_reply
|
|
23
23
|
* / private_note) labelled `[think] …` — that is the resident's own diary and
|
|
24
|
-
* is exactly what "what did I think about X" should find. The
|
|
25
|
-
*
|
|
24
|
+
* is exactly what "what did I think about X" should find. The words of a
|
|
25
|
+
* speech tool's call (send-tools.ts), labelled by tool, such as
|
|
26
26
|
* `[send_message] …`, since with prose routing disabled the resident speaks
|
|
27
27
|
* through them.
|
|
28
28
|
* tool_result payloads, other tool arguments, thinking blocks and media are
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
import type { ContextManager, StoredMessage } from '@animalabs/context-manager';
|
|
36
36
|
import type { ContentBlock } from '@animalabs/membrane';
|
|
37
37
|
import { safeSlice } from '../../safe-slice.js';
|
|
38
|
-
import {
|
|
38
|
+
import { speechOf } from '../../send-tools.js';
|
|
39
39
|
import { storedInjectionMarkOf } from '../../stored-injections.js';
|
|
40
40
|
|
|
41
41
|
export interface SemanticIndexConfig {
|
|
@@ -137,12 +137,6 @@ export interface SearchResponse {
|
|
|
137
137
|
}
|
|
138
138
|
|
|
139
139
|
const PRIVATE_PROSE_TOOLS = new Set(['think', 'journal', 'skip_reply', 'private_note']);
|
|
140
|
-
/**
|
|
141
|
-
* Tools whose message argument is what the resident said: the send tools,
|
|
142
|
-
* and edit_message, whose argument is the new text of a message it sent.
|
|
143
|
-
* With prose routing disabled the resident speaks through these.
|
|
144
|
-
*/
|
|
145
|
-
const SPEECH_TOOLS = new Set([...SEND_TOOLS, 'edit_message']);
|
|
146
140
|
|
|
147
141
|
/**
|
|
148
142
|
* The semantic index service's failure, said of the service alone: it didn't
|
|
@@ -302,8 +296,10 @@ function isHit(hit: unknown): boolean {
|
|
|
302
296
|
return isObject(hit) && typeof (hit as { id?: unknown }).id === 'string';
|
|
303
297
|
}
|
|
304
298
|
|
|
299
|
+
export const ERROR_MARK = ', error';
|
|
300
|
+
|
|
305
301
|
/** Text to embed for one message, or '' when there is nothing worth indexing. */
|
|
306
|
-
export function messageIndexText(msg: StoredMessage, includePrivateTools = true): string {
|
|
302
|
+
export function messageIndexText(msg: StoredMessage, includePrivateTools = true, failed: ReadonlySet<string> = new Set()): string {
|
|
307
303
|
const parts: string[] = [];
|
|
308
304
|
for (const block of msg.content as ContentBlock[]) {
|
|
309
305
|
if (block.type === 'text' && typeof block.text === 'string') {
|
|
@@ -313,12 +309,9 @@ export function messageIndexText(msg: StoredMessage, includePrivateTools = true)
|
|
|
313
309
|
for (const v of Object.values(input)) {
|
|
314
310
|
if (typeof v === 'string' && v.trim().length > 0) parts.push(`[${block.name}] ${v}`);
|
|
315
311
|
}
|
|
316
|
-
} else if (block.type === 'tool_use'
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
const input = (block as { input?: { content?: unknown; text?: unknown } }).input ?? {};
|
|
320
|
-
const v = input.content ?? input.text;
|
|
321
|
-
if (typeof v === 'string' && v.trim().length > 0) parts.push(`[${bareToolName(block.name)}] ${v}`);
|
|
312
|
+
} else if (block.type === 'tool_use') {
|
|
313
|
+
const said = speechOf(block.name, (block as { input?: unknown }).input);
|
|
314
|
+
if (said) parts.push(`[${said.tool}${failed.has(block.id) ? ERROR_MARK : ''}] ${said.words}`);
|
|
322
315
|
}
|
|
323
316
|
}
|
|
324
317
|
return parts.join('\n').trim();
|
|
@@ -705,9 +698,10 @@ export class SemanticIndexer {
|
|
|
705
698
|
if (budget <= 0) break;
|
|
706
699
|
this.editedIds.delete(id);
|
|
707
700
|
const m = this.cm.getMessage(id as never);
|
|
708
|
-
// Not on the current branch (e.g.
|
|
709
|
-
// never delete —
|
|
710
|
-
//
|
|
701
|
+
// Not on the current branch (e.g. a rollback after the edit): drop
|
|
702
|
+
// it, never delete — a switch back to the branch that holds it
|
|
703
|
+
// brings the message back and the time walk will not revisit it.
|
|
704
|
+
// Search-time branch checks hide it meanwhile.
|
|
711
705
|
if (!m) continue;
|
|
712
706
|
edited.push(id); budget--;
|
|
713
707
|
const item = messageToItem(m, this.cfg);
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*
|
|
6
6
|
* P describes disk, and disk does not rewind with a branch switch, so P lives
|
|
7
7
|
* in global chronicle records (RecordJournal) rather than branch state: after
|
|
8
|
-
*
|
|
8
|
+
* a rollback selects an older tree, P still says what disk holds, and a
|
|
9
9
|
* difference reads as a store-side change, never as a disk edit. Branch-local
|
|
10
10
|
* intent — tombstones, store origin, conflicts — lives in BranchIntents and
|
|
11
11
|
* rewinds with the tree.
|
|
@@ -1052,6 +1052,12 @@ export class WorkspaceModule implements Module {
|
|
|
1052
1052
|
/** Whether an agent's history holds a message, as the framework hands it over (useHistory). */
|
|
1053
1053
|
private historyLookup: ((agentName: string, messageId: string) => boolean) | null = null;
|
|
1054
1054
|
|
|
1055
|
+
/** Whether an agent's window still holds what it did after a place in the record, as the framework hands it over (useWindow). */
|
|
1056
|
+
private windowLookup: ((agentName: string, afterSequence: number) => boolean) | null = null;
|
|
1057
|
+
|
|
1058
|
+
/** Whether a turn of an agent's is alive now, as the framework hands it over with the window lookup (useWindow). */
|
|
1059
|
+
private turnLookup: ((agentName: string) => boolean) | null = null;
|
|
1060
|
+
|
|
1055
1061
|
constructor(config: WorkspaceConfig) {
|
|
1056
1062
|
for (const mount of config.mounts) {
|
|
1057
1063
|
const cap: unknown = mount.walkCap;
|
|
@@ -1228,8 +1234,13 @@ export class WorkspaceModule implements Module {
|
|
|
1228
1234
|
carried.push(saved);
|
|
1229
1235
|
continue;
|
|
1230
1236
|
}
|
|
1237
|
+
// An entry an earlier release saved (no `v`) doesn't say whether a
|
|
1238
|
+
// turn made each write, and that release judged a position by the
|
|
1239
|
+
// branch alone: so is it judged here (outsideTurn), so its head
|
|
1240
|
+
// isn't taken for a later turn's.
|
|
1241
|
+
const fromEarlier = saved.v === undefined;
|
|
1231
1242
|
restored.set(saved.mount, new Map(Object.entries(saved.agents).map(([agent, head]) =>
|
|
1232
|
-
[agent, { branchId: head.branchId, after: head.after, notice: head.notice ?? null }])));
|
|
1243
|
+
[agent, { branchId: head.branchId, after: head.after, notice: head.notice ?? null, ...(head.outsideTurn || fromEarlier ? { outsideTurn: true as const } : {}) }])));
|
|
1233
1244
|
}
|
|
1234
1245
|
this.headsJournal = journal;
|
|
1235
1246
|
this.loadedHeads = text;
|
|
@@ -1821,10 +1832,12 @@ export class WorkspaceModule implements Module {
|
|
|
1821
1832
|
if (!this.headsJournal) return;
|
|
1822
1833
|
const snapshot: DirectHeadsSnapshot = [
|
|
1823
1834
|
...this.carriedHeads,
|
|
1824
|
-
...[...this.directHeads].filter(([, heads]) => heads.size > 0).map(([name, heads]) => ({
|
|
1835
|
+
...[...this.directHeads].filter(([, heads]) => heads.size > 0).map(([name, heads]): DirectHeadsEntry => ({
|
|
1825
1836
|
mount: name,
|
|
1826
1837
|
root: resolve(this.mounts.get(name)!.config.path),
|
|
1827
|
-
|
|
1838
|
+
v: DIRECT_HEADS_VERSION,
|
|
1839
|
+
agents: Object.fromEntries([...heads].map(([agent, { branchId, after, notice, outsideTurn }]) =>
|
|
1840
|
+
[agent, { branchId, after, ...(notice !== null ? { notice } : {}), ...(outsideTurn ? { outsideTurn } : {}) }])),
|
|
1828
1841
|
})),
|
|
1829
1842
|
];
|
|
1830
1843
|
const text = canonicalHeads(snapshot);
|
|
@@ -5088,7 +5101,10 @@ export class WorkspaceModule implements Module {
|
|
|
5088
5101
|
* changed meanwhile, the head moved under the call, and P is set there,
|
|
5089
5102
|
* so the next start judges the deletion by the branch its turn was on,
|
|
5090
5103
|
* unless the history doesn't hold P already, whose notice is owed. A write no agent
|
|
5091
|
-
* made tells no one.
|
|
5104
|
+
* made tells no one. A write made while no turn of the agent's is alive (a
|
|
5105
|
+
* host's executeToolCall naming it) is marked so (`outsideTurn`): no round
|
|
5106
|
+
* of the agent's history made it, so the window can't say it was undone,
|
|
5107
|
+
* and only the branch's position decides. The store's reads here come after the write landed,
|
|
5092
5108
|
* so one that throws is logged and P stays, as for a history that can't
|
|
5093
5109
|
* be read, and the write still answers that it landed.
|
|
5094
5110
|
*/
|
|
@@ -5100,12 +5116,13 @@ export class WorkspaceModule implements Module {
|
|
|
5100
5116
|
if (!heads) this.directHeads.set(mount.config.name, (heads = new Map()));
|
|
5101
5117
|
const head = heads.get(agentName);
|
|
5102
5118
|
const branchId = store.currentBranch().id;
|
|
5119
|
+
const outsideTurn = this.turnLookup?.(agentName) === false ? { outsideTurn: true as const } : {};
|
|
5103
5120
|
if (since && since.branchId !== branchId) {
|
|
5104
|
-
if (!head || this.historyHoldsWrites(agentName, head) === true) heads.set(agentName, { ...since, notice: null });
|
|
5121
|
+
if (!head || this.historyHoldsWrites(agentName, head) === true) heads.set(agentName, { ...since, notice: null, ...outsideTurn });
|
|
5105
5122
|
return;
|
|
5106
5123
|
}
|
|
5107
5124
|
if (head && this.historyHoldsWrites(agentName, head) !== true) return;
|
|
5108
|
-
heads.set(agentName, { branchId, after: store.currentSequence(), notice: null });
|
|
5125
|
+
heads.set(agentName, { branchId, after: store.currentSequence(), notice: null, ...outsideTurn });
|
|
5109
5126
|
} catch (err) {
|
|
5110
5127
|
console.error('[workspace] could not record a direct write\'s position:', err);
|
|
5111
5128
|
}
|
|
@@ -5132,7 +5149,20 @@ export class WorkspaceModule implements Module {
|
|
|
5132
5149
|
* leaves the next start to decide (headMoveNotice).
|
|
5133
5150
|
*/
|
|
5134
5151
|
private historyHoldsWrites(agentName: string, head: DirectHead): boolean | null {
|
|
5135
|
-
if (this.holdsPosition(head))
|
|
5152
|
+
if (this.holdsPosition(head)) {
|
|
5153
|
+
// The branch holds the write, but an undo on the agent's window (the
|
|
5154
|
+
// framework's presentation index) moves no branch: it takes the turn
|
|
5155
|
+
// that wrote out of the window, which the framework's lookup says. A
|
|
5156
|
+
// write made outside any turn of the agent's has no turn to take out.
|
|
5157
|
+
let held: boolean;
|
|
5158
|
+
try {
|
|
5159
|
+
held = head.outsideTurn === true || this.windowLookup?.(agentName, head.after) !== false;
|
|
5160
|
+
} catch (err) {
|
|
5161
|
+
console.error('[workspace] window lookup for the head-move notice failed:', err);
|
|
5162
|
+
return null;
|
|
5163
|
+
}
|
|
5164
|
+
if (held) return true;
|
|
5165
|
+
}
|
|
5136
5166
|
if (head.notice === null) return false;
|
|
5137
5167
|
try {
|
|
5138
5168
|
return this.historyLookup?.(agentName, head.notice) === true;
|
|
@@ -5146,9 +5176,10 @@ export class WorkspaceModule implements Module {
|
|
|
5146
5176
|
* Whether the store's current branch holds what came before a direct
|
|
5147
5177
|
* write: it's the write's branch, or continues it with every fork point on
|
|
5148
5178
|
* the way after `after`, the store's head when the write landed. A fork at
|
|
5149
|
-
* exactly `after` doesn't:
|
|
5150
|
-
*
|
|
5151
|
-
*
|
|
5179
|
+
* exactly `after` doesn't: a rollback cut there (to the row the write
|
|
5180
|
+
* followed) leaves the write out, as an undo's fork at its turn's
|
|
5181
|
+
* sequenceBefore did before #291 (an undo moves no branch since). A
|
|
5182
|
+
* missing branch or one without fork metadata holds nothing,
|
|
5152
5183
|
* as for the materialize guard (isLinearContinuation).
|
|
5153
5184
|
*/
|
|
5154
5185
|
private holdsPosition({ branchId, after }: DirectHead): boolean {
|
|
@@ -5201,14 +5232,31 @@ export class WorkspaceModule implements Module {
|
|
|
5201
5232
|
}
|
|
5202
5233
|
|
|
5203
5234
|
/**
|
|
5204
|
-
* How the module asks whether an agent's history holds a message
|
|
5205
|
-
*
|
|
5206
|
-
* over once, when the module is added.
|
|
5235
|
+
* How the module asks whether an agent's history holds a message: its
|
|
5236
|
+
* record holds it, and, on a window the framework presents, no undo has
|
|
5237
|
+
* taken it out of the window. Handed over once, when the module is added.
|
|
5238
|
+
* Without it, no notice is held.
|
|
5207
5239
|
*/
|
|
5208
5240
|
useHistory(lookup: (agentName: string, messageId: string) => boolean): void {
|
|
5209
5241
|
this.historyLookup = lookup;
|
|
5210
5242
|
}
|
|
5211
5243
|
|
|
5244
|
+
/**
|
|
5245
|
+
* How the module asks whether an agent's window still holds what the
|
|
5246
|
+
* agent did after a place in the record (`afterSequence`, the store's head
|
|
5247
|
+
* when it wrote a mount direct): false once an undo on its window took
|
|
5248
|
+
* that turn out, though the branch still holds the write. Handed over
|
|
5249
|
+
* once, by a framework with the presentation index. Without it, the
|
|
5250
|
+
* branch's position alone decides. `turnAlive` says whether a turn of the
|
|
5251
|
+
* agent's is alive at a write: one made outside any (a host's
|
|
5252
|
+
* executeToolCall naming the agent) has no turn in the window, so the
|
|
5253
|
+
* branch's position alone decides for it too.
|
|
5254
|
+
*/
|
|
5255
|
+
useWindow(lookup: (agentName: string, afterSequence: number) => boolean, turnAlive?: (agentName: string) => boolean): void {
|
|
5256
|
+
this.windowLookup = lookup;
|
|
5257
|
+
this.turnLookup = turnAlive ?? null;
|
|
5258
|
+
}
|
|
5259
|
+
|
|
5212
5260
|
private async handleDelete(input: DeleteInput, callerAgentName?: string): Promise<ToolResult> {
|
|
5213
5261
|
const { mount, relativePath, path } = await this.parseFilePath(input.path).catch((error: unknown) => { throw notStored(error); });
|
|
5214
5262
|
if (relativePath === '') return { success: false, error: didNothing('delete', namesRoot(input.path, mount.config.name)), isError: true };
|
|
@@ -6250,10 +6298,11 @@ export class WorkspaceModule implements Module {
|
|
|
6250
6298
|
mount.lastMaterializedBranchId = null;
|
|
6251
6299
|
mount.lastMaterializedSeq = 0;
|
|
6252
6300
|
|
|
6253
|
-
// force: this path only runs after a deliberate
|
|
6254
|
-
// on the framework's own _config mount — restoring disk
|
|
6255
|
-
// state IS the operator intent, so the freshness guard
|
|
6256
|
-
// the whole tree is that deliberate scope, entries
|
|
6301
|
+
// force: this path only runs after a deliberate branch switch, rollback
|
|
6302
|
+
// or suppression on the framework's own _config mount — restoring disk
|
|
6303
|
+
// to the branch state IS the operator intent, so the freshness guard
|
|
6304
|
+
// yields. named: the whole tree is that deliberate scope, entries
|
|
6305
|
+
// without evidence too.
|
|
6257
6306
|
const pushed = await this.withMount(mount, () => {
|
|
6258
6307
|
const branchId = store.currentBranch().id;
|
|
6259
6308
|
return this.pushUnlocked(mount, store.treeList(mount.treeStateId).map((e) => e.path), { force: true, named: true, branchId });
|
|
@@ -6803,6 +6852,8 @@ interface DirectHead {
|
|
|
6803
6852
|
branchId: string;
|
|
6804
6853
|
after: number;
|
|
6805
6854
|
notice: string | null;
|
|
6855
|
+
/** Set where P was written while no turn of the agent's was alive (recordDirectWrite), or read from a record an earlier release saved, which doesn't say (loadDirectHeads): the window isn't asked of it. */
|
|
6856
|
+
outsideTurn?: true;
|
|
6806
6857
|
}
|
|
6807
6858
|
|
|
6808
6859
|
/** A store position: a branch and its head. */
|
|
@@ -6811,11 +6862,20 @@ type DirectPosition = Pick<DirectHead, 'branchId' | 'after'>;
|
|
|
6811
6862
|
/** The global record type directHeads is saved as: a checkpoint at a clean stop that changed it. */
|
|
6812
6863
|
const DIRECT_HEADS_RECORD_TYPE = 'workspace/direct-heads';
|
|
6813
6864
|
|
|
6865
|
+
/**
|
|
6866
|
+
* The saved entries' version: an entry this release saves carries it, and
|
|
6867
|
+
* says of each position whether a turn of its agent's made it (`outsideTurn`
|
|
6868
|
+
* where none did). An entry an earlier release saved has none.
|
|
6869
|
+
*/
|
|
6870
|
+
const DIRECT_HEADS_VERSION = 2;
|
|
6871
|
+
|
|
6814
6872
|
/** One mount's positions at one root (resolved, as DiskAgreement keeps a root), by agent, with N only where it's set. */
|
|
6815
6873
|
interface DirectHeadsEntry {
|
|
6816
6874
|
mount: string;
|
|
6817
6875
|
root: string;
|
|
6818
|
-
|
|
6876
|
+
/** DIRECT_HEADS_VERSION, absent on an entry an earlier release saved. */
|
|
6877
|
+
v?: typeof DIRECT_HEADS_VERSION;
|
|
6878
|
+
agents: Record<string, { branchId: string; after: number; notice?: string; outsideTurn?: true }>;
|
|
6819
6879
|
}
|
|
6820
6880
|
|
|
6821
6881
|
/** directHeads as saved: an entry per mount and root its agents wrote direct under. */
|
|
@@ -6832,12 +6892,14 @@ function checkedHeads(value: unknown): DirectHeadsSnapshot {
|
|
|
6832
6892
|
const isObject = (v: unknown): v is Record<string, unknown> => typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
6833
6893
|
if (!Array.isArray(value)) throw new Error("the record isn't of the shape saved");
|
|
6834
6894
|
for (const saved of value as unknown[]) {
|
|
6835
|
-
if (!isObject(saved) || typeof saved.mount !== 'string' || typeof saved.root !== 'string' || !isObject(saved.agents)
|
|
6895
|
+
if (!isObject(saved) || typeof saved.mount !== 'string' || typeof saved.root !== 'string' || !isObject(saved.agents)
|
|
6896
|
+
|| (saved.v !== undefined && saved.v !== DIRECT_HEADS_VERSION)) {
|
|
6836
6897
|
throw new Error(`an entry isn't of the shape saved: ${JSON.stringify(saved)?.slice(0, 200)}`);
|
|
6837
6898
|
}
|
|
6838
6899
|
for (const [agent, head] of Object.entries(saved.agents)) {
|
|
6839
6900
|
if (!isObject(head) || typeof head.branchId !== 'string' || typeof head.after !== 'number'
|
|
6840
|
-
|| (head.notice !== undefined && typeof head.notice !== 'string')
|
|
6901
|
+
|| (head.notice !== undefined && typeof head.notice !== 'string')
|
|
6902
|
+
|| (head.outsideTurn !== undefined && head.outsideTurn !== true)) {
|
|
6841
6903
|
throw new Error(`agent ${JSON.stringify(agent)}'s position on mount ${JSON.stringify(saved.mount)} isn't of the shape saved`);
|
|
6842
6904
|
}
|
|
6843
6905
|
}
|
|
@@ -6847,9 +6909,9 @@ function checkedHeads(value: unknown): DirectHeadsSnapshot {
|
|
|
6847
6909
|
|
|
6848
6910
|
/** A saved record's content, whatever order its mounts and agents were written in, to tell whether a save would change it. */
|
|
6849
6911
|
function canonicalHeads(snapshot: DirectHeadsSnapshot): string {
|
|
6850
|
-
return JSON.stringify(snapshot.map(({ mount, root, agents }) => [mount, root, Object.keys(agents).sort().map((agent) => {
|
|
6851
|
-
const { branchId, after, notice } = agents[agent]!;
|
|
6852
|
-
return [agent, branchId, after, notice ?? null];
|
|
6912
|
+
return JSON.stringify(snapshot.map(({ mount, root, v, agents }) => [mount, root, v ?? null, Object.keys(agents).sort().map((agent) => {
|
|
6913
|
+
const { branchId, after, notice, outsideTurn } = agents[agent]!;
|
|
6914
|
+
return [agent, branchId, after, notice ?? null, outsideTurn === true];
|
|
6853
6915
|
})]).sort((a, b) => {
|
|
6854
6916
|
const [x, y] = [JSON.stringify(a.slice(0, 2)), JSON.stringify(b.slice(0, 2))];
|
|
6855
6917
|
return x < y ? -1 : x > y ? 1 : 0;
|
package/src/notice-tags.ts
CHANGED
|
@@ -5,7 +5,13 @@
|
|
|
5
5
|
* `[tag: …]` or `[tag …]`: text the framework didn't write is marked
|
|
6
6
|
* wherever it would open with one of these (supplied-text.ts). A toolset's
|
|
7
7
|
* `[server/toolset:instance]` label is built from its server's id and names
|
|
8
|
-
* instead
|
|
8
|
+
* instead, and so is a line of another agent's round as an agent that watches
|
|
9
|
+
* its slot is sent it (foreign-rounds.ts, #291): a bracket of the
|
|
10
|
+
* framework's around the tool's name, which the other agent supplied, and
|
|
11
|
+
* the call's input or the result's outcome. The line is marked as one text,
|
|
12
|
+
* so an opening of one of these tags is marked wherever it forms across it,
|
|
13
|
+
* the name included, while the framework's own words and placeholders in it
|
|
14
|
+
* stay unmarked.
|
|
9
15
|
*/
|
|
10
16
|
export const NOTICE_TAG = {
|
|
11
17
|
turnInterrupted: 'turn-interrupted',
|
|
@@ -39,6 +45,8 @@ export const NOTICE_TAG = {
|
|
|
39
45
|
channelInvitation: 'Channel invitation',
|
|
40
46
|
system: 'system',
|
|
41
47
|
toolsets: 'toolsets',
|
|
48
|
+
wakeOnboarding: 'wake onboarding',
|
|
49
|
+
suppressionReview: 'suppression review',
|
|
42
50
|
heartbeat: 'heartbeat',
|
|
43
51
|
silentHeartbeat: 'silent heartbeat',
|
|
44
52
|
heartbeatTick: 'heartbeat tick',
|
|
@@ -64,6 +72,7 @@ export const NOTICE_TAG = {
|
|
|
64
72
|
truncated: 'truncated',
|
|
65
73
|
cutToFit: 'cut to fit',
|
|
66
74
|
blockNotShown: 'block not shown',
|
|
75
|
+
noText: 'no text',
|
|
67
76
|
} as const;
|
|
68
77
|
|
|
69
78
|
/**
|
package/src/operator-log.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Operator action log — a durable, append-only JSONL record of every
|
|
3
3
|
* operator-initiated mutation of a live resident: branch rollbacks, message
|
|
4
|
-
* suppressions, undo/redo/hide,
|
|
5
|
-
* host quiesce/resume. One file per store, next to the chronicle
|
|
4
|
+
* suppressions, branch checkouts (switchBranch), undo/redo/hide,
|
|
5
|
+
* unstick/nudge, runtime-settings changes, host quiesce/resume. One file per store, next to the chronicle
|
|
6
6
|
* (`<storePath>/operator-actions.jsonl`), so it travels with backups and
|
|
7
7
|
* survives host restarts the way `repair-receipts.jsonl` and
|
|
8
8
|
* `watchdog-wedge.jsonl` do.
|
|
@@ -32,7 +32,7 @@ export interface OperatorRequester {
|
|
|
32
32
|
export interface OperatorLogEntry {
|
|
33
33
|
/** ISO-8601 wall-clock time of the record. */
|
|
34
34
|
at: string;
|
|
35
|
-
/** Action kind, e.g. 'rollback', 'suppress', 'undo', 'hide', 'quiesce'. */
|
|
35
|
+
/** Action kind, e.g. 'rollback', 'suppress', 'checkout', 'undo-turn', 'hide', 'quiesce'. */
|
|
36
36
|
kind: string;
|
|
37
37
|
/** Agent the action targeted (absent for host-wide actions). */
|
|
38
38
|
agent?: string;
|
|
@@ -167,6 +167,39 @@ export interface SurgeryMarksPreview {
|
|
|
167
167
|
messagesRemoved: number;
|
|
168
168
|
/** Removed messages that carry a Discord address at all. */
|
|
169
169
|
addressable: number;
|
|
170
|
+
/**
|
|
171
|
+
* Of the messages removed, how many no live agent is shown (#291): no
|
|
172
|
+
* window holds them (stored and never presented to an agent, or taken out
|
|
173
|
+
* of every window since), or only windows whose view leaves them out (a
|
|
174
|
+
* row a tune-out holds, which a window written down from the record
|
|
175
|
+
* holds). Their marks tell Discord of messages no agent was being shown.
|
|
176
|
+
* A message that may be in a window that couldn't be read isn't counted,
|
|
177
|
+
* and is logged. Set only when the agent's context is presented.
|
|
178
|
+
*/
|
|
179
|
+
neverPresented?: number;
|
|
180
|
+
/**
|
|
181
|
+
* For a rollback on a presented window: the rows after the target in the
|
|
182
|
+
* agent's window that the branch cut keeps in the record (stored before
|
|
183
|
+
* the write that presented the target, presented after it). They leave
|
|
184
|
+
* the window as arrived and not presented, and enter it again at the
|
|
185
|
+
* agent's next turn start, after what its window holds then; nothing at
|
|
186
|
+
* rest presents them before it (rollbackToMessage). An own row of the
|
|
187
|
+
* agent's among them re-enters at the surgery's release. The hold is in
|
|
188
|
+
* memory, so a restart before then presents them at its pass at rest.
|
|
189
|
+
* Not removed, so not counted in `messagesRemoved`, and not marked. Set
|
|
190
|
+
* only then.
|
|
191
|
+
*/
|
|
192
|
+
returnedToArrivals?: number;
|
|
193
|
+
/**
|
|
194
|
+
* For a rollback on a presented window: the rows after the target in the
|
|
195
|
+
* agent's window that the write presenting the target presented too (a
|
|
196
|
+
* batch). The cut is at that write, so they stay in the window after the
|
|
197
|
+
* target. Not removed, so not counted in `messagesRemoved`, and not
|
|
198
|
+
* marked: a suppression, or, for those with a Discord message id, a hide
|
|
199
|
+
* by it, takes them out.
|
|
200
|
+
* Set only then.
|
|
201
|
+
*/
|
|
202
|
+
keptInWindowAfterTarget?: number;
|
|
170
203
|
emoji: string;
|
|
171
204
|
scopes: Record<'addressed' | 'all', {
|
|
172
205
|
count: number;
|