@vascend/talos 0.1.5 → 0.1.6
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/dist/core/agent.d.ts +16 -3
- package/dist/core/agent.js +114 -34
- package/dist/core/background.d.ts +10 -3
- package/dist/core/background.js +55 -9
- package/dist/core/bootstrap.js +1 -0
- package/dist/core/compaction.js +1 -1
- package/dist/core/config-storage.d.ts +5 -0
- package/dist/core/config-storage.js +83 -0
- package/dist/core/config.d.ts +11 -2
- package/dist/core/config.js +24 -8
- package/dist/core/context-ledger.js +2 -1
- package/dist/core/context-policy.d.ts +1 -1
- package/dist/core/context-policy.js +10 -7
- package/dist/core/credentials.js +29 -30
- package/dist/core/effort.d.ts +1 -1
- package/dist/core/effort.js +5 -1
- package/dist/core/execution-guidance.d.ts +1 -1
- package/dist/core/execution-guidance.js +2 -0
- package/dist/core/file-coordination.d.ts +3 -0
- package/dist/core/file-coordination.js +28 -0
- package/dist/core/file-lease-store.d.ts +3 -0
- package/dist/core/file-lease-store.js +28 -12
- package/dist/core/fusion.d.ts +24 -0
- package/dist/core/fusion.js +80 -0
- package/dist/core/model-limits.d.ts +1 -0
- package/dist/core/model-limits.js +5 -1
- package/dist/core/permission-queue.js +15 -15
- package/dist/core/request-plan.js +4 -3
- package/dist/core/session-naming.js +4 -0
- package/dist/core/session.d.ts +4 -2
- package/dist/core/session.js +13 -4
- package/dist/core/settings.d.ts +2 -0
- package/dist/core/settings.js +5 -16
- package/dist/core/step-policy.d.ts +18 -0
- package/dist/core/step-policy.js +6 -0
- package/dist/core/tool-artifacts.d.ts +2 -0
- package/dist/core/tool-artifacts.js +21 -3
- package/dist/core/tool-result-index.js +29 -33
- package/dist/core/tool-result-store.js +6 -5
- package/dist/core/types.d.ts +10 -3
- package/dist/core/user-inbox.d.ts +9 -0
- package/dist/core/user-inbox.js +22 -3
- package/dist/core/user-input.js +1 -1
- package/dist/fusion/autopilot-fast.d.ts +59 -0
- package/dist/fusion/autopilot-fast.js +213 -0
- package/dist/fusion/autopilot.d.ts +75 -0
- package/dist/fusion/autopilot.js +308 -0
- package/dist/fusion/focus.d.ts +30 -0
- package/dist/fusion/focus.js +122 -0
- package/dist/fusion/gate.d.ts +30 -0
- package/dist/fusion/gate.js +95 -0
- package/dist/fusion/jev.d.ts +71 -0
- package/dist/fusion/jev.js +164 -0
- package/dist/fusion/receipts.d.ts +25 -0
- package/dist/fusion/receipts.js +34 -0
- package/dist/fusion/route.d.ts +25 -0
- package/dist/fusion/route.js +84 -0
- package/dist/fusion/run.d.ts +4 -0
- package/dist/fusion/run.js +186 -0
- package/dist/horizon/engine.d.ts +20 -1
- package/dist/horizon/engine.js +57 -0
- package/dist/horizon/index.d.ts +2 -2
- package/dist/horizon/index.js +1 -1
- package/dist/horizon/types.d.ts +29 -0
- package/dist/index.js +12 -0
- package/dist/providers/anthropic-oauth.d.ts +8 -3
- package/dist/providers/anthropic-oauth.js +13 -10
- package/dist/providers/anthropic.d.ts +9 -2
- package/dist/providers/anthropic.js +64 -21
- package/dist/providers/cli-models.d.ts +30 -0
- package/dist/providers/cli-models.js +194 -0
- package/dist/providers/model-effort.js +1 -1
- package/dist/providers/openai-oauth.d.ts +8 -3
- package/dist/providers/openai-oauth.js +9 -3
- package/dist/providers/openrouter-manual-fallback.d.ts +3 -1
- package/dist/providers/openrouter-manual-fallback.js +20 -20
- package/dist/providers/registry.js +3 -2
- package/dist/providers/retry.d.ts +3 -0
- package/dist/providers/retry.js +44 -1
- package/dist/remote/cifratura.d.ts +12 -0
- package/dist/remote/cifratura.js +66 -0
- package/dist/remote/index.d.ts +15 -0
- package/dist/remote/index.js +65 -0
- package/dist/remote/relay-client.d.ts +58 -0
- package/dist/remote/relay-client.js +315 -0
- package/dist/remote/sessione-remota.d.ts +60 -0
- package/dist/remote/sessione-remota.js +266 -0
- package/dist/sdk.d.ts +7 -2
- package/dist/sdk.js +3 -1
- package/dist/tools/builtin.js +41 -20
- package/dist/tools/capabilities.d.ts +3 -1
- package/dist/tools/capabilities.js +5 -2
- package/dist/tools/computer-use.js +2 -1
- package/dist/tools/pagination.js +1 -1
- package/dist/tools/program.js +34 -21
- package/dist/tools/team-tools.js +11 -6
- package/dist/tui/account-entry.js +14 -9
- package/dist/tui/agent-label.d.ts +2 -0
- package/dist/tui/agent-label.js +5 -0
- package/dist/tui/agent-sessions-screen.d.ts +12 -2
- package/dist/tui/agent-sessions-screen.js +62 -16
- package/dist/tui/agent-sessions.d.ts +14 -0
- package/dist/tui/agent-sessions.js +67 -6
- package/dist/tui/bottom-input.d.ts +46 -2
- package/dist/tui/bottom-input.js +358 -59
- package/dist/tui/branding.js +8 -4
- package/dist/tui/capability-lists.d.ts +10 -0
- package/dist/tui/capability-lists.js +41 -0
- package/dist/tui/command-output-registry.js +4 -0
- package/dist/tui/command-transcript.d.ts +1 -1
- package/dist/tui/command-transcript.js +17 -21
- package/dist/tui/commands.js +4 -1
- package/dist/tui/compaction-status.d.ts +7 -0
- package/dist/tui/compaction-status.js +39 -0
- package/dist/tui/config-recovery.d.ts +12 -0
- package/dist/tui/config-recovery.js +54 -0
- package/dist/tui/context-meter.d.ts +3 -0
- package/dist/tui/context-meter.js +35 -8
- package/dist/tui/diff.d.ts +9 -0
- package/dist/tui/diff.js +43 -19
- package/dist/tui/fusion-menu.d.ts +5 -0
- package/dist/tui/fusion-menu.js +89 -0
- package/dist/tui/i18n-catalog.js +312 -1
- package/dist/tui/live-command.d.ts +1 -0
- package/dist/tui/live-command.js +9 -0
- package/dist/tui/live-output.d.ts +1 -0
- package/dist/tui/live-output.js +11 -0
- package/dist/tui/model-details.js +13 -12
- package/dist/tui/model-picker.js +17 -7
- package/dist/tui/model-selection.js +19 -10
- package/dist/tui/native-scrollback.js +5 -0
- package/dist/tui/prompt-queue.d.ts +3 -0
- package/dist/tui/prompt-queue.js +19 -1
- package/dist/tui/provider-label.d.ts +2 -0
- package/dist/tui/provider-label.js +9 -0
- package/dist/tui/provider-menu.js +25 -24
- package/dist/tui/queue-screen.js +2 -1
- package/dist/tui/remote-command.d.ts +7 -0
- package/dist/tui/remote-command.js +79 -0
- package/dist/tui/repl.d.ts +8 -2
- package/dist/tui/repl.js +355 -311
- package/dist/tui/review-store.d.ts +1 -0
- package/dist/tui/review-store.js +28 -7
- package/dist/tui/review-team.js +4 -3
- package/dist/tui/runtime-error.d.ts +2 -0
- package/dist/tui/runtime-error.js +26 -0
- package/dist/tui/selector-mouse.d.ts +1 -0
- package/dist/tui/selector-mouse.js +1 -1
- package/dist/tui/selector.d.ts +7 -0
- package/dist/tui/selector.js +19 -2
- package/dist/tui/session-controls.d.ts +26 -0
- package/dist/tui/session-controls.js +65 -0
- package/dist/tui/session-naming-notice.js +5 -3
- package/dist/tui/session-replay.d.ts +1 -0
- package/dist/tui/session-replay.js +101 -32
- package/dist/tui/session-transcript-layout.d.ts +9 -0
- package/dist/tui/session-transcript-layout.js +41 -0
- package/dist/tui/startup.js +63 -33
- package/dist/tui/status-line.d.ts +1 -1
- package/dist/tui/status-line.js +20 -12
- package/dist/tui/talos-art-data.d.ts +1 -0
- package/dist/tui/talos-art-data.js +2 -0
- package/dist/tui/talos-art.d.ts +1 -0
- package/dist/tui/talos-art.js +9 -0
- package/dist/tui/task-labels.d.ts +1 -0
- package/dist/tui/task-labels.js +8 -0
- package/dist/tui/terminal-text.d.ts +2 -1
- package/dist/tui/terminal-text.js +28 -2
- package/dist/tui/theme.js +2 -2
- package/dist/tui/tool-presentation.d.ts +3 -0
- package/dist/tui/tool-presentation.js +98 -0
- package/dist/tui/tool-style.js +4 -0
- package/dist/tui/transcript-store.d.ts +25 -0
- package/dist/tui/transcript-store.js +151 -0
- package/dist/tui/usage-footer.d.ts +1 -1
- package/dist/tui/usage-footer.js +3 -1
- package/dist/tui/vascend-id.d.ts +49 -0
- package/dist/tui/vascend-id.js +321 -0
- package/dist/tui/web-login-screen.js +4 -3
- package/dist/tui/web-login.d.ts +7 -15
- package/dist/tui/web-login.js +38 -78
- package/dist/tui/worker-transcripts.d.ts +31 -0
- package/dist/tui/worker-transcripts.js +91 -0
- package/dist/vascend/candidate-collector.d.ts +6 -5
- package/dist/vascend/candidate-collector.js +44 -43
- package/dist/vascend/context-lint.js +32 -2
- package/dist/vascend/context-market-selection.js +12 -5
- package/dist/vascend/context-pack-render.js +10 -4
- package/dist/vascend/context-packet-mirrors.d.ts +8 -0
- package/dist/vascend/context-packet-mirrors.js +24 -0
- package/dist/vascend/context-plan-events.d.ts +4 -0
- package/dist/vascend/context-plan-events.js +44 -0
- package/dist/vascend/context-snapshot.js +4 -2
- package/dist/vascend/context-store-reader.d.ts +20 -0
- package/dist/vascend/context-store-reader.js +46 -0
- package/dist/vascend/file-lock.d.ts +1 -0
- package/dist/vascend/file-lock.js +26 -0
- package/dist/vascend/granular-kingdom.d.ts +1 -0
- package/dist/vascend/granular-kingdom.js +22 -15
- package/dist/vascend/kingdom-bus.d.ts +1 -0
- package/dist/vascend/kingdom-bus.js +3 -0
- package/dist/vascend/kingdom-channel.d.ts +2 -0
- package/dist/vascend/kingdom-channel.js +3 -0
- package/dist/vascend/kingdom-live.d.ts +32 -4
- package/dist/vascend/kingdom-live.js +149 -13
- package/dist/vascend/kingdom-run.d.ts +5 -1
- package/dist/vascend/kingdom-run.js +6 -2
- package/dist/vascend/kingdom.d.ts +3 -0
- package/dist/vascend/kingdom.js +20 -13
- package/dist/vascend/memory-packet.d.ts +2 -1
- package/dist/vascend/memory-packet.js +31 -44
- package/dist/vascend/plan-store.d.ts +3 -1
- package/dist/vascend/plan-store.js +6 -4
- package/dist/vascend/room-memory.d.ts +10 -1
- package/dist/vascend/room-memory.js +42 -2
- package/dist/vascend/runtime.d.ts +3 -11
- package/dist/vascend/runtime.js +11 -123
- package/dist/vascend/session-search.js +2 -0
- package/dist/vascend/team-session.js +3 -2
- package/dist/vascend/vision.d.ts +3 -1
- package/dist/vascend/vision.js +6 -4
- package/dist/vascend/worker-session.d.ts +20 -0
- package/dist/vascend/worker-session.js +83 -0
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { runTurn } from "../core/agent.js";
|
|
2
2
|
import { Session } from "../core/session.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { createWorkerInbox } from "./kingdom-live.js";
|
|
4
|
+
import { createWorkerSession } from "./worker-session.js";
|
|
5
5
|
import { disjointAreas } from "./team-areas.js";
|
|
6
6
|
import { fileActor, withFileActor } from "../core/file-coordination.js";
|
|
7
7
|
import { launchGranular, granularConcurrency, formatGranularReport, } from "./granular-launcher.js";
|
|
@@ -114,7 +114,7 @@ OBIETTIVO_UNITA'
|
|
|
114
114
|
}
|
|
115
115
|
// Costruisce il TaskRunner che esegue una unita' come sessione di agente.
|
|
116
116
|
export function makeAgentUnitRunner(opts) {
|
|
117
|
-
const { harness, kingdomId, castleSlug,
|
|
117
|
+
const { harness, kingdomId, castleSlug, confirm, cwd, isolated } = opts;
|
|
118
118
|
const peers = opts.units.map((u) => u.id);
|
|
119
119
|
const depth = opts.depth ?? 2;
|
|
120
120
|
const maxDepth = maxTeamDepth(opts);
|
|
@@ -150,6 +150,8 @@ export function makeAgentUnitRunner(opts) {
|
|
|
150
150
|
...(cwd ? { cwd } : {}),
|
|
151
151
|
};
|
|
152
152
|
const self = `${castleSlug}/${unit.id}`;
|
|
153
|
+
let controller = new AbortController();
|
|
154
|
+
const signal = controller.signal;
|
|
153
155
|
const spawnKingdom = depth < maxDepth ? async (specs) => {
|
|
154
156
|
const units = nestedUnits(specs);
|
|
155
157
|
if (!units.length)
|
|
@@ -188,6 +190,7 @@ export function makeAgentUnitRunner(opts) {
|
|
|
188
190
|
};
|
|
189
191
|
const report = await launchGranularKingdom({
|
|
190
192
|
...opts,
|
|
193
|
+
signal: controller.signal,
|
|
191
194
|
harness: { ...harness, config: runConfig, tools: workerTools },
|
|
192
195
|
castleSlug: self,
|
|
193
196
|
units,
|
|
@@ -196,6 +199,9 @@ export function makeAgentUnitRunner(opts) {
|
|
|
196
199
|
markCastle: undefined,
|
|
197
200
|
onEvent: (id, event) => {
|
|
198
201
|
const slug = `${self}/${id}`;
|
|
202
|
+
// Preserve raw child events for the host before the compact parent summary.
|
|
203
|
+
if (event.type !== "kingdom" && event.type !== "usage")
|
|
204
|
+
opts.onEvent?.(`${unit.id}/${id}`, event);
|
|
199
205
|
if (event.type === "text") {
|
|
200
206
|
const text = (textBuffers.get(slug) ?? "") + event.delta;
|
|
201
207
|
textBuffers.set(slug, text);
|
|
@@ -216,13 +222,14 @@ export function makeAgentUnitRunner(opts) {
|
|
|
216
222
|
} : undefined;
|
|
217
223
|
// Anche il sotto-collaboratore ha la sua casella: la scheda laterale non
|
|
218
224
|
// distingue i livelli, e nemmeno chi ci scrive dentro deve farlo.
|
|
219
|
-
const
|
|
220
|
-
|
|
225
|
+
const binding = createWorkerInbox();
|
|
226
|
+
const inbox = binding.inbox;
|
|
221
227
|
const deps = {
|
|
222
228
|
provider: resolved.provider,
|
|
223
229
|
tools: workerTools,
|
|
224
230
|
session,
|
|
225
231
|
config: runConfig,
|
|
232
|
+
env: harness.env,
|
|
226
233
|
confirm,
|
|
227
234
|
ask: opts.ask,
|
|
228
235
|
host: undefined,
|
|
@@ -251,22 +258,22 @@ export function makeAgentUnitRunner(opts) {
|
|
|
251
258
|
+ (unit.assignment?.instructions ? `\nISTRUZIONI_AGGIUNTIVE\n${unit.assignment.instructions}\n` : "")
|
|
252
259
|
+ (ctx.prerequisites?.length ? "\nPREREQUISITI_COMPLETATI (risultati da verificare)\n"
|
|
253
260
|
+ ctx.prerequisites.map((result) => `[${result.id}] ${result.summary}`).join("\n").slice(0, 6000) + "\n" : "") + unit.goal;
|
|
261
|
+
const worker = createWorkerSession({ kingdomId, slug: self, sessionId: session.id, goal: unit.goal,
|
|
262
|
+
parentSignal: ctx.signal, controller, binding, deps, sink, retain: !isolated ? opts.retainSessions ?? false : false,
|
|
263
|
+
onController: next => { controller = next; } });
|
|
254
264
|
try {
|
|
255
265
|
sink({ type: "kingdom", phase: "session", kingdomId, sessionId: session.id,
|
|
256
266
|
slug: self, state: "spawned", goal: unit.goal, at: Date.now() });
|
|
257
|
-
await runTurn(deps, input, sink,
|
|
267
|
+
await runTurn(deps, input, sink, signal);
|
|
268
|
+
if (signal.aborted)
|
|
269
|
+
throw new Error("interrotta");
|
|
270
|
+
if (runError || !completed)
|
|
271
|
+
throw new Error(runError || "unita' terminata senza completamento verificato");
|
|
272
|
+
return { summary: summary.trim() };
|
|
258
273
|
}
|
|
259
274
|
finally {
|
|
260
|
-
|
|
261
|
-
kingdomLive.release(kingdomId, self);
|
|
262
|
-
sink({ type: "kingdom", phase: "session", kingdomId, sessionId: session.id,
|
|
263
|
-
slug: self, state: "despawned", at: Date.now() });
|
|
275
|
+
worker.finish();
|
|
264
276
|
}
|
|
265
|
-
if (ctx.signal.aborted)
|
|
266
|
-
throw new Error("interrotta");
|
|
267
|
-
if (runError || !completed)
|
|
268
|
-
throw new Error(runError || "unita' terminata senza completamento verificato");
|
|
269
|
-
return { summary: summary.trim() };
|
|
270
277
|
};
|
|
271
278
|
}
|
|
272
279
|
// Endpoint completo: lancia le unita' granulari di un castello in parallelo.
|
|
@@ -19,6 +19,7 @@ export declare class KingdomBus {
|
|
|
19
19
|
private seq;
|
|
20
20
|
post(kingdomId: string, from: string, to: string | null, text: string, ts: number): KingdomMessage;
|
|
21
21
|
inbox(kingdomId: string, me: string, filter?: (message: KingdomMessage) => boolean): KingdomMessage[];
|
|
22
|
+
peekInbox(kingdomId: string, me: string): readonly KingdomMessage[];
|
|
22
23
|
history(kingdomId: string): readonly KingdomMessage[];
|
|
23
24
|
clear(kingdomId: string): void;
|
|
24
25
|
}
|
|
@@ -41,6 +41,9 @@ export class KingdomBus {
|
|
|
41
41
|
return read.messages;
|
|
42
42
|
}
|
|
43
43
|
// Tutti i messaggi del regno (per il riepilogo/log), senza toccare i cursori.
|
|
44
|
+
peekInbox(kingdomId, me) {
|
|
45
|
+
return consumeInbox(this.boards.get(kingdomId) ?? [], me, this.cursors.get(`${kingdomId}::${me}`) ?? { last: 0 }).messages;
|
|
46
|
+
}
|
|
44
47
|
history(kingdomId) {
|
|
45
48
|
return this.boards.get(kingdomId) ?? [];
|
|
46
49
|
}
|
|
@@ -8,6 +8,7 @@ export declare class PersistentKingdomChannel {
|
|
|
8
8
|
constructor(sessionDir: string, opts?: KingdomChannelOptions);
|
|
9
9
|
post(kingdomId: string, from: string, to: string | null, text: string, ts: number): KingdomMessage;
|
|
10
10
|
inbox(kingdomId: string, me: string, filter?: (message: KingdomMessage) => boolean): KingdomMessage[];
|
|
11
|
+
peekInbox(kingdomId: string, me: string): readonly KingdomMessage[];
|
|
11
12
|
history(kingdomId: string): readonly KingdomMessage[];
|
|
12
13
|
clear(kingdomId: string): void;
|
|
13
14
|
}
|
|
@@ -15,6 +16,7 @@ export declare function getKingdomChannel(sessionDir: string, opts?: KingdomChan
|
|
|
15
16
|
export interface KingdomBusLike {
|
|
16
17
|
post(kingdomId: string, from: string, to: string | null, text: string, ts: number): KingdomMessage;
|
|
17
18
|
inbox(kingdomId: string, me: string, filter?: (message: KingdomMessage) => boolean): KingdomMessage[];
|
|
19
|
+
peekInbox(kingdomId: string, me: string): readonly KingdomMessage[];
|
|
18
20
|
history(kingdomId: string): readonly KingdomMessage[];
|
|
19
21
|
clear(kingdomId: string): void;
|
|
20
22
|
}
|
|
@@ -127,6 +127,9 @@ export class PersistentKingdomChannel {
|
|
|
127
127
|
});
|
|
128
128
|
}
|
|
129
129
|
// Tutti i messaggi del regno (per riepilogo/log), senza toccare i cursori.
|
|
130
|
+
peekInbox(kingdomId, me) {
|
|
131
|
+
return consumeInbox(readBoard(busFile(this.sessionDir, kingdomId)), me, readCursors(cursorsFile(this.sessionDir, kingdomId))[me] ?? { last: 0 }).messages;
|
|
132
|
+
}
|
|
130
133
|
history(kingdomId) {
|
|
131
134
|
return readBoard(busFile(this.sessionDir, kingdomId));
|
|
132
135
|
}
|
|
@@ -1,9 +1,20 @@
|
|
|
1
|
-
import type
|
|
2
|
-
|
|
1
|
+
import { type PendingUserMessage, type UserInbox } from "../core/user-inbox.js";
|
|
2
|
+
import type { ContentPart } from "../core/types.js";
|
|
3
|
+
export interface LiveVassalOptions {
|
|
4
|
+
readonly contextSource?: Pick<import("../core/agent.js").AgentDeps, "config" | "env" | "session" | "tools">;
|
|
5
|
+
readonly stop?: () => void;
|
|
6
|
+
readonly wake?: () => void;
|
|
7
|
+
readonly bindInbox?: (inbox: UserInbox) => void;
|
|
8
|
+
readonly close?: () => void;
|
|
9
|
+
}
|
|
10
|
+
export interface LiveVassal extends LiveVassalOptions {
|
|
3
11
|
readonly kingdomId: string;
|
|
4
12
|
readonly slug: string;
|
|
5
13
|
readonly inbox: UserInbox;
|
|
6
14
|
readonly since: number;
|
|
15
|
+
readonly stop?: () => void;
|
|
16
|
+
stopping?: boolean;
|
|
17
|
+
active?: boolean;
|
|
7
18
|
}
|
|
8
19
|
export interface DeliveryOutcome {
|
|
9
20
|
readonly ok: boolean;
|
|
@@ -12,9 +23,14 @@ export interface DeliveryOutcome {
|
|
|
12
23
|
}
|
|
13
24
|
export declare class KingdomLive {
|
|
14
25
|
private readonly vassals;
|
|
15
|
-
register(kingdomId: string, slug: string, inbox: UserInbox, now?: number): void;
|
|
26
|
+
register(kingdomId: string, slug: string, inbox: UserInbox, now?: number, options?: LiveVassalOptions): void;
|
|
16
27
|
release(kingdomId: string, slug: string): void;
|
|
17
28
|
has(kingdomId: string, slug: string): boolean;
|
|
29
|
+
reachable(kingdomId: string, slug: string): boolean;
|
|
30
|
+
contextSource(kingdomId: string, slug: string): LiveVassalOptions["contextSource"];
|
|
31
|
+
setActive(kingdomId: string, slug: string, active: boolean): void;
|
|
32
|
+
bindInbox(kingdomId: string, slug: string, inbox: UserInbox): DeliveryOutcome;
|
|
33
|
+
wake(kingdomId: string, slug: string): DeliveryOutcome;
|
|
18
34
|
/** Slug dei collaboratori che stanno lavorando adesso in questo regno. */
|
|
19
35
|
slugs(kingdomId: string): readonly string[];
|
|
20
36
|
/**
|
|
@@ -22,7 +38,19 @@ export declare class KingdomLive {
|
|
|
22
38
|
* letto: ritorna l'id, cosi' l'host puo' dire "in attesa" e poi "letto"
|
|
23
39
|
* quando arriva l'evento `user_message` di quel vassallo.
|
|
24
40
|
*/
|
|
25
|
-
deliver(kingdomId: string, slug: string, text: string, messageId?: string): DeliveryOutcome;
|
|
41
|
+
deliver(kingdomId: string, slug: string, text: string, messageId?: string, parts?: readonly ContentPart[], immediate?: boolean): DeliveryOutcome;
|
|
42
|
+
/** Accoda la compattazione reale; runTurn la esegue al prossimo confine sicuro. */
|
|
43
|
+
compact(kingdomId: string, slug: string, instructions?: string): DeliveryOutcome;
|
|
44
|
+
/** Richiede l'arresto del solo worker. Il finally del runtime rilascia il registro. */
|
|
45
|
+
stop(kingdomId: string, slug: string): DeliveryOutcome;
|
|
26
46
|
clear(kingdomId: string): void;
|
|
47
|
+
clearAll(): void;
|
|
27
48
|
}
|
|
28
49
|
export declare const kingdomLive: KingdomLive;
|
|
50
|
+
/** Casella stabile del loop, anche quando l'host collega la sua coda interattiva. */
|
|
51
|
+
export declare function createWorkerInbox(): {
|
|
52
|
+
inbox: UserInbox;
|
|
53
|
+
bind: (inbox: UserInbox) => void;
|
|
54
|
+
take: () => PendingUserMessage | undefined;
|
|
55
|
+
dispose: () => void;
|
|
56
|
+
};
|
|
@@ -8,54 +8,190 @@
|
|
|
8
8
|
// chat principale), che l'agente svuota da solo al primo confine sicuro, subito
|
|
9
9
|
// dopo gli esiti dei tool.
|
|
10
10
|
//
|
|
11
|
-
// Registro in-memory di processo, chiave `${kingdomId}::${slug}`.
|
|
12
|
-
//
|
|
13
|
-
//
|
|
11
|
+
// Registro in-memory di processo, chiave `${kingdomId}::${slug}`. Il runtime
|
|
12
|
+
// rilascia i worker effimeri al finally; gli host possono conservare sessioni
|
|
13
|
+
// idle con un vero controller di ripresa, fino a clear o abort del padre.
|
|
14
|
+
import { createUserInbox } from "../core/user-inbox.js";
|
|
14
15
|
const key = (kingdomId, slug) => `${kingdomId}::${slug}`;
|
|
15
16
|
export class KingdomLive {
|
|
16
17
|
vassals = new Map();
|
|
17
|
-
register(kingdomId, slug, inbox, now = Date.now()) {
|
|
18
|
+
register(kingdomId, slug, inbox, now = Date.now(), options = {}) {
|
|
18
19
|
const id = String(kingdomId || "").trim();
|
|
19
20
|
const who = String(slug || "").trim();
|
|
20
21
|
if (!id || !who)
|
|
21
22
|
return;
|
|
22
|
-
this.
|
|
23
|
+
this.release(id, who);
|
|
24
|
+
this.vassals.set(key(id, who), { kingdomId: id, slug: who, inbox, since: now, active: true, ...options });
|
|
23
25
|
}
|
|
24
26
|
release(kingdomId, slug) {
|
|
25
|
-
|
|
27
|
+
const id = key(String(kingdomId || "").trim(), String(slug || "").trim());
|
|
28
|
+
const live = this.vassals.get(id);
|
|
29
|
+
this.vassals.delete(id);
|
|
30
|
+
live?.close?.();
|
|
26
31
|
}
|
|
27
32
|
has(kingdomId, slug) {
|
|
33
|
+
return Boolean(this.vassals.get(key(String(kingdomId || "").trim(), String(slug || "").trim()))?.active);
|
|
34
|
+
}
|
|
35
|
+
reachable(kingdomId, slug) {
|
|
28
36
|
return this.vassals.has(key(String(kingdomId || "").trim(), String(slug || "").trim()));
|
|
29
37
|
}
|
|
38
|
+
contextSource(kingdomId, slug) {
|
|
39
|
+
return this.vassals.get(key(kingdomId, slug))?.contextSource;
|
|
40
|
+
}
|
|
41
|
+
setActive(kingdomId, slug, active) {
|
|
42
|
+
const live = this.vassals.get(key(String(kingdomId || "").trim(), String(slug || "").trim()));
|
|
43
|
+
if (live) {
|
|
44
|
+
live.active = active;
|
|
45
|
+
live.stopping = false;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
bindInbox(kingdomId, slug, inbox) {
|
|
49
|
+
const live = this.vassals.get(key(String(kingdomId || "").trim(), String(slug || "").trim()));
|
|
50
|
+
if (!live)
|
|
51
|
+
return { ok: false, error: "collaboratore non piu' attivo" };
|
|
52
|
+
if (!live.bindInbox)
|
|
53
|
+
return { ok: false, error: "coda esterna non disponibile" };
|
|
54
|
+
try {
|
|
55
|
+
live.bindInbox(inbox);
|
|
56
|
+
return { ok: true };
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
return { ok: false, error: err.message };
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
wake(kingdomId, slug) {
|
|
63
|
+
const live = this.vassals.get(key(String(kingdomId || "").trim(), String(slug || "").trim()));
|
|
64
|
+
if (!live || live.stopping)
|
|
65
|
+
return { ok: false, error: "collaboratore non piu' attivo" };
|
|
66
|
+
try {
|
|
67
|
+
live.wake?.();
|
|
68
|
+
return { ok: true };
|
|
69
|
+
}
|
|
70
|
+
catch (err) {
|
|
71
|
+
return { ok: false, error: err.message };
|
|
72
|
+
}
|
|
73
|
+
}
|
|
30
74
|
/** Slug dei collaboratori che stanno lavorando adesso in questo regno. */
|
|
31
75
|
slugs(kingdomId) {
|
|
32
76
|
const id = String(kingdomId || "").trim();
|
|
33
|
-
return [...this.vassals.values()].filter((v) => v.kingdomId === id).map((v) => v.slug);
|
|
77
|
+
return [...this.vassals.values()].filter((v) => v.kingdomId === id && v.active).map((v) => v.slug);
|
|
34
78
|
}
|
|
35
79
|
/**
|
|
36
80
|
* Consegna un messaggio dell'utente a un collaboratore. Non attende che sia
|
|
37
81
|
* letto: ritorna l'id, cosi' l'host puo' dire "in attesa" e poi "letto"
|
|
38
82
|
* quando arriva l'evento `user_message` di quel vassallo.
|
|
39
83
|
*/
|
|
40
|
-
deliver(kingdomId, slug, text, messageId) {
|
|
84
|
+
deliver(kingdomId, slug, text, messageId, parts, immediate = false) {
|
|
41
85
|
const body = String(text ?? "").trim();
|
|
42
|
-
|
|
86
|
+
const content = parts ?? body;
|
|
87
|
+
if (typeof content === "string" ? !content : !content.some((part) => part.type !== "text" || part.text.trim())) {
|
|
43
88
|
return { ok: false, error: "messaggio vuoto" };
|
|
89
|
+
}
|
|
44
90
|
const live = this.vassals.get(key(String(kingdomId || "").trim(), String(slug || "").trim()));
|
|
45
|
-
if (!live)
|
|
91
|
+
if (!live || live.stopping)
|
|
92
|
+
return { ok: false, error: "collaboratore non piu' attivo" };
|
|
93
|
+
try {
|
|
94
|
+
const id = live.inbox.push(content, messageId);
|
|
95
|
+
if (immediate)
|
|
96
|
+
live.inbox.promote(id);
|
|
97
|
+
live.wake?.();
|
|
98
|
+
return { ok: true, messageId: id };
|
|
99
|
+
}
|
|
100
|
+
catch (err) {
|
|
101
|
+
return { ok: false, error: err.message };
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/** Accoda la compattazione reale; runTurn la esegue al prossimo confine sicuro. */
|
|
105
|
+
compact(kingdomId, slug, instructions) {
|
|
106
|
+
const live = this.vassals.get(key(String(kingdomId || "").trim(), String(slug || "").trim()));
|
|
107
|
+
if (!live || live.stopping)
|
|
46
108
|
return { ok: false, error: "collaboratore non piu' attivo" };
|
|
109
|
+
if (!live.inbox.requestCompact)
|
|
110
|
+
return { ok: false, error: "compattazione non disponibile per questo collaboratore" };
|
|
47
111
|
try {
|
|
48
|
-
|
|
112
|
+
live.inbox.requestCompact(instructions);
|
|
113
|
+
live.wake?.();
|
|
114
|
+
return { ok: true };
|
|
49
115
|
}
|
|
50
116
|
catch (err) {
|
|
51
117
|
return { ok: false, error: err.message };
|
|
52
118
|
}
|
|
53
119
|
}
|
|
120
|
+
/** Richiede l'arresto del solo worker. Il finally del runtime rilascia il registro. */
|
|
121
|
+
stop(kingdomId, slug) {
|
|
122
|
+
const live = this.vassals.get(key(String(kingdomId || "").trim(), String(slug || "").trim()));
|
|
123
|
+
if (!live || live.stopping)
|
|
124
|
+
return { ok: false, error: "collaboratore non piu' attivo" };
|
|
125
|
+
if (!live.active)
|
|
126
|
+
return { ok: false, error: "collaboratore gia' inattivo" };
|
|
127
|
+
if (!live.stop)
|
|
128
|
+
return { ok: false, error: "arresto non disponibile per questo collaboratore" };
|
|
129
|
+
live.stopping = true;
|
|
130
|
+
try {
|
|
131
|
+
live.stop();
|
|
132
|
+
return { ok: true };
|
|
133
|
+
}
|
|
134
|
+
catch (err) {
|
|
135
|
+
live.stopping = false;
|
|
136
|
+
return { ok: false, error: err.message };
|
|
137
|
+
}
|
|
138
|
+
}
|
|
54
139
|
clear(kingdomId) {
|
|
55
140
|
const id = String(kingdomId || "").trim();
|
|
56
|
-
for (const
|
|
141
|
+
for (const v of [...this.vassals.values()])
|
|
57
142
|
if (v.kingdomId === id)
|
|
58
|
-
this.
|
|
143
|
+
this.release(v.kingdomId, v.slug);
|
|
144
|
+
}
|
|
145
|
+
clearAll() {
|
|
146
|
+
for (const v of [...this.vassals.values()])
|
|
147
|
+
this.release(v.kingdomId, v.slug);
|
|
59
148
|
}
|
|
60
149
|
}
|
|
61
150
|
export const kingdomLive = new KingdomLive();
|
|
151
|
+
/** Casella stabile del loop, anche quando l'host collega la sua coda interattiva. */
|
|
152
|
+
export function createWorkerInbox() {
|
|
153
|
+
let taken = [];
|
|
154
|
+
let current = createUserInbox();
|
|
155
|
+
const controls = createUserInbox();
|
|
156
|
+
const subscriptions = new Map();
|
|
157
|
+
const inbox = {
|
|
158
|
+
push: (input, id) => current.push(input, id),
|
|
159
|
+
promote: id => current.promote(id),
|
|
160
|
+
get pending() { return taken.length + current.pending; },
|
|
161
|
+
get queued() { return taken.length + (current.queued ?? current.pending); },
|
|
162
|
+
drain: () => { const pending = [...taken, ...current.drain()]; taken = []; return pending; },
|
|
163
|
+
onImmediate(listener) {
|
|
164
|
+
subscriptions.set(listener, current.onImmediate?.(listener) ?? (() => { }));
|
|
165
|
+
return () => { subscriptions.get(listener)?.(); subscriptions.delete(listener); };
|
|
166
|
+
},
|
|
167
|
+
requestCompact: instructions => controls.requestCompact(instructions),
|
|
168
|
+
drainCompactions: () => controls.drainCompactions(),
|
|
169
|
+
get pendingCompactions() { return controls.pendingCompactions; },
|
|
170
|
+
};
|
|
171
|
+
return { inbox,
|
|
172
|
+
take() { taken.push(...current.drain()); return taken.shift(); },
|
|
173
|
+
bind(next) {
|
|
174
|
+
if (next === current || next === inbox)
|
|
175
|
+
return;
|
|
176
|
+
const pending = current.drain();
|
|
177
|
+
for (const off of subscriptions.values())
|
|
178
|
+
off();
|
|
179
|
+
current = next;
|
|
180
|
+
for (const message of pending) {
|
|
181
|
+
current.push(message.parts, message.id);
|
|
182
|
+
if (message.immediate)
|
|
183
|
+
current.promote(message.id);
|
|
184
|
+
}
|
|
185
|
+
for (const listener of subscriptions.keys())
|
|
186
|
+
subscriptions.set(listener, current.onImmediate?.(listener) ?? (() => { }));
|
|
187
|
+
},
|
|
188
|
+
dispose() {
|
|
189
|
+
for (const off of subscriptions.values())
|
|
190
|
+
off();
|
|
191
|
+
subscriptions.clear();
|
|
192
|
+
taken = [];
|
|
193
|
+
current = createUserInbox();
|
|
194
|
+
controls.drainCompactions?.();
|
|
195
|
+
},
|
|
196
|
+
};
|
|
197
|
+
}
|
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
import type { EventSink, ToolContext } from "../core/types.js";
|
|
1
|
+
import type { AgentEvent, EventSink, ToolContext } from "../core/types.js";
|
|
2
2
|
import type { Harness } from "../core/bootstrap.js";
|
|
3
3
|
import { type CastleSpec, type VassalReport } from "./kingdom.js";
|
|
4
4
|
import type { FileCoordinationContext } from "../core/file-coordination.js";
|
|
5
5
|
export interface KingdomRunInput {
|
|
6
|
+
readonly kingdomId?: string;
|
|
7
|
+
readonly resumeSessions?: Readonly<Record<string, string>>;
|
|
8
|
+
readonly retainSessions?: boolean | "queued";
|
|
9
|
+
readonly onWorkerEvent?: (slug: string, event: AgentEvent) => void;
|
|
6
10
|
readonly harness: Harness;
|
|
7
11
|
readonly castles: readonly CastleSpec[];
|
|
8
12
|
readonly signal: AbortSignal;
|
|
@@ -35,7 +35,7 @@ export async function runKingdomForHost(input) {
|
|
|
35
35
|
// La sessione dura quanto la conversazione, uno swarm no. Un id riusato
|
|
36
36
|
// faceva fondere nella UI il regno concluso con quello successivo.
|
|
37
37
|
kingdomRunSequence = (kingdomRunSequence + 1) % 0xfffff;
|
|
38
|
-
const kingdomId = `kw-${harness.session.id}-${Date.now().toString(36)}-${kingdomRunSequence.toString(36)}`;
|
|
38
|
+
const kingdomId = input.kingdomId ?? `kw-${harness.session.id}-${Date.now().toString(36)}-${kingdomRunSequence.toString(36)}`;
|
|
39
39
|
const concurrency = warmConcurrency(env);
|
|
40
40
|
const worktree = worktreeMode(env);
|
|
41
41
|
// Bus pulito per il nuovo regno (in memoria e sul canale persistente).
|
|
@@ -89,6 +89,7 @@ export async function runKingdomForHost(input) {
|
|
|
89
89
|
sink({ type: "kingdom", phase: "say", slug, text: buffered.slice(0, SAY_MAX), at: Date.now() });
|
|
90
90
|
};
|
|
91
91
|
const onEvent = (slug, event) => {
|
|
92
|
+
input.onWorkerEvent?.(slug, event);
|
|
92
93
|
if (event.type === "usage") {
|
|
93
94
|
sink({ ...event, record: { ...event.record, actor: event.record.actor ?? slug } });
|
|
94
95
|
return;
|
|
@@ -312,6 +313,8 @@ export async function runKingdomForHost(input) {
|
|
|
312
313
|
signal,
|
|
313
314
|
confirm,
|
|
314
315
|
ask: input.ask,
|
|
316
|
+
retainSessions: input.retainSessions,
|
|
317
|
+
resumeSessions: input.resumeSessions,
|
|
315
318
|
concurrency,
|
|
316
319
|
onEvent,
|
|
317
320
|
onMemberState: (slug, status, report) => {
|
|
@@ -364,7 +367,8 @@ export async function runKingdomForHost(input) {
|
|
|
364
367
|
// Ultime parole rimaste nel buffer di chi ha finito senza un confine di turno.
|
|
365
368
|
for (const slug of [...saying.keys()])
|
|
366
369
|
flushSay(slug);
|
|
367
|
-
|
|
370
|
+
if (!input.retainSessions)
|
|
371
|
+
kingdomLive.clear(kingdomId);
|
|
368
372
|
for (const report of reports) {
|
|
369
373
|
updateTeamMember(kingdomId, report.slug, { status: report.ok ? "completed" : "failed", summary: report.summary, error: report.error, artifacts: report.artifacts });
|
|
370
374
|
sink({
|
|
@@ -45,6 +45,9 @@ export interface ConflictEntry {
|
|
|
45
45
|
export declare function collectConflicts(reports: readonly VassalReport[]): ConflictEntry[];
|
|
46
46
|
export declare function formatConflictList(conflicts: readonly ConflictEntry[], base?: string): string;
|
|
47
47
|
export interface KingdomWarmOptions {
|
|
48
|
+
/** Explicit persisted worker sessions for hosts that resume a named worker. */
|
|
49
|
+
readonly resumeSessions?: Readonly<Record<string, string>>;
|
|
50
|
+
readonly retainSessions?: boolean | "queued";
|
|
48
51
|
readonly harness: Harness;
|
|
49
52
|
readonly kingdomId: string;
|
|
50
53
|
readonly castles: readonly CastleSpec[];
|
package/dist/vascend/kingdom.js
CHANGED
|
@@ -4,8 +4,8 @@ import { existsSync } from "node:fs";
|
|
|
4
4
|
import { resolve, sep } from "node:path";
|
|
5
5
|
import { runTurn } from "../core/agent.js";
|
|
6
6
|
import { Session } from "../core/session.js";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
7
|
+
import { createWorkerInbox } from "./kingdom-live.js";
|
|
8
|
+
import { createWorkerSession } from "./worker-session.js";
|
|
9
9
|
import { fileActor, withFileActor } from "../core/file-coordination.js";
|
|
10
10
|
import { RoomMemory } from "./room-memory.js";
|
|
11
11
|
import { VascendPlanStore } from "./plan-store.js";
|
|
@@ -661,6 +661,7 @@ function subTeamSpawner(opts, castle, mandate, iso, planStoreId) {
|
|
|
661
661
|
const report = await launchGranularKingdom({
|
|
662
662
|
harness: opts.harness,
|
|
663
663
|
kingdomId: opts.kingdomId,
|
|
664
|
+
retainSessions: opts.retainSessions,
|
|
664
665
|
castleSlug: castle.slug,
|
|
665
666
|
units,
|
|
666
667
|
signal: opts.signal,
|
|
@@ -691,10 +692,14 @@ function subTeamSpawner(opts, castle, mandate, iso, planStoreId) {
|
|
|
691
692
|
};
|
|
692
693
|
}
|
|
693
694
|
async function runVassal(opts, provider, modelId, displayModel, castle, peers, iso, prerequisites = []) {
|
|
694
|
-
const { harness, kingdomId, signal, confirm, onEvent } = opts;
|
|
695
|
+
const { harness, kingdomId, signal: parentSignal, confirm, onEvent } = opts;
|
|
696
|
+
let controller = new AbortController();
|
|
697
|
+
const signal = controller.signal;
|
|
695
698
|
// Sessione (conversazione) dedicata al vassallo; store memoria CONDIVISO del
|
|
696
699
|
// regno (kingdomId) con id stanze namespaced sullo slug del castello.
|
|
697
|
-
const
|
|
700
|
+
const resumeId = opts.resumeSessions?.[castle.slug];
|
|
701
|
+
const session = resumeId ? Session.load(harness.config.sessionDir, resumeId)
|
|
702
|
+
: Session.create(harness.config.sessionDir, `${kingdomId}-${castle.slug}`);
|
|
698
703
|
const effort = ["low", "medium", "high", "max"].includes(String(castle.effort ?? "").toLowerCase())
|
|
699
704
|
? String(castle.effort).toLowerCase()
|
|
700
705
|
: "";
|
|
@@ -719,8 +724,8 @@ async function runVassal(opts, provider, modelId, displayModel, castle, peers, i
|
|
|
719
724
|
// Casella del vassallo: l'utente puo' scrivergli mentre lavora dalla sua
|
|
720
725
|
// scheda, e il messaggio entra nel contesto al primo confine sicuro come in
|
|
721
726
|
// chat principale. Senza, l'unico modo di correggerlo era fermare il regno.
|
|
722
|
-
const
|
|
723
|
-
|
|
727
|
+
const binding = createWorkerInbox();
|
|
728
|
+
const inbox = binding.inbox;
|
|
724
729
|
const workerTools = harness.tools.scoped(castle.tools);
|
|
725
730
|
for (const name of ["team_say", "team_inbox", "team_wait", "team_report", "vascend_status"])
|
|
726
731
|
workerTools.promote(name);
|
|
@@ -729,6 +734,9 @@ async function runVassal(opts, provider, modelId, displayModel, castle, peers, i
|
|
|
729
734
|
tools: workerTools,
|
|
730
735
|
session,
|
|
731
736
|
config: runConfig,
|
|
737
|
+
env: harness.env,
|
|
738
|
+
fsRoots: harness.fsRoots,
|
|
739
|
+
executionTarget: harness.executionTarget,
|
|
732
740
|
confirm,
|
|
733
741
|
ask: opts.ask,
|
|
734
742
|
host: undefined,
|
|
@@ -739,7 +747,8 @@ async function runVassal(opts, provider, modelId, displayModel, castle, peers, i
|
|
|
739
747
|
// Delega di secondo livello: un castello grande si gestisce formando un team
|
|
740
748
|
// sulle proprie stanze. Prima questo campo mancava, e kingdoms_warm dentro
|
|
741
749
|
// un vassallo rispondeva "non disponibile": la gerarchia era ferma a 1.
|
|
742
|
-
spawnKingdom: subTeamSpawner({ ...opts,
|
|
750
|
+
spawnKingdom: (specs) => subTeamSpawner({ ...opts, signal: controller.signal,
|
|
751
|
+
harness: { ...harness, config: runConfig, tools: workerTools } }, castle, mandate, iso, planStoreId)(specs),
|
|
743
752
|
// isolated abilita il git nel vassallo (worktree proprio); altrimenti il
|
|
744
753
|
// bash tool blocca il git che muta (working dir condivisa).
|
|
745
754
|
kingdom: { id: kingdomId, self: castle.slug, isolated: iso.isolated, peers },
|
|
@@ -772,6 +781,9 @@ async function runVassal(opts, provider, modelId, displayModel, castle, peers, i
|
|
|
772
781
|
completed = true;
|
|
773
782
|
onEvent?.(castle.slug, event);
|
|
774
783
|
};
|
|
784
|
+
const worker = createWorkerSession({ kingdomId, slug: castle.slug, sessionId: session.id, goal: castle.goal,
|
|
785
|
+
parentSignal, controller, binding, deps, sink, retain: !iso.isolated ? opts.retainSessions ?? false : false,
|
|
786
|
+
onController: next => { controller = next; } });
|
|
775
787
|
try {
|
|
776
788
|
const role = castle.role?.trim() || "collaboratore";
|
|
777
789
|
sink({ type: "kingdom", phase: "session", kingdomId, sessionId: session.id,
|
|
@@ -827,12 +839,7 @@ async function runVassal(opts, provider, modelId, displayModel, castle, peers, i
|
|
|
827
839
|
};
|
|
828
840
|
}
|
|
829
841
|
finally {
|
|
830
|
-
|
|
831
|
-
// Il collaboratore non c'e' piu': la UI deve saperlo subito, altrimenti
|
|
832
|
-
// continuerebbe a offrire un campo di scrittura che non consegna nulla.
|
|
833
|
-
kingdomLive.release(kingdomId, castle.slug);
|
|
834
|
-
sink({ type: "kingdom", phase: "session", kingdomId, sessionId: session.id,
|
|
835
|
-
slug: castle.slug, state: "despawned", at: Date.now() });
|
|
842
|
+
worker.finish();
|
|
836
843
|
}
|
|
837
844
|
}
|
|
838
845
|
function mandateCompletion(sessionDir, planStoreId, mandate) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ContextStoreReader } from "./context-store-reader.js";
|
|
1
2
|
export interface MemoryPacketInput {
|
|
2
3
|
readonly sessionDir: string;
|
|
3
4
|
readonly scopeId: string;
|
|
@@ -9,5 +10,5 @@ export interface MemoryPacketInput {
|
|
|
9
10
|
/** Preselected dependencies supplied by a coherent snapshot. */
|
|
10
11
|
readonly projectScopes?: readonly string[];
|
|
11
12
|
}
|
|
12
|
-
export declare function buildMemoryPacket(input: MemoryPacketInput): string;
|
|
13
|
+
export declare function buildMemoryPacket(input: MemoryPacketInput, reader?: ContextStoreReader): string;
|
|
13
14
|
export declare function clampMemoryPacket(value: string, max: number): string;
|