@epoch-agent/core 3.0.0 → 3.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/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, 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",
@@ -2037,13 +2065,13 @@ var DelegateManager = class {
2037
2065
  ).then((results) => {
2038
2066
  const total = Date.now() - start;
2039
2067
  const summary = this.buildSummary(results, total);
2040
- const ok2 = results.every((r) => r.success);
2068
+ const ok4 = results.every((r) => r.success);
2041
2069
  if (job) {
2042
2070
  job.append(`
2043
2071
  ${summary}`);
2044
- job.finish(ok2 ? "exited" : "failed");
2072
+ job.finish(ok4 ? "exited" : "failed");
2045
2073
  }
2046
- return { results, summary, total, ok: ok2 };
2074
+ return { results, summary, total, ok: ok4 };
2047
2075
  });
2048
2076
  if (background && job) {
2049
2077
  void run.catch(() => void 0);
@@ -2120,7 +2148,19 @@ ${summary}`);
2120
2148
  }
2121
2149
  async runSingleTask(task, parentSessionId, signal, onProgress) {
2122
2150
  const start = Date.now();
2123
- const sessionId = `delegate-${randomUUID().slice(0, 8)}`;
2151
+ const resuming = task.resumeSessionId !== void 0;
2152
+ const sessionId = task.resumeSessionId ?? `delegate-${randomUUID().slice(0, 8)}`;
2153
+ const memberId = task.agentId ?? sessionId;
2154
+ if (resuming) {
2155
+ this.config.team?.markRunning(memberId);
2156
+ } else {
2157
+ this.config.team?.createMember({
2158
+ sessionId,
2159
+ parentSessionId,
2160
+ ...task.agentId ? { agentId: task.agentId } : {},
2161
+ ...task.role ? { role: task.role } : {}
2162
+ });
2163
+ }
2124
2164
  const failed = (error, summary = "") => ({
2125
2165
  goal: task.goal,
2126
2166
  success: false,
@@ -2131,9 +2171,11 @@ ${summary}`);
2131
2171
  });
2132
2172
  if (signal?.aborted) return failed(ABORTED);
2133
2173
  const controller = new AbortController();
2174
+ this.config.team?.setAbort(memberId, () => controller.abort());
2134
2175
  const unlink = linkAbort(isAbortSignal(signal) ? signal : void 0, controller);
2135
2176
  const ms = this.config.task_timeout;
2136
2177
  let timer;
2178
+ let outcome = "failed";
2137
2179
  try {
2138
2180
  const work = this.runner(
2139
2181
  task.goal,
@@ -2142,7 +2184,11 @@ ${summary}`);
2142
2184
  task.role,
2143
2185
  parentSessionId,
2144
2186
  controller.signal,
2145
- onProgress
2187
+ (line) => {
2188
+ this.config.team?.setActivity(memberId, line);
2189
+ onProgress?.(line);
2190
+ },
2191
+ resuming ? { resume: true } : void 0
2146
2192
  );
2147
2193
  const result = await (ms > 0 ? Promise.race([
2148
2194
  work,
@@ -2154,6 +2200,7 @@ ${summary}`);
2154
2200
  })
2155
2201
  ]) : work);
2156
2202
  if (controller.signal.aborted) return failed(ABORTED, result.text);
2203
+ outcome = result.error ? "failed" : "finalized";
2157
2204
  return {
2158
2205
  goal: task.goal,
2159
2206
  success: !result.error,
@@ -2162,11 +2209,12 @@ ${summary}`);
2162
2209
  duration: Date.now() - start,
2163
2210
  ...task.role ? { role: task.role } : {}
2164
2211
  };
2165
- } catch (err) {
2166
- const msg = err instanceof Error ? err.message : String(err);
2212
+ } catch (err3) {
2213
+ const msg = err3 instanceof Error ? err3.message : String(err3);
2167
2214
  if (signal?.aborted) return failed(ABORTED);
2168
2215
  return failed(msg.includes("\u8D85\u65F6") ? `[\u8D85\u65F6] ${msg}` : msg);
2169
2216
  } finally {
2217
+ this.config.team?.markFinished(memberId, outcome);
2170
2218
  clearTimeout(timer);
2171
2219
  unlink();
2172
2220
  }
@@ -2211,8 +2259,9 @@ function renderRoles(roles) {
2211
2259
  ...roles.map((r) => `- ${r.name}: ${r.description}`)
2212
2260
  ];
2213
2261
  }
2214
- function createDelegateTool(runner, config, roles) {
2262
+ function createDelegateTool(runner, config, roles, onManager) {
2215
2263
  const manager = new DelegateManager(runner, config);
2264
+ onManager?.(manager);
2216
2265
  const listRoles = roles ?? (() => []);
2217
2266
  return {
2218
2267
  name: "delegate_task",
@@ -2413,9 +2462,9 @@ function goalBlockBody(view) {
2413
2462
  return lines;
2414
2463
  }
2415
2464
  // src/tools/builtin/goal.ts
2416
- function say2(text, ok2, startedAt) {
2465
+ function say2(text, ok4, startedAt) {
2417
2466
  const duration = Date.now() - startedAt;
2418
- return ok2 ? { success: true, output: text, duration } : { success: false, output: "", error: { code: 7101, message: text }, duration };
2467
+ return ok4 ? { success: true, output: text, duration } : { success: false, output: "", error: { code: 7101, message: text }, duration };
2419
2468
  }
2420
2469
  function createGoalTool(deps) {
2421
2470
  return {
@@ -2629,8 +2678,8 @@ ${f.content}`);
2629
2678
  );
2630
2679
  }
2631
2680
  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);
2681
+ } catch (err3) {
2682
+ return fail(err3 instanceof Error ? err3.message : String(err3), start, 4002);
2634
2683
  }
2635
2684
  }
2636
2685
  };
@@ -2837,9 +2886,9 @@ async function runCode(input) {
2837
2886
  }
2838
2887
  void relay(msg);
2839
2888
  });
