zooid 0.10.0 → 0.11.1
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/bin.js +1 -1
- package/dist/{chunk-LIMRV7C4.js → chunk-KGYQ5YNP.js} +93 -15
- package/dist/chunk-KGYQ5YNP.js.map +1 -0
- package/dist/index.js +1 -1
- package/package.json +9 -9
- package/src/build-registry.context.test.ts +51 -0
- package/src/build-registry.ts +20 -2
- package/dist/chunk-LIMRV7C4.js.map +0 -1
package/dist/bin.js
CHANGED
|
@@ -24326,7 +24326,7 @@ var AcpClient = class {
|
|
|
24326
24326
|
this.connection = null;
|
|
24327
24327
|
this.initialized = false;
|
|
24328
24328
|
}
|
|
24329
|
-
async ensureSession(threadId, channelId) {
|
|
24329
|
+
async ensureSession(threadId, channelId, contextThreadId) {
|
|
24330
24330
|
if (!this.connection || !this.initialized) {
|
|
24331
24331
|
throw new Error("AcpClient.start() must be called before ensureSession()");
|
|
24332
24332
|
}
|
|
@@ -24334,7 +24334,7 @@ var AcpClient = class {
|
|
|
24334
24334
|
const key = { threadId, agentId: this.options.agent.id };
|
|
24335
24335
|
const cached3 = this.sessions.get(key);
|
|
24336
24336
|
if (cached3) return cached3.sessionId;
|
|
24337
|
-
const mcpServers = this.options.contextSpawn ? [await this.options.contextSpawn(threadId, channelId)] : [];
|
|
24337
|
+
const mcpServers = this.options.contextSpawn ? [await this.options.contextSpawn(contextThreadId ?? threadId, channelId)] : [];
|
|
24338
24338
|
process.stderr.write(
|
|
24339
24339
|
`[acp-client:${this.options.agent.id}] ensureSession(${threadId}) mcpServers=${mcpServers.length === 0 ? "[]" : JSON.stringify(mcpServers.map((s) => ({ name: s.name, command: s.command, args: s.args })))}
|
|
24340
24340
|
`
|
|
@@ -24408,7 +24408,11 @@ var AcpClient = class {
|
|
|
24408
24408
|
let sessionId = null;
|
|
24409
24409
|
let turnId = null;
|
|
24410
24410
|
try {
|
|
24411
|
-
sessionId = await this.ensureSession(
|
|
24411
|
+
sessionId = await this.ensureSession(
|
|
24412
|
+
input.threadId,
|
|
24413
|
+
input.channelId,
|
|
24414
|
+
input.contextThreadId
|
|
24415
|
+
);
|
|
24412
24416
|
const promptText = stringifyPromptForLog(input.content);
|
|
24413
24417
|
turnId = this.turns?.startTurn({ sessionId, promptText }) ?? null;
|
|
24414
24418
|
debugLog(this.options.agent.id, "prompt \u2192", { sessionId, content: input.content });
|
|
@@ -25410,10 +25414,10 @@ var AcpAgentRegistry = class {
|
|
|
25410
25414
|
getApprovalTimeoutMs(name) {
|
|
25411
25415
|
return this.opts.agents[name]?.approval_timeout_ms ?? 0;
|
|
25412
25416
|
}
|
|
25413
|
-
async ensureSession(name, threadId, channelId) {
|
|
25417
|
+
async ensureSession(name, threadId, channelId, contextThreadId) {
|
|
25414
25418
|
if (!this.hasAgent(name)) throw new Error(`unknown agent: ${name}`);
|
|
25415
25419
|
const client = await this.ensureClient(name);
|
|
25416
|
-
return client.ensureSession(threadId, channelId);
|
|
25420
|
+
return client.ensureSession(threadId, channelId, contextThreadId);
|
|
25417
25421
|
}
|
|
25418
25422
|
endSession(name, threadId) {
|
|
25419
25423
|
if (!this.hasAgent(name)) return;
|
|
@@ -26301,6 +26305,16 @@ function buildUserPowerLevels(asUserId, admins, agents, roomAlias) {
|
|
|
26301
26305
|
import { Hono } from "hono";
|
|
26302
26306
|
import { timingSafeEqual } from "crypto";
|
|
26303
26307
|
|
|
26308
|
+
// ../transport-matrix/src/session-keys.ts
|
|
26309
|
+
var HANDOFF_KEY_SEP = "|";
|
|
26310
|
+
function composeHandoffKey(threadRoot, callEventId) {
|
|
26311
|
+
return `${threadRoot}${HANDOFF_KEY_SEP}${callEventId}`;
|
|
26312
|
+
}
|
|
26313
|
+
function sessionKeyFor(agentName, threadRoot, state) {
|
|
26314
|
+
const arc = state?.handoffs[agentName]?.at(-1);
|
|
26315
|
+
return arc ? composeHandoffKey(threadRoot, arc) : threadRoot;
|
|
26316
|
+
}
|
|
26317
|
+
|
|
26304
26318
|
// ../transport-matrix/src/event-encoders.ts
|
|
26305
26319
|
var RAW_INPUT_STR_MAX = 250;
|
|
26306
26320
|
function toToolCallBody(evt) {
|
|
@@ -26865,8 +26879,22 @@ function createMatrixTransport(opts) {
|
|
|
26865
26879
|
return;
|
|
26866
26880
|
}
|
|
26867
26881
|
console.log(`[matrix] inbound dev.zooid.session_reset in ${evt.room_id} thread=${threadRoot}`);
|
|
26882
|
+
if (!threadStates.has(threadRoot) && evt.room_id) {
|
|
26883
|
+
try {
|
|
26884
|
+
threadStates.set(
|
|
26885
|
+
threadRoot,
|
|
26886
|
+
await rebuildThreadState(client, evt.room_id, threadRoot, bindings)
|
|
26887
|
+
);
|
|
26888
|
+
} catch (err) {
|
|
26889
|
+
console.warn(`[matrix] failed to rebuild threadState for reset ${threadRoot}:`, err);
|
|
26890
|
+
}
|
|
26891
|
+
}
|
|
26892
|
+
const st = threadStates.get(threadRoot);
|
|
26868
26893
|
for (const a of bindings) {
|
|
26869
26894
|
agents.endSession(a.name, threadRoot);
|
|
26895
|
+
for (const arc of st?.handoffs[a.name] ?? []) {
|
|
26896
|
+
agents.endSession(a.name, composeHandoffKey(threadRoot, arc));
|
|
26897
|
+
}
|
|
26870
26898
|
}
|
|
26871
26899
|
return;
|
|
26872
26900
|
}
|
|
@@ -26955,7 +26983,7 @@ function createMatrixTransport(opts) {
|
|
|
26955
26983
|
if (matches.length > 0 && promotedRoot) {
|
|
26956
26984
|
let st = threadStates.get(promotedRoot);
|
|
26957
26985
|
if (!st) {
|
|
26958
|
-
st = { participants: [], rootMentions: [], callers: {} };
|
|
26986
|
+
st = { participants: [], rootMentions: [], callers: {}, handoffs: {} };
|
|
26959
26987
|
threadStates.set(promotedRoot, st);
|
|
26960
26988
|
}
|
|
26961
26989
|
const msgMentions = new Set(extractMentions(evt));
|
|
@@ -26963,7 +26991,13 @@ function createMatrixTransport(opts) {
|
|
|
26963
26991
|
for (const a of bindings) {
|
|
26964
26992
|
if (!msgMentions.has(a.userId)) continue;
|
|
26965
26993
|
if (!st.rootMentions.includes(a.name)) st.rootMentions.push(a.name);
|
|
26966
|
-
if (senderAgent && a.name !== senderAgent.name)
|
|
26994
|
+
if (senderAgent && a.name !== senderAgent.name) {
|
|
26995
|
+
st.callers[a.name] = senderAgent.name;
|
|
26996
|
+
if (evt.event_id) {
|
|
26997
|
+
const arcs = st.handoffs[a.name] ??= [];
|
|
26998
|
+
if (!arcs.includes(evt.event_id)) arcs.push(evt.event_id);
|
|
26999
|
+
}
|
|
27000
|
+
}
|
|
26967
27001
|
}
|
|
26968
27002
|
}
|
|
26969
27003
|
for (const a of matches) {
|
|
@@ -26972,7 +27006,7 @@ function createMatrixTransport(opts) {
|
|
|
26972
27006
|
if (!promotedRoot) return;
|
|
26973
27007
|
let st = threadStates.get(promotedRoot);
|
|
26974
27008
|
if (!st) {
|
|
26975
|
-
st = { participants: [], rootMentions: [], callers: {} };
|
|
27009
|
+
st = { participants: [], rootMentions: [], callers: {}, handoffs: {} };
|
|
26976
27010
|
threadStates.set(promotedRoot, st);
|
|
26977
27011
|
}
|
|
26978
27012
|
if (st.participants.at(-1) !== a.name) st.participants.push(a.name);
|
|
@@ -27045,8 +27079,8 @@ function createMatrixTransport(opts) {
|
|
|
27045
27079
|
if (!evt.room_id || !evt.event_id) return;
|
|
27046
27080
|
const inbound = inboundThreadRoot2(evt);
|
|
27047
27081
|
const threadRoot = inbound ?? evt.event_id;
|
|
27048
|
-
const sessionKey = threadRoot;
|
|
27049
|
-
const sessionId = await agents.ensureSession(agent.name, sessionKey, evt.room_id);
|
|
27082
|
+
const sessionKey = sessionKeyFor(agent.name, threadRoot, threadStates.get(threadRoot));
|
|
27083
|
+
const sessionId = await agents.ensureSession(agent.name, sessionKey, evt.room_id, threadRoot);
|
|
27050
27084
|
sessions.set(sessionId, { agent, roomId: evt.room_id, threadRoot });
|
|
27051
27085
|
buffers.set(sessionId, "");
|
|
27052
27086
|
bufferMessageIds.delete(sessionId);
|
|
@@ -27094,6 +27128,7 @@ function createMatrixTransport(opts) {
|
|
|
27094
27128
|
await agents.prompt(agent.name, {
|
|
27095
27129
|
threadId: sessionKey,
|
|
27096
27130
|
channelId: evt.room_id,
|
|
27131
|
+
contextThreadId: threadRoot,
|
|
27097
27132
|
content: [...blocks, { type: "text", text: fullPromptText }]
|
|
27098
27133
|
});
|
|
27099
27134
|
const drainStart = Date.now();
|
|
@@ -27148,7 +27183,7 @@ function createMatrixTransport(opts) {
|
|
|
27148
27183
|
};
|
|
27149
27184
|
}
|
|
27150
27185
|
async function rebuildThreadState(client, roomId, rootEventId, bindings) {
|
|
27151
|
-
const state = { participants: [], rootMentions: [], callers: {} };
|
|
27186
|
+
const state = { participants: [], rootMentions: [], callers: {}, handoffs: {} };
|
|
27152
27187
|
const asUser = (bindings.find((b) => b.rooms.some((r) => r.alias === roomId)) ?? bindings[0])?.userId;
|
|
27153
27188
|
if (!asUser) return state;
|
|
27154
27189
|
const root = await client.fetchEvent(roomId, rootEventId, asUser);
|
|
@@ -27159,7 +27194,11 @@ async function rebuildThreadState(client, roomId, rootEventId, bindings) {
|
|
|
27159
27194
|
for (const a of bindings) {
|
|
27160
27195
|
if (!rootMentions.has(a.userId)) continue;
|
|
27161
27196
|
if (!state.rootMentions.includes(a.name)) state.rootMentions.push(a.name);
|
|
27162
|
-
if (rootSenderAgent && a.name !== rootSenderAgent.name)
|
|
27197
|
+
if (rootSenderAgent && a.name !== rootSenderAgent.name) {
|
|
27198
|
+
state.callers[a.name] = rootSenderAgent.name;
|
|
27199
|
+
const arcs = state.handoffs[a.name] ??= [];
|
|
27200
|
+
if (!arcs.includes(rootEventId)) arcs.push(rootEventId);
|
|
27201
|
+
}
|
|
27163
27202
|
}
|
|
27164
27203
|
}
|
|
27165
27204
|
const { chunk: thread } = await client.fetchThreadRelations({
|
|
@@ -27171,10 +27210,17 @@ async function rebuildThreadState(client, roomId, rootEventId, bindings) {
|
|
|
27171
27210
|
const mentions = new Set(extractMentions(ev));
|
|
27172
27211
|
const evSender = ev.sender;
|
|
27173
27212
|
const evSenderAgent = evSender ? bindings.find((b) => b.userId === evSender) : void 0;
|
|
27213
|
+
const evId = ev.event_id;
|
|
27174
27214
|
for (const a of bindings) {
|
|
27175
27215
|
if (!mentions.has(a.userId)) continue;
|
|
27176
27216
|
if (!state.rootMentions.includes(a.name)) state.rootMentions.push(a.name);
|
|
27177
|
-
if (evSenderAgent && a.name !== evSenderAgent.name)
|
|
27217
|
+
if (evSenderAgent && a.name !== evSenderAgent.name) {
|
|
27218
|
+
state.callers[a.name] = evSenderAgent.name;
|
|
27219
|
+
if (evId) {
|
|
27220
|
+
const arcs = state.handoffs[a.name] ??= [];
|
|
27221
|
+
if (!arcs.includes(evId)) arcs.push(evId);
|
|
27222
|
+
}
|
|
27223
|
+
}
|
|
27178
27224
|
}
|
|
27179
27225
|
const type = ev.type;
|
|
27180
27226
|
if (type === "m.room.message" && evSender) {
|
|
@@ -32571,6 +32617,7 @@ var McpZodTypeKind;
|
|
|
32571
32617
|
|
|
32572
32618
|
// ../context-mcp/src/factory.ts
|
|
32573
32619
|
import { createRequire } from "module";
|
|
32620
|
+
import { dirname } from "path";
|
|
32574
32621
|
function resolveDefaultBin() {
|
|
32575
32622
|
const req = createRequire(import.meta.url);
|
|
32576
32623
|
return req.resolve("@zooid/context-mcp/bin");
|
|
@@ -32580,7 +32627,25 @@ function getDefaultBin() {
|
|
|
32580
32627
|
if (!cachedDefaultBin) cachedDefaultBin = resolveDefaultBin();
|
|
32581
32628
|
return cachedDefaultBin;
|
|
32582
32629
|
}
|
|
32630
|
+
var CONTEXT_CONTAINER_BIN_DIR = "/zooid/context-mcp";
|
|
32631
|
+
var CONTEXT_CONTAINER_BIN = `${CONTEXT_CONTAINER_BIN_DIR}/bin.js`;
|
|
32632
|
+
var CONTEXT_CONTAINER_SOCK = "/zooid/context.sock";
|
|
32633
|
+
function contextContainerMounts(opts) {
|
|
32634
|
+
const binFile = opts.binPath ?? getDefaultBin();
|
|
32635
|
+
return [
|
|
32636
|
+
{ path: dirname(binFile), target: CONTEXT_CONTAINER_BIN_DIR, mode: "ro" },
|
|
32637
|
+
{ path: opts.sockPath, target: CONTEXT_CONTAINER_SOCK, mode: "rw" }
|
|
32638
|
+
];
|
|
32639
|
+
}
|
|
32583
32640
|
function buildContextServerSpec(opts) {
|
|
32641
|
+
if (opts.containerize) {
|
|
32642
|
+
return {
|
|
32643
|
+
name: "zooid-context",
|
|
32644
|
+
command: "node",
|
|
32645
|
+
args: [CONTEXT_CONTAINER_BIN, "--spawn-id", opts.spawnId],
|
|
32646
|
+
env: [{ name: "ZOOID_DAEMON_SOCK", value: CONTEXT_CONTAINER_SOCK }]
|
|
32647
|
+
};
|
|
32648
|
+
}
|
|
32584
32649
|
return {
|
|
32585
32650
|
name: "zooid-context",
|
|
32586
32651
|
command: process.execPath,
|
|
@@ -32730,6 +32795,15 @@ Set agents.<name>.container.image, top-level container.image, or use a preset th
|
|
|
32730
32795
|
}
|
|
32731
32796
|
}
|
|
32732
32797
|
const contextSpawns = buildContextSpawns(cfg, opts);
|
|
32798
|
+
if (cfg.runtime !== "local" && opts.daemonSockPath && contextSpawns) {
|
|
32799
|
+
for (const name of Object.keys(cfg.agents)) {
|
|
32800
|
+
if (!contextSpawns[name]) continue;
|
|
32801
|
+
mountsByAgent[name] = [
|
|
32802
|
+
...mountsByAgent[name] ?? [],
|
|
32803
|
+
...contextContainerMounts({ sockPath: opts.daemonSockPath })
|
|
32804
|
+
];
|
|
32805
|
+
}
|
|
32806
|
+
}
|
|
32733
32807
|
return new AcpAgentRegistry({
|
|
32734
32808
|
runtime,
|
|
32735
32809
|
agents: cfg.agents,
|
|
@@ -32775,7 +32849,11 @@ function buildContextSpawns(cfg, opts) {
|
|
|
32775
32849
|
threadRef: { channelId: channelId ?? threadId, threadId },
|
|
32776
32850
|
provider
|
|
32777
32851
|
});
|
|
32778
|
-
return buildContextServerSpec({
|
|
32852
|
+
return buildContextServerSpec({
|
|
32853
|
+
spawnId,
|
|
32854
|
+
sockPath,
|
|
32855
|
+
containerize: cfg.runtime !== "local"
|
|
32856
|
+
});
|
|
32779
32857
|
};
|
|
32780
32858
|
} else {
|
|
32781
32859
|
result[name] = void 0;
|
|
@@ -32812,4 +32890,4 @@ export {
|
|
|
32812
32890
|
startDaemonSocketServer,
|
|
32813
32891
|
buildAcpRegistry
|
|
32814
32892
|
};
|
|
32815
|
-
//# sourceMappingURL=chunk-
|
|
32893
|
+
//# sourceMappingURL=chunk-KGYQ5YNP.js.map
|