@epoch-agent/core 3.0.0 → 3.1.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/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { REASONING_EFFORTS, MODEL_ENTRY_PROTOCOLS, PROVIDER_TYPES, isModelEntryId, parseModelRef, OPERATION_TYPES as OPERATION_TYPES$1, COMPLIANCE_CATEGORIES, COMPLIANCE_ACTIONS, SEARCH_PROVIDER_TYPES, CURRENCIES, LANGS, isSettingsPaneId, SETTINGS_PANE_IDS, BRAND_WHEN_SIDEBAR_COLLAPSED, DEFAULT_PERMISSION_LEVEL, resolvePermissionLevel, PERMISSION_LEVELS, SHELL_KINDS, cronTimes, SCHEDULE_MAX_TIMES_PER_DAY, SCHEDULE_INTERVAL_MIN_MINUTES, SCHEDULE_INTERVAL_MAX_MINUTES, ToolExposure, MIN_OPTIONS, MAX_OPTIONS, MAX_HEADER_CHARS, MAX_QUESTIONS, SCHEDULE_DEFAULT_PERMISSION, approvalPolicyForLevel, SCHEDULE_DRAFT_TOOL, isValidAgentRoleName, DEFAULT_AGENT_ROLE, isValidCommandName, RESERVED_COMMAND_NAMES, isWirePluginArchiveName, systemNote, formatMoney, totalUsageTokens, OFFLOADED_IMAGE_NOTE, NOOP_TELEMETRY, METRIC, contentToText, GEN_AI, isPromptOversize, promptTokens, entrySecretName, isEntrySecretName, entryRef, KEY_ACTIONS, tableOf, perAction, isKeyAction, parseSequence, RESERVED_CHORDS, chordId, sequenceId, ACTION_CONTEXTS, SEQUENCE_CONTEXTS, assertNeverPart, normalizeAppearanceTranslucent, MAX_ATTACH_FILES, MAX_ATTACH_TOTAL_BYTES, MAX_SESSION_REFS, utf8ByteLength, truncateToBudget, attachSessionSurface, isContextNearlyFull, isOperationType, normalizeApproval, SCHEDULE_DRAFT_SAVED_MARK, imagePartOmittedSummary, ENTRY_REF_PREFIX, placeholdersOf, SCHEDULE_CONFIRM_PLACEHOLDER, MAX_ATTACH_BYTES, SIMULTANEOUS_CONTEXTS, SESSION_REFERENCE_ERROR_CODES, filePartSummary, sessionPartSummary } from '@epoch-agent/protocol';
1
+ import { REASONING_EFFORTS, MODEL_ENTRY_PROTOCOLS, PROVIDER_TYPES, isModelEntryId, parseModelRef, OPERATION_TYPES as OPERATION_TYPES$1, COMPLIANCE_CATEGORIES, COMPLIANCE_ACTIONS, SEARCH_PROVIDER_TYPES, CURRENCIES, LANGS, isSettingsPaneId, SETTINGS_PANE_IDS, BRAND_WHEN_SIDEBAR_COLLAPSED, DEFAULT_PERMISSION_LEVEL, resolvePermissionLevel, PERMISSION_LEVELS, SHELL_KINDS, cronTimes, SCHEDULE_MAX_TIMES_PER_DAY, SCHEDULE_INTERVAL_MIN_MINUTES, SCHEDULE_INTERVAL_MAX_MINUTES, ToolExposure, MIN_OPTIONS, MAX_OPTIONS, MAX_HEADER_CHARS, MAX_QUESTIONS, SCHEDULE_DEFAULT_PERMISSION, approvalPolicyForLevel, SCHEDULE_DRAFT_TOOL, agentMessageLine, systemNote, LEAD_AGENT_ID, sessionSenderLabel, isValidAgentRoleName, DEFAULT_AGENT_ROLE, isValidCommandName, RESERVED_COMMAND_NAMES, isWirePluginArchiveName, contentToText, AGENT_MESSAGE_NOTE_TITLE, formatMoney, totalUsageTokens, OFFLOADED_IMAGE_NOTE, NOOP_TELEMETRY, METRIC, GEN_AI, isPromptOversize, promptTokens, entrySecretName, isEntrySecretName, entryRef, KEY_ACTIONS, tableOf, perAction, isKeyAction, parseSequence, RESERVED_CHORDS, chordId, sequenceId, ACTION_CONTEXTS, SEQUENCE_CONTEXTS, assertNeverPart, normalizeAppearanceTranslucent, MAX_ATTACH_FILES, MAX_ATTACH_TOTAL_BYTES, MAX_SESSION_REFS, utf8ByteLength, truncateToBudget, attachSessionSurface, isContextNearlyFull, isOperationType, normalizeApproval, SCHEDULE_DRAFT_SAVED_MARK, imagePartOmittedSummary, ENTRY_REF_PREFIX, placeholdersOf, SCHEDULE_CONFIRM_PLACEHOLDER, MAX_ATTACH_BYTES, SIMULTANEOUS_CONTEXTS, SESSION_REFERENCE_ERROR_CODES, filePartSummary, sessionPartSummary } from '@epoch-agent/protocol';
2
2
  export { API_KEY_ENV_VARS, COMPLIANCE_ACTIONS, COMPLIANCE_CATEGORIES, LEGACY_LEVEL_ALIASES, MAX_ATTACH_BYTES, MAX_ATTACH_FILES, MAX_ATTACH_TOTAL_BYTES, MAX_SESSION_ATTACH_BYTES, MAX_SESSION_REFS, OPERATION_TYPES, PERMISSION_LEVELS, PLAN_OUTCOMES, PROVIDER_INFOS, PROVIDER_TYPES, ToolExposure, apiKeyEnvVar, approvalPolicyForLevel, extractAllMentions, extractMentions, extractSessionMentions, getProviderInfo, isOperationType, isPermissionLevel, isPlanOutcome, isProviderType, normalizeApproval, resolvePermissionLevel } from '@epoch-agent/protocol';
3
3
  import { existsSync, mkdirSync, rmSync, writeFileSync, statSync, readdirSync, readFileSync, renameSync, realpathSync, symlinkSync, cpSync, lstatSync, unlinkSync, rmdirSync, mkdtempSync, copyFileSync, openSync, writeSync, closeSync, readSync } from 'fs';
4
4
  import { platform, tmpdir, homedir, hostname } from 'os';