2840
- worker.on("error", (err) => {
2889
+ worker.on("error", (err3) => {
2841
2890
  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 };
2891
+ 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
2892
  finish();
2844
2893
  });
2845
2894
  worker.on("exit", () => {
@@ -2862,11 +2911,11 @@ async function runCode(input) {
2862
2911
  const result = await input.callTool(msg.name, msg.args);
2863
2912
  if (result.success) reply(msg.id, { ok: true, output: result.output });
2864
2913
  else reply(msg.id, { ok: false, fatal: false, message: result.output });
2865
- } catch (err) {
2914
+ } catch (err3) {
2866
2915
  reply(msg.id, {
2867
2916
  ok: false,
2868
2917
  fatal: false,
2869
- message: err instanceof Error ? err.message : String(err)
2918
+ message: err3 instanceof Error ? err3.message : String(err3)
2870
2919
  });
2871
2920
  }
2872
2921
  };
@@ -3959,9 +4008,9 @@ function needsAllowlist(permission2) {
3959
4008
  return permission2 !== "plan" && approvalPolicyForLevel(permission2) !== "never";
3960
4009
  }
3961
4010
  // src/tools/builtin/schedule-draft.ts
3962
- function say4(text, ok2, startedAt) {
4011
+ function say4(text, ok4, startedAt) {
3963
4012
  const duration = Date.now() - startedAt;
3964
- return ok2 ? { success: true, output: text, duration } : { success: false, output: "", error: { code: 7201, message: text }, duration };
4013
+ return ok4 ? { success: true, output: text, duration } : { success: false, output: "", error: { code: 7201, message: text }, duration };
3965
4014
  }
3966
4015
  function describeRow(def) {
3967
4016
  const state = def.enabled ? "\u542F\u7528" : "\u505C\u7528";
@@ -4125,146 +4174,1416 @@ async function persist(save, draft, current) {
4125
4174
  }
4126
4175
  function createScheduleDraftTool(deps) {
4127
4176
  return {
4128
- name: SCHEDULE_DRAFT_TOOL,
4129
- description: "\u5EFA\u4E00\u6761\u5B9A\u65F6\u4EFB\u52A1\uFF0C\u6216\u8005\u6539\u4E00\u6761\u5DF2\u6709\u7684\u3002\u5B9A\u65F6\u4EFB\u52A1\u662F\u300C\u5230\u70B9\u4E86\u81EA\u5DF1\u8DD1\u4E00\u6B21\u300D\u2014\u2014\u7528\u6237\u8BF4\u300C\u4EE5\u540E\u6BCF\u5929/\u6BCF\u5468\u5E2E\u6211\u505A\u67D0\u4EF6\u4E8B\u300D\u300C\u5B9A\u671F\u68C0\u67E5\u67D0\u67D0\u300D\uFF0C\u6216\u8005\u4F60\u53D1\u73B0\u67D0\u4EF6\u4E8B\u4ED6\u6BCF\u6B21\u90FD\u8981\u624B\u52A8\u505A\u4E00\u904D\u65F6\uFF0C\u7528\u5B83\u3002action=list \u770B\u73B0\u6709\u4EFB\u52A1\uFF08\u8981\u6539\u67D0\u6761\u5FC5\u987B\u5148 list \u62FF\u5230 id\uFF09\uFF1Baction=create \u76F4\u63A5\u5EFA\u4E00\u6761\uFF1Baction=update \u76F4\u63A5\u6539\u4E00\u6761\u3002\u26A0\uFE0F **\u5B83\u4EA4\u4E0A\u53BB\u5C31\u751F\u6548**\uFF08plan \u53EA\u8BFB\u6863\u4E0B\u9664\u5916\uFF0C\u90A3\u4E00\u6863\u53EA\u4EA4\u63D0\u6848\uFF09\u2014\u2014 \u5EFA\u5B8C\u5728\u4F60\u7684\u56DE\u590D\u91CC\u4EA4\u4EE3\u4E00\u53E5\u5C31\u884C\uFF0C\u522B\u95EE\u300C\u8981\u4E0D\u8981\u6211\u5EFA\u300D\u3002\u6743\u9650\u6863\u4E0D\u7ED9\u5C31\u662F auto\uFF08\u65B0\u5EFA\u4EFB\u52A1\u7684\u7F3A\u7701\uFF09\u2014\u2014 \u5B9A\u65F6\u4EFB\u52A1\u6CA1\u4EBA\u53EF\u95EE\uFF0C\u4F4E\u6863\u5728\u8FD9\u91CC\u7B49\u4E8E\u300C\u5230\u70B9\u5FC5\u7136\u5931\u8D25\u300D\u3002\u53EA\u6709\u7528\u6237\u660E\u786E\u8981\u6C42\u300C\u53EA\u8BFB / \u522B\u52A8\u4E1C\u897F\u300D\u65F6\u624D\u7528 plan\uFF0C\u90A3\u7C7B\u4EFB\u52A1\u5929\u7136\u96F6\u6388\u6743\u9762\u3002",
4177
+ name: SCHEDULE_DRAFT_TOOL,
4178
+ description: "\u5EFA\u4E00\u6761\u5B9A\u65F6\u4EFB\u52A1\uFF0C\u6216\u8005\u6539\u4E00\u6761\u5DF2\u6709\u7684\u3002\u5B9A\u65F6\u4EFB\u52A1\u662F\u300C\u5230\u70B9\u4E86\u81EA\u5DF1\u8DD1\u4E00\u6B21\u300D\u2014\u2014\u7528\u6237\u8BF4\u300C\u4EE5\u540E\u6BCF\u5929/\u6BCF\u5468\u5E2E\u6211\u505A\u67D0\u4EF6\u4E8B\u300D\u300C\u5B9A\u671F\u68C0\u67E5\u67D0\u67D0\u300D\uFF0C\u6216\u8005\u4F60\u53D1\u73B0\u67D0\u4EF6\u4E8B\u4ED6\u6BCF\u6B21\u90FD\u8981\u624B\u52A8\u505A\u4E00\u904D\u65F6\uFF0C\u7528\u5B83\u3002action=list \u770B\u73B0\u6709\u4EFB\u52A1\uFF08\u8981\u6539\u67D0\u6761\u5FC5\u987B\u5148 list \u62FF\u5230 id\uFF09\uFF1Baction=create \u76F4\u63A5\u5EFA\u4E00\u6761\uFF1Baction=update \u76F4\u63A5\u6539\u4E00\u6761\u3002\u26A0\uFE0F **\u5B83\u4EA4\u4E0A\u53BB\u5C31\u751F\u6548**\uFF08plan \u53EA\u8BFB\u6863\u4E0B\u9664\u5916\uFF0C\u90A3\u4E00\u6863\u53EA\u4EA4\u63D0\u6848\uFF09\u2014\u2014 \u5EFA\u5B8C\u5728\u4F60\u7684\u56DE\u590D\u91CC\u4EA4\u4EE3\u4E00\u53E5\u5C31\u884C\uFF0C\u522B\u95EE\u300C\u8981\u4E0D\u8981\u6211\u5EFA\u300D\u3002\u6743\u9650\u6863\u4E0D\u7ED9\u5C31\u662F auto\uFF08\u65B0\u5EFA\u4EFB\u52A1\u7684\u7F3A\u7701\uFF09\u2014\u2014 \u5B9A\u65F6\u4EFB\u52A1\u6CA1\u4EBA\u53EF\u95EE\uFF0C\u4F4E\u6863\u5728\u8FD9\u91CC\u7B49\u4E8E\u300C\u5230\u70B9\u5FC5\u7136\u5931\u8D25\u300D\u3002\u53EA\u6709\u7528\u6237\u660E\u786E\u8981\u6C42\u300C\u53EA\u8BFB / \u522B\u52A8\u4E1C\u897F\u300D\u65F6\u624D\u7528 plan\uFF0C\u90A3\u7C7B\u4EFB\u52A1\u5929\u7136\u96F6\u6388\u6743\u9762\u3002",
4179
+ parameters: {
4180
+ type: "object",
4181
+ properties: {
4182
+ action: {
4183
+ type: "string",
4184
+ description: "\u505A\u54EA\u4E00\u4EF6",
4185
+ enum: ["list", "create", "update"]
4186
+ },
4187
+ note: {
4188
+ type: "string",
4189
+ description: "\u4E3A\u4EC0\u4E48\u5EFA\u8FD9\u6761\uFF0C\u4E00\u53E5\u8BDD\u3002create / update \u5FC5\u586B\uFF0C\u4F1A\u5370\u5728\u7528\u6237\u770B\u5230\u7684\u5361\u7247\u4E0A\uFF1B\u8BF4\u4E0D\u51FA\u771F\u5B9E\u7406\u7531\u5C31\u522B\u63D0\u8FD9\u4E2A\u5EFA\u8BAE"
4190
+ },
4191
+ id: { type: "string", description: "\u6539\u54EA\u4E00\u6761\u3002update \u5FC5\u586B\uFF0C\u4ECE action=list \u91CC\u62FF" },
4192
+ name: { type: "string", description: "\u4EFB\u52A1\u540D\uFF0C\u7528\u6237\u5728\u5217\u8868\u91CC\u770B\u5230\u7684\u5C31\u662F\u5B83" },
4193
+ prompt: {
4194
+ type: "string",
4195
+ description: "\u5230\u70B9\u4E86\u53D1\u7ED9 agent \u7684\u63D0\u793A\u8BCD\u3002\u65E0\u4EBA\u503C\u5B88\uFF0C\u6240\u4EE5\u8981\u5199\u6210\u4E00\u53E5\u81EA\u8DB3\u7684\u6307\u4EE4\uFF1B\u8BA9\u5B83\u628A\u7ED3\u679C\u8FFD\u52A0\u5230\u4E00\u4EFD markdown \u6587\u4EF6\u91CC\u901A\u5E38\u6BD4\u4EC0\u4E48\u90FD\u4E0D\u843D\u5730\u6709\u7528"
4196
+ },
4197
+ trigger: {
4198
+ type: "object",
4199
+ description: '\u4EC0\u4E48\u65F6\u5019\u8DD1\u3002\u4E09\u6863\uFF1A{kind:"cron",cycle:"daily",at:"09:00"} / {kind:"cron",cycle:"weekly",at:"09:00",weekdays:[1,3,5]} / {kind:"cron",cycle:"monthly",at:"09:00",days:[1,15]} / {kind:"interval",everyMinutes:30} / {kind:"once",date:"2026-12-31",at:"23:00"}\u3002cron \u6863\u4E00\u5929\u8DD1\u51E0\u6B21\u5C31\u628A\u5176\u4F59\u65F6\u523B\u653E\u8FDB alsoAt\uFF1A{kind:"cron",cycle:"daily",at:"09:00",alsoAt:["14:00","18:00"]}\u3002everyMinutes \u662F 5\u20131440 \u7684\u6574\u6570\uFF0C\u6BCF\u5929\u4ECE 0 \u70B9\u8D77\u7B97\u3002\u6CA1\u6709\u5B8C\u6574 cron \u8868\u8FBE\u5F0F',
4200
+ properties: {
4201
+ kind: { type: "string", enum: ["cron", "interval", "once"] },
4202
+ cycle: { type: "string", enum: ["daily", "weekly", "monthly"] },
4203
+ at: { type: "string", description: "HH:mm\uFF0C24 \u5C0F\u65F6\u5236\uFF0C\u672C\u673A\u65F6\u533A" },
4204
+ alsoAt: {
4205
+ type: "array",
4206
+ items: { type: "string" },
4207
+ description: "cron \u6863\u5728 at \u4E4B\u5916\u7684\u5176\u4F59\u65F6\u523B\uFF08HH:mm\uFF09"
4208
+ },
4209
+ weekdays: { type: "array", items: { type: "number" }, description: "0=\u5468\u65E5 \u2026 6=\u5468\u516D" },
4210
+ days: { type: "array", items: { type: "number" }, description: "\u51E0\u53F7\uFF0C1\u201331" },
4211
+ everyMinutes: { type: "number" },
4212
+ date: { type: "string", description: "YYYY-MM-DD" }
4213
+ },
4214
+ required: ["kind"]
4215
+ },
4216
+ workDir: {
4217
+ type: "string",
4218
+ description: "\u5728\u54EA\u4E2A\u76EE\u5F55\u91CC\u8DD1\u3002\u7EDD\u5BF9\u8DEF\u5F84\u3002\u4E0D\u7ED9\u5C31\u843D\u5728 ~/.epoch/automation/<id>/"
4219
+ },
4220
+ permission: {
4221
+ type: "string",
4222
+ description: "\u6743\u9650\u6863\u3002\u4E0D\u7ED9\u5C31\u662F auto\uFF08**\u65B0\u5EFA\u4EFB\u52A1\u7684\u7F3A\u7701**\uFF0C2026-10-27 \u8D77\uFF1A\u5B9A\u65F6\u4EFB\u52A1\u6CA1\u4EBA\u53EF\u95EE\uFF0C\u4F4E\u6863\u5728\u8FD9\u91CC\u7B49\u4E8E\u300C\u5230\u70B9\u5FC5\u7136\u5931\u8D25\u300D\uFF09\u3002auto=\u5B8C\u5168\u8BBF\u95EE\uFF08\u4E0D\u518D\u786E\u8BA4\uFF0C\u53EA\u5269\u707E\u96BE\u7EA7\u4F1A\u88AB\u62E6\u4E0B\uFF09\uFF1BacceptEdits=\u8BF7\u6C42\u6279\u51C6\uFF1Bdefault=\u9010\u6761\u786E\u8BA4\uFF1Bplan=\u53EA\u8BFB\uFF08\u8BFB\u4E00\u904D\u5199\u4EFD\u62A5\u544A\u7684\u4EFB\u52A1\u7528\u5B83\uFF0C\u5929\u7136\u96F6\u6388\u6743\u9762\uFF09\u3002**\u53EA\u6709\u5728\u7528\u6237\u660E\u786E\u8BF4\u4E86\u8981\u7A84\u4E00\u6863\u65F6\u624D\u964D**",
4223
+ enum: ["plan", "default", "acceptEdits", "auto"]
4224
+ },
4225
+ allowTools: {
4226
+ type: "array",
4227
+ items: { type: "string" },
4228
+ description: "\u6574\u4E2A\u5DE5\u5177\u90FD\u4E0D\u7528\u95EE\u3002\u8303\u56F4\u6700\u7C97\uFF0C\u80FD\u7528 allowRules \u5C31\u522B\u7528\u5B83"
4229
+ },
4230
+ allowOperations: {
4231
+ type: "array",
4232
+ items: { type: "string" },
4233
+ description: "\u6574\u7C7B\u64CD\u4F5C\u90FD\u4E0D\u7528\u95EE\uFF1Afile_read / file_write / command / network / code_exec"
4234
+ },
4235
+ allowRules: {
4236
+ type: "array",
4237
+ items: { type: "string" },
4238
+ 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"
4239
+ },
4240
+ enabled: { type: "boolean", description: "\u53EA\u6709 update \u7528\u3002\u542F\u7528 / \u505C\u7528\u90A3\u4E00\u6761" },
4241
+ maxTurns: { type: "number", description: "\u53EA\u6709 update \u7528\u3002\u8F6E\u6B21\u4E0A\u9650\uFF0C\u6B63\u6574\u6570" },
4242
+ timeoutMs: { type: "number", description: "\u53EA\u6709 update \u7528\u3002\u5899\u949F\u8D85\u65F6\uFF0C\u6BEB\u79D2" }
4243
+ },
4244
+ required: ["action"]
4245
+ },
4246
+ exposure: ToolExposure.Direct,
4247
+ supportsParallel: false,
4248
+ annotations: {
4249
+ readOnlyHint: false,
4250
+ destructiveHint: true,
4251
+ idempotentHint: false,
4252
+ openWorldHint: false
4253
+ },
4254
+ operation: "file_read",
4255
+ describeTarget: (args) => `schedule_draft:${String(args["action"] ?? "list")}`,
4256
+ async execute(rawArgs, ctx) {
4257
+ const startedAt = Date.now();
4258
+ const action = rawArgs["action"];
4259
+ if (action === "list") {
4260
+ const rows = deps.list();
4261
+ return say4(
4262
+ 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
4263
+ ${rows.map(describeRow).join("\n")}`,
4264
+ true,
4265
+ startedAt
4266
+ );
4267
+ }
4268
+ const parsed = parseScheduleDraft(rawArgs);
4269
+ if (!parsed.ok) return say4(parsed.message, false, startedAt);
4270
+ const draft = parsed.value;
4271
+ const current = draft.action === "update" ? deps.get(draft.id) : void 0;
4272
+ if (draft.action === "update" && current === void 0) {
4273
+ return say4(
4274
+ `\u6CA1\u6709 id \u4E3A ${draft.id} \u7684\u4EFB\u52A1\u3002\u5148\u7528 action=list \u770B\u4E00\u773C\u73B0\u6709\u7684\u3002`,
4275
+ false,
4276
+ startedAt
4277
+ );
4278
+ }
4279
+ const issues = validateDraft(draft, deps.homeDir, current);
4280
+ if (issues.length > 0) {
4281
+ return say4(
4282
+ `\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`,
4283
+ false,
4284
+ startedAt
4285
+ );
4286
+ }
4287
+ const unattended = unattendedIssues(draft);
4288
+ if (unattended.length > 0) {
4289
+ return say4(
4290
+ `\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
4291
+ ${unattended.map((x) => `\xB7 ${x}`).join("\n")}`,
4292
+ false,
4293
+ startedAt
4294
+ );
4295
+ }
4296
+ const readOnly = ctx.permissionLevel === "plan";
4297
+ if (readOnly || deps.save === void 0) {
4298
+ return say4(summarizeProposal(draft, current, readOnly), true, startedAt);
4299
+ }
4300
+ const saved = await persist(deps.save, draft, current);
4301
+ if (saved.issues.length > 0) {
4302
+ const codes = saved.issues.map((x) => x.detail ? `${x.code}\uFF08${x.detail}\uFF09` : x.code);
4303
+ 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);
4304
+ }
4305
+ const def = saved.schedule;
4306
+ if (def === void 0) {
4307
+ return say4(
4308
+ "\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",
4309
+ false,
4310
+ startedAt
4311
+ );
4312
+ }
4313
+ return say4(summarizeSaved(draft, def, saved.registration, current), true, startedAt);
4314
+ }
4315
+ };
4316
+ }
4317
+ var DEFAULT_INBOX_CAPACITY = 20;
4318
+ var AgentInbox = class {
4319
+ constructor(capacity = DEFAULT_INBOX_CAPACITY) {
4320
+ this.capacity = capacity;
4321
+ }
4322
+ capacity;
4323
+ queue = [];
4324
+ dropped = 0;
4325
+ push(msg) {
4326
+ let evicted = false;
4327
+ while (this.queue.length >= this.capacity) {
4328
+ this.queue.shift();
4329
+ this.dropped += 1;
4330
+ evicted = true;
4331
+ }
4332
+ this.queue.push(msg);
4333
+ return !evicted;
4334
+ }
4335
+ pending() {
4336
+ return this.queue.length > 0;
4337
+ }
4338
+ take() {
4339
+ if (this.queue.length === 0) return [];
4340
+ const lines = this.queue.map((m) => agentMessageLine(m));
4341
+ this.queue = [];
4342
+ if (this.dropped > 0) {
4343
+ lines.unshift(systemNote(`\u6536\u4EF6\u7BB1\u6EE1\u4E86\uFF0C\u6709 ${this.dropped} \u6761\u66F4\u65E9\u7684\u6D88\u606F\u88AB\u4E22\u5F03`));
4344
+ this.dropped = 0;
4345
+ }
4346
+ return [lines.join("\n")];
4347
+ }
4348
+ get size() {
4349
+ return this.queue.length;
4350
+ }
4351
+ };
4352
+ var DEFAULT_TASK_CAPACITY = 200;
4353
+ var TeamTaskBoard = class {
4354
+ constructor(capacity = DEFAULT_TASK_CAPACITY) {
4355
+ this.capacity = capacity;
4356
+ }
4357
+ capacity;
4358
+ tasks = /* @__PURE__ */ new Map();
4359
+ listeners = /* @__PURE__ */ new Set();
4360
+ onChange(cb) {
4361
+ this.listeners.add(cb);
4362
+ return () => {
4363
+ this.listeners.delete(cb);
4364
+ };
4365
+ }
4366
+ notify() {
4367
+ for (const cb of this.listeners) {
4368
+ try {
4369
+ cb();
4370
+ } catch {
4371
+ }
4372
+ }
4373
+ }
4374
+ create(input) {
4375
+ if (this.tasks.size >= this.capacity) {
4376
+ return { ok: false, reason: `\u4EFB\u52A1\u677F\u6EE1\u4E86\uFF08${this.capacity} \u6761\uFF09\uFF0C\u5148\u505A\u5B8C\u518D\u5EFA` };
4377
+ }
4378
+ const dependsOn = input.dependsOn ?? [];
4379
+ const missing = dependsOn.filter((id) => !this.tasks.has(id));
4380
+ if (missing.length > 0) {
4381
+ return { ok: false, reason: `\u4F9D\u8D56\u7684\u4EFB\u52A1\u4E0D\u5B58\u5728\uFF1A${missing.join(", ")}` };
4382
+ }
4383
+ const now = Date.now();
4384
+ const task = {
4385
+ id: `task-${randomUUID().slice(0, 8)}`,
4386
+ title: input.title,
4387
+ ...input.description ? { description: input.description } : {},
4388
+ ...input.owner ? { owner: input.owner } : {},
4389
+ status: "pending",
4390
+ dependsOn,
4391
+ revision: 1,
4392
+ createdAt: now,
4393
+ updatedAt: now
4394
+ };
4395
+ this.tasks.set(task.id, task);
4396
+ this.notify();
4397
+ return { ok: true, task: { ...task } };
4398
+ }
4399
+ get(id) {
4400
+ const t83 = this.tasks.get(id);
4401
+ return t83 ? { ...t83 } : void 0;
4402
+ }
4403
+ list(filter) {
4404
+ 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 }));
4405
+ }
4406
+ update(id, patch, expectedRevision) {
4407
+ const current = this.tasks.get(id);
4408
+ if (!current) return { ok: false, reason: `\u6CA1\u6709\u8FD9\u4E2A\u4EFB\u52A1\uFF1A${id}` };
4409
+ if (expectedRevision !== void 0 && current.revision !== expectedRevision) {
4410
+ return {
4411
+ ok: false,
4412
+ 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`
4413
+ };
4414
+ }
4415
+ const next = {
4416
+ ...current,
4417
+ ...patch.title !== void 0 ? { title: patch.title } : {},
4418
+ ...patch.description !== void 0 ? { description: patch.description } : {},
4419
+ ...patch.status !== void 0 ? { status: patch.status } : {},
4420
+ ...patch.owner !== void 0 ? { owner: patch.owner } : {},
4421
+ revision: current.revision + 1,
4422
+ updatedAt: Date.now()
4423
+ };
4424
+ this.tasks.set(id, next);
4425
+ this.notify();
4426
+ return { ok: true, task: { ...next } };
4427
+ }
4428
+ };
4429
+ // src/team/registry.ts
4430
+ var TeamRegistry = class {
4431
+ constructor(inboxCapacity = DEFAULT_INBOX_CAPACITY) {
4432
+ this.inboxCapacity = inboxCapacity;
4433
+ this.tasks = new TeamTaskBoard();
4434
+ this.tasks.onChange(() => this.notify());
4435
+ }
4436
+ inboxCapacity;
4437
+ members = /* @__PURE__ */ new Map();
4438
+ bySessionId = /* @__PURE__ */ new Map();
4439
+ mainInboxes = /* @__PURE__ */ new Map();
4440
+ sessions = /* @__PURE__ */ new Set();
4441
+ aborters = /* @__PURE__ */ new Map();
4442
+ listeners = /* @__PURE__ */ new Set();
4443
+ tasks;
4444
+ onChange(cb) {
4445
+ this.listeners.add(cb);
4446
+ return () => {
4447
+ this.listeners.delete(cb);
4448
+ };
4449
+ }
4450
+ notify() {
4451
+ for (const cb of this.listeners) {
4452
+ try {
4453
+ cb();
4454
+ } catch {
4455
+ }
4456
+ }
4457
+ }
4458
+ waitForChange(ms, signal) {
4459
+ return new Promise((resolve17) => {
4460
+ let done2 = false;
4461
+ const onAbort = () => finish(false);
4462
+ const cleanup = () => {
4463
+ off();
4464
+ clearTimeout(timer);
4465
+ signal?.removeEventListener?.("abort", onAbort);
4466
+ };
4467
+ const finish = (v) => {
4468
+ if (done2) return;
4469
+ done2 = true;
4470
+ cleanup();
4471
+ resolve17(v);
4472
+ };
4473
+ const off = this.onChange(() => finish(true));
4474
+ const timer = setTimeout(() => finish(false), ms);
4475
+ signal?.addEventListener?.("abort", onAbort);
4476
+ });
4477
+ }
4478
+ createMember(args) {
4479
+ const agentId = args.agentId ?? args.sessionId;
4480
+ if (this.members.has(agentId)) {
4481
+ throw new Error(`\u6210\u5458\u540D\u5DF2\u88AB\u5360\u7528\uFF1A${agentId}`);
4482
+ }
4483
+ const info = {
4484
+ agentId,
4485
+ sessionId: args.sessionId,
4486
+ parentSessionId: args.parentSessionId,
4487
+ status: "running",
4488
+ ...args.role ? { role: args.role } : {},
4489
+ startedAt: Date.now()
4490
+ };
4491
+ this.members.set(agentId, {
4492
+ info,
4493
+ inbox: new AgentInbox(this.inboxCapacity)
4494
+ });
4495
+ this.bySessionId.set(args.sessionId, agentId);
4496
+ this.notify();
4497
+ return { ...info };
4498
+ }
4499
+ setAbort(agentId, fn) {
4500
+ if (!this.members.has(agentId)) return;
4501
+ this.aborters.set(agentId, fn);
4502
+ }
4503
+ interrupt(agentId) {
4504
+ const fn = this.aborters.get(agentId);
4505
+ if (!fn) return false;
4506
+ fn();
4507
+ this.notify();
4508
+ return true;
4509
+ }
4510
+ get(agentId) {
4511
+ const entry = this.members.get(agentId);
4512
+ return entry ? { ...entry.info } : void 0;
4513
+ }
4514
+ bySession(sessionId) {
4515
+ const agentId = this.bySessionId.get(sessionId);
4516
+ return agentId ? this.get(agentId) : void 0;
4517
+ }
4518
+ list() {
4519
+ return [...this.members.values()].map((e) => e.info).sort((a, b) => a.startedAt - b.startedAt);
4520
+ }
4521
+ inboxOf(agentId) {
4522
+ return this.members.get(agentId)?.inbox;
4523
+ }
4524
+ inboxBySession(sessionId) {
4525
+ const agentId = this.bySessionId.get(sessionId);
4526
+ return agentId ? this.inboxOf(agentId) : void 0;
4527
+ }
4528
+ registerSession(sessionId) {
4529
+ if (this.sessions.has(sessionId)) return;
4530
+ this.sessions.add(sessionId);
4531
+ this.notify();
4532
+ }
4533
+ hasSession(sessionId) {
4534
+ return this.sessions.has(sessionId);
4535
+ }
4536
+ sessionIds() {
4537
+ return [...this.sessions];
4538
+ }
4539
+ mainInbox(sessionId) {
4540
+ let inbox = this.mainInboxes.get(sessionId);
4541
+ if (!inbox) {
4542
+ inbox = new AgentInbox(this.inboxCapacity);
4543
+ this.mainInboxes.set(sessionId, inbox);
4544
+ }
4545
+ return inbox;
4546
+ }
4547
+ setActivity(agentId, line) {
4548
+ const entry = this.members.get(agentId);
4549
+ if (!entry) return;
4550
+ entry.info.activity = line;
4551
+ }
4552
+ markRunning(agentId) {
4553
+ const entry = this.members.get(agentId);
4554
+ if (!entry) return;
4555
+ entry.info.status = "running";
4556
+ delete entry.info.finishedAt;
4557
+ delete entry.info.activity;
4558
+ this.notify();
4559
+ }
4560
+ markFinished(agentId, status) {
4561
+ const entry = this.members.get(agentId);
4562
+ if (!entry) return;
4563
+ if (entry.info.finishedAt !== void 0) return;
4564
+ entry.info.status = status;
4565
+ entry.info.finishedAt = Date.now();
4566
+ this.aborters.delete(agentId);
4567
+ this.notify();
4568
+ }
4569
+ deliver(msg) {
4570
+ if (msg.to === LEAD_AGENT_ID) {
4571
+ const sender = this.members.get(msg.from);
4572
+ if (sender) {
4573
+ this.mainInbox(sender.info.parentSessionId).push(msg);
4574
+ this.notify();
4575
+ return { ok: true, to: msg.to, status: "running" };
4576
+ }
4577
+ return { ok: false, to: msg.to, reason: `\u4E3B\u4F1A\u8BDD\u4E0D\u80FD\u53D1\u7ED9 ${LEAD_AGENT_ID}` };
4578
+ }
4579
+ const entry = this.members.get(msg.to);
4580
+ if (entry) {
4581
+ if (entry.info.status === "finalized" || entry.info.status === "failed") {
4582
+ return {
4583
+ ok: false,
4584
+ to: msg.to,
4585
+ 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`
4586
+ };
4587
+ }
4588
+ entry.inbox.push(msg);
4589
+ this.notify();
4590
+ return { ok: true, to: msg.to, status: entry.info.status };
4591
+ }
4592
+ if (this.sessions.has(msg.to)) {
4593
+ this.mainInbox(msg.to).push(msg);
4594
+ this.notify();
4595
+ return { ok: true, to: msg.to, status: "running" };
4596
+ }
4597
+ return {
4598
+ ok: false,
4599
+ to: msg.to,
4600
+ reason: `\u6CA1\u6709\u8FD9\u4E2A\u6210\u5458\u6216\u4F1A\u8BDD\uFF1A${msg.to}\u3002\u7528 list_agents --all \u770B\u73B0\u5728\u6709\u8C01`
4601
+ };
4602
+ }
4603
+ static message(args) {
4604
+ return {
4605
+ id: randomUUID(),
4606
+ from: args.from,
4607
+ to: args.to,
4608
+ text: args.text,
4609
+ sentAt: Date.now()
4610
+ };
4611
+ }
4612
+ };
4613
+ // src/tools/builtin/send-message.ts
4614
+ var SEND_MESSAGE_TOOL = "send_message";
4615
+ function createSendMessageTool(team) {
4616
+ return {
4617
+ name: SEND_MESSAGE_TOOL,
4618
+ description: [
4619
+ "\u7ED9\u53E6\u4E00\u4E2A agent \u6216**\u53E6\u4E00\u6BB5\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",
4620
+ "\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",
4621
+ `\u53D1\u7ED9 \`${LEAD_AGENT_ID}\`\uFF08\u6D3E\u4F60\u51FA\u6765\u7684\u90A3\u4E2A\u4F1A\u8BDD\uFF09\uFF1A\u5B83\u4E0B\u4E00\u8F6E\u5F00\u5934\u4F1A\u770B\u5230\u3002`,
4622
+ "\u53D1\u7ED9**\u53E6\u4E00\u6BB5\u4E3B\u4F1A\u8BDD**\uFF08\u7528 list_agents --all \u770B\u5230\u7684\u90A3\u4E2A sessionId\uFF09\uFF1A\u5B83\u4E0B\u4E00\u8F6E\u5F00\u5934\u4F1A\u770B\u5230\u3002",
4623
+ "\u53D1\u7ED9\u5DF2\u7ECF\u6536\u5DE5\u7684\u6210\u5458\u4F1A\u5931\u8D25 \u2014\u2014 \u90A3\u4E9B\u8981\u9760 delegate_task \u91CD\u65B0\u6D3E\u3002",
4624
+ "\u7528 list_agents \u770B\u672C\u4F1A\u8BDD\u7684\u6210\u5458\uFF1B\u52A0 --all \u770B\u6240\u6709\u4F1A\u8BDD\u548C\u6210\u5458\u3002"
4625
+ ].join("\n"),
4626
+ parameters: {
4627
+ type: "object",
4628
+ properties: {
4629
+ to: {
4630
+ type: "string",
4631
+ description: `\u6536\u4EF6\u4EBA\uFF1A\u67D0\u4E2A\u6210\u5458\u7684 id\uFF0C\u6216 \`${LEAD_AGENT_ID}\``
4632
+ },
4633
+ text: {
4634
+ type: "string",
4635
+ 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"
4636
+ }
4637
+ },
4638
+ required: ["to", "text"]
4639
+ },
4640
+ exposure: ToolExposure.Direct,
4641
+ supportsParallel: false,
4642
+ operation: "file_read",
4643
+ annotations: {
4644
+ readOnlyHint: true,
4645
+ destructiveHint: false,
4646
+ idempotentHint: false,
4647
+ openWorldHint: false
4648
+ },
4649
+ describeTarget: (args) => String(args["to"] ?? ""),
4650
+ async execute(args, ctx) {
4651
+ const start = Date.now();
4652
+ const to = typeof args["to"] === "string" ? args["to"].trim() : "";
4653
+ const text = typeof args["text"] === "string" ? args["text"].trim() : "";
4654
+ if (!to) {
4655
+ return {
4656
+ success: false,
4657
+ output: "",
4658
+ error: {
4659
+ code: 7101,
4660
+ message: "\u7F3A\u5C11\u6536\u4EF6\u4EBA\uFF08to\uFF09",
4661
+ suggestion: `\u586B\u4E00\u4E2A\u6210\u5458 id\uFF0C\u6216 \`${LEAD_AGENT_ID}\``
4662
+ },
4663
+ duration: Date.now() - start
4664
+ };
4665
+ }
4666
+ if (!text) {
4667
+ return {
4668
+ success: false,
4669
+ output: "",
4670
+ error: { code: 7102, message: "\u6D88\u606F\u5185\u5BB9\uFF08text\uFF09\u662F\u7A7A\u7684" },
4671
+ duration: Date.now() - start
4672
+ };
4673
+ }
4674
+ const memberInfo = team.bySession(ctx.sessionId);
4675
+ const target = team.get(to);
4676
+ const ownMember = target !== void 0 && target.parentSessionId === ctx.sessionId;
4677
+ const from = memberInfo ? memberInfo.agentId : ownMember ? LEAD_AGENT_ID : ctx.sessionId;
4678
+ const result = team.deliver(TeamRegistry.message({ from, to, text }));
4679
+ if (!result.ok) {
4680
+ return {
4681
+ success: false,
4682
+ output: "",
4683
+ error: { code: 7103, message: result.reason },
4684
+ duration: Date.now() - start
4685
+ };
4686
+ }
4687
+ return {
4688
+ success: true,
4689
+ output: result.to === LEAD_AGENT_ID ? `\u5DF2\u9001\u5230 lead\uFF0C\u5B83\u4E0B\u4E00\u8F6E\u5F00\u5934\u4F1A\u770B\u5230\u3002` : `\u5DF2\u9001\u5230 ${result.to}\uFF08${result.status}\uFF09\uFF0C\u5B83\u4E0B\u4E00\u8F6E\u5F00\u5934\u4F1A\u770B\u5230\u3002`,
4690
+ duration: Date.now() - start
4691
+ };
4692
+ }
4693
+ };
4694
+ }
4695
+ function err(code, message, suggestion) {
4696
+ return {
4697
+ success: false,
4698
+ output: "",
4699
+ error: { code, message, ...{} },
4700
+ duration: 0
4701
+ };
4702
+ }
4703
+ function ok2(output) {
4704
+ return { success: true, output, duration: 0 };
4705
+ }
4706
+ function str2(args, key) {
4707
+ const v = args[key];
4708
+ return typeof v === "string" ? v.trim() : "";
4709
+ }
4710
+ function parseTarget(raw) {
4711
+ const t83 = raw.trim();
4712
+ if (!t83) return null;
4713
+ return t83.startsWith("th-") ? { kind: "thread", id: t83 } : { kind: "channel", name: t83 };
4714
+ }
4715
+ function authorOf(deps, ctx) {
4716
+ return deps.agentOf(ctx.sessionId) ?? LEAD_AGENT_ID;
4717
+ }
4718
+ function renderPost(p) {
4719
+ const who = p.author;
4720
+ const when = new Date(p.createdAt).toISOString().slice(0, 16).replace("T", " ");
4721
+ const body2 = p.text.length > 2e3 ? `${p.text.slice(0, 2e3)}\u2026` : p.text;
4722
+ return `#${p.seq} [${p.id}] ${who} \xB7 ${when}
4723
+ ${body2}`;
4724
+ }
4725
+ function renderThread(t83) {
4726
+ return `- ${t83.id} ${t83.title} (${t83.postCount} \u5E16\uFF0C\u6700\u540E ${new Date(t83.lastPostAt).toISOString().slice(0, 16).replace("T", " ")})`;
4727
+ }
4728
+ function createBoardTools(store, deps) {
4729
+ const targetParam = {
4730
+ type: "string",
4731
+ 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"
4732
+ };
4733
+ const tools = [
4734
+ {
4735
+ name: "get_channels",
4736
+ 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",
4737
+ parameters: { type: "object", properties: {}, required: [] },
4738
+ exposure: ToolExposure.Direct,
4739
+ supportsParallel: true,
4740
+ operation: "file_read",
4741
+ annotations: {
4742
+ readOnlyHint: true,
4743
+ destructiveHint: false,
4744
+ idempotentHint: true,
4745
+ openWorldHint: false
4746
+ },
4747
+ describeTarget: () => "\u9891\u9053\u5217\u8868",
4748
+ async execute() {
4749
+ const channels = store.listChannels();
4750
+ if (channels.length === 0) return ok2("\u8FD8\u6CA1\u6709\u9891\u9053\u3002\u7528 create_channel \u5EFA\u4E00\u4E2A\u3002");
4751
+ return ok2(
4752
+ channels.map((c) => `- ${c.name}${c.description ? `\uFF1A${c.description}` : ""}`).join("\n")
4753
+ );
4754
+ }
4755
+ },
4756
+ {
4757
+ name: "create_channel",
4758
+ 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",
4759
+ parameters: {
4760
+ type: "object",
4761
+ properties: {
4762
+ name: { type: "string", description: "\u9891\u9053\u540D\uFF0C\u5B57\u6BCD\u6570\u5B57 _ . -" },
4763
+ description: { type: "string", description: "\u8FD9\u4E2A\u9891\u9053\u662F\u5E72\u4EC0\u4E48\u7684" }
4764
+ },
4765
+ required: ["name"]
4766
+ },
4767
+ exposure: ToolExposure.Deferred,
4768
+ supportsParallel: false,
4769
+ operation: "file_read",
4770
+ annotations: {
4771
+ readOnlyHint: false,
4772
+ destructiveHint: false,
4773
+ idempotentHint: true,
4774
+ openWorldHint: false
4775
+ },
4776
+ describeTarget: (args) => String(args["name"] ?? ""),
4777
+ async execute(args, ctx) {
4778
+ const name = str2(args, "name");
4779
+ if (!name) return err(7401, "\u7F3A\u5C11 name");
4780
+ try {
4781
+ const description = str2(args, "description");
4782
+ const ch = store.createChannel({
4783
+ name,
4784
+ ...description ? { description } : {},
4785
+ by: authorOf(deps, ctx)
4786
+ });
4787
+ return ok2(`\u9891\u9053 ${ch.name} \u5C31\u7EEA${ch.description ? `\uFF1A${ch.description}` : ""}`);
4788
+ } catch (cause) {
4789
+ return err(7402, cause instanceof Error ? cause.message : String(cause));
4790
+ }
4791
+ }
4792
+ },
4793
+ {
4794
+ name: "upsert_channel",
4795
+ 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",
4796
+ parameters: {
4797
+ type: "object",
4798
+ properties: {
4799
+ name: { type: "string", description: "\u9891\u9053\u540D" },
4800
+ description: { type: "string", description: "\u65B0\u7684\u63CF\u8FF0" }
4801
+ },
4802
+ required: ["name", "description"]
4803
+ },
4804
+ exposure: ToolExposure.Deferred,
4805
+ supportsParallel: false,
4806
+ operation: "file_read",
4807
+ annotations: {
4808
+ readOnlyHint: false,
4809
+ destructiveHint: false,
4810
+ idempotentHint: true,
4811
+ openWorldHint: false
4812
+ },
4813
+ describeTarget: (args) => String(args["name"] ?? ""),
4814
+ async execute(args, ctx) {
4815
+ const name = str2(args, "name");
4816
+ const description = str2(args, "description");
4817
+ if (!name) return err(7403, "\u7F3A\u5C11 name");
4818
+ if (!description) return err(7404, "\u7F3A\u5C11 description");
4819
+ try {
4820
+ store.upsertChannel({ name, description, by: authorOf(deps, ctx) });
4821
+ return ok2(`\u9891\u9053 ${name} \u7684\u63CF\u8FF0\u5DF2\u66F4\u65B0\u3002`);
4822
+ } catch (cause) {
4823
+ return err(7405, cause instanceof Error ? cause.message : String(cause));
4824
+ }
4825
+ }
4826
+ },
4827
+ {
4828
+ name: "list_threads",
4829
+ description: "\u5217\u51FA\u67D0\u4E2A\u9891\u9053\u91CC\u7684\u7EBF\u7A0B\uFF0C\u6309\u6700\u540E\u6D3B\u52A8\u6392\u5E8F\u3002",
4830
+ parameters: {
4831
+ type: "object",
4832
+ properties: {
4833
+ channel: { type: "string", description: "\u9891\u9053\u540D" },
4834
+ limit: { type: "number", description: "\u6700\u591A\u51E0\u6761\uFF0C\u9ED8\u8BA4 20" }
4835
+ },
4836
+ required: ["channel"]
4837
+ },
4838
+ exposure: ToolExposure.Deferred,
4839
+ supportsParallel: true,
4840
+ operation: "file_read",
4841
+ annotations: {
4842
+ readOnlyHint: true,
4843
+ destructiveHint: false,
4844
+ idempotentHint: true,
4845
+ openWorldHint: false
4846
+ },
4847
+ describeTarget: (args) => String(args["channel"] ?? ""),
4848
+ async execute(args) {
4849
+ const channel = str2(args, "channel");
4850
+ if (!channel) return err(7406, "\u7F3A\u5C11 channel");
4851
+ if (!store.channel(channel)) return err(7407, `\u6CA1\u6709\u8FD9\u4E2A\u9891\u9053\uFF1A${channel}`);
4852
+ const limit = typeof args["limit"] === "number" ? Math.min(Math.max(1, args["limit"]), 200) : 20;
4853
+ const threads = store.listThreads(channel, limit);
4854
+ if (threads.length === 0) return ok2(`\u9891\u9053 ${channel} \u91CC\u8FD8\u6CA1\u6709\u7EBF\u7A0B\u3002`);
4855
+ return ok2(threads.map(renderThread).join("\n"));
4856
+ }
4857
+ },
4858
+ {
4859
+ name: "read_thread",
4860
+ 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",
4861
+ parameters: {
4862
+ type: "object",
4863
+ properties: {
4864
+ threadId: { type: "string", description: "\u7EBF\u7A0B id\uFF08th- \u5F00\u5934\uFF09" },
4865
+ limit: { type: "number", description: "\u6700\u591A\u51E0\u6761\uFF0C\u9ED8\u8BA4 50" }
4866
+ },
4867
+ required: ["threadId"]
4868
+ },
4869
+ exposure: ToolExposure.Direct,
4870
+ supportsParallel: true,
4871
+ operation: "file_read",
4872
+ annotations: {
4873
+ readOnlyHint: false,
4874
+ destructiveHint: false,
4875
+ idempotentHint: false,
4876
+ openWorldHint: false
4877
+ },
4878
+ describeTarget: (args) => String(args["threadId"] ?? ""),
4879
+ async execute(args, ctx) {
4880
+ const threadId = str2(args, "threadId");
4881
+ if (!threadId) return err(7408, "\u7F3A\u5C11 threadId");
4882
+ const limit = typeof args["limit"] === "number" ? Math.min(Math.max(1, args["limit"]), 500) : 50;
4883
+ const posts = store.readThread(threadId, limit);
4884
+ if (posts.length === 0) {
4885
+ return ok2(`\u7EBF\u7A0B ${threadId} \u91CC\u6CA1\u6709\u5E16\u5B50\uFF08\u6216\u8005\u8FD9\u4E2A\u7EBF\u7A0B\u4E0D\u5B58\u5728\uFF09\u3002`);
4886
+ }
4887
+ store.markRead(authorOf(deps, ctx), { kind: "thread", id: threadId });
4888
+ return ok2(posts.map(renderPost).join("\n\n"));
4889
+ }
4890
+ },
4891
+ {
4892
+ name: "read_post",
4893
+ description: "\u8BFB\u4E00\u6761\u5E16\u5B50\u7684\u5168\u6587\uFF08`read_thread` \u4F1A\u622A\u65AD\u957F\u5E16\uFF09\u3002",
4894
+ parameters: {
4895
+ type: "object",
4896
+ properties: { postId: { type: "string", description: "\u5E16\u5B50 id\uFF08po- \u5F00\u5934\uFF09" } },
4897
+ required: ["postId"]
4898
+ },
4899
+ exposure: ToolExposure.Deferred,
4900
+ supportsParallel: true,
4901
+ operation: "file_read",
4902
+ annotations: {
4903
+ readOnlyHint: true,
4904
+ destructiveHint: false,
4905
+ idempotentHint: true,
4906
+ openWorldHint: false
4907
+ },
4908
+ describeTarget: (args) => String(args["postId"] ?? ""),
4909
+ async execute(args) {
4910
+ const id = str2(args, "postId");
4911
+ const p = store.readPost(id);
4912
+ if (!p) return err(7409, `\u6CA1\u6709\u8FD9\u6761\u5E16\u5B50\uFF1A${id}`);
4913
+ return ok2(renderPost(p));
4914
+ }
4915
+ },
4916
+ {
4917
+ name: "search_posts",
4918
+ 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",
4919
+ parameters: {
4920
+ type: "object",
4921
+ properties: {
4922
+ query: { type: "string", description: "\u8981\u627E\u7684\u8BCD" },
4923
+ channel: { type: "string", description: "\u53EA\u5728\u8FD9\u4E2A\u9891\u9053\u91CC\u627E" },
4924
+ limit: { type: "number", description: "\u6700\u591A\u51E0\u6761\uFF0C\u9ED8\u8BA4 20" }
4925
+ },
4926
+ required: ["query"]
4927
+ },
4928
+ exposure: ToolExposure.Deferred,
4929
+ supportsParallel: true,
4930
+ operation: "file_read",
4931
+ annotations: {
4932
+ readOnlyHint: true,
4933
+ destructiveHint: false,
4934
+ idempotentHint: true,
4935
+ openWorldHint: false
4936
+ },
4937
+ describeTarget: (args) => String(args["query"] ?? ""),
4938
+ async execute(args) {
4939
+ const query = str2(args, "query");
4940
+ if (!query) return err(7410, "\u7F3A\u5C11 query");
4941
+ const channel = str2(args, "channel");
4942
+ const limit = typeof args["limit"] === "number" ? Math.min(Math.max(1, args["limit"]), 100) : 20;
4943
+ const posts = store.searchPosts(query, channel || void 0, limit);
4944
+ if (posts.length === 0) return ok2(`\u6CA1\u6709\u627E\u5230\u5305\u542B\u300C${query}\u300D\u7684\u5E16\u5B50\u3002`);
4945
+ return ok2(posts.map(renderPost).join("\n\n"));
4946
+ }
4947
+ },
4948
+ {
4949
+ name: "post",
4950
+ description: [
4951
+ "\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",
4952
+ "**\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",
4953
+ "\u60F3\u9759\u9ED8\u8BB0\u4E2A\u6D41\u6C34\uFF08\u4E0D\u901A\u77E5\u4EFB\u4F55\u4EBA\uFF09\u7528 append\u3002"
4954
+ ].join("\n"),
4955
+ parameters: {
4956
+ type: "object",
4957
+ properties: { target: targetParam, text: { type: "string", description: "\u5E16\u5B50\u6B63\u6587" } },
4958
+ required: ["target", "text"]
4959
+ },
4960
+ exposure: ToolExposure.Deferred,
4961
+ supportsParallel: false,
4962
+ operation: "file_read",
4963
+ annotations: {
4964
+ readOnlyHint: false,
4965
+ destructiveHint: false,
4966
+ idempotentHint: false,
4967
+ openWorldHint: false
4968
+ },
4969
+ describeTarget: (args) => String(args["target"] ?? ""),
4970
+ async execute(args, ctx) {
4971
+ const target = parseTarget(str2(args, "target"));
4972
+ const text = str2(args, "text");
4973
+ if (!target) return err(7411, "\u7F3A\u5C11 target");
4974
+ if (!text) return err(7412, "\u7F3A\u5C11 text");
4975
+ try {
4976
+ const r = store.post({ target, author: authorOf(deps, ctx), text });
4977
+ return ok2(`\u5DF2\u53D1\u5E16 ${r.post.id}\uFF08\u7EBF\u7A0B ${r.threadId}\uFF0C#${r.post.seq}\uFF09\u3002`);
4978
+ } catch (cause) {
4979
+ return err(7413, cause instanceof Error ? cause.message : String(cause));
4980
+ }
4981
+ }
4982
+ },
4983
+ {
4984
+ name: "append",
4985
+ description: [
4986
+ "**\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",
4987
+ "\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**",
4988
+ "\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"
4989
+ ].join("\n"),
4990
+ parameters: {
4991
+ type: "object",
4992
+ properties: { target: targetParam, text: { type: "string", description: "\u6B63\u6587" } },
4993
+ required: ["target", "text"]
4994
+ },
4995
+ exposure: ToolExposure.Deferred,
4996
+ supportsParallel: false,
4997
+ operation: "file_read",
4998
+ annotations: {
4999
+ readOnlyHint: false,
5000
+ destructiveHint: false,
5001
+ idempotentHint: false,
5002
+ openWorldHint: false
5003
+ },
5004
+ describeTarget: (args) => String(args["target"] ?? ""),
5005
+ async execute(args, ctx) {
5006
+ const target = parseTarget(str2(args, "target"));
5007
+ const text = str2(args, "text");
5008
+ if (!target) return err(7414, "\u7F3A\u5C11 target");
5009
+ if (!text) return err(7415, "\u7F3A\u5C11 text");
5010
+ try {
5011
+ const r = store.append({ target, author: authorOf(deps, ctx), text });
5012
+ 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`);
5013
+ } catch (cause) {
5014
+ return err(7416, cause instanceof Error ? cause.message : String(cause));
5015
+ }
5016
+ }
5017
+ },
5018
+ {
5019
+ name: "subscribe",
5020
+ 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",
5021
+ parameters: {
5022
+ type: "object",
5023
+ properties: { target: { ...targetParam, description: "\u9891\u9053\u540D\u6216\u7EBF\u7A0B id" } },
5024
+ required: ["target"]
5025
+ },
5026
+ exposure: ToolExposure.Deferred,
5027
+ supportsParallel: false,
5028
+ operation: "file_read",
5029
+ annotations: {
5030
+ readOnlyHint: false,
5031
+ destructiveHint: false,
5032
+ idempotentHint: true,
5033
+ openWorldHint: false
5034
+ },
5035
+ describeTarget: (args) => String(args["target"] ?? ""),
5036
+ async execute(args, ctx) {
5037
+ const target = parseTarget(str2(args, "target"));
5038
+ if (!target) return err(7417, "\u7F3A\u5C11 target");
5039
+ store.subscribe(authorOf(deps, ctx), target);
5040
+ return ok2(`\u5DF2\u8BA2\u9605 ${str2(args, "target")}\u3002`);
5041
+ }
5042
+ },
5043
+ {
5044
+ name: "unsubscribe",
5045
+ description: "\u53D6\u6D88\u8BA2\u9605\u3002",
5046
+ parameters: {
5047
+ type: "object",
5048
+ properties: { target: { ...targetParam, description: "\u9891\u9053\u540D\u6216\u7EBF\u7A0B id" } },
5049
+ required: ["target"]
5050
+ },
5051
+ exposure: ToolExposure.Deferred,
5052
+ supportsParallel: false,
5053
+ operation: "file_read",
5054
+ annotations: {
5055
+ readOnlyHint: false,
5056
+ destructiveHint: false,
5057
+ idempotentHint: true,
5058
+ openWorldHint: false
5059
+ },
5060
+ describeTarget: (args) => String(args["target"] ?? ""),
5061
+ async execute(args, ctx) {
5062
+ const target = parseTarget(str2(args, "target"));
5063
+ if (!target) return err(7418, "\u7F3A\u5C11 target");
5064
+ const removed = store.unsubscribe(authorOf(deps, ctx), target);
5065
+ return ok2(
5066
+ removed ? `\u5DF2\u53D6\u6D88\u8BA2\u9605 ${str2(args, "target")}\u3002` : `\u672C\u6765\u5C31\u6CA1\u8BA2\u9605 ${str2(args, "target")}\u3002`
5067
+ );
5068
+ }
5069
+ }
5070
+ ];
5071
+ return tools;
5072
+ }
5073
+ var BOARD_TOOL_NAMES = Object.freeze([
5074
+ "create_channel",
5075
+ "upsert_channel",
5076
+ "get_channels",
5077
+ "list_threads",
5078
+ "search_posts",
5079
+ "read_thread",
5080
+ "read_post",
5081
+ "subscribe",
5082
+ "unsubscribe",
5083
+ "post",
5084
+ "append"
5085
+ ]);
5086
+ var TASK_STATUSES = ["pending", "in_progress", "done", "blocked"];
5087
+ var AGENT_ID_PATTERN = /^[A-Za-z0-9_-]{1,64}$/;
5088
+ function err2(code, message, suggestion) {
5089
+ return {
5090
+ success: false,
5091
+ output: "",
5092
+ error: { code, message, ...suggestion ? { suggestion } : {} },
5093
+ duration: 0
5094
+ };
5095
+ }
5096
+ function ok3(output, start = Date.now()) {
5097
+ return { success: true, output, duration: Date.now() - start };
5098
+ }
5099
+ function str3(args, key) {
5100
+ const v = args[key];
5101
+ return typeof v === "string" ? v.trim() : "";
5102
+ }
5103
+ function spawnTeammate(team, manager) {
5104
+ return {
5105
+ name: "spawn_teammate",
5106
+ description: [
5107
+ "\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",
5108
+ "\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",
5109
+ "\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",
5110
+ "\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"
5111
+ ].join("\n"),
5112
+ parameters: {
5113
+ type: "object",
5114
+ properties: {
5115
+ agentId: {
5116
+ type: "string",
5117
+ 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"
5118
+ },
5119
+ goal: { type: "string", description: "\u8981\u5B83\u5B8C\u6210\u4EC0\u4E48\uFF0C\u5199\u5177\u4F53" },
5120
+ context: {
5121
+ type: "string",
5122
+ description: "\u5B8C\u6210\u8FD9\u4E2A\u4EFB\u52A1\u9700\u8981\u77E5\u9053\u7684\u80CC\u666F\uFF08\u5B83\u770B\u4E0D\u5230\u5F53\u524D\u5BF9\u8BDD\uFF09"
5123
+ }
5124
+ },
5125
+ required: ["agentId", "goal"]
5126
+ },
5127
+ exposure: ToolExposure.Deferred,
5128
+ supportsParallel: false,
5129
+ operation: "command",
5130
+ annotations: {
5131
+ readOnlyHint: false,
5132
+ destructiveHint: true,
5133
+ idempotentHint: false,
5134
+ openWorldHint: true
5135
+ },
5136
+ describeTarget: (args) => `${String(args["agentId"] ?? "")}: ${String(args["goal"] ?? "")}`,
5137
+ async execute(args, ctx) {
5138
+ const start = Date.now();
5139
+ const agentId = str3(args, "agentId");
5140
+ const goal = str3(args, "goal");
5141
+ const context = str3(args, "context");
5142
+ if (!AGENT_ID_PATTERN.test(agentId)) {
5143
+ return err2(
5144
+ 7201,
5145
+ `\u6210\u5458\u540D\u4E0D\u5408\u6CD5\uFF1A${agentId || "(\u7A7A)"}`,
5146
+ "\u53EA\u8BB8\u5B57\u6BCD\u3001\u6570\u5B57\u3001\u4E0B\u5212\u7EBF\u3001\u8FDE\u5B57\u7B26\uFF0C\u6700\u957F 64"
5147
+ );
5148
+ }
5149
+ if (!goal) return err2(7202, "\u7F3A\u5C11 goal");
5150
+ if (team.get(agentId)) {
5151
+ return err2(
5152
+ 7203,
5153
+ `\u5DF2\u7ECF\u6709\u4E00\u4E2A\u6210\u5458\u53EB ${agentId} \u4E86`,
5154
+ "\u6362\u4E00\u4E2A\u540D\u5B57\uFF0C\u6216\u8005\u76F4\u63A5 send_message \u7ED9\u5B83"
5155
+ );
5156
+ }
5157
+ const r = await manager.delegate(
5158
+ {
5159
+ tasks: [{ goal, ...context ? { context } : {}, agentId }],
5160
+ background: true,
5161
+ max_concurrent: 1
5162
+ },
5163
+ ctx.sessionId,
5164
+ ctx.signal
5165
+ );
5166
+ if (!r.success) return { ...err2(7204, r.output), duration: Date.now() - start };
5167
+ return ok3(
5168
+ [
5169
+ `\u5DF2\u6D3E\u51FA\u6210\u5458 ${agentId}\uFF08\u540E\u53F0\u4F5C\u4E1A ${r.jobId ?? "(\u65E0)"}\uFF09\u3002`,
5170
+ `\u8DDF\u5B83\u8BF4\u8BDD\uFF1Asend_message({ to: "${agentId}", text: "\u2026" })`,
5171
+ `\u770B\u5B83\u5728\u5E72\u4EC0\u4E48\uFF1Alist_agents\u3002\u6536\u6389\u5B83\uFF1Ainterrupt_agent({ agentId: "${agentId}" })`
5172
+ ].join("\n"),
5173
+ start
5174
+ );
5175
+ }
5176
+ };
5177
+ }
5178
+ function listAgents(team) {
5179
+ return {
5180
+ name: "list_agents",
5181
+ description: [
5182
+ "\u5217\u51FA\u56E2\u961F\u6210\u5458\u548C\u5B83\u4EEC\u7684\u72B6\u6001\u3002",
5183
+ "status \u662F running\uFF08\u6B63\u5728\u8DD1\uFF09/ finalized\uFF08\u8DD1\u5B8C\u4E86\uFF09/ failed\uFF08\u6302\u4E86\uFF09\u3002",
5184
+ "running \u7684\u6210\u5458\u80FD\u88AB send_message \u5F53\u8F6E\u6536\u5230\uFF1B\u6536\u5DE5\u7684\u6536\u4E0D\u5230\u3002",
5185
+ "",
5186
+ "\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",
5187
+ "\u52A0 --all \u53EF\u4EE5\u770B\u5230\u6240\u6709\u6D3B\u8DC3\u4F1A\u8BDD\u548C\u6210\u5458\u3002"
5188
+ ].join("\n"),
5189
+ parameters: {
5190
+ type: "object",
5191
+ properties: {
5192
+ all: {
5193
+ type: "boolean",
5194
+ 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"
5195
+ }
5196
+ },
5197
+ required: []
5198
+ },
5199
+ exposure: ToolExposure.Direct,
5200
+ supportsParallel: true,
5201
+ operation: "file_read",
5202
+ annotations: {
5203
+ readOnlyHint: true,
5204
+ destructiveHint: false,
5205
+ idempotentHint: true,
5206
+ openWorldHint: false
5207
+ },
5208
+ describeTarget: () => "\u56E2\u961F\u6210\u5458",
5209
+ async execute(args, ctx) {
5210
+ const showAll = args["all"] === true;
5211
+ const self = team.bySession(ctx.sessionId);
5212
+ const scopeParent = self?.parentSessionId ?? ctx.sessionId;
5213
+ const members = showAll ? team.list() : team.list().filter((m) => m.parentSessionId === scopeParent);
5214
+ const others = showAll ? team.sessionIds().filter((id) => id !== ctx.sessionId).map((id) => `- ${id} [\u4F1A\u8BDD] running \u2014 \u53E6\u4E00\u6BB5\u4E3B\u4F1A\u8BDD`) : [];
5215
+ if (members.length === 0 && others.length === 0) {
5216
+ return ok3(
5217
+ 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`
5218
+ );
5219
+ }
5220
+ const lines = members.map((m) => {
5221
+ const bits = [`- ${m.agentId}`, m.status];
5222
+ if (m.role) bits.push(`[${m.role}]`);
5223
+ if (m.activity) bits.push(`\u2014 ${m.activity}`);
5224
+ return bits.join(" ");
5225
+ });
5226
+ 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`;
5227
+ return ok3([head, ...lines, ...others].join("\n"));
5228
+ }
5229
+ };
5230
+ }
5231
+ function waitAgent(team) {
5232
+ return {
5233
+ name: "wait_agent",
5234
+ description: [
5235
+ "\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",
5236
+ "\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",
5237
+ "\u9002\u5408\uFF1A\u6D3E\u5B8C\u6D3B\u4E4B\u540E\u7B49\u5B83\u4EEC\u5E72\u6D3B\uFF0C\u800C\u4E0D\u662F\u53CD\u590D\u8F6E\u8BE2\u3002"
5238
+ ].join("\n"),
5239
+ parameters: {
5240
+ type: "object",
5241
+ properties: {
5242
+ timeoutSec: {
5243
+ type: "number",
5244
+ description: "\u6700\u591A\u7B49\u591A\u4E45\uFF08\u79D2\uFF09\uFF0C1\u20133600\uFF0C\u9ED8\u8BA4 30"
5245
+ }
5246
+ },
5247
+ required: []
5248
+ },
5249
+ exposure: ToolExposure.Deferred,
5250
+ supportsParallel: false,
5251
+ operation: "file_read",
5252
+ annotations: {
5253
+ readOnlyHint: true,
5254
+ destructiveHint: false,
5255
+ idempotentHint: false,
5256
+ openWorldHint: false
5257
+ },
5258
+ describeTarget: () => "\u7B49\u5F85\u56E2\u961F\u53D8\u5316",
5259
+ async execute(args, ctx) {
5260
+ const raw = typeof args["timeoutSec"] === "number" ? args["timeoutSec"] : 30;
5261
+ const sec = Math.min(Math.max(Math.floor(raw), 1), 3600);
5262
+ const changed = await team.waitForChange(sec * 1e3, ctx.signal);
5263
+ if (ctx.signal?.aborted) return err2(7205, "\u7B49\u5F85\u88AB\u4E2D\u6B62\u4E86");
5264
+ 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`);
5265
+ }
5266
+ };
5267
+ }
5268
+ function interruptAgent(team) {
5269
+ return {
5270
+ name: "interrupt_agent",
5271
+ description: [
5272
+ "\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",
5273
+ "\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"
5274
+ ].join("\n"),
5275
+ parameters: {
5276
+ type: "object",
5277
+ properties: {
5278
+ agentId: { type: "string", description: "\u8981\u6253\u65AD\u7684\u6210\u5458\u540D" }
5279
+ },
5280
+ required: ["agentId"]
5281
+ },
5282
+ exposure: ToolExposure.Deferred,
5283
+ supportsParallel: false,
5284
+ operation: "command",
5285
+ annotations: {
5286
+ readOnlyHint: false,
5287
+ destructiveHint: true,
5288
+ idempotentHint: false,
5289
+ openWorldHint: false
5290
+ },
5291
+ describeTarget: (args) => String(args["agentId"] ?? ""),
5292
+ async execute(args) {
5293
+ const agentId = str3(args, "agentId");
5294
+ if (!agentId) return err2(7206, "\u7F3A\u5C11 agentId");
5295
+ const member = team.get(agentId);
5296
+ if (!member) return err2(7207, `\u6CA1\u6709\u8FD9\u4E2A\u6210\u5458\uFF1A${agentId}`, "\u7528 list_agents \u770B\u5F53\u524D\u6709\u8C01");
5297
+ if (!team.interrupt(agentId)) {
5298
+ return err2(
5299
+ 7208,
5300
+ `${agentId} \u73B0\u5728\u6253\u4E0D\u65AD\uFF08${member.status}\uFF09`,
5301
+ 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"
5302
+ );
5303
+ }
5304
+ return ok3(`\u5DF2\u6253\u65AD ${agentId}\u3002`);
5305
+ }
5306
+ };
5307
+ }
5308
+ function taskCreate(team) {
5309
+ return {
5310
+ name: "team_task_create",
5311
+ description: [
5312
+ "\u5728\u5171\u4EAB\u4EFB\u52A1\u677F\u4E0A\u5EFA\u4E00\u6761\u4EFB\u52A1\u3002\u5168\u961F\u90FD\u770B\u5F97\u5230\u540C\u4E00\u4EFD\u3002",
5313
+ "dependsOn \u586B\u522B\u7684\u4EFB\u52A1 id\uFF08\u53EA\u80FD\u662F\u5DF2\u7ECF\u5B58\u5728\u7684\uFF09\u3002",
5314
+ "owner \u586B\u67D0\u4E2A\u6210\u5458\u540D\uFF0C\u8868\u793A\u8FD9\u6761\u5F52\u5B83\u3002"
5315
+ ].join("\n"),
5316
+ parameters: {
5317
+ type: "object",
5318
+ properties: {
5319
+ title: { type: "string", description: "\u4E00\u53E5\u8BDD\u8BF4\u660E\u8981\u505A\u4EC0\u4E48" },
5320
+ description: { type: "string", description: "\u7EC6\u8282" },
5321
+ owner: { type: "string", description: "\u5F52\u8C01\uFF08\u6210\u5458\u540D\uFF09" },
5322
+ dependsOn: {
5323
+ type: "array",
5324
+ items: { type: "string" },
5325
+ description: "\u4F9D\u8D56\u54EA\u4E9B\u4EFB\u52A1\u7684 id"
5326
+ }
5327
+ },
5328
+ required: ["title"]
5329
+ },
5330
+ exposure: ToolExposure.Deferred,
5331
+ supportsParallel: true,
5332
+ operation: "file_read",
5333
+ annotations: {
5334
+ readOnlyHint: false,
5335
+ destructiveHint: false,
5336
+ idempotentHint: false,
5337
+ openWorldHint: false
5338
+ },
5339
+ describeTarget: (args) => String(args["title"] ?? ""),
5340
+ async execute(args) {
5341
+ const title = str3(args, "title");
5342
+ if (!title) return err2(7301, "\u7F3A\u5C11 title");
5343
+ const dependsOn = Array.isArray(args["dependsOn"]) ? args["dependsOn"].map(String).filter(Boolean) : [];
5344
+ const description = str3(args, "description");
5345
+ const owner = str3(args, "owner");
5346
+ const r = team.tasks.create({
5347
+ title,
5348
+ ...description ? { description } : {},
5349
+ ...owner ? { owner } : {},
5350
+ ...dependsOn.length > 0 ? { dependsOn } : {}
5351
+ });
5352
+ if (!r.ok) return err2(7302, r.reason);
5353
+ return ok3(`\u5DF2\u5EFA\u4EFB\u52A1 ${r.task.id}\uFF08revision ${r.task.revision}\uFF09\uFF1A${r.task.title}`);
5354
+ }
5355
+ };
5356
+ }
5357
+ function taskList(team) {
5358
+ return {
5359
+ name: "team_task_list",
5360
+ description: "\u5217\u51FA\u5171\u4EAB\u4EFB\u52A1\u677F\u4E0A\u7684\u4EFB\u52A1\uFF0C\u53EF\u6309\u72B6\u6001\u6216 owner \u8FC7\u6EE4\u3002",
5361
+ parameters: {
5362
+ type: "object",
5363
+ properties: {
5364
+ status: { type: "string", enum: [...TASK_STATUSES], description: "\u53EA\u770B\u8FD9\u4E2A\u72B6\u6001" },
5365
+ owner: { type: "string", description: "\u53EA\u770B\u5F52\u8FD9\u4E2A\u6210\u5458\u7684" }
5366
+ },
5367
+ required: []
5368
+ },
5369
+ exposure: ToolExposure.Deferred,
5370
+ supportsParallel: true,
5371
+ operation: "file_read",
5372
+ annotations: {
5373
+ readOnlyHint: true,
5374
+ destructiveHint: false,
5375
+ idempotentHint: true,
5376
+ openWorldHint: false
5377
+ },
5378
+ describeTarget: () => "\u56E2\u961F\u4EFB\u52A1\u677F",
5379
+ async execute(args) {
5380
+ const status = str3(args, "status");
5381
+ if (status && !TASK_STATUSES.includes(status)) {
5382
+ return err2(7303, `\u4E0D\u8BA4\u8BC6\u7684\u72B6\u6001\uFF1A${status}`, `\u53EF\u7528\uFF1A${TASK_STATUSES.join(" / ")}`);
5383
+ }
5384
+ const owner = str3(args, "owner");
5385
+ const tasks = team.tasks.list({
5386
+ ...status ? { status } : {},
5387
+ ...owner ? { owner } : {}
5388
+ });
5389
+ if (tasks.length === 0) return ok3("\u677F\u5B50\u4E0A\u6CA1\u6709\u7B26\u5408\u6761\u4EF6\u7684\u4EFB\u52A1\u3002");
5390
+ const lines = tasks.map((t83) => {
5391
+ const bits = [`- ${t83.id}`, `[${t83.status}]`, t83.title, `rev ${t83.revision}`];
5392
+ if (t83.owner) bits.push(`\u2192 ${t83.owner}`);
5393
+ if (t83.dependsOn.length > 0) bits.push(`(\u7B49 ${t83.dependsOn.join(", ")})`);
5394
+ return bits.join(" ");
5395
+ });
5396
+ return ok3(`\u5171 ${tasks.length} \u6761\uFF1A
5397
+ ${lines.join("\n")}`);
5398
+ }
5399
+ };
5400
+ }
5401
+ function taskGet(team) {
5402
+ return {
5403
+ name: "team_task_get",
5404
+ description: "\u8BFB\u4E00\u6761\u4EFB\u52A1\u7684\u5B8C\u6574\u5185\u5BB9\uFF08\u542B revision \u2014\u2014 \u6539\u4E4B\u524D\u5148\u8BFB\u5B83\uFF09\u3002",
5405
+ parameters: {
5406
+ type: "object",
5407
+ properties: { id: { type: "string", description: "\u4EFB\u52A1 id" } },
5408
+ required: ["id"]
5409
+ },
5410
+ exposure: ToolExposure.Deferred,
5411
+ supportsParallel: true,
5412
+ operation: "file_read",
5413
+ annotations: {
5414
+ readOnlyHint: true,
5415
+ destructiveHint: false,
5416
+ idempotentHint: true,
5417
+ openWorldHint: false
5418
+ },
5419
+ describeTarget: (args) => String(args["id"] ?? ""),
5420
+ async execute(args) {
5421
+ const id = str3(args, "id");
5422
+ const t83 = team.tasks.get(id);
5423
+ if (!t83) return err2(7304, `\u6CA1\u6709\u8FD9\u4E2A\u4EFB\u52A1\uFF1A${id}`, "\u7528 team_task_list \u770B\u6709\u54EA\u4E9B");
5424
+ return ok3(
5425
+ [
5426
+ `${t83.id} [${t83.status}] revision ${t83.revision}`,
5427
+ `\u6807\u9898\uFF1A${t83.title}`,
5428
+ t83.description ? `\u7EC6\u8282\uFF1A${t83.description}` : "",
5429
+ t83.owner ? `\u5F52\u5C5E\uFF1A${t83.owner}` : "\u5F52\u5C5E\uFF1A\uFF08\u65E0\uFF09",
5430
+ t83.dependsOn.length > 0 ? `\u4F9D\u8D56\uFF1A${t83.dependsOn.join(", ")}` : "\u4F9D\u8D56\uFF1A\u65E0"
5431
+ ].filter(Boolean).join("\n")
5432
+ );
5433
+ }
5434
+ };
5435
+ }
5436
+ function taskUpdate(team) {
5437
+ return {
5438
+ name: "team_task_update",
5439
+ description: [
5440
+ "\u6539\u4E00\u6761\u4EFB\u52A1\u3002**\u6539\u4E4B\u524D\u5148 team_task_get \u62FF\u5230 revision\uFF0C\u539F\u6837\u586B\u8FDB expectedRevision**\u3002",
5441
+ "\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",
5442
+ "\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"
5443
+ ].join("\n"),
5444
+ parameters: {
5445
+ type: "object",
5446
+ properties: {
5447
+ id: { type: "string", description: "\u4EFB\u52A1 id" },
5448
+ expectedRevision: {
5449
+ type: "number",
5450
+ description: "\u4F60\u4E0A\u6B21\u8BFB\u5230\u7684 revision\u3002\u5BF9\u4E0D\u4E0A\u5C31\u62D2\u7EDD\u6574\u7B14\u5199\u5165"
5451
+ },
5452
+ title: { type: "string" },
5453
+ description: { type: "string" },
5454
+ status: { type: "string", enum: [...TASK_STATUSES] },
5455
+ owner: { type: "string", description: "\u6539\u6210\u5F52\u8C01" }
5456
+ },
5457
+ required: ["id"]
5458
+ },
5459
+ exposure: ToolExposure.Deferred,
5460
+ supportsParallel: false,
5461
+ operation: "file_read",
5462
+ annotations: {
5463
+ readOnlyHint: false,
5464
+ destructiveHint: false,
5465
+ idempotentHint: false,
5466
+ openWorldHint: false
5467
+ },
5468
+ describeTarget: (args) => String(args["id"] ?? ""),
5469
+ async execute(args) {
5470
+ const id = str3(args, "id");
5471
+ if (!id) return err2(7305, "\u7F3A\u5C11 id");
5472
+ const status = str3(args, "status");
5473
+ if (status && !TASK_STATUSES.includes(status)) {
5474
+ return err2(7306, `\u4E0D\u8BA4\u8BC6\u7684\u72B6\u6001\uFF1A${status}`, `\u53EF\u7528\uFF1A${TASK_STATUSES.join(" / ")}`);
5475
+ }
5476
+ const patch = {};
5477
+ const title = str3(args, "title");
5478
+ const description = str3(args, "description");
5479
+ const owner = str3(args, "owner");
5480
+ if (title) patch.title = title;
5481
+ if (description) patch.description = description;
5482
+ if (status) patch.status = status;
5483
+ if (owner) patch.owner = owner;
5484
+ if (Object.keys(patch).length === 0) return err2(7307, "\u4E00\u4E2A\u5B57\u6BB5\u90FD\u6CA1\u7ED9\uFF0C\u6CA1\u4EC0\u4E48\u53EF\u6539\u7684");
5485
+ const expected = typeof args["expectedRevision"] === "number" ? args["expectedRevision"] : void 0;
5486
+ const r = team.tasks.update(id, patch, expected);
5487
+ if (!r.ok) return err2(7308, r.reason);
5488
+ return ok3(`\u5DF2\u66F4\u65B0 ${r.task.id}\uFF08revision ${r.task.revision}\uFF0C\u72B6\u6001 ${r.task.status}\uFF09\u3002`);
5489
+ }
5490
+ };
5491
+ }
5492
+ function followupTask(team, manager) {
5493
+ return {
5494
+ name: "followup_task",
5495
+ description: [
5496
+ "\u7ED9\u4E00\u4E2A**\u5DF2\u7ECF\u6536\u5DE5**\u7684\u6210\u5458\u518D\u6D3E\u4E00\u53E5\u8BDD\uFF0C\u8BA9\u5B83\u5E26\u7740\u4E0A\u4E00\u6B21\u7684\u5168\u90E8\u4E0A\u4E0B\u6587\u518D\u8DD1\u4E00\u8F6E\u3002",
5497
+ "\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",
5498
+ "\u5BF9\u65B9\u5DF2\u7ECF\u6536\u5DE5\u4E86\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",
5499
+ "\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"
5500
+ ].join("\n"),
4130
5501
  parameters: {
4131
5502
  type: "object",
4132
5503
  properties: {
4133
- action: {
4134
- type: "string",
4135
- description: "\u505A\u54EA\u4E00\u4EF6",
4136
- enum: ["list", "create", "update"]
4137
- },
4138
- note: {
4139
- type: "string",
4140
- description: "\u4E3A\u4EC0\u4E48\u5EFA\u8FD9\u6761\uFF0C\u4E00\u53E5\u8BDD\u3002create / update \u5FC5\u586B\uFF0C\u4F1A\u5370\u5728\u7528\u6237\u770B\u5230\u7684\u5361\u7247\u4E0A\uFF1B\u8BF4\u4E0D\u51FA\u771F\u5B9E\u7406\u7531\u5C31\u522B\u63D0\u8FD9\u4E2A\u5EFA\u8BAE"
4141
- },
4142
- id: { type: "string", description: "\u6539\u54EA\u4E00\u6761\u3002update \u5FC5\u586B\uFF0C\u4ECE action=list \u91CC\u62FF" },
4143
- name: { type: "string", description: "\u4EFB\u52A1\u540D\uFF0C\u7528\u6237\u5728\u5217\u8868\u91CC\u770B\u5230\u7684\u5C31\u662F\u5B83" },
4144
- prompt: {
4145
- type: "string",
4146
- description: "\u5230\u70B9\u4E86\u53D1\u7ED9 agent \u7684\u63D0\u793A\u8BCD\u3002\u65E0\u4EBA\u503C\u5B88\uFF0C\u6240\u4EE5\u8981\u5199\u6210\u4E00\u53E5\u81EA\u8DB3\u7684\u6307\u4EE4\uFF1B\u8BA9\u5B83\u628A\u7ED3\u679C\u8FFD\u52A0\u5230\u4E00\u4EFD markdown \u6587\u4EF6\u91CC\u901A\u5E38\u6BD4\u4EC0\u4E48\u90FD\u4E0D\u843D\u5730\u6709\u7528"
4147
- },
4148
- trigger: {
4149
- type: "object",
4150
- description: '\u4EC0\u4E48\u65F6\u5019\u8DD1\u3002\u4E09\u6863\uFF1A{kind:"cron",cycle:"daily",at:"09:00"} / {kind:"cron",cycle:"weekly",at:"09:00",weekdays:[1,3,5]} / {kind:"cron",cycle:"monthly",at:"09:00",days:[1,15]} / {kind:"interval",everyMinutes:30} / {kind:"once",date:"2026-12-31",at:"23:00"}\u3002cron \u6863\u4E00\u5929\u8DD1\u51E0\u6B21\u5C31\u628A\u5176\u4F59\u65F6\u523B\u653E\u8FDB alsoAt\uFF1A{kind:"cron",cycle:"daily",at:"09:00",alsoAt:["14:00","18:00"]}\u3002everyMinutes \u662F 5\u20131440 \u7684\u6574\u6570\uFF0C\u6BCF\u5929\u4ECE 0 \u70B9\u8D77\u7B97\u3002\u6CA1\u6709\u5B8C\u6574 cron \u8868\u8FBE\u5F0F',
4151
- properties: {
4152
- kind: { type: "string", enum: ["cron", "interval", "once"] },
4153
- cycle: { type: "string", enum: ["daily", "weekly", "monthly"] },
4154
- at: { type: "string", description: "HH:mm\uFF0C24 \u5C0F\u65F6\u5236\uFF0C\u672C\u673A\u65F6\u533A" },
4155
- alsoAt: {
4156
- type: "array",
4157
- items: { type: "string" },
4158
- description: "cron \u6863\u5728 at \u4E4B\u5916\u7684\u5176\u4F59\u65F6\u523B\uFF08HH:mm\uFF09"
4159
- },
4160
- weekdays: { type: "array", items: { type: "number" }, description: "0=\u5468\u65E5 \u2026 6=\u5468\u516D" },
4161
- days: { type: "array", items: { type: "number" }, description: "\u51E0\u53F7\uFF0C1\u201331" },
4162
- everyMinutes: { type: "number" },
4163
- date: { type: "string", description: "YYYY-MM-DD" }
4164
- },
4165
- required: ["kind"]
4166
- },
4167
- workDir: {
4168
- type: "string",
4169
- description: "\u5728\u54EA\u4E2A\u76EE\u5F55\u91CC\u8DD1\u3002\u7EDD\u5BF9\u8DEF\u5F84\u3002\u4E0D\u7ED9\u5C31\u843D\u5728 ~/.epoch/automation/<id>/"
4170
- },
4171
- permission: {
4172
- type: "string",
4173
- description: "\u6743\u9650\u6863\u3002\u4E0D\u7ED9\u5C31\u662F auto\uFF08**\u65B0\u5EFA\u4EFB\u52A1\u7684\u7F3A\u7701**\uFF0C2026-10-27 \u8D77\uFF1A\u5B9A\u65F6\u4EFB\u52A1\u6CA1\u4EBA\u53EF\u95EE\uFF0C\u4F4E\u6863\u5728\u8FD9\u91CC\u7B49\u4E8E\u300C\u5230\u70B9\u5FC5\u7136\u5931\u8D25\u300D\uFF09\u3002auto=\u5B8C\u5168\u8BBF\u95EE\uFF08\u4E0D\u518D\u786E\u8BA4\uFF0C\u53EA\u5269\u707E\u96BE\u7EA7\u4F1A\u88AB\u62E6\u4E0B\uFF09\uFF1BacceptEdits=\u8BF7\u6C42\u6279\u51C6\uFF1Bdefault=\u9010\u6761\u786E\u8BA4\uFF1Bplan=\u53EA\u8BFB\uFF08\u8BFB\u4E00\u904D\u5199\u4EFD\u62A5\u544A\u7684\u4EFB\u52A1\u7528\u5B83\uFF0C\u5929\u7136\u96F6\u6388\u6743\u9762\uFF09\u3002**\u53EA\u6709\u5728\u7528\u6237\u660E\u786E\u8BF4\u4E86\u8981\u7A84\u4E00\u6863\u65F6\u624D\u964D**",
4174
- enum: ["plan", "default", "acceptEdits", "auto"]
4175
- },
4176
- allowTools: {
4177
- type: "array",
4178
- items: { type: "string" },
4179
- description: "\u6574\u4E2A\u5DE5\u5177\u90FD\u4E0D\u7528\u95EE\u3002\u8303\u56F4\u6700\u7C97\uFF0C\u80FD\u7528 allowRules \u5C31\u522B\u7528\u5B83"
4180
- },
4181
- allowOperations: {
4182
- type: "array",
4183
- items: { type: "string" },
4184
- description: "\u6574\u7C7B\u64CD\u4F5C\u90FD\u4E0D\u7528\u95EE\uFF1Afile_read / file_write / command / network / code_exec"
4185
- },
4186
- allowRules: {
4187
- type: "array",
4188
- items: { type: "string" },
4189
- 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
- },
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" }
5504
+ agentId: { type: "string", description: "\u6210\u5458\u540D\uFF08list_agents \u91CC\u6709\uFF09" },
5505
+ message: { type: "string", description: "\u8FD9\u4E00\u8F6E\u8981\u5B83\u505A\u4EC0\u4E48" }
4194
5506
  },
4195
- required: ["action"]
5507
+ required: ["agentId", "message"]
4196
5508
  },
4197
- exposure: ToolExposure.Direct,
5509
+ exposure: ToolExposure.Deferred,
4198
5510
  supportsParallel: false,
5511
+ operation: "command",
4199
5512
  annotations: {
4200
5513
  readOnlyHint: false,
4201
5514
  destructiveHint: true,
4202
5515
  idempotentHint: false,
4203
- openWorldHint: false
5516
+ openWorldHint: true
4204
5517
  },
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
- );
4218
- }
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
4228
- );
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
4236
- );
4237
- }
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
4245
- );
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);
5518
+ describeTarget: (args) => `${String(args["agentId"] ?? "")}: ${String(args["message"] ?? "")}`,
5519
+ async execute(args, ctx) {
5520
+ const start = Date.now();
5521
+ const agentId = str3(args, "agentId");
5522
+ const message = str3(args, "message");
5523
+ if (!agentId) return err2(7205, "\u7F3A\u5C11 agentId");
5524
+ if (!message) return err2(7206, "\u7F3A\u5C11 message");
5525
+ const member = team.get(agentId);
5526
+ if (!member) {
5527
+ return err2(7207, `\u6CA1\u6709\u8FD9\u4E2A\u6210\u5458\uFF1A${agentId}`, "\u7528 list_agents \u770B\u5F53\u524D\u6709\u8C01");
4255
5528
  }
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
5529
+ if (member.status === "running") {
5530
+ return err2(
5531
+ 7208,
5532
+ `${agentId} \u6B63\u5728\u8DD1\uFF0C\u4E0D\u9700\u8981\u5524\u9192`,
5533
+ "\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"
4262
5534
  );
4263
5535
  }
4264
- return say4(summarizeSaved(draft, def, saved.registration, current), true, startedAt);
5536
+ const r = await manager.delegate(
5537
+ {
5538
+ tasks: [
5539
+ {
5540
+ goal: message,
5541
+ agentId,
5542
+ resumeSessionId: member.sessionId,
5543
+ ...member.role ? { role: member.role } : {}
5544
+ }
5545
+ ],
5546
+ background: true,
5547
+ max_concurrent: 1
5548
+ },
5549
+ ctx.sessionId,
5550
+ ctx.signal
5551
+ );
5552
+ if (!r.success) return { ...err2(7209, r.output), duration: Date.now() - start };
5553
+ return ok3(
5554
+ [
5555
+ `\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`,
5556
+ `\u770B\u5B83\u5E72\u5230\u54EA\u513F\u4E86\uFF1Atask_output ${r.jobId ?? ""} \u6216 list_agents`
5557
+ ].join("\n"),
5558
+ start
5559
+ );
4265
5560
  }
4266
5561
  };
