zooid 0.11.0 → 0.11.2

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 CHANGED
@@ -16,7 +16,7 @@ import {
16
16
  renderRegistration,
17
17
  startDaemonSocketServer,
18
18
  startWorkforcePublisher
19
- } from "./chunk-OCRQ3LWL.js";
19
+ } from "./chunk-KGYQ5YNP.js";
20
20
 
21
21
  // src/bin.ts
22
22
  import { resolve as resolve6 } from "path";
@@ -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(input.threadId, input.channelId);
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) st.callers[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) state.callers[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) state.callers[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) {
@@ -32844,4 +32890,4 @@ export {
32844
32890
  startDaemonSocketServer,
32845
32891
  buildAcpRegistry
32846
32892
  };
32847
- //# sourceMappingURL=chunk-OCRQ3LWL.js.map
32893
+ //# sourceMappingURL=chunk-KGYQ5YNP.js.map