@@ -230,15 +230,15 @@ function createSchtasksBackend(opts = {}) {
230
230
  let dir;
231
231
  try {
232
232
  dir = mkdtempSync(join(tmpdir(), "epoch-schtasks-"));
233
- } catch (err) {
234
- return { ok: false, detail: `task-xml-write-failed: ${describe10(err)}` };
233
+ } catch (err3) {
234
+ return { ok: false, detail: `task-xml-write-failed: ${describe10(err3)}` };
235
235
  }
236
236
  try {
237
237
  const file = join(dir, "task.xml");
238
238
  try {
239
239
  writeFileSync(file, encodeTaskXml(renderTaskXml(input)));
240
- } catch (err) {
241
- return { ok: false, detail: `task-xml-write-failed: ${describe10(err)}` };
240
+ } catch (err3) {
241
+ return { ok: false, detail: `task-xml-write-failed: ${describe10(err3)}` };
242
242
  }
243
243
  const res = await run("schtasks", ["/Create", "/F", "/TN", input.osTaskId, "/XML", file]);
244
244
  if (res.code !== 0) return { ok: false, detail: detailOf("schtasks /Create", res) };
@@ -471,8 +471,8 @@ function detailOf(what, res) {
471
471
  const msg = (res.stderr || res.stdout).trim();
472
472
  return `${what} exit ${res.code}${msg ? `: ${msg}` : ""}`;
473
473
  }
474
- function describe10(err) {
475
- return err instanceof Error ? err.message : String(err);
474
+ function describe10(err3) {
475
+ return err3 instanceof Error ? err3.message : String(err3);
476
476
  }
477
477
  var SCHTASKS_FOLDER, WEEKDAY_CODES, WEEKDAY_NAMES, MONTH_NAMES;
478
478
  var init_schtasks = __esm({
@@ -545,8 +545,8 @@ function createLaunchdBackend(opts = {}) {
545
545
  mkdirSync(agentsDir(), { recursive: true });
546
546
  mkdirSync(input.logDir, { recursive: true });
547
547
  writeFileSync(path, renderPlist(label, input), "utf-8");
548
- } catch (err) {
549
- return { ok: false, detail: `plist-write-failed: ${describe11(err)}` };
548
+ } catch (err3) {
549
+ return { ok: false, detail: `plist-write-failed: ${describe11(err3)}` };
550
550
  }
551
551
  await run("launchctl", ["bootout", `${guiDomain()}/${label}`]);
552
552
  const toggle = await backend.setEnabled(label, input.enabled);
@@ -561,8 +561,8 @@ function createLaunchdBackend(opts = {}) {
561
561
  }
562
562
  try {
563
563
  rmSync(plistPath(label), { force: true });
564
- } catch (err) {
565
- return { ok: false, detail: `plist-remove-failed: ${describe11(err)}` };
564
+ } catch (err3) {
565
+ return { ok: false, detail: `plist-remove-failed: ${describe11(err3)}` };
566
566
  }
567
567
  return { ok: true };
568
568
  },
@@ -723,8 +723,8 @@ function detailOf2(what, res) {
723
723
  const msg = (res.stderr || res.stdout).trim();
724
724
  return `${what} exit ${res.code}${msg ? `: ${msg}` : ""}`;
725
725
  }
726
- function describe11(err) {
727
- return err instanceof Error ? err.message : String(err);
726
+ function describe11(err3) {
727
+ return err3 instanceof Error ? err3.message : String(err3);
728
728
  }
729
729
  var LAUNCHD_LABEL_PREFIX;
730
730
  var init_launchd = __esm({
@@ -775,12 +775,12 @@ var init_backend = __esm({
775
775
  file,
776
776
  [...args],
777
777
  { encoding: "buffer", windowsHide: true },
778
- (err, stdout, stderr) => {
779
- const code = err && typeof err.code === "number" ? err.code ?? 1 : err ? 1 : 0;
778
+ (err3, stdout, stderr) => {
779
+ const code = err3 && typeof err3.code === "number" ? err3.code ?? 1 : err3 ? 1 : 0;
780
780
  resolve17({ code, stdout: decodeOutput(stdout), stderr: decodeOutput(stderr) });
781
781
  }
782
782
  ),
783
- (err) => resolve17({ code: 1, stdout: "", stderr: `${file}: ${err.message}` })
783
+ (err3) => resolve17({ code: 1, stdout: "", stderr: `${file}: ${err3.message}` })
784
784
  );
785
785
  });
786
786
  }
@@ -818,12 +818,21 @@ var COMMAND_TOOLS = /* @__PURE__ */ new Set([
818
818
  "shell_open",
819
819
  "shell_send",
820
820
  "delegate_task",
821
+ "spawn_teammate",
822
+ "interrupt_agent",
823
+ "followup_task",
821
824
  "run_code",
822
825
  "mcp_add",
823
826
  "mcp_update",
824
827
  "mcp_remove"
825
828
  ]);
826
- var NON_SHELL_COMMAND_TOOLS = /* @__PURE__ */ new Set(["run_code", "delegate_task"]);
829
+ var NON_SHELL_COMMAND_TOOLS = /* @__PURE__ */ new Set([
830
+ "run_code",
831
+ "delegate_task",
832
+ "spawn_teammate",
833
+ "interrupt_agent",
834
+ "followup_task"
835
+ ]);
827
836
  var CODE_EXEC_TOOLS = /* @__PURE__ */ new Set(["code_exec", "sandbox"]);
828
837
  var NETWORK_TOOLS = /* @__PURE__ */ new Set(["web_fetch", "web_search"]);
829
838
  var INTERNAL_TOOLS = /* @__PURE__ */ new Set([
@@ -840,7 +849,25 @@ var INTERNAL_TOOLS = /* @__PURE__ */ new Set([
840
849
  "goal",
841
850
  "skill_view",
842
851
  "tool_search",
843
- "schedule_draft"
852
+ "schedule_draft",
853
+ "send_message",
854
+ "list_agents",
855
+ "wait_agent",
856
+ "team_task_create",
857
+ "team_task_list",
858
+ "team_task_get",
859
+ "team_task_update",
860
+ "create_channel",
861
+ "upsert_channel",
862
+ "get_channels",
863
+ "list_threads",
864
+ "search_posts",
865
+ "read_thread",
866
+ "read_post",
867
+ "subscribe",
868
+ "unsubscribe",
869
+ "post",
870
+ "append"
844
871
  ]);
845
872
  function mapOperationType(toolName) {
846
873
  if (COMMAND_TOOLS.has(toolName)) return "command";
@@ -1035,10 +1062,10 @@ var ToolRegistry = class {
1035
1062
  if (!plugin.onInit) continue;
1036
1063
  try {
1037
1064
  await plugin.onInit(ctx);
1038
- } catch (err) {
1065
+ } catch (err3) {
1039
1066
  failures.push({
1040
1067
  plugin: plugin.name,
1041
- error: err instanceof Error ? err.message : String(err)
1068
+ error: err3 instanceof Error ? err3.message : String(err3)
1042
1069
  });
1043
1070
  }
1044
1071
  }
@@ -1087,12 +1114,12 @@ function encoderFor(encoding) {
1087
1114
  throw new Error(`${encoding} \u7684\u6A21\u5757\u91CC\u6CA1\u6709 countTokens`);
1088
1115
  }
1089
1116
  entry.counter = { countTokens: mod.countTokens };
1090
- } catch (err) {
1117
+ } catch (err3) {
1091
1118
  if (!warned) {
1092
1119
  warned = true;
1093
1120
  log.debug("\u5206\u8BCD\u5668\u52A0\u8F7D\u5931\u8D25\uFF0C\u672C\u8FDB\u7A0B\u56DE\u843D\u5230 chars/4 \u4F30\u7B97", {
1094
1121
  encoding,
1095
- error: err instanceof Error ? err.message : String(err)
1122
+ error: err3 instanceof Error ? err3.message : String(err3)
1096
1123
  });
1097
1124
  }
1098
1125
  }
@@ -1461,8 +1488,8 @@ var CodeSandbox = class {
1461
1488
  ...req.signal ? { signal: req.signal } : {}
1462
1489
  });
1463
1490
  return { ...result, isolation };
1464
- } catch (err) {
1465
- const msg = err instanceof Error ? err.message : String(err);
1491
+ } catch (err3) {
1492
+ const msg = err3 instanceof Error ? err3.message : String(err3);
1466
1493
  if (msg.includes("timed out") || msg.includes("killed")) {
1467
1494
  return {
1468
1495
  success: false,
@@ -1548,9 +1575,9 @@ var CodeSandbox = class {
1548
1575
  const onAbort = () => {
1549
1576
  child?.kill("SIGKILL");
1550
1577
  };
1551
- const failToStart = (err) => {
1578
+ const failToStart = (err3) => {
1552
1579
  opts.signal?.removeEventListener("abort", onAbort);
1553
- if (err.code === "ENOENT") {
1580
+ if (err3.code === "ENOENT") {
1554
1581
  resolve17({
1555
1582
  success: false,
1556
1583
  output: "",
@@ -1563,7 +1590,7 @@ var CodeSandbox = class {
1563
1590
  resolve17({
1564
1591
  success: false,
1565
1592
  output: "",
1566
- error: `[\u9519\u8BEF] ${err.message}\uFF08command=${command}\uFF0Ccwd=${spawnOpts.cwd ?? ""}\uFF09`,
1593
+ error: `[\u9519\u8BEF] ${err3.message}\uFF08command=${command}\uFF0Ccwd=${spawnOpts.cwd ?? ""}\uFF09`,
1567
1594
  errorType: "runtime",
1568
1595
  duration: Date.now() - start
1569
1596
  });
@@ -1978,7 +2005,8 @@ var BLOCKED_TOOLS = Object.freeze([
1978
2005
  "delegate_task",
1979
2006
  "clarify",
1980
2007
  "memory",
1981
- "send_message",
2008
+ "spawn_teammate",
2009
+ "followup_task",
1982
2010
  "cronjob",
1983
2011
  "enter_plan_mode",
1984
2012
  "exit_plan_mode",
@@ -2006,7 +2034,7 @@ var DelegateManager = class {
2006
2034
  async delegate(args, parentSessionId, signal) {
2007
2035
  const start = Date.now();
2008
2036
  const tasks = this.normalizeTasks(args);
2009
- const maxConcurrent = args.max_concurrent ?? this.config.max_concurrent_children;
2037
+ let maxConcurrent = args.max_concurrent ?? this.config.max_concurrent_children;
2010
2038
  if (this.currentDepth >= this.config.max_spawn_depth) {
2011
2039
  return {
2012
2040
  success: false,
@@ -2018,6 +2046,18 @@ var DelegateManager = class {
2018
2046
  return { success: true, output: this.buildSummary([], Date.now() - start), duration: 0 };
2019
2047
  }
2020
2048
  const background = args.background === true;
2049
+ const team = this.config.team;
2050
+ if (team) {
2051
+ const slots = team.availableMemberSlots(parentSessionId);
2052
+ if (slots <= 0) {
2053
+ return {
2054
+ success: false,
2055
+ output: `\u8FD9\u4E2A\u4F1A\u8BDD\u5DF2\u7ECF\u6709 ${team.memberLimit} \u4E2A\u6210\u5458\u5728\u8DD1\uFF08\u5E76\u53D1\u4E0A\u9650\uFF09\uFF0C\u8FD9\u4E00\u6279\u6CA1\u6D3E\u51FA\u53BB \u2014\u2014 \u7B49\u5176\u4E2D\u4E00\u4E2A\u6536\u5DE5\u518D\u6765\uFF0C\u6216\u8005\u5148 interrupt_agent \u6536\u6389\u4E00\u4E2A`,
2056
+ duration: 0
2057
+ };
2058
+ }
2059
+ maxConcurrent = Math.min(maxConcurrent, slots);
2060
+ }
2021
2061
  if (signal?.aborted) {
2022
2062
  return { success: false, output: ABORTED, duration: 0 };
2023
2063
  }
@@ -2037,13 +2077,13 @@ var DelegateManager = class {
2037
2077
  ).then((results) => {
2038
2078
  const total = Date.now() - start;
2039
2079
  const summary = this.buildSummary(results, total);
2040
- const ok2 = results.every((r) => r.success);
2080
+ const ok4 = results.every((r) => r.success);
2041
2081
  if (job) {
2042
2082
  job.append(`
2043
2083
  ${summary}`);
2044
- job.finish(ok2 ? "exited" : "failed");
2084
+ job.finish(ok4 ? "exited" : "failed");
2045
2085
  }
2046
- return { results, summary, total, ok: ok2 };
2086
+ return { results, summary, total, ok: ok4 };
2047
2087
  });
2048
2088
  if (background && job) {
2049
2089
  void run.catch(() => void 0);
@@ -2120,7 +2160,9 @@ ${summary}`);
2120
2160
  }
2121
2161
  async runSingleTask(task, parentSessionId, signal, onProgress) {
2122
2162
  const start = Date.now();
2123
- const sessionId = `delegate-${randomUUID().slice(0, 8)}`;
2163
+ const resuming = task.resumeSessionId !== void 0;
2164
+ const sessionId = task.resumeSessionId ?? `delegate-${randomUUID().slice(0, 8)}`;
2165
+ const memberId = task.agentId ?? sessionId;
2124
2166
  const failed = (error, summary = "") => ({
2125
2167
  goal: task.goal,
2126
2168
  success: false,
@@ -2129,11 +2171,29 @@ ${summary}`);
2129
2171
  duration: Date.now() - start,
2130
2172
  ...task.role ? { role: task.role } : {}
2131
2173
  });
2174
+ const team = this.config.team;
2132
2175
  if (signal?.aborted) return failed(ABORTED);
2176
+ if (team && team.availableMemberSlots(parentSessionId) <= 0) {
2177
+ return failed(
2178
+ `\u8FD9\u4E2A\u4F1A\u8BDD\u5DF2\u7ECF\u6709 ${team.memberLimit} \u4E2A\u6210\u5458\u5728\u8DD1\uFF08\u5E76\u53D1\u4E0A\u9650\uFF09\uFF0C\u8FD9\u4E00\u4E2A\u6CA1\u6D3E\u51FA\u53BB\u3002\u7B49\u5176\u4E2D\u4E00\u4E2A\u6536\u5DE5\u518D\u6765\uFF0C\u6216\u8005\u5148 interrupt_agent \u6536\u6389\u4E00\u4E2A`
2179
+ );
2180
+ }
2181
+ if (resuming) {
2182
+ this.config.team?.markRunning(memberId);
2183
+ } else {
2184
+ this.config.team?.createMember({
2185
+ sessionId,
2186
+ parentSessionId,
2187
+ ...task.agentId ? { agentId: task.agentId } : {},
2188
+ ...task.role ? { role: task.role } : {}
2189
+ });
2190
+ }
2133
2191
  const controller = new AbortController();
2192
+ this.config.team?.setAbort(memberId, () => controller.abort());
2134
2193
  const unlink = linkAbort(isAbortSignal(signal) ? signal : void 0, controller);
2135
2194
  const ms = this.config.task_timeout;
2136
2195
  let timer;
2196
+ let outcome = "failed";
2137
2197
  try {
2138
2198
  const work = this.runner(
2139
2199
  task.goal,
@@ -2142,7 +2202,11 @@ ${summary}`);
2142
2202
  task.role,
2143
2203
  parentSessionId,
2144
2204
  controller.signal,
2145
- onProgress
2205
+ (line) => {
2206
+ this.config.team?.setActivity(memberId, line);
2207
+ onProgress?.(line);
2208
+ },
2209
+ resuming ? { resume: true } : void 0
2146
2210
  );
2147
2211
  const result = await (ms > 0 ? Promise.race([
2148
2212
  work,
@@ -2154,6 +2218,7 @@ ${summary}`);
2154
2218
  })
2155
2219
  ]) : work);
2156
2220
  if (controller.signal.aborted) return failed(ABORTED, result.text);
2221
+ outcome = result.error ? "failed" : "finalized";
2157
2222
  return {
2158
2223
  goal: task.goal,
2159
2224
  success: !result.error,
@@ -2162,11 +2227,12 @@ ${summary}`);
2162
2227
  duration: Date.now() - start,
2163
2228
  ...task.role ? { role: task.role } : {}
2164
2229
  };
2165
- } catch (err) {
2166
- const msg = err instanceof Error ? err.message : String(err);
2230
+ } catch (err3) {
2231
+ const msg = err3 instanceof Error ? err3.message : String(err3);
2167
2232
  if (signal?.aborted) return failed(ABORTED);
2168
2233
  return failed(msg.includes("\u8D85\u65F6") ? `[\u8D85\u65F6] ${msg}` : msg);
2169
2234
  } finally {
2235
+ this.config.team?.markFinished(memberId, outcome);
2170
2236
  clearTimeout(timer);
2171
2237
  unlink();
2172
2238
  }
@@ -2211,8 +2277,9 @@ function renderRoles(roles) {
2211
2277
  ...roles.map((r) => `- ${r.name}: ${r.description}`)
2212
2278
  ];
2213
2279
  }
2214
- function createDelegateTool(runner, config, roles) {
2280
+ function createDelegateTool(runner, config, roles, onManager) {
2215
2281
  const manager = new DelegateManager(runner, config);
2282
+ onManager?.(manager);
2216
2283
  const listRoles = roles ?? (() => []);
2217
2284
  return {
2218
2285
  name: "delegate_task",
@@ -2413,9 +2480,9 @@ function goalBlockBody(view) {
2413
2480
  return lines;
2414
2481
  }
2415
2482
  // src/tools/builtin/goal.ts
2416
- function say2(text, ok2, startedAt) {
2483
+ function say2(text, ok4, startedAt) {
2417
2484
  const duration = Date.now() - startedAt;
2418
- return ok2 ? { success: true, output: text, duration } : { success: false, output: "", error: { code: 7101, message: text }, duration };
2485
+ return ok4 ? { success: true, output: text, duration } : { success: false, output: "", error: { code: 7101, message: text }, duration };
2419
2486
  }
2420
2487
  function createGoalTool(deps) {
2421
2488
  return {
@@ -2629,8 +2696,8 @@ ${f.content}`);
2629
2696
  );
2630
2697
  }
2631
2698
  return ok(`\u5DF2\u5220\u9664 ${target} \u8BB0\u5FC6\u6761\u76EE`, start);
2632
- } catch (err) {
2633
- return fail(err instanceof Error ? err.message : String(err), start, 4002);
2699
+ } catch (err3) {
2700
+ return fail(err3 instanceof Error ? err3.message : String(err3), start, 4002);
2634
2701
  }
2635
2702
  }
2636
2703
  };
@@ -2837,9 +2904,9 @@ async function runCode(input) {
2837
2904
  }
2838
2905
  void relay(msg);
2839
2906
  });
2840
- worker.on("error", (err) => {
2907
+ worker.on("error", (err3) => {
2841
2908
  if (settled) return;
2842
- ending = err.code === "ERR_WORKER_OUT_OF_MEMORY" ? { kind: "oom", message: oomNotice(limits.maxMemoryMb) } : err.code === "ERR_ACCESS_DENIED" ? { kind: "policy", message: policyNotice() } : { kind: "failed", message: err.message };
2909
+ ending = err3.code === "ERR_WORKER_OUT_OF_MEMORY" ? { kind: "oom", message: oomNotice(limits.maxMemoryMb) } : err3.code === "ERR_ACCESS_DENIED" ? { kind: "policy", message: policyNotice() } : { kind: "failed", message: err3.message };
2843
2910
  finish();
2844
2911
  });
2845
2912
  worker.on("exit", () => {
@@ -2862,11 +2929,11 @@ async function runCode(input) {
2862
2929
  const result = await input.callTool(msg.name, msg.args);
2863
2930
  if (result.success) reply(msg.id, { ok: true, output: result.output });
2864
2931
  else reply(msg.id, { ok: false, fatal: false, message: result.output });
2865
- } catch (err) {
2932
+ } catch (err3) {
2866
2933
  reply(msg.id, {
2867
2934
  ok: false,
2868
2935
  fatal: false,
2869
- message: err instanceof Error ? err.message : String(err)
2936
+ message: err3 instanceof Error ? err3.message : String(err3)
2870
2937
  });
2871
2938
  }
2872
2939
  };
@@ -3959,9 +4026,9 @@ function needsAllowlist(permission2) {
3959
4026
  return permission2 !== "plan" && approvalPolicyForLevel(permission2) !== "never";
3960
4027
  }
3961
4028
  // src/tools/builtin/schedule-draft.ts
3962
- function say4(text, ok2, startedAt) {
4029
+ function say4(text, ok4, startedAt) {
3963
4030
  const duration = Date.now() - startedAt;
3964
- return ok2 ? { success: true, output: text, duration } : { success: false, output: "", error: { code: 7201, message: text }, duration };
4031
+ return ok4 ? { success: true, output: text, duration } : { success: false, output: "", error: { code: 7201, message: text }, duration };
3965
4032
  }
3966
4033
  function describeRow(def) {
3967
4034
  const state = def.enabled ? "\u542F\u7528" : "\u505C\u7528";
@@ -4188,83 +4255,1488 @@ function createScheduleDraftTool(deps) {
4188
4255
  items: { type: "string" },
4189
4256
  description: "\u9010\u6761\u653E\u884C\uFF0C\u6700\u63A8\u8350\u7684\u4E00\u683C\u3002\u5199\u6CD5\uFF1Aterminal(git status) / terminal(git log:*) / file_write(~/reports/**)\u3002\u65E0\u4EBA\u503C\u5B88\u4E0B\u649E\u5230\u8981\u786E\u8BA4\u7684\u64CD\u4F5C\u4E0D\u4F1A\u7B49\u4EBA\uFF0C\u4F1A\u76F4\u63A5\u6536\u5C3E\u5E76\u8BB0\u4E00\u6761\u6B20\u6761 \u2014\u2014 \u6240\u4EE5\u4EFB\u52A1\u8981\u8DD1\u4EC0\u4E48\u547D\u4EE4\uFF0C\u8FD9\u91CC\u5C31\u5F97\u9010\u6761\u5217\u51FA\u6765"
4190
4257
  },
4191
- enabled: { type: "boolean", description: "\u53EA\u6709 update \u7528\u3002\u542F\u7528 / \u505C\u7528\u90A3\u4E00\u6761" },
4192
- maxTurns: { type: "number", description: "\u53EA\u6709 update \u7528\u3002\u8F6E\u6B21\u4E0A\u9650\uFF0C\u6B63\u6574\u6570" },
4193
- timeoutMs: { type: "number", description: "\u53EA\u6709 update \u7528\u3002\u5899\u949F\u8D85\u65F6\uFF0C\u6BEB\u79D2" }
4258
+ enabled: { type: "boolean", description: "\u53EA\u6709 update \u7528\u3002\u542F\u7528 / \u505C\u7528\u90A3\u4E00\u6761" },
4259
+ maxTurns: { type: "number", description: "\u53EA\u6709 update \u7528\u3002\u8F6E\u6B21\u4E0A\u9650\uFF0C\u6B63\u6574\u6570" },
4260
+ timeoutMs: { type: "number", description: "\u53EA\u6709 update \u7528\u3002\u5899\u949F\u8D85\u65F6\uFF0C\u6BEB\u79D2" }
4261
+ },
4262
+ required: ["action"]
4263
+ },
4264
+ exposure: ToolExposure.Direct,
4265
+ supportsParallel: false,
4266
+ annotations: {
4267
+ readOnlyHint: false,
4268
+ destructiveHint: true,
4269
+ idempotentHint: false,
4270
+ openWorldHint: false
4271
+ },
4272
+ operation: "file_read",
4273
+ describeTarget: (args) => `schedule_draft:${String(args["action"] ?? "list")}`,
4274
+ async execute(rawArgs, ctx) {
4275
+ const startedAt = Date.now();
4276
+ const action = rawArgs["action"];
4277
+ if (action === "list") {
4278
+ const rows = deps.list();
4279
+ return say4(
4280
+ rows.length === 0 ? "\u4E00\u6761\u5B9A\u65F6\u4EFB\u52A1\u90FD\u8FD8\u6CA1\u6709\u3002\u8981\u65B0\u5EFA\u5C31\u7528 action=create\u3002" : `\u73B0\u6709 ${rows.length} \u6761\uFF1A
4281
+ ${rows.map(describeRow).join("\n")}`,
4282
+ true,
4283
+ startedAt
4284
+ );
4285
+ }
4286
+ const parsed = parseScheduleDraft(rawArgs);
4287
+ if (!parsed.ok) return say4(parsed.message, false, startedAt);
4288
+ const draft = parsed.value;
4289
+ const current = draft.action === "update" ? deps.get(draft.id) : void 0;
4290
+ if (draft.action === "update" && current === void 0) {
4291
+ return say4(
4292
+ `\u6CA1\u6709 id \u4E3A ${draft.id} \u7684\u4EFB\u52A1\u3002\u5148\u7528 action=list \u770B\u4E00\u773C\u73B0\u6709\u7684\u3002`,
4293
+ false,
4294
+ startedAt
4295
+ );
4296
+ }
4297
+ const issues = validateDraft(draft, deps.homeDir, current);
4298
+ if (issues.length > 0) {
4299
+ return say4(
4300
+ `\u8FD9\u4EFD\u63D0\u6848\u5B58\u4E0D\u4E0B\u6765\uFF0C\u5148\u6539\u8FD9\u51E0\u5904\u518D\u8BF4\uFF1A${issues.join("\u3001")}\u3002\uFF08\u8FD9\u4E9B\u662F\u6821\u9A8C\u7801\uFF0C\u542B\u4E49\u770B\u5B57\u9762\uFF1Bdetail \u62EC\u5728\u540E\u9762\uFF09`,
4301
+ false,
4302
+ startedAt
4303
+ );
4304
+ }
4305
+ const unattended = unattendedIssues(draft);
4306
+ if (unattended.length > 0) {
4307
+ return say4(
4308
+ `\u8FD9\u4EFD\u63D0\u6848\u5B58\u5F97\u4E0B\u6765\uFF0C\u4F46\u5B83\u5230\u70B9\u4E86**\u8DD1\u4E0D\u51FA\u7ED3\u679C** \u2014\u2014 \u5B9A\u65F6\u4EFB\u52A1\u662F\u65E0\u4EBA\u503C\u5B88\u7684\uFF0C\u6CA1\u4EBA\u5728\u65C1\u8FB9\u56DE\u8BDD\u3002\u6539\u5B8C\u518D\u4EA4\uFF1A
4309
+ ${unattended.map((x) => `\xB7 ${x}`).join("\n")}`,
4310
+ false,
4311
+ startedAt
4312
+ );
4313
+ }
4314
+ const readOnly = ctx.permissionLevel === "plan";
4315
+ if (readOnly || deps.save === void 0) {
4316
+ return say4(summarizeProposal(draft, current, readOnly), true, startedAt);
4317
+ }
4318
+ const saved = await persist(deps.save, draft, current);
4319
+ if (saved.issues.length > 0) {
4320
+ const codes = saved.issues.map((x) => x.detail ? `${x.code}\uFF08${x.detail}\uFF09` : x.code);
4321
+ return say4(`\u5F15\u64CE\u62D2\u7EDD\u4E86\u8FD9\u4EFD\u63D0\u6848\uFF0C\u4E00\u4E2A\u5B57\u90FD\u6CA1\u5199\uFF1A${codes.join("\u3001")}\u3002`, false, startedAt);
4322
+ }
4323
+ const def = saved.schedule;
4324
+ if (def === void 0) {
4325
+ return say4(
4326
+ "\u5F15\u64CE\u8BF4\u5B58\u4E0B\u6765\u4E86\uFF0C\u4F46\u6CA1\u56DE\u90A3\u6761\u4EFB\u52A1 \u2014\u2014 \u53BB\u81EA\u52A8\u5316\u9762\u677F\u770B\u4E00\u773C\u5B83\u5230\u5E95\u5728\u4E0D\u5728\u3002",
4327
+ false,
4328
+ startedAt
4329
+ );
4330
+ }
4331
+ return say4(summarizeSaved(draft, def, saved.registration, current), true, startedAt);
4332
+ }
4333
+ };
4334
+ }
4335
+ var DEFAULT_INBOX_CAPACITY = 20;
4336
+ var AgentInbox = class {
4337
+ constructor(capacity = DEFAULT_INBOX_CAPACITY) {
4338
+ this.capacity = capacity;
4339
+ }
4340
+ capacity;
4341
+ queue = [];
4342
+ dropped = 0;
4343
+ push(msg) {
4344
+ let evicted = false;
4345
+ while (this.queue.length >= this.capacity) {
4346
+ this.queue.shift();
4347
+ this.dropped += 1;
4348
+ evicted = true;
4349
+ }
4350
+ this.queue.push(msg);
4351
+ return !evicted;
4352
+ }
4353
+ pending() {
4354
+ return this.queue.length > 0;
4355
+ }
4356
+ take() {
4357
+ if (this.queue.length === 0) return [];
4358
+ const lines = this.queue.map((m) => agentMessageLine(m));
4359
+ this.queue = [];
4360
+ if (this.dropped > 0) {
4361
+ lines.unshift(systemNote(`\u6536\u4EF6\u7BB1\u6EE1\u4E86\uFF0C\u6709 ${this.dropped} \u6761\u66F4\u65E9\u7684\u6D88\u606F\u88AB\u4E22\u5F03`));
4362
+ this.dropped = 0;
4363
+ }
4364
+ return [lines.join("\n")];
4365
+ }
4366
+ get size() {
4367
+ return this.queue.length;
4368
+ }
4369
+ };
4370
+ var DEFAULT_TASK_CAPACITY = 200;
4371
+ var TeamTaskBoard = class {
4372
+ constructor(capacity = DEFAULT_TASK_CAPACITY) {
4373
+ this.capacity = capacity;
4374
+ }
4375
+ capacity;
4376
+ tasks = /* @__PURE__ */ new Map();
4377
+ listeners = /* @__PURE__ */ new Set();
4378
+ onChange(cb) {
4379
+ this.listeners.add(cb);
4380
+ return () => {
4381
+ this.listeners.delete(cb);
4382
+ };
4383
+ }
4384
+ notify() {
4385
+ for (const cb of this.listeners) {
4386
+ try {
4387
+ cb();
4388
+ } catch {
4389
+ }
4390
+ }
4391
+ }
4392
+ create(input) {
4393
+ if (this.tasks.size >= this.capacity) {
4394
+ return { ok: false, reason: `\u4EFB\u52A1\u677F\u6EE1\u4E86\uFF08${this.capacity} \u6761\uFF09\uFF0C\u5148\u505A\u5B8C\u518D\u5EFA` };
4395
+ }
4396
+ const dependsOn = input.dependsOn ?? [];
4397
+ const missing = dependsOn.filter((id) => !this.tasks.has(id));
4398
+ if (missing.length > 0) {
4399
+ return { ok: false, reason: `\u4F9D\u8D56\u7684\u4EFB\u52A1\u4E0D\u5B58\u5728\uFF1A${missing.join(", ")}` };
4400
+ }
4401
+ const now = Date.now();
4402
+ const task = {
4403
+ id: `task-${randomUUID().slice(0, 8)}`,
4404
+ title: input.title,
4405
+ ...input.description ? { description: input.description } : {},
4406
+ ...input.owner ? { owner: input.owner } : {},
4407
+ status: "pending",
4408
+ dependsOn,
4409
+ revision: 1,
4410
+ createdAt: now,
4411
+ updatedAt: now
4412
+ };
4413
+ this.tasks.set(task.id, task);
4414
+ this.notify();
4415
+ return { ok: true, task: { ...task } };
4416
+ }
4417
+ get(id) {
4418
+ const t83 = this.tasks.get(id);
4419
+ return t83 ? { ...t83 } : void 0;
4420
+ }
4421
+ list(filter) {
4422
+ return [...this.tasks.values()].filter((t83) => filter?.status ? t83.status === filter.status : true).filter((t83) => filter?.owner ? t83.owner === filter.owner : true).sort((a, b) => a.createdAt - b.createdAt).map((t83) => ({ ...t83 }));
4423
+ }
4424
+ update(id, patch, expectedRevision) {
4425
+ const current = this.tasks.get(id);
4426
+ if (!current) return { ok: false, reason: `\u6CA1\u6709\u8FD9\u4E2A\u4EFB\u52A1\uFF1A${id}` };
4427
+ if (expectedRevision !== void 0 && current.revision !== expectedRevision) {
4428
+ return {
4429
+ ok: false,
4430
+ reason: `\u4EFB\u52A1 ${id} \u5DF2\u7ECF\u53D8\u8FC7\u4E86\uFF1A\u4F60\u624B\u4E0A\u662F revision ${expectedRevision}\uFF0C\u73B0\u5728\u662F ${current.revision}\u3002\u91CD\u65B0 team_task_get \u8BFB\u4E00\u904D\u518D\u6539`
4431
+ };
4432
+ }
4433
+ const next = {
4434
+ ...current,
4435
+ ...patch.title !== void 0 ? { title: patch.title } : {},
4436
+ ...patch.description !== void 0 ? { description: patch.description } : {},
4437
+ ...patch.status !== void 0 ? { status: patch.status } : {},
4438
+ ...patch.owner !== void 0 ? { owner: patch.owner } : {},
4439
+ revision: current.revision + 1,
4440
+ updatedAt: Date.now()
4441
+ };
4442
+ this.tasks.set(id, next);
4443
+ this.notify();
4444
+ return { ok: true, task: { ...next } };
4445
+ }
4446
+ };
4447
+ // src/team/registry.ts
4448
+ var DEFAULT_MAX_RUNNING_MEMBERS = 3;
4449
+ var DEFAULT_MAX_WOKEN_SESSIONS = 3;
4450
+ var WAKE_RAMP_MS = 6e4;
4451
+ var TeamRegistry = class {
4452
+ constructor(inboxCapacity = DEFAULT_INBOX_CAPACITY, limits = {}) {
4453
+ this.inboxCapacity = inboxCapacity;
4454
+ this.limits = {
4455
+ maxRunningMembers: limits.maxRunningMembers ?? DEFAULT_MAX_RUNNING_MEMBERS,
4456
+ maxWokenSessions: limits.maxWokenSessions ?? DEFAULT_MAX_WOKEN_SESSIONS
4457
+ };
4458
+ this.tasks = new TeamTaskBoard();
4459
+ this.tasks.onChange(() => this.notify());
4460
+ }
4461
+ inboxCapacity;
4462
+ members = /* @__PURE__ */ new Map();
4463
+ bySessionId = /* @__PURE__ */ new Map();
4464
+ mainInboxes = /* @__PURE__ */ new Map();
4465
+ sessions = /* @__PURE__ */ new Set();
4466
+ activeTurns = /* @__PURE__ */ new Map();
4467
+ wokenSessions = /* @__PURE__ */ new Map();
4468
+ limits;
4469
+ bridge;
4470
+ aborters = /* @__PURE__ */ new Map();
4471
+ listeners = /* @__PURE__ */ new Set();
4472
+ tasks;
4473
+ onChange(cb) {
4474
+ this.listeners.add(cb);
4475
+ return () => {
4476
+ this.listeners.delete(cb);
4477
+ };
4478
+ }
4479
+ notify() {
4480
+ for (const cb of this.listeners) {
4481
+ try {
4482
+ cb();
4483
+ } catch {
4484
+ }
4485
+ }
4486
+ }
4487
+ waitForChange(ms, signal) {
4488
+ return new Promise((resolve17) => {
4489
+ let done2 = false;
4490
+ const onAbort = () => finish(false);
4491
+ const cleanup = () => {
4492
+ off();
4493
+ clearTimeout(timer);
4494
+ signal?.removeEventListener?.("abort", onAbort);
4495
+ };
4496
+ const finish = (v) => {
4497
+ if (done2) return;
4498
+ done2 = true;
4499
+ cleanup();
4500
+ resolve17(v);
4501
+ };
4502
+ const off = this.onChange(() => finish(true));
4503
+ const timer = setTimeout(() => finish(false), ms);
4504
+ signal?.addEventListener?.("abort", onAbort);
4505
+ });
4506
+ }
4507
+ createMember(args) {
4508
+ const agentId = args.agentId ?? args.sessionId;
4509
+ if (this.members.has(agentId)) {
4510
+ throw new Error(`\u6210\u5458\u540D\u5DF2\u88AB\u5360\u7528\uFF1A${agentId}`);
4511
+ }
4512
+ const info = {
4513
+ agentId,
4514
+ sessionId: args.sessionId,
4515
+ parentSessionId: args.parentSessionId,
4516
+ status: "running",
4517
+ ...args.role ? { role: args.role } : {},
4518
+ startedAt: Date.now()
4519
+ };
4520
+ this.members.set(agentId, {
4521
+ info,
4522
+ inbox: new AgentInbox(this.inboxCapacity)
4523
+ });
4524
+ this.bySessionId.set(args.sessionId, agentId);
4525
+ this.notify();
4526
+ return { ...info };
4527
+ }
4528
+ setAbort(agentId, fn) {
4529
+ if (!this.members.has(agentId)) return;
4530
+ this.aborters.set(agentId, fn);
4531
+ }
4532
+ interrupt(agentId) {
4533
+ const fn = this.aborters.get(agentId);
4534
+ if (!fn) return false;
4535
+ fn();
4536
+ this.notify();
4537
+ return true;
4538
+ }
4539
+ get(agentId) {
4540
+ const entry = this.members.get(agentId);
4541
+ return entry ? { ...entry.info } : void 0;
4542
+ }
4543
+ bySession(sessionId) {
4544
+ const agentId = this.bySessionId.get(sessionId);
4545
+ return agentId ? this.get(agentId) : void 0;
4546
+ }
4547
+ list() {
4548
+ return [...this.members.values()].map((e) => e.info).sort((a, b) => a.startedAt - b.startedAt);
4549
+ }
4550
+ inboxOf(agentId) {
4551
+ return this.members.get(agentId)?.inbox;
4552
+ }
4553
+ inboxBySession(sessionId) {
4554
+ const agentId = this.bySessionId.get(sessionId);
4555
+ return agentId ? this.inboxOf(agentId) : void 0;
4556
+ }
4557
+ registerSession(sessionId) {
4558
+ if (this.sessions.has(sessionId)) return;
4559
+ this.sessions.add(sessionId);
4560
+ this.notify();
4561
+ }
4562
+ hasSession(sessionId) {
4563
+ return this.sessions.has(sessionId);
4564
+ }
4565
+ beginSessionTurn(sessionId) {
4566
+ this.activeTurns.set(sessionId, (this.activeTurns.get(sessionId) ?? 0) + 1);
4567
+ }
4568
+ endSessionTurn(sessionId) {
4569
+ const n = this.activeTurns.get(sessionId);
4570
+ if (n === void 0) return;
4571
+ if (n <= 1) {
4572
+ this.activeTurns.delete(sessionId);
4573
+ this.wokenSessions.delete(sessionId);
4574
+ return;
4575
+ }
4576
+ this.activeTurns.set(sessionId, n - 1);
4577
+ }
4578
+ isSessionActive(sessionId) {
4579
+ return this.activeTurns.has(sessionId);
4580
+ }
4581
+ setSessionBridge(bridge) {
4582
+ this.bridge = bridge;
4583
+ }
4584
+ async wakeSession(sessionId, text) {
4585
+ if (!this.bridge) {
4586
+ return {
4587
+ ok: false,
4588
+ reason: "\u8FD9\u4E2A\u5BBF\u4E3B\u4E0D\u652F\u6301\u5524\u9192\u522B\u7684\u4F1A\u8BDD\uFF08CLI \u5355\u4F1A\u8BDD\u6A21\u5F0F\uFF09\u3002\u8BA9\u5B83\u81EA\u5DF1\u53D1\u4E00\u53E5\u8BDD\u624D\u80FD\u63A5\u4E0A"
4589
+ };
4590
+ }
4591
+ const now = Date.now();
4592
+ this.reapWokenSessions(now);
4593
+ if (this.wokenSessions.has(sessionId)) {
4594
+ return {
4595
+ ok: false,
4596
+ reason: `${sessionId} \u521A\u88AB\u53EB\u8D77\u6765\uFF0C\u8FD8\u6CA1\u771F\u6B63\u5F00\u8DD1 \u2014\u2014 \u522B\u91CD\u590D\u53EB\u3002\u770B\u5B83\u7B54\u4E86\u4EC0\u4E48\uFF1Asession_messages_read ${sessionId}`
4597
+ };
4598
+ }
4599
+ if (this.wokenSessions.size >= this.limits.maxWokenSessions) {
4600
+ return {
4601
+ ok: false,
4602
+ reason: `\u73B0\u5728\u5DF2\u7ECF\u6709 ${this.wokenSessions.size} \u6BB5\u88AB\u53EB\u9192\u7684\u4F1A\u8BDD\u5728\u8DD1\uFF08\u4E0A\u9650 ${this.limits.maxWokenSessions} \u6BB5\uFF09\u2014\u2014 \u7B49\u5176\u4E2D\u4E00\u6BB5\u8DD1\u5B8C\u518D\u53EB\u4E0B\u4E00\u4E2A\uFF0C\u6216\u8005\u628A\u5B83\u4EEC\u8981\u5E72\u7684\u4E8B\u5199\u8FDB\u4F60\u81EA\u5DF1\u7684\u7ED3\u8BBA\u91CC`
4603
+ };
4604
+ }
4605
+ const r = await this.bridge.wake(sessionId, text);
4606
+ if (r.ok) this.wokenSessions.set(sessionId, now);
4607
+ return r;
4608
+ }
4609
+ reapWokenSessions(now) {
4610
+ for (const [id, at] of this.wokenSessions) {
4611
+ if (!this.activeTurns.has(id) && now - at > WAKE_RAMP_MS) this.wokenSessions.delete(id);
4612
+ }
4613
+ }
4614
+ get memberLimit() {
4615
+ return this.limits.maxRunningMembers;
4616
+ }
4617
+ availableMemberSlots(parentSessionId) {
4618
+ let running = 0;
4619
+ for (const entry of this.members.values()) {
4620
+ if (entry.info.parentSessionId === parentSessionId && entry.info.status === "running") {
4621
+ running += 1;
4622
+ }
4623
+ }
4624
+ return Math.max(0, this.limits.maxRunningMembers - running);
4625
+ }
4626
+ sessionExists(sessionId) {
4627
+ if (this.bridge) return this.bridge.exists(sessionId);
4628
+ return this.sessions.has(sessionId);
4629
+ }
4630
+ sessionTitle(sessionId) {
4631
+ return this.bridge?.title?.(sessionId);
4632
+ }
4633
+ sessionIds() {
4634
+ return [...this.sessions];
4635
+ }
4636
+ mainInbox(sessionId) {
4637
+ let inbox = this.mainInboxes.get(sessionId);
4638
+ if (!inbox) {
4639
+ inbox = new AgentInbox(this.inboxCapacity);
4640
+ this.mainInboxes.set(sessionId, inbox);
4641
+ }
4642
+ return inbox;
4643
+ }
4644
+ setActivity(agentId, line) {
4645
+ const entry = this.members.get(agentId);
4646
+ if (!entry) return;
4647
+ entry.info.activity = line;
4648
+ }
4649
+ markRunning(agentId) {
4650
+ const entry = this.members.get(agentId);
4651
+ if (!entry) return;
4652
+ entry.info.status = "running";
4653
+ delete entry.info.finishedAt;
4654
+ delete entry.info.activity;
4655
+ this.notify();
4656
+ }
4657
+ markFinished(agentId, status) {
4658
+ const entry = this.members.get(agentId);
4659
+ if (!entry) return;
4660
+ if (entry.info.finishedAt !== void 0) return;
4661
+ entry.info.status = status;
4662
+ entry.info.finishedAt = Date.now();
4663
+ this.aborters.delete(agentId);
4664
+ this.notify();
4665
+ }
4666
+ deliver(msg) {
4667
+ if (msg.to === LEAD_AGENT_ID) {
4668
+ const sender = this.members.get(msg.from);
4669
+ if (sender) {
4670
+ const parent = sender.info.parentSessionId;
4671
+ this.mainInbox(parent).push(msg);
4672
+ this.notify();
4673
+ return { ok: true, to: msg.to, status: this.isSessionActive(parent) ? "running" : "idle" };
4674
+ }
4675
+ return { ok: false, to: msg.to, reason: `\u4E3B\u4F1A\u8BDD\u4E0D\u80FD\u53D1\u7ED9 ${LEAD_AGENT_ID}` };
4676
+ }
4677
+ const entry = this.members.get(msg.to);
4678
+ if (entry) {
4679
+ if (entry.info.status === "finalized" || entry.info.status === "failed") {
4680
+ return {
4681
+ ok: false,
4682
+ to: msg.to,
4683
+ reason: `${msg.to} \u5DF2\u7ECF\u6536\u5DE5\u4E86\uFF08${entry.info.status}\uFF09\uFF0C\u6D88\u606F\u6CA1\u9001\u51FA\u53BB \u2014\u2014 \u5B83\u4E0D\u4F1A\u6709\u4E0B\u4E00\u8F6E\u6765\u8BFB`
4684
+ };
4685
+ }
4686
+ entry.inbox.push(msg);
4687
+ this.notify();
4688
+ return { ok: true, to: msg.to, status: entry.info.status };
4689
+ }
4690
+ if (this.isSessionActive(msg.to)) {
4691
+ this.mainInbox(msg.to).push(msg);
4692
+ this.notify();
4693
+ return { ok: true, to: msg.to, status: "running" };
4694
+ }
4695
+ if (this.sessionExists(msg.to)) {
4696
+ const senderIsMember = this.members.has(msg.from);
4697
+ return {
4698
+ ok: false,
4699
+ to: msg.to,
4700
+ reason: senderIsMember ? `${msg.to} \u73B0\u5728\u6CA1\u5728\u8DD1\uFF0C\u4E0B\u4E00\u8F6E\u4E0D\u4F1A\u6765 \u2014\u2014 \u8FD9\u6761\u6D88\u606F\u6CA1\u9001\u51FA\u53BB\u3002\u4F60\u53EB\u4E0D\u9192\u522B\u7684\u4F1A\u8BDD\uFF08\u6210\u5458\u62FF\u4E0D\u5230 followup_task\uFF09\uFF1A\u8981\u7D27\u7684\u8BDD\u5199\u8FDB\u4F60\u8FD9\u4E00\u8F6E\u7684\u7ED3\u8BBA\u91CC\uFF0C\u6D3E\u4F60\u51FA\u6765\u7684\u4F1A\u8BDD\u4F1A\u770B\u5230` : `${msg.to} \u73B0\u5728\u6CA1\u5728\u8DD1\uFF0C\u4E0B\u4E00\u8F6E\u4E0D\u4F1A\u6765 \u2014\u2014 \u8FD9\u6761\u6D88\u606F\u6CA1\u9001\u51FA\u53BB\u3002\u8981\u7528 followup_task \u628A\u5B83\u53EB\u8D77\u6765\u8DD1\u4E00\u8F6E\uFF08agentId \u586B ${msg.to}\uFF0Cmessage \u586B\u4F60\u8981\u8BF4\u7684\u8BDD\uFF09`
4701
+ };
4702
+ }
4703
+ return {
4704
+ ok: false,
4705
+ to: msg.to,
4706
+ reason: `\u6CA1\u6709\u8FD9\u4E2A\u6210\u5458\u6216\u4F1A\u8BDD\uFF1A${msg.to}\u3002\u7528 list_agents --all \u770B\u73B0\u5728\u6709\u8C01`
4707
+ };
4708
+ }
4709
+ static message(args) {
4710
+ return {
4711
+ id: randomUUID(),
4712
+ from: args.from,
4713
+ to: args.to,
4714
+ text: args.text,
4715
+ sentAt: Date.now(),
4716
+ ...args.fromLabel ? { fromLabel: args.fromLabel } : {}
4717
+ };
4718
+ }
4719
+ };
4720
+ // src/tools/builtin/send-message.ts
4721
+ var SEND_MESSAGE_TOOL = "send_message";
4722
+ function createSendMessageTool(team) {
4723
+ return {
4724
+ name: SEND_MESSAGE_TOOL,
4725
+ description: [
4726
+ "\u7ED9\u53E6\u4E00\u4E2A agent \u6216**\u6B63\u6709\u4E00\u6BB5\u5728\u8DD1\u7684\u4E3B\u4F1A\u8BDD**\u53D1\u4E00\u6761\u6D88\u606F\u3002**\u4E0D\u662F\u6D3E\u6D3B** \u2014\u2014 \u4E0D\u4F1A\u65B0\u5F00\u6210\u5458\u3001\u4E0D\u4F1A\u7B49\u5B83\u4EA4\u7ED3\u8BBA\u3002",
4727
+ "\u53D1\u7ED9\u6B63\u5728\u8DD1\u7684\u6210\u5458\uFF08\u5B50 agent\uFF09\uFF1A\u5B83\u5728\u4E0B\u4E00\u6B65\u5C31\u6536\u5230\uFF0C\u5F53\u8F6E\u5C31\u80FD\u636E\u6B64\u6539\u53D8\u884C\u4E3A\u3002",
4728
+ `\u53D1\u7ED9 \`${LEAD_AGENT_ID}\`\uFF08\u6D3E\u4F60\u51FA\u6765\u7684\u90A3\u4E2A\u4F1A\u8BDD\uFF09\uFF1A\u5B83\u5728\u8DD1\u65F6\u63A5\u4E0B\u6765\u7684\u6B65\u9AA4\u91CC\u4F1A\u770B\u5230\uFF1B\u5B83\u6CA1\u5728\u8DD1\u65F6\u8FD9\u6761\u53EA\u662F\u6392\u8FDB\u5B83\u7684\u6536\u4EF6\u7BB1\uFF0C\u7B49\u5B83\u4E0B\u6B21\u8DD1\u8D77\u6765\u624D\u8BFB\u5F97\u5230\uFF08\u4F60\u73B0\u5728\u7B49\u4E0D\u5230\u56DE\u97F3\uFF09\u3002`,
4729
+ "\u53D1\u7ED9**\u53E6\u4E00\u6BB5\u4E3B\u4F1A\u8BDD**\uFF08\u7528 list_agents --all \u770B\u5230\u7684\u90A3\u4E2A sessionId\uFF09\uFF1A\u53EA\u6709\u5B83**\u6B64\u523B\u6B63\u5728\u8DD1**\u624D\u9001\u5F97\u5230\u3002",
4730
+ "\u5BF9\u65B9\u6CA1\u5728\u8DD1\uFF08\u4F11\u7720 / \u5DF2\u7ECF\u6536\u5DE5\uFF09\u4F1A\u5F53\u573A\u5931\u8D25\uFF08\u53D1\u7ED9 lead \u90A3\u4E00\u6761\u9664\u5916\uFF0C\u5B83\u6392\u961F\uFF09\u2014\u2014 \u90A3\u79CD\u60C5\u51B5\u7528 followup_task \u628A\u5B83\u53EB\u8D77\u6765\u8DD1\u4E00\u8F6E\uFF0C\u522B\u5E72\u7B49\u3002",
4731
+ "\u7528 list_agents \u770B\u672C\u4F1A\u8BDD\u7684\u6210\u5458\uFF1B\u52A0 --all \u770B\u6240\u6709\u4F1A\u8BDD\u548C\u6210\u5458\u3002"
4732
+ ].join("\n"),
4733
+ parameters: {
4734
+ type: "object",
4735
+ properties: {
4736
+ to: {
4737
+ type: "string",
4738
+ description: `\u6536\u4EF6\u4EBA\uFF1A\u67D0\u4E2A\u6210\u5458\u7684 id\uFF0C\u6216 \`${LEAD_AGENT_ID}\``
4739
+ },
4740
+ text: {
4741
+ type: "string",
4742
+ description: "\u8981\u8BF4\u4EC0\u4E48\u3002\u5199\u6E05\u695A\u4F60\u8981\u5BF9\u65B9\u505A\u4EC0\u4E48\u3001\u4E3A\u4EC0\u4E48 \u2014\u2014 \u5B83\u770B\u4E0D\u5230\u4F60\u8FD9\u8FB9\u53D1\u751F\u4E86\u4EC0\u4E48"
4743
+ }
4744
+ },
4745
+ required: ["to", "text"]
4746
+ },
4747
+ exposure: ToolExposure.Direct,
4748
+ supportsParallel: false,
4749
+ operation: "file_read",
4750
+ annotations: {
4751
+ readOnlyHint: true,
4752
+ destructiveHint: false,
4753
+ idempotentHint: false,
4754
+ openWorldHint: false
4755
+ },
4756
+ describeTarget: (args) => String(args["to"] ?? ""),
4757
+ async execute(args, ctx) {
4758
+ const start = Date.now();
4759
+ const to = typeof args["to"] === "string" ? args["to"].trim() : "";
4760
+ const text = typeof args["text"] === "string" ? args["text"].trim() : "";
4761
+ if (!to) {
4762
+ return {
4763
+ success: false,
4764
+ output: "",
4765
+ error: {
4766
+ code: 7101,
4767
+ message: "\u7F3A\u5C11\u6536\u4EF6\u4EBA\uFF08to\uFF09",
4768
+ suggestion: `\u586B\u4E00\u4E2A\u6210\u5458 id\uFF0C\u6216 \`${LEAD_AGENT_ID}\``
4769
+ },
4770
+ duration: Date.now() - start
4771
+ };
4772
+ }
4773
+ if (!text) {
4774
+ return {
4775
+ success: false,
4776
+ output: "",
4777
+ error: { code: 7102, message: "\u6D88\u606F\u5185\u5BB9\uFF08text\uFF09\u662F\u7A7A\u7684" },
4778
+ duration: Date.now() - start
4779
+ };
4780
+ }
4781
+ const memberInfo = team.bySession(ctx.sessionId);
4782
+ const target = team.get(to);
4783
+ const ownMember = target !== void 0 && target.parentSessionId === ctx.sessionId;
4784
+ const from = memberInfo ? memberInfo.agentId : ownMember ? LEAD_AGENT_ID : ctx.sessionId;
4785
+ const labelled = from === ctx.sessionId ? sessionSenderLabel(from, team.sessionTitle(from)) : "";
4786
+ const result = team.deliver(
4787
+ TeamRegistry.message({
4788
+ from,
4789
+ to,
4790
+ text,
4791
+ ...labelled && labelled !== from ? { fromLabel: labelled } : {}
4792
+ })
4793
+ );
4794
+ if (!result.ok) {
4795
+ return {
4796
+ success: false,
4797
+ output: "",
4798
+ error: { code: 7103, message: result.reason },
4799
+ duration: Date.now() - start
4800
+ };
4801
+ }
4802
+ if (result.status !== "running") {
4803
+ const who = result.to === LEAD_AGENT_ID ? "lead" : result.to;
4804
+ return {
4805
+ success: true,
4806
+ output: `\u5DF2\u6392\u8FDB ${who} \u7684\u6536\u4EF6\u7BB1\uFF0C\u4F46\u5B83\u73B0\u5728\u6CA1\u5728\u8DD1 \u2014\u2014 \u8FD9\u6761\u8981\u7B49\u5B83\u4E0B\u6B21\u8DD1\u8D77\u6765\u624D\u4F1A\u88AB\u8BFB\u5230\uFF0C\u4F60\u73B0\u5728\u7B49\u4E0D\u5230\u56DE\u97F3\u3002` + (result.to === LEAD_AGENT_ID ? "\u8981\u7D27\u7684\u8BDD\u4E5F\u5199\u8FDB\u4F60\u8FD9\u4E00\u8F6E\u7684\u7ED3\u8BBA\u91CC\u3002" : ""),
4807
+ duration: Date.now() - start
4808
+ };
4809
+ }
4810
+ return {
4811
+ success: true,
4812
+ output: result.to === LEAD_AGENT_ID ? `\u5DF2\u9001\u5230 lead\uFF0C\u5B83\u63A5\u4E0B\u6765\u7684\u6B65\u9AA4\u91CC\u4F1A\u770B\u5230\u3002` : `\u5DF2\u9001\u5230 ${result.to}\uFF0C\u5B83\u6B63\u5728\u8DD1\u7684\u90A3\u4E00\u8F6E\u4F1A\u770B\u5230\u3002`,
4813
+ duration: Date.now() - start
4814
+ };
4815
+ }
4816
+ };
4817
+ }
4818
+ function err(code, message, suggestion) {
4819
+ return {
4820
+ success: false,
4821
+ output: "",
4822
+ error: { code, message, ...{} },
4823
+ duration: 0
4824
+ };
4825
+ }
4826
+ function ok2(output) {
4827
+ return { success: true, output, duration: 0 };
4828
+ }
4829
+ function str2(args, key) {
4830
+ const v = args[key];
4831
+ return typeof v === "string" ? v.trim() : "";
4832
+ }
4833
+ function parseTarget(raw) {
4834
+ const t83 = raw.trim();
4835
+ if (!t83) return null;
4836
+ return t83.startsWith("th-") ? { kind: "thread", id: t83 } : { kind: "channel", name: t83 };
4837
+ }
4838
+ function authorOf(deps, ctx) {
4839
+ return deps.agentOf(ctx.sessionId) ?? LEAD_AGENT_ID;
4840
+ }
4841
+ function renderPost(p) {
4842
+ const who = p.author;
4843
+ const when = new Date(p.createdAt).toISOString().slice(0, 16).replace("T", " ");
4844
+ const body2 = p.text.length > 2e3 ? `${p.text.slice(0, 2e3)}\u2026` : p.text;
4845
+ return `#${p.seq} [${p.id}] ${who} \xB7 ${when}
4846
+ ${body2}`;
4847
+ }
4848
+ function renderThread(t83) {
4849
+ return `- ${t83.id} ${t83.title} (${t83.postCount} \u5E16\uFF0C\u6700\u540E ${new Date(t83.lastPostAt).toISOString().slice(0, 16).replace("T", " ")})`;
4850
+ }
4851
+ function createBoardTools(store, deps) {
4852
+ const targetParam = {
4853
+ type: "string",
4854
+ description: "\u9891\u9053\u540D\uFF08\u5F00\u65B0\u7EBF\u7A0B\uFF09\uFF0C\u6216 `th-xxxxxxxx` \u8FD9\u6837\u7684\u7EBF\u7A0B id\uFF08\u56DE\u590D\u8FDB\u53BB\uFF09"
4855
+ };
4856
+ const tools = [
4857
+ {
4858
+ name: "get_channels",
4859
+ description: "\u5217\u51FA\u8BA8\u8BBA\u677F\u4E0A\u7684\u9891\u9053\u3002**\u8FD9\u5757\u677F\u662F\u8DE8\u8FDB\u7A0B\u5171\u4EAB\u7684** \u2014\u2014 \u4F60\u53E6\u4E00\u4E2A\u7A97\u53E3\u5EFA\u7684\u9891\u9053\u8FD9\u91CC\u4E5F\u770B\u5F97\u5230\u3002",
4860
+ parameters: { type: "object", properties: {}, required: [] },
4861
+ exposure: ToolExposure.Direct,
4862
+ supportsParallel: true,
4863
+ operation: "file_read",
4864
+ annotations: {
4865
+ readOnlyHint: true,
4866
+ destructiveHint: false,
4867
+ idempotentHint: true,
4868
+ openWorldHint: false
4869
+ },
4870
+ describeTarget: () => "\u9891\u9053\u5217\u8868",
4871
+ async execute() {
4872
+ const channels = store.listChannels();
4873
+ if (channels.length === 0) return ok2("\u8FD8\u6CA1\u6709\u9891\u9053\u3002\u7528 create_channel \u5EFA\u4E00\u4E2A\u3002");
4874
+ return ok2(
4875
+ channels.map((c) => `- ${c.name}${c.description ? `\uFF1A${c.description}` : ""}`).join("\n")
4876
+ );
4877
+ }
4878
+ },
4879
+ {
4880
+ name: "create_channel",
4881
+ description: "\u5EFA\u4E00\u4E2A\u9891\u9053\u3002\u5DF2\u5B58\u5728\u7684\u8BDD\u539F\u6837\u8FD4\u56DE\u5B83\uFF08\u4E0D\u62A5\u9519\u3001\u4E0D\u6539\u63CF\u8FF0\uFF09\u3002",
4882
+ parameters: {
4883
+ type: "object",
4884
+ properties: {
4885
+ name: { type: "string", description: "\u9891\u9053\u540D\uFF0C\u5B57\u6BCD\u6570\u5B57 _ . -" },
4886
+ description: { type: "string", description: "\u8FD9\u4E2A\u9891\u9053\u662F\u5E72\u4EC0\u4E48\u7684" }
4887
+ },
4888
+ required: ["name"]
4889
+ },
4890
+ exposure: ToolExposure.Deferred,
4891
+ supportsParallel: false,
4892
+ operation: "file_read",
4893
+ annotations: {
4894
+ readOnlyHint: false,
4895
+ destructiveHint: false,
4896
+ idempotentHint: true,
4897
+ openWorldHint: false
4898
+ },
4899
+ describeTarget: (args) => String(args["name"] ?? ""),
4900
+ async execute(args, ctx) {
4901
+ const name = str2(args, "name");
4902
+ if (!name) return err(7401, "\u7F3A\u5C11 name");
4903
+ try {
4904
+ const description = str2(args, "description");
4905
+ const ch = store.createChannel({
4906
+ name,
4907
+ ...description ? { description } : {},
4908
+ by: authorOf(deps, ctx)
4909
+ });
4910
+ return ok2(`\u9891\u9053 ${ch.name} \u5C31\u7EEA${ch.description ? `\uFF1A${ch.description}` : ""}`);
4911
+ } catch (cause) {
4912
+ return err(7402, cause instanceof Error ? cause.message : String(cause));
4913
+ }
4914
+ }
4915
+ },
4916
+ {
4917
+ name: "upsert_channel",
4918
+ description: "\u6539\u4E00\u4E2A\u9891\u9053\u7684\u63CF\u8FF0\uFF08\u5E16\u5B50\u3001\u8BA2\u9605\u90FD\u4E0D\u52A8\uFF09\u3002\u4E0D\u5B58\u5728\u5C31\u5EFA\u51FA\u6765\u3002",
4919
+ parameters: {
4920
+ type: "object",
4921
+ properties: {
4922
+ name: { type: "string", description: "\u9891\u9053\u540D" },
4923
+ description: { type: "string", description: "\u65B0\u7684\u63CF\u8FF0" }
4924
+ },
4925
+ required: ["name", "description"]
4926
+ },
4927
+ exposure: ToolExposure.Deferred,
4928
+ supportsParallel: false,
4929
+ operation: "file_read",
4930
+ annotations: {
4931
+ readOnlyHint: false,
4932
+ destructiveHint: false,
4933
+ idempotentHint: true,
4934
+ openWorldHint: false
4935
+ },
4936
+ describeTarget: (args) => String(args["name"] ?? ""),
4937
+ async execute(args, ctx) {
4938
+ const name = str2(args, "name");
4939
+ const description = str2(args, "description");
4940
+ if (!name) return err(7403, "\u7F3A\u5C11 name");
4941
+ if (!description) return err(7404, "\u7F3A\u5C11 description");
4942
+ try {
4943
+ store.upsertChannel({ name, description, by: authorOf(deps, ctx) });
4944
+ return ok2(`\u9891\u9053 ${name} \u7684\u63CF\u8FF0\u5DF2\u66F4\u65B0\u3002`);
4945
+ } catch (cause) {
4946
+ return err(7405, cause instanceof Error ? cause.message : String(cause));
4947
+ }
4948
+ }
4949
+ },
4950
+ {
4951
+ name: "list_threads",
4952
+ description: "\u5217\u51FA\u67D0\u4E2A\u9891\u9053\u91CC\u7684\u7EBF\u7A0B\uFF0C\u6309\u6700\u540E\u6D3B\u52A8\u6392\u5E8F\u3002",
4953
+ parameters: {
4954
+ type: "object",
4955
+ properties: {
4956
+ channel: { type: "string", description: "\u9891\u9053\u540D" },
4957
+ limit: { type: "number", description: "\u6700\u591A\u51E0\u6761\uFF0C\u9ED8\u8BA4 20" }
4958
+ },
4959
+ required: ["channel"]
4960
+ },
4961
+ exposure: ToolExposure.Deferred,
4962
+ supportsParallel: true,
4963
+ operation: "file_read",
4964
+ annotations: {
4965
+ readOnlyHint: true,
4966
+ destructiveHint: false,
4967
+ idempotentHint: true,
4968
+ openWorldHint: false
4969
+ },
4970
+ describeTarget: (args) => String(args["channel"] ?? ""),
4971
+ async execute(args) {
4972
+ const channel = str2(args, "channel");
4973
+ if (!channel) return err(7406, "\u7F3A\u5C11 channel");
4974
+ if (!store.channel(channel)) return err(7407, `\u6CA1\u6709\u8FD9\u4E2A\u9891\u9053\uFF1A${channel}`);
4975
+ const limit = typeof args["limit"] === "number" ? Math.min(Math.max(1, args["limit"]), 200) : 20;
4976
+ const threads = store.listThreads(channel, limit);
4977
+ if (threads.length === 0) return ok2(`\u9891\u9053 ${channel} \u91CC\u8FD8\u6CA1\u6709\u7EBF\u7A0B\u3002`);
4978
+ return ok2(threads.map(renderThread).join("\n"));
4979
+ }
4980
+ },
4981
+ {
4982
+ name: "read_thread",
4983
+ description: "\u8BFB\u4E00\u4E2A\u7EBF\u7A0B\u91CC\u7684\u5E16\u5B50\uFF08\u6309\u65F6\u95F4\u6B63\u5E8F\uFF09\u3002**\u8BFB\u5B8C\u4F1A\u7528 markRead \u628A\u8BA2\u9605\u6E38\u6807\u63A8\u5230\u73B0\u5728** \u2014\u2014 \u4E0B\u6B21\u5C31\u4E0D\u4F1A\u518D\u62A5\u8FD9\u4E9B\u3002",
4984
+ parameters: {
4985
+ type: "object",
4986
+ properties: {
4987
+ threadId: { type: "string", description: "\u7EBF\u7A0B id\uFF08th- \u5F00\u5934\uFF09" },
4988
+ limit: { type: "number", description: "\u6700\u591A\u51E0\u6761\uFF0C\u9ED8\u8BA4 50" }
4989
+ },
4990
+ required: ["threadId"]
4991
+ },
4992
+ exposure: ToolExposure.Direct,
4993
+ supportsParallel: true,
4994
+ operation: "file_read",
4995
+ annotations: {
4996
+ readOnlyHint: false,
4997
+ destructiveHint: false,
4998
+ idempotentHint: false,
4999
+ openWorldHint: false
5000
+ },
5001
+ describeTarget: (args) => String(args["threadId"] ?? ""),
5002
+ async execute(args, ctx) {
5003
+ const threadId = str2(args, "threadId");
5004
+ if (!threadId) return err(7408, "\u7F3A\u5C11 threadId");
5005
+ const limit = typeof args["limit"] === "number" ? Math.min(Math.max(1, args["limit"]), 500) : 50;
5006
+ const posts = store.readThread(threadId, limit);
5007
+ if (posts.length === 0) {
5008
+ return ok2(`\u7EBF\u7A0B ${threadId} \u91CC\u6CA1\u6709\u5E16\u5B50\uFF08\u6216\u8005\u8FD9\u4E2A\u7EBF\u7A0B\u4E0D\u5B58\u5728\uFF09\u3002`);
5009
+ }
5010
+ store.markRead(authorOf(deps, ctx), { kind: "thread", id: threadId });
5011
+ return ok2(posts.map(renderPost).join("\n\n"));
5012
+ }
5013
+ },
5014
+ {
5015
+ name: "read_post",
5016
+ description: "\u8BFB\u4E00\u6761\u5E16\u5B50\u7684\u5168\u6587\uFF08`read_thread` \u4F1A\u622A\u65AD\u957F\u5E16\uFF09\u3002",
5017
+ parameters: {
5018
+ type: "object",
5019
+ properties: { postId: { type: "string", description: "\u5E16\u5B50 id\uFF08po- \u5F00\u5934\uFF09" } },
5020
+ required: ["postId"]
5021
+ },
5022
+ exposure: ToolExposure.Deferred,
5023
+ supportsParallel: true,
5024
+ operation: "file_read",
5025
+ annotations: {
5026
+ readOnlyHint: true,
5027
+ destructiveHint: false,
5028
+ idempotentHint: true,
5029
+ openWorldHint: false
5030
+ },
5031
+ describeTarget: (args) => String(args["postId"] ?? ""),
5032
+ async execute(args) {
5033
+ const id = str2(args, "postId");
5034
+ const p = store.readPost(id);
5035
+ if (!p) return err(7409, `\u6CA1\u6709\u8FD9\u6761\u5E16\u5B50\uFF1A${id}`);
5036
+ return ok2(renderPost(p));
5037
+ }
5038
+ },
5039
+ {
5040
+ name: "search_posts",
5041
+ description: "\u5728\u677F\u5B50\u7684\u5E16\u5B50\u91CC\u5168\u6587\u641C\u7D22\uFF08\u5B50\u4E32\u5339\u914D\uFF09\u3002\u53EF\u4EE5\u9650\u5B9A\u9891\u9053\u3002",
5042
+ parameters: {
5043
+ type: "object",
5044
+ properties: {
5045
+ query: { type: "string", description: "\u8981\u627E\u7684\u8BCD" },
5046
+ channel: { type: "string", description: "\u53EA\u5728\u8FD9\u4E2A\u9891\u9053\u91CC\u627E" },
5047
+ limit: { type: "number", description: "\u6700\u591A\u51E0\u6761\uFF0C\u9ED8\u8BA4 20" }
5048
+ },
5049
+ required: ["query"]
5050
+ },
5051
+ exposure: ToolExposure.Deferred,
5052
+ supportsParallel: true,
5053
+ operation: "file_read",
5054
+ annotations: {
5055
+ readOnlyHint: true,
5056
+ destructiveHint: false,
5057
+ idempotentHint: true,
5058
+ openWorldHint: false
5059
+ },
5060
+ describeTarget: (args) => String(args["query"] ?? ""),
5061
+ async execute(args) {
5062
+ const query = str2(args, "query");
5063
+ if (!query) return err(7410, "\u7F3A\u5C11 query");
5064
+ const channel = str2(args, "channel");
5065
+ const limit = typeof args["limit"] === "number" ? Math.min(Math.max(1, args["limit"]), 100) : 20;
5066
+ const posts = store.searchPosts(query, channel || void 0, limit);
5067
+ if (posts.length === 0) return ok2(`\u6CA1\u6709\u627E\u5230\u5305\u542B\u300C${query}\u300D\u7684\u5E16\u5B50\u3002`);
5068
+ return ok2(posts.map(renderPost).join("\n\n"));
5069
+ }
5070
+ },
5071
+ {
5072
+ name: "post",
5073
+ description: [
5074
+ "\u53D1\u4E00\u6761\u5E16\u5B50\u3002target \u662F\u9891\u9053\u540D\u5C31**\u5F00\u4E00\u4E2A\u65B0\u7EBF\u7A0B**\uFF0C\u662F th- \u5F00\u5934\u7684\u7EBF\u7A0B id \u5C31\u56DE\u590D\u8FDB\u53BB\u3002",
5075
+ "**\u4F1A\u81EA\u52A8\u8BA2\u9605\u4F60\u90A3\u6761**\uFF08\u6240\u4EE5\u4E4B\u540E\u522B\u4EBA\u7684\u56DE\u590D\u4F60\u4F1A\u6536\u5230\u63D0\u9192\uFF09\u3002",
5076
+ "\u60F3\u9759\u9ED8\u8BB0\u4E2A\u6D41\u6C34\uFF08\u4E0D\u901A\u77E5\u4EFB\u4F55\u4EBA\uFF09\u7528 append\u3002"
5077
+ ].join("\n"),
5078
+ parameters: {
5079
+ type: "object",
5080
+ properties: { target: targetParam, text: { type: "string", description: "\u5E16\u5B50\u6B63\u6587" } },
5081
+ required: ["target", "text"]
5082
+ },
5083
+ exposure: ToolExposure.Deferred,
5084
+ supportsParallel: false,
5085
+ operation: "file_read",
5086
+ annotations: {
5087
+ readOnlyHint: false,
5088
+ destructiveHint: false,
5089
+ idempotentHint: false,
5090
+ openWorldHint: false
5091
+ },
5092
+ describeTarget: (args) => String(args["target"] ?? ""),
5093
+ async execute(args, ctx) {
5094
+ const target = parseTarget(str2(args, "target"));
5095
+ const text = str2(args, "text");
5096
+ if (!target) return err(7411, "\u7F3A\u5C11 target");
5097
+ if (!text) return err(7412, "\u7F3A\u5C11 text");
5098
+ try {
5099
+ const r = store.post({ target, author: authorOf(deps, ctx), text });
5100
+ return ok2(`\u5DF2\u53D1\u5E16 ${r.post.id}\uFF08\u7EBF\u7A0B ${r.threadId}\uFF0C#${r.post.seq}\uFF09\u3002`);
5101
+ } catch (cause) {
5102
+ return err(7413, cause instanceof Error ? cause.message : String(cause));
5103
+ }
5104
+ }
5105
+ },
5106
+ {
5107
+ name: "append",
5108
+ description: [
5109
+ "**\u9759\u9ED8**\u8FFD\u52A0\u4E00\u6761\u5E16\u5B50\uFF1A\u4E0D\u4E3A\u4F5C\u8005\u5EFA\u8BA2\u9605\u3001\u4E5F\u4E0D\u63A8\u9001\u4EFB\u4F55\u901A\u77E5\u3002",
5110
+ "\u8D34\u8BC1\u636E\u3001\u8BB0\u6D41\u6C34\u7528\u5B83\u3002**\u8981\u5728\u8BA8\u8BBA\u91CC\u8BF4\u4E00\u53E5\u8BDD\u8BA9\u8BA2\u9605\u7684\u4EBA\u77E5\u9053\uFF0C\u7528 post\u3002**",
5111
+ "\u6CE8\u610F\uFF1A\u5DF2\u7ECF\u4E3B\u52A8 subscribe \u8FC7\u8FD9\u4E2A\u7EBF\u7A0B\u7684\u4EBA\u62C9\u53D6\u65F6**\u4ECD\u7136\u770B\u5F97\u5230**\u5B83 \u2014\u2014 \u8BA2\u9605\u5173\u7CFB\u662F\u8BFB\u8005\u81EA\u5DF1\u5B9A\u7684\uFF0C\u4E0D\u53D7\u53D1\u5E16\u5DE5\u5177\u5F71\u54CD\u3002"
5112
+ ].join("\n"),
5113
+ parameters: {
5114
+ type: "object",
5115
+ properties: { target: targetParam, text: { type: "string", description: "\u6B63\u6587" } },
5116
+ required: ["target", "text"]
5117
+ },
5118
+ exposure: ToolExposure.Deferred,
5119
+ supportsParallel: false,
5120
+ operation: "file_read",
5121
+ annotations: {
5122
+ readOnlyHint: false,
5123
+ destructiveHint: false,
5124
+ idempotentHint: false,
5125
+ openWorldHint: false
5126
+ },
5127
+ describeTarget: (args) => String(args["target"] ?? ""),
5128
+ async execute(args, ctx) {
5129
+ const target = parseTarget(str2(args, "target"));
5130
+ const text = str2(args, "text");
5131
+ if (!target) return err(7414, "\u7F3A\u5C11 target");
5132
+ if (!text) return err(7415, "\u7F3A\u5C11 text");
5133
+ try {
5134
+ const r = store.append({ target, author: authorOf(deps, ctx), text });
5135
+ return ok2(`\u5DF2\u8FFD\u52A0 ${r.post.id}\uFF08\u7EBF\u7A0B ${r.threadId}\uFF0C#${r.post.seq}\uFF09\u3002\u6CA1\u6709\u901A\u77E5\u4EFB\u4F55\u4EBA\u3002`);
5136
+ } catch (cause) {
5137
+ return err(7416, cause instanceof Error ? cause.message : String(cause));
5138
+ }
5139
+ }
5140
+ },
5141
+ {
5142
+ name: "subscribe",
5143
+ description: "\u8BA2\u9605\u4E00\u4E2A\u9891\u9053\u6216\u7EBF\u7A0B\u3002\u4E4B\u540E\u5B83\u6709\u4E86\u65B0\u5E16\uFF0C\u4F60\u4E0B\u4E00\u8F6E\u5F00\u5934\u4F1A\u6536\u5230\u4E00\u6761\u63D0\u9192\uFF08**\u4E0D\u4F1A\u5524\u9192\u4F60**\uFF09\u3002",
5144
+ parameters: {
5145
+ type: "object",
5146
+ properties: { target: { ...targetParam, description: "\u9891\u9053\u540D\u6216\u7EBF\u7A0B id" } },
5147
+ required: ["target"]
5148
+ },
5149
+ exposure: ToolExposure.Deferred,
5150
+ supportsParallel: false,
5151
+ operation: "file_read",
5152
+ annotations: {
5153
+ readOnlyHint: false,
5154
+ destructiveHint: false,
5155
+ idempotentHint: true,
5156
+ openWorldHint: false
5157
+ },
5158
+ describeTarget: (args) => String(args["target"] ?? ""),
5159
+ async execute(args, ctx) {
5160
+ const target = parseTarget(str2(args, "target"));
5161
+ if (!target) return err(7417, "\u7F3A\u5C11 target");
5162
+ store.subscribe(authorOf(deps, ctx), target);
5163
+ return ok2(`\u5DF2\u8BA2\u9605 ${str2(args, "target")}\u3002`);
5164
+ }
5165
+ },
5166
+ {
5167
+ name: "unsubscribe",
5168
+ description: "\u53D6\u6D88\u8BA2\u9605\u3002",
5169
+ parameters: {
5170
+ type: "object",
5171
+ properties: { target: { ...targetParam, description: "\u9891\u9053\u540D\u6216\u7EBF\u7A0B id" } },
5172
+ required: ["target"]
5173
+ },
5174
+ exposure: ToolExposure.Deferred,
5175
+ supportsParallel: false,
5176
+ operation: "file_read",
5177
+ annotations: {
5178
+ readOnlyHint: false,
5179
+ destructiveHint: false,
5180
+ idempotentHint: true,
5181
+ openWorldHint: false
5182
+ },
5183
+ describeTarget: (args) => String(args["target"] ?? ""),
5184
+ async execute(args, ctx) {
5185
+ const target = parseTarget(str2(args, "target"));
5186
+ if (!target) return err(7418, "\u7F3A\u5C11 target");
5187
+ const removed = store.unsubscribe(authorOf(deps, ctx), target);
5188
+ return ok2(
5189
+ removed ? `\u5DF2\u53D6\u6D88\u8BA2\u9605 ${str2(args, "target")}\u3002` : `\u672C\u6765\u5C31\u6CA1\u8BA2\u9605 ${str2(args, "target")}\u3002`
5190
+ );
5191
+ }
5192
+ }
5193
+ ];
5194
+ return tools;
5195
+ }
5196
+ var BOARD_TOOL_NAMES = Object.freeze([
5197
+ "create_channel",
5198
+ "upsert_channel",
5199
+ "get_channels",
5200
+ "list_threads",
5201
+ "search_posts",
5202
+ "read_thread",
5203
+ "read_post",
5204
+ "subscribe",
5205
+ "unsubscribe",
5206
+ "post",
5207
+ "append"
5208
+ ]);
5209
+ var TASK_STATUSES = ["pending", "in_progress", "done", "blocked"];
5210
+ var AGENT_ID_PATTERN = /^[A-Za-z0-9_-]{1,64}$/;
5211
+ function err2(code, message, suggestion) {
5212
+ return {
5213
+ success: false,
5214
+ output: "",
5215
+ error: { code, message, ...suggestion ? { suggestion } : {} },
5216
+ duration: 0
5217
+ };
5218
+ }
5219
+ function ok3(output, start = Date.now()) {
5220
+ return { success: true, output, duration: Date.now() - start };
5221
+ }
5222
+ function str3(args, key) {
5223
+ const v = args[key];
5224
+ return typeof v === "string" ? v.trim() : "";
5225
+ }
5226
+ function spawnTeammate(team, manager) {
5227
+ return {
5228
+ name: "spawn_teammate",
5229
+ description: [
5230
+ "\u6D3E\u4E00\u4E2A**\u5177\u540D**\u7684\u6210\u5458\u5230\u540E\u53F0\u53BB\u5E72\u4E00\u4EF6\u6D3B\u3002\u5B83\u8DD1\u7740\u7684\u65F6\u5019\u4F60\u80FD\u7528 send_message \u8DDF\u5B83\u8BF4\u8BDD\u3002",
5231
+ "\u548C delegate_task \u7684\u533A\u522B\uFF1Adelegate_task \u662F\u4E00\u6B21\u6027\u7684\uFF08\u6D3E\u5B8C\u7B49\u7ED3\u8BBA\uFF0C\u4E2D\u9014\u8BF4\u4E0D\u4E0A\u8BDD\uFF09\uFF1B",
5232
+ "\u8FD9\u4E2A\u6D3E\u51FA\u53BB\u7684\u6210\u5458\u6709\u540D\u5B57\u3001\u5728\u540E\u53F0\u8DD1\u3001**\u4E2D\u9014\u6536\u5F97\u5230\u4F60\u7684\u6D88\u606F**\uFF0C\u4E5F\u80FD\u88AB interrupt_agent \u6253\u65AD\u3002",
5233
+ "\u7528 list_agents \u770B\u73B0\u5728\u6709\u8C01\u3001\u5404\u81EA\u5728\u5E72\u4EC0\u4E48\uFF1Bteam_task_* \u90A3\u56DB\u4E2A\u5DE5\u5177\u7ED9\u5B83\u4EEC\u5206\u6D3B\u3002",
5234
+ "\u540C\u4E00\u4E2A\u4F1A\u8BDD\u6700\u591A\u540C\u65F6\u8DD1\u51E0\u4E2A\u6210\u5458\u662F\u6709\u4E0A\u9650\u7684\uFF08list_agents \u91CC\u6570 running \u90A3\u51E0\u6761\uFF09\uFF0C\u6EE1\u4E86\u4F1A\u6D3E\u4E0D\u51FA\u53BB \u2014\u2014 \u7B49\u4E00\u4E2A\u6536\u5DE5\uFF0C\u6216\u8005\u5148 interrupt_agent \u6536\u6389\u4E00\u4E2A\u3002"
5235
+ ].join("\n"),
5236
+ parameters: {
5237
+ type: "object",
5238
+ properties: {
5239
+ agentId: {
5240
+ type: "string",
5241
+ description: "\u6210\u5458\u540D\uFF0C\u5B57\u6BCD\u6570\u5B57\u4E0B\u5212\u7EBF\u8FDE\u5B57\u7B26\u3002**\u4E0D\u80FD\u91CD\u540D**\uFF0C\u4E4B\u540E send_message \u7528\u5B83\u5BFB\u5740"
5242
+ },
5243
+ goal: { type: "string", description: "\u8981\u5B83\u5B8C\u6210\u4EC0\u4E48\uFF0C\u5199\u5177\u4F53" },
5244
+ context: {
5245
+ type: "string",
5246
+ description: "\u5B8C\u6210\u8FD9\u4E2A\u4EFB\u52A1\u9700\u8981\u77E5\u9053\u7684\u80CC\u666F\uFF08\u5B83\u770B\u4E0D\u5230\u5F53\u524D\u5BF9\u8BDD\uFF09"
5247
+ }
5248
+ },
5249
+ required: ["agentId", "goal"]
5250
+ },
5251
+ exposure: ToolExposure.Deferred,
5252
+ supportsParallel: false,
5253
+ operation: "command",
5254
+ annotations: {
5255
+ readOnlyHint: false,
5256
+ destructiveHint: true,
5257
+ idempotentHint: false,
5258
+ openWorldHint: true
5259
+ },
5260
+ describeTarget: (args) => `${String(args["agentId"] ?? "")}: ${String(args["goal"] ?? "")}`,
5261
+ async execute(args, ctx) {
5262
+ const start = Date.now();
5263
+ const agentId = str3(args, "agentId");
5264
+ const goal = str3(args, "goal");
5265
+ const context = str3(args, "context");
5266
+ if (!AGENT_ID_PATTERN.test(agentId)) {
5267
+ return err2(
5268
+ 7201,
5269
+ `\u6210\u5458\u540D\u4E0D\u5408\u6CD5\uFF1A${agentId || "(\u7A7A)"}`,
5270
+ "\u53EA\u8BB8\u5B57\u6BCD\u3001\u6570\u5B57\u3001\u4E0B\u5212\u7EBF\u3001\u8FDE\u5B57\u7B26\uFF0C\u6700\u957F 64"
5271
+ );
5272
+ }
5273
+ if (!goal) return err2(7202, "\u7F3A\u5C11 goal");
5274
+ if (team.get(agentId)) {
5275
+ return err2(
5276
+ 7203,
5277
+ `\u5DF2\u7ECF\u6709\u4E00\u4E2A\u6210\u5458\u53EB ${agentId} \u4E86`,
5278
+ "\u6362\u4E00\u4E2A\u540D\u5B57\uFF0C\u6216\u8005\u76F4\u63A5 send_message \u7ED9\u5B83"
5279
+ );
5280
+ }
5281
+ const r = await manager.delegate(
5282
+ {
5283
+ tasks: [{ goal, ...context ? { context } : {}, agentId }],
5284
+ background: true,
5285
+ max_concurrent: 1
5286
+ },
5287
+ ctx.sessionId,
5288
+ ctx.signal
5289
+ );
5290
+ if (!r.success) return { ...err2(7204, r.output), duration: Date.now() - start };
5291
+ return ok3(
5292
+ [
5293
+ `\u5DF2\u6D3E\u51FA\u6210\u5458 ${agentId}\uFF08\u540E\u53F0\u4F5C\u4E1A ${r.jobId ?? "(\u65E0)"}\uFF09\u3002`,
5294
+ `\u8DDF\u5B83\u8BF4\u8BDD\uFF1Asend_message({ to: "${agentId}", text: "\u2026" })`,
5295
+ `\u770B\u5B83\u5728\u5E72\u4EC0\u4E48\uFF1Alist_agents\u3002\u6536\u6389\u5B83\uFF1Ainterrupt_agent({ agentId: "${agentId}" })`
5296
+ ].join("\n"),
5297
+ start
5298
+ );
5299
+ }
5300
+ };
5301
+ }
5302
+ function listAgents(team) {
5303
+ return {
5304
+ name: "list_agents",
5305
+ description: [
5306
+ "\u5217\u51FA\u56E2\u961F\u6210\u5458\u548C\u5B83\u4EEC\u7684\u72B6\u6001\u3002",
5307
+ "status \u662F running\uFF08\u6B63\u5728\u8DD1\uFF09/ finalized\uFF08\u8DD1\u5B8C\u4E86\uFF09/ failed\uFF08\u6302\u4E86\uFF09\u3002",
5308
+ "running \u7684\u6210\u5458\u80FD\u88AB send_message \u5F53\u8F6E\u6536\u5230\uFF1B\u6536\u5DE5\u7684\u6536\u4E0D\u5230\u3002",
5309
+ "",
5310
+ "\u9ED8\u8BA4\u53EA\u5217\u672C\u4F1A\u8BDD\u6D3E\u51FA\u7684\u6210\u5458\uFF08\u4F60\u81EA\u5DF1\u662F\u6210\u5458\u65F6\uFF1A\u540C\u4E00\u961F\u7684\u5176\u4ED6\u6210\u5458\uFF09\u3002",
5311
+ "\u52A0 --all \u53EF\u4EE5\u770B\u5230\u6240\u6709\u6D3B\u8DC3\u4F1A\u8BDD\u548C\u6210\u5458\u3002"
5312
+ ].join("\n"),
5313
+ parameters: {
5314
+ type: "object",
5315
+ properties: {
5316
+ all: {
5317
+ type: "boolean",
5318
+ description: "\u662F\u5426\u5217\u51FA\u6240\u6709\u6D3B\u8DC3\u4F1A\u8BDD\u548C\u6210\u5458\uFF08\u9ED8\u8BA4 false\uFF0C\u53EA\u5217\u672C\u4F1A\u8BDD\u6D3E\u51FA\u7684\uFF09"
5319
+ }
5320
+ },
5321
+ required: []
5322
+ },
5323
+ exposure: ToolExposure.Direct,
5324
+ supportsParallel: true,
5325
+ operation: "file_read",
5326
+ annotations: {
5327
+ readOnlyHint: true,
5328
+ destructiveHint: false,
5329
+ idempotentHint: true,
5330
+ openWorldHint: false
5331
+ },
5332
+ describeTarget: () => "\u56E2\u961F\u6210\u5458",
5333
+ async execute(args, ctx) {
5334
+ const showAll = args["all"] === true;
5335
+ const self = team.bySession(ctx.sessionId);
5336
+ const scopeParent = self?.parentSessionId ?? ctx.sessionId;
5337
+ const members = showAll ? team.list() : team.list().filter((m) => m.parentSessionId === scopeParent);
5338
+ const others = showAll ? team.sessionIds().filter((id) => id !== ctx.sessionId).map(
5339
+ (id) => `- ${id} [\u4F1A\u8BDD] ${team.isSessionActive(id) ? "running" : "idle"} \u2014 \u53E6\u4E00\u6BB5\u4E3B\u4F1A\u8BDD`
5340
+ ) : [];
5341
+ if (members.length === 0 && others.length === 0) {
5342
+ return ok3(
5343
+ showAll ? `\u8FD8\u6CA1\u6709\u4EFB\u4F55\u6210\u5458\u6216\u522B\u7684\u4F1A\u8BDD\u3002\u7528 spawn_teammate \u6216 delegate_task \u6D3E\u4E00\u4E2A\u3002` : `\u672C\u4F1A\u8BDD\u8FD8\u6CA1\u6D3E\u51FA\u4EFB\u4F55\u6210\u5458\u3002\u7528 spawn_teammate \u6216 delegate_task \u6D3E\u4E00\u4E2A\uFF0C\u6216\u52A0 --all \u770B\u6240\u6709\u4F1A\u8BDD\u3002`
5344
+ );
5345
+ }
5346
+ const lines = members.map((m) => {
5347
+ const bits = [`- ${m.agentId}`, m.status];
5348
+ if (m.role) bits.push(`[${m.role}]`);
5349
+ if (m.activity) bits.push(`\u2014 ${m.activity}`);
5350
+ return bits.join(" ");
5351
+ });
5352
+ const head = showAll ? `\u4F60\u662F ${ctx.sessionId}\u3002\u6210\u5458 ${members.length} \u4E2A\u3001\u522B\u7684\u4E3B\u4F1A\u8BDD ${others.length} \u4E2A\uFF1A` : `\u672C\u4F1A\u8BDD\u7684\u6210\u5458 ${members.length} \u4E2A\uFF08\u4F60\u662F ${ctx.sessionId}\uFF09\uFF1A`;
5353
+ return ok3([head, ...lines, ...others].join("\n"));
5354
+ }
5355
+ };
5356
+ }
5357
+ function waitAgent(team) {
5358
+ return {
5359
+ name: "wait_agent",
5360
+ description: [
5361
+ "\u7B49\u5230\u56E2\u961F\u91CC\u51FA\u73B0**\u4E0B\u4E00\u6B21\u53D8\u5316**\uFF08\u6709\u4EBA\u88AB\u6D3E\u51FA\u6765\u3001\u6709\u4EBA\u7ED9\u4F60\u53D1\u6D88\u606F\u3001\u4EFB\u52A1\u677F\u53D8\u4E86\uFF09\uFF0C\u6216\u8005\u7B49\u5230\u8D85\u65F6\u3002",
5362
+ "\u53EA\u544A\u8BC9\u4F60\u300C\u6709\u6CA1\u6709\u53D8\u300D\uFF0C**\u4E0D\u544A\u8BC9\u4F60\u53D8\u4E86\u4EC0\u4E48** \u2014\u2014 \u9192\u6765\u4E4B\u540E\u81EA\u5DF1 list_agents / team_task_list \u8BFB\u4E00\u904D\u3002",
5363
+ "\u9002\u5408\uFF1A\u6D3E\u5B8C\u6D3B\u4E4B\u540E\u7B49\u5B83\u4EEC\u5E72\u6D3B\uFF0C\u800C\u4E0D\u662F\u53CD\u590D\u8F6E\u8BE2\u3002"
5364
+ ].join("\n"),
5365
+ parameters: {
5366
+ type: "object",
5367
+ properties: {
5368
+ timeoutSec: {
5369
+ type: "number",
5370
+ description: "\u6700\u591A\u7B49\u591A\u4E45\uFF08\u79D2\uFF09\uFF0C1\u20133600\uFF0C\u9ED8\u8BA4 30"
5371
+ }
5372
+ },
5373
+ required: []
5374
+ },
5375
+ exposure: ToolExposure.Deferred,
5376
+ supportsParallel: false,
5377
+ operation: "file_read",
5378
+ annotations: {
5379
+ readOnlyHint: true,
5380
+ destructiveHint: false,
5381
+ idempotentHint: false,
5382
+ openWorldHint: false
5383
+ },
5384
+ describeTarget: () => "\u7B49\u5F85\u56E2\u961F\u53D8\u5316",
5385
+ async execute(args, ctx) {
5386
+ const raw = typeof args["timeoutSec"] === "number" ? args["timeoutSec"] : 30;
5387
+ const sec = Math.min(Math.max(Math.floor(raw), 1), 3600);
5388
+ const changed = await team.waitForChange(sec * 1e3, ctx.signal);
5389
+ if (ctx.signal?.aborted) return err2(7205, "\u7B49\u5F85\u88AB\u4E2D\u6B62\u4E86");
5390
+ return changed ? ok3("\u56E2\u961F\u6709\u53D8\u5316\u3002\u7528 list_agents \u6216 team_task_list \u770B\u73B0\u5728\u662F\u4EC0\u4E48\u60C5\u51B5\u3002") : ok3(`\u7B49\u4E86 ${sec} \u79D2\uFF0C\u6CA1\u6709\u53D8\u5316\u3002`);
5391
+ }
5392
+ };
5393
+ }
5394
+ function interruptAgent(team) {
5395
+ return {
5396
+ name: "interrupt_agent",
5397
+ description: [
5398
+ "\u6253\u65AD\u4E00\u4E2A\u6B63\u5728\u8DD1\u7684\u6210\u5458\uFF08\u5B83\u4F1A\u88AB\u4E2D\u6B62\uFF0C\u5DF2\u7ECF\u4EA7\u751F\u7684\u534A\u622A\u7ED3\u679C\u7559\u7740\uFF09\u3002",
5399
+ "\u6536\u5DE5\u4E86\u7684\u6210\u5458\u6253\u4E0D\u65AD \u2014\u2014 \u90A3\u79CD\u60C5\u51B5\u4F1A\u8FD4\u56DE false\uFF0C\u7528 list_agents \u786E\u8BA4\u3002"
5400
+ ].join("\n"),
5401
+ parameters: {
5402
+ type: "object",
5403
+ properties: {
5404
+ agentId: { type: "string", description: "\u8981\u6253\u65AD\u7684\u6210\u5458\u540D" }
5405
+ },
5406
+ required: ["agentId"]
5407
+ },
5408
+ exposure: ToolExposure.Deferred,
5409
+ supportsParallel: false,
5410
+ operation: "command",
5411
+ annotations: {
5412
+ readOnlyHint: false,
5413
+ destructiveHint: true,
5414
+ idempotentHint: false,
5415
+ openWorldHint: false
5416
+ },
5417
+ describeTarget: (args) => String(args["agentId"] ?? ""),
5418
+ async execute(args) {
5419
+ const agentId = str3(args, "agentId");
5420
+ if (!agentId) return err2(7206, "\u7F3A\u5C11 agentId");
5421
+ const member = team.get(agentId);
5422
+ if (!member) return err2(7207, `\u6CA1\u6709\u8FD9\u4E2A\u6210\u5458\uFF1A${agentId}`, "\u7528 list_agents \u770B\u5F53\u524D\u6709\u8C01");
5423
+ if (!team.interrupt(agentId)) {
5424
+ return err2(
5425
+ 7208,
5426
+ `${agentId} \u73B0\u5728\u6253\u4E0D\u65AD\uFF08${member.status}\uFF09`,
5427
+ member.status === "running" ? "\u5B83\u53EF\u80FD\u521A\u8DD1\u5B8C\uFF0C\u6216\u8005\u63A7\u5236\u5668\u8FD8\u6CA1\u63A5\u4E0A \u2014\u2014 \u518D list_agents \u770B\u4E00\u773C" : "\u5B83\u5DF2\u7ECF\u6536\u5DE5\u4E86"
5428
+ );
5429
+ }
5430
+ return ok3(`\u5DF2\u6253\u65AD ${agentId}\u3002`);
5431
+ }
5432
+ };
5433
+ }
5434
+ function taskCreate(team) {
5435
+ return {
5436
+ name: "team_task_create",
5437
+ description: [
5438
+ "\u5728\u5171\u4EAB\u4EFB\u52A1\u677F\u4E0A\u5EFA\u4E00\u6761\u4EFB\u52A1\u3002\u5168\u961F\u90FD\u770B\u5F97\u5230\u540C\u4E00\u4EFD\u3002",
5439
+ "dependsOn \u586B\u522B\u7684\u4EFB\u52A1 id\uFF08\u53EA\u80FD\u662F\u5DF2\u7ECF\u5B58\u5728\u7684\uFF09\u3002",
5440
+ "owner \u586B\u67D0\u4E2A\u6210\u5458\u540D\uFF0C\u8868\u793A\u8FD9\u6761\u5F52\u5B83\u3002"
5441
+ ].join("\n"),
5442
+ parameters: {
5443
+ type: "object",
5444
+ properties: {
5445
+ title: { type: "string", description: "\u4E00\u53E5\u8BDD\u8BF4\u660E\u8981\u505A\u4EC0\u4E48" },
5446
+ description: { type: "string", description: "\u7EC6\u8282" },
5447
+ owner: { type: "string", description: "\u5F52\u8C01\uFF08\u6210\u5458\u540D\uFF09" },
5448
+ dependsOn: {
5449
+ type: "array",
5450
+ items: { type: "string" },
5451
+ description: "\u4F9D\u8D56\u54EA\u4E9B\u4EFB\u52A1\u7684 id"
5452
+ }
5453
+ },
5454
+ required: ["title"]
5455
+ },
5456
+ exposure: ToolExposure.Deferred,
5457
+ supportsParallel: true,
5458
+ operation: "file_read",
5459
+ annotations: {
5460
+ readOnlyHint: false,
5461
+ destructiveHint: false,
5462
+ idempotentHint: false,
5463
+ openWorldHint: false
5464
+ },
5465
+ describeTarget: (args) => String(args["title"] ?? ""),
5466
+ async execute(args) {
5467
+ const title = str3(args, "title");
5468
+ if (!title) return err2(7301, "\u7F3A\u5C11 title");
5469
+ const dependsOn = Array.isArray(args["dependsOn"]) ? args["dependsOn"].map(String).filter(Boolean) : [];
5470
+ const description = str3(args, "description");
5471
+ const owner = str3(args, "owner");
5472
+ const r = team.tasks.create({
5473
+ title,
5474
+ ...description ? { description } : {},
5475
+ ...owner ? { owner } : {},
5476
+ ...dependsOn.length > 0 ? { dependsOn } : {}
5477
+ });
5478
+ if (!r.ok) return err2(7302, r.reason);
5479
+ return ok3(`\u5DF2\u5EFA\u4EFB\u52A1 ${r.task.id}\uFF08revision ${r.task.revision}\uFF09\uFF1A${r.task.title}`);
5480
+ }
5481
+ };
5482
+ }
5483
+ function taskList(team) {
5484
+ return {
5485
+ name: "team_task_list",
5486
+ description: "\u5217\u51FA\u5171\u4EAB\u4EFB\u52A1\u677F\u4E0A\u7684\u4EFB\u52A1\uFF0C\u53EF\u6309\u72B6\u6001\u6216 owner \u8FC7\u6EE4\u3002",
5487
+ parameters: {
5488
+ type: "object",
5489
+ properties: {
5490
+ status: { type: "string", enum: [...TASK_STATUSES], description: "\u53EA\u770B\u8FD9\u4E2A\u72B6\u6001" },
5491
+ owner: { type: "string", description: "\u53EA\u770B\u5F52\u8FD9\u4E2A\u6210\u5458\u7684" }
5492
+ },
5493
+ required: []
5494
+ },
5495
+ exposure: ToolExposure.Deferred,
5496
+ supportsParallel: true,
5497
+ operation: "file_read",
5498
+ annotations: {
5499
+ readOnlyHint: true,
5500
+ destructiveHint: false,
5501
+ idempotentHint: true,
5502
+ openWorldHint: false
5503
+ },
5504
+ describeTarget: () => "\u56E2\u961F\u4EFB\u52A1\u677F",
5505
+ async execute(args) {
5506
+ const status = str3(args, "status");
5507
+ if (status && !TASK_STATUSES.includes(status)) {
5508
+ return err2(7303, `\u4E0D\u8BA4\u8BC6\u7684\u72B6\u6001\uFF1A${status}`, `\u53EF\u7528\uFF1A${TASK_STATUSES.join(" / ")}`);
5509
+ }
5510
+ const owner = str3(args, "owner");
5511
+ const tasks = team.tasks.list({
5512
+ ...status ? { status } : {},
5513
+ ...owner ? { owner } : {}
5514
+ });
5515
+ if (tasks.length === 0) return ok3("\u677F\u5B50\u4E0A\u6CA1\u6709\u7B26\u5408\u6761\u4EF6\u7684\u4EFB\u52A1\u3002");
5516
+ const lines = tasks.map((t83) => {
5517
+ const bits = [`- ${t83.id}`, `[${t83.status}]`, t83.title, `rev ${t83.revision}`];
5518
+ if (t83.owner) bits.push(`\u2192 ${t83.owner}`);
5519
+ if (t83.dependsOn.length > 0) bits.push(`(\u7B49 ${t83.dependsOn.join(", ")})`);
5520
+ return bits.join(" ");
5521
+ });
5522
+ return ok3(`\u5171 ${tasks.length} \u6761\uFF1A
5523
+ ${lines.join("\n")}`);
5524
+ }
5525
+ };
5526
+ }
5527
+ function taskGet(team) {
5528
+ return {
5529
+ name: "team_task_get",
5530
+ description: "\u8BFB\u4E00\u6761\u4EFB\u52A1\u7684\u5B8C\u6574\u5185\u5BB9\uFF08\u542B revision \u2014\u2014 \u6539\u4E4B\u524D\u5148\u8BFB\u5B83\uFF09\u3002",
5531
+ parameters: {
5532
+ type: "object",
5533
+ properties: { id: { type: "string", description: "\u4EFB\u52A1 id" } },
5534
+ required: ["id"]
5535
+ },
5536
+ exposure: ToolExposure.Deferred,
5537
+ supportsParallel: true,
5538
+ operation: "file_read",
5539
+ annotations: {
5540
+ readOnlyHint: true,
5541
+ destructiveHint: false,
5542
+ idempotentHint: true,
5543
+ openWorldHint: false
5544
+ },
5545
+ describeTarget: (args) => String(args["id"] ?? ""),
5546
+ async execute(args) {
5547
+ const id = str3(args, "id");
5548
+ const t83 = team.tasks.get(id);
5549
+ if (!t83) return err2(7304, `\u6CA1\u6709\u8FD9\u4E2A\u4EFB\u52A1\uFF1A${id}`, "\u7528 team_task_list \u770B\u6709\u54EA\u4E9B");
5550
+ return ok3(
5551
+ [
5552
+ `${t83.id} [${t83.status}] revision ${t83.revision}`,
5553
+ `\u6807\u9898\uFF1A${t83.title}`,
5554
+ t83.description ? `\u7EC6\u8282\uFF1A${t83.description}` : "",
5555
+ t83.owner ? `\u5F52\u5C5E\uFF1A${t83.owner}` : "\u5F52\u5C5E\uFF1A\uFF08\u65E0\uFF09",
5556
+ t83.dependsOn.length > 0 ? `\u4F9D\u8D56\uFF1A${t83.dependsOn.join(", ")}` : "\u4F9D\u8D56\uFF1A\u65E0"
5557
+ ].filter(Boolean).join("\n")
5558
+ );
5559
+ }
5560
+ };
5561
+ }
5562
+ function taskUpdate(team) {
5563
+ return {
5564
+ name: "team_task_update",
5565
+ description: [
5566
+ "\u6539\u4E00\u6761\u4EFB\u52A1\u3002**\u6539\u4E4B\u524D\u5148 team_task_get \u62FF\u5230 revision\uFF0C\u539F\u6837\u586B\u8FDB expectedRevision**\u3002",
5567
+ "\u522B\u4EBA\u5728\u8FD9\u671F\u95F4\u52A8\u8FC7\u5B83\u7684\u8BDD\uFF0C\u8FD9\u6B21\u5199\u5165\u4F1A\u88AB**\u6574\u7B14\u62D2\u7EDD**\u5E76\u544A\u8BC9\u4F60\u73B0\u5728\u662F\u51E0 \u2014\u2014",
5568
+ "\u91CD\u8BFB\u4E00\u904D\u518D\u51B3\u5B9A\uFF0C\u522B\u731C\u3002\u4E0D\u586B expectedRevision \u5C31\u662F\u4E0D\u68C0\u67E5\uFF08\u53EA\u5728\u4F60\u786E\u5B9A\u81EA\u5DF1\u662F\u552F\u4E00\u5199\u8005\u65F6\u7528\uFF09\u3002"
5569
+ ].join("\n"),
5570
+ parameters: {
5571
+ type: "object",
5572
+ properties: {
5573
+ id: { type: "string", description: "\u4EFB\u52A1 id" },
5574
+ expectedRevision: {
5575
+ type: "number",
5576
+ description: "\u4F60\u4E0A\u6B21\u8BFB\u5230\u7684 revision\u3002\u5BF9\u4E0D\u4E0A\u5C31\u62D2\u7EDD\u6574\u7B14\u5199\u5165"
5577
+ },
5578
+ title: { type: "string" },
5579
+ description: { type: "string" },
5580
+ status: { type: "string", enum: [...TASK_STATUSES] },
5581
+ owner: { type: "string", description: "\u6539\u6210\u5F52\u8C01" }
4194
5582
  },
4195
- required: ["action"]
5583
+ required: ["id"]
4196
5584
  },
4197
- exposure: ToolExposure.Direct,
5585
+ exposure: ToolExposure.Deferred,
4198
5586
  supportsParallel: false,
5587
+ operation: "file_read",
4199
5588
  annotations: {
4200
5589
  readOnlyHint: false,
4201
- destructiveHint: true,
5590
+ destructiveHint: false,
4202
5591
  idempotentHint: false,
4203
5592
  openWorldHint: false
4204
5593
  },
4205
- operation: "file_read",
4206
- describeTarget: (args) => `schedule_draft:${String(args["action"] ?? "list")}`,
4207
- async execute(rawArgs, ctx) {
4208
- const startedAt = Date.now();
4209
- const action = rawArgs["action"];
4210
- if (action === "list") {
4211
- const rows = deps.list();
4212
- return say4(
4213
- rows.length === 0 ? "\u4E00\u6761\u5B9A\u65F6\u4EFB\u52A1\u90FD\u8FD8\u6CA1\u6709\u3002\u8981\u65B0\u5EFA\u5C31\u7528 action=create\u3002" : `\u73B0\u6709 ${rows.length} \u6761\uFF1A
4214
- ${rows.map(describeRow).join("\n")}`,
4215
- true,
4216
- startedAt
4217
- );
5594
+ describeTarget: (args) => String(args["id"] ?? ""),
5595
+ async execute(args) {
5596
+ const id = str3(args, "id");
5597
+ if (!id) return err2(7305, "\u7F3A\u5C11 id");
5598
+ const status = str3(args, "status");
5599
+ if (status && !TASK_STATUSES.includes(status)) {
5600
+ return err2(7306, `\u4E0D\u8BA4\u8BC6\u7684\u72B6\u6001\uFF1A${status}`, `\u53EF\u7528\uFF1A${TASK_STATUSES.join(" / ")}`);
4218
5601
  }
4219
- const parsed = parseScheduleDraft(rawArgs);
4220
- if (!parsed.ok) return say4(parsed.message, false, startedAt);
4221
- const draft = parsed.value;
4222
- const current = draft.action === "update" ? deps.get(draft.id) : void 0;
4223
- if (draft.action === "update" && current === void 0) {
4224
- return say4(
4225
- `\u6CA1\u6709 id \u4E3A ${draft.id} \u7684\u4EFB\u52A1\u3002\u5148\u7528 action=list \u770B\u4E00\u773C\u73B0\u6709\u7684\u3002`,
4226
- false,
4227
- startedAt
5602
+ const patch = {};
5603
+ const title = str3(args, "title");
5604
+ const description = str3(args, "description");
5605
+ const owner = str3(args, "owner");
5606
+ if (title) patch.title = title;
5607
+ if (description) patch.description = description;
5608
+ if (status) patch.status = status;
5609
+ if (owner) patch.owner = owner;
5610
+ if (Object.keys(patch).length === 0) return err2(7307, "\u4E00\u4E2A\u5B57\u6BB5\u90FD\u6CA1\u7ED9\uFF0C\u6CA1\u4EC0\u4E48\u53EF\u6539\u7684");
5611
+ const expected = typeof args["expectedRevision"] === "number" ? args["expectedRevision"] : void 0;
5612
+ const r = team.tasks.update(id, patch, expected);
5613
+ if (!r.ok) return err2(7308, r.reason);
5614
+ return ok3(`\u5DF2\u66F4\u65B0 ${r.task.id}\uFF08revision ${r.task.revision}\uFF0C\u72B6\u6001 ${r.task.status}\uFF09\u3002`);
5615
+ }
5616
+ };
5617
+ }
5618
+ function followupTask(team, manager) {
5619
+ return {
5620
+ name: "followup_task",
5621
+ description: [
5622
+ "\u53EB\u9192\u4E00\u4E2A**\u6CA1\u5728\u8DD1**\u7684\u5BF9\u65B9\uFF0C\u8BA9\u5B83\u5E26\u7740\u4E0A\u4E00\u6B21\u7684\u5168\u90E8\u4E0A\u4E0B\u6587\u518D\u8DD1\u4E00\u8F6E\u3002",
5623
+ "\u5BF9\u8C61\u53EF\u4EE5\u662F\uFF1A\u5DF2\u7ECF\u6536\u5DE5\u7684\u6210\u5458\uFF08list_agents \u91CC\u7684 agentId\uFF09\uFF0C\u6216\u8005**\u53E6\u4E00\u6BB5\u4E3B\u4F1A\u8BDD**\uFF08list_agents --all \u91CC\u7684 sessionId\uFF09\u3002",
5624
+ "\u548C send_message \u7684\u5206\u5DE5\uFF1Asend_message \u53EA\u5728\u5BF9\u65B9**\u6B63\u5728\u8DD1**\u7684\u65F6\u5019\u6709\u7528\uFF08\u5F53\u8F6E\u751F\u6548\uFF09\uFF1B",
5625
+ "\u5BF9\u65B9\u6CA1\u5728\u8DD1\u5C31\u7528\u8FD9\u4E2A \u2014\u2014 \u5B83\u63A5\u7740\u81EA\u5DF1\u90A3\u6BB5\u4F1A\u8BDD\u7EE7\u7EED\uFF0C\u4E0D\u662F\u4ECE\u96F6\u5F00\u59CB\u3002",
5626
+ "\u53EB\u9192\u662F\u5F02\u6B65\u7684\uFF1A\u5DE5\u5177\u4E00\u8FD4\u56DE\u5C31\u7B97\u5B8C\u6210\uFF0C\u5B83\u81EA\u5DF1\u90A3\u4E00\u8F6E\u5728\u540E\u53F0\u8DD1\uFF0C\u4E0D\u7528\u7B49\u5B83\u7B54\u5B8C\u3002",
5627
+ "\u4E00\u6B21\u5524\u9192 = \u4E00\u6B21\u5B8C\u6574\u7684\u6A21\u578B\u8C03\u7528\uFF08\u5168\u91CF\u5386\u53F2\u91CD\u53D1\uFF09\uFF0C\u80FD\u4E00\u6B21\u8BF4\u5B8C\u5C31\u522B\u62C6\u6210\u4E09\u6B21\u3002",
5628
+ "\u540C\u65F6\u88AB\u53EB\u9192\u7684\u4F1A\u8BDD\u662F\u6709\u4E0A\u9650\u7684\uFF08\u9ED8\u8BA4 3 \u6BB5\uFF09\uFF0C\u8FDE\u7740\u53EB\u7B2C\u56DB\u6BB5\u4F1A\u88AB\u62D2 \u2014\u2014 \u7B49\u4E00\u6BB5\u8DD1\u5B8C\u518D\u53EB\u3002"
5629
+ ].join("\n"),
5630
+ parameters: {
5631
+ type: "object",
5632
+ properties: {
5633
+ agentId: { type: "string", description: "\u6210\u5458\u540D\uFF08list_agents \u91CC\u6709\uFF09" },
5634
+ message: { type: "string", description: "\u8FD9\u4E00\u8F6E\u8981\u5B83\u505A\u4EC0\u4E48" }
5635
+ },
5636
+ required: ["agentId", "message"]
5637
+ },
5638
+ exposure: ToolExposure.Deferred,
5639
+ supportsParallel: false,
5640
+ operation: "command",
5641
+ annotations: {
5642
+ readOnlyHint: false,
5643
+ destructiveHint: true,
5644
+ idempotentHint: false,
5645
+ openWorldHint: true
5646
+ },
5647
+ describeTarget: (args) => `${String(args["agentId"] ?? "")}: ${String(args["message"] ?? "")}`,
5648
+ async execute(args, ctx) {
5649
+ const start = Date.now();
5650
+ const agentId = str3(args, "agentId");
5651
+ const message = str3(args, "message");
5652
+ if (!agentId) return err2(7205, "\u7F3A\u5C11 agentId");
5653
+ if (!message) return err2(7206, "\u7F3A\u5C11 message");
5654
+ const member = team.get(agentId);
5655
+ if (member) {
5656
+ if (member.status === "running") {
5657
+ return err2(
5658
+ 7208,
5659
+ `${agentId} \u6B63\u5728\u8DD1\uFF0C\u4E0D\u9700\u8981\u5524\u9192`,
5660
+ "\u73B0\u5728\u7ED9\u5B83\u8BF4\u8BDD\u7528 send_message \u2014\u2014 \u90A3\u6761\u4F1A\u63D2\u5230\u5B83\u4E0B\u4E00\u4E2A\u6B65\u9AA4\u8FB9\u754C\uFF0C\u5F53\u8F6E\u5C31\u751F\u6548"
5661
+ );
5662
+ }
5663
+ const r = await manager.delegate(
5664
+ {
5665
+ tasks: [
5666
+ {
5667
+ goal: message,
5668
+ agentId,
5669
+ resumeSessionId: member.sessionId,
5670
+ ...member.role ? { role: member.role } : {}
5671
+ }
5672
+ ],
5673
+ background: true,
5674
+ max_concurrent: 1
5675
+ },
5676
+ ctx.sessionId,
5677
+ ctx.signal
4228
5678
  );
4229
- }
4230
- const issues = validateDraft(draft, deps.homeDir, current);
4231
- if (issues.length > 0) {
4232
- return say4(
4233
- `\u8FD9\u4EFD\u63D0\u6848\u5B58\u4E0D\u4E0B\u6765\uFF0C\u5148\u6539\u8FD9\u51E0\u5904\u518D\u8BF4\uFF1A${issues.join("\u3001")}\u3002\uFF08\u8FD9\u4E9B\u662F\u6821\u9A8C\u7801\uFF0C\u542B\u4E49\u770B\u5B57\u9762\uFF1Bdetail \u62EC\u5728\u540E\u9762\uFF09`,
4234
- false,
4235
- startedAt
5679
+ if (!r.success) return { ...err2(7209, r.output), duration: Date.now() - start };
5680
+ return ok3(
5681
+ [
5682
+ `\u5DF2\u5524\u9192 ${agentId}\uFF08\u540E\u53F0\u4F5C\u4E1A ${r.jobId ?? "(\u65E0)"}\uFF09\uFF0C\u5B83\u5E26\u7740\u4E0A\u4E00\u6B21\u7684\u4E0A\u4E0B\u6587\u63A5\u7740\u5E72\u3002`,
5683
+ `\u770B\u5B83\u5E72\u5230\u54EA\u513F\u4E86\uFF1Atask_output ${r.jobId ?? ""} \u6216 list_agents`
5684
+ ].join("\n"),
5685
+ start
4236
5686
  );
4237
5687
  }
4238
- const unattended = unattendedIssues(draft);
4239
- if (unattended.length > 0) {
4240
- return say4(
4241
- `\u8FD9\u4EFD\u63D0\u6848\u5B58\u5F97\u4E0B\u6765\uFF0C\u4F46\u5B83\u5230\u70B9\u4E86**\u8DD1\u4E0D\u51FA\u7ED3\u679C** \u2014\u2014 \u5B9A\u65F6\u4EFB\u52A1\u662F\u65E0\u4EBA\u503C\u5B88\u7684\uFF0C\u6CA1\u4EBA\u5728\u65C1\u8FB9\u56DE\u8BDD\u3002\u6539\u5B8C\u518D\u4EA4\uFF1A
4242
- ${unattended.map((x) => `\xB7 ${x}`).join("\n")}`,
4243
- false,
4244
- startedAt
5688
+ if (team.sessionExists(agentId)) {
5689
+ if (team.isSessionActive(agentId)) {
5690
+ return err2(
5691
+ 7210,
5692
+ `${agentId} \u6B63\u5728\u8DD1\uFF0C\u4E0D\u9700\u8981\u5524\u9192`,
5693
+ "\u73B0\u5728\u7ED9\u5B83\u8BF4\u8BDD\u7528 send_message \u2014\u2014 \u90A3\u6761\u4F1A\u8FDB\u5B83\u6B63\u5728\u8DD1\u7684\u90A3\u4E00\u8F6E"
5694
+ );
5695
+ }
5696
+ const self = team.bySession(ctx.sessionId);
5697
+ const from = self ? self.agentId : ctx.sessionId;
5698
+ const fromLabel = self ? void 0 : sessionSenderLabel(from, team.sessionTitle(from));
5699
+ const r = await team.wakeSession(
5700
+ agentId,
5701
+ agentMessageLine({ from, text: message, ...fromLabel ? { fromLabel } : {} })
4245
5702
  );
4246
- }
4247
- const readOnly = ctx.permissionLevel === "plan";
4248
- if (readOnly || deps.save === void 0) {
4249
- return say4(summarizeProposal(draft, current, readOnly), true, startedAt);
4250
- }
4251
- const saved = await persist(deps.save, draft, current);
4252
- if (saved.issues.length > 0) {
4253
- const codes = saved.issues.map((x) => x.detail ? `${x.code}\uFF08${x.detail}\uFF09` : x.code);
4254
- return say4(`\u5F15\u64CE\u62D2\u7EDD\u4E86\u8FD9\u4EFD\u63D0\u6848\uFF0C\u4E00\u4E2A\u5B57\u90FD\u6CA1\u5199\uFF1A${codes.join("\u3001")}\u3002`, false, startedAt);
4255
- }
4256
- const def = saved.schedule;
4257
- if (def === void 0) {
4258
- return say4(
4259
- "\u5F15\u64CE\u8BF4\u5B58\u4E0B\u6765\u4E86\uFF0C\u4F46\u6CA1\u56DE\u90A3\u6761\u4EFB\u52A1 \u2014\u2014 \u53BB\u81EA\u52A8\u5316\u9762\u677F\u770B\u4E00\u773C\u5B83\u5230\u5E95\u5728\u4E0D\u5728\u3002",
4260
- false,
4261
- startedAt
5703
+ if (!r.ok) return { ...err2(7211, r.reason ?? "\u5524\u9192\u5931\u8D25"), duration: Date.now() - start };
5704
+ return ok3(
5705
+ [
5706
+ `\u5DF2\u628A\u4F1A\u8BDD ${agentId} \u53EB\u8D77\u6765\u8DD1\u4E00\u8F6E\uFF08\u4E0D\u7B49\u5B83\u7B54\u5B8C\uFF0C\u5B83\u81EA\u5DF1\u90A3\u4E00\u8F6E\u5728\u540E\u53F0\u8DD1\uFF09\u3002`,
5707
+ `\u770B\u5B83\u7B54\u4E86\u4EC0\u4E48\uFF1Asession_messages_read ${agentId}\uFF1B\u6216\u8005\u7B49\u5B83\u7ED9\u4F60\u56DE\u6D88\u606F\u3002`
5708
+ ].join("\n"),
5709
+ start
4262
5710
  );
4263
5711
  }
4264
- return say4(summarizeSaved(draft, def, saved.registration, current), true, startedAt);
5712
+ return err2(7207, `\u6CA1\u6709\u8FD9\u4E2A\u6210\u5458\u6216\u4F1A\u8BDD\uFF1A${agentId}`, "\u7528 list_agents --all \u770B\u5F53\u524D\u6709\u8C01");
4265
5713
  }
4266
5714
  };
4267
5715
  }
5716
+ function createTeamTools(team, manager) {
5717
+ return [
5718
+ listAgents(team),
5719
+ spawnTeammate(team, manager),
5720
+ waitAgent(team),
5721
+ interruptAgent(team),
5722
+ followupTask(team, manager),
5723
+ taskCreate(team),
5724
+ taskList(team),
5725
+ taskGet(team),
5726
+ taskUpdate(team)
5727
+ ];
5728
+ }
5729
+ var TEAM_TOOL_NAMES = Object.freeze([
5730
+ "spawn_teammate",
5731
+ "list_agents",
5732
+ "wait_agent",
5733
+ "interrupt_agent",
5734
+ "followup_task",
5735
+ "team_task_create",
5736
+ "team_task_list",
5737
+ "team_task_get",
5738
+ "team_task_update"
5739
+ ]);
4268
5740
  // src/session/authorization.ts
4269
5741
  function lineageOf(db, sessionId) {
4270
5742
  const rows = db.prepare(
@@ -4520,6 +5992,14 @@ var SessionQueries = class {
4520
5992
  if (!meta) return { authorized: false, title: "", before: [], after: [], total: 0 };
4521
5993
  const total = this.db.prepare(`SELECT count(*) AS n FROM messages WHERE session_id = @sid`).get({ sid: input.sessionId }).n;
4522
5994
  const base2 = { authorized: true, title: meta.title, total };
5995
+ if (input.messageId === void 0) {
5996
+ return {
5997
+ ...base2,
5998
+ before: [],
5999
+ after: [],
6000
+ tail: this.tailRows(input.sessionId, input.tail ?? 0).reverse().map(toRecord)
6001
+ };
6002
+ }
4523
6003
  const anchor = this.recordRow(input.sessionId, input.messageId);
4524
6004
  if (!anchor) return { ...base2, before: [], after: [] };
4525
6005
  return {
@@ -4625,6 +6105,16 @@ var SessionQueries = class {
4625
6105
  LIMIT @n`
4626
6106
  ).all({ sid: sessionId, anchor: anchorId, n });
4627
6107
  }
6108
+ tailRows(sessionId, n) {
6109
+ if (n <= 0) return [];
6110
+ return this.db.prepare(
6111
+ `SELECT id, role, content, timestamp, active, tool_name
6112
+ FROM messages
6113
+ WHERE session_id = @sid
6114
+ ORDER BY id DESC
6115
+ LIMIT @n`
6116
+ ).all({ sid: sessionId, n });
6117
+ }
4628
6118
  messageRows(safe, sessionId, limit) {
4629
6119
  const sql = (table) => `
4630
6120
  SELECT m.id, m.session_id, m.role, m.content, m.timestamp, m.active,
@@ -4749,14 +6239,16 @@ function createSessionListTool(deps) {
4749
6239
  output: render(out, scopeNote(allWorkspaces, archived)),
4750
6240
  duration: Date.now() - start
4751
6241
  });
4752
- } catch (err) {
4753
- return Promise.resolve(fail3(err instanceof Error ? err.message : String(err), start, 8014));
6242
+ } catch (err3) {
6243
+ return Promise.resolve(fail3(err3 instanceof Error ? err3.message : String(err3), start, 8014));
4754
6244
  }
4755
6245
  }
4756
6246
  };
4757
6247
  }
4758
6248
  var DEFAULT_WINDOW = 2;
4759
6249
  var MAX_WINDOW = 10;
6250
+ var DEFAULT_TAIL = 5;
6251
+ var MAX_TAIL = MAX_WINDOW;
4760
6252
  var DEFAULT_TRACE_LIMIT = 20;
4761
6253
  var MAX_TRACE_LIMIT = 50;
4762
6254
  var BODY_BUDGET = 1500;
@@ -4789,7 +6281,7 @@ function body(text, budget) {
4789
6281
  if (flat.length <= budget) return flat;
4790
6282
  const rest = flat.length - budget;
4791
6283
  return `${flat.slice(0, budget)}
4792
- \u2026[cut ${rest} more chars \u2014 lower before/after to spend the budget on fewer messages]`;
6284
+ \u2026[cut ${rest} more chars \u2014 narrow the window (before / after / tail) to spend the budget on fewer messages]`;
4793
6285
  }
4794
6286
  function surfaceOf(record, isCurrent) {
4795
6287
  if (!isCurrent) return record.surface === "active" ? "active there" : "compacted there";
@@ -4802,7 +6294,21 @@ function renderRecord(record, mark, budget, isCurrent) {
4802
6294
  ` ${body(record.content, budget).split("\n").join("\n ")}`
4803
6295
  ].join("\n");
4804
6296
  }
6297
+ function tailBudgetOf(count) {
6298
+ return Math.max(MIN_BODY, Math.floor(BODY_BUDGET / Math.max(1, count)));
6299
+ }
6300
+ function renderTail(out, sessionId, isCurrent) {
6301
+ const tail = out.tail ?? [];
6302
+ const head = [
6303
+ `Session ${sessionId}${isCurrent ? " (this session)" : ""} \u2014 ${out.title || "(untitled)"}`,
6304
+ tail.length === 0 ? "this session has no messages." : `latest ${tail.length} of ${out.total} message(s), oldest first:`
6305
+ ];
6306
+ if (tail.length === 0) return head.join("\n");
6307
+ const budget = tailBudgetOf(tail.length);
6308
+ return [...head, "", ...tail.map((r) => renderRecord(r, " ", budget, isCurrent))].join("\n");
6309
+ }
4805
6310
  function renderWindow(out, sessionId, isCurrent) {
6311
+ if (out.tail) return renderTail(out, sessionId, isCurrent);
4806
6312
  const anchor = out.anchor;
4807
6313
  if (!anchor) return "";
4808
6314
  const count = out.before.length + out.after.length + 1;
@@ -4821,6 +6327,7 @@ function createSessionMessagesReadTool(deps) {
4821
6327
  name: SESSION_MESSAGES_READ_TOOL,
4822
6328
  description: `\u628A\u67D0\u4E00\u6761\u5386\u53F2\u6D88\u606F\u8FDE\u540C\u5B83\u524D\u540E\u51E0\u6761\u4E00\u8D77\u8BFB\u51FA\u6765 \u2014\u2014 \u68C0\u7D22\u7ED9\u7684\u662F\u7247\u6BB5\uFF0C\u8FD9\u4E2A\u7ED9\u7684\u662F\u539F\u6587\u3002
4823
6329
  sessionId + messageId \u6765\u81EA session_search / session_messages_search \u7684\u547D\u4E2D\u3002
6330
+ **\u4E0D\u4F20 messageId \u5C31\u6539\u8BFB\u8FD9\u6BB5\u4F1A\u8BDD\u6700\u8FD1\u51E0\u6761** \u2014\u2014 \u6CA1\u547D\u4E2D\u3001\u4E0D\u77E5\u9053\u4ECE\u54EA\u8BFB\u8D77\u65F6\u7528\u8FD9\u4E2A\uFF0C\u522B\u53BB\u731C id\uFF08id \u662F\u5168\u5E93\u81EA\u589E\u7684\uFF0C\u731C\u4E0D\u4E2D\uFF09\u3002
4824
6331
  before / after \u5404\u9ED8\u8BA4 ${DEFAULT_WINDOW}\u3001\u4E0A\u9650 ${MAX_WINDOW}\uFF08\u4F20\u5927\u4E86\u81EA\u52A8\u5939\u7D27\uFF0C\u4E0D\u62A5\u9519\uFF09\u3002
4825
6332
  \u6B63\u6587\u6709\u5B57\u7B26\u9884\u7B97\uFF0C\u8D85\u4E86\u4F1A\u622A\u65AD\u5E76\u660E\u8BF4\u622A\u4E86\u591A\u5C11 \u2014\u2014 \u60F3\u770B\u5168\u5C31\u628A before / after \u8C03\u5C0F\u3002
4826
6333
  \u5DF2\u7ECF\u88AB\u538B\u7F29\u76D6\u6389\u7684\u539F\u6587\u7167\u6837\u8BFB\u5F97\u5230\uFF0C\u90A3\u6B63\u662F\u8FD9\u4E2A\u5DE5\u5177\u5B58\u5728\u7684\u7406\u7531\u3002`,
@@ -4831,7 +6338,11 @@ before / after \u5404\u9ED8\u8BA4 ${DEFAULT_WINDOW}\u3001\u4E0A\u9650 ${MAX_WIND
4831
6338
  sessionId: { type: "string", description: "\u8BFB\u54EA\u6BB5\u4F1A\u8BDD\u3002\u6765\u81EA\u68C0\u7D22\u7ED3\u679C" },
4832
6339
  messageId: {
4833
6340
  type: "number",
4834
- description: "\u951A\u70B9\u6D88\u606F\u7684 id\uFF08\u68C0\u7D22\u547D\u4E2D\u91CC # \u540E\u9762\u90A3\u4E2A\u6570\u5B57\uFF09"
6341
+ description: `\u951A\u70B9\u6D88\u606F\u7684 id\uFF08\u68C0\u7D22\u547D\u4E2D\u91CC # \u540E\u9762\u90A3\u4E2A\u6570\u5B57\uFF09\u3002\u7701\u7565\u65F6\u6539\u4E3A\u8BFB\u6700\u8FD1 ${DEFAULT_TAIL} \u6761`
6342
+ },
6343
+ tail: {
6344
+ type: "number",
6345
+ description: `\u7701\u7565 messageId \u65F6\u8BFB\u6700\u8FD1\u51E0\u6761\uFF0C\u9ED8\u8BA4 ${DEFAULT_TAIL}\uFF0C\u4E0A\u9650 ${MAX_TAIL}`
4835
6346
  },
4836
6347
  before: {
4837
6348
  type: "number",
@@ -4848,7 +6359,7 @@ before / after \u5404\u9ED8\u8BA4 ${DEFAULT_WINDOW}\u3001\u4E0A\u9650 ${MAX_WIND
4848
6359
  }
4849
6360
  } : {}
4850
6361
  },
4851
- required: ["sessionId", "messageId"]
6362
+ required: ["sessionId"]
4852
6363
  };
4853
6364
  },
4854
6365
  exposure: ToolExposure.Direct,
@@ -4865,14 +6376,15 @@ before / after \u5404\u9ED8\u8BA4 ${DEFAULT_WINDOW}\u3001\u4E0A\u9650 ${MAX_WIND
4865
6376
  const start = Date.now();
4866
6377
  const sessionId = String(args["sessionId"] ?? "").trim();
4867
6378
  if (!sessionId) return Promise.resolve(fail4("sessionId must not be empty", start, 8007));
4868
- const messageId = Number(args["messageId"]);
4869
- if (!Number.isInteger(messageId) || messageId <= 0) {
6379
+ const rawId = args["messageId"];
6380
+ const messageId = rawId === void 0 || rawId === null || rawId === "" ? void 0 : Number(rawId);
6381
+ if (messageId !== void 0 && (!Number.isInteger(messageId) || messageId <= 0)) {
4870
6382
  return Promise.resolve(
4871
6383
  fail4(
4872
6384
  "messageId must be a positive integer",
4873
6385
  start,
4874
6386
  8008,
4875
- "Use the number after # from a session_search / session_messages_search hit"
6387
+ "Use the number after # from a session_search / session_messages_search hit \u2014 or omit messageId entirely to read the latest messages in that session"
4876
6388
  )
4877
6389
  );
4878
6390
  }
@@ -4880,9 +6392,10 @@ before / after \u5404\u9ED8\u8BA4 ${DEFAULT_WINDOW}\u3001\u4E0A\u9650 ${MAX_WIND
4880
6392
  try {
4881
6393
  const out = deps.queries.readMessages({
4882
6394
  sessionId,
4883
- messageId,
6395
+ ...messageId === void 0 ? {} : { messageId },
4884
6396
  before: clampWindow(args["before"], DEFAULT_WINDOW, MAX_WINDOW),
4885
6397
  after: clampWindow(args["after"], DEFAULT_WINDOW, MAX_WINDOW),
6398
+ tail: clampWindow(args["tail"], DEFAULT_TAIL, MAX_TAIL),
4886
6399
  currentSessionId: ctx.sessionId,
4887
6400
  workspaceCwd: deps.workspaceCwd,
4888
6401
  allWorkspaces
@@ -4897,13 +6410,13 @@ before / after \u5404\u9ED8\u8BA4 ${DEFAULT_WINDOW}\u3001\u4E0A\u9650 ${MAX_WIND
4897
6410
  )
4898
6411
  );
4899
6412
  }
4900
- if (!out.anchor) {
6413
+ if (messageId !== void 0 && !out.anchor) {
4901
6414
  return Promise.resolve(
4902
6415
  fail4(
4903
6416
  `session ${sessionId} has no message #${messageId} (it has ${out.total})`,
4904
6417
  start,
4905
6418
  8010,
4906
- "messageId must come from a hit in that same session \u2014 ids are not positions"
6419
+ "messageId must come from a hit in that same session \u2014 ids are not positions. Omit messageId entirely to read the latest messages instead."
4907
6420
  )
4908
6421
  );
4909
6422
  }
@@ -4912,8 +6425,8 @@ before / after \u5404\u9ED8\u8BA4 ${DEFAULT_WINDOW}\u3001\u4E0A\u9650 ${MAX_WIND
4912
6425
  output: renderWindow(out, sessionId, sessionId === ctx.sessionId),
4913
6426
  duration: Date.now() - start
4914
6427
  });
4915
- } catch (err) {
4916
- return Promise.resolve(fail4(err instanceof Error ? err.message : String(err), start, 8011));
6428
+ } catch (err3) {
6429
+ return Promise.resolve(fail4(err3 instanceof Error ? err3.message : String(err3), start, 8011));
4917
6430
  }
4918
6431
  }
4919
6432
  };
@@ -5019,8 +6532,8 @@ function createSessionTraceTool(deps) {
5019
6532
  output: renderTrace(trace, ctx.sessionId),
5020
6533
  duration: Date.now() - start
5021
6534
  });
5022
- } catch (err) {
5023
- return Promise.resolve(fail4(err instanceof Error ? err.message : String(err), start, 8013));
6535
+ } catch (err3) {
6536
+ return Promise.resolve(fail4(err3 instanceof Error ? err3.message : String(err3), start, 8013));
5024
6537
  }
5025
6538
  }
5026
6539
  };
@@ -5036,7 +6549,9 @@ function fail5(message, start, code, suggestion) {
5036
6549
  };
5037
6550
  }
5038
6551
  function emptyHint(query) {
5039
- return belowTrigramFloor(sanitizeFtsQuery(query)) ? ` Note: every word here is shorter than ${TRIGRAM_MIN_CHARS} characters, which the substring index cannot match at all \u2014 this is "cannot search", not "not found". Retry with a longer phrase.` : " Try fewer or different words.";
6552
+ return belowTrigramFloor(sanitizeFtsQuery(query)) ? ` Note: every word here is shorter than ${TRIGRAM_MIN_CHARS} characters, which the substring index cannot match at all \u2014 this is "cannot search", not "not found". Retry with a longer phrase.` : (
6553
+ " Try a shorter phrase copied verbatim from the text you expect \u2014 matching is on a continuous substring (at least 3 characters), not on separate keywords joined together."
6554
+ );
5040
6555
  }
5041
6556
  function clampLimit2(raw) {
5042
6557
  const n = Number(raw);
@@ -5078,7 +6593,7 @@ function createSessionSearchTool(deps) {
5078
6593
  properties: {
5079
6594
  query: {
5080
6595
  type: "string",
5081
- description: "\u68C0\u7D22\u8BCD\u3002\u5F53\u666E\u901A\u6587\u672C\u5199\uFF0C\u4E0D\u8981\u5199 FTS5 \u8BED\u6CD5\uFF08\u5F15\u53F7 / \u62EC\u53F7 / AND \u4F1A\u88AB\u6E05\u6389\uFF09"
6596
+ description: "\u68C0\u7D22\u8BCD\u3002\u5F53\u666E\u901A\u6587\u672C\u5199\uFF0C\u4E0D\u8981\u5199 FTS5 \u8BED\u6CD5\uFF08\u5F15\u53F7 / \u62EC\u53F7 / AND \u4F1A\u88AB\u6E05\u6389\uFF09\u3002\n\u5339\u914D\u7684\u662F**\u539F\u6587\u91CC\u8FDE\u7EED\u51FA\u73B0\u7684\u4E00\u6BB5**\uFF08\u81F3\u5C11 3 \u4E2A\u5B57\uFF09\uFF0C\u4E0D\u662F\u5206\u8BCD \u2014\u2014 \u6284\u539F\u6587\u91CC\u8FB9\u8FDE\u7740\u7684\u51E0\u4E2A\u5B57\u6BD4\u62FC\u5173\u952E\u8BCD\u51C6\u3002"
5082
6597
  },
5083
6598
  limit: {
5084
6599
  type: "number",
@@ -5143,10 +6658,10 @@ function createSessionSearchTool(deps) {
5143
6658
  ].join("\n"),
5144
6659
  duration: Date.now() - start
5145
6660
  });
5146
- } catch (err) {
6661
+ } catch (err3) {
5147
6662
  return Promise.resolve(
5148
6663
  fail5(
5149
- err instanceof Error ? err.message : String(err),
6664
+ err3 instanceof Error ? err3.message : String(err3),
5150
6665
  start,
5151
6666
  8002,
5152
6667
  "Retry with different words"
@@ -5170,7 +6685,7 @@ function createSessionMessagesSearchTool(deps) {
5170
6685
  },
5171
6686
  query: {
5172
6687
  type: "string",
5173
- description: "\u68C0\u7D22\u8BCD\u3002\u5F53\u666E\u901A\u6587\u672C\u5199\uFF0C\u4E0D\u8981\u5199 FTS5 \u8BED\u6CD5"
6688
+ description: "\u68C0\u7D22\u8BCD\u3002\u5F53\u666E\u901A\u6587\u672C\u5199\uFF0C\u4E0D\u8981\u5199 FTS5 \u8BED\u6CD5\u3002\n\u5339\u914D\u7684\u662F**\u539F\u6587\u91CC\u8FDE\u7EED\u51FA\u73B0\u7684\u4E00\u6BB5**\uFF08\u81F3\u5C11 3 \u4E2A\u5B57\uFF09\uFF0C\u4E0D\u662F\u5206\u8BCD \u2014\u2014 \u6284\u539F\u6587\u91CC\u8FB9\u8FDE\u7740\u7684\u51E0\u4E2A\u5B57\u6BD4\u62FC\u5173\u952E\u8BCD\u51C6\u3002"
5174
6689
  },
5175
6690
  limit: {
5176
6691
  type: "number",
@@ -5239,10 +6754,10 @@ function createSessionMessagesSearchTool(deps) {
5239
6754
  ].join("\n"),
5240
6755
  duration: Date.now() - start
5241
6756
  });
5242
- } catch (err) {
6757
+ } catch (err3) {
5243
6758
  return Promise.resolve(
5244
6759
  fail5(
5245
- err instanceof Error ? err.message : String(err),
6760
+ err3 instanceof Error ? err3.message : String(err3),
5246
6761
  start,
5247
6762
  8006,
5248
6763
  "Retry with different words"
@@ -5341,10 +6856,10 @@ function parseFrontmatter(raw) {
5341
6856
  if (!split) return { error: t("frontmatter.missing") };
5342
6857
  try {
5343
6858
  return { data: load(split.frontmatter), body: split.body };
5344
- } catch (err) {
6859
+ } catch (err3) {
5345
6860
  return {
5346
6861
  error: t("frontmatter.bad_yaml", {
5347
- reason: err instanceof Error ? err.message : String(err)
6862
+ reason: err3 instanceof Error ? err3.message : String(err3)
5348
6863
  })
5349
6864
  };
5350
6865
  }
@@ -5457,10 +6972,10 @@ function fail7(message, start, code, suggestion) {
5457
6972
  function done(output, start) {
5458
6973
  return { success: true, output, duration: Date.now() - start };
5459
6974
  }
5460
- function fromThrow(err, start, suggestion) {
5461
- return fail7(err instanceof Error ? err.message : String(err), start, 3102, suggestion);
6975
+ function fromThrow(err3, start, suggestion) {
6976
+ return fail7(err3 instanceof Error ? err3.message : String(err3), start, 3102, suggestion);
5462
6977
  }
5463
- function str2(args, key) {
6978
+ function str4(args, key) {
5464
6979
  const raw = args[key];
5465
6980
  return typeof raw === "string" ? raw : "";
5466
6981
  }
@@ -5510,9 +7025,9 @@ function createTool(deps) {
5510
7025
  describeTarget: (args) => `${SKILL_CREATE_TOOL}:${String(args["name"] ?? "")}`,
5511
7026
  async execute(args) {
5512
7027
  const start = Date.now();
5513
- const name = str2(args, "name").trim();
5514
- const content = str2(args, "content");
5515
- const category = str2(args, "category").trim() || "general";
7028
+ const name = str4(args, "name").trim();
7029
+ const content = str4(args, "content");
7030
+ const category = str4(args, "category").trim() || "general";
5516
7031
  if (!WRITABLE_SKILL_NAME.test(name)) {
5517
7032
  return fail7(`invalid skill name: ${JSON.stringify(name)}`, start, 3101, WRITABLE_HINT);
5518
7033
  }
@@ -5524,8 +7039,8 @@ function createTool(deps) {
5524
7039
  try {
5525
7040
  const path = await deps.skills.create(name, content, category);
5526
7041
  return done(`created skill "${name}" at ${path}`, start);
5527
- } catch (err) {
5528
- return fromThrow(err, start);
7042
+ } catch (err3) {
7043
+ return fromThrow(err3, start);
5529
7044
  }
5530
7045
  }
5531
7046
  };
@@ -5549,8 +7064,8 @@ function editTool(deps) {
5549
7064
  describeTarget: (args) => `${SKILL_EDIT_TOOL}:${String(args["name"] ?? "")}`,
5550
7065
  async execute(args) {
5551
7066
  const start = Date.now();
5552
- const name = str2(args, "name").trim();
5553
- const content = str2(args, "content");
7067
+ const name = str4(args, "name").trim();
7068
+ const content = str4(args, "content");
5554
7069
  if (!name) {
5555
7070
  return fail7("name must not be empty", start, 3101, describeAvailableSkills(deps.skills));
5556
7071
  }
@@ -5559,8 +7074,8 @@ function editTool(deps) {
5559
7074
  try {
5560
7075
  await deps.skills.edit(name, content);
5561
7076
  return done(`rewrote SKILL.md of skill "${name}"`, start);
5562
- } catch (err) {
5563
- return fromThrow(err, start, describeAvailableSkills(deps.skills));
7077
+ } catch (err3) {
7078
+ return fromThrow(err3, start, describeAvailableSkills(deps.skills));
5564
7079
  }
5565
7080
  }
5566
7081
  };
@@ -5589,9 +7104,9 @@ function patchTool(deps) {
5589
7104
  describeTarget: (args) => `${SKILL_PATCH_TOOL}:${String(args["name"] ?? "")}/${String(args["file_path"] ?? "SKILL.md")}`,
5590
7105
  async execute(args) {
5591
7106
  const start = Date.now();
5592
- const name = str2(args, "name").trim();
5593
- const oldString = str2(args, "old_string");
5594
- const filePath = str2(args, "file_path").trim();
7107
+ const name = str4(args, "name").trim();
7108
+ const oldString = str4(args, "old_string");
7109
+ const filePath = str4(args, "file_path").trim();
5595
7110
  if (!name) {
5596
7111
  return fail7("name must not be empty", start, 3101, describeAvailableSkills(deps.skills));
5597
7112
  }
@@ -5602,12 +7117,12 @@ function patchTool(deps) {
5602
7117
  await deps.skills.patch(
5603
7118
  name,
5604
7119
  oldString,
5605
- str2(args, "new_string"),
7120
+ str4(args, "new_string"),
5606
7121
  filePath === "" ? void 0 : filePath
5607
7122
  );
5608
7123
  return done(`patched ${filePath || "SKILL.md"} of skill "${name}"`, start);
5609
- } catch (err) {
5610
- return fromThrow(err, start, describeAvailableSkills(deps.skills));
7124
+ } catch (err3) {
7125
+ return fromThrow(err3, start, describeAvailableSkills(deps.skills));
5611
7126
  }
5612
7127
  }
5613
7128
  };
@@ -5635,17 +7150,17 @@ function writeFileTool(deps) {
5635
7150
  describeTarget: (args) => `${SKILL_WRITE_FILE_TOOL}:${String(args["name"] ?? "")}/${String(args["file_path"] ?? "")}`,
5636
7151
  async execute(args) {
5637
7152
  const start = Date.now();
5638
- const name = str2(args, "name").trim();
5639
- const filePath = str2(args, "file_path").trim();
7153
+ const name = str4(args, "name").trim();
7154
+ const filePath = str4(args, "file_path").trim();
5640
7155
  if (!name) {
5641
7156
  return fail7("name must not be empty", start, 3101, describeAvailableSkills(deps.skills));
5642
7157
  }
5643
7158
  if (!filePath) return fail7("file_path must not be empty", start, 3101);
5644
7159
  try {
5645
- await deps.skills.writeFile(name, filePath, str2(args, "content"));
7160
+ await deps.skills.writeFile(name, filePath, str4(args, "content"));
5646
7161
  return done(`wrote ${filePath} into skill "${name}"`, start);
5647
- } catch (err) {
5648
- return fromThrow(err, start, describeAvailableSkills(deps.skills));
7162
+ } catch (err3) {
7163
+ return fromThrow(err3, start, describeAvailableSkills(deps.skills));
5649
7164
  }
5650
7165
  }
5651
7166
  };
@@ -5680,7 +7195,7 @@ function matches(tool, terms) {
5680
7195
  function createToolSearchTool(deps) {
5681
7196
  return {
5682
7197
  name: "tool_search",
5683
- description: '\u6309\u5173\u952E\u8BCD\u627E\u51FA**\u5F53\u524D\u5DE5\u5177\u5217\u8868\u91CC\u6CA1\u6709**\u7684\u5DE5\u5177\uFF0C\u627E\u5230\u4E4B\u540E\u5B83\u4EEC\u5C31\u4F1A\u51FA\u73B0\u5728\u4F60\u7684\u5DE5\u5177\u5217\u8868\u91CC\u3002\n\u8FD9\u53F0\u673A\u5668\u4E0A\u63A5\u7684\u5DE5\u5177\u53EF\u80FD\u5F88\u591A\uFF08\u6BD4\u5982\u5404\u79CD MCP server\uFF09\uFF0C\u5168\u90E8\u585E\u8FDB\u5217\u8868\u4F1A\u5360\u6389\u5927\u91CF\u4E0A\u4E0B\u6587\uFF0C\u6240\u4EE5\u4E0D\u5E38\u7528\u7684\u90A3\u4E9B\u9ED8\u8BA4\u4E0D\u5728\u91CC\u9762 \u2014\u2014 \u9700\u8981\u65F6\u7528\u8FD9\u4E2A\u5DE5\u5177\u628A\u5B83\u4EEC\u627E\u51FA\u6765\u3002\n\u67E5\u8BE2\u8BCD\u5199\u4F60\u60F3\u5E72\u7684\u4E8B\u6216\u76EE\u6807\u7CFB\u7EDF\uFF0C\u6BD4\u5982 "github issue"\u3001"\u6570\u636E\u5E93 \u67E5\u8BE2"\u3002\u591A\u4E2A\u8BCD\u662F\u300C\u90FD\u8981\u547D\u4E2D\u300D\uFF0C\u5148\u5199\u5BBD\u4E00\u70B9\u518D\u6536\u7A84\u3002\n\u26A0\uFE0F \u627E\u5230\u4E4B\u540E**\u4E0D\u8981\u5728\u8FD9\u4E00\u8F6E\u91CC\u8C03\u5B83** \u2014\u2014 \u5B83\u8981\u5230\u4F60\u7684\u4E0B\u4E00\u6B21\u53D1\u8A00\u624D\u771F\u6B63\u51FA\u73B0\u5728\u5DE5\u5177\u5217\u8868\u91CC\uFF0C\u76F4\u63A5\u8C03\u4F1A\u5931\u8D25\u3002',
7198
+ description: '\u6309\u5173\u952E\u8BCD\u627E\u51FA**\u5F53\u524D\u5DE5\u5177\u5217\u8868\u91CC\u6CA1\u6709**\u7684\u5DE5\u5177\uFF0C\u627E\u5230\u4E4B\u540E\u5B83\u4EEC\u5C31\u4F1A\u51FA\u73B0\u5728\u4F60\u7684\u5DE5\u5177\u5217\u8868\u91CC\u3002\n\u8FD9\u53F0\u673A\u5668\u4E0A\u63A5\u7684\u5DE5\u5177\u53EF\u80FD\u5F88\u591A\uFF08\u6BD4\u5982\u5404\u79CD MCP server\uFF09\uFF0C\u5168\u90E8\u585E\u8FDB\u5217\u8868\u4F1A\u5360\u6389\u5927\u91CF\u4E0A\u4E0B\u6587\uFF0C\u6240\u4EE5\u4E0D\u5E38\u7528\u7684\u90A3\u4E9B\u9ED8\u8BA4\u4E0D\u5728\u91CC\u9762 \u2014\u2014 \u9700\u8981\u65F6\u7528\u8FD9\u4E2A\u5DE5\u5177\u628A\u5B83\u4EEC\u627E\u51FA\u6765\u3002\n\u67E5\u8BE2\u8BCD\u5199\u4F60\u60F3\u5E72\u7684\u4E8B\u6216\u76EE\u6807\u7CFB\u7EDF\uFF0C\u6BD4\u5982 "github issue"\u3001"\u6570\u636E\u5E93 \u67E5\u8BE2"\u3002\u591A\u4E2A\u8BCD\u662F\u300C\u90FD\u8981\u547D\u4E2D\u300D\uFF0C\u5148\u5199\u5BBD\u4E00\u70B9\u518D\u6536\u7A84\u3002\n\u26A0\uFE0F \u627E\u5230\u4E4B\u540E**\u4E0D\u8981\u505C\u4E0B\u6765\u7B49\u7528\u6237** \u2014\u2014 \u7D27\u63A5\u7740\u518D\u53D1\u8D77\u4E00\u6B21\u8BF7\u6C42\uFF0C\u5B83\u4EEC\u5C31\u5DF2\u7ECF\u5728\u4F60\u7684\u5DE5\u5177\u5217\u8868\u91CC\u4E86\uFF1B\n\u552F\u4E00\u505A\u4E0D\u5230\u7684\u662F\u548C `tool_search` \u5728**\u540C\u4E00\u6B21\u54CD\u5E94\u91CC**\u5E76\u884C\u8C03\u5B83\u4EEC\uFF08\u53D1\u8FD9\u6B21\u8BF7\u6C42\u65F6\u5B83\u4EEC\u8FD8\u4E0D\u5728\u5217\u8868\u91CC\uFF09\u3002',
5684
7199
  parameters: {
5685
7200
  type: "object",
5686
7201
  properties: {
@@ -5721,7 +7236,7 @@ function createToolSearchTool(deps) {
5721
7236
  (${hits.length - picked.length} more matched but were not added \u2014 narrow the query if the tool you want is missing.)` : "";
5722
7237
  return Promise.resolve({
5723
7238
  success: true,
5724
- output: `Added ${picked.length} tool(s) to your tool list. They become callable on your next turn \u2014 do not call them in this one.
7239
+ output: `Added ${picked.length} tool(s) to your tool list. They are callable on your **next request** \u2014 the next step of this same turn. The only thing you cannot do is call them in the same response that ran this search. Do not stop and wait for the user.
5725
7240
 
5726
7241
  ${lines.join("\n")}${truncated}`,
5727
7242
  duration: Date.now() - start
@@ -5765,8 +7280,8 @@ var MIGRATIONS = [
5765
7280
  var TrackerDB = class {
5766
7281
  db;
5767
7282
  path;
5768
- constructor(dbPath) {
5769
- this.path = dbPath;
7283
+ constructor(dbPath2) {
7284
+ this.path = dbPath2;
5770
7285
  this.db = openDatabase(this.path);
5771
7286
  migrate(this.db, NS, MIGRATIONS);
5772
7287
  }
@@ -5918,13 +7433,13 @@ function createTodoTool(db) {
5918
7433
  output: formatTodoList(todos, pendingCount),
5919
7434
  duration: Date.now() - startTime
5920
7435
  };
5921
- } catch (err) {
7436
+ } catch (err3) {
5922
7437
  return {
5923
7438
  success: false,
5924
7439
  output: "TODO \u5217\u8868\u5199\u5165\u5931\u8D25",
5925
7440
  error: {
5926
7441
  code: 1,
5927
- message: err instanceof Error ? err.message : String(err)
7442
+ message: err3 instanceof Error ? err3.message : String(err3)
5928
7443
  },
5929
7444
  duration: Date.now() - startTime
5930
7445
  };
@@ -5932,6 +7447,260 @@ function createTodoTool(db) {
5932
7447
  }
5933
7448
  };
5934
7449
  }
7450
+ var MAX_POST_CHARS = 2e4;
7451
+ var CHANNEL_PATTERN = /^[A-Za-z0-9_.-]{1,64}$/;
7452
+ var MIGRATIONS2 = [
7453
+ {
7454
+ id: "board-initial",
7455
+ version: 1,
7456
+ description: "\u8BA8\u8BBA\u677F\uFF1A\u9891\u9053 / \u7EBF\u7A0B / \u5E16\u5B50 / \u8BA2\u9605",
7457
+ up: (db) => {
7458
+ db.exec(`
7459
+ CREATE TABLE IF NOT EXISTS board_channels (
7460
+ id TEXT PRIMARY KEY,
7461
+ name TEXT NOT NULL UNIQUE,
7462
+ description TEXT,
7463
+ created_by TEXT NOT NULL,
7464
+ created_at INTEGER NOT NULL
7465
+ );
7466
+ CREATE TABLE IF NOT EXISTS board_threads (
7467
+ id TEXT PRIMARY KEY,
7468
+ channel TEXT NOT NULL,
7469
+ title TEXT NOT NULL,
7470
+ created_by TEXT NOT NULL,
7471
+ created_at INTEGER NOT NULL,
7472
+ last_post_at INTEGER NOT NULL
7473
+ );
7474
+ CREATE INDEX IF NOT EXISTS board_threads_channel ON board_threads(channel, last_post_at DESC);
7475
+ CREATE TABLE IF NOT EXISTS board_posts (
7476
+ seq INTEGER PRIMARY KEY AUTOINCREMENT,
7477
+ id TEXT NOT NULL UNIQUE,
7478
+ thread_id TEXT NOT NULL,
7479
+ author TEXT NOT NULL,
7480
+ text TEXT NOT NULL,
7481
+ created_at INTEGER NOT NULL
7482
+ );
7483
+ CREATE INDEX IF NOT EXISTS board_posts_thread ON board_posts(thread_id, seq);
7484
+ CREATE TABLE IF NOT EXISTS board_subscriptions (
7485
+ agent TEXT NOT NULL,
7486
+ target TEXT NOT NULL,
7487
+ last_seen_seq INTEGER NOT NULL DEFAULT 0,
7488
+ PRIMARY KEY (agent, target)
7489
+ );
7490
+ `);
7491
+ }
7492
+ }
7493
+ ];
7494
+ function targetKey(t83) {
7495
+ return t83.kind === "channel" ? `channel:${t83.name}` : `thread:${t83.id}`;
7496
+ }
7497
+ var BoardStore = class {
7498
+ path;
7499
+ db;
7500
+ constructor(homeDir) {
7501
+ this.path = dbPath(homeDir);
7502
+ this.db = openDatabase(this.path);
7503
+ migrate(this.db, "board", MIGRATIONS2);
7504
+ }
7505
+ close() {
7506
+ releaseDatabase(this.path);
7507
+ }
7508
+ createChannel(args) {
7509
+ if (!CHANNEL_PATTERN.test(args.name)) {
7510
+ throw new Error(`\u9891\u9053\u540D\u4E0D\u5408\u6CD5\uFF1A${args.name}\uFF08\u53EA\u8BB8\u5B57\u6BCD\u6570\u5B57 _ . -\uFF0C\u6700\u957F 64\uFF09`);
7511
+ }
7512
+ const existing = this.channel(args.name);
7513
+ if (existing) return existing;
7514
+ const row = {
7515
+ id: `ch-${randomUUID().slice(0, 8)}`,
7516
+ name: args.name,
7517
+ ...args.description ? { description: args.description } : {},
7518
+ createdBy: args.by,
7519
+ createdAt: Date.now()
7520
+ };
7521
+ this.db.prepare(
7522
+ `INSERT INTO board_channels (id, name, description, created_by, created_at)
7523
+ VALUES (?, ?, ?, ?, ?)`
7524
+ ).run(row.id, row.name, row.description ?? null, row.createdBy, row.createdAt);
7525
+ return row;
7526
+ }
7527
+ upsertChannel(args) {
7528
+ const existing = this.channel(args.name);
7529
+ if (!existing) return this.createChannel(args);
7530
+ this.db.prepare(`UPDATE board_channels SET description = ? WHERE name = ?`).run(args.description, args.name);
7531
+ return { ...existing, description: args.description };
7532
+ }
7533
+ channel(name) {
7534
+ const row = this.db.prepare(
7535
+ `SELECT id, name, description, created_by, created_at FROM board_channels WHERE name = ?`
7536
+ ).get(name);
7537
+ return row ? toChannel(row) : void 0;
7538
+ }
7539
+ listChannels() {
7540
+ const rows = this.db.prepare(
7541
+ `SELECT id, name, description, created_by, created_at FROM board_channels ORDER BY name`
7542
+ ).all();
7543
+ return rows.map(toChannel);
7544
+ }
7545
+ listThreads(channel, limit = 20) {
7546
+ const rows = this.db.prepare(
7547
+ `SELECT t.id, t.channel, t.title, t.created_by, t.created_at, t.last_post_at,
7548
+ (SELECT COUNT(*) FROM board_posts p WHERE p.thread_id = t.id) AS posts
7549
+ FROM board_threads t WHERE t.channel = ? ORDER BY t.last_post_at DESC LIMIT ?`
7550
+ ).all(channel, limit);
7551
+ return rows.map((r) => ({
7552
+ id: r.id,
7553
+ channel: r.channel,
7554
+ title: r.title,
7555
+ createdBy: r.created_by,
7556
+ createdAt: r.created_at,
7557
+ lastPostAt: r.last_post_at,
7558
+ postCount: r.posts
7559
+ }));
7560
+ }
7561
+ post(args) {
7562
+ return this.write({ ...args, notify: true });
7563
+ }
7564
+ append(args) {
7565
+ return this.write({ ...args, notify: false });
7566
+ }
7567
+ write(args) {
7568
+ const text = clip(args.text);
7569
+ const now = Date.now();
7570
+ const run = this.db.transaction(() => {
7571
+ let threadId;
7572
+ if (args.target.kind === "thread") {
7573
+ const exists2 = this.db.prepare(`SELECT id FROM board_threads WHERE id = ?`).get(args.target.id);
7574
+ if (!exists2) throw new Error(`\u6CA1\u6709\u8FD9\u4E2A\u7EBF\u7A0B\uFF1A${args.target.id}`);
7575
+ threadId = args.target.id;
7576
+ } else {
7577
+ const ch = this.channel(args.target.name);
7578
+ if (!ch) throw new Error(`\u6CA1\u6709\u8FD9\u4E2A\u9891\u9053\uFF1A${args.target.name}`);
7579
+ threadId = `th-${randomUUID().slice(0, 8)}`;
7580
+ this.db.prepare(
7581
+ `INSERT INTO board_threads (id, channel, title, created_by, created_at, last_post_at)
7582
+ VALUES (?, ?, ?, ?, ?, ?)`
7583
+ ).run(threadId, ch.name, firstLine(text), args.author, now, now);
7584
+ }
7585
+ const id = `po-${randomUUID().slice(0, 8)}`;
7586
+ const info = this.db.prepare(
7587
+ `INSERT INTO board_posts (id, thread_id, author, text, created_at) VALUES (?, ?, ?, ?, ?)`
7588
+ ).run(id, threadId, args.author, text, now);
7589
+ const seq = Number(info.lastInsertRowid);
7590
+ this.db.prepare(`UPDATE board_threads SET last_post_at = ? WHERE id = ?`).run(now, threadId);
7591
+ if (args.notify) {
7592
+ this.subscribe(args.author, { kind: "thread", id: threadId }, seq);
7593
+ }
7594
+ return {
7595
+ post: { id, threadId, author: args.author, text, createdAt: now, seq },
7596
+ threadId
7597
+ };
7598
+ });
7599
+ return run();
7600
+ }
7601
+ readThread(threadId, limit = 50) {
7602
+ const rows = this.db.prepare(
7603
+ `SELECT seq, id, thread_id, author, text, created_at FROM board_posts
7604
+ WHERE thread_id = ? ORDER BY seq ASC LIMIT ?`
7605
+ ).all(threadId, limit);
7606
+ return rows.map(toPost);
7607
+ }
7608
+ readPost(id) {
7609
+ const row = this.db.prepare(`SELECT seq, id, thread_id, author, text, created_at FROM board_posts WHERE id = ?`).get(id);
7610
+ return row ? toPost(row) : void 0;
7611
+ }
7612
+ searchPosts(query, channel, limit = 20) {
7613
+ const like = `%${query}%`;
7614
+ const rows = channel ? this.db.prepare(
7615
+ `SELECT p.seq, p.id, p.thread_id, p.author, p.text, p.created_at
7616
+ FROM board_posts p JOIN board_threads t ON t.id = p.thread_id
7617
+ WHERE t.channel = ? AND p.text LIKE ? ORDER BY p.seq DESC LIMIT ?`
7618
+ ).all(channel, like, limit) : this.db.prepare(
7619
+ `SELECT seq, id, thread_id, author, text, created_at FROM board_posts
7620
+ WHERE text LIKE ? ORDER BY seq DESC LIMIT ?`
7621
+ ).all(like, limit);
7622
+ return rows.map(toPost);
7623
+ }
7624
+ subscribe(agent, target, seenSeq) {
7625
+ const key = targetKey(target);
7626
+ const initial = seenSeq ?? this.maxSeq();
7627
+ this.db.prepare(
7628
+ `INSERT INTO board_subscriptions (agent, target, last_seen_seq) VALUES (?, ?, ?)
7629
+ ON CONFLICT(agent, target) DO UPDATE SET
7630
+ last_seen_seq = MAX(board_subscriptions.last_seen_seq, excluded.last_seen_seq)`
7631
+ ).run(agent, key, initial);
7632
+ }
7633
+ maxSeq() {
7634
+ const row = this.db.prepare(`SELECT COALESCE(MAX(seq), 0) AS n FROM board_posts`).get();
7635
+ return row.n;
7636
+ }
7637
+ unsubscribe(agent, target) {
7638
+ const info = this.db.prepare(`DELETE FROM board_subscriptions WHERE agent = ? AND target = ?`).run(agent, targetKey(target));
7639
+ return info.changes > 0;
7640
+ }
7641
+ pendingFor(agent) {
7642
+ const subs = this.db.prepare(`SELECT target, last_seen_seq FROM board_subscriptions WHERE agent = ?`).all(agent);
7643
+ const out = [];
7644
+ for (const s of subs) {
7645
+ const count = this.countSince(s.target, s.last_seen_seq);
7646
+ if (count > 0) out.push({ target: s.target, count });
7647
+ }
7648
+ return out;
7649
+ }
7650
+ markRead(agent, target) {
7651
+ if (target) {
7652
+ const key = targetKey(target);
7653
+ this.db.prepare(
7654
+ `UPDATE board_subscriptions SET last_seen_seq = (SELECT MAX(seq) FROM board_posts) WHERE agent = ? AND target = ?`
7655
+ ).run(agent, key);
7656
+ return;
7657
+ }
7658
+ this.db.prepare(
7659
+ `UPDATE board_subscriptions SET last_seen_seq = (SELECT COALESCE(MAX(seq), 0) FROM board_posts) WHERE agent = ?`
7660
+ ).run(agent);
7661
+ }
7662
+ countSince(target, sinceSeq) {
7663
+ if (target.startsWith("thread:")) {
7664
+ const id = target.slice("thread:".length);
7665
+ const row2 = this.db.prepare(`SELECT COUNT(*) AS n FROM board_posts WHERE thread_id = ? AND seq > ?`).get(id, sinceSeq);
7666
+ return row2.n;
7667
+ }
7668
+ const name = target.slice("channel:".length);
7669
+ const row = this.db.prepare(
7670
+ `SELECT COUNT(*) AS n FROM board_posts p JOIN board_threads t ON t.id = p.thread_id
7671
+ WHERE t.channel = ? AND p.seq > ?`
7672
+ ).get(name, sinceSeq);
7673
+ return row.n;
7674
+ }
7675
+ };
7676
+ function clip(text) {
7677
+ if (text.length <= MAX_POST_CHARS) return text;
7678
+ return `${text.slice(0, MAX_POST_CHARS)}
7679
+ \u2026\uFF08\u622A\u65AD\uFF0C\u539F\u6587 ${text.length} \u5B57\uFF09`;
7680
+ }
7681
+ function firstLine(text) {
7682
+ const line = text.split("\n", 1)[0] ?? text;
7683
+ return line.length > 80 ? `${line.slice(0, 80)}\u2026` : line;
7684
+ }
7685
+ function toChannel(r) {
7686
+ return {
7687
+ id: r.id,
7688
+ name: r.name,
7689
+ ...r.description ? { description: r.description } : {},
7690
+ createdBy: r.created_by,
7691
+ createdAt: r.created_at
7692
+ };
7693
+ }
7694
+ function toPost(r) {
7695
+ return {
7696
+ seq: r.seq,
7697
+ id: r.id,
7698
+ threadId: r.thread_id,
7699
+ author: r.author,
7700
+ text: r.text,
7701
+ createdAt: r.created_at
7702
+ };
7703
+ }
5935
7704
  var PlanModeState = class {
5936
7705
  constructor(permission2) {
5937
7706
  this.permission = permission2;
@@ -6024,11 +7793,11 @@ function loadRoleDir(dir, source) {
6024
7793
  let files;
6025
7794
  try {
6026
7795
  files = readdirSync(dir).filter((f) => f.endsWith(".md")).sort();
6027
- } catch (err) {
7796
+ } catch (err3) {
6028
7797
  return {
6029
7798
  roles: [],
6030
7799
  issues: [
6031
- { path: dir, message: t("agent_role_load.dir_read_failed", { reason: reason(err) }) }
7800
+ { path: dir, message: t("agent_role_load.dir_read_failed", { reason: reason(err3) }) }
6032
7801
  ]
6033
7802
  };
6034
7803
  }
@@ -6045,9 +7814,9 @@ function loadRoleFile(path, file, source) {
6045
7814
  let raw;
6046
7815
  try {
6047
7816
  raw = readFileSync(path, "utf8");
6048
- } catch (err) {
7817
+ } catch (err3) {
6049
7818
  return {
6050
- issues: [{ path: file, message: t("agent_role_load.read_failed", { reason: reason(err) }) }]
7819
+ issues: [{ path: file, message: t("agent_role_load.read_failed", { reason: reason(err3) }) }]
6051
7820
  };
6052
7821
  }
6053
7822
  return parseRoleDefinition(raw, file, source);
@@ -6136,8 +7905,8 @@ function loadRoleDefinitions(opts) {
6136
7905
  projectSkipped: false
6137
7906
  };
6138
7907
  }
6139
- function reason(err) {
6140
- return err instanceof Error ? err.message : String(err);
7908
+ function reason(err3) {
7909
+ return err3 instanceof Error ? err3.message : String(err3);
6141
7910
  }
6142
7911
  var READ_ONLY_TOOLS = [
6143
7912
  "file_read",
@@ -6297,11 +8066,11 @@ function createRoleFile(input, opts) {
6297
8066
  try {
6298
8067
  mkdirSync(opts.dir, { recursive: true });
6299
8068
  writeFileSync(path, text, { encoding: "utf-8", flag: "wx" });
6300
- } catch (err) {
6301
- if (err.code === "EEXIST") {
8069
+ } catch (err3) {
8070
+ if (err3.code === "EEXIST") {
6302
8071
  return { ok: false, reason: "duplicate", detail: t("role_write.taken", { name }) };
6303
8072
  }
6304
- return { ok: false, reason: "unwritable", detail: describe(err) };
8073
+ return { ok: false, reason: "unwritable", detail: describe(err3) };
6305
8074
  }
6306
8075
  return { ok: true, path, role: back.role };
6307
8076
  }
@@ -6341,8 +8110,8 @@ function driftOf(role, name, input) {
6341
8110
  if ((role.maxTurns ?? null) !== (input.maxTurns ?? null)) return "maxTurns";
6342
8111
  return void 0;
6343
8112
  }
6344
- function describe(err) {
6345
- return err instanceof Error ? err.message : String(err);
8113
+ function describe(err3) {
8114
+ return err3 instanceof Error ? err3.message : String(err3);
6346
8115
  }
6347
8116
  function removeRoleFile(name, opts) {
6348
8117
  const wanted = name.trim();
@@ -6371,8 +8140,8 @@ function removeRoleFile(name, opts) {
6371
8140
  }
6372
8141
  try {
6373
8142
  rmSync(path);
6374
- } catch (err) {
6375
- return { ok: false, reason: "failed", detail: describe2(err, path, opts.lang) };
8143
+ } catch (err3) {
8144
+ return { ok: false, reason: "failed", detail: describe2(err3, path, opts.lang) };
6376
8145
  }
6377
8146
  return { ok: true, path };
6378
8147
  }
@@ -6398,8 +8167,8 @@ function matchingFiles(dir, name) {
6398
8167
  }
6399
8168
  return hits;
6400
8169
  }
6401
- function describe2(err, path, lang) {
6402
- const reason9 = err instanceof Error ? err.message : String(err);
8170
+ function describe2(err3, path, lang) {
8171
+ const reason9 = err3 instanceof Error ? err3.message : String(err3);
6403
8172
  return t("role_write.remove_failed", { path, reason: reason9 }, lang);
6404
8173
  }
6405
8174
  // src/agent-role/scope.ts
@@ -6480,14 +8249,14 @@ function walk(dir, prefix, depth, files, issues) {
6480
8249
  let entries2;
6481
8250
  try {
6482
8251
  entries2 = readdirSync(dir, { withFileTypes: true });
6483
- } catch (err) {
6484
- if (isMissing(err)) {
8252
+ } catch (err3) {
8253
+ if (isMissing(err3)) {
6485
8254
  if (depth > 0) issues.push({ path: dir, message: t("custom_command.dir_vanished") });
6486
8255
  return;
6487
8256
  }
6488
8257
  issues.push({
6489
8258
  path: dir,
6490
- message: t("custom_command.dir_read_failed", { reason: reason2(err) })
8259
+ message: t("custom_command.dir_read_failed", { reason: reason2(err3) })
6491
8260
  });
6492
8261
  return;
6493
8262
  }
@@ -6512,11 +8281,11 @@ function walk(dir, prefix, depth, files, issues) {
6512
8281
  function commandNameFromRelPath(relPath) {
6513
8282
  return relPath.replace(/\.md$/i, "").split("/").join(":").toLowerCase();
6514
8283
  }
6515
- function isMissing(err) {
6516
- return err?.code === "ENOENT";
8284
+ function isMissing(err3) {
8285
+ return err3?.code === "ENOENT";
6517
8286
  }
6518
- function reason2(err) {
6519
- return err instanceof Error ? err.message : String(err);
8287
+ function reason2(err3) {
8288
+ return err3 instanceof Error ? err3.message : String(err3);
6520
8289
  }
6521
8290
  // src/extensions/commands.ts
6522
8291
  var CommandFrontmatterSchema = z.object({
@@ -6563,9 +8332,9 @@ function loadCommandFile(file, source, prefix) {
6563
8332
  let raw;
6564
8333
  try {
6565
8334
  raw = readFileSync(file.path, "utf8");
6566
- } catch (err) {
8335
+ } catch (err3) {
6567
8336
  return {
6568
- issues: [{ path: at, message: t("custom_command.read_failed", { reason: reason3(err) }) }]
8337
+ issues: [{ path: at, message: t("custom_command.read_failed", { reason: reason3(err3) }) }]
6569
8338
  };
6570
8339
  }
6571
8340
  const parsed = parseFrontmatter(raw);
@@ -6668,8 +8437,8 @@ function resolveCommandModel(def, opts, warnings) {
6668
8437
  }
6669
8438
  return ref;
6670
8439
  }
6671
- function reason3(err) {
6672
- return err instanceof Error ? err.message : String(err);
8440
+ function reason3(err3) {
8441
+ return err3 instanceof Error ? err3.message : String(err3);
6673
8442
  }
6674
8443
  // src/extensions/registry.ts
6675
8444
  var SLASH_COMMANDS_DIAG_MODULE = "SlashCommands";
@@ -6952,10 +8721,10 @@ function scanHooks(dir, issues) {
6952
8721
  let raw;
6953
8722
  try {
6954
8723
  raw = JSON.parse(readFileSync(path, "utf-8"));
6955
- } catch (err) {
8724
+ } catch (err3) {
6956
8725
  issues.push({
6957
8726
  path,
6958
- message: t("plugin_inventory.hooks_bad_json", { reason: firstLine(err) })
8727
+ message: t("plugin_inventory.hooks_bad_json", { reason: firstLine2(err3) })
6959
8728
  });
6960
8729
  return [];
6961
8730
  }
@@ -6981,8 +8750,8 @@ function scanMcp(dir, plugin, issues) {
6981
8750
  let raw;
6982
8751
  try {
6983
8752
  raw = JSON.parse(readFileSync(path, "utf-8"));
6984
- } catch (err) {
6985
- issues.push({ path, message: t("plugin.mcp_not_json", { reason: firstLine(err) }) });
8753
+ } catch (err3) {
8754
+ issues.push({ path, message: t("plugin.mcp_not_json", { reason: firstLine2(err3) }) });
6986
8755
  return [];
6987
8756
  }
6988
8757
  if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
@@ -7007,10 +8776,10 @@ function readSettingsSummary(path, issues) {
7007
8776
  let raw;
7008
8777
  try {
7009
8778
  raw = JSON.parse(readFileSync(path, "utf-8"));
7010
- } catch (err) {
8779
+ } catch (err3) {
7011
8780
  issues.push({
7012
8781
  path,
7013
- message: t("plugin_inventory.settings_bad_json", { reason: firstLine(err) })
8782
+ message: t("plugin_inventory.settings_bad_json", { reason: firstLine2(err3) })
7014
8783
  });
7015
8784
  return { deny: 0, ignored: [] };
7016
8785
  }
@@ -7038,16 +8807,16 @@ function readEntries(dir, issues) {
7038
8807
  name: e.name,
7039
8808
  isFile: e.isFile()
7040
8809
  }));
7041
- } catch (err) {
8810
+ } catch (err3) {
7042
8811
  issues.push({
7043
8812
  path: dir,
7044
- message: t("plugin_inventory.dir_read_failed", { reason: firstLine(err) })
8813
+ message: t("plugin_inventory.dir_read_failed", { reason: firstLine2(err3) })
7045
8814
  });
7046
8815
  return [];
7047
8816
  }
7048
8817
  }
7049
- function firstLine(err) {
7050
- const message = err instanceof Error ? err.message : String(err);
8818
+ function firstLine2(err3) {
8819
+ const message = err3 instanceof Error ? err3.message : String(err3);
7051
8820
  return message.split("\n")[0] ?? t("plugin_inventory.unknown_error");
7052
8821
  }
7053
8822
  var PLUGIN_MANIFEST_FILE = "epoch-plugin.json";
@@ -7109,13 +8878,13 @@ function readPluginManifest(dir) {
7109
8878
  let raw;
7110
8879
  try {
7111
8880
  raw = readFileSync(path, "utf-8");
7112
- } catch (err) {
7113
- const missing = err.code === "ENOENT";
8881
+ } catch (err3) {
8882
+ const missing = err3.code === "ENOENT";
7114
8883
  return {
7115
8884
  issues: [
7116
8885
  {
7117
8886
  path,
7118
- message: missing ? t("plugin_manifest.missing", { file: PLUGIN_MANIFEST_FILE }) : t("plugin_manifest.read_failed", { reason: reason4(err) })
8887
+ message: missing ? t("plugin_manifest.missing", { file: PLUGIN_MANIFEST_FILE }) : t("plugin_manifest.read_failed", { reason: reason4(err3) })
7119
8888
  }
7120
8889
  ]
7121
8890
  };
@@ -7123,9 +8892,9 @@ function readPluginManifest(dir) {
7123
8892
  let parsed;
7124
8893
  try {
7125
8894
  parsed = JSON.parse(raw);
7126
- } catch (err) {
8895
+ } catch (err3) {
7127
8896
  return {
7128
- issues: [{ path, message: t("plugin_manifest.bad_json", { reason: firstLine2(err) }) }]
8897
+ issues: [{ path, message: t("plugin_manifest.bad_json", { reason: firstLine3(err3) }) }]
7129
8898
  };
7130
8899
  }
7131
8900
  const issues = unknownKeyIssues(PLUGIN_MANIFEST_KEYS, parsed, PLUGIN_MANIFEST_FILE);
@@ -7288,11 +9057,11 @@ function currentEpochVersion() {
7288
9057
  cachedVersion = "unknown";
7289
9058
  return cachedVersion;
7290
9059
  }
7291
- function reason4(err) {
7292
- return err instanceof Error ? err.message : String(err);
9060
+ function reason4(err3) {
9061
+ return err3 instanceof Error ? err3.message : String(err3);
7293
9062
  }
7294
- function firstLine2(err) {
7295
- return reason4(err).split("\n")[0] ?? t("plugin_manifest.unknown_error");
9063
+ function firstLine3(err3) {
9064
+ return reason4(err3).split("\n")[0] ?? t("plugin_manifest.unknown_error");
7296
9065
  }
7297
9066
  var RecordSchema = z.object({
7298
9067
  name: z.string().regex(PLUGIN_NAME_PATTERN),
@@ -7327,8 +9096,8 @@ async function acquireStateLock(path) {
7327
9096
  } catch {
7328
9097
  }
7329
9098
  };
7330
- } catch (err) {
7331
- if (err.code !== "EEXIST") throw err;
9099
+ } catch (err3) {
9100
+ if (err3.code !== "EEXIST") throw err3;
7332
9101
  if (breakStaleLock(lockPath)) continue;
7333
9102
  if (Date.now() >= deadline) {
7334
9103
  throw new Error(t("plugin_store.lock_timeout", { path: lockPath }));
@@ -7360,8 +9129,8 @@ function readPluginRecords(path) {
7360
9129
  let raw;
7361
9130
  try {
7362
9131
  raw = JSON.parse(readFileSync(path, "utf-8"));
7363
- } catch (err) {
7364
- const detail = (err instanceof Error ? err.message : String(err)).split("\n")[0];
9132
+ } catch (err3) {
9133
+ const detail = (err3 instanceof Error ? err3.message : String(err3)).split("\n")[0];
7365
9134
  return {
7366
9135
  records: [],
7367
9136
  issues: [{ path, message: t("plugin_store.bad_json", { detail: detail ?? "" }) }]
@@ -7652,30 +9421,30 @@ function runCommand(file, args, opts = {}) {
7652
9421
  windowsVerbatimArguments: viaCmd,
7653
9422
  ...opts.cwd ? { cwd: opts.cwd } : {}
7654
9423
  },
7655
- (err, stdout, stderr) => {
9424
+ (err3, stdout, stderr) => {
7656
9425
  const out = String(stdout ?? "");
7657
9426
  const errOut = String(stderr ?? "");
7658
- if (!err) {
9427
+ if (!err3) {
7659
9428
  resolvePromise({ ok: true, stdout: out, stderr: errOut });
7660
9429
  return;
7661
9430
  }
7662
- const detail = describe3(file, err, errOut);
9431
+ const detail = describe3(file, err3, errOut);
7663
9432
  resolvePromise({
7664
9433
  ok: false,
7665
9434
  detail,
7666
9435
  stdout: out,
7667
9436
  stderr: errOut,
7668
- ...err.code === "ENOENT" ? { notFound: true } : {}
9437
+ ...err3.code === "ENOENT" ? { notFound: true } : {}
7669
9438
  });
7670
9439
  }
7671
9440
  ),
7672
- (err) => {
9441
+ (err3) => {
7673
9442
  resolvePromise({
7674
9443
  ok: false,
7675
- detail: describe3(file, err, ""),
9444
+ detail: describe3(file, err3, ""),
7676
9445
  stdout: "",
7677
9446
  stderr: "",
7678
- ...err.code === "ENOENT" || err.code === "ENOTDIR" ? { notFound: true } : {}
9447
+ ...err3.code === "ENOENT" || err3.code === "ENOTDIR" ? { notFound: true } : {}
7679
9448
  });
7680
9449
  }
7681
9450
  );
@@ -7688,11 +9457,11 @@ function escapeForCmd(arg) {
7688
9457
  const quoted = `"${arg.replace(/(\\*)"/g, '$1$1\\"').replace(/(\\*)$/, "$1$1")}"`;
7689
9458
  return quoted.replace(/([()%!^<>&|;,"])/g, "^$1");
7690
9459
  }
7691
- function describe3(file, err, stderr) {
7692
- if (err.code === "ENOENT") return t("plugin_cmd.not_found", { file });
7693
- if (err.killed) return t("plugin_cmd.timeout", { file });
9460
+ function describe3(file, err3, stderr) {
9461
+ if (err3.code === "ENOENT") return t("plugin_cmd.not_found", { file });
9462
+ if (err3.killed) return t("plugin_cmd.timeout", { file });
7694
9463
  const tail = stderr.trim().split("\n").slice(-4).join("\n").trim();
7695
- return tail || err.message;
9464
+ return tail || err3.message;
7696
9465
  }
7697
9466
  // src/plugin/archive.ts
7698
9467
  function resolveTar() {
@@ -7757,8 +9526,8 @@ ${detail}` }) };
7757
9526
  let entries2;
7758
9527
  try {
7759
9528
  entries2 = readdirSync(current, { withFileTypes: true });
7760
- } catch (err) {
7761
- return t("plugin_pack.read_failed", { path: current, reason: firstLine3(err) });
9529
+ } catch (err3) {
9530
+ return t("plugin_pack.read_failed", { path: current, reason: firstLine4(err3) });
7762
9531
  }
7763
9532
  for (const entry of entries2) {
7764
9533
  if (PACK_EXCLUDES.includes(entry.name)) continue;
@@ -7781,8 +9550,8 @@ ${detail}` }) };
7781
9550
  let stat5;
7782
9551
  try {
7783
9552
  stat5 = statSync(abs);
7784
- } catch (err) {
7785
- return t("plugin_pack.read_failed", { path: abs, reason: firstLine3(err) });
9553
+ } catch (err3) {
9554
+ return t("plugin_pack.read_failed", { path: abs, reason: firstLine4(err3) });
7786
9555
  }
7787
9556
  files.push({ path: rel, bytes: stat5.size, mtimeMs: Math.floor(stat5.mtimeMs) });
7788
9557
  totalBytes += stat5.size;
@@ -7819,10 +9588,10 @@ async function packPlugin(plan, destDir) {
7819
9588
  try {
7820
9589
  writeFileSync(listFile, `${plan.files.map((f) => f.path).join("\n")}
7821
9590
  `, "utf-8");
7822
- } catch (err) {
9591
+ } catch (err3) {
7823
9592
  return {
7824
9593
  ok: false,
7825
- reason: t("plugin_pack.read_failed", { path: listFile, reason: firstLine3(err) })
9594
+ reason: t("plugin_pack.read_failed", { path: listFile, reason: firstLine4(err3) })
7826
9595
  };
7827
9596
  }
7828
9597
  let result;
@@ -7850,10 +9619,10 @@ async function packPlugin(plan, destDir) {
7850
9619
  let bytes;
7851
9620
  try {
7852
9621
  bytes = statSync(archivePath).size;
7853
- } catch (err) {
9622
+ } catch (err3) {
7854
9623
  return {
7855
9624
  ok: false,
7856
- reason: t("plugin_pack.read_failed", { path: archivePath, reason: firstLine3(err) })
9625
+ reason: t("plugin_pack.read_failed", { path: archivePath, reason: firstLine4(err3) })
7857
9626
  };
7858
9627
  }
7859
9628
  return { ok: true, archivePath, bytes };
@@ -7861,8 +9630,8 @@ async function packPlugin(plan, destDir) {
7861
9630
  function isVirtualenv(dir) {
7862
9631
  return existsSync(join(dir, "pyvenv.cfg"));
7863
9632
  }
7864
- function firstLine3(err) {
7865
- const message = err instanceof Error ? err.message : String(err);
9633
+ function firstLine4(err3) {
9634
+ const message = err3 instanceof Error ? err3.message : String(err3);
7866
9635
  return message.split("\n")[0] ?? message;
7867
9636
  }
7868
9637
  var ABOUT_README_MAX_CHARS = 32e3;
@@ -8118,11 +9887,11 @@ function readMarketplaces(statePath) {
8118
9887
  let raw;
8119
9888
  try {
8120
9889
  raw = JSON.parse(readFileSync(statePath, "utf-8"));
8121
- } catch (err) {
9890
+ } catch (err3) {
8122
9891
  return {
8123
9892
  records: [],
8124
9893
  issues: [
8125
- { path: statePath, message: t("plugin_marketplace.bad_json", { reason: first(err) }) }
9894
+ { path: statePath, message: t("plugin_marketplace.bad_json", { reason: first(err3) }) }
8126
9895
  ]
8127
9896
  };
8128
9897
  }
@@ -8282,8 +10051,8 @@ async function fetchCatalog(source) {
8282
10051
  }
8283
10052
  try {
8284
10053
  return parseCatalog(readFileSync(local, "utf-8"), local);
8285
- } catch (err) {
8286
- return { ok: false, reason: t("plugin_marketplace.read_failed", { reason: first(err) }) };
10054
+ } catch (err3) {
10055
+ return { ok: false, reason: t("plugin_marketplace.read_failed", { reason: first(err3) }) };
8287
10056
  }
8288
10057
  }
8289
10058
  const url = catalogUrl(input);
@@ -8303,8 +10072,8 @@ async function fetchCatalog(source) {
8303
10072
  };
8304
10073
  }
8305
10074
  return parseCatalog(await response.text(), url);
8306
- } catch (err) {
8307
- return { ok: false, reason: t("marketplace.fetch_error", { url, reason: first(err) }) };
10075
+ } catch (err3) {
10076
+ return { ok: false, reason: t("marketplace.fetch_error", { url, reason: first(err3) }) };
8308
10077
  }
8309
10078
  }
8310
10079
  function looksPrivate(status) {
@@ -8334,10 +10103,10 @@ function parseCatalog(body2, where) {
8334
10103
  let raw;
8335
10104
  try {
8336
10105
  raw = JSON.parse(body2);
8337
- } catch (err) {
10106
+ } catch (err3) {
8338
10107
  return {
8339
10108
  ok: false,
8340
- reason: t("plugin_marketplace.catalog_bad_json", { where, reason: first(err) })
10109
+ reason: t("plugin_marketplace.catalog_bad_json", { where, reason: first(err3) })
8341
10110
  };
8342
10111
  }
8343
10112
  const checked = parseLenient(CatalogSchema.optional(), raw, void 0);
@@ -8347,8 +10116,8 @@ function parseCatalog(body2, where) {
8347
10116
  }
8348
10117
  return { ok: true, catalog: checked.value };
8349
10118
  }
8350
- function first(err) {
8351
- const message = err instanceof Error ? err.message : String(err);
10119
+ function first(err3) {
10120
+ const message = err3 instanceof Error ? err3.message : String(err3);
8352
10121
  return message.split("\n")[0] ?? t("plugin_marketplace.unknown_error");
8353
10122
  }
8354
10123
  var NPM_SPEC = /^(?:@[a-z0-9][a-z0-9._-]*\/)?[a-z0-9][a-z0-9._-]*(?:@[a-zA-Z0-9.^~*+-]+)?$/;
@@ -8756,11 +10525,11 @@ async function fetchFromHost(source, staging, opts) {
8756
10525
  );
8757
10526
  }
8758
10527
  });
8759
- } catch (err) {
10528
+ } catch (err3) {
8760
10529
  return {
8761
10530
  ok: false,
8762
10531
  reason: t("plugin_install.host_fetch_threw", {
8763
- reason: (err instanceof Error ? err.message : String(err)).split("\n")[0] ?? ""
10532
+ reason: (err3 instanceof Error ? err3.message : String(err3)).split("\n")[0] ?? ""
8764
10533
  })
8765
10534
  };
8766
10535
  }
@@ -8832,11 +10601,11 @@ async function fetchArchive(source, staging, opts) {
8832
10601
  };
8833
10602
  }
8834
10603
  bytes = await readBodyWithProgress(response, byteReporter(opts, "download", source.target));
8835
- } catch (err) {
10604
+ } catch (err3) {
8836
10605
  return {
8837
10606
  ok: false,
8838
10607
  reason: t("plugin_install.download_failed", {
8839
- message: err instanceof Error ? err.message : String(err)
10608
+ message: err3 instanceof Error ? err3.message : String(err3)
8840
10609
  })
8841
10610
  };
8842
10611
  }
@@ -8974,8 +10743,8 @@ async function applyRewind(store, sessionId, manifest, apply, skippedConflicts)
8974
10743
  let staged;
8975
10744
  try {
8976
10745
  staged = await stageAll(store, sessionId, manifest, todo, byPath);
8977
- } catch (err) {
8978
- return { ...empty, failed: t("rewind.stage_failed", { message: messageOf(err) }) };
10746
+ } catch (err3) {
10747
+ return { ...empty, failed: t("rewind.stage_failed", { message: messageOf(err3) }) };
8979
10748
  }
8980
10749
  return commitAll2(staged, skippedConflicts);
8981
10750
  }
@@ -8999,9 +10768,9 @@ async function stageAll(store, sessionId, manifest, todo, byPath) {
8999
10768
  }
9000
10769
  staged.push(item);
9001
10770
  }
9002
- } catch (err) {
10771
+ } catch (err3) {
9003
10772
  await discard(staged);
9004
- throw err;
10773
+ throw err3;
9005
10774
  }
9006
10775
  return staged;
9007
10776
  }
@@ -9016,7 +10785,7 @@ async function commitAll2(staged, skippedConflicts) {
9016
10785
  for (const item of staged) {
9017
10786
  try {
9018
10787
  await commitOne(item);
9019
- } catch (err) {
10788
+ } catch (err3) {
9020
10789
  await rollback(done2);
9021
10790
  await discard(staged);
9022
10791
  return {
@@ -9024,7 +10793,7 @@ async function commitAll2(staged, skippedConflicts) {
9024
10793
  restored: [],
9025
10794
  deleted: [],
9026
10795
  recreated: [],
9027
- failed: t("rewind.commit_failed", { message: messageOf(err) })
10796
+ failed: t("rewind.commit_failed", { message: messageOf(err3) })
9028
10797
  };
9029
10798
  }
9030
10799
  done2.push(item);
@@ -9080,8 +10849,8 @@ function bucketOf(outcome, action) {
9080
10849
  if (action === "recreate") return outcome.recreated;
9081
10850
  return outcome.restored;
9082
10851
  }
9083
- function messageOf(err) {
9084
- return err instanceof Error ? err.message : String(err);
10852
+ function messageOf(err3) {
10853
+ return err3 instanceof Error ? err3.message : String(err3);
9085
10854
  }
9086
10855
  // src/disk-ledger.ts
9087
10856
  var CHECKPOINT_MAX_TOTAL_BYTES = 200 * 1024 * 1024;
@@ -9238,9 +11007,9 @@ async function atomicWrite(path, data) {
9238
11007
  await writeFile(tmp, data);
9239
11008
  try {
9240
11009
  await rename(tmp, path);
9241
- } catch (err) {
11010
+ } catch (err3) {
9242
11011
  await rm(tmp, { force: true });
9243
- throw err;
11012
+ throw err3;
9244
11013
  }
9245
11014
  }
9246
11015
  function isManifest(value) {
@@ -9334,9 +11103,9 @@ var CheckpointManager = class {
9334
11103
  turnIndex = turn.turnIndex ?? await this.nextTurnIndex(sessionId);
9335
11104
  turn.turnIndex = turnIndex;
9336
11105
  for (const path of fresh) {
9337
- const { file, ok: ok2 } = await this.snapshotFile(sessionId, turnIndex, path);
11106
+ const { file, ok: ok4 } = await this.snapshotFile(sessionId, turnIndex, path);
9338
11107
  turn.files.push(file);
9339
- if (!ok2) turn.incomplete = true;
11108
+ if (!ok4) turn.incomplete = true;
9340
11109
  }
9341
11110
  await this.store.writeManifest(sessionId, manifestOf(turn, turnIndex, this.workDir()));
9342
11111
  } catch {
@@ -9375,8 +11144,8 @@ var CheckpointManager = class {
9375
11144
  if (info.size > MAX_FILE_BYTES) return { file: absent, ok: false };
9376
11145
  const hash = await this.store.putBlob(sessionId, turnIndex, await readFile(path));
9377
11146
  return { file: { path, hash, mode: info.mode & 511 }, ok: true };
9378
- } catch (err) {
9379
- return { file: absent, ok: isNotFound(err) };
11147
+ } catch (err3) {
11148
+ return { file: absent, ok: isNotFound(err3) };
9380
11149
  }
9381
11150
  }
9382
11151
  async nextTurnIndex(sessionId) {
@@ -9426,8 +11195,8 @@ function preview(text) {
9426
11195
  const flat = text.replace(/\s+/g, " ").trim();
9427
11196
  return flat.length > PREVIEW_LEN ? `${flat.slice(0, PREVIEW_LEN)}\u2026` : flat;
9428
11197
  }
9429
- function isNotFound(err) {
9430
- return err?.code === "ENOENT";
11198
+ function isNotFound(err3) {
11199
+ return err3?.code === "ENOENT";
9431
11200
  }
9432
11201
  async function hashOf(path) {
9433
11202
  try {
@@ -9515,8 +11284,8 @@ async function readSnapshot(path) {
9515
11284
  const buf = await readFile(path);
9516
11285
  if (buf.includes(0)) return { kind: "opaque" };
9517
11286
  return { kind: "text", text: buf.toString("utf-8"), bytes: buf.byteLength };
9518
- } catch (err) {
9519
- return isNotFound2(err) ? { kind: "absent" } : { kind: "opaque" };
11287
+ } catch (err3) {
11288
+ return isNotFound2(err3) ? { kind: "absent" } : { kind: "opaque" };
9520
11289
  }
9521
11290
  }
9522
11291
  function workspaceDisplayPath(path, workDir) {
@@ -9524,34 +11293,64 @@ function workspaceDisplayPath(path, workDir) {
9524
11293
  if (!rel || rel.startsWith("..") || isAbsolute(rel)) return path;
9525
11294
  return sep === "/" ? rel : rel.split(sep).join("/");
9526
11295
  }
9527
- function isNotFound2(err) {
9528
- return err?.code === "ENOENT";
11296
+ function isNotFound2(err3) {
11297
+ return err3?.code === "ENOENT";
9529
11298
  }
9530
11299
  var TaskNoticeTracker = class {
9531
- constructor(source) {
11300
+ constructor(source, team, board) {
9532
11301
  this.source = source;
11302
+ this.team = team;
11303
+ this.board = board;
9533
11304
  }
9534
11305
  source;
11306
+ team;
11307
+ board;
9535
11308
  seen = /* @__PURE__ */ new Map();
9536
- notice() {
9537
- if (!this.source) return null;
9538
- let tasks;
9539
- try {
9540
- tasks = this.source();
9541
- } catch {
9542
- return null;
9543
- }
11309
+ takeAgentMessages(sessionId) {
11310
+ const inbox = this.team?.mainInbox(sessionId);
11311
+ if (!inbox?.pending()) return [];
11312
+ return inbox.take().map((c) => typeof c === "string" ? c : contentToText(c));
11313
+ }
11314
+ notice(sessionId = LEAD_AGENT_ID) {
11315
+ return this.noticeDetailed(sessionId)?.text ?? null;
11316
+ }
11317
+ noticeDetailed(sessionId = LEAD_AGENT_ID) {
9544
11318
  const lines = [];
9545
- for (const task of tasks) {
9546
- if (task.kind === "shell") continue;
9547
- const before = this.seen.get(task.id);
9548
- if (before === task.status) continue;
9549
- this.seen.set(task.id, task.status);
9550
- if (task.kind === "agent" && task.status === "running") continue;
9551
- lines.push(describeBackgroundTask(task));
11319
+ if (this.source) {
11320
+ let tasks;
11321
+ try {
11322
+ tasks = this.source();
11323
+ } catch {
11324
+ tasks = [];
11325
+ }
11326
+ for (const task of tasks) {
11327
+ if (task.kind === "shell") continue;
11328
+ const before = this.seen.get(task.id);
11329
+ if (before === task.status) continue;
11330
+ this.seen.set(task.id, task.status);
11331
+ if (task.kind === "agent" && task.status === "running") continue;
11332
+ lines.push(describeBackgroundTask(task));
11333
+ }
11334
+ }
11335
+ const agentLines = this.takeAgentMessages(sessionId);
11336
+ const boardLines = this.board?.pending() ?? [];
11337
+ if (lines.length === 0 && agentLines.length === 0 && boardLines.length === 0) return null;
11338
+ const out = [];
11339
+ if (lines.length > 0) {
11340
+ out.push(systemNote("\u540E\u53F0\u4EFB\u52A1\u72B6\u6001"), ...lines, "\u8981\u770B\u8F93\u51FA\u7528 task_output\u3002");
11341
+ }
11342
+ if (agentLines.length > 0) {
11343
+ out.push(systemNote(AGENT_MESSAGE_NOTE_TITLE), ...agentLines);
11344
+ }
11345
+ if (boardLines.length > 0) {
11346
+ out.push(
11347
+ systemNote("\u8BA8\u8BBA\u677F"),
11348
+ ...boardLines.map((b) => `- ${b.target}\uFF1A${b.count} \u6761\u65B0\u5E16`),
11349
+ "\u8981\u770B\u5185\u5BB9\u7528 read_thread\uFF08\u8BFB\u5B8C\u81EA\u52A8\u6807\u6210\u5DF2\u770B\uFF09\u3002"
11350
+ );
11351
+ this.board?.markRead();
9552
11352
  }
9553
- if (lines.length === 0) return null;
9554
- return [systemNote("\u540E\u53F0\u4EFB\u52A1\u72B6\u6001"), ...lines, "\u8981\u770B\u8F93\u51FA\u7528 task_output\u3002"].join("\n");
11353
+ return { text: out.join("\n"), agent: agentLines };
9555
11354
  }
9556
11355
  };
9557
11356
  function describeBackgroundTask(task) {
@@ -9840,8 +11639,8 @@ function readImageSize(bytes) {
9840
11639
  const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
9841
11640
  const size = pngSize(bytes, view) ?? jpegSize(bytes, view) ?? gifSize(bytes, view) ?? webpSize(bytes, view);
9842
11641
  if (!size) return void 0;
9843
- const ok2 = (n) => Number.isInteger(n) && n > 0;
9844
- return ok2(size.width) && ok2(size.height) ? size : void 0;
11642
+ const ok4 = (n) => Number.isInteger(n) && n > 0;
11643
+ return ok4(size.width) && ok4(size.height) ? size : void 0;
9845
11644
  }
9846
11645
  function sniffMediaType(bytes) {
9847
11646
  if (bytes.length < 12) return void 0;
@@ -10181,8 +11980,8 @@ function imageFromPath(filePath, mediaType) {
10181
11980
  const st = statSync(abs);
10182
11981
  if (!st.isFile()) throw new ImageLoadError(t("image_load.not_a_file", { path: abs }));
10183
11982
  size = st.size;
10184
- } catch (err) {
10185
- if (err instanceof ImageLoadError) throw err;
11983
+ } catch (err3) {
11984
+ if (err3 instanceof ImageLoadError) throw err3;
10186
11985
  throw new ImageLoadError(t("image_load.unreadable", { path: abs }));
10187
11986
  }
10188
11987
  if (size === 0) throw new ImageLoadError(t("image_load.empty", { path: abs }));
@@ -10399,8 +12198,8 @@ function decideTrust(dir) {
10399
12198
  return ambient ? ambient.decide(dir) : noGate();
10400
12199
  }
10401
12200
  var FILE_VERSION = 1;
10402
- function describe5(err) {
10403
- return err instanceof Error ? err.message : String(err);
12201
+ function describe5(err3) {
12202
+ return err3 instanceof Error ? err3.message : String(err3);
10404
12203
  }
10405
12204
  var ImportTrustStore = class {
10406
12205
  constructor(filePath = trustedImportsPath()) {
@@ -10439,18 +12238,18 @@ var ImportTrustStore = class {
10439
12238
  let raw;
10440
12239
  try {
10441
12240
  raw = readFileSync(this.filePath, "utf-8");
10442
- } catch (err) {
12241
+ } catch (err3) {
10443
12242
  this.loadErrors.push(
10444
- t("import_trust.read_failed", { path: this.filePath, reason: describe5(err) })
12243
+ t("import_trust.read_failed", { path: this.filePath, reason: describe5(err3) })
10445
12244
  );
10446
12245
  return;
10447
12246
  }
10448
12247
  let parsed;
10449
12248
  try {
10450
12249
  parsed = JSON.parse(raw);
10451
- } catch (err) {
12250
+ } catch (err3) {
10452
12251
  this.loadErrors.push(
10453
- t("import_trust.bad_json", { path: this.filePath, reason: describe5(err) })
12252
+ t("import_trust.bad_json", { path: this.filePath, reason: describe5(err3) })
10454
12253
  );
10455
12254
  return;
10456
12255
  }
@@ -10505,10 +12304,10 @@ var ImportTrustStore = class {
10505
12304
  try {
10506
12305
  writeFileSync(tmp, body2, { encoding: "utf-8", mode: 384 });
10507
12306
  renameSync(tmp, this.filePath);
10508
- } catch (err) {
12307
+ } catch (err3) {
10509
12308
  rmSync(tmp, { force: true });
10510
12309
  throw new Error(
10511
- t("import_trust.write_failed", { path: this.filePath, reason: describe5(err) })
12310
+ t("import_trust.write_failed", { path: this.filePath, reason: describe5(err3) })
10512
12311
  );
10513
12312
  }
10514
12313
  }
@@ -11152,8 +12951,8 @@ var BudgetStore = class {
11152
12951
  throw new Error(t("budget.state_missing_sessions"));
11153
12952
  }
11154
12953
  return { version: 1, sessions };
11155
- } catch (err) {
11156
- const reason9 = err instanceof Error ? err.message : String(err);
12954
+ } catch (err3) {
12955
+ const reason9 = err3 instanceof Error ? err3.message : String(err3);
11157
12956
  this.quarantine();
11158
12957
  this.onWarn?.(t("budget.state_corrupt", { reason: reason9, path: this.path }));
11159
12958
  return empty;
@@ -11169,10 +12968,10 @@ var BudgetStore = class {
11169
12968
  try {
11170
12969
  mkdirSync(dirname(this.path), { recursive: true });
11171
12970
  writeFileSync(this.path, JSON.stringify(state, null, 2));
11172
- } catch (err) {
12971
+ } catch (err3) {
11173
12972
  this.onWarn?.(
11174
12973
  t("budget.state_write_failed", {
11175
- message: err instanceof Error ? err.message : String(err)
12974
+ message: err3 instanceof Error ? err3.message : String(err3)
11176
12975
  })
11177
12976
  );
11178
12977
  }
@@ -11496,25 +13295,25 @@ var PROVIDER_NO_CREDENTIAL = 1001;
11496
13295
  var PROVIDER_ABORTED = 1060;
11497
13296
  var PROVIDER_CONTEXT_OVERFLOW = 1030;
11498
13297
  var PROVIDER_BODY_TOO_LARGE = 1051;
11499
- function isContextOverflow(err) {
11500
- if (err instanceof ProviderError) return err.code === PROVIDER_CONTEXT_OVERFLOW;
11501
- return classifyProviderError(err).code === PROVIDER_CONTEXT_OVERFLOW;
13298
+ function isContextOverflow(err3) {
13299
+ if (err3 instanceof ProviderError) return err3.code === PROVIDER_CONTEXT_OVERFLOW;
13300
+ return classifyProviderError(err3).code === PROVIDER_CONTEXT_OVERFLOW;
11502
13301
  }
11503
- function isBodyTooLarge(err) {
11504
- if (err instanceof ProviderError) return err.code === PROVIDER_BODY_TOO_LARGE;
11505
- return classifyProviderError(err).code === PROVIDER_BODY_TOO_LARGE;
13302
+ function isBodyTooLarge(err3) {
13303
+ if (err3 instanceof ProviderError) return err3.code === PROVIDER_BODY_TOO_LARGE;
13304
+ return classifyProviderError(err3).code === PROVIDER_BODY_TOO_LARGE;
11506
13305
  }
11507
- function isAbortError(err) {
11508
- for (let cur = err, depth = 0; cur && depth < 5; depth++) {
13306
+ function isAbortError(err3) {
13307
+ for (let cur = err3, depth = 0; cur && depth < 5; depth++) {
11509
13308
  if (typeof cur !== "object") return false;
11510
13309
  if (cur.name === "AbortError") return true;
11511
13310
  cur = cur.cause;
11512
13311
  }
11513
13312
  return false;
11514
13313
  }
11515
- function causeChain(err) {
13314
+ function causeChain(err3) {
11516
13315
  const out = [];
11517
- for (let cur = err, depth = 0; cur && depth < 5; depth++) {
13316
+ for (let cur = err3, depth = 0; cur && depth < 5; depth++) {
11518
13317
  if (typeof cur !== "object") break;
11519
13318
  const e = cur;
11520
13319
  out.push({
@@ -11539,20 +13338,20 @@ var NETWORK_ERROR_CODES = /* @__PURE__ */ new Set([
11539
13338
  "UND_ERR_RESPONSE_STATUS_CODE"
11540
13339
  ]);
11541
13340
  var NETWORK_MESSAGE_RE = /timeout|timed.?out|etimedout|econnreset|enotfound|socket.?hang.?up|other.?side.?closed|terminated|network.?error|fetch.?failed/i;
11542
- function describeProviderError(err) {
11543
- const chain = causeChain(err);
11544
- const head = chain[0]?.message ?? (typeof err === "string" ? err : String(err));
13341
+ function describeProviderError(err3) {
13342
+ const chain = causeChain(err3);
13343
+ const head = chain[0]?.message ?? (typeof err3 === "string" ? err3 : String(err3));
11545
13344
  const root = [...chain].reverse().find((link) => link.message !== "" && link.message !== head)?.message;
11546
13345
  if (!head.trim()) {
11547
13346
  if (root) return root;
11548
- const status = extractStatus(err);
13347
+ const status = extractStatus(err3);
11549
13348
  return status === void 0 ? t("provider_route.no_detail") : t("provider_route.no_detail_status", { status });
11550
13349
  }
11551
13350
  return root ? t("provider_route.root_cause", { message: head, cause: root }) : head;
11552
13351
  }
11553
- function extractStatus(err) {
11554
- if (!err || typeof err !== "object") return void 0;
11555
- const e = err;
13352
+ function extractStatus(err3) {
13353
+ if (!err3 || typeof err3 !== "object") return void 0;
13354
+ const e = err3;
11556
13355
  for (const candidate of [e.statusCode, e.status, e.response?.status]) {
11557
13356
  if (typeof candidate === "number" && candidate >= 100 && candidate < 600) return candidate;
11558
13357
  }
@@ -11565,10 +13364,10 @@ function extractStatusFromMessage(msg) {
11565
13364
  if (labelled?.[1]) return Number(labelled[1]);
11566
13365
  return void 0;
11567
13366
  }
11568
- function classifyProviderError(err) {
11569
- const msg = err instanceof Error ? err.message : String(err);
11570
- const status = extractStatus(err);
11571
- if (isAbortError(err)) return { code: PROVIDER_ABORTED, recovery: "abort" };
13367
+ function classifyProviderError(err3) {
13368
+ const msg = err3 instanceof Error ? err3.message : String(err3);
13369
+ const status = extractStatus(err3);
13370
+ if (isAbortError(err3)) return { code: PROVIDER_ABORTED, recovery: "abort" };
11572
13371
  if (/context.?length|context.?window|maximum.*token|token.?limit|too.?many.?tokens|prompt.*too.?long|reduce.*(length|tokens)/i.test(
11573
13372
  msg
11574
13373
  ))
@@ -11597,7 +13396,7 @@ function classifyProviderError(err) {
11597
13396
  if (code >= 500) return { code: 1020, recovery: "retry" };
11598
13397
  if (code >= 400) return { code: 1050, recovery: "abort" };
11599
13398
  }
11600
- for (const link of causeChain(err)) {
13399
+ for (const link of causeChain(err3)) {
11601
13400
  if (link.code && NETWORK_ERROR_CODES.has(link.code)) return { code: 1041, recovery: "retry" };
11602
13401
  if (NETWORK_MESSAGE_RE.test(link.message)) return { code: 1041, recovery: "retry" };
11603
13402
  }
@@ -12752,7 +14551,10 @@ function outputText(output) {
12752
14551
  function failureText(r) {
12753
14552
  const detail = r.error?.message?.trim() || outputText(r.output).trim();
12754
14553
  if (!detail) return "\u5DE5\u5177\u6267\u884C\u5931\u8D25\uFF08\u5DE5\u5177\u672A\u63D0\u4F9B\u539F\u56E0\uFF09";
12755
- return r.error?.code === void 0 ? `\u5DE5\u5177\u6267\u884C\u5931\u8D25\uFF1A${detail}` : `\u5DE5\u5177\u6267\u884C\u5931\u8D25 [${r.error.code}]: ${detail}`;
14554
+ const head = r.error?.code === void 0 ? `\u5DE5\u5177\u6267\u884C\u5931\u8D25\uFF1A${detail}` : `\u5DE5\u5177\u6267\u884C\u5931\u8D25 [${r.error.code}]: ${detail}`;
14555
+ const hint = r.error?.suggestion?.trim();
14556
+ return hint ? `${head}
14557
+ ${hint}` : head;
12756
14558
  }
12757
14559
  var ToolExecutor = class {
12758
14560
  constructor(deps) {
@@ -12885,12 +14687,12 @@ var ToolExecutor = class {
12885
14687
  truncateForModel(failureText(r), budgetOf2(et, depth, "failure"), "text")
12886
14688
  )
12887
14689
  });
12888
- } catch (err) {
12889
- span.recordError(err);
14690
+ } catch (err3) {
14691
+ span.recordError(err3);
12890
14692
  return finish({
12891
14693
  ...base2,
12892
14694
  success: false,
12893
- output: `\u5DE5\u5177\u6267\u884C\u5F02\u5E38: ${err instanceof Error ? err.message : String(err)}`
14695
+ output: `\u5DE5\u5177\u6267\u884C\u5F02\u5E38: ${err3 instanceof Error ? err3.message : String(err3)}`
12894
14696
  });
12895
14697
  }
12896
14698
  }
@@ -13300,6 +15102,7 @@ var AgentLoop = class {
13300
15102
  async *runTurns(input, turns) {
13301
15103
  const maxTurns = turnLimitOf(input.maxTurns ?? this.config.maxTurns);
13302
15104
  this.stallDetector.reset();
15105
+ const pendingReceived = [];
13303
15106
  const rawUserText = contentToText(input.userMessage, { imagesCarriedAsParts: true });
13304
15107
  const images = imageParts(input.userMessage);
13305
15108
  const inputGate = this.config.compliance?.checkInput(rawUserText);
@@ -13397,11 +15200,13 @@ var AgentLoop = class {
13397
15200
  ...breach ? { breach } : {}
13398
15201
  });
13399
15202
  this.hooks.fire("session:start", { sessionId: input.sessionId });
15203
+ this.config.team?.registerSession(input.sessionId);
13400
15204
  const runSpan = this.telemetry.startSpan("agent_run", {
13401
15205
  [GEN_AI.OPERATION_NAME]: "agent_run",
13402
15206
  [GEN_AI.CONVERSATION_ID]: input.sessionId
13403
15207
  });
13404
15208
  try {
15209
+ this.config.team?.beginSessionTurn(input.sessionId);
13405
15210
  const rawHistory = (input.history ?? []).map((h) => ({
13406
15211
  role: h.role,
13407
15212
  content: h.content,
@@ -13427,7 +15232,11 @@ var AgentLoop = class {
13427
15232
  ...history,
13428
15233
  { role: "user", content: userContent, ...userParts ? { parts: userParts } : {} }
13429
15234
  ];
13430
- const taskNotice = new TaskNoticeTracker(this.config.backgroundTasks);
15235
+ const taskNotice = new TaskNoticeTracker(
15236
+ this.config.backgroundTasks,
15237
+ this.config.team,
15238
+ this.config.board
15239
+ );
13431
15240
  let todoNudged = false;
13432
15241
  let idleNudged = false;
13433
15242
  let blankNudged = false;
@@ -13456,9 +15265,21 @@ var AgentLoop = class {
13456
15265
  yield finish("budget-exceeded", stop.breach);
13457
15266
  return;
13458
15267
  }
13459
- const notice2 = taskNotice.notice();
13460
- if (notice2) messages.push({ role: "user", content: notice2 });
13461
- if (turn > 1) yield* this.drainSteer(input, messages);
15268
+ const notice2 = taskNotice.noticeDetailed(input.sessionId);
15269
+ if (notice2) messages.push({ role: "user", content: notice2.text });
15270
+ if (notice2 && notice2.agent.length > 0) {
15271
+ yield {
15272
+ type: "notice",
15273
+ code: "agent-message",
15274
+ text: [systemNote(AGENT_MESSAGE_NOTE_TITLE), ...notice2.agent].join("\n")
15275
+ };
15276
+ }
15277
+ if (turn > 1) {
15278
+ for await (const ev of this.drainSteer(input, messages)) {
15279
+ if (ev.type === "steer") pendingReceived.push(ev.text);
15280
+ yield ev;
15281
+ }
15282
+ }
13462
15283
  this.hooks.fire("turn:before", {
13463
15284
  sessionId: input.sessionId,
13464
15285
  userMessage: transformed,
@@ -13584,9 +15405,9 @@ var AgentLoop = class {
13584
15405
  }
13585
15406
  llmSpan.setAttribute("epoch.finish_reason", result.finishReason);
13586
15407
  break;
13587
- } catch (err) {
13588
- llmSpan.recordError(err);
13589
- if (isBodyTooLarge(err) && imagesRescue.offloaded === 0) {
15408
+ } catch (err3) {
15409
+ llmSpan.recordError(err3);
15410
+ if (isBodyTooLarge(err3) && imagesRescue.offloaded === 0) {
13590
15411
  const saved = this.tryOffloadForBodyLimit(messages);
13591
15412
  if (saved) {
13592
15413
  messages = saved.messages;
@@ -13602,8 +15423,8 @@ var AgentLoop = class {
13602
15423
  }
13603
15424
  }
13604
15425
  const engine = this.config.contextEngine;
13605
- const retriable = isContextOverflow(err) || isBodyTooLarge(err);
13606
- if (overflowRescued || !engine || !retriable) throw err;
15426
+ const retriable = isContextOverflow(err3) || isBodyTooLarge(err3);
15427
+ if (overflowRescued || !engine || !retriable) throw err3;
13607
15428
  overflowRescued = true;
13608
15429
  const rescued = await this.compressNow(messages, {
13609
15430
  totalTokens: totalInput + totalOutput,
@@ -13616,7 +15437,7 @@ var AgentLoop = class {
13616
15437
  runUsage
13617
15438
  );
13618
15439
  }
13619
- if (!shrank(messages, rescued.messages)) throw err;
15440
+ if (!shrank(messages, rescued.messages)) throw err3;
13620
15441
  messages = rescued.messages;
13621
15442
  yield {
13622
15443
  type: "notice",
@@ -13729,7 +15550,8 @@ var AgentLoop = class {
13729
15550
  index: turn,
13730
15551
  llmResponse: result.text,
13731
15552
  toolCalls: [],
13732
- duration: Date.now() - turnStart
15553
+ duration: Date.now() - turnStart,
15554
+ ...pendingReceived.length > 0 ? { received: pendingReceived.splice(0) } : {}
13733
15555
  });
13734
15556
  yield { type: "turn-complete", turn };
13735
15557
  const finalText = await this.hooks.transformResponse(result.text, input.sessionId);
@@ -13750,7 +15572,10 @@ ${finalText}` };
13750
15572
  content: finalText || NO_OUTPUT_TEXT,
13751
15573
  ...result.reasoningText ? { reasoning: result.reasoningText } : {}
13752
15574
  });
13753
- yield* this.drainSteer(input, messages);
15575
+ for await (const ev of this.drainSteer(input, messages)) {
15576
+ if (ev.type === "steer") pendingReceived.push(ev.text);
15577
+ yield ev;
15578
+ }
13754
15579
  continue;
13755
15580
  }
13756
15581
  const wantContinue = await this.hooks.wantsContinue(
@@ -13898,7 +15723,8 @@ ${finalText}` };
13898
15723
  args: e.args,
13899
15724
  result: e.output
13900
15725
  })),
13901
- duration: Date.now() - turnStart
15726
+ duration: Date.now() - turnStart,
15727
+ ...pendingReceived.length > 0 ? { received: pendingReceived.splice(0) } : {}
13902
15728
  });
13903
15729
  this.hooks.fire("turn:after", {
13904
15730
  sessionId: input.sessionId,
@@ -13954,15 +15780,15 @@ ${finalText}` };
13954
15780
  turns
13955
15781
  });
13956
15782
  yield finish("max-turns");
13957
- } catch (err) {
15783
+ } catch (err3) {
13958
15784
  if (this.isAborted(input.signal)) {
13959
15785
  await this.prompt.syncMemory(userText, lastText);
13960
15786
  yield { type: "notice", code: "aborted", text: t("agent_run.aborted") };
13961
15787
  yield finish("aborted");
13962
15788
  return;
13963
15789
  }
13964
- const msg = err instanceof Error ? err.message : String(err);
13965
- runSpan.recordError(err);
15790
+ const msg = err3 instanceof Error ? err3.message : String(err3);
15791
+ runSpan.recordError(err3);
13966
15792
  await this.prompt.syncMemory(userText, "");
13967
15793
  const errorText = t("agent_run.error", { message: msg });
13968
15794
  this.hooks.fire("turn:after", { sessionId: input.sessionId, response: errorText });
@@ -13978,6 +15804,7 @@ ${finalText}` };
13978
15804
  sessionId: input.sessionId,
13979
15805
  totalTokens: totalInput + totalOutput
13980
15806
  });
15807
+ this.config.team?.endSessionTurn(input.sessionId);
13981
15808
  runSpan.setAttribute("epoch.turns", turns.length);
13982
15809
  runSpan.setAttribute(GEN_AI.USAGE_INPUT_TOKENS, totalInput);
13983
15810
  runSpan.setAttribute(GEN_AI.USAGE_OUTPUT_TOKENS, totalOutput);
@@ -14048,7 +15875,8 @@ ${finalText}` };
14048
15875
  messages: compressed.messages.map((m) => unflattenMessage(m)),
14049
15876
  ...bill,
14050
15877
  ...compressed.carriedHead === void 0 ? {} : { carriedHead: compressed.carriedHead },
14051
- ...compressed.carriedTail === void 0 ? {} : { carriedTail: compressed.carriedTail }
15878
+ ...compressed.carriedTail === void 0 ? {} : { carriedTail: compressed.carriedTail },
15879
+ summarySkipped: compressed.summarySkipped === true
14052
15880
  };
14053
15881
  } catch {
14054
15882
  return { messages };
@@ -14174,10 +16002,10 @@ function loadModelEntries(homeDir) {
14174
16002
  let raw;
14175
16003
  try {
14176
16004
  raw = JSON.parse(readFileSync(path, "utf-8"));
14177
- } catch (err) {
16005
+ } catch (err3) {
14178
16006
  return {
14179
16007
  entries: [],
14180
- issues: [`${path}: ${err instanceof Error ? err.message : String(err)}`]
16008
+ issues: [`${path}: ${err3 instanceof Error ? err3.message : String(err3)}`]
14181
16009
  };
14182
16010
  }
14183
16011
  const list = raw?.models;
@@ -14225,9 +16053,9 @@ function saveModelEntries(homeDir, entries2, hostLabel) {
14225
16053
  try {
14226
16054
  writeFileSync(tmp, body2, { encoding: "utf-8", mode: 384 });
14227
16055
  renameSync(tmp, path);
14228
- } catch (err) {
16056
+ } catch (err3) {
14229
16057
  rmSync(tmp, { force: true });
14230
- throw err;
16058
+ throw err3;
14231
16059
  }
14232
16060
  }
14233
16061
  var EntryRefSchema = z.string().refine((v) => parseModelRef(v) !== void 0, { message: "expected @<model-entry-id>" });
@@ -14511,8 +16339,8 @@ var SettingsFileError = class extends Error {
14511
16339
  this.hint = hint;
14512
16340
  }
14513
16341
  };
14514
- function describeJsonError(err, text) {
14515
- const message = err instanceof Error ? err.message.split("\n")[0] ?? "" : "";
16342
+ function describeJsonError(err3, text) {
16343
+ const message = err3 instanceof Error ? err3.message.split("\n")[0] ?? "" : "";
14516
16344
  if (!message) return t("config_load.json_unknown_error");
14517
16345
  const at = /position (\d+)/.exec(message);
14518
16346
  if (!at?.[1]) return message;
@@ -14529,8 +16357,8 @@ function readSettingsFile(path, schema, known, empty, issues, sanitize = (raw) =
14529
16357
  let raw;
14530
16358
  try {
14531
16359
  raw = JSON.parse(text);
14532
- } catch (err) {
14533
- const reason9 = describeJsonError(err, text);
16360
+ } catch (err3) {
16361
+ const reason9 = describeJsonError(err3, text);
14534
16362
  issues.push({ path, message: t("config_load.json_invalid", { reason: reason9 }) });
14535
16363
  return { failed: reason9 };
14536
16364
  }
@@ -14968,13 +16796,13 @@ function readRawConfig(configPath2, issues) {
14968
16796
  const text = readFileSync(configPath2, "utf-8");
14969
16797
  if (text.trim() === "") return { kind: "ok", raw: {} };
14970
16798
  return { kind: "ok", raw: load(text) ?? {} };
14971
- } catch (err) {
16799
+ } catch (err3) {
14972
16800
  const backup = backupCorruptConfig(configPath2);
14973
16801
  issues.push({
14974
16802
  path: "(root)",
14975
16803
  message: t("config_load.bad_yaml", {
14976
16804
  path: configPath2,
14977
- reason: err.message.split("\n")[0] ?? "",
16805
+ reason: err3.message.split("\n")[0] ?? "",
14978
16806
  backup: backup ? t("config_load.bad_yaml_backup", { path: backup }) : t("config_load.bad_yaml_no_backup")
14979
16807
  })
14980
16808
  });
@@ -15254,16 +17082,16 @@ async function runImageProbe(model) {
15254
17082
  let withImage;
15255
17083
  try {
15256
17084
  withImage = await shoot(model, true);
15257
- } catch (err) {
15258
- return { verdict: "no", detail: err instanceof Error ? err.message : String(err) };
17085
+ } catch (err3) {
17086
+ return { verdict: "no", detail: err3 instanceof Error ? err3.message : String(err3) };
15259
17087
  }
15260
17088
  let baseline;
15261
17089
  try {
15262
17090
  baseline = await shoot(model, false);
15263
- } catch (err) {
17091
+ } catch (err3) {
15264
17092
  return {
15265
17093
  verdict: "inconclusive",
15266
- detail: `baseline failed: ${err instanceof Error ? err.message : String(err)}`
17094
+ detail: `baseline failed: ${err3 instanceof Error ? err3.message : String(err3)}`
15267
17095
  };
15268
17096
  }
15269
17097
  const shot = withImage.inputTokens;
@@ -15793,11 +17621,11 @@ var ProviderSdkMissingError = class extends Error {
15793
17621
  async function createModelFactory(type, opts) {
15794
17622
  try {
15795
17623
  return await LOADERS[type](opts);
15796
- } catch (err) {
15797
- if (isModuleNotFound(err)) {
15798
- throw new ProviderSdkMissingError(type, PACKAGES[type], err);
17624
+ } catch (err3) {
17625
+ if (isModuleNotFound(err3)) {
17626
+ throw new ProviderSdkMissingError(type, PACKAGES[type], err3);
15799
17627
  }
15800
- throw err;
17628
+ throw err3;
15801
17629
  }
15802
17630
  }
15803
17631
  async function createEntryFactory(entry, apiKey) {
@@ -15805,9 +17633,9 @@ async function createEntryFactory(entry, apiKey) {
15805
17633
  const pkg = type === "openai-compatible" && entry.protocol === "anthropic-messages" ? "@ai-sdk/anthropic" : PACKAGES[type];
15806
17634
  try {
15807
17635
  return await loadEntry(entry, apiKey);
15808
- } catch (err) {
15809
- if (isModuleNotFound(err)) throw new ProviderSdkMissingError(type, pkg, err);
15810
- throw err;
17636
+ } catch (err3) {
17637
+ if (isModuleNotFound(err3)) throw new ProviderSdkMissingError(type, pkg, err3);
17638
+ throw err3;
15811
17639
  }
15812
17640
  }
15813
17641
  async function loadEntry(entry, apiKey) {
@@ -15880,11 +17708,11 @@ var CARRIES_REASONING_BACK = {
15880
17708
  function carriesReasoningBack(type) {
15881
17709
  return CARRIES_REASONING_BACK[type];
15882
17710
  }
15883
- function isModuleNotFound(err) {
15884
- if (!err || typeof err !== "object") return false;
15885
- const code = err.code;
17711
+ function isModuleNotFound(err3) {
17712
+ if (!err3 || typeof err3 !== "object") return false;
17713
+ const code = err3.code;
15886
17714
  if (code === "ERR_MODULE_NOT_FOUND" || code === "MODULE_NOT_FOUND") return true;
15887
- const msg = err instanceof Error ? err.message : "";
17715
+ const msg = err3 instanceof Error ? err3.message : "";
15888
17716
  return /Cannot find (module|package)|Failed to resolve/i.test(msg);
15889
17717
  }
15890
17718
  // src/provider/entry-route.ts
@@ -16180,8 +18008,8 @@ var ProviderRouter = class {
16180
18008
  }
16181
18009
  if (this.effort !== void 0) {
16182
18010
  const state = this.getEffort();
16183
- const ok2 = this.effort === "off" ? state.canTurnOff : state.levels.includes(this.effort);
16184
- if (!ok2) this.effort = void 0;
18011
+ const ok4 = this.effort === "off" ? state.canTurnOff : state.levels.includes(this.effort);
18012
+ if (!ok4) this.effort = void 0;
16185
18013
  }
16186
18014
  }
16187
18015
  refreshedSelection(sel) {
@@ -16211,9 +18039,9 @@ var ProviderRouter = class {
16211
18039
  this.effort = void 0;
16212
18040
  return true;
16213
18041
  }
16214
- const ok2 = choice === "off" ? state.canTurnOff : state.levels.includes(choice);
16215
- if (ok2) this.effort = choice;
16216
- return ok2;
18042
+ const ok4 = choice === "off" ? state.canTurnOff : state.levels.includes(choice);
18043
+ if (ok4) this.effort = choice;
18044
+ return ok4;
16217
18045
  }
16218
18046
  reasoningFor(input, ct, entry) {
16219
18047
  if (input.entry || entry !== this.selection.entry) return void 0;
@@ -16314,8 +18142,8 @@ var ProviderRouter = class {
16314
18142
  let factory;
16315
18143
  try {
16316
18144
  factory = opts.entry ? await createEntryFactory(opts.entry, opts.apiKey || void 0) : await createModelFactory(route, opts);
16317
- } catch (err) {
16318
- throw new ProviderError(err instanceof Error ? err.message : String(err), 1005, false);
18145
+ } catch (err3) {
18146
+ throw new ProviderError(err3 instanceof Error ? err3.message : String(err3), 1005, false);
16319
18147
  }
16320
18148
  this.factories.set(route, factory);
16321
18149
  return factory(modelId ?? this.selection.model);
@@ -16344,9 +18172,9 @@ var ProviderRouter = class {
16344
18172
  const fb = this.fallbackEntry(sel.entry, /* @__PURE__ */ new Set([entryTried(sel.entry)]));
16345
18173
  return fb && !this.failures.isAbandoned(this.routeOf(fb.provider, fb.entry)) ? fb : sel;
16346
18174
  }
16347
- async recover(err, state) {
16348
- const { code, recovery } = classifyProviderError(err);
16349
- const message = describeProviderError(err);
18175
+ async recover(err3, state) {
18176
+ const { code, recovery } = classifyProviderError(err3);
18177
+ const message = describeProviderError(err3);
16350
18178
  const stay = { kind: "continue", ct: state.ct, cm: state.cm, entry: state.entry };
16351
18179
  if (code === PROVIDER_ABORTED) return { kind: "give-up", message, code };
16352
18180
  if (recovery === "retry") {
@@ -16471,8 +18299,8 @@ var ProviderRouter = class {
16471
18299
  ...applied === void 0 ? {} : { responseFormatApplied: applied },
16472
18300
  ...warnings ? { warnings } : {}
16473
18301
  };
16474
- } catch (err) {
16475
- const plan = await this.recover(err, state);
18302
+ } catch (err3) {
18303
+ const plan = await this.recover(err3, state);
16476
18304
  if (plan.kind === "give-up") throw new ProviderError(plan.message, plan.code, false);
16477
18305
  state.ct = plan.ct;
16478
18306
  state.cm = plan.cm;
@@ -16574,8 +18402,8 @@ var ProviderRouter = class {
16574
18402
  ...warnings ? { warnings } : {}
16575
18403
  };
16576
18404
  return;
16577
- } catch (err) {
16578
- const cause = streamPartError ?? err;
18405
+ } catch (err3) {
18406
+ const cause = streamPartError ?? err3;
16579
18407
  if (emitted) {
16580
18408
  yield { type: "error", error: describeProviderError(cause) };
16581
18409
  return;
@@ -16909,9 +18737,9 @@ async function testModelEntry(entry, apiKey) {
16909
18737
  abortSignal: AbortSignal.timeout(2e4)
16910
18738
  });
16911
18739
  return { code: "ok", models, latencyMs: elapsed() };
16912
- } catch (err) {
16913
- const status = extractStatus(err);
16914
- const detail = redact(describeProviderError(err), apiKey);
18740
+ } catch (err3) {
18741
+ const status = extractStatus(err3);
18742
+ const detail = redact(describeProviderError(err3), apiKey);
16915
18743
  return {
16916
18744
  code: classify(status, detail),
16917
18745
  models,
@@ -17179,9 +19007,9 @@ function commit(path, body2, createMode, value) {
17179
19007
  try {
17180
19008
  writeFileSync(tmp, body2, { encoding: "utf-8", mode });
17181
19009
  renameSync(tmp, path);
17182
- } catch (err) {
19010
+ } catch (err3) {
17183
19011
  rmSync(tmp, { force: true });
17184
- throw err;
19012
+ throw err3;
17185
19013
  }
17186
19014
  } catch {
17187
19015
  return { ok: false, reason: "io" };
@@ -17598,13 +19426,13 @@ function readRaw(path) {
17598
19426
  let text;
17599
19427
  try {
17600
19428
  text = readFileSync(path, "utf-8");
17601
- } catch (err) {
17602
- return { issue: reason5(err) };
19429
+ } catch (err3) {
19430
+ return { issue: reason5(err3) };
17603
19431
  }
17604
19432
  try {
17605
19433
  return { value: JSON.parse(text) };
17606
- } catch (err) {
17607
- return { issue: reason5(err) };
19434
+ } catch (err3) {
19435
+ return { issue: reason5(err3) };
17608
19436
  }
17609
19437
  }
17610
19438
  function readVimMode(raw, issues) {
@@ -17687,8 +19515,8 @@ function supportsSequence(action) {
17687
19515
  function warn(detail, code) {
17688
19516
  return { module: MODULE2, status: "warn", detail, code };
17689
19517
  }
17690
- function reason5(err) {
17691
- return (err instanceof Error ? err.message : String(err)).split("\n")[0] ?? "";
19518
+ function reason5(err3) {
19519
+ return (err3 instanceof Error ? err3.message : String(err3)).split("\n")[0] ?? "";
17692
19520
  }
17693
19521
  // src/memory/tokenize.ts
17694
19522
  var CJK_RUN = /[぀-ヿ㐀-䶿一-鿿豈-﫿가-힯]+/gu;
@@ -17732,7 +19560,7 @@ function buildSearchQuery(query) {
17732
19560
  // src/memory/db.ts
17733
19561
  var NS2 = "memory";
17734
19562
  var FTS_SCHEMA_VERSION = 2;
17735
- var MIGRATIONS2 = [
19563
+ var MIGRATIONS3 = [
17736
19564
  {
17737
19565
  id: "memory-baseline",
17738
19566
  version: 1,
@@ -17774,10 +19602,10 @@ var MemoryDB = class {
17774
19602
  db;
17775
19603
  path;
17776
19604
  nextPosition = { memory: 0, user: 0 };
17777
- constructor(dbPath) {
17778
- this.path = dbPath;
19605
+ constructor(dbPath2) {
19606
+ this.path = dbPath2;
17779
19607
  this.db = openDatabase(this.path);
17780
- migrate(this.db, NS2, MIGRATIONS2);
19608
+ migrate(this.db, NS2, MIGRATIONS3);
17781
19609
  this.migrateFts();
17782
19610
  for (const target of ["memory", "user"]) {
17783
19611
  const row = this.db.prepare(
@@ -18020,9 +19848,9 @@ function stripUndefined(obj) {
18020
19848
  return Object.fromEntries(Object.entries(obj).filter(([, v]) => v !== void 0));
18021
19849
  }
18022
19850
  var MemoryManager = class {
18023
- constructor(dbPath, memDir, config, options = {}) {
19851
+ constructor(dbPath2, memDir, config, options = {}) {
18024
19852
  this.options = options;
18025
- const dp = dbPath ?? DB_PATH;
19853
+ const dp = dbPath2 ?? DB_PATH;
18026
19854
  const md = memDir ?? MEM_DIR;
18027
19855
  this.memDir = md;
18028
19856
  mkdirSync(dirname(dp), { recursive: true });
@@ -18440,8 +20268,8 @@ var MemoryManager = class {
18440
20268
  });
18441
20269
  continue;
18442
20270
  }
18443
- const firstLine4 = (entry.content.split("\n")[0] ?? "").trim();
18444
- const summary = countCodePoints(firstLine4) > INDEX_SUMMARY_CHARS ? `${headCodePoints(firstLine4, INDEX_SUMMARY_CHARS)}\u2026` : firstLine4;
20271
+ const firstLine5 = (entry.content.split("\n")[0] ?? "").trim();
20272
+ const summary = countCodePoints(firstLine5) > INDEX_SUMMARY_CHARS ? `${headCodePoints(firstLine5, INDEX_SUMMARY_CHARS)}\u2026` : firstLine5;
18445
20273
  out.push({ id, target, summary, charLength: entry.content.length });
18446
20274
  }
18447
20275
  return out;
@@ -18768,7 +20596,7 @@ function nonEmpty(items) {
18768
20596
  function isRecord4(v) {
18769
20597
  return typeof v === "object" && v !== null;
18770
20598
  }
18771
- function str3(v) {
20599
+ function str5(v) {
18772
20600
  return typeof v === "string" && v.length > 0 ? v : void 0;
18773
20601
  }
18774
20602
  function isSessionOmitReason(value) {
@@ -18780,8 +20608,8 @@ function parseToolCalls(json) {
18780
20608
  const calls = [];
18781
20609
  for (const item of raw) {
18782
20610
  if (!isRecord4(item)) continue;
18783
- const toolCallId = str3(item["toolCallId"]) ?? str3(item["id"]);
18784
- const toolName = str3(item["toolName"]) ?? str3(item["name"]);
20611
+ const toolCallId = str5(item["toolCallId"]) ?? str5(item["id"]);
20612
+ const toolName = str5(item["toolName"]) ?? str5(item["name"]);
18785
20613
  if (!toolCallId || !toolName) continue;
18786
20614
  const input = item["input"] ?? item["args"];
18787
20615
  calls.push({ toolCallId, toolName, input: isRecord4(input) ? input : {} });
@@ -18796,10 +20624,10 @@ function parseArtifacts(raw) {
18796
20624
  const kind = item["kind"];
18797
20625
  out.push({
18798
20626
  kind: kind === "image" || kind === "audio" || kind === "file" ? kind : "file",
18799
- mediaType: str3(item["mediaType"]) ?? "application/octet-stream",
20627
+ mediaType: str5(item["mediaType"]) ?? "application/octet-stream",
18800
20628
  summary: typeof item["summary"] === "string" ? item["summary"] : "",
18801
20629
  bytes: typeof item["bytes"] === "number" ? item["bytes"] : 0,
18802
- ...str3(item["path"]) ? { path: item["path"] } : {},
20630
+ ...str5(item["path"]) ? { path: item["path"] } : {},
18803
20631
  ...typeof item["width"] === "number" ? { width: item["width"] } : {},
18804
20632
  ...typeof item["height"] === "number" ? { height: item["height"] } : {},
18805
20633
  ...typeof item["estimatedTokens"] === "number" ? { estimatedTokens: item["estimatedTokens"] } : {}
@@ -18813,8 +20641,8 @@ function parseToolResults(json) {
18813
20641
  const results = [];
18814
20642
  for (const item of raw) {
18815
20643
  if (!isRecord4(item)) continue;
18816
- const toolCallId = str3(item["toolCallId"]);
18817
- const toolName = str3(item["toolName"]);
20644
+ const toolCallId = str5(item["toolCallId"]);
20645
+ const toolName = str5(item["toolName"]);
18818
20646
  if (!toolCallId || !toolName) continue;
18819
20647
  const artifacts = parseArtifacts(item["artifacts"]);
18820
20648
  results.push({
@@ -18826,24 +20654,41 @@ function parseToolResults(json) {
18826
20654
  }
18827
20655
  return nonEmpty(results);
18828
20656
  }
20657
+ function parseDiffs(json) {
20658
+ const raw = parseArray(json);
20659
+ if (!raw) return void 0;
20660
+ const diffs = [];
20661
+ for (const item of raw) {
20662
+ if (!isRecord4(item)) continue;
20663
+ const filePath = str5(item["filePath"]);
20664
+ if (!filePath) continue;
20665
+ diffs.push({
20666
+ filePath,
20667
+ ...typeof item["oldContent"] === "string" ? { oldContent: item["oldContent"] } : {},
20668
+ ...typeof item["newContent"] === "string" ? { newContent: item["newContent"] } : {},
20669
+ ...item["omitted"] === "too-large" ? { omitted: "too-large" } : {}
20670
+ });
20671
+ }
20672
+ return nonEmpty(diffs);
20673
+ }
18829
20674
  function parseParts(json) {
18830
20675
  const raw = parseArray(json);
18831
20676
  if (!raw) return void 0;
18832
20677
  const parts = [];
18833
20678
  for (const item of raw) {
18834
20679
  if (!isRecord4(item)) continue;
18835
- const mediaType = str3(item["mediaType"]);
20680
+ const mediaType = str5(item["mediaType"]);
18836
20681
  const media = mediaType ? { mediaType } : {};
18837
20682
  if (item["type"] === "text") {
18838
20683
  if (typeof item["text"] === "string") parts.push({ type: "text", text: item["text"] });
18839
20684
  continue;
18840
20685
  }
18841
20686
  if (item["type"] === "session") {
18842
- const ref = str3(item["ref"]);
20687
+ const ref = str5(item["ref"]);
18843
20688
  if (!ref) continue;
18844
- const sessionId = str3(item["sessionId"]);
18845
- const title = str3(item["title"]);
18846
- const omitted = str3(item["omitted"]);
20689
+ const sessionId = str5(item["sessionId"]);
20690
+ const title = str5(item["title"]);
20691
+ const omitted = str5(item["omitted"]);
18847
20692
  parts.push({
18848
20693
  type: "session",
18849
20694
  ref,
@@ -18856,9 +20701,9 @@ function parseParts(json) {
18856
20701
  continue;
18857
20702
  }
18858
20703
  if (item["type"] === "file") {
18859
- const filePath = str3(item["path"]);
20704
+ const filePath = str5(item["path"]);
18860
20705
  if (!filePath) continue;
18861
- const fileOmitted = str3(item["omitted"]);
20706
+ const fileOmitted = str5(item["omitted"]);
18862
20707
  parts.push({
18863
20708
  type: "file",
18864
20709
  path: filePath,
@@ -18868,8 +20713,8 @@ function parseParts(json) {
18868
20713
  continue;
18869
20714
  }
18870
20715
  if (item["type"] !== "image") continue;
18871
- const path = str3(item["path"]);
18872
- const url = str3(item["url"]);
20716
+ const path = str5(item["path"]);
20717
+ const url = str5(item["url"]);
18873
20718
  if (path) parts.push({ type: "image", path, ...media });
18874
20719
  else if (url) parts.push({ type: "image", url, ...media });
18875
20720
  }
@@ -18916,10 +20761,10 @@ function parseTurnFacts(json) {
18916
20761
  const toolCalls = num2(raw["toolCalls"]);
18917
20762
  if (toolCalls === void 0) return void 0;
18918
20763
  const usage = parseUsage(raw["usage"]);
18919
- const model = str3(raw["model"]);
18920
- const requestedModel = str3(raw["requestedModel"]);
20764
+ const model = str5(raw["model"]);
20765
+ const requestedModel = str5(raw["requestedModel"]);
18921
20766
  const durationMs = num2(raw["durationMs"]);
18922
- const error = str3(raw["error"])?.trim() || void 0;
20767
+ const error = str5(raw["error"])?.trim() || void 0;
18923
20768
  return {
18924
20769
  toolCalls,
18925
20770
  ...usage ? { usage } : {},
@@ -18941,10 +20786,10 @@ function parseUserCommand(json) {
18941
20786
  return void 0;
18942
20787
  }
18943
20788
  if (!isRecord4(raw)) return void 0;
18944
- const name = str3(raw["name"]);
20789
+ const name = str5(raw["name"]);
18945
20790
  if (!name) return void 0;
18946
- const displayName = str3(raw["displayName"]);
18947
- const args = str3(raw["args"]);
20791
+ const displayName = str5(raw["displayName"]);
20792
+ const args = str5(raw["args"]);
18948
20793
  return {
18949
20794
  name,
18950
20795
  ...displayName ? { displayName } : {},
@@ -19269,13 +21114,21 @@ var FTS_EXTERNAL_MIGRATIONS = [
19269
21114
  up: (db) => {
19270
21115
  db.exec(`ALTER TABLE messages ADD COLUMN command TEXT`);
19271
21116
  }
21117
+ },
21118
+ {
21119
+ id: "messages-diffs",
21120
+ version: 17,
21121
+ description: "\u6D88\u606F\u8868\u52A0 diffs \u4E00\u5217\uFF08\u8865\u4E01\u9884\u89C8\u843D\u76D8\uFF0C2026-10-30\uFF09",
21122
+ up: (db) => {
21123
+ db.exec(`ALTER TABLE messages ADD COLUMN diffs TEXT`);
21124
+ }
19272
21125
  }
19273
21126
  ];
19274
21127
  var SessionDB = class {
19275
21128
  db;
19276
21129
  path;
19277
- constructor(dbPath$1) {
19278
- this.path = dbPath$1 ?? dbPath();
21130
+ constructor(dbPath2) {
21131
+ this.path = dbPath2 ?? dbPath();
19279
21132
  this.db = openDatabase(this.path);
19280
21133
  migrate(this.db, NS3, SESSION_MIGRATIONS);
19281
21134
  this.migrateFtsIndex();
@@ -19283,10 +21136,10 @@ var SessionDB = class {
19283
21136
  migrateFtsIndex() {
19284
21137
  try {
19285
21138
  migrate(this.db, NS3, FTS_EXTERNAL_MIGRATIONS);
19286
- } catch (err) {
21139
+ } catch (err3) {
19287
21140
  log2.warn(
19288
21141
  "FTS index rebuild (v8) failed; keeping the legacy schema for now (content stored three times, ~36% larger). Will retry on next start.",
19289
- { error: err instanceof Error ? err.message : String(err) }
21142
+ { error: err3 instanceof Error ? err3.message : String(err3) }
19290
21143
  );
19291
21144
  }
19292
21145
  }
@@ -19466,8 +21319,8 @@ var SessionDB = class {
19466
21319
  insertMessage(msg) {
19467
21320
  const info = this.db.prepare(
19468
21321
  `
19469
- INSERT INTO messages (session_id, role, content, tool_call_id, tool_calls, tool_results, parts, command, tool_name, timestamp, token_count, finish_reason, reasoning, turn_facts, active, compacted, observed)
19470
- VALUES (@sessionId, @role, @content, @toolCallId, @toolCalls, @toolResults, @parts, @command, @toolName, @timestamp, @tokenCount, @finishReason, @reasoning, @turnFacts, 1, 0, 0)
21322
+ INSERT INTO messages (session_id, role, content, tool_call_id, tool_calls, tool_results, parts, command, tool_name, timestamp, token_count, finish_reason, reasoning, diffs, turn_facts, active, compacted, observed)
21323
+ VALUES (@sessionId, @role, @content, @toolCallId, @toolCalls, @toolResults, @parts, @command, @toolName, @timestamp, @tokenCount, @finishReason, @reasoning, @diffs, @turnFacts, 1, 0, 0)
19471
21324
  `
19472
21325
  ).run({
19473
21326
  ...msg,
@@ -19480,6 +21333,7 @@ var SessionDB = class {
19480
21333
  tokenCount: msg.tokenCount ?? null,
19481
21334
  finishReason: msg.finishReason ?? null,
19482
21335
  reasoning: msg.reasoning ?? null,
21336
+ diffs: encodeColumn(msg.diffs),
19483
21337
  turnFacts: encodeTurnFacts(msg.turnFacts)
19484
21338
  });
19485
21339
  const toolCalls = msg.toolCalls?.length ?? 0;
@@ -19729,8 +21583,8 @@ var SessionDB = class {
19729
21583
  forkMessages(fromSessionId, toSessionId, upToIndex) {
19730
21584
  const messages = this.db.prepare("SELECT * FROM messages WHERE session_id = ? AND id <= ? ORDER BY timestamp ASC").all(fromSessionId, upToIndex);
19731
21585
  const stmt = this.db.prepare(`
19732
- INSERT INTO messages (session_id, role, content, tool_call_id, tool_calls, tool_results, parts, command, tool_name, timestamp, token_count, finish_reason, reasoning, turn_facts, active, compacted, observed)
19733
- VALUES (@sessionId, @role, @content, @toolCallId, @toolCalls, @toolResults, @parts, @command, @toolName, @timestamp, @tokenCount, @finishReason, @reasoning, @turnFacts, @active, @compacted, @observed)
21586
+ INSERT INTO messages (session_id, role, content, tool_call_id, tool_calls, tool_results, parts, command, tool_name, timestamp, token_count, finish_reason, reasoning, diffs, turn_facts, active, compacted, observed)
21587
+ VALUES (@sessionId, @role, @content, @toolCallId, @toolCalls, @toolResults, @parts, @command, @toolName, @timestamp, @tokenCount, @finishReason, @reasoning, @diffs, @turnFacts, @active, @compacted, @observed)
19734
21588
  `);
19735
21589
  for (const m of messages) {
19736
21590
  const { id: _id, ...rest } = m;
@@ -19748,6 +21602,7 @@ var SessionDB = class {
19748
21602
  tokenCount: rest["token_count"] ?? null,
19749
21603
  finishReason: rest["finish_reason"] ?? null,
19750
21604
  reasoning: rest["reasoning"] ?? null,
21605
+ diffs: rest["diffs"] ?? null,
19751
21606
  turnFacts: rest["turn_facts"] ?? null,
19752
21607
  active: rest["active"] ?? 1,
19753
21608
  compacted: rest["compacted"] ?? 0,
@@ -19831,6 +21686,7 @@ var SessionDB = class {
19831
21686
  tokenCount: row["token_count"],
19832
21687
  finishReason: row["finish_reason"],
19833
21688
  reasoning: row["reasoning"],
21689
+ diffs: parseDiffs(row["diffs"]),
19834
21690
  active: row["active"] === 1,
19835
21691
  compacted: row["compacted"] === 1,
19836
21692
  observed: row["observed"] === 1
@@ -19865,8 +21721,8 @@ function integrityOf(db, table, compareContent = false) {
19865
21721
  db.prepare(`INSERT INTO ${table}(${table}) VALUES('integrity-check')`).run();
19866
21722
  }
19867
21723
  return null;
19868
- } catch (err) {
19869
- return err instanceof Error ? err.message : String(err);
21724
+ } catch (err3) {
21725
+ return err3 instanceof Error ? err3.message : String(err3);
19870
21726
  }
19871
21727
  }
19872
21728
  function indexBytesOf(db) {
@@ -19942,8 +21798,8 @@ function reclaimFtsSpace(db, vacuum = true) {
19942
21798
  if (vacuum) {
19943
21799
  try {
19944
21800
  db.exec("VACUUM");
19945
- } catch (err) {
19946
- vacuumError = err instanceof Error ? err.message : String(err);
21801
+ } catch (err3) {
21802
+ vacuumError = err3 instanceof Error ? err3.message : String(err3);
19947
21803
  }
19948
21804
  }
19949
21805
  const vacuumed = vacuum && vacuumError === null;
@@ -20153,8 +22009,8 @@ var SessionManager = class {
20153
22009
  queries;
20154
22010
  goals;
20155
22011
  references;
20156
- constructor(dbPath) {
20157
- this.db = new SessionDB(dbPath);
22012
+ constructor(dbPath2) {
22013
+ this.db = new SessionDB(dbPath2);
20158
22014
  this.queries = new SessionQueries(this.db.db);
20159
22015
  this.goals = new GoalStore(this.db.db);
20160
22016
  this.references = new SessionReferences(this.db.db);
@@ -20286,12 +22142,12 @@ var SessionManager = class {
20286
22142
  ...input.todos === void 0 ? {} : { todoIds: todos.map((t83) => t83.id) },
20287
22143
  ...goal === void 0 ? {} : { goalId: goal.id }
20288
22144
  };
20289
- } catch (err) {
22145
+ } catch (err3) {
20290
22146
  return {
20291
22147
  ok: false,
20292
22148
  id,
20293
22149
  reason: "failed",
20294
- ...err instanceof Error ? { detail: err.name } : {}
22150
+ ...err3 instanceof Error ? { detail: err3.name } : {}
20295
22151
  };
20296
22152
  }
20297
22153
  }
@@ -20869,8 +22725,8 @@ function inspect(input, resolved, root, accepted) {
20869
22725
  }
20870
22726
  var MAX_RECENT_WORKSPACES = 20;
20871
22727
  var FILE_VERSION2 = 1;
20872
- function describe7(err) {
20873
- return err instanceof Error ? err.message : String(err);
22728
+ function describe7(err3) {
22729
+ return err3 instanceof Error ? err3.message : String(err3);
20874
22730
  }
20875
22731
  var RecentWorkspaces = class {
20876
22732
  constructor(filePath = workspacesPath()) {
@@ -20907,9 +22763,9 @@ var RecentWorkspaces = class {
20907
22763
  let parsed;
20908
22764
  try {
20909
22765
  parsed = JSON.parse(readFileSync(this.filePath, "utf-8"));
20910
- } catch (err) {
22766
+ } catch (err3) {
20911
22767
  this.loadErrors.push(
20912
- (lang) => t("workspace.recent_unreadable", { path: this.filePath, reason: describe7(err) }, lang)
22768
+ (lang) => t("workspace.recent_unreadable", { path: this.filePath, reason: describe7(err3) }, lang)
20913
22769
  );
20914
22770
  return;
20915
22771
  }
@@ -20959,10 +22815,10 @@ var RecentWorkspaces = class {
20959
22815
  mkdirSync(dirname(this.filePath), { recursive: true });
20960
22816
  writeFileSync(tmp, body2, { encoding: "utf-8", mode: 384 });
20961
22817
  renameSync(tmp, this.filePath);
20962
- } catch (err) {
22818
+ } catch (err3) {
20963
22819
  rmSync(tmp, { force: true });
20964
22820
  this.writeErrors.push(
20965
- (lang) => t("workspace.recent_write_failed", { path: this.filePath, reason: describe7(err) }, lang)
22821
+ (lang) => t("workspace.recent_write_failed", { path: this.filePath, reason: describe7(err3) }, lang)
20966
22822
  );
20967
22823
  }
20968
22824
  }
@@ -20974,8 +22830,8 @@ function isRecentWorkspace(value) {
20974
22830
  }
20975
22831
  var MAX_LAST_OPEN_SESSIONS = 20;
20976
22832
  var FILE_VERSION3 = 1;
20977
- function describe8(err) {
20978
- return err instanceof Error ? err.message : String(err);
22833
+ function describe8(err3) {
22834
+ return err3 instanceof Error ? err3.message : String(err3);
20979
22835
  }
20980
22836
  var LastOpenSessions = class {
20981
22837
  constructor(filePath = lastSessionsPath()) {
@@ -21011,9 +22867,9 @@ var LastOpenSessions = class {
21011
22867
  let parsed;
21012
22868
  try {
21013
22869
  parsed = JSON.parse(readFileSync(this.filePath, "utf-8"));
21014
- } catch (err) {
22870
+ } catch (err3) {
21015
22871
  this.loadErrors.push(
21016
- (lang) => t("last_session.unreadable", { path: this.filePath, reason: describe8(err) }, lang)
22872
+ (lang) => t("last_session.unreadable", { path: this.filePath, reason: describe8(err3) }, lang)
21017
22873
  );
21018
22874
  return;
21019
22875
  }
@@ -21037,10 +22893,10 @@ var LastOpenSessions = class {
21037
22893
  mkdirSync(dirname(this.filePath), { recursive: true });
21038
22894
  writeFileSync(tmp, body2, { encoding: "utf-8", mode: 384 });
21039
22895
  renameSync(tmp, this.filePath);
21040
- } catch (err) {
22896
+ } catch (err3) {
21041
22897
  rmSync(tmp, { force: true });
21042
22898
  this.writeErrors.push(
21043
- (lang) => t("last_session.write_failed", { path: this.filePath, reason: describe8(err) }, lang)
22899
+ (lang) => t("last_session.write_failed", { path: this.filePath, reason: describe8(err3) }, lang)
21044
22900
  );
21045
22901
  }
21046
22902
  }
@@ -21053,8 +22909,8 @@ function isLastOpenSession(value) {
21053
22909
  var isWidthShaped = (value) => typeof value === "number" && Number.isInteger(value) && value > 0;
21054
22910
  var FILE_VERSION4 = 2;
21055
22911
  var isPlainObject2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
21056
- function describe9(err) {
21057
- return err instanceof Error ? err.message : String(err);
22912
+ function describe9(err3) {
22913
+ return err3 instanceof Error ? err3.message : String(err3);
21058
22914
  }
21059
22915
  var AppearanceStore = class {
21060
22916
  constructor(filePath = appearancePath()) {
@@ -21109,9 +22965,9 @@ var AppearanceStore = class {
21109
22965
  this.prefs = {};
21110
22966
  try {
21111
22967
  rmSync(this.filePath, { force: true });
21112
- } catch (err) {
22968
+ } catch (err3) {
21113
22969
  this.writeErrors.push(
21114
- (lang) => t("appearance.write_failed", { path: this.filePath, reason: describe9(err) }, lang)
22970
+ (lang) => t("appearance.write_failed", { path: this.filePath, reason: describe9(err3) }, lang)
21115
22971
  );
21116
22972
  }
21117
22973
  }
@@ -21121,9 +22977,9 @@ var AppearanceStore = class {
21121
22977
  let parsed;
21122
22978
  try {
21123
22979
  parsed = JSON.parse(readFileSync(this.filePath, "utf-8"));
21124
- } catch (err) {
22980
+ } catch (err3) {
21125
22981
  this.loadErrors.push(
21126
- (lang) => t("appearance.unreadable", { path: this.filePath, reason: describe9(err) }, lang)
22982
+ (lang) => t("appearance.unreadable", { path: this.filePath, reason: describe9(err3) }, lang)
21127
22983
  );
21128
22984
  return;
21129
22985
  }
@@ -21172,10 +23028,10 @@ var AppearanceStore = class {
21172
23028
  mkdirSync(dirname(this.filePath), { recursive: true });
21173
23029
  writeFileSync(tmp, body2, { encoding: "utf-8", mode: 384 });
21174
23030
  renameSync(tmp, this.filePath);
21175
- } catch (err) {
23031
+ } catch (err3) {
21176
23032
  rmSync(tmp, { force: true });
21177
23033
  this.writeErrors.push(
21178
- (lang) => t("appearance.write_failed", { path: this.filePath, reason: describe9(err) }, lang)
23034
+ (lang) => t("appearance.write_failed", { path: this.filePath, reason: describe9(err3) }, lang)
21179
23035
  );
21180
23036
  }
21181
23037
  }
@@ -21931,7 +23787,7 @@ function suggestRuleFromApproval(request) {
21931
23787
  // src/schedule/store.ts
21932
23788
  init_trigger();
21933
23789
  var NS4 = "schedule";
21934
- var MIGRATIONS3 = [
23790
+ var MIGRATIONS4 = [
21935
23791
  {
21936
23792
  id: "schedule-baseline",
21937
23793
  version: 1,
@@ -22018,10 +23874,10 @@ var MIGRATIONS3 = [
22018
23874
  var ScheduleStore = class {
22019
23875
  db;
22020
23876
  path;
22021
- constructor(dbPath) {
22022
- this.path = dbPath;
23877
+ constructor(dbPath2) {
23878
+ this.path = dbPath2;
22023
23879
  this.db = openDatabase(this.path);
22024
- migrate(this.db, NS4, MIGRATIONS3);
23880
+ migrate(this.db, NS4, MIGRATIONS4);
22025
23881
  }
22026
23882
  get connection() {
22027
23883
  return this.db;
@@ -22399,8 +24255,8 @@ function pidAlive(pid) {
22399
24255
  try {
22400
24256
  process.kill(pid, 0);
22401
24257
  return true;
22402
- } catch (err) {
22403
- return err.code === "EPERM";
24258
+ } catch (err3) {
24259
+ return err3.code === "EPERM";
22404
24260
  }
22405
24261
  }
22406
24262
  function acquireScheduleLock(db, scheduleId, clock2 = Date.now) {
@@ -22430,8 +24286,8 @@ function acquireScheduleLock(db, scheduleId, clock2 = Date.now) {
22430
24286
  db.prepare(
22431
24287
  "UPDATE schedule_locks SET heartbeat_at = ? WHERE schedule_id = ? AND pid = ? AND host = ?"
22432
24288
  ).run(clock2(), scheduleId, pid, host);
22433
- } catch (err) {
22434
- log4.debug("lock heartbeat write failed", { scheduleId, err: String(err) });
24289
+ } catch (err3) {
24290
+ log4.debug("lock heartbeat write failed", { scheduleId, err: String(err3) });
22435
24291
  }
22436
24292
  }, LOCK_HEARTBEAT_MS);
22437
24293
  beat.unref?.();
@@ -22447,8 +24303,8 @@ function acquireScheduleLock(db, scheduleId, clock2 = Date.now) {
22447
24303
  db.prepare(
22448
24304
  "DELETE FROM schedule_locks WHERE schedule_id = ? AND pid = ? AND host = ?"
22449
24305
  ).run(scheduleId, pid, host);
22450
- } catch (err) {
22451
- log4.debug("lock release failed", { scheduleId, err: String(err) });
24306
+ } catch (err3) {
24307
+ log4.debug("lock release failed", { scheduleId, err: String(err3) });
22452
24308
  }
22453
24309
  }
22454
24310
  }
@@ -22878,10 +24734,10 @@ function loadPolicyRules(dir) {
22878
24734
  let files;
22879
24735
  try {
22880
24736
  files = readdirSync(dir).filter((f) => f.endsWith(".toml"));
22881
- } catch (err) {
24737
+ } catch (err3) {
22882
24738
  return {
22883
24739
  rules: [],
22884
- issues: [{ path: dir, message: t("policy_load.dir_read_failed", { reason: reason6(err) }) }]
24740
+ issues: [{ path: dir, message: t("policy_load.dir_read_failed", { reason: reason6(err3) }) }]
22885
24741
  };
22886
24742
  }
22887
24743
  const rules = [];
@@ -22890,10 +24746,10 @@ function loadPolicyRules(dir) {
22890
24746
  let content;
22891
24747
  try {
22892
24748
  content = readFileSync(join(dir, file), "utf-8");
22893
- } catch (err) {
24749
+ } catch (err3) {
22894
24750
  issues.push({
22895
24751
  path: file,
22896
- message: t("policy_load.file_read_failed", { reason: reason6(err) })
24752
+ message: t("policy_load.file_read_failed", { reason: reason6(err3) })
22897
24753
  });
22898
24754
  continue;
22899
24755
  }
@@ -23016,8 +24872,8 @@ function unescapeTomlString(s) {
23016
24872
  function preview2(line) {
23017
24873
  return line.length > 40 ? `${line.slice(0, 40)}\u2026` : line;
23018
24874
  }
23019
- function reason6(err) {
23020
- return err instanceof Error ? err.message : String(err);
24875
+ function reason6(err3) {
24876
+ return err3 instanceof Error ? err3.message : String(err3);
23021
24877
  }
23022
24878
  var MODULE3 = "Policy";
23023
24879
  function resolvePolicyDirs(opts) {
@@ -23738,12 +25594,12 @@ function loadLexiconDir(dir, source) {
23738
25594
  let files;
23739
25595
  try {
23740
25596
  files = readdirSync(dir).filter((f) => f.endsWith(".txt"));
23741
- } catch (err) {
25597
+ } catch (err3) {
23742
25598
  return {
23743
25599
  rules: [],
23744
25600
  exempt: [],
23745
25601
  issues: [
23746
- { path: dir, message: t("compliance_load.dir_read_failed", { reason: reason7(err) }) }
25602
+ { path: dir, message: t("compliance_load.dir_read_failed", { reason: reason7(err3) }) }
23747
25603
  ]
23748
25604
  };
23749
25605
  }
@@ -23762,10 +25618,10 @@ function loadLexiconDir(dir, source) {
23762
25618
  let content;
23763
25619
  try {
23764
25620
  content = readFileSync(join(dir, file), "utf-8");
23765
- } catch (err) {
25621
+ } catch (err3) {
23766
25622
  out.issues.push({
23767
25623
  path: file,
23768
- message: t("compliance_load.file_read_failed", { reason: reason7(err) })
25624
+ message: t("compliance_load.file_read_failed", { reason: reason7(err3) })
23769
25625
  });
23770
25626
  continue;
23771
25627
  }
@@ -23812,12 +25668,12 @@ function regexError(pattern) {
23812
25668
  try {
23813
25669
  new RegExp(pattern, "gu");
23814
25670
  return void 0;
23815
- } catch (err) {
23816
- return reason7(err);
25671
+ } catch (err3) {
25672
+ return reason7(err3);
23817
25673
  }
23818
25674
  }
23819
- function reason7(err) {
23820
- return err instanceof Error ? err.message : String(err);
25675
+ function reason7(err3) {
25676
+ return err3 instanceof Error ? err3.message : String(err3);
23821
25677
  }
23822
25678
  var MODULE4 = "Compliance";
23823
25679
  function resolveComplianceDirs(opts) {
@@ -23887,7 +25743,7 @@ function runCommandHook(config, event, workDir) {
23887
25743
  let stdout = "";
23888
25744
  let stderr = "";
23889
25745
  let settled = false;
23890
- const failToStart = (err) => {
25746
+ const failToStart = (err3) => {
23891
25747
  if (settled) return;
23892
25748
  settled = true;
23893
25749
  resolve17({
@@ -23895,7 +25751,7 @@ function runCommandHook(config, event, workDir) {
23895
25751
  stdout,
23896
25752
  stderr,
23897
25753
  blocked: false,
23898
- rejectReason: t("hook_load.spawn_failed", { message: err.message }),
25754
+ rejectReason: t("hook_load.spawn_failed", { message: err3.message }),
23899
25755
  sandbox
23900
25756
  });
23901
25757
  };
@@ -23971,9 +25827,9 @@ function runCommandHook(config, event, workDir) {
23971
25827
  ...failure ? { failure } : {}
23972
25828
  });
23973
25829
  });
23974
- child.on("error", (err) => {
25830
+ child.on("error", (err3) => {
23975
25831
  clearTimeout(timer);
23976
- failToStart(err);
25832
+ failToStart(err3);
23977
25833
  });
23978
25834
  const input = JSON.stringify({
23979
25835
  session_id: event.sessionId,
@@ -24079,8 +25935,8 @@ var HookManager = class {
24079
25935
  if (result.blocked) {
24080
25936
  return { blocked: true, reason: result.rejectReason || t("hook_load.rejected") };
24081
25937
  }
24082
- } catch (err) {
24083
- this.log("warn", `[HookManager] ${type} \u7684 command hook \u6267\u884C\u5F02\u5E38: ${describe12(err)}`, {
25938
+ } catch (err3) {
25939
+ this.log("warn", `[HookManager] ${type} \u7684 command hook \u6267\u884C\u5F02\u5E38: ${describe12(err3)}`, {
24084
25940
  hookType: type,
24085
25941
  command: config.command
24086
25942
  });
@@ -24097,8 +25953,8 @@ var HookManager = class {
24097
25953
  new Promise(
24098
25954
  (_, reject2) => setTimeout(() => reject2(new Error("Hook timeout")), HOOK_TIMEOUT_MS)
24099
25955
  )
24100
- ]).catch((err) => {
24101
- this.log("warn", `[HookManager] ${type} (${reg.plugin}) \u5931\u8D25: ${describe12(err)}`, {
25956
+ ]).catch((err3) => {
25957
+ this.log("warn", `[HookManager] ${type} (${reg.plugin}) \u5931\u8D25: ${describe12(err3)}`, {
24102
25958
  hookType: type,
24103
25959
  plugin: reg.plugin
24104
25960
  });
@@ -24109,8 +25965,8 @@ var HookManager = class {
24109
25965
  for (const entry of cmdEntries) {
24110
25966
  if (!matchesHook(entry.matcher, event)) continue;
24111
25967
  for (const config of entry.configs) {
24112
- runCommandHook(config, event, ctx.workDir).then((result) => reportIfNotRun(this.log, type, config, result)).catch((err) => {
24113
- this.log("warn", `[HookManager] ${type} \u7684 command hook \u5F02\u6B65\u5F02\u5E38: ${describe12(err)}`, {
25968
+ runCommandHook(config, event, ctx.workDir).then((result) => reportIfNotRun(this.log, type, config, result)).catch((err3) => {
25969
+ this.log("warn", `[HookManager] ${type} \u7684 command hook \u5F02\u6B65\u5F02\u5E38: ${describe12(err3)}`, {
24114
25970
  hookType: type,
24115
25971
  command: config.command
24116
25972
  });
@@ -24130,8 +25986,8 @@ var HookManager = class {
24130
25986
  )
24131
25987
  ]);
24132
25988
  if (result !== null && result !== void 0) return result;
24133
- } catch (err) {
24134
- this.log("warn", `[HookManager] ${type} (${reg.plugin}) \u5931\u8D25: ${describe12(err)}`, {
25989
+ } catch (err3) {
25990
+ this.log("warn", `[HookManager] ${type} (${reg.plugin}) \u5931\u8D25: ${describe12(err3)}`, {
24135
25991
  hookType: type,
24136
25992
  plugin: reg.plugin
24137
25993
  });
@@ -24151,8 +26007,8 @@ var HookManager = class {
24151
26007
  )
24152
26008
  ]);
24153
26009
  if (result) results.push(result);
24154
- } catch (err) {
24155
- this.log("warn", `[HookManager] ${type} (${reg.plugin}) \u5931\u8D25: ${describe12(err)}`, {
26010
+ } catch (err3) {
26011
+ this.log("warn", `[HookManager] ${type} (${reg.plugin}) \u5931\u8D25: ${describe12(err3)}`, {
24156
26012
  hookType: type,
24157
26013
  plugin: reg.plugin
24158
26014
  });
@@ -24168,8 +26024,8 @@ var HookManager = class {
24168
26024
  reportIfNotRun(this.log, type, config, result);
24169
26025
  const verdict = verdictOf2(result);
24170
26026
  if (verdict) results.push(verdict);
24171
- } catch (err) {
24172
- this.log("warn", `[HookManager] ${type} \u7684 command hook \u6267\u884C\u5F02\u5E38: ${describe12(err)}`, {
26027
+ } catch (err3) {
26028
+ this.log("warn", `[HookManager] ${type} \u7684 command hook \u6267\u884C\u5F02\u5E38: ${describe12(err3)}`, {
24173
26029
  hookType: type,
24174
26030
  command: config.command
24175
26031
  });
@@ -24185,8 +26041,8 @@ var HookManager = class {
24185
26041
  return [...list].sort((a, b) => a.priority - b.priority);
24186
26042
  }
24187
26043
  };
24188
- function describe12(err) {
24189
- return err instanceof Error ? err.message : String(err);
26044
+ function describe12(err3) {
26045
+ return err3 instanceof Error ? err3.message : String(err3);
24190
26046
  }
24191
26047
  function verdictOf2(result) {
24192
26048
  const action = result.output?.["action"];
@@ -24738,8 +26594,8 @@ function readHooksFile(path, issues, opts = {}) {
24738
26594
  let raw;
24739
26595
  try {
24740
26596
  raw = JSON.parse(readFileSync(path, "utf-8"));
24741
- } catch (err) {
24742
- const reason9 = err.message.split("\n")[0] ?? t("hook_load.unknown_error");
26597
+ } catch (err3) {
26598
+ const reason9 = err3.message.split("\n")[0] ?? t("hook_load.unknown_error");
24743
26599
  issues.push({ path, message: t("hook_load.bad_json", { reason: reason9 }) });
24744
26600
  return void 0;
24745
26601
  }
@@ -24954,8 +26810,8 @@ function readEntries2(dir, label, issues, lang) {
24954
26810
  isDir: e.isDirectory(),
24955
26811
  isFile: e.isFile()
24956
26812
  }));
24957
- } catch (err) {
24958
- const reason9 = err instanceof Error ? err.message : String(err);
26813
+ } catch (err3) {
26814
+ const reason9 = err3 instanceof Error ? err3.message : String(err3);
24959
26815
  issues.push({ path: label, message: t("skill.import_read_failed", { reason: reason9 }, lang) });
24960
26816
  return [];
24961
26817
  }
@@ -25070,10 +26926,10 @@ function scanOneDir(spec, skills, issues) {
25070
26926
  let categories;
25071
26927
  try {
25072
26928
  categories = readdirSync(spec.dir, { withFileTypes: true });
25073
- } catch (err) {
26929
+ } catch (err3) {
25074
26930
  issues.push({
25075
26931
  path: spec.dir,
25076
- message: t("skill_load.dir_read_failed", { reason: reason8(err) })
26932
+ message: t("skill_load.dir_read_failed", { reason: reason8(err3) })
25077
26933
  });
25078
26934
  return;
25079
26935
  }
@@ -25083,10 +26939,10 @@ function scanOneDir(spec, skills, issues) {
25083
26939
  let entries2;
25084
26940
  try {
25085
26941
  entries2 = readdirSync(catPath, { withFileTypes: true });
25086
- } catch (err) {
26942
+ } catch (err3) {
25087
26943
  issues.push({
25088
26944
  path: cat.name,
25089
- message: t("skill_load.category_read_failed", { reason: reason8(err) })
26945
+ message: t("skill_load.category_read_failed", { reason: reason8(err3) })
25090
26946
  });
25091
26947
  continue;
25092
26948
  }
@@ -25106,8 +26962,8 @@ function loadOne(mdFile, catPath, category, dirName, spec, skills, issues) {
25106
26962
  try {
25107
26963
  raw = readFileSync(mdFile, "utf-8");
25108
26964
  stat5 = statSync(mdFile);
25109
- } catch (err) {
25110
- issues.push({ path: label, message: t("skill_load.read_failed", { reason: reason8(err) }) });
26965
+ } catch (err3) {
26966
+ issues.push({ path: label, message: t("skill_load.read_failed", { reason: reason8(err3) }) });
25111
26967
  return;
25112
26968
  }
25113
26969
  const parsed = parseSkillFrontmatter(raw, label);
@@ -25144,8 +27000,8 @@ function loadOne(mdFile, catPath, category, dirName, spec, skills, issues) {
25144
27000
  source: "manual"
25145
27001
  });
25146
27002
  }
25147
- function reason8(err) {
25148
- return err instanceof Error ? err.message : String(err);
27003
+ function reason8(err3) {
27004
+ return err3 instanceof Error ? err3.message : String(err3);
25149
27005
  }
25150
27006
  // src/skill/manager.ts
25151
27007
  var SKILLS_DIR = join(homedir(), ".epoch", "skills");
@@ -25593,17 +27449,17 @@ function swapInto(from, old, dest, skillsDir) {
25593
27449
  try {
25594
27450
  mkdirSync(trash, { recursive: true });
25595
27451
  renameSync(old, join(trash, "old"));
25596
- } catch (err) {
27452
+ } catch (err3) {
25597
27453
  rmSync(trash, { recursive: true, force: true });
25598
- return err instanceof Error ? err.message : String(err);
27454
+ return err3 instanceof Error ? err3.message : String(err3);
25599
27455
  }
25600
27456
  try {
25601
27457
  mkdirSync(dirname(dest), { recursive: true });
25602
27458
  renameSync(from, dest);
25603
- } catch (err) {
27459
+ } catch (err3) {
25604
27460
  renameSync(join(trash, "old"), old);
25605
27461
  rmSync(trash, { recursive: true, force: true });
25606
- return err instanceof Error ? err.message : String(err);
27462
+ return err3 instanceof Error ? err3.message : String(err3);
25607
27463
  }
25608
27464
  rmSync(trash, { recursive: true, force: true });
25609
27465
  return null;
@@ -25681,8 +27537,8 @@ function commit3(preview3, staged, skillsDir, lang, replace = false) {
25681
27537
  mkdirSync(join(skillsDir, entry.category), { recursive: true });
25682
27538
  renameSync(from, dest);
25683
27539
  imported.push(entry.name);
25684
- } catch (err) {
25685
- const reason9 = err instanceof Error ? err.message : String(err);
27540
+ } catch (err3) {
27541
+ const reason9 = err3 instanceof Error ? err3.message : String(err3);
25686
27542
  skipped.push({ path: label, message: t("skill.import_write_failed", { reason: reason9 }, lang) });
25687
27543
  }
25688
27544
  }
@@ -25769,8 +27625,8 @@ var SkillLearner = class {
25769
27625
  messages: [{ role: "user", content: buildLearningPrompt(ctx) }]
25770
27626
  });
25771
27627
  text = result.text;
25772
- } catch (err) {
25773
- return { created: false, reason: "provider-error", error: messageOf2(err) };
27628
+ } catch (err3) {
27629
+ return { created: false, reason: "provider-error", error: messageOf2(err3) };
25774
27630
  }
25775
27631
  return this.parseAndCreate(text);
25776
27632
  }
@@ -25803,13 +27659,13 @@ var SkillLearner = class {
25803
27659
  try {
25804
27660
  await this.skillSystem.create(declared, parsed.content, category);
25805
27661
  return { created: true, skillName: declared };
25806
- } catch (err) {
25807
- return { created: false, reason: "create-failed", error: messageOf2(err) };
27662
+ } catch (err3) {
27663
+ return { created: false, reason: "create-failed", error: messageOf2(err3) };
25808
27664
  }
25809
27665
  }
25810
27666
  };
25811
- function messageOf2(err) {
25812
- return err instanceof Error ? err.message : String(err);
27667
+ function messageOf2(err3) {
27668
+ return err3 instanceof Error ? err3.message : String(err3);
25813
27669
  }
25814
27670
  var MAX_FILES = 2e4;
25815
27671
  var SKIP_DIRS = /* @__PURE__ */ new Set([
@@ -26082,11 +27938,11 @@ async function openArtifact(path, homeDir) {
26082
27938
  const child = spawn(launch.command, launch.args, { stdio: "ignore", detached: true });
26083
27939
  child.on(
26084
27940
  "error",
26085
- (err) => fail9(
27941
+ (err3) => fail9(
26086
27942
  new Error(
26087
27943
  t("artifact.open_launch_failed_detail", {
26088
27944
  reason: describeArtifactRefusal("launch-failed"),
26089
- message: err.message
27945
+ message: err3.message
26090
27946
  })
26091
27947
  )
26092
27948
  )
@@ -26095,12 +27951,12 @@ async function openArtifact(path, homeDir) {
26095
27951
  child.unref();
26096
27952
  done2();
26097
27953
  });
26098
- } catch (err) {
27954
+ } catch (err3) {
26099
27955
  fail9(
26100
27956
  new Error(
26101
27957
  t("artifact.open_launch_failed_detail", {
26102
27958
  reason: describeArtifactRefusal("launch-failed"),
26103
- message: String(err)
27959
+ message: String(err3)
26104
27960
  })
26105
27961
  )
26106
27962
  );
@@ -26439,8 +28295,8 @@ ${extra}` : withGoal;
26439
28295
  var FILE_VERSION5 = 1;
26440
28296
  var LEVELS = ["trusted", "untrusted"];
26441
28297
  var SCOPES = ["directory", "directory-tree"];
26442
- function describe14(err) {
26443
- return err instanceof Error ? err.message : String(err);
28298
+ function describe14(err3) {
28299
+ return err3 instanceof Error ? err3.message : String(err3);
26444
28300
  }
26445
28301
  function covers(base2, target, scope) {
26446
28302
  if (samePath(base2, target)) return true;
@@ -26511,18 +28367,18 @@ var TrustManager = class {
26511
28367
  let raw;
26512
28368
  try {
26513
28369
  raw = readFileSync(this.filePath, "utf-8");
26514
- } catch (err) {
28370
+ } catch (err3) {
26515
28371
  this.loadErrors.push(
26516
- t("trust_gate.record_read_failed", { path: this.filePath, reason: describe14(err) })
28372
+ t("trust_gate.record_read_failed", { path: this.filePath, reason: describe14(err3) })
26517
28373
  );
26518
28374
  return;
26519
28375
  }
26520
28376
  let parsed;
26521
28377
  try {
26522
28378
  parsed = JSON.parse(raw);
26523
- } catch (err) {
28379
+ } catch (err3) {
26524
28380
  this.loadErrors.push(
26525
- t("trust_gate.record_bad_json", { path: this.filePath, reason: describe14(err) })
28381
+ t("trust_gate.record_bad_json", { path: this.filePath, reason: describe14(err3) })
26526
28382
  );
26527
28383
  return;
26528
28384
  }
@@ -26568,10 +28424,10 @@ var TrustManager = class {
26568
28424
  try {
26569
28425
  writeFileSync(tmp, body2, { encoding: "utf-8", mode: 384 });
26570
28426
  renameSync(tmp, this.filePath);
26571
- } catch (err) {
28427
+ } catch (err3) {
26572
28428
  rmSync(tmp, { force: true });
26573
28429
  throw new Error(
26574
- t("trust_gate.record_write_failed", { path: this.filePath, reason: describe14(err) })
28430
+ t("trust_gate.record_write_failed", { path: this.filePath, reason: describe14(err3) })
26575
28431
  );
26576
28432
  }
26577
28433
  }
@@ -26718,4 +28574,4 @@ function hasDedicatedExecContent(inv) {
26718
28574
  * `--tree` 的命令帮助里,让用户自己知道 `--tree` 意味着什么。
26719
28575
  */
26720
28576
 
26721
- export { ABOUT_DESC_MAX_CHARS, ABOUT_README_MAX_CHARS, AGENT_ROLE_DIAG_MODULE, ARTIFACT_MAX_TOTAL_BYTES, ARTIFACT_RETENTION_DEFAULTS, ATTACHMENT_MAX_TOTAL_BYTES, ATTACHMENT_RETENTION_DEFAULTS, AgentLoop, AppearanceStore, ApprovalCache, BLOCKED_TOOLS, BudgetGuard, BudgetStore, CHECKPOINT_MAX_TOTAL_BYTES, CLAUDE_EVENT_NAMES, CLAUDE_TOOL_NAMES, CODE_MODE_LIMITS, CODE_MODE_SDK_TAG, CONFIG_KEYS, CURRENT_CONFIG_VERSION, CheckpointManager, CheckpointStore, CodeSandbox, ComplianceEngine, ContextCompressor, DEFAULT_COMPLIANCE_ACTIONS, DEFAULT_COMPLIANCE_SETTINGS, DEFAULT_COMPRESSION_THRESHOLD, DEFAULT_GOAL_MAX_ROUNDS, DEFAULT_MAX_HOLD_CHARS, DELEGATE_SESSION_SOURCE, DelegateManager, EMPTY_RULES, EPOCH_DISK_LEDGER, EpochConfigSchema, FTS_TABLES, FTS_TRIGGERS, GOAL_BLOCK_CODES, GoalService, GoalStore, HEADLESS_AUDIT_CODES, HookManager, INSTRUCTION_BUDGET_CHARS, INSTRUCTION_FILES, ImageLoadError, ImportTrustStore, LAUNCHD_LABEL_PREFIX, LOCK_HEARTBEAT_MS, LOCK_STALE_MS, LastOpenSessions, MARKETPLACE_DISPLAY_FIELDS, MARKETPLACE_FILE, MAX_AUDIT_ENTRIES, MAX_COMMAND_DEPTH, MAX_GOAL_MAX_ROUNDS, MAX_IMPORT_DEPTH, MAX_LAST_OPEN_SESSIONS, MAX_OBJECTIVE_CHARS, MAX_REASON_CHARS, MAX_RECENT_WORKSPACES, MODEL_ENTRIES_FILE, MODEL_GIVE_UP_THRESHOLD, MULTIMODAL_DEFAULTS, ManagedPolicyError, ManagedSettingsSchema, MemoryManager, ModelFailureTracker, NOMINAL_TOTAL_BYTES, NO_REVEALED_TOOLS, PACK_EXCLUDES, PERMISSION_AUDIT_CODES, PLUGIN_ICON_MAX_BYTES, PLUGIN_LAYOUT, PLUGIN_MANIFEST_FILE, PLUGIN_MANIFEST_KEYS, PLUGIN_NAME_PATTERN, PLUGIN_ROOT_ENV, PLUGIN_ROOT_TOKEN, PLUGIN_VISIBILITY, POLICY_DECISIONS, PROBE_VERSION, PROJECT_AGENTS_SUBDIR, PROVIDER_NO_CREDENTIAL, PermissionManager, PlanModeState, PluginAuthorSchema, PluginStore, PolicyRuleSchema, ProviderError, ProviderRouter, RECORDING_KEEP_RUNS, RECORDING_MAX_BYTES, ROLE_FRONTMATTER_SCHEMA, RUN_CODE_TOOL, RecentWorkspaces, SANDBOX_COVERS, SANDBOX_EXCLUDES, SCALAR_KEYS, SCHEDULE_DEFAULTS, SCHEDULE_DEFAULT_ALLOWLIST, SCHEDULE_ISSUE_CODES, SCHTASKS_FOLDER, SESSION_MESSAGES_READ_TOOL, SESSION_MESSAGES_SEARCH_TOOL, SESSION_QUERY_TOOLS, SESSION_SEARCH_TOOL, SESSION_TRACE_TOOL, SETTINGS_LAYER_ORDER, SETTING_WRITE_KEYS, SETTING_WRITE_LAYERS, SKILL_ASSET_DIRS, SKILL_CREATE_TOOL, SKILL_EDIT_TOOL, SKILL_FILE, SKILL_PATCH_TOOL, SKILL_VIEW_TOOL, SKILL_WRITE_FILE_TOOL, SLASH_COMMANDS_DIAG_MODULE, ScheduleRecorder, ScheduleRegistrar, ScheduleStore, SessionManager, SessionQueries, SessionReferences, SettingsFileError, SettingsFileSchema, SkillLearner, SkillSystem, TOOL_SEARCH_TOOL, TaskNoticeTracker, ToolRegistry, TrackerDB, TrustManager, UNSETTABLE_USER_KEYS, Workspace, acquireScheduleLock, addMarketplace, addUsage, admitArtifact, admitArtifacts, affectedPaths, approvalEntryFor, approvalRootFor, artifactLaunchArgv, artifactOpenRefusal, assertLevelAllowed, blockedRoleTools, buildContextBreakdown, buildFireArgv, buildFtsMatchQuery, buildSchemaExports, buildSystemPrompt, buildTrigramMatchQuery, builtinRoles, capabilityOfRef, checkConfigValue, checkEpochVersion, checkFtsHealth, checkShadowing, classifyPersistFailure, classifyProviderError, clearModelCache, coalesceRecording, codeModeWorkerPath, commandNameFromRelPath, compileRuleLists, compressionOptions, computeCost, computeCostMicros, computeExecHash, configKeyByPath, configKeyTable, countRules, createAllowAllGate, createAllowAllImportGate, createAskQuestionTool, createCodeExecTool, createDelegateTool, createDenyAllGate, createDenyAllImportGate, createGoalTool, createImportGate, createMemoryTool, createPlanModeTools, createPluginScope, createRoleFile, createRoleScope, createRunCodeTool, createScheduleDraftTool, createSessionMessagesReadTool, createSessionMessagesSearchTool, createSessionSearchTool, createSessionSearchTools, createSessionTraceTool, createSkillViewTool, createSkillWriteTools, createTodoTool, createToolRevealState, createToolScope, createToolSearchTool, createTrustGate, currentEpochVersion, decideImport, decideTrust, defaultConfig, describeArtifactRefusal, describeBackgroundTask, describeHeadlessPolicy, describeIsolation, describeJsonError, diagnoseSchedules, discoverMarkdown, discoverModels, discoverProject, discoverySpec, displayAllows, displayCurrency, draftCommandLine, draftWidening, escapeRuleContent, estimateImageTokens, estimateRunTokens, estimateTokens, evaluateSelection, expandCommand, expandImports, explainSetting, extractArchive, findInstructionFiles, findProjectInstructions, findRole, formatBytes, formatSkillIndex, formatUsd, gateForTool, getCapability, getConfigIssues, getConfigOrigins, getImportGate, getTrustGate, grantedPathsFor, hasDedicatedExecContent, hasExecTierContent, hasPromptCaching, hasProviderCredentials, hasReadTierContent, hasUsableModel, imageFromBase64, imageFromPath, imagePartTokens, importParts, importSkills, installPlugin, instructionDirs, instructionNotices, intervalSlots, inventoryProjectExtensions, inventoryTotal, isBlockCode, isCodeModeDeferred, isEmptyRules, isGoalPhase, isNonInteractive, isReadOnlySubCall, isSettingWriteLayer, isTransientPersistFailure, isValidInterval, isValidPluginName, isWithinWindow, isWritableSettingKey, labelSlug, layerRank, listEntryModels, listRunningSchedules, listSessionCandidates, listWorkspaceFiles, loadCommandDefinitions, loadCommandFile, loadCommands, loadConfig, loadHookSources, loadKeybindings, loadLexiconDir, loadLexiconFiles, loadModelEntries, loadPlugins, loadPolicyFiles, loadPolicyRules, loadRoleDefinitions, loadRoleDir, loadedImports, localDateString, managedSwitchNotes, mapClaudeToolName, mapEpochToolName, mapOperationType, matchPreauthorization, matchRuleLists, matchesHook, mentionsPluginRoot, mergeHeadlessPolicy, mergeRoles, mergeSchedulePatch, microsToUsd, modelEntriesPath, modelListCandidates, needsAllowlist, nextRunAt, noConfigOrigins, noManagedPolicy, noPlugins, normalizeModelEntry, normalizeTrigger, offloadOldestImages, openArtifact, originOf, packFileName, packPlugin, parseClaudeSettingsHooks, parseClock, parseDate, parseFrontmatter, parseHooksConfig, parseHooksConfigVerbose, parseImportLine, parseModelEntry, parseModelList, parseRoleDefinition, parseScheduleDraft, parseSkillFrontmatter, parseTrigger, pendingImageTokens, persistFailureCode, persistParts, persistToolResults, persistedUsage, planPack, previewSkillImport, pricingFor, projectEntryForDisplay, pruneArtifacts, pruneAttachments, pruneRecordings, pruneSchedules, readEntryKey, readImageSize, readMarketplaces, readPluginAbout, readPluginIcon, readPluginManifest, readPluginRecords, readRecording, readSessionSurface, reclaimFtsSpace, redactLine, refreshOpenRouterMetadata, removeMarketplace, removeRecordings, removeRoleFile, removeSessionArtifacts, removeSessionAttachments, renderImportTree, renderProjectContext, renderSdkDeclaration, renderSelfIndex, repairSchedules, requestImageBytes, resolveArtifactRetention, resolveCodeModeWorker, resolveComplianceDirs, resolveEntrySource, resolveInWorkspace, resolveMarketplaceRef, resolveMentions, resolveMultimodalPolicy, resolvePolicyDirs, resolvePricingAt, resolveProjectRoot, resolveScheduleBackend, resolveSessionReference, resolveSessionVisibility, resolveSettings, resolveSkillDirs, resolveSource, resolveTar, resolveWorkspace, restoreParts, revealScopedProvider, roleScopedProvider, roleSourceLabel, ruleCovers, ruleFromString, ruleToString, runCode, runCommand2 as runCommand, sanitizeArgNames, sanitizeCommand, sanitizeFtsQuery, sanitizePath, sanitizeToolOutput, saveModelEntries, scanInstructions, scanPluginDir, scanSkillDirs, searchMarketplaces, setDisplayCurrency, setImportGate, setPluginEnabled, setTrustGate, settingValueChoices, settingValueKind, settingWriteApply, settingWriteLayers, settingWriteTargets, skillIndexDescription, skillIndexResidency, skillIndexStats, sniffMediaType, splitFrontmatter, staticToolProvider, stripArtifactData, substitutePluginRoot, suggestRuleFromApproval, systemOpenArgv, systemPromptSegments, testModelEntry, toPosix, toolDefinitionTokens, toolMatches, toolTableTokens, totalTokens, traceSession, triggerPeriodMs, unescapeRuleContent, uninstallPlugin, unknownRoleSkills, unknownRoleTools, unloadedInstructionFiles, unsetUserSetting, updateMarketplace, updatePlugin, usdToMicros, validateSchedule, validateTrigger, validateWindow, withGoalCompression, withGoalPrompt, workspaceDisplayPath, writableConfigKeys, writeSettingValue };
28577
+ export { ABOUT_DESC_MAX_CHARS, ABOUT_README_MAX_CHARS, AGENT_ROLE_DIAG_MODULE, ARTIFACT_MAX_TOTAL_BYTES, ARTIFACT_RETENTION_DEFAULTS, ATTACHMENT_MAX_TOTAL_BYTES, ATTACHMENT_RETENTION_DEFAULTS, AgentInbox, AgentLoop, AppearanceStore, ApprovalCache, BLOCKED_TOOLS, BOARD_TOOL_NAMES, BoardStore, BudgetGuard, BudgetStore, CHECKPOINT_MAX_TOTAL_BYTES, CLAUDE_EVENT_NAMES, CLAUDE_TOOL_NAMES, CODE_MODE_LIMITS, CODE_MODE_SDK_TAG, CONFIG_KEYS, CURRENT_CONFIG_VERSION, CheckpointManager, CheckpointStore, CodeSandbox, ComplianceEngine, ContextCompressor, DEFAULT_COMPLIANCE_ACTIONS, DEFAULT_COMPLIANCE_SETTINGS, DEFAULT_COMPRESSION_THRESHOLD, DEFAULT_GOAL_MAX_ROUNDS, DEFAULT_INBOX_CAPACITY, DEFAULT_MAX_HOLD_CHARS, DEFAULT_MAX_RUNNING_MEMBERS, DEFAULT_MAX_WOKEN_SESSIONS, DELEGATE_SESSION_SOURCE, DelegateManager, EMPTY_RULES, EPOCH_DISK_LEDGER, EpochConfigSchema, FTS_TABLES, FTS_TRIGGERS, GOAL_BLOCK_CODES, GoalService, GoalStore, HEADLESS_AUDIT_CODES, HookManager, INSTRUCTION_BUDGET_CHARS, INSTRUCTION_FILES, ImageLoadError, ImportTrustStore, LAUNCHD_LABEL_PREFIX, LOCK_HEARTBEAT_MS, LOCK_STALE_MS, LastOpenSessions, MARKETPLACE_DISPLAY_FIELDS, MARKETPLACE_FILE, MAX_AUDIT_ENTRIES, MAX_COMMAND_DEPTH, MAX_GOAL_MAX_ROUNDS, MAX_IMPORT_DEPTH, MAX_LAST_OPEN_SESSIONS, MAX_OBJECTIVE_CHARS, MAX_POST_CHARS, MAX_REASON_CHARS, MAX_RECENT_WORKSPACES, MODEL_ENTRIES_FILE, MODEL_GIVE_UP_THRESHOLD, MULTIMODAL_DEFAULTS, ManagedPolicyError, ManagedSettingsSchema, MemoryManager, ModelFailureTracker, NOMINAL_TOTAL_BYTES, NO_REVEALED_TOOLS, PACK_EXCLUDES, PERMISSION_AUDIT_CODES, PLUGIN_ICON_MAX_BYTES, PLUGIN_LAYOUT, PLUGIN_MANIFEST_FILE, PLUGIN_MANIFEST_KEYS, PLUGIN_NAME_PATTERN, PLUGIN_ROOT_ENV, PLUGIN_ROOT_TOKEN, PLUGIN_VISIBILITY, POLICY_DECISIONS, PROBE_VERSION, PROJECT_AGENTS_SUBDIR, PROVIDER_NO_CREDENTIAL, PermissionManager, PlanModeState, PluginAuthorSchema, PluginStore, PolicyRuleSchema, ProviderError, ProviderRouter, RECORDING_KEEP_RUNS, RECORDING_MAX_BYTES, ROLE_FRONTMATTER_SCHEMA, RUN_CODE_TOOL, RecentWorkspaces, SANDBOX_COVERS, SANDBOX_EXCLUDES, SCALAR_KEYS, SCHEDULE_DEFAULTS, SCHEDULE_DEFAULT_ALLOWLIST, SCHEDULE_ISSUE_CODES, SCHTASKS_FOLDER, SEND_MESSAGE_TOOL, SESSION_MESSAGES_READ_TOOL, SESSION_MESSAGES_SEARCH_TOOL, SESSION_QUERY_TOOLS, SESSION_SEARCH_TOOL, SESSION_TRACE_TOOL, SETTINGS_LAYER_ORDER, SETTING_WRITE_KEYS, SETTING_WRITE_LAYERS, SKILL_ASSET_DIRS, SKILL_CREATE_TOOL, SKILL_EDIT_TOOL, SKILL_FILE, SKILL_PATCH_TOOL, SKILL_VIEW_TOOL, SKILL_WRITE_FILE_TOOL, SLASH_COMMANDS_DIAG_MODULE, ScheduleRecorder, ScheduleRegistrar, ScheduleStore, SessionManager, SessionQueries, SessionReferences, SettingsFileError, SettingsFileSchema, SkillLearner, SkillSystem, TEAM_TOOL_NAMES, TOOL_SEARCH_TOOL, TaskNoticeTracker, TeamRegistry, ToolRegistry, TrackerDB, TrustManager, UNSETTABLE_USER_KEYS, Workspace, acquireScheduleLock, addMarketplace, addUsage, admitArtifact, admitArtifacts, affectedPaths, approvalEntryFor, approvalRootFor, artifactLaunchArgv, artifactOpenRefusal, assertLevelAllowed, blockedRoleTools, buildContextBreakdown, buildFireArgv, buildFtsMatchQuery, buildSchemaExports, buildSystemPrompt, buildTrigramMatchQuery, builtinRoles, capabilityOfRef, checkConfigValue, checkEpochVersion, checkFtsHealth, checkShadowing, classifyPersistFailure, classifyProviderError, clearModelCache, coalesceRecording, codeModeWorkerPath, commandNameFromRelPath, compileRuleLists, compressionOptions, computeCost, computeCostMicros, computeExecHash, configKeyByPath, configKeyTable, countRules, createAllowAllGate, createAllowAllImportGate, createAskQuestionTool, createBoardTools, createCodeExecTool, createDelegateTool, createDenyAllGate, createDenyAllImportGate, createGoalTool, createImportGate, createMemoryTool, createPlanModeTools, createPluginScope, createRoleFile, createRoleScope, createRunCodeTool, createScheduleDraftTool, createSendMessageTool, createSessionMessagesReadTool, createSessionMessagesSearchTool, createSessionSearchTool, createSessionSearchTools, createSessionTraceTool, createSkillViewTool, createSkillWriteTools, createTeamTools, createTodoTool, createToolRevealState, createToolScope, createToolSearchTool, createTrustGate, currentEpochVersion, decideImport, decideTrust, defaultConfig, describeArtifactRefusal, describeBackgroundTask, describeHeadlessPolicy, describeIsolation, describeJsonError, diagnoseSchedules, discoverMarkdown, discoverModels, discoverProject, discoverySpec, displayAllows, displayCurrency, draftCommandLine, draftWidening, escapeRuleContent, estimateImageTokens, estimateRunTokens, estimateTokens, evaluateSelection, expandCommand, expandImports, explainSetting, extractArchive, findInstructionFiles, findProjectInstructions, findRole, formatBytes, formatSkillIndex, formatUsd, gateForTool, getCapability, getConfigIssues, getConfigOrigins, getImportGate, getTrustGate, grantedPathsFor, hasDedicatedExecContent, hasExecTierContent, hasPromptCaching, hasProviderCredentials, hasReadTierContent, hasUsableModel, imageFromBase64, imageFromPath, imagePartTokens, importParts, importSkills, installPlugin, instructionDirs, instructionNotices, intervalSlots, inventoryProjectExtensions, inventoryTotal, isBlockCode, isCodeModeDeferred, isEmptyRules, isGoalPhase, isNonInteractive, isReadOnlySubCall, isSettingWriteLayer, isTransientPersistFailure, isValidInterval, isValidPluginName, isWithinWindow, isWritableSettingKey, labelSlug, layerRank, listEntryModels, listRunningSchedules, listSessionCandidates, listWorkspaceFiles, loadCommandDefinitions, loadCommandFile, loadCommands, loadConfig, loadHookSources, loadKeybindings, loadLexiconDir, loadLexiconFiles, loadModelEntries, loadPlugins, loadPolicyFiles, loadPolicyRules, loadRoleDefinitions, loadRoleDir, loadedImports, localDateString, managedSwitchNotes, mapClaudeToolName, mapEpochToolName, mapOperationType, matchPreauthorization, matchRuleLists, matchesHook, mentionsPluginRoot, mergeHeadlessPolicy, mergeRoles, mergeSchedulePatch, microsToUsd, modelEntriesPath, modelListCandidates, needsAllowlist, nextRunAt, noConfigOrigins, noManagedPolicy, noPlugins, normalizeModelEntry, normalizeTrigger, offloadOldestImages, openArtifact, originOf, packFileName, packPlugin, parseClaudeSettingsHooks, parseClock, parseDate, parseFrontmatter, parseHooksConfig, parseHooksConfigVerbose, parseImportLine, parseModelEntry, parseModelList, parseRoleDefinition, parseScheduleDraft, parseSkillFrontmatter, parseTrigger, pendingImageTokens, persistFailureCode, persistParts, persistToolResults, persistedUsage, planPack, previewSkillImport, pricingFor, projectEntryForDisplay, pruneArtifacts, pruneAttachments, pruneRecordings, pruneSchedules, readEntryKey, readImageSize, readMarketplaces, readPluginAbout, readPluginIcon, readPluginManifest, readPluginRecords, readRecording, readSessionSurface, reclaimFtsSpace, redactLine, refreshOpenRouterMetadata, removeMarketplace, removeRecordings, removeRoleFile, removeSessionArtifacts, removeSessionAttachments, renderImportTree, renderProjectContext, renderSdkDeclaration, renderSelfIndex, repairSchedules, requestImageBytes, resolveArtifactRetention, resolveCodeModeWorker, resolveComplianceDirs, resolveEntrySource, resolveInWorkspace, resolveMarketplaceRef, resolveMentions, resolveMultimodalPolicy, resolvePolicyDirs, resolvePricingAt, resolveProjectRoot, resolveScheduleBackend, resolveSessionReference, resolveSessionVisibility, resolveSettings, resolveSkillDirs, resolveSource, resolveTar, resolveWorkspace, restoreParts, revealScopedProvider, roleScopedProvider, roleSourceLabel, ruleCovers, ruleFromString, ruleToString, runCode, runCommand2 as runCommand, sanitizeArgNames, sanitizeCommand, sanitizeFtsQuery, sanitizePath, sanitizeToolOutput, saveModelEntries, scanInstructions, scanPluginDir, scanSkillDirs, searchMarketplaces, setDisplayCurrency, setImportGate, setPluginEnabled, setTrustGate, settingValueChoices, settingValueKind, settingWriteApply, settingWriteLayers, settingWriteTargets, skillIndexDescription, skillIndexResidency, skillIndexStats, sniffMediaType, splitFrontmatter, staticToolProvider, stripArtifactData, substitutePluginRoot, suggestRuleFromApproval, systemOpenArgv, systemPromptSegments, testModelEntry, toPosix, toolDefinitionTokens, toolMatches, toolTableTokens, totalTokens, traceSession, triggerPeriodMs, unescapeRuleContent, uninstallPlugin, unknownRoleSkills, unknownRoleTools, unloadedInstructionFiles, unsetUserSetting, updateMarketplace, updatePlugin, usdToMicros, validateSchedule, validateTrigger, validateWindow, withGoalCompression, withGoalPrompt, workspaceDisplayPath, writableConfigKeys, writeSettingValue };