4267
5562
  }
5563
+ function createTeamTools(team, manager) {
5564
+ return [
5565
+ listAgents(team),
5566
+ spawnTeammate(team, manager),
5567
+ waitAgent(team),
5568
+ interruptAgent(team),
5569
+ followupTask(team, manager),
5570
+ taskCreate(team),
5571
+ taskList(team),
5572
+ taskGet(team),
5573
+ taskUpdate(team)
5574
+ ];
5575
+ }
5576
+ var TEAM_TOOL_NAMES = Object.freeze([
5577
+ "spawn_teammate",
5578
+ "list_agents",
5579
+ "wait_agent",
5580
+ "interrupt_agent",
5581
+ "followup_task",
5582
+ "team_task_create",
5583
+ "team_task_list",
5584
+ "team_task_get",
5585
+ "team_task_update"
5586
+ ]);
4268
5587
  // src/session/authorization.ts
4269
5588
  function lineageOf(db, sessionId) {
4270
5589
  const rows = db.prepare(
@@ -4749,8 +6068,8 @@ function createSessionListTool(deps) {
4749
6068
  output: render(out, scopeNote(allWorkspaces, archived)),
4750
6069
  duration: Date.now() - start
4751
6070
  });
4752
- } catch (err) {
4753
- return Promise.resolve(fail3(err instanceof Error ? err.message : String(err), start, 8014));
6071
+ } catch (err3) {
6072
+ return Promise.resolve(fail3(err3 instanceof Error ? err3.message : String(err3), start, 8014));
4754
6073
  }
4755
6074
  }
4756
6075
  };
@@ -4912,8 +6231,8 @@ before / after \u5404\u9ED8\u8BA4 ${DEFAULT_WINDOW}\u3001\u4E0A\u9650 ${MAX_WIND
4912
6231
  output: renderWindow(out, sessionId, sessionId === ctx.sessionId),
4913
6232
  duration: Date.now() - start
4914
6233
  });
4915
- } catch (err) {
4916
- return Promise.resolve(fail4(err instanceof Error ? err.message : String(err), start, 8011));
6234
+ } catch (err3) {
6235
+ return Promise.resolve(fail4(err3 instanceof Error ? err3.message : String(err3), start, 8011));
4917
6236
  }
4918
6237
  }
4919
6238
  };
@@ -5019,8 +6338,8 @@ function createSessionTraceTool(deps) {
5019
6338
  output: renderTrace(trace, ctx.sessionId),
5020
6339
  duration: Date.now() - start
5021
6340
  });
5022
- } catch (err) {
5023
- return Promise.resolve(fail4(err instanceof Error ? err.message : String(err), start, 8013));
6341
+ } catch (err3) {
6342
+ return Promise.resolve(fail4(err3 instanceof Error ? err3.message : String(err3), start, 8013));
5024
6343
  }
5025
6344
  }
5026
6345
  };
@@ -5143,10 +6462,10 @@ function createSessionSearchTool(deps) {
5143
6462
  ].join("\n"),
5144
6463
  duration: Date.now() - start
5145
6464
  });
5146
- } catch (err) {
6465
+ } catch (err3) {
5147
6466
  return Promise.resolve(
5148
6467
  fail5(
5149
- err instanceof Error ? err.message : String(err),
6468
+ err3 instanceof Error ? err3.message : String(err3),
5150
6469
  start,
5151
6470
  8002,
5152
6471
  "Retry with different words"
@@ -5239,10 +6558,10 @@ function createSessionMessagesSearchTool(deps) {
5239
6558
  ].join("\n"),
5240
6559
  duration: Date.now() - start
5241
6560
  });
5242
- } catch (err) {
6561
+ } catch (err3) {
5243
6562
  return Promise.resolve(
5244
6563
  fail5(
5245
- err instanceof Error ? err.message : String(err),
6564
+ err3 instanceof Error ? err3.message : String(err3),
5246
6565
  start,
5247
6566
  8006,
5248
6567
  "Retry with different words"
@@ -5341,10 +6660,10 @@ function parseFrontmatter(raw) {
5341
6660
  if (!split) return { error: t("frontmatter.missing") };
5342
6661
  try {
5343
6662
  return { data: load(split.frontmatter), body: split.body };
5344
- } catch (err) {
6663
+ } catch (err3) {
5345
6664
  return {
5346
6665
  error: t("frontmatter.bad_yaml", {
5347
- reason: err instanceof Error ? err.message : String(err)
6666
+ reason: err3 instanceof Error ? err3.message : String(err3)
5348
6667
  })
5349
6668
  };
5350
6669
  }
@@ -5457,10 +6776,10 @@ function fail7(message, start, code, suggestion) {
5457
6776
  function done(output, start) {
5458
6777
  return { success: true, output, duration: Date.now() - start };
5459
6778
  }
5460
- function fromThrow(err, start, suggestion) {
5461
- return fail7(err instanceof Error ? err.message : String(err), start, 3102, suggestion);
6779
+ function fromThrow(err3, start, suggestion) {
6780
+ return fail7(err3 instanceof Error ? err3.message : String(err3), start, 3102, suggestion);
5462
6781
  }
5463
- function str2(args, key) {
6782
+ function str4(args, key) {
5464
6783
  const raw = args[key];
5465
6784
  return typeof raw === "string" ? raw : "";
5466
6785
  }
@@ -5510,9 +6829,9 @@ function createTool(deps) {
5510
6829
  describeTarget: (args) => `${SKILL_CREATE_TOOL}:${String(args["name"] ?? "")}`,
5511
6830
  async execute(args) {
5512
6831
  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";
6832
+ const name = str4(args, "name").trim();
6833
+ const content = str4(args, "content");
6834
+ const category = str4(args, "category").trim() || "general";
5516
6835
  if (!WRITABLE_SKILL_NAME.test(name)) {
5517
6836
  return fail7(`invalid skill name: ${JSON.stringify(name)}`, start, 3101, WRITABLE_HINT);
5518
6837
  }
@@ -5524,8 +6843,8 @@ function createTool(deps) {
5524
6843
  try {
5525
6844
  const path = await deps.skills.create(name, content, category);
5526
6845
  return done(`created skill "${name}" at ${path}`, start);
5527
- } catch (err) {
5528
- return fromThrow(err, start);
6846
+ } catch (err3) {
6847
+ return fromThrow(err3, start);
5529
6848
  }
5530
6849
  }
5531
6850
  };
@@ -5549,8 +6868,8 @@ function editTool(deps) {
5549
6868
  describeTarget: (args) => `${SKILL_EDIT_TOOL}:${String(args["name"] ?? "")}`,
5550
6869
  async execute(args) {
5551
6870
  const start = Date.now();
5552
- const name = str2(args, "name").trim();
5553
- const content = str2(args, "content");
6871
+ const name = str4(args, "name").trim();
6872
+ const content = str4(args, "content");
5554
6873
  if (!name) {
5555
6874
  return fail7("name must not be empty", start, 3101, describeAvailableSkills(deps.skills));
5556
6875
  }
@@ -5559,8 +6878,8 @@ function editTool(deps) {
5559
6878
  try {
5560
6879
  await deps.skills.edit(name, content);
5561
6880
  return done(`rewrote SKILL.md of skill "${name}"`, start);
5562
- } catch (err) {
5563
- return fromThrow(err, start, describeAvailableSkills(deps.skills));
6881
+ } catch (err3) {
6882
+ return fromThrow(err3, start, describeAvailableSkills(deps.skills));
5564
6883
  }
5565
6884
  }
5566
6885
  };
@@ -5589,9 +6908,9 @@ function patchTool(deps) {
5589
6908
  describeTarget: (args) => `${SKILL_PATCH_TOOL}:${String(args["name"] ?? "")}/${String(args["file_path"] ?? "SKILL.md")}`,
5590
6909
  async execute(args) {
5591
6910
  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();
6911
+ const name = str4(args, "name").trim();
6912
+ const oldString = str4(args, "old_string");
6913
+ const filePath = str4(args, "file_path").trim();
5595
6914
  if (!name) {
5596
6915
  return fail7("name must not be empty", start, 3101, describeAvailableSkills(deps.skills));
5597
6916
  }
@@ -5602,12 +6921,12 @@ function patchTool(deps) {
5602
6921
  await deps.skills.patch(
5603
6922
  name,
5604
6923
  oldString,
5605
- str2(args, "new_string"),
6924
+ str4(args, "new_string"),
5606
6925
  filePath === "" ? void 0 : filePath
5607
6926
  );
5608
6927
  return done(`patched ${filePath || "SKILL.md"} of skill "${name}"`, start);
5609
- } catch (err) {
5610
- return fromThrow(err, start, describeAvailableSkills(deps.skills));
6928
+ } catch (err3) {
6929
+ return fromThrow(err3, start, describeAvailableSkills(deps.skills));
5611
6930
  }
5612
6931
  }
5613
6932
  };
@@ -5635,17 +6954,17 @@ function writeFileTool(deps) {
5635
6954
  describeTarget: (args) => `${SKILL_WRITE_FILE_TOOL}:${String(args["name"] ?? "")}/${String(args["file_path"] ?? "")}`,
5636
6955
  async execute(args) {
5637
6956
  const start = Date.now();
5638
- const name = str2(args, "name").trim();
5639
- const filePath = str2(args, "file_path").trim();
6957
+ const name = str4(args, "name").trim();
6958
+ const filePath = str4(args, "file_path").trim();
5640
6959
  if (!name) {
5641
6960
  return fail7("name must not be empty", start, 3101, describeAvailableSkills(deps.skills));
5642
6961
  }
5643
6962
  if (!filePath) return fail7("file_path must not be empty", start, 3101);
5644
6963
  try {
5645
- await deps.skills.writeFile(name, filePath, str2(args, "content"));
6964
+ await deps.skills.writeFile(name, filePath, str4(args, "content"));
5646
6965
  return done(`wrote ${filePath} into skill "${name}"`, start);
5647
- } catch (err) {
5648
- return fromThrow(err, start, describeAvailableSkills(deps.skills));
6966
+ } catch (err3) {
6967
+ return fromThrow(err3, start, describeAvailableSkills(deps.skills));
5649
6968
  }
5650
6969
  }
5651
6970
  };
@@ -5765,8 +7084,8 @@ var MIGRATIONS = [
5765
7084
  var TrackerDB = class {
5766
7085
  db;
5767
7086
  path;
5768
- constructor(dbPath) {
5769
- this.path = dbPath;
7087
+ constructor(dbPath2) {
7088
+ this.path = dbPath2;
5770
7089
  this.db = openDatabase(this.path);
5771
7090
  migrate(this.db, NS, MIGRATIONS);
5772
7091
  }
@@ -5918,13 +7237,13 @@ function createTodoTool(db) {
5918
7237
  output: formatTodoList(todos, pendingCount),
5919
7238
  duration: Date.now() - startTime
5920
7239
  };
5921
- } catch (err) {
7240
+ } catch (err3) {
5922
7241
  return {
5923
7242
  success: false,
5924
7243
  output: "TODO \u5217\u8868\u5199\u5165\u5931\u8D25",
5925
7244
  error: {
5926
7245
  code: 1,
5927
- message: err instanceof Error ? err.message : String(err)
7246
+ message: err3 instanceof Error ? err3.message : String(err3)
5928
7247
  },
5929
7248
  duration: Date.now() - startTime
5930
7249
  };
@@ -5932,6 +7251,260 @@ function createTodoTool(db) {
5932
7251
  }
5933
7252
  };
5934
7253
  }
7254
+ var MAX_POST_CHARS = 2e4;
7255
+ var CHANNEL_PATTERN = /^[A-Za-z0-9_.-]{1,64}$/;
7256
+ var MIGRATIONS2 = [
7257
+ {
7258
+ id: "board-initial",
7259
+ version: 1,
7260
+ description: "\u8BA8\u8BBA\u677F\uFF1A\u9891\u9053 / \u7EBF\u7A0B / \u5E16\u5B50 / \u8BA2\u9605",
7261
+ up: (db) => {
7262
+ db.exec(`
7263
+ CREATE TABLE IF NOT EXISTS board_channels (
7264
+ id TEXT PRIMARY KEY,
7265
+ name TEXT NOT NULL UNIQUE,
7266
+ description TEXT,
7267
+ created_by TEXT NOT NULL,
7268
+ created_at INTEGER NOT NULL
7269
+ );
7270
+ CREATE TABLE IF NOT EXISTS board_threads (
7271
+ id TEXT PRIMARY KEY,
7272
+ channel TEXT NOT NULL,
7273
+ title TEXT NOT NULL,
7274
+ created_by TEXT NOT NULL,
7275
+ created_at INTEGER NOT NULL,
7276
+ last_post_at INTEGER NOT NULL
7277
+ );
7278
+ CREATE INDEX IF NOT EXISTS board_threads_channel ON board_threads(channel, last_post_at DESC);
7279
+ CREATE TABLE IF NOT EXISTS board_posts (
7280
+ seq INTEGER PRIMARY KEY AUTOINCREMENT,
7281
+ id TEXT NOT NULL UNIQUE,
7282
+ thread_id TEXT NOT NULL,
7283
+ author TEXT NOT NULL,
7284
+ text TEXT NOT NULL,
7285
+ created_at INTEGER NOT NULL
7286
+ );
7287
+ CREATE INDEX IF NOT EXISTS board_posts_thread ON board_posts(thread_id, seq);
7288
+ CREATE TABLE IF NOT EXISTS board_subscriptions (
7289
+ agent TEXT NOT NULL,
7290
+ target TEXT NOT NULL,
7291
+ last_seen_seq INTEGER NOT NULL DEFAULT 0,
7292
+ PRIMARY KEY (agent, target)
7293
+ );
7294
+ `);
7295
+ }
7296
+ }
7297
+ ];
7298
+ function targetKey(t83) {
7299
+ return t83.kind === "channel" ? `channel:${t83.name}` : `thread:${t83.id}`;
7300
+ }
7301
+ var BoardStore = class {
7302
+ path;
7303
+ db;
7304
+ constructor(homeDir) {
7305
+ this.path = dbPath(homeDir);
7306
+ this.db = openDatabase(this.path);
7307
+ migrate(this.db, "board", MIGRATIONS2);
7308
+ }
7309
+ close() {
7310
+ releaseDatabase(this.path);
7311
+ }
7312
+ createChannel(args) {
7313
+ if (!CHANNEL_PATTERN.test(args.name)) {
7314
+ throw new Error(`\u9891\u9053\u540D\u4E0D\u5408\u6CD5\uFF1A${args.name}\uFF08\u53EA\u8BB8\u5B57\u6BCD\u6570\u5B57 _ . -\uFF0C\u6700\u957F 64\uFF09`);
7315
+ }
7316
+ const existing = this.channel(args.name);
7317
+ if (existing) return existing;
7318
+ const row = {
7319
+ id: `ch-${randomUUID().slice(0, 8)}`,
7320
+ name: args.name,
7321
+ ...args.description ? { description: args.description } : {},
7322
+ createdBy: args.by,
7323
+ createdAt: Date.now()
7324
+ };
7325
+ this.db.prepare(
7326
+ `INSERT INTO board_channels (id, name, description, created_by, created_at)
7327
+ VALUES (?, ?, ?, ?, ?)`
7328
+ ).run(row.id, row.name, row.description ?? null, row.createdBy, row.createdAt);
7329
+ return row;
7330
+ }
7331
+ upsertChannel(args) {
7332
+ const existing = this.channel(args.name);
7333
+ if (!existing) return this.createChannel(args);
7334
+ this.db.prepare(`UPDATE board_channels SET description = ? WHERE name = ?`).run(args.description, args.name);
7335
+ return { ...existing, description: args.description };
7336
+ }
7337
+ channel(name) {
7338
+ const row = this.db.prepare(
7339
+ `SELECT id, name, description, created_by, created_at FROM board_channels WHERE name = ?`
7340
+ ).get(name);
7341
+ return row ? toChannel(row) : void 0;
7342
+ }
7343
+ listChannels() {
7344
+ const rows = this.db.prepare(
7345
+ `SELECT id, name, description, created_by, created_at FROM board_channels ORDER BY name`
7346
+ ).all();
7347
+ return rows.map(toChannel);
7348
+ }
7349
+ listThreads(channel, limit = 20) {
7350
+ const rows = this.db.prepare(
7351
+ `SELECT t.id, t.channel, t.title, t.created_by, t.created_at, t.last_post_at,
7352
+ (SELECT COUNT(*) FROM board_posts p WHERE p.thread_id = t.id) AS posts
7353
+ FROM board_threads t WHERE t.channel = ? ORDER BY t.last_post_at DESC LIMIT ?`
7354
+ ).all(channel, limit);
7355
+ return rows.map((r) => ({
7356
+ id: r.id,
7357
+ channel: r.channel,
7358
+ title: r.title,
7359
+ createdBy: r.created_by,
7360
+ createdAt: r.created_at,
7361
+ lastPostAt: r.last_post_at,
7362
+ postCount: r.posts
7363
+ }));
7364
+ }
7365
+ post(args) {
7366
+ return this.write({ ...args, notify: true });
7367
+ }
7368
+ append(args) {
7369
+ return this.write({ ...args, notify: false });
7370
+ }
7371
+ write(args) {
7372
+ const text = clip(args.text);
7373
+ const now = Date.now();
7374
+ const run = this.db.transaction(() => {
7375
+ let threadId;
7376
+ if (args.target.kind === "thread") {
7377
+ const exists2 = this.db.prepare(`SELECT id FROM board_threads WHERE id = ?`).get(args.target.id);
7378
+ if (!exists2) throw new Error(`\u6CA1\u6709\u8FD9\u4E2A\u7EBF\u7A0B\uFF1A${args.target.id}`);
7379
+ threadId = args.target.id;
7380
+ } else {
7381
+ const ch = this.channel(args.target.name);
7382
+ if (!ch) throw new Error(`\u6CA1\u6709\u8FD9\u4E2A\u9891\u9053\uFF1A${args.target.name}`);
7383
+ threadId = `th-${randomUUID().slice(0, 8)}`;
7384
+ this.db.prepare(
7385
+ `INSERT INTO board_threads (id, channel, title, created_by, created_at, last_post_at)
7386
+ VALUES (?, ?, ?, ?, ?, ?)`
7387
+ ).run(threadId, ch.name, firstLine(text), args.author, now, now);
7388
+ }
7389
+ const id = `po-${randomUUID().slice(0, 8)}`;
7390
+ const info = this.db.prepare(
7391
+ `INSERT INTO board_posts (id, thread_id, author, text, created_at) VALUES (?, ?, ?, ?, ?)`
7392
+ ).run(id, threadId, args.author, text, now);
7393
+ const seq = Number(info.lastInsertRowid);
7394
+ this.db.prepare(`UPDATE board_threads SET last_post_at = ? WHERE id = ?`).run(now, threadId);
7395
+ if (args.notify) {
7396
+ this.subscribe(args.author, { kind: "thread", id: threadId }, seq);
7397
+ }
7398
+ return {
7399
+ post: { id, threadId, author: args.author, text, createdAt: now, seq },
7400
+ threadId
7401
+ };
7402
+ });
7403
+ return run();
7404
+ }
7405
+ readThread(threadId, limit = 50) {
7406
+ const rows = this.db.prepare(
7407
+ `SELECT seq, id, thread_id, author, text, created_at FROM board_posts
7408
+ WHERE thread_id = ? ORDER BY seq ASC LIMIT ?`
7409
+ ).all(threadId, limit);
7410
+ return rows.map(toPost);
7411
+ }
7412
+ readPost(id) {
7413
+ const row = this.db.prepare(`SELECT seq, id, thread_id, author, text, created_at FROM board_posts WHERE id = ?`).get(id);
7414
+ return row ? toPost(row) : void 0;
7415
+ }
7416
+ searchPosts(query, channel, limit = 20) {
7417
+ const like = `%${query}%`;
7418
+ const rows = channel ? this.db.prepare(
7419
+ `SELECT p.seq, p.id, p.thread_id, p.author, p.text, p.created_at
7420
+ FROM board_posts p JOIN board_threads t ON t.id = p.thread_id
7421
+ WHERE t.channel = ? AND p.text LIKE ? ORDER BY p.seq DESC LIMIT ?`
7422
+ ).all(channel, like, limit) : this.db.prepare(
7423
+ `SELECT seq, id, thread_id, author, text, created_at FROM board_posts
7424
+ WHERE text LIKE ? ORDER BY seq DESC LIMIT ?`
7425
+ ).all(like, limit);
7426
+ return rows.map(toPost);
7427
+ }
7428
+ subscribe(agent, target, seenSeq) {
7429
+ const key = targetKey(target);
7430
+ const initial = seenSeq ?? this.maxSeq();
7431
+ this.db.prepare(
7432
+ `INSERT INTO board_subscriptions (agent, target, last_seen_seq) VALUES (?, ?, ?)
7433
+ ON CONFLICT(agent, target) DO UPDATE SET
7434
+ last_seen_seq = MAX(board_subscriptions.last_seen_seq, excluded.last_seen_seq)`
7435
+ ).run(agent, key, initial);
7436
+ }
7437
+ maxSeq() {
7438
+ const row = this.db.prepare(`SELECT COALESCE(MAX(seq), 0) AS n FROM board_posts`).get();
7439
+ return row.n;
7440
+ }
7441
+ unsubscribe(agent, target) {
7442
+ const info = this.db.prepare(`DELETE FROM board_subscriptions WHERE agent = ? AND target = ?`).run(agent, targetKey(target));
7443
+ return info.changes > 0;
7444
+ }
7445
+ pendingFor(agent) {
7446
+ const subs = this.db.prepare(`SELECT target, last_seen_seq FROM board_subscriptions WHERE agent = ?`).all(agent);
7447
+ const out = [];
7448
+ for (const s of subs) {
7449
+ const count = this.countSince(s.target, s.last_seen_seq);
7450
+ if (count > 0) out.push({ target: s.target, count });
7451
+ }
7452
+ return out;
7453
+ }
7454
+ markRead(agent, target) {
7455
+ if (target) {
7456
+ const key = targetKey(target);
7457
+ this.db.prepare(
7458
+ `UPDATE board_subscriptions SET last_seen_seq = (SELECT MAX(seq) FROM board_posts) WHERE agent = ? AND target = ?`
7459
+ ).run(agent, key);
7460
+ return;
7461
+ }
7462
+ this.db.prepare(
7463
+ `UPDATE board_subscriptions SET last_seen_seq = (SELECT COALESCE(MAX(seq), 0) FROM board_posts) WHERE agent = ?`
7464
+ ).run(agent);
7465
+ }
7466
+ countSince(target, sinceSeq) {
7467
+ if (target.startsWith("thread:")) {
7468
+ const id = target.slice("thread:".length);
7469
+ const row2 = this.db.prepare(`SELECT COUNT(*) AS n FROM board_posts WHERE thread_id = ? AND seq > ?`).get(id, sinceSeq);
7470
+ return row2.n;
7471
+ }
7472
+ const name = target.slice("channel:".length);
7473
+ const row = this.db.prepare(
7474
+ `SELECT COUNT(*) AS n FROM board_posts p JOIN board_threads t ON t.id = p.thread_id
7475
+ WHERE t.channel = ? AND p.seq > ?`
7476
+ ).get(name, sinceSeq);
7477
+ return row.n;
7478
+ }
7479
+ };
7480
+ function clip(text) {
7481
+ if (text.length <= MAX_POST_CHARS) return text;
7482
+ return `${text.slice(0, MAX_POST_CHARS)}
7483
+ \u2026\uFF08\u622A\u65AD\uFF0C\u539F\u6587 ${text.length} \u5B57\uFF09`;
7484
+ }
7485
+ function firstLine(text) {
7486
+ const line = text.split("\n", 1)[0] ?? text;
7487
+ return line.length > 80 ? `${line.slice(0, 80)}\u2026` : line;
7488
+ }
7489
+ function toChannel(r) {
7490
+ return {
7491
+ id: r.id,
7492
+ name: r.name,
7493
+ ...r.description ? { description: r.description } : {},
7494
+ createdBy: r.created_by,
7495
+ createdAt: r.created_at
7496
+ };
7497
+ }
7498
+ function toPost(r) {
7499
+ return {
7500
+ seq: r.seq,
7501
+ id: r.id,
7502
+ threadId: r.thread_id,
7503
+ author: r.author,
7504
+ text: r.text,
7505
+ createdAt: r.created_at
7506
+ };
7507
+ }
5935
7508
  var PlanModeState = class {
5936
7509
  constructor(permission2) {
5937
7510
  this.permission = permission2;
@@ -6024,11 +7597,11 @@ function loadRoleDir(dir, source) {
6024
7597
  let files;
6025
7598
  try {
6026
7599
  files = readdirSync(dir).filter((f) => f.endsWith(".md")).sort();
6027
- } catch (err) {
7600
+ } catch (err3) {
6028
7601
  return {
6029
7602
  roles: [],
6030
7603
  issues: [
6031
- { path: dir, message: t("agent_role_load.dir_read_failed", { reason: reason(err) }) }
7604
+ { path: dir, message: t("agent_role_load.dir_read_failed", { reason: reason(err3) }) }
6032
7605
  ]
6033
7606
  };
6034
7607
  }
@@ -6045,9 +7618,9 @@ function loadRoleFile(path, file, source) {
6045
7618
  let raw;
6046
7619
  try {
6047
7620
  raw = readFileSync(path, "utf8");
6048
- } catch (err) {
7621
+ } catch (err3) {
6049
7622
  return {
6050
- issues: [{ path: file, message: t("agent_role_load.read_failed", { reason: reason(err) }) }]
7623
+ issues: [{ path: file, message: t("agent_role_load.read_failed", { reason: reason(err3) }) }]
6051
7624
  };
6052
7625
  }
6053
7626
  return parseRoleDefinition(raw, file, source);
@@ -6136,8 +7709,8 @@ function loadRoleDefinitions(opts) {
6136
7709
  projectSkipped: false
6137
7710
  };
6138
7711
  }
6139
- function reason(err) {
6140
- return err instanceof Error ? err.message : String(err);
7712
+ function reason(err3) {
7713
+ return err3 instanceof Error ? err3.message : String(err3);
6141
7714
  }
6142
7715
  var READ_ONLY_TOOLS = [
6143
7716
  "file_read",
@@ -6297,11 +7870,11 @@ function createRoleFile(input, opts) {
6297
7870
  try {
6298
7871
  mkdirSync(opts.dir, { recursive: true });
6299
7872
  writeFileSync(path, text, { encoding: "utf-8", flag: "wx" });
6300
- } catch (err) {
6301
- if (err.code === "EEXIST") {
7873
+ } catch (err3) {
7874
+ if (err3.code === "EEXIST") {
6302
7875
  return { ok: false, reason: "duplicate", detail: t("role_write.taken", { name }) };
6303
7876
  }
6304
- return { ok: false, reason: "unwritable", detail: describe(err) };
7877
+ return { ok: false, reason: "unwritable", detail: describe(err3) };
6305
7878
  }
6306
7879
  return { ok: true, path, role: back.role };
6307
7880
  }
@@ -6341,8 +7914,8 @@ function driftOf(role, name, input) {
6341
7914
  if ((role.maxTurns ?? null) !== (input.maxTurns ?? null)) return "maxTurns";
6342
7915
  return void 0;
6343
7916
  }
6344
- function describe(err) {
6345
- return err instanceof Error ? err.message : String(err);
7917
+ function describe(err3) {
7918
+ return err3 instanceof Error ? err3.message : String(err3);
6346
7919
  }
6347
7920
  function removeRoleFile(name, opts) {
6348
7921
  const wanted = name.trim();
@@ -6371,8 +7944,8 @@ function removeRoleFile(name, opts) {
6371
7944
  }
6372
7945
  try {
6373
7946
  rmSync(path);
6374
- } catch (err) {
6375
- return { ok: false, reason: "failed", detail: describe2(err, path, opts.lang) };
7947
+ } catch (err3) {
7948
+ return { ok: false, reason: "failed", detail: describe2(err3, path, opts.lang) };
6376
7949
  }
6377
7950
  return { ok: true, path };
6378
7951
  }
@@ -6398,8 +7971,8 @@ function matchingFiles(dir, name) {
6398
7971
  }
6399
7972
  return hits;
6400
7973
  }
6401
- function describe2(err, path, lang) {
6402
- const reason9 = err instanceof Error ? err.message : String(err);
7974
+ function describe2(err3, path, lang) {
7975
+ const reason9 = err3 instanceof Error ? err3.message : String(err3);
6403
7976
  return t("role_write.remove_failed", { path, reason: reason9 }, lang);
6404
7977
  }
6405
7978
  // src/agent-role/scope.ts
@@ -6480,14 +8053,14 @@ function walk(dir, prefix, depth, files, issues) {
6480
8053
  let entries2;
6481
8054
  try {
6482
8055
  entries2 = readdirSync(dir, { withFileTypes: true });
6483
- } catch (err) {
6484
- if (isMissing(err)) {
8056
+ } catch (err3) {
8057
+ if (isMissing(err3)) {
6485
8058
  if (depth > 0) issues.push({ path: dir, message: t("custom_command.dir_vanished") });
6486
8059
  return;
6487
8060
  }
6488
8061
  issues.push({
6489
8062
  path: dir,
6490
- message: t("custom_command.dir_read_failed", { reason: reason2(err) })
8063
+ message: t("custom_command.dir_read_failed", { reason: reason2(err3) })
6491
8064
  });
6492
8065
  return;
6493
8066
  }
@@ -6512,11 +8085,11 @@ function walk(dir, prefix, depth, files, issues) {
6512
8085
  function commandNameFromRelPath(relPath) {
6513
8086
  return relPath.replace(/\.md$/i, "").split("/").join(":").toLowerCase();
6514
8087
  }
6515
- function isMissing(err) {
6516
- return err?.code === "ENOENT";
8088
+ function isMissing(err3) {
8089
+ return err3?.code === "ENOENT";
6517
8090
  }
6518
- function reason2(err) {
6519
- return err instanceof Error ? err.message : String(err);
8091
+ function reason2(err3) {
8092
+ return err3 instanceof Error ? err3.message : String(err3);
6520
8093
  }
6521
8094
  // src/extensions/commands.ts
6522
8095
  var CommandFrontmatterSchema = z.object({
@@ -6563,9 +8136,9 @@ function loadCommandFile(file, source, prefix) {
6563
8136
  let raw;
6564
8137
  try {
6565
8138
  raw = readFileSync(file.path, "utf8");
6566
- } catch (err) {
8139
+ } catch (err3) {
6567
8140
  return {
6568
- issues: [{ path: at, message: t("custom_command.read_failed", { reason: reason3(err) }) }]
8141
+ issues: [{ path: at, message: t("custom_command.read_failed", { reason: reason3(err3) }) }]
6569
8142
  };
6570
8143
  }
6571
8144
  const parsed = parseFrontmatter(raw);
@@ -6668,8 +8241,8 @@ function resolveCommandModel(def, opts, warnings) {
6668
8241
  }
6669
8242
  return ref;
6670
8243
  }
6671
- function reason3(err) {
6672
- return err instanceof Error ? err.message : String(err);
8244
+ function reason3(err3) {
8245
+ return err3 instanceof Error ? err3.message : String(err3);
6673
8246
  }
6674
8247
  // src/extensions/registry.ts
6675
8248
  var SLASH_COMMANDS_DIAG_MODULE = "SlashCommands";
@@ -6952,10 +8525,10 @@ function scanHooks(dir, issues) {
6952
8525
  let raw;
6953
8526
  try {
6954
8527
  raw = JSON.parse(readFileSync(path, "utf-8"));
6955
- } catch (err) {
8528
+ } catch (err3) {
6956
8529
  issues.push({
6957
8530
  path,
6958
- message: t("plugin_inventory.hooks_bad_json", { reason: firstLine(err) })
8531
+ message: t("plugin_inventory.hooks_bad_json", { reason: firstLine2(err3) })
6959
8532
  });
6960
8533
  return [];
6961
8534
  }
@@ -6981,8 +8554,8 @@ function scanMcp(dir, plugin, issues) {
6981
8554
  let raw;
6982
8555
  try {
6983
8556
  raw = JSON.parse(readFileSync(path, "utf-8"));
6984
- } catch (err) {
6985
- issues.push({ path, message: t("plugin.mcp_not_json", { reason: firstLine(err) }) });
8557
+ } catch (err3) {
8558
+ issues.push({ path, message: t("plugin.mcp_not_json", { reason: firstLine2(err3) }) });
6986
8559
  return [];
6987
8560
  }
6988
8561
  if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
@@ -7007,10 +8580,10 @@ function readSettingsSummary(path, issues) {
7007
8580
  let raw;
7008
8581
  try {
7009
8582
  raw = JSON.parse(readFileSync(path, "utf-8"));
7010
- } catch (err) {
8583
+ } catch (err3) {
7011
8584
  issues.push({
7012
8585
  path,
7013
- message: t("plugin_inventory.settings_bad_json", { reason: firstLine(err) })
8586
+ message: t("plugin_inventory.settings_bad_json", { reason: firstLine2(err3) })
7014
8587
  });
7015
8588
  return { deny: 0, ignored: [] };
7016
8589
  }
@@ -7038,16 +8611,16 @@ function readEntries(dir, issues) {
7038
8611
  name: e.name,
7039
8612
  isFile: e.isFile()
7040
8613
  }));
7041
- } catch (err) {
8614
+ } catch (err3) {
7042
8615
  issues.push({
7043
8616
  path: dir,
7044
- message: t("plugin_inventory.dir_read_failed", { reason: firstLine(err) })
8617
+ message: t("plugin_inventory.dir_read_failed", { reason: firstLine2(err3) })
7045
8618
  });
7046
8619
  return [];
7047
8620
  }
7048
8621
  }
7049
- function firstLine(err) {
7050
- const message = err instanceof Error ? err.message : String(err);
8622
+ function firstLine2(err3) {
8623
+ const message = err3 instanceof Error ? err3.message : String(err3);
7051
8624
  return message.split("\n")[0] ?? t("plugin_inventory.unknown_error");
7052
8625
  }
7053
8626
  var PLUGIN_MANIFEST_FILE = "epoch-plugin.json";
@@ -7109,13 +8682,13 @@ function readPluginManifest(dir) {
7109
8682
  let raw;
7110
8683
  try {
7111
8684
  raw = readFileSync(path, "utf-8");
7112
- } catch (err) {
7113
- const missing = err.code === "ENOENT";
8685
+ } catch (err3) {
8686
+ const missing = err3.code === "ENOENT";
7114
8687
  return {
7115
8688
  issues: [
7116
8689
  {
7117
8690
  path,
7118
- message: missing ? t("plugin_manifest.missing", { file: PLUGIN_MANIFEST_FILE }) : t("plugin_manifest.read_failed", { reason: reason4(err) })
8691
+ message: missing ? t("plugin_manifest.missing", { file: PLUGIN_MANIFEST_FILE }) : t("plugin_manifest.read_failed", { reason: reason4(err3) })
7119
8692
  }
7120
8693
  ]
7121
8694
  };
@@ -7123,9 +8696,9 @@ function readPluginManifest(dir) {
7123
8696
  let parsed;
7124
8697
  try {
7125
8698
  parsed = JSON.parse(raw);
7126
- } catch (err) {
8699
+ } catch (err3) {
7127
8700
  return {
7128
- issues: [{ path, message: t("plugin_manifest.bad_json", { reason: firstLine2(err) }) }]
8701
+ issues: [{ path, message: t("plugin_manifest.bad_json", { reason: firstLine3(err3) }) }]
7129
8702
  };
7130
8703
  }
7131
8704
  const issues = unknownKeyIssues(PLUGIN_MANIFEST_KEYS, parsed, PLUGIN_MANIFEST_FILE);
@@ -7288,11 +8861,11 @@ function currentEpochVersion() {
7288
8861
  cachedVersion = "unknown";
7289
8862
  return cachedVersion;
7290
8863
  }
7291
- function reason4(err) {
7292
- return err instanceof Error ? err.message : String(err);
8864
+ function reason4(err3) {
8865
+ return err3 instanceof Error ? err3.message : String(err3);
7293
8866
  }
7294
- function firstLine2(err) {
7295
- return reason4(err).split("\n")[0] ?? t("plugin_manifest.unknown_error");
8867
+ function firstLine3(err3) {
8868
+ return reason4(err3).split("\n")[0] ?? t("plugin_manifest.unknown_error");
7296
8869
  }
7297
8870
  var RecordSchema = z.object({
7298
8871
  name: z.string().regex(PLUGIN_NAME_PATTERN),
@@ -7327,8 +8900,8 @@ async function acquireStateLock(path) {
7327
8900
  } catch {
7328
8901
  }
7329
8902
  };
7330
- } catch (err) {
7331
- if (err.code !== "EEXIST") throw err;
8903
+ } catch (err3) {
8904
+ if (err3.code !== "EEXIST") throw err3;
7332
8905
  if (breakStaleLock(lockPath)) continue;
7333
8906
  if (Date.now() >= deadline) {
7334
8907
  throw new Error(t("plugin_store.lock_timeout", { path: lockPath }));
@@ -7360,8 +8933,8 @@ function readPluginRecords(path) {
7360
8933
  let raw;
7361
8934
  try {
7362
8935
  raw = JSON.parse(readFileSync(path, "utf-8"));
7363
- } catch (err) {
7364
- const detail = (err instanceof Error ? err.message : String(err)).split("\n")[0];
8936
+ } catch (err3) {
8937
+ const detail = (err3 instanceof Error ? err3.message : String(err3)).split("\n")[0];
7365
8938
  return {
7366
8939
  records: [],
7367
8940
  issues: [{ path, message: t("plugin_store.bad_json", { detail: detail ?? "" }) }]
@@ -7652,30 +9225,30 @@ function runCommand(file, args, opts = {}) {
7652
9225
  windowsVerbatimArguments: viaCmd,
7653
9226
  ...opts.cwd ? { cwd: opts.cwd } : {}
7654
9227
  },
7655
- (err, stdout, stderr) => {
9228
+ (err3, stdout, stderr) => {
7656
9229
  const out = String(stdout ?? "");
7657
9230
  const errOut = String(stderr ?? "");
7658
- if (!err) {
9231
+ if (!err3) {
7659
9232
  resolvePromise({ ok: true, stdout: out, stderr: errOut });
7660
9233
  return;
7661
9234
  }
7662
- const detail = describe3(file, err, errOut);
9235
+ const detail = describe3(file, err3, errOut);
7663
9236
  resolvePromise({
7664
9237
  ok: false,
7665
9238
  detail,
7666
9239
  stdout: out,
7667
9240
  stderr: errOut,
7668
- ...err.code === "ENOENT" ? { notFound: true } : {}
9241
+ ...err3.code === "ENOENT" ? { notFound: true } : {}
7669
9242
  });
7670
9243
  }
7671
9244
  ),
7672
- (err) => {
9245
+ (err3) => {
7673
9246
  resolvePromise({
7674
9247
  ok: false,
7675
- detail: describe3(file, err, ""),
9248
+ detail: describe3(file, err3, ""),
7676
9249
  stdout: "",
7677
9250
  stderr: "",
7678
- ...err.code === "ENOENT" || err.code === "ENOTDIR" ? { notFound: true } : {}
9251
+ ...err3.code === "ENOENT" || err3.code === "ENOTDIR" ? { notFound: true } : {}
7679
9252
  });
7680
9253
  }
7681
9254
  );
@@ -7688,11 +9261,11 @@ function escapeForCmd(arg) {
7688
9261
  const quoted = `"${arg.replace(/(\\*)"/g, '$1$1\\"').replace(/(\\*)$/, "$1$1")}"`;
7689
9262
  return quoted.replace(/([()%!^<>&|;,"])/g, "^$1");
7690
9263
  }
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 });
9264
+ function describe3(file, err3, stderr) {
9265
+ if (err3.code === "ENOENT") return t("plugin_cmd.not_found", { file });
9266
+ if (err3.killed) return t("plugin_cmd.timeout", { file });
7694
9267
  const tail = stderr.trim().split("\n").slice(-4).join("\n").trim();
7695
- return tail || err.message;
9268
+ return tail || err3.message;
7696
9269
  }
7697
9270
  // src/plugin/archive.ts
7698
9271
  function resolveTar() {
@@ -7757,8 +9330,8 @@ ${detail}` }) };
7757
9330
  let entries2;
7758
9331
  try {
7759
9332
  entries2 = readdirSync(current, { withFileTypes: true });
7760
- } catch (err) {
7761
- return t("plugin_pack.read_failed", { path: current, reason: firstLine3(err) });
9333
+ } catch (err3) {
9334
+ return t("plugin_pack.read_failed", { path: current, reason: firstLine4(err3) });
7762
9335
  }
7763
9336
  for (const entry of entries2) {
7764
9337
  if (PACK_EXCLUDES.includes(entry.name)) continue;
@@ -7781,8 +9354,8 @@ ${detail}` }) };
7781
9354
  let stat5;
7782
9355
  try {
7783
9356
  stat5 = statSync(abs);
7784
- } catch (err) {
7785
- return t("plugin_pack.read_failed", { path: abs, reason: firstLine3(err) });
9357
+ } catch (err3) {
9358
+ return t("plugin_pack.read_failed", { path: abs, reason: firstLine4(err3) });
7786
9359
  }
7787
9360
  files.push({ path: rel, bytes: stat5.size, mtimeMs: Math.floor(stat5.mtimeMs) });
7788
9361
  totalBytes += stat5.size;
@@ -7819,10 +9392,10 @@ async function packPlugin(plan, destDir) {
7819
9392
  try {
7820
9393
  writeFileSync(listFile, `${plan.files.map((f) => f.path).join("\n")}
7821
9394
  `, "utf-8");
7822
- } catch (err) {
9395
+ } catch (err3) {
7823
9396
  return {
7824
9397
  ok: false,
7825
- reason: t("plugin_pack.read_failed", { path: listFile, reason: firstLine3(err) })
9398
+ reason: t("plugin_pack.read_failed", { path: listFile, reason: firstLine4(err3) })
7826
9399
  };
7827
9400
  }
7828
9401
  let result;
@@ -7850,10 +9423,10 @@ async function packPlugin(plan, destDir) {
7850
9423
  let bytes;
7851
9424
  try {
7852
9425
  bytes = statSync(archivePath).size;
7853
- } catch (err) {
9426
+ } catch (err3) {
7854
9427
  return {
7855
9428
  ok: false,
7856
- reason: t("plugin_pack.read_failed", { path: archivePath, reason: firstLine3(err) })
9429
+ reason: t("plugin_pack.read_failed", { path: archivePath, reason: firstLine4(err3) })
7857
9430
  };
7858
9431
  }
7859
9432
  return { ok: true, archivePath, bytes };
@@ -7861,8 +9434,8 @@ async function packPlugin(plan, destDir) {
7861
9434
  function isVirtualenv(dir) {
7862
9435
  return existsSync(join(dir, "pyvenv.cfg"));
7863
9436
  }
7864
- function firstLine3(err) {
7865
- const message = err instanceof Error ? err.message : String(err);
9437
+ function firstLine4(err3) {
9438
+ const message = err3 instanceof Error ? err3.message : String(err3);
7866
9439
  return message.split("\n")[0] ?? message;
7867
9440
  }
7868
9441
  var ABOUT_README_MAX_CHARS = 32e3;
@@ -8118,11 +9691,11 @@ function readMarketplaces(statePath) {
8118
9691
  let raw;
8119
9692
  try {
8120
9693
  raw = JSON.parse(readFileSync(statePath, "utf-8"));
8121
- } catch (err) {
9694
+ } catch (err3) {
8122
9695
  return {
8123
9696
  records: [],
8124
9697
  issues: [
8125
- { path: statePath, message: t("plugin_marketplace.bad_json", { reason: first(err) }) }
9698
+ { path: statePath, message: t("plugin_marketplace.bad_json", { reason: first(err3) }) }
8126
9699
  ]
8127
9700
  };
8128
9701
  }
@@ -8282,8 +9855,8 @@ async function fetchCatalog(source) {
8282
9855
  }
8283
9856
  try {
8284
9857
  return parseCatalog(readFileSync(local, "utf-8"), local);
8285
- } catch (err) {
8286
- return { ok: false, reason: t("plugin_marketplace.read_failed", { reason: first(err) }) };
9858
+ } catch (err3) {
9859
+ return { ok: false, reason: t("plugin_marketplace.read_failed", { reason: first(err3) }) };
8287
9860
  }
8288
9861
  }
8289
9862
  const url = catalogUrl(input);
@@ -8303,8 +9876,8 @@ async function fetchCatalog(source) {
8303
9876
  };
8304
9877
  }
8305
9878
  return parseCatalog(await response.text(), url);
8306
- } catch (err) {
8307
- return { ok: false, reason: t("marketplace.fetch_error", { url, reason: first(err) }) };
9879
+ } catch (err3) {
9880
+ return { ok: false, reason: t("marketplace.fetch_error", { url, reason: first(err3) }) };
8308
9881
  }
8309
9882
  }
8310
9883
  function looksPrivate(status) {
@@ -8334,10 +9907,10 @@ function parseCatalog(body2, where) {
8334
9907
  let raw;
8335
9908
  try {
8336
9909
  raw = JSON.parse(body2);
8337
- } catch (err) {
9910
+ } catch (err3) {
8338
9911
  return {
8339
9912
  ok: false,
8340
- reason: t("plugin_marketplace.catalog_bad_json", { where, reason: first(err) })
9913
+ reason: t("plugin_marketplace.catalog_bad_json", { where, reason: first(err3) })
8341
9914
  };
8342
9915
  }
8343
9916
  const checked = parseLenient(CatalogSchema.optional(), raw, void 0);
@@ -8347,8 +9920,8 @@ function parseCatalog(body2, where) {
8347
9920
  }
8348
9921
  return { ok: true, catalog: checked.value };
8349
9922
  }
8350
- function first(err) {
8351
- const message = err instanceof Error ? err.message : String(err);
9923
+ function first(err3) {
9924
+ const message = err3 instanceof Error ? err3.message : String(err3);
8352
9925
  return message.split("\n")[0] ?? t("plugin_marketplace.unknown_error");
8353
9926
  }
8354
9927
  var NPM_SPEC = /^(?:@[a-z0-9][a-z0-9._-]*\/)?[a-z0-9][a-z0-9._-]*(?:@[a-zA-Z0-9.^~*+-]+)?$/;
@@ -8756,11 +10329,11 @@ async function fetchFromHost(source, staging, opts) {
8756
10329
  );
8757
10330
  }
8758
10331
  });
8759
- } catch (err) {
10332
+ } catch (err3) {
8760
10333
  return {
8761
10334
  ok: false,
8762
10335
  reason: t("plugin_install.host_fetch_threw", {
8763
- reason: (err instanceof Error ? err.message : String(err)).split("\n")[0] ?? ""
10336
+ reason: (err3 instanceof Error ? err3.message : String(err3)).split("\n")[0] ?? ""
8764
10337
  })
8765
10338
  };
8766
10339
  }
@@ -8832,11 +10405,11 @@ async function fetchArchive(source, staging, opts) {
8832
10405
  };
8833
10406
  }
8834
10407
  bytes = await readBodyWithProgress(response, byteReporter(opts, "download", source.target));
8835
- } catch (err) {
10408
+ } catch (err3) {
8836
10409
  return {
8837
10410
  ok: false,
8838
10411
  reason: t("plugin_install.download_failed", {
8839
- message: err instanceof Error ? err.message : String(err)
10412
+ message: err3 instanceof Error ? err3.message : String(err3)
8840
10413
  })
8841
10414
  };
8842
10415
  }
@@ -8974,8 +10547,8 @@ async function applyRewind(store, sessionId, manifest, apply, skippedConflicts)
8974
10547
  let staged;
8975
10548
  try {
8976
10549
  staged = await stageAll(store, sessionId, manifest, todo, byPath);
8977
- } catch (err) {
8978
- return { ...empty, failed: t("rewind.stage_failed", { message: messageOf(err) }) };
10550
+ } catch (err3) {
10551
+ return { ...empty, failed: t("rewind.stage_failed", { message: messageOf(err3) }) };
8979
10552
  }
8980
10553
  return commitAll2(staged, skippedConflicts);
8981
10554
  }
@@ -8999,9 +10572,9 @@ async function stageAll(store, sessionId, manifest, todo, byPath) {
8999
10572
  }
9000
10573
  staged.push(item);
9001
10574
  }
9002
- } catch (err) {
10575
+ } catch (err3) {
9003
10576
  await discard(staged);
9004
- throw err;
10577
+ throw err3;
9005
10578
  }
9006
10579
  return staged;
9007
10580
  }
@@ -9016,7 +10589,7 @@ async function commitAll2(staged, skippedConflicts) {
9016
10589
  for (const item of staged) {
9017
10590
  try {
9018
10591
  await commitOne(item);
9019
- } catch (err) {
10592
+ } catch (err3) {
9020
10593
  await rollback(done2);
9021
10594
  await discard(staged);
9022
10595
  return {
@@ -9024,7 +10597,7 @@ async function commitAll2(staged, skippedConflicts) {
9024
10597
  restored: [],
9025
10598
  deleted: [],
9026
10599
  recreated: [],
9027
- failed: t("rewind.commit_failed", { message: messageOf(err) })
10600
+ failed: t("rewind.commit_failed", { message: messageOf(err3) })
9028
10601
  };
9029
10602
  }
9030
10603
  done2.push(item);
@@ -9080,8 +10653,8 @@ function bucketOf(outcome, action) {
9080
10653
  if (action === "recreate") return outcome.recreated;
9081
10654
  return outcome.restored;
9082
10655
  }
9083
- function messageOf(err) {
9084
- return err instanceof Error ? err.message : String(err);
10656
+ function messageOf(err3) {
10657
+ return err3 instanceof Error ? err3.message : String(err3);
9085
10658
  }
9086
10659
  // src/disk-ledger.ts
9087
10660
  var CHECKPOINT_MAX_TOTAL_BYTES = 200 * 1024 * 1024;
@@ -9238,9 +10811,9 @@ async function atomicWrite(path, data) {
9238
10811
  await writeFile(tmp, data);
9239
10812
  try {
9240
10813
  await rename(tmp, path);
9241
- } catch (err) {
10814
+ } catch (err3) {
9242
10815
  await rm(tmp, { force: true });
9243
- throw err;
10816
+ throw err3;
9244
10817
  }
9245
10818
  }
9246
10819
  function isManifest(value) {
@@ -9334,9 +10907,9 @@ var CheckpointManager = class {
9334
10907
  turnIndex = turn.turnIndex ?? await this.nextTurnIndex(sessionId);
9335
10908
  turn.turnIndex = turnIndex;
9336
10909
  for (const path of fresh) {
9337
- const { file, ok: ok2 } = await this.snapshotFile(sessionId, turnIndex, path);
10910
+ const { file, ok: ok4 } = await this.snapshotFile(sessionId, turnIndex, path);
9338
10911
  turn.files.push(file);
9339
- if (!ok2) turn.incomplete = true;
10912
+ if (!ok4) turn.incomplete = true;
9340
10913
  }
9341
10914
  await this.store.writeManifest(sessionId, manifestOf(turn, turnIndex, this.workDir()));
9342
10915
  } catch {
@@ -9375,8 +10948,8 @@ var CheckpointManager = class {
9375
10948
  if (info.size > MAX_FILE_BYTES) return { file: absent, ok: false };
9376
10949
  const hash = await this.store.putBlob(sessionId, turnIndex, await readFile(path));
9377
10950
  return { file: { path, hash, mode: info.mode & 511 }, ok: true };
9378
- } catch (err) {
9379
- return { file: absent, ok: isNotFound(err) };
10951
+ } catch (err3) {
10952
+ return { file: absent, ok: isNotFound(err3) };
9380
10953
  }
9381
10954
  }
9382
10955
  async nextTurnIndex(sessionId) {
@@ -9426,8 +10999,8 @@ function preview(text) {
9426
10999
  const flat = text.replace(/\s+/g, " ").trim();
9427
11000
  return flat.length > PREVIEW_LEN ? `${flat.slice(0, PREVIEW_LEN)}\u2026` : flat;
9428
11001
  }
9429
- function isNotFound(err) {
9430
- return err?.code === "ENOENT";
11002
+ function isNotFound(err3) {
11003
+ return err3?.code === "ENOENT";
9431
11004
  }
9432
11005
  async function hashOf(path) {
9433
11006
  try {
@@ -9515,8 +11088,8 @@ async function readSnapshot(path) {
9515
11088
  const buf = await readFile(path);
9516
11089
  if (buf.includes(0)) return { kind: "opaque" };
9517
11090
  return { kind: "text", text: buf.toString("utf-8"), bytes: buf.byteLength };
9518
- } catch (err) {
9519
- return isNotFound2(err) ? { kind: "absent" } : { kind: "opaque" };
11091
+ } catch (err3) {
11092
+ return isNotFound2(err3) ? { kind: "absent" } : { kind: "opaque" };
9520
11093
  }
9521
11094
  }
9522
11095
  function workspaceDisplayPath(path, workDir) {
@@ -9524,34 +11097,64 @@ function workspaceDisplayPath(path, workDir) {
9524
11097
  if (!rel || rel.startsWith("..") || isAbsolute(rel)) return path;
9525
11098
  return sep === "/" ? rel : rel.split(sep).join("/");
9526
11099
  }
9527
- function isNotFound2(err) {
9528
- return err?.code === "ENOENT";
11100
+ function isNotFound2(err3) {
11101
+ return err3?.code === "ENOENT";
9529
11102
  }
9530
11103
  var TaskNoticeTracker = class {
9531
- constructor(source) {
11104
+ constructor(source, team, board) {
9532
11105
  this.source = source;
11106
+ this.team = team;
11107
+ this.board = board;
9533
11108
  }
9534
11109
  source;
11110
+ team;
11111
+ board;
9535
11112
  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
- }
11113
+ takeAgentMessages(sessionId) {
11114
+ const inbox = this.team?.mainInbox(sessionId);
11115
+ if (!inbox?.pending()) return [];
11116
+ return inbox.take().map((c) => typeof c === "string" ? c : contentToText(c));
11117
+ }
11118
+ notice(sessionId = LEAD_AGENT_ID) {
11119
+ return this.noticeDetailed(sessionId)?.text ?? null;
11120
+ }
11121
+ noticeDetailed(sessionId = LEAD_AGENT_ID) {
9544
11122
  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));
11123
+ if (this.source) {
11124
+ let tasks;
11125
+ try {
11126
+ tasks = this.source();
11127
+ } catch {
11128
+ tasks = [];
11129
+ }
11130
+ for (const task of tasks) {
11131
+ if (task.kind === "shell") continue;
11132
+ const before = this.seen.get(task.id);
11133
+ if (before === task.status) continue;
11134
+ this.seen.set(task.id, task.status);
11135
+ if (task.kind === "agent" && task.status === "running") continue;
11136
+ lines.push(describeBackgroundTask(task));
11137
+ }
11138
+ }
11139
+ const agentLines = this.takeAgentMessages(sessionId);
11140
+ const boardLines = this.board?.pending() ?? [];
11141
+ if (lines.length === 0 && agentLines.length === 0 && boardLines.length === 0) return null;
11142
+ const out = [];
11143
+ if (lines.length > 0) {
11144
+ out.push(systemNote("\u540E\u53F0\u4EFB\u52A1\u72B6\u6001"), ...lines, "\u8981\u770B\u8F93\u51FA\u7528 task_output\u3002");
11145
+ }
11146
+ if (agentLines.length > 0) {
11147
+ out.push(systemNote(AGENT_MESSAGE_NOTE_TITLE), ...agentLines);
11148
+ }
11149
+ if (boardLines.length > 0) {
11150
+ out.push(
11151
+ systemNote("\u8BA8\u8BBA\u677F"),
11152
+ ...boardLines.map((b) => `- ${b.target}\uFF1A${b.count} \u6761\u65B0\u5E16`),
11153
+ "\u8981\u770B\u5185\u5BB9\u7528 read_thread\uFF08\u8BFB\u5B8C\u81EA\u52A8\u6807\u6210\u5DF2\u770B\uFF09\u3002"
11154
+ );
11155
+ this.board?.markRead();
9552
11156
  }
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");
11157
+ return { text: out.join("\n"), agent: agentLines };
9555
11158
  }
9556
11159
  };
9557
11160
  function describeBackgroundTask(task) {
@@ -9840,8 +11443,8 @@ function readImageSize(bytes) {
9840
11443
  const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
9841
11444
  const size = pngSize(bytes, view) ?? jpegSize(bytes, view) ?? gifSize(bytes, view) ?? webpSize(bytes, view);
9842
11445
  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;
11446
+ const ok4 = (n) => Number.isInteger(n) && n > 0;
11447
+ return ok4(size.width) && ok4(size.height) ? size : void 0;
9845
11448
  }
9846
11449
  function sniffMediaType(bytes) {
9847
11450
  if (bytes.length < 12) return void 0;
@@ -10181,8 +11784,8 @@ function imageFromPath(filePath, mediaType) {
10181
11784
  const st = statSync(abs);
10182
11785
  if (!st.isFile()) throw new ImageLoadError(t("image_load.not_a_file", { path: abs }));
10183
11786
  size = st.size;
10184
- } catch (err) {
10185
- if (err instanceof ImageLoadError) throw err;
11787
+ } catch (err3) {
11788
+ if (err3 instanceof ImageLoadError) throw err3;
10186
11789
  throw new ImageLoadError(t("image_load.unreadable", { path: abs }));
10187
11790
  }
10188
11791
  if (size === 0) throw new ImageLoadError(t("image_load.empty", { path: abs }));
@@ -10399,8 +12002,8 @@ function decideTrust(dir) {
10399
12002
  return ambient ? ambient.decide(dir) : noGate();
10400
12003
  }
10401
12004
  var FILE_VERSION = 1;
10402
- function describe5(err) {
10403
- return err instanceof Error ? err.message : String(err);
12005
+ function describe5(err3) {
12006
+ return err3 instanceof Error ? err3.message : String(err3);
10404
12007
  }
10405
12008
  var ImportTrustStore = class {
10406
12009
  constructor(filePath = trustedImportsPath()) {
@@ -10439,18 +12042,18 @@ var ImportTrustStore = class {
10439
12042
  let raw;
10440
12043
  try {
10441
12044
  raw = readFileSync(this.filePath, "utf-8");
10442
- } catch (err) {
12045
+ } catch (err3) {
10443
12046
  this.loadErrors.push(
10444
- t("import_trust.read_failed", { path: this.filePath, reason: describe5(err) })
12047
+ t("import_trust.read_failed", { path: this.filePath, reason: describe5(err3) })
10445
12048
  );
10446
12049
  return;
10447
12050
  }
10448
12051
  let parsed;
10449
12052
  try {
10450
12053
  parsed = JSON.parse(raw);
10451
- } catch (err) {
12054
+ } catch (err3) {
10452
12055
  this.loadErrors.push(
10453
- t("import_trust.bad_json", { path: this.filePath, reason: describe5(err) })
12056
+ t("import_trust.bad_json", { path: this.filePath, reason: describe5(err3) })
10454
12057
  );
10455
12058
  return;
10456
12059
  }
@@ -10505,10 +12108,10 @@ var ImportTrustStore = class {
10505
12108
  try {
10506
12109
  writeFileSync(tmp, body2, { encoding: "utf-8", mode: 384 });
10507
12110
  renameSync(tmp, this.filePath);
10508
- } catch (err) {
12111
+ } catch (err3) {
10509
12112
  rmSync(tmp, { force: true });
10510
12113
  throw new Error(
10511
- t("import_trust.write_failed", { path: this.filePath, reason: describe5(err) })
12114
+ t("import_trust.write_failed", { path: this.filePath, reason: describe5(err3) })
10512
12115
  );
10513
12116
  }
10514
12117
  }
@@ -11152,8 +12755,8 @@ var BudgetStore = class {
11152
12755
  throw new Error(t("budget.state_missing_sessions"));
11153
12756
  }
11154
12757
  return { version: 1, sessions };
11155
- } catch (err) {
11156
- const reason9 = err instanceof Error ? err.message : String(err);
12758
+ } catch (err3) {
12759
+ const reason9 = err3 instanceof Error ? err3.message : String(err3);
11157
12760
  this.quarantine();
11158
12761
  this.onWarn?.(t("budget.state_corrupt", { reason: reason9, path: this.path }));
11159
12762
  return empty;
@@ -11169,10 +12772,10 @@ var BudgetStore = class {
11169
12772
  try {
11170
12773
  mkdirSync(dirname(this.path), { recursive: true });
11171
12774
  writeFileSync(this.path, JSON.stringify(state, null, 2));
11172
- } catch (err) {
12775
+ } catch (err3) {
11173
12776
  this.onWarn?.(
11174
12777
  t("budget.state_write_failed", {
11175
- message: err instanceof Error ? err.message : String(err)
12778
+ message: err3 instanceof Error ? err3.message : String(err3)
11176
12779
  })
11177
12780
  );
11178
12781
  }
@@ -11496,25 +13099,25 @@ var PROVIDER_NO_CREDENTIAL = 1001;
11496
13099
  var PROVIDER_ABORTED = 1060;
11497
13100
  var PROVIDER_CONTEXT_OVERFLOW = 1030;
11498
13101
  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;
13102
+ function isContextOverflow(err3) {
13103
+ if (err3 instanceof ProviderError) return err3.code === PROVIDER_CONTEXT_OVERFLOW;
13104
+ return classifyProviderError(err3).code === PROVIDER_CONTEXT_OVERFLOW;
11502
13105
  }
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;
13106
+ function isBodyTooLarge(err3) {
13107
+ if (err3 instanceof ProviderError) return err3.code === PROVIDER_BODY_TOO_LARGE;
13108
+ return classifyProviderError(err3).code === PROVIDER_BODY_TOO_LARGE;
11506
13109
  }
11507
- function isAbortError(err) {
11508
- for (let cur = err, depth = 0; cur && depth < 5; depth++) {
13110
+ function isAbortError(err3) {
13111
+ for (let cur = err3, depth = 0; cur && depth < 5; depth++) {
11509
13112
  if (typeof cur !== "object") return false;
11510
13113
  if (cur.name === "AbortError") return true;
11511
13114
  cur = cur.cause;
11512
13115
  }
11513
13116
  return false;
11514
13117
  }
11515
- function causeChain(err) {
13118
+ function causeChain(err3) {
11516
13119
  const out = [];
11517
- for (let cur = err, depth = 0; cur && depth < 5; depth++) {
13120
+ for (let cur = err3, depth = 0; cur && depth < 5; depth++) {
11518
13121
  if (typeof cur !== "object") break;
11519
13122
  const e = cur;
11520
13123
  out.push({
@@ -11539,20 +13142,20 @@ var NETWORK_ERROR_CODES = /* @__PURE__ */ new Set([
11539
13142
  "UND_ERR_RESPONSE_STATUS_CODE"
11540
13143
  ]);
11541
13144
  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));
13145
+ function describeProviderError(err3) {
13146
+ const chain = causeChain(err3);
13147
+ const head = chain[0]?.message ?? (typeof err3 === "string" ? err3 : String(err3));
11545
13148
  const root = [...chain].reverse().find((link) => link.message !== "" && link.message !== head)?.message;
11546
13149
  if (!head.trim()) {
11547
13150
  if (root) return root;
11548
- const status = extractStatus(err);
13151
+ const status = extractStatus(err3);
11549
13152
  return status === void 0 ? t("provider_route.no_detail") : t("provider_route.no_detail_status", { status });
11550
13153
  }
11551
13154
  return root ? t("provider_route.root_cause", { message: head, cause: root }) : head;
11552
13155
  }
11553
- function extractStatus(err) {
11554
- if (!err || typeof err !== "object") return void 0;
11555
- const e = err;
13156
+ function extractStatus(err3) {
13157
+ if (!err3 || typeof err3 !== "object") return void 0;
13158
+ const e = err3;
11556
13159
  for (const candidate of [e.statusCode, e.status, e.response?.status]) {
11557
13160
  if (typeof candidate === "number" && candidate >= 100 && candidate < 600) return candidate;
11558
13161
  }
@@ -11565,10 +13168,10 @@ function extractStatusFromMessage(msg) {
11565
13168
  if (labelled?.[1]) return Number(labelled[1]);
11566
13169
  return void 0;
11567
13170
  }
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" };
13171
+ function classifyProviderError(err3) {
13172
+ const msg = err3 instanceof Error ? err3.message : String(err3);
13173
+ const status = extractStatus(err3);
13174
+ if (isAbortError(err3)) return { code: PROVIDER_ABORTED, recovery: "abort" };
11572
13175
  if (/context.?length|context.?window|maximum.*token|token.?limit|too.?many.?tokens|prompt.*too.?long|reduce.*(length|tokens)/i.test(
11573
13176
  msg
11574
13177
  ))
@@ -11597,7 +13200,7 @@ function classifyProviderError(err) {
11597
13200
  if (code >= 500) return { code: 1020, recovery: "retry" };
11598
13201
  if (code >= 400) return { code: 1050, recovery: "abort" };
11599
13202
  }
11600
- for (const link of causeChain(err)) {
13203
+ for (const link of causeChain(err3)) {
11601
13204
  if (link.code && NETWORK_ERROR_CODES.has(link.code)) return { code: 1041, recovery: "retry" };
11602
13205
  if (NETWORK_MESSAGE_RE.test(link.message)) return { code: 1041, recovery: "retry" };
11603
13206
  }
@@ -12885,12 +14488,12 @@ var ToolExecutor = class {
12885
14488
  truncateForModel(failureText(r), budgetOf2(et, depth, "failure"), "text")
12886
14489
  )
12887
14490
  });
12888
- } catch (err) {
12889
- span.recordError(err);
14491
+ } catch (err3) {
14492
+ span.recordError(err3);
12890
14493
  return finish({
12891
14494
  ...base2,
12892
14495
  success: false,
12893
- output: `\u5DE5\u5177\u6267\u884C\u5F02\u5E38: ${err instanceof Error ? err.message : String(err)}`
14496
+ output: `\u5DE5\u5177\u6267\u884C\u5F02\u5E38: ${err3 instanceof Error ? err3.message : String(err3)}`
12894
14497
  });
12895
14498
  }
12896
14499
  }
@@ -13300,6 +14903,7 @@ var AgentLoop = class {
13300
14903
  async *runTurns(input, turns) {
13301
14904
  const maxTurns = turnLimitOf(input.maxTurns ?? this.config.maxTurns);
13302
14905
  this.stallDetector.reset();
14906
+ const pendingReceived = [];
13303
14907
  const rawUserText = contentToText(input.userMessage, { imagesCarriedAsParts: true });
13304
14908
  const images = imageParts(input.userMessage);
13305
14909
  const inputGate = this.config.compliance?.checkInput(rawUserText);
@@ -13397,6 +15001,7 @@ var AgentLoop = class {
13397
15001
  ...breach ? { breach } : {}
13398
15002
  });
13399
15003
  this.hooks.fire("session:start", { sessionId: input.sessionId });
15004
+ this.config.team?.registerSession(input.sessionId);
13400
15005
  const runSpan = this.telemetry.startSpan("agent_run", {
13401
15006
  [GEN_AI.OPERATION_NAME]: "agent_run",
13402
15007
  [GEN_AI.CONVERSATION_ID]: input.sessionId
@@ -13427,7 +15032,11 @@ var AgentLoop = class {
13427
15032
  ...history,
13428
15033
  { role: "user", content: userContent, ...userParts ? { parts: userParts } : {} }
13429
15034
  ];
13430
- const taskNotice = new TaskNoticeTracker(this.config.backgroundTasks);
15035
+ const taskNotice = new TaskNoticeTracker(
15036
+ this.config.backgroundTasks,
15037
+ this.config.team,
15038
+ this.config.board
15039
+ );
13431
15040
  let todoNudged = false;
13432
15041
  let idleNudged = false;
13433
15042
  let blankNudged = false;
@@ -13456,9 +15065,21 @@ var AgentLoop = class {
13456
15065
  yield finish("budget-exceeded", stop.breach);
13457
15066
  return;
13458
15067
  }
13459
- const notice2 = taskNotice.notice();
13460
- if (notice2) messages.push({ role: "user", content: notice2 });
13461
- if (turn > 1) yield* this.drainSteer(input, messages);
15068
+ const notice2 = taskNotice.noticeDetailed(input.sessionId);
15069
+ if (notice2) messages.push({ role: "user", content: notice2.text });
15070
+ if (notice2 && notice2.agent.length > 0) {
15071
+ yield {
15072
+ type: "notice",
15073
+ code: "agent-message",
15074
+ text: [systemNote(AGENT_MESSAGE_NOTE_TITLE), ...notice2.agent].join("\n")
15075
+ };
15076
+ }
15077
+ if (turn > 1) {
15078
+ for await (const ev of this.drainSteer(input, messages)) {
15079
+ if (ev.type === "steer") pendingReceived.push(ev.text);
15080
+ yield ev;
15081
+ }
15082
+ }
13462
15083
  this.hooks.fire("turn:before", {
13463
15084
  sessionId: input.sessionId,
13464
15085
  userMessage: transformed,
@@ -13584,9 +15205,9 @@ var AgentLoop = class {
13584
15205
  }
13585
15206
  llmSpan.setAttribute("epoch.finish_reason", result.finishReason);
13586
15207
  break;
13587
- } catch (err) {
13588
- llmSpan.recordError(err);
13589
- if (isBodyTooLarge(err) && imagesRescue.offloaded === 0) {
15208
+ } catch (err3) {
15209
+ llmSpan.recordError(err3);
15210
+ if (isBodyTooLarge(err3) && imagesRescue.offloaded === 0) {
13590
15211
  const saved = this.tryOffloadForBodyLimit(messages);
13591
15212
  if (saved) {
13592
15213
  messages = saved.messages;
@@ -13602,8 +15223,8 @@ var AgentLoop = class {
13602
15223
  }
13603
15224
  }
13604
15225
  const engine = this.config.contextEngine;
13605
- const retriable = isContextOverflow(err) || isBodyTooLarge(err);
13606
- if (overflowRescued || !engine || !retriable) throw err;
15226
+ const retriable = isContextOverflow(err3) || isBodyTooLarge(err3);
15227
+ if (overflowRescued || !engine || !retriable) throw err3;
13607
15228
  overflowRescued = true;
13608
15229
  const rescued = await this.compressNow(messages, {
13609
15230
  totalTokens: totalInput + totalOutput,
@@ -13616,7 +15237,7 @@ var AgentLoop = class {
13616
15237
  runUsage
13617
15238
  );
13618
15239
  }
13619
- if (!shrank(messages, rescued.messages)) throw err;
15240
+ if (!shrank(messages, rescued.messages)) throw err3;
13620
15241
  messages = rescued.messages;
13621
15242
  yield {
13622
15243
  type: "notice",
@@ -13729,7 +15350,8 @@ var AgentLoop = class {
13729
15350
  index: turn,
13730
15351
  llmResponse: result.text,
13731
15352
  toolCalls: [],
13732
- duration: Date.now() - turnStart
15353
+ duration: Date.now() - turnStart,
15354
+ ...pendingReceived.length > 0 ? { received: pendingReceived.splice(0) } : {}
13733
15355
  });
13734
15356
  yield { type: "turn-complete", turn };
13735
15357
  const finalText = await this.hooks.transformResponse(result.text, input.sessionId);
@@ -13750,7 +15372,10 @@ ${finalText}` };
13750
15372
  content: finalText || NO_OUTPUT_TEXT,
13751
15373
  ...result.reasoningText ? { reasoning: result.reasoningText } : {}
13752
15374
  });
13753
- yield* this.drainSteer(input, messages);
15375
+ for await (const ev of this.drainSteer(input, messages)) {
15376
+ if (ev.type === "steer") pendingReceived.push(ev.text);
15377
+ yield ev;
15378
+ }
13754
15379
  continue;
13755
15380
  }
13756
15381
  const wantContinue = await this.hooks.wantsContinue(
@@ -13898,7 +15523,8 @@ ${finalText}` };
13898
15523
  args: e.args,
13899
15524
  result: e.output
13900
15525
  })),
13901
- duration: Date.now() - turnStart
15526
+ duration: Date.now() - turnStart,
15527
+ ...pendingReceived.length > 0 ? { received: pendingReceived.splice(0) } : {}
13902
15528
  });
13903
15529
  this.hooks.fire("turn:after", {
13904
15530
  sessionId: input.sessionId,
@@ -13954,15 +15580,15 @@ ${finalText}` };
13954
15580
  turns
13955
15581
  });
13956
15582
  yield finish("max-turns");
13957
- } catch (err) {
15583
+ } catch (err3) {
13958
15584
  if (this.isAborted(input.signal)) {
13959
15585
  await this.prompt.syncMemory(userText, lastText);
13960
15586
  yield { type: "notice", code: "aborted", text: t("agent_run.aborted") };
13961
15587
  yield finish("aborted");
13962
15588
  return;
13963
15589
  }
13964
- const msg = err instanceof Error ? err.message : String(err);
13965
- runSpan.recordError(err);
15590
+ const msg = err3 instanceof Error ? err3.message : String(err3);
15591
+ runSpan.recordError(err3);
13966
15592
  await this.prompt.syncMemory(userText, "");
13967
15593
  const errorText = t("agent_run.error", { message: msg });
13968
15594
  this.hooks.fire("turn:after", { sessionId: input.sessionId, response: errorText });
@@ -14174,10 +15800,10 @@ function loadModelEntries(homeDir) {
14174
15800
  let raw;
14175
15801
  try {
14176
15802
  raw = JSON.parse(readFileSync(path, "utf-8"));
14177
- } catch (err) {
15803
+ } catch (err3) {
14178
15804
  return {
14179
15805
  entries: [],
14180
- issues: [`${path}: ${err instanceof Error ? err.message : String(err)}`]
15806
+ issues: [`${path}: ${err3 instanceof Error ? err3.message : String(err3)}`]
14181
15807
  };
14182
15808
  }
14183
15809
  const list = raw?.models;
@@ -14225,9 +15851,9 @@ function saveModelEntries(homeDir, entries2, hostLabel) {
14225
15851
  try {
14226
15852
  writeFileSync(tmp, body2, { encoding: "utf-8", mode: 384 });
14227
15853
  renameSync(tmp, path);
14228
- } catch (err) {
15854
+ } catch (err3) {
14229
15855
  rmSync(tmp, { force: true });
14230
- throw err;
15856
+ throw err3;
14231
15857
  }
14232
15858
  }
14233
15859
  var EntryRefSchema = z.string().refine((v) => parseModelRef(v) !== void 0, { message: "expected @<model-entry-id>" });
@@ -14511,8 +16137,8 @@ var SettingsFileError = class extends Error {
14511
16137
  this.hint = hint;
14512
16138
  }
14513
16139
  };
14514
- function describeJsonError(err, text) {
14515
- const message = err instanceof Error ? err.message.split("\n")[0] ?? "" : "";
16140
+ function describeJsonError(err3, text) {
16141
+ const message = err3 instanceof Error ? err3.message.split("\n")[0] ?? "" : "";
14516
16142
  if (!message) return t("config_load.json_unknown_error");
14517
16143
  const at = /position (\d+)/.exec(message);
14518
16144
  if (!at?.[1]) return message;
@@ -14529,8 +16155,8 @@ function readSettingsFile(path, schema, known, empty, issues, sanitize = (raw) =
14529
16155
  let raw;
14530
16156
  try {
14531
16157
  raw = JSON.parse(text);
14532
- } catch (err) {
14533
- const reason9 = describeJsonError(err, text);
16158
+ } catch (err3) {
16159
+ const reason9 = describeJsonError(err3, text);
14534
16160
  issues.push({ path, message: t("config_load.json_invalid", { reason: reason9 }) });
14535
16161
  return { failed: reason9 };
14536
16162
  }
@@ -14968,13 +16594,13 @@ function readRawConfig(configPath2, issues) {
14968
16594
  const text = readFileSync(configPath2, "utf-8");
14969
16595
  if (text.trim() === "") return { kind: "ok", raw: {} };
14970
16596
  return { kind: "ok", raw: load(text) ?? {} };
14971
- } catch (err) {
16597
+ } catch (err3) {
14972
16598
  const backup = backupCorruptConfig(configPath2);
14973
16599
  issues.push({
14974
16600
  path: "(root)",
14975
16601
  message: t("config_load.bad_yaml", {
14976
16602
  path: configPath2,
14977
- reason: err.message.split("\n")[0] ?? "",
16603
+ reason: err3.message.split("\n")[0] ?? "",
14978
16604
  backup: backup ? t("config_load.bad_yaml_backup", { path: backup }) : t("config_load.bad_yaml_no_backup")
14979
16605
  })
14980
16606
  });
@@ -15254,16 +16880,16 @@ async function runImageProbe(model) {
15254
16880
  let withImage;
15255
16881
  try {
15256
16882
  withImage = await shoot(model, true);
15257
- } catch (err) {
15258
- return { verdict: "no", detail: err instanceof Error ? err.message : String(err) };
16883
+ } catch (err3) {
16884
+ return { verdict: "no", detail: err3 instanceof Error ? err3.message : String(err3) };
15259
16885
  }
15260
16886
  let baseline;
15261
16887
  try {
15262
16888
  baseline = await shoot(model, false);
15263
- } catch (err) {
16889
+ } catch (err3) {
15264
16890
  return {
15265
16891
  verdict: "inconclusive",
15266
- detail: `baseline failed: ${err instanceof Error ? err.message : String(err)}`
16892
+ detail: `baseline failed: ${err3 instanceof Error ? err3.message : String(err3)}`
15267
16893
  };
15268
16894
  }
15269
16895
  const shot = withImage.inputTokens;
@@ -15793,11 +17419,11 @@ var ProviderSdkMissingError = class extends Error {
15793
17419
  async function createModelFactory(type, opts) {
15794
17420
  try {
15795
17421
  return await LOADERS[type](opts);
15796
- } catch (err) {
15797
- if (isModuleNotFound(err)) {
15798
- throw new ProviderSdkMissingError(type, PACKAGES[type], err);
17422
+ } catch (err3) {
17423
+ if (isModuleNotFound(err3)) {
17424
+ throw new ProviderSdkMissingError(type, PACKAGES[type], err3);
15799
17425
  }
15800
- throw err;
17426
+ throw err3;
15801
17427
  }
15802
17428
  }
15803
17429
  async function createEntryFactory(entry, apiKey) {
@@ -15805,9 +17431,9 @@ async function createEntryFactory(entry, apiKey) {
15805
17431
  const pkg = type === "openai-compatible" && entry.protocol === "anthropic-messages" ? "@ai-sdk/anthropic" : PACKAGES[type];
15806
17432
  try {
15807
17433
  return await loadEntry(entry, apiKey);
15808
- } catch (err) {
15809
- if (isModuleNotFound(err)) throw new ProviderSdkMissingError(type, pkg, err);
15810
- throw err;
17434
+ } catch (err3) {
17435
+ if (isModuleNotFound(err3)) throw new ProviderSdkMissingError(type, pkg, err3);
17436
+ throw err3;
15811
17437
  }
15812
17438
  }
15813
17439
  async function loadEntry(entry, apiKey) {
@@ -15880,11 +17506,11 @@ var CARRIES_REASONING_BACK = {
15880
17506
  function carriesReasoningBack(type) {
15881
17507
  return CARRIES_REASONING_BACK[type];
15882
17508
  }
15883
- function isModuleNotFound(err) {
15884
- if (!err || typeof err !== "object") return false;
15885
- const code = err.code;
17509
+ function isModuleNotFound(err3) {
17510
+ if (!err3 || typeof err3 !== "object") return false;
17511
+ const code = err3.code;
15886
17512
  if (code === "ERR_MODULE_NOT_FOUND" || code === "MODULE_NOT_FOUND") return true;
15887
- const msg = err instanceof Error ? err.message : "";
17513
+ const msg = err3 instanceof Error ? err3.message : "";
15888
17514
  return /Cannot find (module|package)|Failed to resolve/i.test(msg);
15889
17515
  }
15890
17516
  // src/provider/entry-route.ts
@@ -16180,8 +17806,8 @@ var ProviderRouter = class {
16180
17806
  }
16181
17807
  if (this.effort !== void 0) {
16182
17808
  const state = this.getEffort();
16183
- const ok2 = this.effort === "off" ? state.canTurnOff : state.levels.includes(this.effort);
16184
- if (!ok2) this.effort = void 0;
17809
+ const ok4 = this.effort === "off" ? state.canTurnOff : state.levels.includes(this.effort);
17810
+ if (!ok4) this.effort = void 0;
16185
17811
  }
16186
17812
  }
16187
17813
  refreshedSelection(sel) {
@@ -16211,9 +17837,9 @@ var ProviderRouter = class {
16211
17837
  this.effort = void 0;
16212
17838
  return true;
16213
17839
  }
16214
- const ok2 = choice === "off" ? state.canTurnOff : state.levels.includes(choice);
16215
- if (ok2) this.effort = choice;
16216
- return ok2;
17840
+ const ok4 = choice === "off" ? state.canTurnOff : state.levels.includes(choice);
17841
+ if (ok4) this.effort = choice;
17842
+ return ok4;
16217
17843
  }
16218
17844
  reasoningFor(input, ct, entry) {
16219
17845
  if (input.entry || entry !== this.selection.entry) return void 0;
@@ -16314,8 +17940,8 @@ var ProviderRouter = class {
16314
17940
  let factory;
16315
17941
  try {
16316
17942
  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);
17943
+ } catch (err3) {
17944
+ throw new ProviderError(err3 instanceof Error ? err3.message : String(err3), 1005, false);
16319
17945
  }
16320
17946
  this.factories.set(route, factory);
16321
17947
  return factory(modelId ?? this.selection.model);
@@ -16344,9 +17970,9 @@ var ProviderRouter = class {
16344
17970
  const fb = this.fallbackEntry(sel.entry, /* @__PURE__ */ new Set([entryTried(sel.entry)]));
16345
17971
  return fb && !this.failures.isAbandoned(this.routeOf(fb.provider, fb.entry)) ? fb : sel;
16346
17972
  }
16347
- async recover(err, state) {
16348
- const { code, recovery } = classifyProviderError(err);
16349
- const message = describeProviderError(err);
17973
+ async recover(err3, state) {
17974
+ const { code, recovery } = classifyProviderError(err3);
17975
+ const message = describeProviderError(err3);
16350
17976
  const stay = { kind: "continue", ct: state.ct, cm: state.cm, entry: state.entry };
16351
17977
  if (code === PROVIDER_ABORTED) return { kind: "give-up", message, code };
16352
17978
  if (recovery === "retry") {
@@ -16471,8 +18097,8 @@ var ProviderRouter = class {
16471
18097
  ...applied === void 0 ? {} : { responseFormatApplied: applied },
16472
18098
  ...warnings ? { warnings } : {}
16473
18099
  };
16474
- } catch (err) {
16475
- const plan = await this.recover(err, state);
18100
+ } catch (err3) {
18101
+ const plan = await this.recover(err3, state);
16476
18102
  if (plan.kind === "give-up") throw new ProviderError(plan.message, plan.code, false);
16477
18103
  state.ct = plan.ct;
16478
18104
  state.cm = plan.cm;
@@ -16574,8 +18200,8 @@ var ProviderRouter = class {
16574
18200
  ...warnings ? { warnings } : {}
16575
18201
  };
16576
18202
  return;
16577
- } catch (err) {
16578
- const cause = streamPartError ?? err;
18203
+ } catch (err3) {
18204
+ const cause = streamPartError ?? err3;
16579
18205
  if (emitted) {
16580
18206
  yield { type: "error", error: describeProviderError(cause) };
16581
18207
  return;
@@ -16909,9 +18535,9 @@ async function testModelEntry(entry, apiKey) {
16909
18535
  abortSignal: AbortSignal.timeout(2e4)
16910
18536
  });
16911
18537
  return { code: "ok", models, latencyMs: elapsed() };
16912
- } catch (err) {
16913
- const status = extractStatus(err);
16914
- const detail = redact(describeProviderError(err), apiKey);
18538
+ } catch (err3) {
18539
+ const status = extractStatus(err3);
18540
+ const detail = redact(describeProviderError(err3), apiKey);
16915
18541
  return {
16916
18542
  code: classify(status, detail),
16917
18543
  models,
@@ -17179,9 +18805,9 @@ function commit(path, body2, createMode, value) {
17179
18805
  try {
17180
18806
  writeFileSync(tmp, body2, { encoding: "utf-8", mode });
17181
18807
  renameSync(tmp, path);
17182
- } catch (err) {
18808
+ } catch (err3) {
17183
18809
  rmSync(tmp, { force: true });
17184
- throw err;
18810
+ throw err3;
17185
18811
  }
17186
18812
  } catch {
17187
18813
  return { ok: false, reason: "io" };
@@ -17598,13 +19224,13 @@ function readRaw(path) {
17598
19224
  let text;
17599
19225
  try {
17600
19226
  text = readFileSync(path, "utf-8");
17601
- } catch (err) {
17602
- return { issue: reason5(err) };
19227
+ } catch (err3) {
19228
+ return { issue: reason5(err3) };
17603
19229
  }
17604
19230
  try {
17605
19231
  return { value: JSON.parse(text) };
17606
- } catch (err) {
17607
- return { issue: reason5(err) };
19232
+ } catch (err3) {
19233
+ return { issue: reason5(err3) };
17608
19234
  }
17609
19235
  }
17610
19236
  function readVimMode(raw, issues) {
@@ -17687,8 +19313,8 @@ function supportsSequence(action) {
17687
19313
  function warn(detail, code) {
17688
19314
  return { module: MODULE2, status: "warn", detail, code };
17689
19315
  }
17690
- function reason5(err) {
17691
- return (err instanceof Error ? err.message : String(err)).split("\n")[0] ?? "";
19316
+ function reason5(err3) {
19317
+ return (err3 instanceof Error ? err3.message : String(err3)).split("\n")[0] ?? "";
17692
19318
  }
17693
19319
  // src/memory/tokenize.ts
17694
19320
  var CJK_RUN = /[぀-ヿ㐀-䶿一-鿿豈-﫿가-힯]+/gu;
@@ -17732,7 +19358,7 @@ function buildSearchQuery(query) {
17732
19358
  // src/memory/db.ts
17733
19359
  var NS2 = "memory";
17734
19360
  var FTS_SCHEMA_VERSION = 2;
17735
- var MIGRATIONS2 = [
19361
+ var MIGRATIONS3 = [
17736
19362
  {
17737
19363
  id: "memory-baseline",
17738
19364
  version: 1,
@@ -17774,10 +19400,10 @@ var MemoryDB = class {
17774
19400
  db;
17775
19401
  path;
17776
19402
  nextPosition = { memory: 0, user: 0 };
17777
- constructor(dbPath) {
17778
- this.path = dbPath;
19403
+ constructor(dbPath2) {
19404
+ this.path = dbPath2;
17779
19405
  this.db = openDatabase(this.path);
17780
- migrate(this.db, NS2, MIGRATIONS2);
19406
+ migrate(this.db, NS2, MIGRATIONS3);
17781
19407
  this.migrateFts();
17782
19408
  for (const target of ["memory", "user"]) {
17783
19409
  const row = this.db.prepare(
@@ -18020,9 +19646,9 @@ function stripUndefined(obj) {
18020
19646
  return Object.fromEntries(Object.entries(obj).filter(([, v]) => v !== void 0));
18021
19647
  }
18022
19648
  var MemoryManager = class {
18023
- constructor(dbPath, memDir, config, options = {}) {
19649
+ constructor(dbPath2, memDir, config, options = {}) {
18024
19650
  this.options = options;
18025
- const dp = dbPath ?? DB_PATH;
19651
+ const dp = dbPath2 ?? DB_PATH;
18026
19652
  const md = memDir ?? MEM_DIR;
18027
19653
  this.memDir = md;
18028
19654
  mkdirSync(dirname(dp), { recursive: true });
@@ -18440,8 +20066,8 @@ var MemoryManager = class {
18440
20066
  });
18441
20067
  continue;
18442
20068
  }
18443
- const firstLine4 = (entry.content.split("\n")[0] ?? "").trim();
18444
- const summary = countCodePoints(firstLine4) > INDEX_SUMMARY_CHARS ? `${headCodePoints(firstLine4, INDEX_SUMMARY_CHARS)}\u2026` : firstLine4;
20069
+ const firstLine5 = (entry.content.split("\n")[0] ?? "").trim();
20070
+ const summary = countCodePoints(firstLine5) > INDEX_SUMMARY_CHARS ? `${headCodePoints(firstLine5, INDEX_SUMMARY_CHARS)}\u2026` : firstLine5;
18445
20071
  out.push({ id, target, summary, charLength: entry.content.length });
18446
20072
  }
18447
20073
  return out;
@@ -18768,7 +20394,7 @@ function nonEmpty(items) {
18768
20394
  function isRecord4(v) {
18769
20395
  return typeof v === "object" && v !== null;
18770
20396
  }
18771
- function str3(v) {
20397
+ function str5(v) {
18772
20398
  return typeof v === "string" && v.length > 0 ? v : void 0;
18773
20399
  }
18774
20400
  function isSessionOmitReason(value) {
@@ -18780,8 +20406,8 @@ function parseToolCalls(json) {
18780
20406
  const calls = [];
18781
20407
  for (const item of raw) {
18782
20408
  if (!isRecord4(item)) continue;
18783
- const toolCallId = str3(item["toolCallId"]) ?? str3(item["id"]);
18784
- const toolName = str3(item["toolName"]) ?? str3(item["name"]);
20409
+ const toolCallId = str5(item["toolCallId"]) ?? str5(item["id"]);
20410
+ const toolName = str5(item["toolName"]) ?? str5(item["name"]);
18785
20411
  if (!toolCallId || !toolName) continue;
18786
20412
  const input = item["input"] ?? item["args"];
18787
20413
  calls.push({ toolCallId, toolName, input: isRecord4(input) ? input : {} });
@@ -18796,10 +20422,10 @@ function parseArtifacts(raw) {
18796
20422
  const kind = item["kind"];
18797
20423
  out.push({
18798
20424
  kind: kind === "image" || kind === "audio" || kind === "file" ? kind : "file",
18799
- mediaType: str3(item["mediaType"]) ?? "application/octet-stream",
20425
+ mediaType: str5(item["mediaType"]) ?? "application/octet-stream",
18800
20426
  summary: typeof item["summary"] === "string" ? item["summary"] : "",
18801
20427
  bytes: typeof item["bytes"] === "number" ? item["bytes"] : 0,
18802
- ...str3(item["path"]) ? { path: item["path"] } : {},
20428
+ ...str5(item["path"]) ? { path: item["path"] } : {},
18803
20429
  ...typeof item["width"] === "number" ? { width: item["width"] } : {},
18804
20430
  ...typeof item["height"] === "number" ? { height: item["height"] } : {},
18805
20431
  ...typeof item["estimatedTokens"] === "number" ? { estimatedTokens: item["estimatedTokens"] } : {}
@@ -18813,8 +20439,8 @@ function parseToolResults(json) {
18813
20439
  const results = [];
18814
20440
  for (const item of raw) {
18815
20441
  if (!isRecord4(item)) continue;
18816
- const toolCallId = str3(item["toolCallId"]);
18817
- const toolName = str3(item["toolName"]);
20442
+ const toolCallId = str5(item["toolCallId"]);
20443
+ const toolName = str5(item["toolName"]);
18818
20444
  if (!toolCallId || !toolName) continue;
18819
20445
  const artifacts = parseArtifacts(item["artifacts"]);
18820
20446
  results.push({
@@ -18826,24 +20452,41 @@ function parseToolResults(json) {
18826
20452
  }
18827
20453
  return nonEmpty(results);
18828
20454
  }
20455
+ function parseDiffs(json) {
20456
+ const raw = parseArray(json);
20457
+ if (!raw) return void 0;
20458
+ const diffs = [];
20459
+ for (const item of raw) {
20460
+ if (!isRecord4(item)) continue;
20461
+ const filePath = str5(item["filePath"]);
20462
+ if (!filePath) continue;
20463
+ diffs.push({
20464
+ filePath,
20465
+ ...typeof item["oldContent"] === "string" ? { oldContent: item["oldContent"] } : {},
20466
+ ...typeof item["newContent"] === "string" ? { newContent: item["newContent"] } : {},
20467
+ ...item["omitted"] === "too-large" ? { omitted: "too-large" } : {}
20468
+ });
20469
+ }
20470
+ return nonEmpty(diffs);
20471
+ }
18829
20472
  function parseParts(json) {
18830
20473
  const raw = parseArray(json);
18831
20474
  if (!raw) return void 0;
18832
20475
  const parts = [];
18833
20476
  for (const item of raw) {
18834
20477
  if (!isRecord4(item)) continue;
18835
- const mediaType = str3(item["mediaType"]);
20478
+ const mediaType = str5(item["mediaType"]);
18836
20479
  const media = mediaType ? { mediaType } : {};
18837
20480
  if (item["type"] === "text") {
18838
20481
  if (typeof item["text"] === "string") parts.push({ type: "text", text: item["text"] });
18839
20482
  continue;
18840
20483
  }
18841
20484
  if (item["type"] === "session") {
18842
- const ref = str3(item["ref"]);
20485
+ const ref = str5(item["ref"]);
18843
20486
  if (!ref) continue;
18844
- const sessionId = str3(item["sessionId"]);
18845
- const title = str3(item["title"]);
18846
- const omitted = str3(item["omitted"]);
20487
+ const sessionId = str5(item["sessionId"]);
20488
+ const title = str5(item["title"]);
20489
+ const omitted = str5(item["omitted"]);
18847
20490
  parts.push({
18848
20491
  type: "session",
18849
20492
  ref,
@@ -18856,9 +20499,9 @@ function parseParts(json) {
18856
20499
  continue;
18857
20500
  }
18858
20501
  if (item["type"] === "file") {
18859
- const filePath = str3(item["path"]);
20502
+ const filePath = str5(item["path"]);
18860
20503
  if (!filePath) continue;
18861
- const fileOmitted = str3(item["omitted"]);
20504
+ const fileOmitted = str5(item["omitted"]);
18862
20505
  parts.push({
18863
20506
  type: "file",
18864
20507
  path: filePath,
@@ -18868,8 +20511,8 @@ function parseParts(json) {
18868
20511
  continue;
18869
20512
  }
18870
20513
  if (item["type"] !== "image") continue;
18871
- const path = str3(item["path"]);
18872
- const url = str3(item["url"]);
20514
+ const path = str5(item["path"]);
20515
+ const url = str5(item["url"]);
18873
20516
  if (path) parts.push({ type: "image", path, ...media });
18874
20517
  else if (url) parts.push({ type: "image", url, ...media });
18875
20518
  }
@@ -18916,10 +20559,10 @@ function parseTurnFacts(json) {
18916
20559
  const toolCalls = num2(raw["toolCalls"]);
18917
20560
  if (toolCalls === void 0) return void 0;
18918
20561
  const usage = parseUsage(raw["usage"]);
18919
- const model = str3(raw["model"]);
18920
- const requestedModel = str3(raw["requestedModel"]);
20562
+ const model = str5(raw["model"]);
20563
+ const requestedModel = str5(raw["requestedModel"]);
18921
20564
  const durationMs = num2(raw["durationMs"]);
18922
- const error = str3(raw["error"])?.trim() || void 0;
20565
+ const error = str5(raw["error"])?.trim() || void 0;
18923
20566
  return {
18924
20567
  toolCalls,
18925
20568
  ...usage ? { usage } : {},
@@ -18941,10 +20584,10 @@ function parseUserCommand(json) {
18941
20584
  return void 0;
18942
20585
  }
18943
20586
  if (!isRecord4(raw)) return void 0;
18944
- const name = str3(raw["name"]);
20587
+ const name = str5(raw["name"]);
18945
20588
  if (!name) return void 0;
18946
- const displayName = str3(raw["displayName"]);
18947
- const args = str3(raw["args"]);
20589
+ const displayName = str5(raw["displayName"]);
20590
+ const args = str5(raw["args"]);
18948
20591
  return {
18949
20592
  name,
18950
20593
  ...displayName ? { displayName } : {},
@@ -19269,13 +20912,21 @@ var FTS_EXTERNAL_MIGRATIONS = [
19269
20912
  up: (db) => {
19270
20913
  db.exec(`ALTER TABLE messages ADD COLUMN command TEXT`);
19271
20914
  }
20915
+ },
20916
+ {
20917
+ id: "messages-diffs",
20918
+ version: 17,
20919
+ description: "\u6D88\u606F\u8868\u52A0 diffs \u4E00\u5217\uFF08\u8865\u4E01\u9884\u89C8\u843D\u76D8\uFF0C2026-10-30\uFF09",
20920
+ up: (db) => {
20921
+ db.exec(`ALTER TABLE messages ADD COLUMN diffs TEXT`);
20922
+ }
19272
20923
  }
19273
20924
  ];
19274
20925
  var SessionDB = class {
19275
20926
  db;
19276
20927
  path;
19277
- constructor(dbPath$1) {
19278
- this.path = dbPath$1 ?? dbPath();
20928
+ constructor(dbPath2) {
20929
+ this.path = dbPath2 ?? dbPath();
19279
20930
  this.db = openDatabase(this.path);
19280
20931
  migrate(this.db, NS3, SESSION_MIGRATIONS);
19281
20932
  this.migrateFtsIndex();
@@ -19283,10 +20934,10 @@ var SessionDB = class {
19283
20934
  migrateFtsIndex() {
19284
20935
  try {
19285
20936
  migrate(this.db, NS3, FTS_EXTERNAL_MIGRATIONS);
19286
- } catch (err) {
20937
+ } catch (err3) {
19287
20938
  log2.warn(
19288
20939
  "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) }
20940
+ { error: err3 instanceof Error ? err3.message : String(err3) }
19290
20941
  );
19291
20942
  }
19292
20943
  }
@@ -19466,8 +21117,8 @@ var SessionDB = class {
19466
21117
  insertMessage(msg) {
19467
21118
  const info = this.db.prepare(
19468
21119
  `
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)
21120
+ 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)
21121
+ VALUES (@sessionId, @role, @content, @toolCallId, @toolCalls, @toolResults, @parts, @command, @toolName, @timestamp, @tokenCount, @finishReason, @reasoning, @diffs, @turnFacts, 1, 0, 0)
19471
21122
  `
19472
21123
  ).run({
19473
21124
  ...msg,
@@ -19480,6 +21131,7 @@ var SessionDB = class {
19480
21131
  tokenCount: msg.tokenCount ?? null,
19481
21132
  finishReason: msg.finishReason ?? null,
19482
21133
  reasoning: msg.reasoning ?? null,
21134
+ diffs: encodeColumn(msg.diffs),
19483
21135
  turnFacts: encodeTurnFacts(msg.turnFacts)
19484
21136
  });
19485
21137
  const toolCalls = msg.toolCalls?.length ?? 0;
@@ -19729,8 +21381,8 @@ var SessionDB = class {
19729
21381
  forkMessages(fromSessionId, toSessionId, upToIndex) {
19730
21382
  const messages = this.db.prepare("SELECT * FROM messages WHERE session_id = ? AND id <= ? ORDER BY timestamp ASC").all(fromSessionId, upToIndex);
19731
21383
  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)
21384
+ 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)
21385
+ VALUES (@sessionId, @role, @content, @toolCallId, @toolCalls, @toolResults, @parts, @command, @toolName, @timestamp, @tokenCount, @finishReason, @reasoning, @diffs, @turnFacts, @active, @compacted, @observed)
19734
21386
  `);
19735
21387
  for (const m of messages) {
19736
21388
  const { id: _id, ...rest } = m;
@@ -19748,6 +21400,7 @@ var SessionDB = class {
19748
21400
  tokenCount: rest["token_count"] ?? null,
19749
21401
  finishReason: rest["finish_reason"] ?? null,
19750
21402
  reasoning: rest["reasoning"] ?? null,
21403
+ diffs: rest["diffs"] ?? null,
19751
21404
  turnFacts: rest["turn_facts"] ?? null,
19752
21405
  active: rest["active"] ?? 1,
19753
21406
  compacted: rest["compacted"] ?? 0,
@@ -19831,6 +21484,7 @@ var SessionDB = class {
19831
21484
  tokenCount: row["token_count"],
19832
21485
  finishReason: row["finish_reason"],
19833
21486
  reasoning: row["reasoning"],
21487
+ diffs: parseDiffs(row["diffs"]),
19834
21488
  active: row["active"] === 1,
19835
21489
  compacted: row["compacted"] === 1,
19836
21490
  observed: row["observed"] === 1
@@ -19865,8 +21519,8 @@ function integrityOf(db, table, compareContent = false) {
19865
21519
  db.prepare(`INSERT INTO ${table}(${table}) VALUES('integrity-check')`).run();
19866
21520
  }
19867
21521
  return null;
19868
- } catch (err) {
19869
- return err instanceof Error ? err.message : String(err);
21522
+ } catch (err3) {
21523
+ return err3 instanceof Error ? err3.message : String(err3);
19870
21524
  }
19871
21525
  }
19872
21526
  function indexBytesOf(db) {
@@ -19942,8 +21596,8 @@ function reclaimFtsSpace(db, vacuum = true) {
19942
21596
  if (vacuum) {
19943
21597
  try {
19944
21598
  db.exec("VACUUM");
19945
- } catch (err) {
19946
- vacuumError = err instanceof Error ? err.message : String(err);
21599
+ } catch (err3) {
21600
+ vacuumError = err3 instanceof Error ? err3.message : String(err3);
19947
21601
  }
19948
21602
  }
19949
21603
  const vacuumed = vacuum && vacuumError === null;
@@ -20153,8 +21807,8 @@ var SessionManager = class {
20153
21807
  queries;
20154
21808
  goals;
20155
21809
  references;
20156
- constructor(dbPath) {
20157
- this.db = new SessionDB(dbPath);
21810
+ constructor(dbPath2) {
21811
+ this.db = new SessionDB(dbPath2);
20158
21812
  this.queries = new SessionQueries(this.db.db);
20159
21813
  this.goals = new GoalStore(this.db.db);
20160
21814
  this.references = new SessionReferences(this.db.db);
@@ -20286,12 +21940,12 @@ var SessionManager = class {
20286
21940
  ...input.todos === void 0 ? {} : { todoIds: todos.map((t83) => t83.id) },
20287
21941
  ...goal === void 0 ? {} : { goalId: goal.id }
20288
21942
  };
20289
- } catch (err) {
21943
+ } catch (err3) {
20290
21944
  return {
20291
21945
  ok: false,
20292
21946
  id,
20293
21947
  reason: "failed",
20294
- ...err instanceof Error ? { detail: err.name } : {}
21948
+ ...err3 instanceof Error ? { detail: err3.name } : {}
20295
21949
  };
20296
21950
  }
20297
21951
  }
@@ -20869,8 +22523,8 @@ function inspect(input, resolved, root, accepted) {
20869
22523
  }
20870
22524
  var MAX_RECENT_WORKSPACES = 20;
20871
22525
  var FILE_VERSION2 = 1;
20872
- function describe7(err) {
20873
- return err instanceof Error ? err.message : String(err);
22526
+ function describe7(err3) {
22527
+ return err3 instanceof Error ? err3.message : String(err3);
20874
22528
  }
20875
22529
  var RecentWorkspaces = class {
20876
22530
  constructor(filePath = workspacesPath()) {
@@ -20907,9 +22561,9 @@ var RecentWorkspaces = class {
20907
22561
  let parsed;
20908
22562
  try {
20909
22563
  parsed = JSON.parse(readFileSync(this.filePath, "utf-8"));
20910
- } catch (err) {
22564
+ } catch (err3) {
20911
22565
  this.loadErrors.push(
20912
- (lang) => t("workspace.recent_unreadable", { path: this.filePath, reason: describe7(err) }, lang)
22566
+ (lang) => t("workspace.recent_unreadable", { path: this.filePath, reason: describe7(err3) }, lang)
20913
22567
  );
20914
22568
  return;
20915
22569
  }
@@ -20959,10 +22613,10 @@ var RecentWorkspaces = class {
20959
22613
  mkdirSync(dirname(this.filePath), { recursive: true });
20960
22614
  writeFileSync(tmp, body2, { encoding: "utf-8", mode: 384 });
20961
22615
  renameSync(tmp, this.filePath);
20962
- } catch (err) {
22616
+ } catch (err3) {
20963
22617
  rmSync(tmp, { force: true });
20964
22618
  this.writeErrors.push(
20965
- (lang) => t("workspace.recent_write_failed", { path: this.filePath, reason: describe7(err) }, lang)
22619
+ (lang) => t("workspace.recent_write_failed", { path: this.filePath, reason: describe7(err3) }, lang)
20966
22620
  );
20967
22621
  }
20968
22622
  }
@@ -20974,8 +22628,8 @@ function isRecentWorkspace(value) {
20974
22628
  }
20975
22629
  var MAX_LAST_OPEN_SESSIONS = 20;
20976
22630
  var FILE_VERSION3 = 1;
20977
- function describe8(err) {
20978
- return err instanceof Error ? err.message : String(err);
22631
+ function describe8(err3) {
22632
+ return err3 instanceof Error ? err3.message : String(err3);
20979
22633
  }
20980
22634
  var LastOpenSessions = class {
20981
22635
  constructor(filePath = lastSessionsPath()) {
@@ -21011,9 +22665,9 @@ var LastOpenSessions = class {
21011
22665
  let parsed;
21012
22666
  try {
21013
22667
  parsed = JSON.parse(readFileSync(this.filePath, "utf-8"));
21014
- } catch (err) {
22668
+ } catch (err3) {
21015
22669
  this.loadErrors.push(
21016
- (lang) => t("last_session.unreadable", { path: this.filePath, reason: describe8(err) }, lang)
22670
+ (lang) => t("last_session.unreadable", { path: this.filePath, reason: describe8(err3) }, lang)
21017
22671
  );
21018
22672
  return;
21019
22673
  }
@@ -21037,10 +22691,10 @@ var LastOpenSessions = class {
21037
22691
  mkdirSync(dirname(this.filePath), { recursive: true });
21038
22692
  writeFileSync(tmp, body2, { encoding: "utf-8", mode: 384 });
21039
22693
  renameSync(tmp, this.filePath);
21040
- } catch (err) {
22694
+ } catch (err3) {
21041
22695
  rmSync(tmp, { force: true });
21042
22696
  this.writeErrors.push(
21043
- (lang) => t("last_session.write_failed", { path: this.filePath, reason: describe8(err) }, lang)
22697
+ (lang) => t("last_session.write_failed", { path: this.filePath, reason: describe8(err3) }, lang)
21044
22698
  );
21045
22699
  }
21046
22700
  }
@@ -21053,8 +22707,8 @@ function isLastOpenSession(value) {
21053
22707
  var isWidthShaped = (value) => typeof value === "number" && Number.isInteger(value) && value > 0;
21054
22708
  var FILE_VERSION4 = 2;
21055
22709
  var isPlainObject2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
21056
- function describe9(err) {
21057
- return err instanceof Error ? err.message : String(err);
22710
+ function describe9(err3) {
22711
+ return err3 instanceof Error ? err3.message : String(err3);
21058
22712
  }
21059
22713
  var AppearanceStore = class {
21060
22714
  constructor(filePath = appearancePath()) {
@@ -21109,9 +22763,9 @@ var AppearanceStore = class {
21109
22763
  this.prefs = {};
21110
22764
  try {
21111
22765
  rmSync(this.filePath, { force: true });
21112
- } catch (err) {
22766
+ } catch (err3) {
21113
22767
  this.writeErrors.push(
21114
- (lang) => t("appearance.write_failed", { path: this.filePath, reason: describe9(err) }, lang)
22768
+ (lang) => t("appearance.write_failed", { path: this.filePath, reason: describe9(err3) }, lang)
21115
22769
  );
21116
22770
  }
21117
22771
  }
@@ -21121,9 +22775,9 @@ var AppearanceStore = class {
21121
22775
  let parsed;
21122
22776
  try {
21123
22777
  parsed = JSON.parse(readFileSync(this.filePath, "utf-8"));
21124
- } catch (err) {
22778
+ } catch (err3) {
21125
22779
  this.loadErrors.push(
21126
- (lang) => t("appearance.unreadable", { path: this.filePath, reason: describe9(err) }, lang)
22780
+ (lang) => t("appearance.unreadable", { path: this.filePath, reason: describe9(err3) }, lang)
21127
22781
  );
21128
22782
  return;
21129
22783
  }
@@ -21172,10 +22826,10 @@ var AppearanceStore = class {
21172
22826
  mkdirSync(dirname(this.filePath), { recursive: true });
21173
22827
  writeFileSync(tmp, body2, { encoding: "utf-8", mode: 384 });
21174
22828
  renameSync(tmp, this.filePath);
21175
- } catch (err) {
22829
+ } catch (err3) {
21176
22830
  rmSync(tmp, { force: true });
21177
22831
  this.writeErrors.push(
21178
- (lang) => t("appearance.write_failed", { path: this.filePath, reason: describe9(err) }, lang)
22832
+ (lang) => t("appearance.write_failed", { path: this.filePath, reason: describe9(err3) }, lang)
21179
22833
  );
21180
22834
  }
21181
22835
  }
@@ -21931,7 +23585,7 @@ function suggestRuleFromApproval(request) {
21931
23585
  // src/schedule/store.ts
21932
23586
  init_trigger();
21933
23587
  var NS4 = "schedule";
21934
- var MIGRATIONS3 = [
23588
+ var MIGRATIONS4 = [
21935
23589
  {
21936
23590
  id: "schedule-baseline",
21937
23591
  version: 1,
@@ -22018,10 +23672,10 @@ var MIGRATIONS3 = [
22018
23672
  var ScheduleStore = class {
22019
23673
  db;
22020
23674
  path;
22021
- constructor(dbPath) {
22022
- this.path = dbPath;
23675
+ constructor(dbPath2) {
23676
+ this.path = dbPath2;
22023
23677
  this.db = openDatabase(this.path);
22024
- migrate(this.db, NS4, MIGRATIONS3);
23678
+ migrate(this.db, NS4, MIGRATIONS4);
22025
23679
  }
22026
23680
  get connection() {
22027
23681
  return this.db;
@@ -22399,8 +24053,8 @@ function pidAlive(pid) {
22399
24053
  try {
22400
24054
  process.kill(pid, 0);
22401
24055
  return true;
22402
- } catch (err) {
22403
- return err.code === "EPERM";
24056
+ } catch (err3) {
24057
+ return err3.code === "EPERM";
22404
24058
  }
22405
24059
  }
22406
24060
  function acquireScheduleLock(db, scheduleId, clock2 = Date.now) {
@@ -22430,8 +24084,8 @@ function acquireScheduleLock(db, scheduleId, clock2 = Date.now) {
22430
24084
  db.prepare(
22431
24085
  "UPDATE schedule_locks SET heartbeat_at = ? WHERE schedule_id = ? AND pid = ? AND host = ?"
22432
24086
  ).run(clock2(), scheduleId, pid, host);
22433
- } catch (err) {
22434
- log4.debug("lock heartbeat write failed", { scheduleId, err: String(err) });
24087
+ } catch (err3) {
24088
+ log4.debug("lock heartbeat write failed", { scheduleId, err: String(err3) });
22435
24089
  }
22436
24090
  }, LOCK_HEARTBEAT_MS);
22437
24091
  beat.unref?.();
@@ -22447,8 +24101,8 @@ function acquireScheduleLock(db, scheduleId, clock2 = Date.now) {
22447
24101
  db.prepare(
22448
24102
  "DELETE FROM schedule_locks WHERE schedule_id = ? AND pid = ? AND host = ?"
22449
24103
  ).run(scheduleId, pid, host);
22450
- } catch (err) {
22451
- log4.debug("lock release failed", { scheduleId, err: String(err) });
24104
+ } catch (err3) {
24105
+ log4.debug("lock release failed", { scheduleId, err: String(err3) });
22452
24106
  }
22453
24107
  }
22454
24108
  }
@@ -22878,10 +24532,10 @@ function loadPolicyRules(dir) {
22878
24532
  let files;
22879
24533
  try {
22880
24534
  files = readdirSync(dir).filter((f) => f.endsWith(".toml"));
22881
- } catch (err) {
24535
+ } catch (err3) {
22882
24536
  return {
22883
24537
  rules: [],
22884
- issues: [{ path: dir, message: t("policy_load.dir_read_failed", { reason: reason6(err) }) }]
24538
+ issues: [{ path: dir, message: t("policy_load.dir_read_failed", { reason: reason6(err3) }) }]
22885
24539
  };
22886
24540
  }
22887
24541
  const rules = [];
@@ -22890,10 +24544,10 @@ function loadPolicyRules(dir) {
22890
24544
  let content;
22891
24545
  try {
22892
24546
  content = readFileSync(join(dir, file), "utf-8");
22893
- } catch (err) {
24547
+ } catch (err3) {
22894
24548
  issues.push({
22895
24549
  path: file,
22896
- message: t("policy_load.file_read_failed", { reason: reason6(err) })
24550
+ message: t("policy_load.file_read_failed", { reason: reason6(err3) })
22897
24551
  });
22898
24552
  continue;
22899
24553
  }
@@ -23016,8 +24670,8 @@ function unescapeTomlString(s) {
23016
24670
  function preview2(line) {
23017
24671
  return line.length > 40 ? `${line.slice(0, 40)}\u2026` : line;
23018
24672
  }
23019
- function reason6(err) {
23020
- return err instanceof Error ? err.message : String(err);
24673
+ function reason6(err3) {
24674
+ return err3 instanceof Error ? err3.message : String(err3);
23021
24675
  }
23022
24676
  var MODULE3 = "Policy";
23023
24677
  function resolvePolicyDirs(opts) {
@@ -23738,12 +25392,12 @@ function loadLexiconDir(dir, source) {
23738
25392
  let files;
23739
25393
  try {
23740
25394
  files = readdirSync(dir).filter((f) => f.endsWith(".txt"));
23741
- } catch (err) {
25395
+ } catch (err3) {
23742
25396
  return {
23743
25397
  rules: [],
23744
25398
  exempt: [],
23745
25399
  issues: [
23746
- { path: dir, message: t("compliance_load.dir_read_failed", { reason: reason7(err) }) }
25400
+ { path: dir, message: t("compliance_load.dir_read_failed", { reason: reason7(err3) }) }
23747
25401
  ]
23748
25402
  };
23749
25403
  }
@@ -23762,10 +25416,10 @@ function loadLexiconDir(dir, source) {
23762
25416
  let content;
23763
25417
  try {
23764
25418
  content = readFileSync(join(dir, file), "utf-8");
23765
- } catch (err) {
25419
+ } catch (err3) {
23766
25420
  out.issues.push({
23767
25421
  path: file,
23768
- message: t("compliance_load.file_read_failed", { reason: reason7(err) })
25422
+ message: t("compliance_load.file_read_failed", { reason: reason7(err3) })
23769
25423
  });
23770
25424
  continue;
23771
25425
  }
@@ -23812,12 +25466,12 @@ function regexError(pattern) {
23812
25466
  try {
23813
25467
  new RegExp(pattern, "gu");
23814
25468
  return void 0;
23815
- } catch (err) {
23816
- return reason7(err);
25469
+ } catch (err3) {
25470
+ return reason7(err3);
23817
25471
  }
23818
25472
  }
23819
- function reason7(err) {
23820
- return err instanceof Error ? err.message : String(err);
25473
+ function reason7(err3) {
25474
+ return err3 instanceof Error ? err3.message : String(err3);
23821
25475
  }
23822
25476
  var MODULE4 = "Compliance";
23823
25477
  function resolveComplianceDirs(opts) {
@@ -23887,7 +25541,7 @@ function runCommandHook(config, event, workDir) {
23887
25541
  let stdout = "";
23888
25542
  let stderr = "";
23889
25543
  let settled = false;
23890
- const failToStart = (err) => {
25544
+ const failToStart = (err3) => {
23891
25545
  if (settled) return;
23892
25546
  settled = true;
23893
25547
  resolve17({
@@ -23895,7 +25549,7 @@ function runCommandHook(config, event, workDir) {
23895
25549
  stdout,
23896
25550
  stderr,
23897
25551
  blocked: false,
23898
- rejectReason: t("hook_load.spawn_failed", { message: err.message }),
25552
+ rejectReason: t("hook_load.spawn_failed", { message: err3.message }),
23899
25553
  sandbox
23900
25554
  });
23901
25555
  };
@@ -23971,9 +25625,9 @@ function runCommandHook(config, event, workDir) {
23971
25625
  ...failure ? { failure } : {}
23972
25626
  });
23973
25627
  });
23974
- child.on("error", (err) => {
25628
+ child.on("error", (err3) => {
23975
25629
  clearTimeout(timer);
23976
- failToStart(err);
25630
+ failToStart(err3);
23977
25631
  });
23978
25632
  const input = JSON.stringify({
23979
25633
  session_id: event.sessionId,
@@ -24079,8 +25733,8 @@ var HookManager = class {
24079
25733
  if (result.blocked) {
24080
25734
  return { blocked: true, reason: result.rejectReason || t("hook_load.rejected") };
24081
25735
  }
24082
- } catch (err) {
24083
- this.log("warn", `[HookManager] ${type} \u7684 command hook \u6267\u884C\u5F02\u5E38: ${describe12(err)}`, {
25736
+ } catch (err3) {
25737
+ this.log("warn", `[HookManager] ${type} \u7684 command hook \u6267\u884C\u5F02\u5E38: ${describe12(err3)}`, {
24084
25738
  hookType: type,
24085
25739
  command: config.command
24086
25740
  });
@@ -24097,8 +25751,8 @@ var HookManager = class {
24097
25751
  new Promise(
24098
25752
  (_, reject2) => setTimeout(() => reject2(new Error("Hook timeout")), HOOK_TIMEOUT_MS)
24099
25753
  )
24100
- ]).catch((err) => {
24101
- this.log("warn", `[HookManager] ${type} (${reg.plugin}) \u5931\u8D25: ${describe12(err)}`, {
25754
+ ]).catch((err3) => {
25755
+ this.log("warn", `[HookManager] ${type} (${reg.plugin}) \u5931\u8D25: ${describe12(err3)}`, {
24102
25756
  hookType: type,
24103
25757
  plugin: reg.plugin
24104
25758
  });
@@ -24109,8 +25763,8 @@ var HookManager = class {
24109
25763
  for (const entry of cmdEntries) {
24110
25764
  if (!matchesHook(entry.matcher, event)) continue;
24111
25765
  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)}`, {
25766
+ runCommandHook(config, event, ctx.workDir).then((result) => reportIfNotRun(this.log, type, config, result)).catch((err3) => {
25767
+ this.log("warn", `[HookManager] ${type} \u7684 command hook \u5F02\u6B65\u5F02\u5E38: ${describe12(err3)}`, {
24114
25768
  hookType: type,
24115
25769
  command: config.command
24116
25770
  });
@@ -24130,8 +25784,8 @@ var HookManager = class {
24130
25784
  )
24131
25785
  ]);
24132
25786
  if (result !== null && result !== void 0) return result;
24133
- } catch (err) {
24134
- this.log("warn", `[HookManager] ${type} (${reg.plugin}) \u5931\u8D25: ${describe12(err)}`, {
25787
+ } catch (err3) {
25788
+ this.log("warn", `[HookManager] ${type} (${reg.plugin}) \u5931\u8D25: ${describe12(err3)}`, {
24135
25789
  hookType: type,
24136
25790
  plugin: reg.plugin
24137
25791
  });
@@ -24151,8 +25805,8 @@ var HookManager = class {
24151
25805
  )
24152
25806
  ]);
24153
25807
  if (result) results.push(result);
24154
- } catch (err) {
24155
- this.log("warn", `[HookManager] ${type} (${reg.plugin}) \u5931\u8D25: ${describe12(err)}`, {
25808
+ } catch (err3) {
25809
+ this.log("warn", `[HookManager] ${type} (${reg.plugin}) \u5931\u8D25: ${describe12(err3)}`, {
24156
25810
  hookType: type,
24157
25811
  plugin: reg.plugin
24158
25812
  });
@@ -24168,8 +25822,8 @@ var HookManager = class {
24168
25822
  reportIfNotRun(this.log, type, config, result);
24169
25823
  const verdict = verdictOf2(result);
24170
25824
  if (verdict) results.push(verdict);
24171
- } catch (err) {
24172
- this.log("warn", `[HookManager] ${type} \u7684 command hook \u6267\u884C\u5F02\u5E38: ${describe12(err)}`, {
25825
+ } catch (err3) {
25826
+ this.log("warn", `[HookManager] ${type} \u7684 command hook \u6267\u884C\u5F02\u5E38: ${describe12(err3)}`, {
24173
25827
  hookType: type,
24174
25828
  command: config.command
24175
25829
  });
@@ -24185,8 +25839,8 @@ var HookManager = class {
24185
25839
  return [...list].sort((a, b) => a.priority - b.priority);
24186
25840
  }
24187
25841
  };
24188
- function describe12(err) {
24189
- return err instanceof Error ? err.message : String(err);
25842
+ function describe12(err3) {
25843
+ return err3 instanceof Error ? err3.message : String(err3);
24190
25844
  }
24191
25845
  function verdictOf2(result) {
24192
25846
  const action = result.output?.["action"];
@@ -24738,8 +26392,8 @@ function readHooksFile(path, issues, opts = {}) {
24738
26392
  let raw;
24739
26393
  try {
24740
26394
  raw = JSON.parse(readFileSync(path, "utf-8"));
24741
- } catch (err) {
24742
- const reason9 = err.message.split("\n")[0] ?? t("hook_load.unknown_error");
26395
+ } catch (err3) {
26396
+ const reason9 = err3.message.split("\n")[0] ?? t("hook_load.unknown_error");
24743
26397
  issues.push({ path, message: t("hook_load.bad_json", { reason: reason9 }) });
24744
26398
  return void 0;
24745
26399
  }
@@ -24954,8 +26608,8 @@ function readEntries2(dir, label, issues, lang) {
24954
26608
  isDir: e.isDirectory(),
24955
26609
  isFile: e.isFile()
24956
26610
  }));
24957
- } catch (err) {
24958
- const reason9 = err instanceof Error ? err.message : String(err);
26611
+ } catch (err3) {
26612
+ const reason9 = err3 instanceof Error ? err3.message : String(err3);
24959
26613
  issues.push({ path: label, message: t("skill.import_read_failed", { reason: reason9 }, lang) });
24960
26614
  return [];
24961
26615
  }
@@ -25070,10 +26724,10 @@ function scanOneDir(spec, skills, issues) {
25070
26724
  let categories;
25071
26725
  try {
25072
26726
  categories = readdirSync(spec.dir, { withFileTypes: true });
25073
- } catch (err) {
26727
+ } catch (err3) {
25074
26728
  issues.push({
25075
26729
  path: spec.dir,
25076
- message: t("skill_load.dir_read_failed", { reason: reason8(err) })
26730
+ message: t("skill_load.dir_read_failed", { reason: reason8(err3) })
25077
26731
  });
25078
26732
  return;
25079
26733
  }
@@ -25083,10 +26737,10 @@ function scanOneDir(spec, skills, issues) {
25083
26737
  let entries2;
25084
26738
  try {
25085
26739
  entries2 = readdirSync(catPath, { withFileTypes: true });
25086
- } catch (err) {
26740
+ } catch (err3) {
25087
26741
  issues.push({
25088
26742
  path: cat.name,
25089
- message: t("skill_load.category_read_failed", { reason: reason8(err) })
26743
+ message: t("skill_load.category_read_failed", { reason: reason8(err3) })
25090
26744
  });
25091
26745
  continue;
25092
26746
  }
@@ -25106,8 +26760,8 @@ function loadOne(mdFile, catPath, category, dirName, spec, skills, issues) {
25106
26760
  try {
25107
26761
  raw = readFileSync(mdFile, "utf-8");
25108
26762
  stat5 = statSync(mdFile);
25109
- } catch (err) {
25110
- issues.push({ path: label, message: t("skill_load.read_failed", { reason: reason8(err) }) });
26763
+ } catch (err3) {
26764
+ issues.push({ path: label, message: t("skill_load.read_failed", { reason: reason8(err3) }) });
25111
26765
  return;
25112
26766
  }
25113
26767
  const parsed = parseSkillFrontmatter(raw, label);
@@ -25144,8 +26798,8 @@ function loadOne(mdFile, catPath, category, dirName, spec, skills, issues) {
25144
26798
  source: "manual"
25145
26799
  });
25146
26800
  }
25147
- function reason8(err) {
25148
- return err instanceof Error ? err.message : String(err);
26801
+ function reason8(err3) {
26802
+ return err3 instanceof Error ? err3.message : String(err3);
25149
26803
  }
25150
26804
  // src/skill/manager.ts
25151
26805
  var SKILLS_DIR = join(homedir(), ".epoch", "skills");
@@ -25593,17 +27247,17 @@ function swapInto(from, old, dest, skillsDir) {
25593
27247
  try {
25594
27248
  mkdirSync(trash, { recursive: true });
25595
27249
  renameSync(old, join(trash, "old"));
25596
- } catch (err) {
27250
+ } catch (err3) {
25597
27251
  rmSync(trash, { recursive: true, force: true });
25598
- return err instanceof Error ? err.message : String(err);
27252
+ return err3 instanceof Error ? err3.message : String(err3);
25599
27253
  }
25600
27254
  try {
25601
27255
  mkdirSync(dirname(dest), { recursive: true });
25602
27256
  renameSync(from, dest);
25603
- } catch (err) {
27257
+ } catch (err3) {
25604
27258
  renameSync(join(trash, "old"), old);
25605
27259
  rmSync(trash, { recursive: true, force: true });
25606
- return err instanceof Error ? err.message : String(err);
27260
+ return err3 instanceof Error ? err3.message : String(err3);
25607
27261
  }
25608
27262
  rmSync(trash, { recursive: true, force: true });
25609
27263
  return null;
@@ -25681,8 +27335,8 @@ function commit3(preview3, staged, skillsDir, lang, replace = false) {
25681
27335
  mkdirSync(join(skillsDir, entry.category), { recursive: true });
25682
27336
  renameSync(from, dest);
25683
27337
  imported.push(entry.name);
25684
- } catch (err) {
25685
- const reason9 = err instanceof Error ? err.message : String(err);
27338
+ } catch (err3) {
27339
+ const reason9 = err3 instanceof Error ? err3.message : String(err3);
25686
27340
  skipped.push({ path: label, message: t("skill.import_write_failed", { reason: reason9 }, lang) });
25687
27341
  }
25688
27342
  }
@@ -25769,8 +27423,8 @@ var SkillLearner = class {
25769
27423
  messages: [{ role: "user", content: buildLearningPrompt(ctx) }]
25770
27424
  });
25771
27425
  text = result.text;
25772
- } catch (err) {
25773
- return { created: false, reason: "provider-error", error: messageOf2(err) };
27426
+ } catch (err3) {
27427
+ return { created: false, reason: "provider-error", error: messageOf2(err3) };
25774
27428
  }
25775
27429
  return this.parseAndCreate(text);
25776
27430
  }
@@ -25803,13 +27457,13 @@ var SkillLearner = class {
25803
27457
  try {
25804
27458
  await this.skillSystem.create(declared, parsed.content, category);
25805
27459
  return { created: true, skillName: declared };
25806
- } catch (err) {
25807
- return { created: false, reason: "create-failed", error: messageOf2(err) };
27460
+ } catch (err3) {
27461
+ return { created: false, reason: "create-failed", error: messageOf2(err3) };
25808
27462
  }
25809
27463
  }
25810
27464
  };
25811
- function messageOf2(err) {
25812
- return err instanceof Error ? err.message : String(err);
27465
+ function messageOf2(err3) {
27466
+ return err3 instanceof Error ? err3.message : String(err3);
25813
27467
  }
25814
27468
  var MAX_FILES = 2e4;
25815
27469
  var SKIP_DIRS = /* @__PURE__ */ new Set([
@@ -26082,11 +27736,11 @@ async function openArtifact(path, homeDir) {
26082
27736
  const child = spawn(launch.command, launch.args, { stdio: "ignore", detached: true });
26083
27737
  child.on(
26084
27738
  "error",
26085
- (err) => fail9(
27739
+ (err3) => fail9(
26086
27740
  new Error(
26087
27741
  t("artifact.open_launch_failed_detail", {
26088
27742
  reason: describeArtifactRefusal("launch-failed"),
26089
- message: err.message
27743
+ message: err3.message
26090
27744
  })
26091
27745
  )
26092
27746
  )
@@ -26095,12 +27749,12 @@ async function openArtifact(path, homeDir) {
26095
27749
  child.unref();
26096
27750
  done2();
26097
27751
  });
26098
- } catch (err) {
27752
+ } catch (err3) {
26099
27753
  fail9(
26100
27754
  new Error(
26101
27755
  t("artifact.open_launch_failed_detail", {
26102
27756
  reason: describeArtifactRefusal("launch-failed"),
26103
- message: String(err)
27757
+ message: String(err3)
26104
27758
  })
26105
27759
  )
26106
27760
  );
@@ -26439,8 +28093,8 @@ ${extra}` : withGoal;
26439
28093
  var FILE_VERSION5 = 1;
26440
28094
  var LEVELS = ["trusted", "untrusted"];
26441
28095
  var SCOPES = ["directory", "directory-tree"];
26442
- function describe14(err) {
26443
- return err instanceof Error ? err.message : String(err);
28096
+ function describe14(err3) {
28097
+ return err3 instanceof Error ? err3.message : String(err3);
26444
28098
  }
26445
28099
  function covers(base2, target, scope) {
26446
28100
  if (samePath(base2, target)) return true;
@@ -26511,18 +28165,18 @@ var TrustManager = class {
26511
28165
  let raw;
26512
28166
  try {
26513
28167
  raw = readFileSync(this.filePath, "utf-8");
26514
- } catch (err) {
28168
+ } catch (err3) {
26515
28169
  this.loadErrors.push(
26516
- t("trust_gate.record_read_failed", { path: this.filePath, reason: describe14(err) })
28170
+ t("trust_gate.record_read_failed", { path: this.filePath, reason: describe14(err3) })
26517
28171
  );
26518
28172
  return;
26519
28173
  }
26520
28174
  let parsed;
26521
28175
  try {
26522
28176
  parsed = JSON.parse(raw);
26523
- } catch (err) {
28177
+ } catch (err3) {
26524
28178
  this.loadErrors.push(
26525
- t("trust_gate.record_bad_json", { path: this.filePath, reason: describe14(err) })
28179
+ t("trust_gate.record_bad_json", { path: this.filePath, reason: describe14(err3) })
26526
28180
  );
26527
28181
  return;
26528
28182
  }
@@ -26568,10 +28222,10 @@ var TrustManager = class {
26568
28222
  try {
26569
28223
  writeFileSync(tmp, body2, { encoding: "utf-8", mode: 384 });
26570
28224
  renameSync(tmp, this.filePath);
26571
- } catch (err) {
28225
+ } catch (err3) {
26572
28226
  rmSync(tmp, { force: true });
26573
28227
  throw new Error(
26574
- t("trust_gate.record_write_failed", { path: this.filePath, reason: describe14(err) })
28228
+ t("trust_gate.record_write_failed", { path: this.filePath, reason: describe14(err3) })
26575
28229
  );
26576
28230
  }
26577
28231
  }
@@ -26718,4 +28372,4 @@ function hasDedicatedExecContent(inv) {
26718
28372
  * `--tree` 的命令帮助里,让用户自己知道 `--tree` 意味着什么。
26719
28373
  */
26720
28374
 
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 };
28375
+ 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, 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 };