@epoch-agent/core 0.10.1 → 0.12.0

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
@@ -2,7 +2,7 @@ import { existsSync, statSync, readdirSync, readFileSync, mkdirSync, writeFileSy
2
2
  import { homedir, platform, tmpdir, hostname } from 'os';
3
3
  import { join, dirname, resolve, relative, isAbsolute, sep, extname, basename } from 'path';
4
4
  import { execFile, execSync, execFileSync, spawn } from 'child_process';
5
- import { createLogger, dbPath, resolveHomeDir, DEFAULT_MAX_TURNS, PROJECT_DIR_NAME, t, openDatabase, migrate, releaseDatabase, unknownKeyIssues, parseLenient, issueDetails, splitWords, checkpointsDir, pluginsDir, projectHooksPath, projectClaudeSettingsPath, projectClaudeLocalSettingsPath, projectSettingsPath, projectLocalSettingsPath, projectPoliciesDir, trustedImportsPath, budgetStatePath, artifactsDir, UNLIMITED_TURNS, turnLimitOf, configPath, managedSettingsPath, getSecretValues, listStoredSecretNames, maskApiKey, setSectionField, isInWorkspace, workspacesPath, automationLogsDir, projectComplianceDir, projectSkillsDir, attachmentsDir, trustPath, projectCommandsDir, detectBackend, EXEC_PATH_AS_NODE_ENV, isolate, createStreamDecoder, parseShellCommand, writeArtifact, envPath, checkDangerousCommand, checkObfuscation, countCodePoints, keepHeadAndTail, normalizeForMatch, isReadOnlyCommand, CODE_EXEC_ROOTS, headCodePoints, tailCodePoints } from '@epoch-agent/infra';
5
+ import { createLogger, dbPath, resolveHomeDir, DEFAULT_MAX_TURNS, PROJECT_DIR_NAME, t, suggestKey, misspelledKeyIssues, openDatabase, migrate, releaseDatabase, parseLenient, issueDetails, splitWords, unknownKeyIssues, checkpointsDir, pluginsDir, projectHooksPath, projectClaudeSettingsPath, projectClaudeLocalSettingsPath, projectSettingsPath, projectLocalSettingsPath, projectPoliciesDir, trustedImportsPath, budgetStatePath, artifactsDir, UNLIMITED_TURNS, turnLimitOf, configPath, managedSettingsPath, getSecretValues, listStoredSecretNames, maskApiKey, setSectionField, isInWorkspace, workspacesPath, samePath, lastSessionsPath, automationLogsDir, projectComplianceDir, projectSkillsDir, attachmentsDir, trustPath, projectCommandsDir, detectBackend, EXEC_PATH_AS_NODE_ENV, isolate, createStreamDecoder, parseShellCommand, writeArtifact, envPath, checkDangerousCommand, checkObfuscation, countCodePoints, keepHeadAndTail, normalizeForMatch, isReadOnlyCommand, CODE_EXEC_ROOTS, headCodePoints, tailCodePoints } from '@epoch-agent/infra';
6
6
  export { IS_WINDOWS, WINDOWS_HIDE_FLAGS, buildBwrapArgs, buildProfile, checkDangerousCommand, checkObfuscation, createLogger, detectBackend, getDefaultShell, getPythonCommand, isInWorkspace, isReadOnlyCommand, isolate, maskApiKey, probeBubblewrap, probeSeatbelt, complianceDir as resolveComplianceDir, policiesDir as resolvePoliciesDir, setLogLevel } from '@epoch-agent/infra';
7
7
  import { PROVIDER_TYPES, OPERATION_TYPES as OPERATION_TYPES$1, COMPLIANCE_CATEGORIES, COMPLIANCE_ACTIONS, SEARCH_PROVIDER_TYPES, CURRENCIES, LANGS, PERMISSION_LEVELS, SHELL_KINDS, ToolExposure, MAX_OPTIONS, MIN_OPTIONS, MAX_HEADER_CHARS, MAX_QUESTIONS, SCHEDULE_INTERVAL_MINUTES, isPermissionLevel, SCHEDULE_DRAFT_TOOL, isValidAgentRoleName, DEFAULT_AGENT_ROLE, isValidCommandName, RESERVED_COMMAND_NAMES, parseModelRef, isWirePluginArchiveName, systemNote, formatMoney, totalUsageTokens, NOOP_TELEMETRY, METRIC, contentToText, GEN_AI, isPromptOversize, promptTokens, apiKeyEnvVar, PROVIDER_INFOS, isProviderType, API_KEY_ENV_VARS, KEY_ACTIONS, tableOf, perAction, isKeyAction, parseSequence, RESERVED_CHORDS, chordId, sequenceId, ACTION_CONTEXTS, SEQUENCE_CONTEXTS, assertNeverPart, MAX_ATTACH_FILES, MAX_ATTACH_TOTAL_BYTES, MAX_SESSION_REFS, utf8ByteLength, truncateToBudget, attachSessionSurface, isContextNearlyFull, isOperationType, normalizeApproval, imagePartOmittedSummary, MAX_ATTACH_BYTES, SIMULTANEOUS_CONTEXTS, SESSION_REFERENCE_ERROR_CODES, filePartSummary, sessionPartSummary } from '@epoch-agent/protocol';
8
8
  export { API_KEY_ENV_VARS, COMPLIANCE_ACTIONS, COMPLIANCE_CATEGORIES, 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, extractAllMentions, extractMentions, extractSessionMentions, getProviderInfo, isOperationType, isPermissionLevel, isPlanOutcome, isProviderType, normalizeApproval } from '@epoch-agent/protocol';
@@ -264,7 +264,7 @@ function createLaunchdBackend(opts = {}) {
264
264
  mkdirSync(input.logDir, { recursive: true });
265
265
  writeFileSync(path, renderPlist(label, input), "utf-8");
266
266
  } catch (err) {
267
- return { ok: false, detail: `plist-write-failed: ${describe6(err)}` };
267
+ return { ok: false, detail: `plist-write-failed: ${describe8(err)}` };
268
268
  }
269
269
  await run("launchctl", ["bootout", `${guiDomain()}/${label}`]);
270
270
  const toggle = await backend.setEnabled(label, input.enabled);
@@ -280,7 +280,7 @@ function createLaunchdBackend(opts = {}) {
280
280
  try {
281
281
  rmSync(plistPath(label), { force: true });
282
282
  } catch (err) {
283
- return { ok: false, detail: `plist-remove-failed: ${describe6(err)}` };
283
+ return { ok: false, detail: `plist-remove-failed: ${describe8(err)}` };
284
284
  }
285
285
  return { ok: true };
286
286
  },
@@ -435,7 +435,7 @@ function detailOf2(what, res) {
435
435
  const msg = (res.stderr || res.stdout).trim();
436
436
  return `${what} exit ${res.code}${msg ? `: ${msg}` : ""}`;
437
437
  }
438
- function describe6(err) {
438
+ function describe8(err) {
439
439
  return err instanceof Error ? err.message : String(err);
440
440
  }
441
441
  var LAUNCHD_LABEL_PREFIX;
@@ -475,10 +475,10 @@ function intervalSlots(everyMinutes) {
475
475
  var runCommand2;
476
476
  var init_backend = __esm({
477
477
  "src/schedule/os/backend.ts"() {
478
- runCommand2 = (file, args) => new Promise((resolve15) => {
478
+ runCommand2 = (file, args) => new Promise((resolve16) => {
479
479
  execFile(file, [...args], { encoding: "buffer", windowsHide: true }, (err, stdout, stderr) => {
480
480
  const code = err && typeof err.code === "number" ? err.code ?? 1 : err ? 1 : 0;
481
- resolve15({ code, stdout: decodeOutput(stdout), stderr: decodeOutput(stderr) });
481
+ resolve16({ code, stdout: decodeOutput(stdout), stderr: decodeOutput(stderr) });
482
482
  });
483
483
  });
484
484
  }
@@ -629,7 +629,7 @@ var ToolRegistry = class {
629
629
  this.addTool(tool, source);
630
630
  }
631
631
  registerTools(tools, source = "builtin") {
632
- for (const t78 of tools) this.addTool(t78, source);
632
+ for (const t81 of tools) this.addTool(t81, source);
633
633
  }
634
634
  addTool(tool, source) {
635
635
  const existing = this.tools.get(tool.name);
@@ -678,14 +678,14 @@ var ToolRegistry = class {
678
678
  return isCodeModeDeferred(tool) ? ToolExposure.Deferred : declared;
679
679
  }
680
680
  exposed() {
681
- return this.list().filter((t78) => this.exposureOf(t78) === ToolExposure.Direct);
681
+ return this.list().filter((t81) => this.exposureOf(t81) === ToolExposure.Direct);
682
682
  }
683
683
  byExposure(exposure) {
684
- return this.list().filter((t78) => this.exposureOf(t78) === exposure);
684
+ return this.list().filter((t81) => this.exposureOf(t81) === exposure);
685
685
  }
686
686
  codeModeDeclared() {
687
687
  if (!this.codeMode) return [];
688
- return this.list().filter((t78) => isCodeModeDeferred(t78));
688
+ return this.list().filter((t81) => isCodeModeDeferred(t81));
689
689
  }
690
690
  sourceOf(name) {
691
691
  return this.tools.get(name)?.source;
@@ -734,7 +734,7 @@ var ToolRegistry = class {
734
734
  function staticToolProvider(tools) {
735
735
  return {
736
736
  list: () => tools,
737
- get: (name) => tools.find((t78) => t78.name === name)
737
+ get: (name) => tools.find((t81) => t81.name === name)
738
738
  };
739
739
  }
740
740
  var log = createLogger("tokenizer");
@@ -1146,7 +1146,7 @@ var DelegateManager = class {
1146
1146
  }
1147
1147
  normalizeTasks(args) {
1148
1148
  if (args.tasks && args.tasks.length > 0) {
1149
- return args.role ? args.tasks.map((t78) => ({ ...t78, role: t78.role ?? args.role })) : args.tasks;
1149
+ return args.role ? args.tasks.map((t81) => ({ ...t81, role: t81.role ?? args.role })) : args.tasks;
1150
1150
  }
1151
1151
  if (args.goal) return [{ goal: args.goal, ...args.role ? { role: args.role } : {} }];
1152
1152
  return [];
@@ -1156,7 +1156,7 @@ var DelegateManager = class {
1156
1156
  for (let i = 0; i < tasks.length; i += maxConcurrent) {
1157
1157
  const batch = tasks.slice(i, i + maxConcurrent);
1158
1158
  const batchResults = await Promise.allSettled(
1159
- batch.map((t78) => this.runSingleTask(t78, parentSessionId))
1159
+ batch.map((t81) => this.runSingleTask(t81, parentSessionId))
1160
1160
  );
1161
1161
  for (const r of batchResults) {
1162
1162
  if (r.status === "fulfilled") {
@@ -1297,21 +1297,21 @@ function createDelegateTool(runner, config, roles) {
1297
1297
  operation: "command",
1298
1298
  describeTarget: (args) => {
1299
1299
  const tasks = Array.isArray(args["tasks"]) ? args["tasks"] : [];
1300
- const goals = tasks.map((t78) => String(t78["goal"] ?? ""));
1300
+ const goals = tasks.map((t81) => String(t81["goal"] ?? ""));
1301
1301
  const single = typeof args["goal"] === "string" ? args["goal"] : "";
1302
1302
  return [...goals, single].filter(Boolean).join(" | ");
1303
1303
  },
1304
1304
  async execute(args, ctx) {
1305
1305
  const start = Date.now();
1306
1306
  const rawTasks = Array.isArray(args["tasks"]) ? args["tasks"] : void 0;
1307
- const tasks = rawTasks?.map((t78) => {
1308
- const o = t78;
1307
+ const tasks = rawTasks?.map((t81) => {
1308
+ const o = t81;
1309
1309
  return {
1310
1310
  goal: String(o["goal"] ?? "").trim(),
1311
1311
  context: String(o["context"] ?? ""),
1312
1312
  ...typeof o["role"] === "string" && o["role"].trim() ? { role: o["role"].trim() } : {}
1313
1313
  };
1314
- }).filter((t78) => t78.goal.length > 0);
1314
+ }).filter((t81) => t81.goal.length > 0);
1315
1315
  const goal = typeof args["goal"] === "string" ? args["goal"].trim() : "";
1316
1316
  const topRole = typeof args["role"] === "string" ? args["role"].trim() : "";
1317
1317
  if ((!tasks || tasks.length === 0) && !goal) {
@@ -1327,7 +1327,7 @@ function createDelegateTool(runner, config, roles) {
1327
1327
  };
1328
1328
  }
1329
1329
  const known = listRoles();
1330
- const requested = [...(tasks ?? []).map((t78) => t78.role), topRole].filter(
1330
+ const requested = [...(tasks ?? []).map((t81) => t81.role), topRole].filter(
1331
1331
  (r) => Boolean(r)
1332
1332
  );
1333
1333
  const unknown = [...new Set(requested)].filter((r) => !known.some((k) => k.name === r));
@@ -1500,8 +1500,8 @@ function createGoalTool(deps) {
1500
1500
  }
1501
1501
  var VALID_TARGETS = ["memory", "user"];
1502
1502
  var VALID_ACTIONS = ["add", "replace", "remove", "search", "read", "budget"];
1503
- function isValidTarget(t78) {
1504
- return typeof t78 === "string" && VALID_TARGETS.includes(t78);
1503
+ function isValidTarget(t81) {
1504
+ return typeof t81 === "string" && VALID_TARGETS.includes(t81);
1505
1505
  }
1506
1506
  function isValidAction(a) {
1507
1507
  return VALID_ACTIONS.includes(a);
@@ -1773,7 +1773,7 @@ async function runCode(input) {
1773
1773
  let toolCalls = 0;
1774
1774
  let capped2 = false;
1775
1775
  let ending = null;
1776
- return await new Promise((resolve15) => {
1776
+ return await new Promise((resolve16) => {
1777
1777
  let settled = false;
1778
1778
  const finish = () => {
1779
1779
  if (settled) return;
@@ -1782,7 +1782,7 @@ async function runCode(input) {
1782
1782
  clearInterval(abortWatch);
1783
1783
  void worker.terminate().catch(() => {
1784
1784
  }).then(() => Promise.race([drained, delay(STREAM_DRAIN_MS)])).then(() => {
1785
- resolve15(toOutcome(ending, { printed, toolCalls, capped: capped2, limits}));
1785
+ resolve16(toOutcome(ending, { printed, toolCalls, capped: capped2, limits}));
1786
1786
  });
1787
1787
  };
1788
1788
  const timer = setTimeout(() => {
@@ -1853,14 +1853,14 @@ async function runCode(input) {
1853
1853
  var ABORT_POLL_MS = 100;
1854
1854
  var STREAM_DRAIN_MS = 500;
1855
1855
  function streamEnd(stream) {
1856
- return new Promise((resolve15) => {
1857
- stream.once("end", () => resolve15());
1858
- stream.once("close", () => resolve15());
1856
+ return new Promise((resolve16) => {
1857
+ stream.once("end", () => resolve16());
1858
+ stream.once("close", () => resolve16());
1859
1859
  });
1860
1860
  }
1861
1861
  function delay(ms) {
1862
- return new Promise((resolve15) => {
1863
- setTimeout(resolve15, ms).unref();
1862
+ return new Promise((resolve16) => {
1863
+ setTimeout(resolve16, ms).unref();
1864
1864
  });
1865
1865
  }
1866
1866
  function timeoutMessage(timeoutMs, toolCalls) {
@@ -4205,6 +4205,7 @@ var SkillFrontmatterSchema = z.object({
4205
4205
  tags: looseStringList.optional().catch(void 0)
4206
4206
  });
4207
4207
  var FRONTMATTER_KEYS = Object.keys(SkillFrontmatterSchema.shape);
4208
+ var METADATA_KEYS = ["tags"];
4208
4209
  function parseSkillFrontmatter(raw, label) {
4209
4210
  const parsed = parseFrontmatter(raw);
4210
4211
  if ("error" in parsed) {
@@ -4232,7 +4233,13 @@ function parseSkillFrontmatter(raw, label) {
4232
4233
  const raw_ = isRecord3(data) ? data : {};
4233
4234
  for (const key of Object.keys(raw_)) {
4234
4235
  if (!FRONTMATTER_KEYS.includes(key)) {
4235
- issues.push({ path: `${label}.${key}`, message: t("skill_load.unknown_key", { key }) });
4236
+ const suggest = suggestKey(key, FRONTMATTER_KEYS);
4237
+ if (suggest !== void 0) {
4238
+ issues.push({
4239
+ path: `${label}.${key}`,
4240
+ message: t("infra_misc.schema_misspelled_key", { suggest })
4241
+ });
4242
+ }
4236
4243
  continue;
4237
4244
  }
4238
4245
  if (raw_[key] !== void 0 && result.data[key] === void 0) {
@@ -4248,6 +4255,7 @@ function parseSkillFrontmatter(raw, label) {
4248
4255
  });
4249
4256
  }
4250
4257
  }
4258
+ issues.push(...misspelledKeyIssues(METADATA_KEYS, raw_.metadata, `${label}.metadata`));
4251
4259
  const fm = {};
4252
4260
  if (result.data.name !== void 0) fm.name = result.data.name;
4253
4261
  if (result.data.description !== void 0) fm.description = result.data.description;
@@ -4499,7 +4507,7 @@ function available(tools) {
4499
4507
  if (tools.length === 0) {
4500
4508
  return "No deferred tools in this session \u2014 every tool is already in your tool list.";
4501
4509
  }
4502
- const names = tools.map((t78) => t78.name).sort();
4510
+ const names = tools.map((t81) => t81.name).sort();
4503
4511
  const shown = names.slice(0, MAX_LISTED);
4504
4512
  const rest = names.length - shown.length;
4505
4513
  return `Searchable tools: ${shown.join(", ")}${rest > 0 ? ` (\u2026and ${rest} more)` : ""}.`;
@@ -4619,15 +4627,15 @@ var TrackerDB = class {
4619
4627
  );
4620
4628
  this.db.transaction(() => {
4621
4629
  this.db.prepare("DELETE FROM todos WHERE session_id = ?").run(sessionId);
4622
- for (const t78 of todos) {
4630
+ for (const t81 of todos) {
4623
4631
  insertStmt.run({
4624
- id: t78.id,
4632
+ id: t81.id,
4625
4633
  session_id: sessionId,
4626
- content: t78.content,
4627
- status: t78.status,
4628
- reason: t78.reason || null,
4629
- created_at: t78.created_at,
4630
- updated_at: t78.updated_at
4634
+ content: t81.content,
4635
+ status: t81.status,
4636
+ reason: t81.reason || null,
4637
+ created_at: t81.created_at,
4638
+ updated_at: t81.updated_at
4631
4639
  });
4632
4640
  }
4633
4641
  })();
@@ -4649,9 +4657,9 @@ function formatTodoList(todos, pendingCount) {
4649
4657
  cancelled: "\u5DF2\u53D6\u6D88"
4650
4658
  };
4651
4659
  lines.push(`[todo] \u72B6\u6001\u6C47\u603B: ${pendingCount} \u4E2A\u5F85\u5B8C\u6210`);
4652
- for (const t78 of todos) {
4653
- const label = statusLabel[t78.status] || t78.status;
4654
- lines.push(`- [${label}] ${t78.content}${t78.reason ? ` \u2014\u2014 ${t78.reason}` : ""}`);
4660
+ for (const t81 of todos) {
4661
+ const label = statusLabel[t81.status] || t81.status;
4662
+ lines.push(`- [${label}] ${t81.content}${t81.reason ? ` \u2014\u2014 ${t81.reason}` : ""}`);
4655
4663
  }
4656
4664
  return lines.join("\n");
4657
4665
  }
@@ -4725,14 +4733,14 @@ function createTodoTool(db) {
4725
4733
  };
4726
4734
  }
4727
4735
  const now = (/* @__PURE__ */ new Date()).toISOString();
4728
- const existing = new Map(db.listBySession(ctx.sessionId).map((t78) => [t78.id, t78]));
4729
- const todos = rawTodos.map((t78) => {
4730
- const prev = t78.id ? existing.get(t78.id) : void 0;
4731
- const status = isValidStatus(t78.status) ? t78.status : "pending";
4732
- const reason9 = normalizeReason(status, t78.reason);
4736
+ const existing = new Map(db.listBySession(ctx.sessionId).map((t81) => [t81.id, t81]));
4737
+ const todos = rawTodos.map((t81) => {
4738
+ const prev = t81.id ? existing.get(t81.id) : void 0;
4739
+ const status = isValidStatus(t81.status) ? t81.status : "pending";
4740
+ const reason9 = normalizeReason(status, t81.reason);
4733
4741
  return {
4734
- id: t78.id || generateShortId(),
4735
- content: String(t78.content || "").slice(0, 500),
4742
+ id: t81.id || generateShortId(),
4743
+ content: String(t81.content || "").slice(0, 500),
4736
4744
  status,
4737
4745
  ...reason9 ? { reason: reason9 } : {},
4738
4746
  created_at: prev?.created_at || now,
@@ -4740,7 +4748,7 @@ function createTodoTool(db) {
4740
4748
  };
4741
4749
  });
4742
4750
  db.replaceAll(ctx.sessionId, todos);
4743
- const pendingCount = todos.filter((t78) => isOpenTodo(t78.status)).length;
4751
+ const pendingCount = todos.filter((t81) => isOpenTodo(t81.status)).length;
4744
4752
  return {
4745
4753
  success: true,
4746
4754
  output: formatTodoList(todos, pendingCount),
@@ -4889,7 +4897,7 @@ function parseRoleDefinition(raw, file, source) {
4889
4897
  };
4890
4898
  }
4891
4899
  const parsed = split.data;
4892
- const issues = unknownKeyIssues(FRONTMATTER_KEYS2, parsed, file);
4900
+ const issues = misspelledKeyIssues(FRONTMATTER_KEYS2, parsed, file);
4893
4901
  const outcome = parseLenient(FrontmatterSchema.optional(), parsed, void 0);
4894
4902
  if (!outcome.value) {
4895
4903
  issues.push(
@@ -5075,7 +5083,7 @@ function intersectNames(base, incoming) {
5075
5083
  if (!base) return incoming ? [...incoming] : void 0;
5076
5084
  if (!incoming) return [...base];
5077
5085
  const baseSet = new Set(base);
5078
- return incoming.filter((t78) => baseSet.has(t78));
5086
+ return incoming.filter((t81) => baseSet.has(t81));
5079
5087
  }
5080
5088
  function findRole(roles, name) {
5081
5089
  return roles.find((r) => r.name === name);
@@ -5152,6 +5160,64 @@ function driftOf(role, name, input) {
5152
5160
  function describe(err) {
5153
5161
  return err instanceof Error ? err.message : String(err);
5154
5162
  }
5163
+ function removeRoleFile(name, opts) {
5164
+ const wanted = name.trim();
5165
+ const hits = matchingFiles(opts.dir, wanted);
5166
+ if (hits.length > 1) {
5167
+ return {
5168
+ ok: false,
5169
+ reason: "ambiguous",
5170
+ detail: t(
5171
+ "role_write.ambiguous_files",
5172
+ {
5173
+ name: wanted,
5174
+ paths: hits.join(t("role_write.path_sep", void 0, opts.lang))
5175
+ },
5176
+ opts.lang
5177
+ )
5178
+ };
5179
+ }
5180
+ const [path] = hits;
5181
+ if (path === void 0) {
5182
+ return {
5183
+ ok: false,
5184
+ reason: "not-found",
5185
+ detail: t("role_write.no_such_file", { name: wanted }, opts.lang)
5186
+ };
5187
+ }
5188
+ try {
5189
+ rmSync(path);
5190
+ } catch (err) {
5191
+ return { ok: false, reason: "failed", detail: describe2(err, path, opts.lang) };
5192
+ }
5193
+ return { ok: true, path };
5194
+ }
5195
+ function matchingFiles(dir, name) {
5196
+ if (!existsSync(dir)) return [];
5197
+ let files;
5198
+ try {
5199
+ files = readdirSync(dir).filter((f) => f.endsWith(".md")).sort();
5200
+ } catch {
5201
+ return [];
5202
+ }
5203
+ const hits = [];
5204
+ for (const file of files) {
5205
+ const path = join(dir, file);
5206
+ let raw;
5207
+ try {
5208
+ raw = readFileSync(path, "utf-8");
5209
+ } catch {
5210
+ continue;
5211
+ }
5212
+ const parsed = parseRoleDefinition(raw, file, "user");
5213
+ if (parsed.role?.name === name) hits.push(path);
5214
+ }
5215
+ return hits;
5216
+ }
5217
+ function describe2(err, path, lang) {
5218
+ const reason9 = err instanceof Error ? err.message : String(err);
5219
+ return t("role_write.remove_failed", { path, reason: reason9 }, lang);
5220
+ }
5155
5221
  // src/agent-role/scope.ts
5156
5222
  function roleScopedProvider(base, role, blocked) {
5157
5223
  const blockedSet = new Set(blocked);
@@ -5161,7 +5227,7 @@ function roleScopedProvider(base, role, blocked) {
5161
5227
  return allow ? allow.has(name) : true;
5162
5228
  };
5163
5229
  return {
5164
- list: () => base.list().filter((t78) => permitted(t78.name)),
5230
+ list: () => base.list().filter((t81) => permitted(t81.name)),
5165
5231
  get: (name) => permitted(name) ? base.get(name) : void 0
5166
5232
  };
5167
5233
  }
@@ -5188,7 +5254,7 @@ function createRoleScope(base, sessionRole, blocked) {
5188
5254
  }
5189
5255
  function unknownRoleTools(base, role, blocked) {
5190
5256
  if (!role?.tools) return [];
5191
- const available2 = new Set(base.list().map((t78) => t78.name));
5257
+ const available2 = new Set(base.list().map((t81) => t81.name));
5192
5258
  const blockedSet = new Set(blocked);
5193
5259
  return role.tools.filter((name) => !available2.has(name) && !blockedSet.has(name));
5194
5260
  }
@@ -5308,7 +5374,7 @@ function loadCommandFile(file, source, prefix) {
5308
5374
  ]
5309
5375
  };
5310
5376
  }
5311
- const issues = unknownKeyIssues(FRONTMATTER_KEYS3, parsed.data, at);
5377
+ const issues = misspelledKeyIssues(FRONTMATTER_KEYS3, parsed.data, at);
5312
5378
  const checked = parseLenient(CommandFrontmatterSchema.optional(), parsed.data, void 0);
5313
5379
  if (!checked.value) {
5314
5380
  issues.push(
@@ -5524,7 +5590,7 @@ function createToolScope(base) {
5524
5590
  const permitted = (name) => allow ? allow.has(name) : true;
5525
5591
  return {
5526
5592
  provider: {
5527
- list: () => base.list().filter((t78) => permitted(t78.name)),
5593
+ list: () => base.list().filter((t81) => permitted(t81.name)),
5528
5594
  get: (name) => permitted(name) ? base.get(name) : void 0
5529
5595
  },
5530
5596
  enter: (next) => {
@@ -5694,7 +5760,7 @@ function scanHooks(dir, issues) {
5694
5760
  return [...parsed.entries].map(([type, list]) => ({
5695
5761
  type,
5696
5762
  count: list.reduce((sum, entry) => sum + entry.hooks.length, 0)
5697
- })).filter((t78) => t78.count > 0).sort((a, b) => a.type.localeCompare(b.type));
5763
+ })).filter((t81) => t81.count > 0).sort((a, b) => a.type.localeCompare(b.type));
5698
5764
  }
5699
5765
  function scanMcp(dir, plugin, issues) {
5700
5766
  const path = join(dir, PLUGIN_LAYOUT.mcp);
@@ -5781,6 +5847,7 @@ var PluginAuthorSchema = z.object({
5781
5847
  email: z.string().min(1).optional(),
5782
5848
  url: z.string().min(1).optional()
5783
5849
  });
5850
+ var PLUGIN_VISIBILITY = ["private", "public"];
5784
5851
  var ManifestSchema = z.object({
5785
5852
  name: z.string().min(1),
5786
5853
  version: z.string().min(1),
@@ -5788,9 +5855,14 @@ var ManifestSchema = z.object({
5788
5855
  author: PluginAuthorSchema.optional(),
5789
5856
  epochVersion: z.string().min(1).optional(),
5790
5857
  homepage: z.string().min(1).optional(),
5791
- keywords: z.array(z.string().min(1)).optional()
5858
+ keywords: z.array(z.string().min(1)).optional(),
5859
+ displayName: z.string().min(1).optional(),
5860
+ category: z.string().min(1).optional(),
5861
+ icon: z.string().min(1).optional(),
5862
+ changelog: z.string().min(1).optional(),
5863
+ visibility: z.enum(PLUGIN_VISIBILITY).optional().catch(void 0)
5792
5864
  });
5793
- var MANIFEST_KEYS = Object.keys(ManifestSchema.shape);
5865
+ var PLUGIN_MANIFEST_KEYS = Object.keys(ManifestSchema.shape);
5794
5866
  function readPluginManifest(dir) {
5795
5867
  const path = join(dir, PLUGIN_MANIFEST_FILE);
5796
5868
  let raw;
@@ -5815,7 +5887,17 @@ function readPluginManifest(dir) {
5815
5887
  issues: [{ path, message: t("plugin_manifest.bad_json", { reason: firstLine2(err) }) }]
5816
5888
  };
5817
5889
  }
5818
- const issues = unknownKeyIssues(MANIFEST_KEYS, parsed, PLUGIN_MANIFEST_FILE);
5890
+ const issues = unknownKeyIssues(PLUGIN_MANIFEST_KEYS, parsed, PLUGIN_MANIFEST_FILE);
5891
+ const rawVisibility = parsed?.visibility;
5892
+ if (rawVisibility !== void 0 && !PLUGIN_VISIBILITY.includes(rawVisibility)) {
5893
+ issues.push({
5894
+ path: `${path}.visibility`,
5895
+ message: t("plugin_manifest.bad_visibility", {
5896
+ raw: String(rawVisibility),
5897
+ allowed: PLUGIN_VISIBILITY.join(" / ")
5898
+ })
5899
+ });
5900
+ }
5819
5901
  const checked = parseLenient(ManifestSchema.optional(), parsed, void 0);
5820
5902
  if (!checked.value) {
5821
5903
  issues.push(
@@ -6095,7 +6177,7 @@ var PluginStore = class {
6095
6177
  }
6096
6178
  };
6097
6179
  function sleep(ms) {
6098
- return new Promise((resolve15) => setTimeout(resolve15, ms));
6180
+ return new Promise((resolve16) => setTimeout(resolve16, ms));
6099
6181
  }
6100
6182
  // src/plugin/loader.ts
6101
6183
  var MODULE = "Plugin";
@@ -6298,7 +6380,7 @@ function runCommand(file, args, opts = {}) {
6298
6380
  resolvePromise({ ok: true, stdout: out, stderr: errOut });
6299
6381
  return;
6300
6382
  }
6301
- const detail = describe2(file, err, errOut);
6383
+ const detail = describe3(file, err, errOut);
6302
6384
  resolvePromise({
6303
6385
  ok: false,
6304
6386
  detail,
@@ -6317,7 +6399,7 @@ function escapeForCmd(arg) {
6317
6399
  const quoted = `"${arg.replace(/(\\*)"/g, '$1$1\\"').replace(/(\\*)$/, "$1$1")}"`;
6318
6400
  return quoted.replace(/([()%!^<>&|;,"])/g, "^$1");
6319
6401
  }
6320
- function describe2(file, err, stderr) {
6402
+ function describe3(file, err, stderr) {
6321
6403
  if (err.code === "ENOENT") return t("plugin_cmd.not_found", { file });
6322
6404
  if (err.killed) return t("plugin_cmd.timeout", { file });
6323
6405
  const tail = stderr.trim().split("\n").slice(-4).join("\n").trim();
@@ -6900,7 +6982,7 @@ var EntrySchema = z.object({
6900
6982
  changelog: z.string().min(1).optional(),
6901
6983
  size: z.number().int().positive().optional(),
6902
6984
  homepage: z.string().min(1).optional(),
6903
- visibility: z.enum(["private", "public"]).optional().catch(void 0),
6985
+ visibility: z.enum(PLUGIN_VISIBILITY).optional().catch(void 0),
6904
6986
  status: z.enum(["listed", "reviewing", "rejected", "offline"]).optional().catch(void 0)
6905
6987
  });
6906
6988
  var MARKETPLACE_DISPLAY_FIELDS = [
@@ -7403,14 +7485,14 @@ var CheckpointStore = class {
7403
7485
  }
7404
7486
  async enforceTotalSize(protectSession, protectTurnIndex) {
7405
7487
  const turns = await this.collectTurns();
7406
- let total = turns.reduce((sum, t78) => sum + t78.bytes, 0);
7488
+ let total = turns.reduce((sum, t81) => sum + t81.bytes, 0);
7407
7489
  if (total <= this.maxTotalBytes) return;
7408
7490
  turns.sort((a, b) => a.createdAt - b.createdAt);
7409
- for (const t78 of turns) {
7491
+ for (const t81 of turns) {
7410
7492
  if (total <= this.maxTotalBytes) return;
7411
- if (t78.sessionId === protectSession && t78.turnIndex === protectTurnIndex) continue;
7412
- await this.removeTurn(t78.sessionId, t78.turnIndex);
7413
- total -= t78.bytes;
7493
+ if (t81.sessionId === protectSession && t81.turnIndex === protectTurnIndex) continue;
7494
+ await this.removeTurn(t81.sessionId, t81.turnIndex);
7495
+ total -= t81.bytes;
7414
7496
  }
7415
7497
  }
7416
7498
  async collectTurns() {
@@ -8116,8 +8198,8 @@ function sanitizeToolOutput(text) {
8116
8198
  if (!stripped.includes("\r")) return stripped;
8117
8199
  return stripped.split("\n").map((line) => line.includes("\r") ? line.slice(line.lastIndexOf("\r") + 1) : line).join("\n");
8118
8200
  }
8119
- var sleep2 = (ms) => new Promise((resolve15) => {
8120
- setTimeout(resolve15, ms);
8201
+ var sleep2 = (ms) => new Promise((resolve16) => {
8202
+ setTimeout(resolve16, ms);
8121
8203
  });
8122
8204
  async function* pumpToolOutput(target, start, options = {}) {
8123
8205
  const flushMs = options.flushMs ?? FLUSH_MS;
@@ -8185,8 +8267,8 @@ async function* pumpToolOutput(target, start, options = {}) {
8185
8267
  continue;
8186
8268
  }
8187
8269
  if (!running) break;
8188
- await new Promise((resolve15) => {
8189
- wake = resolve15;
8270
+ await new Promise((resolve16) => {
8271
+ wake = resolve16;
8190
8272
  });
8191
8273
  if (running && flushMs > 0) await sleep2(flushMs);
8192
8274
  }
@@ -8595,7 +8677,7 @@ function decideTrust(dir) {
8595
8677
  return ambient ? ambient.decide(dir) : noGate();
8596
8678
  }
8597
8679
  var FILE_VERSION = 1;
8598
- function describe3(err) {
8680
+ function describe4(err) {
8599
8681
  return err instanceof Error ? err.message : String(err);
8600
8682
  }
8601
8683
  var ImportTrustStore = class {
@@ -8637,7 +8719,7 @@ var ImportTrustStore = class {
8637
8719
  raw = readFileSync(this.filePath, "utf-8");
8638
8720
  } catch (err) {
8639
8721
  this.loadErrors.push(
8640
- t("import_trust.read_failed", { path: this.filePath, reason: describe3(err) })
8722
+ t("import_trust.read_failed", { path: this.filePath, reason: describe4(err) })
8641
8723
  );
8642
8724
  return;
8643
8725
  }
@@ -8646,7 +8728,7 @@ var ImportTrustStore = class {
8646
8728
  parsed = JSON.parse(raw);
8647
8729
  } catch (err) {
8648
8730
  this.loadErrors.push(
8649
- t("import_trust.bad_json", { path: this.filePath, reason: describe3(err) })
8731
+ t("import_trust.bad_json", { path: this.filePath, reason: describe4(err) })
8650
8732
  );
8651
8733
  return;
8652
8734
  }
@@ -8704,7 +8786,7 @@ var ImportTrustStore = class {
8704
8786
  } catch (err) {
8705
8787
  rmSync(tmp, { force: true });
8706
8788
  throw new Error(
8707
- t("import_trust.write_failed", { path: this.filePath, reason: describe3(err) })
8789
+ t("import_trust.write_failed", { path: this.filePath, reason: describe4(err) })
8708
8790
  );
8709
8791
  }
8710
8792
  }
@@ -9516,7 +9598,6 @@ ${this.describeWarning(status)}
9516
9598
  });
9517
9599
  }
9518
9600
  };
9519
- // src/provider/errors.ts
9520
9601
  var ProviderError = class extends Error {
9521
9602
  constructor(message, code, recoverable, recovery = "abort") {
9522
9603
  super(message);
@@ -9544,6 +9625,40 @@ function isAbortError(err) {
9544
9625
  }
9545
9626
  return false;
9546
9627
  }
9628
+ function causeChain(err) {
9629
+ const out = [];
9630
+ for (let cur = err, depth = 0; cur && depth < 5; depth++) {
9631
+ if (typeof cur !== "object") break;
9632
+ const e = cur;
9633
+ out.push({
9634
+ message: typeof e.message === "string" ? e.message : "",
9635
+ ...typeof e.code === "string" ? { code: e.code } : {}
9636
+ });
9637
+ cur = e.cause;
9638
+ }
9639
+ return out;
9640
+ }
9641
+ var NETWORK_ERROR_CODES = /* @__PURE__ */ new Set([
9642
+ "ECONNRESET",
9643
+ "ECONNREFUSED",
9644
+ "ETIMEDOUT",
9645
+ "ENOTFOUND",
9646
+ "EPIPE",
9647
+ "EAI_AGAIN",
9648
+ "UND_ERR_SOCKET",
9649
+ "UND_ERR_CONNECT_TIMEOUT",
9650
+ "UND_ERR_HEADERS_TIMEOUT",
9651
+ "UND_ERR_BODY_TIMEOUT",
9652
+ "UND_ERR_RESPONSE_STATUS_CODE"
9653
+ ]);
9654
+ var NETWORK_MESSAGE_RE = /timeout|timed.?out|etimedout|econnreset|enotfound|socket.?hang.?up|other.?side.?closed|terminated|network.?error|fetch.?failed/i;
9655
+ function describeProviderError(err) {
9656
+ const chain = causeChain(err);
9657
+ const head = chain[0]?.message ?? (typeof err === "string" ? err : String(err));
9658
+ if (chain.length === 0) return head;
9659
+ const root = [...chain].reverse().find((link) => link.message !== "" && link.message !== head)?.message;
9660
+ return root ? t("provider_route.root_cause", { message: head, cause: root }) : head;
9661
+ }
9547
9662
  function extractStatus(err) {
9548
9663
  if (!err || typeof err !== "object") return void 0;
9549
9664
  const e = err;
@@ -9576,8 +9691,7 @@ function classifyProviderError(err) {
9576
9691
  return { code: 1040, recovery: "switch_model" };
9577
9692
  if (/overloaded|server.?error|bad.?gateway|service.?unavailable/i.test(msg))
9578
9693
  return { code: 1020, recovery: "retry" };
9579
- if (/timeout|timed.?out|etimedout|econnreset|enotfound|socket.?hang.?up/i.test(msg))
9580
- return { code: 1041, recovery: "retry" };
9694
+ if (NETWORK_MESSAGE_RE.test(msg)) return { code: 1041, recovery: "retry" };
9581
9695
  const code = status ?? extractStatusFromMessage(msg);
9582
9696
  if (code !== void 0) {
9583
9697
  if (code === 401 || code === 403) return { code: 1001, recovery: "rotate_credential" };
@@ -9587,6 +9701,10 @@ function classifyProviderError(err) {
9587
9701
  if (code >= 500) return { code: 1020, recovery: "retry" };
9588
9702
  if (code >= 400) return { code: 1050, recovery: "abort" };
9589
9703
  }
9704
+ for (const link of causeChain(err)) {
9705
+ if (link.code && NETWORK_ERROR_CODES.has(link.code)) return { code: 1041, recovery: "retry" };
9706
+ if (NETWORK_MESSAGE_RE.test(link.message)) return { code: 1041, recovery: "retry" };
9707
+ }
9590
9708
  return { code: 9999, recovery: "retry" };
9591
9709
  }
9592
9710
  function toModelMessages(messages) {
@@ -9777,6 +9895,28 @@ function droppedUserContentParts(warnings) {
9777
9895
  });
9778
9896
  }
9779
9897
  var DROPPED_PART_HINTS = ["image", "file"];
9898
+ // src/agent/blank-turn-detector.ts
9899
+ var NEAR_BLANK_MAX_CHARS = 4;
9900
+ var ACKNOWLEDGEMENTS = [
9901
+ {
9902
+ zh: /^[一-鿿]{0,2}(?:完|好|到)(?:了|啦|的)?[。..!!]?$/,
9903
+ en: /^(?:done|finished|complete[d]?)[.!]?$/i
9904
+ },
9905
+ {
9906
+ zh: /^(?:完成|搞定|收工|行|可以|嗯|是|是的|对|对的|没错)(?:了|啦)?[。..!!]?$/,
9907
+ en: /^(?:ok(?:ay)?|sure|yes|yep|yeah|right|no|nope)[.!]?$/i
9908
+ }
9909
+ ];
9910
+ function isAcknowledgement(text) {
9911
+ return ACKNOWLEDGEMENTS.some((a) => a.zh.test(text) || a.en.test(text));
9912
+ }
9913
+ function blankFinish(text, didToolWork) {
9914
+ if (!didToolWork) return false;
9915
+ const trimmed = text.trim();
9916
+ if (trimmed.length === 0) return true;
9917
+ if (trimmed.length > NEAR_BLANK_MAX_CHARS) return false;
9918
+ return !isAcknowledgement(trimmed);
9919
+ }
9780
9920
  // src/agent/hooks.ts
9781
9921
  var HookDispatcher = class {
9782
9922
  constructor(manager, workDir) {
@@ -10080,6 +10220,14 @@ function announcedButIdleNote() {
10080
10220
  "\u771F\u505A\u4E0D\u4E0B\u53BB\uFF08\u7F3A\u51ED\u636E\u3001\u8981\u82B1\u94B1\u3001\u53D6\u6570\u4E00\u76F4\u5931\u8D25\uFF09\u5C31\u8BF4\u6E05\u5361\u5728\u54EA\u4E00\u6B65\u7684\u54EA\u4E00\u73AF\u3002"
10081
10221
  ].join("\n");
10082
10222
  }
10223
+ function blankResponseNote(chars) {
10224
+ return [
10225
+ `\u4F60\u4E0A\u4E00\u8F6E\u628A\u5DE5\u5177\u8DD1\u5B8C\u4E86\uFF0C\u4F46\u4EA4\u5230\u7528\u6237\u5C4F\u5E55\u4E0A\u7684\u6B63\u6587\u53EA\u6709 ${chars} \u4E2A\u5B57 \u2014\u2014 \u5728\u7528\u6237\u90A3\u8FB9\uFF0C\u8FD9\u4E00\u8F6E\u7B49\u4E8E\u6CA1\u6709\u56DE\u590D\u3002`,
10226
+ "\u73B0\u5728\u628A\u7ED3\u8BBA\u5B8C\u6574\u5199\u51FA\u6765\uFF1A\u7528\u6237\u95EE\u7684\u90A3\u4EF6\u4E8B\uFF0C\u7B54\u6848\u662F\u4EC0\u4E48\u3002\u522B\u53EA\u56DE\u4E00\u53E5\u300C\u597D\u7684\u300D\u300C\u5B8C\u6210\u4E86\u300D\u300C\u5DF2\u5904\u7406\u300D\u3002",
10227
+ "\u5982\u679C\u4F60\u89C9\u5F97\u81EA\u5DF1\u4E0A\u4E00\u8F6E\u5176\u5B9E\u5DF2\u7ECF\u7B54\u5B8C\u4E86\uFF0C\u90A3\u5C31\u628A\u90A3\u6BB5\u7ED3\u8BBA\u5B8C\u6574\u5730\u518D\u8BF4\u4E00\u904D \u2014\u2014 \u5B83\u6CA1\u6709\u5230\u8FBE\u7528\u6237\u3002",
10228
+ "\u4E0A\u4E00\u8F6E\u7684\u5DE5\u5177\u7ED3\u679C\u90FD\u8FD8\u5728\u4E0A\u9762\u7684\u4E0A\u4E0B\u6587\u91CC\uFF0C\u76F4\u63A5\u636E\u6B64\u4F5C\u7B54\uFF0C\u522B\u628A\u90A3\u4E9B\u5DE5\u5177\u91CD\u8DD1\u4E00\u904D\u3002"
10229
+ ].join("\n");
10230
+ }
10083
10231
  var CODE_VERIFICATION_POLICY = [
10084
10232
  "<code_verification>",
10085
10233
  "\u6539\u5B8C\u4EE3\u7801\u3001\u5BA3\u5E03\u5B8C\u6210\u4E4B\u524D\uFF0C\u8C03\u4E00\u6B21 `lsp_diagnostics`\uFF0C\u628A\u672C\u8F6E\u65B0\u5EFA\u6216\u4FEE\u6539\u8FC7\u7684\u6E90\u6587\u4EF6\u5217\u8FDB\u53BB\u3002",
@@ -10123,11 +10271,11 @@ var PromptBuilder = class {
10123
10271
  memoryInitialized = false;
10124
10272
  projectBlock(tools) {
10125
10273
  const permLevel = this.deps.permissionManager?.getLevel() || "default";
10126
- const hasPlanTool = tools.some((t78) => t78.name === "enter_plan_mode");
10127
- const hasLspTool = tools.some((t78) => t78.name === "lsp_diagnostics");
10128
- const hasAskTool = tools.some((t78) => t78.name === "ask_user_question");
10129
- const hasTodoTool = tools.some((t78) => t78.name === "todo");
10130
- const hasTerminal = tools.some((t78) => t78.name === "terminal");
10274
+ const hasPlanTool = tools.some((t81) => t81.name === "enter_plan_mode");
10275
+ const hasLspTool = tools.some((t81) => t81.name === "lsp_diagnostics");
10276
+ const hasAskTool = tools.some((t81) => t81.name === "ask_user_question");
10277
+ const hasTodoTool = tools.some((t81) => t81.name === "todo");
10278
+ const hasTerminal = tools.some((t81) => t81.name === "terminal");
10131
10279
  const needsCommandApproval = hasTerminal && permLevel === "default";
10132
10280
  const plan = this.deps.approvedPlan?.()?.trim();
10133
10281
  const codeSdk = renderSdkDeclaration(this.deps.codeModeTools?.() ?? []);
@@ -11006,8 +11154,8 @@ function imageParts(content) {
11006
11154
  return typeof content === "string" ? [] : content.filter((p) => p.type === "image");
11007
11155
  }
11008
11156
  function toolSignatureOf(config, tools) {
11009
- const direct = tools.map((t78) => t78.name).join("\0");
11010
- const declared = (config.codeModeTools?.() ?? []).map((t78) => t78.name).join("\0");
11157
+ const direct = tools.map((t81) => t81.name).join("\0");
11158
+ const declared = (config.codeModeTools?.() ?? []).map((t81) => t81.name).join("\0");
11011
11159
  return declared ? `${direct}|${declared}` : direct;
11012
11160
  }
11013
11161
  function modelSignatureOf(info) {
@@ -11126,6 +11274,15 @@ var AgentLoop = class {
11126
11274
  isAborted(signal) {
11127
11275
  return this.aborted || signal?.aborted === true;
11128
11276
  }
11277
+ async *drainSteer(input, messages) {
11278
+ const items = input.steer?.take() ?? [];
11279
+ for (const item of items) {
11280
+ const text = contentToText(item);
11281
+ const parts = typeof item === "string" ? void 0 : item;
11282
+ messages.push({ role: "user", content: text, ...parts ? { parts } : {} });
11283
+ yield { type: "steer", text, ...parts ? { parts } : {} };
11284
+ }
11285
+ }
11129
11286
  contextBreakdown(opts) {
11130
11287
  const seg2 = this.prompt.segments();
11131
11288
  return buildContextBreakdown({
@@ -11310,6 +11467,8 @@ var AgentLoop = class {
11310
11467
  const taskNotice = new TaskNoticeTracker(this.config.backgroundTasks);
11311
11468
  let todoNudged = false;
11312
11469
  let idleNudged = false;
11470
+ let blankNudged = false;
11471
+ let blankAfterNudge = false;
11313
11472
  for (let turn = 1; turn <= maxTurns; turn++) {
11314
11473
  if (this.isAborted(input.signal)) {
11315
11474
  yield finish("aborted");
@@ -11332,6 +11491,7 @@ var AgentLoop = class {
11332
11491
  }
11333
11492
  const notice2 = taskNotice.notice();
11334
11493
  if (notice2) messages.push({ role: "user", content: notice2 });
11494
+ if (turn > 1) yield* this.drainSteer(input, messages);
11335
11495
  this.hooks.fire("turn:before", {
11336
11496
  sessionId: input.sessionId,
11337
11497
  userMessage: transformed,
@@ -11409,7 +11569,8 @@ var AgentLoop = class {
11409
11569
  tools,
11410
11570
  system,
11411
11571
  maxSteps: 1,
11412
- ...isAbortSignal(input.signal) ? { signal: input.signal } : {}
11572
+ ...isAbortSignal(input.signal) ? { signal: input.signal } : {},
11573
+ ...this.config.maxOutputTokens ? { maxTokens: this.config.maxOutputTokens } : {}
11413
11574
  },
11414
11575
  streaming,
11415
11576
  ...guard ? { guard } : {},
@@ -11561,6 +11722,11 @@ ${finalText}` };
11561
11722
  usage: result.usage,
11562
11723
  turn
11563
11724
  });
11725
+ if (turn < maxTurns && input.steer?.pending() === true) {
11726
+ messages.push({ role: "assistant", content: finalText || NO_OUTPUT_TEXT });
11727
+ yield* this.drainSteer(input, messages);
11728
+ continue;
11729
+ }
11564
11730
  const wantContinue = await this.hooks.wantsContinue(
11565
11731
  input.sessionId,
11566
11732
  finalText,
@@ -11578,6 +11744,23 @@ ${finalText}` };
11578
11744
  );
11579
11745
  continue;
11580
11746
  }
11747
+ const didToolWork = turns.some((r) => r.toolCalls.length > 0);
11748
+ if (!truncated && blankFinish(finalText, didToolWork)) {
11749
+ if (!blankNudged && turn < maxTurns) {
11750
+ blankNudged = true;
11751
+ yield {
11752
+ type: "notice",
11753
+ code: "blank-response",
11754
+ text: t("agent_run.blank_response")
11755
+ };
11756
+ messages.push(
11757
+ { role: "assistant", content: finalText || NO_OUTPUT_TEXT },
11758
+ { role: "user", content: systemNote(blankResponseNote(finalText.trim().length)) }
11759
+ );
11760
+ continue;
11761
+ }
11762
+ blankAfterNudge = blankNudged;
11763
+ }
11581
11764
  if (!todoNudged && turn < maxTurns) {
11582
11765
  const open = this.config.pendingTodos?.(input.sessionId);
11583
11766
  if (open !== void 0 && open > 0) {
@@ -11606,8 +11789,8 @@ ${finalText}` };
11606
11789
  totalTokens: totalInput + totalOutput,
11607
11790
  turns
11608
11791
  });
11609
- this.maybeLearn(userText, finalText);
11610
- yield finish(truncated ? "length" : "stop");
11792
+ if (!blankAfterNudge) this.maybeLearn(userText, finalText);
11793
+ yield finish(truncated ? "length" : blankAfterNudge ? "blank" : "stop");
11611
11794
  return;
11612
11795
  }
11613
11796
  messages.push({
@@ -11801,7 +11984,12 @@ ${finalText}` };
11801
11984
  "epoch.summary_skipped": compressed.summarySkipped === true,
11802
11985
  "epoch.pruned_tokens": compressed.prunedTokens
11803
11986
  });
11804
- return { messages: compressed.messages.map((m) => unflattenMessage(m)), ...bill };
11987
+ return {
11988
+ messages: compressed.messages.map((m) => unflattenMessage(m)),
11989
+ ...bill,
11990
+ ...compressed.carriedHead === void 0 ? {} : { carriedHead: compressed.carriedHead },
11991
+ ...compressed.carriedTail === void 0 ? {} : { carriedTail: compressed.carriedTail }
11992
+ };
11805
11993
  } catch {
11806
11994
  return { messages };
11807
11995
  }
@@ -11955,6 +12143,11 @@ var ArtifactsSchema = z.object({
11955
12143
  maxAgeDays: z.int().positive().max(3650).default(ARTIFACT_RETENTION_DEFAULTS.maxAgeDays),
11956
12144
  maxTotalBytes: z.int().positive().default(ARTIFACT_RETENTION_DEFAULTS.maxTotalBytes)
11957
12145
  });
12146
+ var SessionsSchema = z.object({
12147
+ autoPrune: z.boolean().default(false),
12148
+ retentionDays: z.int().positive().max(3650).default(90),
12149
+ vacuumAfterPrune: z.boolean().default(true)
12150
+ });
11958
12151
  var TelemetrySchema = z.object({
11959
12152
  enabled: z.boolean().optional(),
11960
12153
  target: z.enum(["file", "console", "otlp"]).optional(),
@@ -11968,6 +12161,7 @@ var EpochConfigSchema = z.object({
11968
12161
  shell: z.enum(SHELL_KINDS).optional(),
11969
12162
  maxTurns: z.int().nonnegative().default(DEFAULT_MAX_TURNS),
11970
12163
  contextLength: z.int().positive().default(2e5),
12164
+ maxOutputTokens: z.int().positive().optional(),
11971
12165
  homeDir: z.string().min(1).default(() => resolveHomeDir()),
11972
12166
  dbPath: z.string().min(1).default(() => dbPath(resolveHomeDir())),
11973
12167
  permission: z.enum(PERMISSION_LEVELS).default("default"),
@@ -11991,6 +12185,7 @@ var EpochConfigSchema = z.object({
11991
12185
  compression: CompressionSchema.prefault({}),
11992
12186
  memory: MemorySchema.prefault({}),
11993
12187
  artifacts: ArtifactsSchema.prefault({}),
12188
+ sessions: SessionsSchema.prefault({}),
11994
12189
  budget: BudgetSchema.optional(),
11995
12190
  compliance: ComplianceSchema.optional(),
11996
12191
  headless: HeadlessSchema.optional(),
@@ -12212,12 +12407,12 @@ function finishLayer(source, read, execTrusted, issues) {
12212
12407
  status: gated ? "gated" : "loaded",
12213
12408
  lists: checked.lists,
12214
12409
  scalars: {},
12215
- detail: describe4(layer, gated, checked.lists)
12410
+ detail: describe5(layer, gated, checked.lists)
12216
12411
  },
12217
12412
  file: { ...file, permissions: checked.lists }
12218
12413
  };
12219
12414
  }
12220
- function describe4(layer, gated, lists) {
12415
+ function describe5(layer, gated, lists) {
12221
12416
  const label = layerLabel(layer);
12222
12417
  if (gated) {
12223
12418
  const deny = lists.deny?.length ?? 0;
@@ -12476,7 +12671,11 @@ function parseRawConfig(raw, issues, track) {
12476
12671
  const migrated = migrateRawConfig(expanded);
12477
12672
  issues.push(...migrated.issues);
12478
12673
  issues.push(...unknownKeyIssues(CONFIG_KEYS, migrated.raw));
12479
- const outcome = parseLenient(EpochConfigSchema, dropEmptySections(migrated.raw), defaultConfig());
12674
+ const outcome = parseLenient(
12675
+ EpochConfigSchema,
12676
+ dropEmptySections(migrated.raw),
12677
+ EpochConfigSchema.parse({})
12678
+ );
12480
12679
  issues.push(...outcome.issues);
12481
12680
  if (outcome.issues.length === 0) collectKeyPaths(migrated.raw, track.file);
12482
12681
  return outcome.value;
@@ -13086,6 +13285,7 @@ function getCapability(modelId, homeDir, provider) {
13086
13285
  }
13087
13286
  return {
13088
13287
  contextLength: DEFAULT_CONTEXT_LENGTH2,
13288
+ contextLengthUnknown: true,
13089
13289
  maxOutputTokens: 4096,
13090
13290
  supportsTools: true,
13091
13291
  ...images,
@@ -13598,7 +13798,7 @@ var ProviderRouter = class {
13598
13798
  }
13599
13799
  async recover(err, state) {
13600
13800
  const { code, recovery } = classifyProviderError(err);
13601
- const message = err instanceof Error ? err.message : String(err);
13801
+ const message = describeProviderError(err);
13602
13802
  const stay = { kind: "continue", ct: state.ct, cm: state.cm };
13603
13803
  if (code === PROVIDER_ABORTED) return { kind: "give-up", message, code };
13604
13804
  if (recovery === "rotate_credential" && this.rotateCredential())
@@ -13789,7 +13989,7 @@ var ProviderRouter = class {
13789
13989
  } catch (err) {
13790
13990
  const cause = streamPartError ?? err;
13791
13991
  if (emitted) {
13792
- yield { type: "error", error: cause instanceof Error ? cause.message : String(cause) };
13992
+ yield { type: "error", error: describeProviderError(cause) };
13793
13993
  return;
13794
13994
  }
13795
13995
  const plan = await this.recover(cause, state);
@@ -14033,6 +14233,7 @@ var SETTING_WRITE_KEYS = [
14033
14233
  "models.utility",
14034
14234
  "fallback.model",
14035
14235
  "contextLength",
14236
+ "maxOutputTokens",
14036
14237
  "compression.enabled",
14037
14238
  "compression.threshold",
14038
14239
  "memory.memoryCharLimit",
@@ -14042,6 +14243,9 @@ var SETTING_WRITE_KEYS = [
14042
14243
  "budget.maxTokens",
14043
14244
  "budget.warnAtPercent",
14044
14245
  "budget.onUnknownPricing",
14246
+ "sessions.autoPrune",
14247
+ "sessions.retentionDays",
14248
+ "sessions.vacuumAfterPrune",
14045
14249
  "permission"
14046
14250
  ];
14047
14251
  function isWritableSettingKey(value) {
@@ -14096,6 +14300,7 @@ var VALUE_SCHEMA = {
14096
14300
  "models.utility": EpochConfigSchema.shape.models.unwrap().shape.utility.unwrap(),
14097
14301
  "fallback.model": EpochConfigSchema.shape.fallback.unwrap().shape.model.unwrap(),
14098
14302
  contextLength: EpochConfigSchema.shape.contextLength.unwrap(),
14303
+ maxOutputTokens: EpochConfigSchema.shape.maxOutputTokens.unwrap(),
14099
14304
  "compression.enabled": EpochConfigSchema.shape.compression.unwrap().shape.enabled.unwrap(),
14100
14305
  "compression.threshold": EpochConfigSchema.shape.compression.unwrap().shape.threshold.unwrap(),
14101
14306
  "memory.memoryCharLimit": EpochConfigSchema.shape.memory.unwrap().shape.memoryCharLimit.unwrap(),
@@ -14105,6 +14310,9 @@ var VALUE_SCHEMA = {
14105
14310
  "budget.maxTokens": EpochConfigSchema.shape.budget.unwrap().shape.maxTokens.unwrap(),
14106
14311
  "budget.warnAtPercent": EpochConfigSchema.shape.budget.unwrap().shape.warnAtPercent.unwrap(),
14107
14312
  "budget.onUnknownPricing": EpochConfigSchema.shape.budget.unwrap().shape.onUnknownPricing.unwrap(),
14313
+ "sessions.autoPrune": EpochConfigSchema.shape.sessions.unwrap().shape.autoPrune.unwrap(),
14314
+ "sessions.retentionDays": EpochConfigSchema.shape.sessions.unwrap().shape.retentionDays.unwrap(),
14315
+ "sessions.vacuumAfterPrune": EpochConfigSchema.shape.sessions.unwrap().shape.vacuumAfterPrune.unwrap(),
14108
14316
  permission: EpochConfigSchema.shape.permission.unwrap()
14109
14317
  };
14110
14318
  function settingValueKind(key) {
@@ -14513,11 +14721,11 @@ function buildSearchQuery(query) {
14513
14721
  }
14514
14722
  const latinPart = cleaned.replace(CJK_RUN, " ");
14515
14723
  for (const w of latinPart.split(/\s+/)) {
14516
- const t78 = w.trim();
14517
- if (t78.length >= 2) terms.add(t78);
14724
+ const t81 = w.trim();
14725
+ if (t81.length >= 2) terms.add(t81);
14518
14726
  }
14519
14727
  if (terms.size === 0) return null;
14520
- return [...terms].map((t78) => `"${t78.replace(/"/g, "")}"`).join(" OR ");
14728
+ return [...terms].map((t81) => `"${t81.replace(/"/g, "")}"`).join(" OR ");
14521
14729
  }
14522
14730
  // src/memory/db.ts
14523
14731
  var NS2 = "memory";
@@ -15846,6 +16054,27 @@ var SESSION_MIGRATIONS = [
15846
16054
  up: (db) => {
15847
16055
  db.exec(`ALTER TABLE sessions ADD COLUMN priced_call_count INTEGER NOT NULL DEFAULT 0;`);
15848
16056
  }
16057
+ },
16058
+ {
16059
+ id: "session-meta-kv",
16060
+ version: 11,
16061
+ description: "\u7EF4\u62A4\u7528\u7684 key/value \u8868\uFF08\u81EA\u52A8\u6E05\u7406\u7684\u8282\u6D41\u65F6\u523B\uFF0C2026-09-15\uFF09",
16062
+ up: (db) => {
16063
+ db.exec(`
16064
+ CREATE TABLE IF NOT EXISTS session_meta (
16065
+ key TEXT PRIMARY KEY,
16066
+ value TEXT NOT NULL
16067
+ );
16068
+ `);
16069
+ }
16070
+ },
16071
+ {
16072
+ id: "sessions-open-turn-from",
16073
+ version: 13,
16074
+ description: "\u4F1A\u8BDD\u8868\u52A0 open_turn_from \u4E00\u5217\uFF08\u88AB\u4E2D\u65AD\u7684\u90A3\u4E00\u8F6E\u8BA4\u5F97\u51FA\u6765\uFF0C2026-09-16\uFF09",
16075
+ up: (db) => {
16076
+ db.exec(`ALTER TABLE sessions ADD COLUMN open_turn_from INTEGER`);
16077
+ }
15849
16078
  }
15850
16079
  ];
15851
16080
  var FTS_EXTERNAL_SCHEMA = `
@@ -15896,7 +16125,7 @@ var FTS_EXTERNAL_SCHEMA = `
15896
16125
  var FTS_EXTERNAL_MIGRATIONS = [
15897
16126
  {
15898
16127
  id: "fts-external-content",
15899
- version: 10,
16128
+ version: 14,
15900
16129
  description: "\u4E24\u5F20 FTS \u8868\u6539\u6210\u5916\u90E8\u5185\u5BB9\u8868\uFF08\u6B63\u6587\u4E0D\u518D\u5B58\u4E09\u4EFD\uFF0C2026-08-21\uFF09",
15901
16130
  up: (db) => {
15902
16131
  db.exec(FTS_EXTERNAL_SCHEMA);
@@ -16092,12 +16321,27 @@ var SessionDB = class {
16092
16321
  }
16093
16322
  getMessages(sessionId, activeOnly = true) {
16094
16323
  const where = activeOnly ? "session_id = ? AND active = 1" : "session_id = ?";
16095
- const rows = this.db.prepare(`SELECT * FROM messages WHERE ${where} ORDER BY timestamp ASC`).all(sessionId);
16324
+ const rows = this.db.prepare(`SELECT * FROM messages WHERE ${where} ORDER BY timestamp ASC, id ASC`).all(sessionId);
16096
16325
  return rows.map((r) => this.rowToMessage(r));
16097
16326
  }
16098
16327
  markObserved(sessionId, messageId) {
16099
16328
  this.db.prepare("UPDATE messages SET observed = 1 WHERE session_id = ? AND id <= ?").run(sessionId, messageId);
16100
16329
  }
16330
+ attachTurnFacts(sessionId, messageId, input) {
16331
+ const sets = [];
16332
+ if (input.turnFacts !== void 0) sets.push("turn_facts = @turnFacts");
16333
+ if (input.finishReason !== void 0) sets.push("finish_reason = @finishReason");
16334
+ if (sets.length === 0) return;
16335
+ this.db.prepare(`UPDATE messages SET ${sets.join(", ")} WHERE session_id = @sessionId AND id = @id`).run({
16336
+ sessionId,
16337
+ id: messageId,
16338
+ turnFacts: encodeTurnFacts(input.turnFacts),
16339
+ finishReason: input.finishReason ?? null
16340
+ });
16341
+ }
16342
+ setOpenTurn(sessionId, from) {
16343
+ this.db.prepare("UPDATE sessions SET open_turn_from = ? WHERE id = ?").run(from, sessionId);
16344
+ }
16101
16345
  lastMessageId(sessionId) {
16102
16346
  const row = this.db.prepare("SELECT MAX(id) AS maxId FROM messages WHERE session_id = ?").get(sessionId);
16103
16347
  return row?.maxId ?? 0;
@@ -16199,6 +16443,46 @@ var SessionDB = class {
16199
16443
  }
16200
16444
  return { results };
16201
16445
  }
16446
+ pruneCandidates(input) {
16447
+ const clauses = ["ended_at IS NOT NULL", "updated_at < @cutoff"];
16448
+ const params = { cutoff: input.olderThanMs };
16449
+ if (typeof input.archived === "boolean") {
16450
+ clauses.push("archived = @archived");
16451
+ params["archived"] = input.archived ? 1 : 0;
16452
+ }
16453
+ if (!input.includePinned) clauses.push("COALESCE(pinned, 0) = 0");
16454
+ const rows = this.db.prepare(`SELECT * FROM sessions WHERE ${clauses.join(" AND ")} ORDER BY updated_at ASC`).all(params);
16455
+ return rows.map((r) => this.rowToMeta(r));
16456
+ }
16457
+ openPruneMatches(input) {
16458
+ const clauses = ["ended_at IS NULL", "updated_at < @cutoff"];
16459
+ if (!input.includePinned) clauses.push("COALESCE(pinned, 0) = 0");
16460
+ const row = this.db.prepare(`SELECT COUNT(*) AS n FROM sessions WHERE ${clauses.join(" AND ")}`).get({ cutoff: input.olderThanMs });
16461
+ return row.n;
16462
+ }
16463
+ freelistRatio() {
16464
+ const pages = Number(this.db.pragma("page_count", { simple: true }));
16465
+ if (pages <= 0) return 0;
16466
+ return Number(this.db.pragma("freelist_count", { simple: true })) / pages;
16467
+ }
16468
+ getMeta(key) {
16469
+ const row = this.db.prepare("SELECT value FROM session_meta WHERE key = ?").get(key);
16470
+ return row?.value ?? null;
16471
+ }
16472
+ setMeta(key, value) {
16473
+ this.db.prepare(
16474
+ "INSERT INTO session_meta (key, value) VALUES (@key, @value) ON CONFLICT(key) DO UPDATE SET value = @value"
16475
+ ).run({ key, value });
16476
+ }
16477
+ claimMaintenanceSlot(key, minIntervalMs, now) {
16478
+ const run = this.db.transaction(() => {
16479
+ const last = this.getMeta(key);
16480
+ if (last !== null && now - Number(last) < minIntervalMs) return false;
16481
+ this.setMeta(key, String(now));
16482
+ return true;
16483
+ });
16484
+ return run();
16485
+ }
16202
16486
  compact(sessionId, summary, beforeCount, keep) {
16203
16487
  const messages = this.db.prepare(
16204
16488
  "SELECT id FROM messages WHERE session_id = ? AND active = 1 ORDER BY timestamp DESC"
@@ -16217,6 +16501,29 @@ var SessionDB = class {
16217
16501
  duration: 0
16218
16502
  };
16219
16503
  }
16504
+ archiveAndCompact(sessionId, input) {
16505
+ const run = this.db.transaction(() => {
16506
+ const rows = this.db.prepare(
16507
+ "SELECT id, timestamp FROM messages WHERE session_id = ? AND active = 1 AND id <= ? ORDER BY timestamp ASC, id ASC"
16508
+ ).all(sessionId, input.watermark);
16509
+ const end = rows.length - input.tailCount;
16510
+ const middle = end > input.headCount ? rows.slice(input.headCount, end) : [];
16511
+ if (middle.length === 0) return null;
16512
+ const mark = this.db.prepare("UPDATE messages SET active = 0, compacted = 1 WHERE id = ?");
16513
+ for (const row of middle) mark.run(row.id);
16514
+ const summaryId = this.nextMessageId();
16515
+ this.insertMessage({
16516
+ sessionId,
16517
+ id: summaryId,
16518
+ role: "user",
16519
+ content: input.summary,
16520
+ timestamp: middle[0].timestamp
16521
+ });
16522
+ this.db.prepare("UPDATE sessions SET summary = @s WHERE id = @id").run({ s: input.summary, id: sessionId });
16523
+ return { archived: middle.length, summaryId };
16524
+ });
16525
+ return run();
16526
+ }
16220
16527
  getSummary(sessionId) {
16221
16528
  const row = this.db.prepare("SELECT summary FROM sessions WHERE id = ?").get(sessionId);
16222
16529
  return row?.summary ?? null;
@@ -16303,6 +16610,7 @@ var SessionDB = class {
16303
16610
  workspaceRoot: row["workspace_root"] ?? void 0,
16304
16611
  startedAt: new Date(row["started_at"]),
16305
16612
  updatedAt: new Date(row["updated_at"] ?? row["started_at"]),
16613
+ openTurnFrom: row["open_turn_from"] ?? null,
16306
16614
  endedAt: row["ended_at"] ? new Date(row["ended_at"]) : void 0,
16307
16615
  endReason: row["end_reason"]
16308
16616
  };
@@ -16415,7 +16723,7 @@ function checkFtsHealth(db) {
16415
16723
  messages,
16416
16724
  tables,
16417
16725
  missingTriggers,
16418
- healthy: missingTriggers.length === 0 && tables.every((t78) => t78.error === null && t78.drift === null && t78.rows === messages),
16726
+ healthy: missingTriggers.length === 0 && tables.every((t81) => t81.error === null && t81.drift === null && t81.rows === messages),
16419
16727
  indexBytes: indexBytesOf(db),
16420
16728
  space: spaceOf(db)
16421
16729
  };
@@ -16561,6 +16869,7 @@ var SessionReferences = class {
16561
16869
  }
16562
16870
  };
16563
16871
  // src/session/manager.ts
16872
+ var AUTO_VACUUM_MIN_FREELIST_RATIO = 0.25;
16564
16873
  var SessionManager = class {
16565
16874
  db;
16566
16875
  queries;
@@ -16655,6 +16964,44 @@ var SessionManager = class {
16655
16964
  unarchive(id) {
16656
16965
  this.db.unarchiveSession(id);
16657
16966
  }
16967
+ pruneCandidates(input) {
16968
+ return this.db.pruneCandidates(input);
16969
+ }
16970
+ openPruneMatches(input) {
16971
+ return this.db.openPruneMatches(input);
16972
+ }
16973
+ freelistRatio() {
16974
+ return this.db.freelistRatio();
16975
+ }
16976
+ maybeAutoPrune(opts) {
16977
+ const result = { skipped: false, pruned: 0, vacuumed: false };
16978
+ if (!opts.enabled) return { ...result, skipped: true };
16979
+ const now = opts.now?.() ?? Date.now();
16980
+ const minInterval = opts.minIntervalMs ?? 24 * 60 * 60 * 1e3;
16981
+ const minVacuumInterval = opts.minVacuumIntervalMs ?? 30 * 24 * 60 * 60 * 1e3;
16982
+ try {
16983
+ if (!this.db.claimMaintenanceSlot("last_auto_prune", minInterval, now)) {
16984
+ return { ...result, skipped: true };
16985
+ }
16986
+ const cutoff = now - opts.retentionDays * 24 * 60 * 60 * 1e3;
16987
+ const victims = this.db.pruneCandidates({ olderThanMs: cutoff });
16988
+ let pruned = 0;
16989
+ for (const s of victims) if (this.db.deleteSession(s.id)) pruned++;
16990
+ let vacuumed = false;
16991
+ if (opts.vacuum && pruned > 0) {
16992
+ const lastVacuum = this.db.getMeta("last_vacuum");
16993
+ const vacuumDue = lastVacuum === null || now - Number(lastVacuum) >= minVacuumInterval;
16994
+ if (vacuumDue && this.db.freelistRatio() > AUTO_VACUUM_MIN_FREELIST_RATIO) {
16995
+ const report3 = reclaimFtsSpace(this.db.db, true);
16996
+ vacuumed = report3.vacuumed;
16997
+ if (vacuumed) this.db.setMeta("last_vacuum", String(now));
16998
+ }
16999
+ }
17000
+ return { skipped: false, pruned, vacuumed };
17001
+ } catch (cause) {
17002
+ return { ...result, error: cause instanceof Error ? cause.message : String(cause) };
17003
+ }
17004
+ }
16658
17005
  delete(id) {
16659
17006
  return this.db.deleteSession(id);
16660
17007
  }
@@ -16665,11 +17012,18 @@ var SessionManager = class {
16665
17012
  const id = this.db.nextMessageId();
16666
17013
  this.db.insertMessage({ ...msg, sessionId, id, timestamp: Date.now() });
16667
17014
  const meta = this.db.getSessionMeta(sessionId);
16668
- if (!meta) return;
17015
+ if (!meta) return id;
16669
17016
  if (!meta.title && msg.role === "user") {
16670
17017
  const title = msg.content.slice(0, 50).replace(/\n/g, " ");
16671
17018
  this.db.updateSessionMeta(sessionId, { title });
16672
17019
  }
17020
+ return id;
17021
+ }
17022
+ attachTurnFacts(sessionId, messageId, input) {
17023
+ this.db.attachTurnFacts(sessionId, messageId, input);
17024
+ }
17025
+ setOpenTurn(sessionId, from) {
17026
+ this.db.setOpenTurn(sessionId, from);
16673
17027
  }
16674
17028
  recordUsage(sessionId, usage) {
16675
17029
  this.db.recordUsage(sessionId, usage);
@@ -16705,6 +17059,9 @@ var SessionManager = class {
16705
17059
  const summary = toSummarize.length === 0 ? "" : await this.buildSummary(toSummarize, summarize3) ?? outlineOf(toSummarize);
16706
17060
  return this.db.compact(sessionId, summary, beforeCount, IMPORTANT_ROUNDS * 2);
16707
17061
  }
17062
+ archiveAndCompact(sessionId, input) {
17063
+ return this.db.archiveAndCompact(sessionId, input);
17064
+ }
16708
17065
  async buildSummary(msgs, summarize3) {
16709
17066
  if (!summarize3) return null;
16710
17067
  const transcript = msgs.map((m) => `[${m.role}] ${m.content}`).join("\n\n");
@@ -17114,7 +17471,7 @@ function inspect(input, resolved, root, accepted) {
17114
17471
  }
17115
17472
  var MAX_RECENT_WORKSPACES = 20;
17116
17473
  var FILE_VERSION2 = 1;
17117
- function describe5(err) {
17474
+ function describe6(err) {
17118
17475
  return err instanceof Error ? err.message : String(err);
17119
17476
  }
17120
17477
  var RecentWorkspaces = class {
@@ -17131,8 +17488,8 @@ var RecentWorkspaces = class {
17131
17488
  }
17132
17489
  remember(dir, now, name) {
17133
17490
  const root = resolve(dir);
17134
- const kept = this.entries.find((e) => e.root === root)?.name;
17135
- const rest = this.entries.filter((e) => e.root !== root);
17491
+ const kept = this.entries.find((e) => samePath(e.root, root))?.name;
17492
+ const rest = this.entries.filter((e) => !samePath(e.root, root));
17136
17493
  this.entries = [
17137
17494
  { root, name: name || kept || basename(root) || root, usedAt: now },
17138
17495
  ...rest
@@ -17141,7 +17498,7 @@ var RecentWorkspaces = class {
17141
17498
  }
17142
17499
  forget(dir) {
17143
17500
  const root = resolve(dir);
17144
- const next = this.entries.filter((e) => e.root !== root);
17501
+ const next = this.entries.filter((e) => !samePath(e.root, root));
17145
17502
  if (next.length === this.entries.length) return;
17146
17503
  this.entries = next;
17147
17504
  this.save();
@@ -17154,7 +17511,7 @@ var RecentWorkspaces = class {
17154
17511
  parsed = JSON.parse(readFileSync(this.filePath, "utf-8"));
17155
17512
  } catch (err) {
17156
17513
  this.loadErrors.push(
17157
- (lang) => t("workspace.recent_unreadable", { path: this.filePath, reason: describe5(err) }, lang)
17514
+ (lang) => t("workspace.recent_unreadable", { path: this.filePath, reason: describe6(err) }, lang)
17158
17515
  );
17159
17516
  return;
17160
17517
  }
@@ -17207,7 +17564,7 @@ var RecentWorkspaces = class {
17207
17564
  } catch (err) {
17208
17565
  rmSync(tmp, { force: true });
17209
17566
  this.writeErrors.push(
17210
- (lang) => t("workspace.recent_write_failed", { path: this.filePath, reason: describe5(err) }, lang)
17567
+ (lang) => t("workspace.recent_write_failed", { path: this.filePath, reason: describe6(err) }, lang)
17211
17568
  );
17212
17569
  }
17213
17570
  }
@@ -17217,6 +17574,87 @@ function isRecentWorkspace(value) {
17217
17574
  const v = value;
17218
17575
  return typeof v["root"] === "string" && v["root"].length > 0 && typeof v["name"] === "string" && typeof v["usedAt"] === "number";
17219
17576
  }
17577
+ var MAX_LAST_OPEN_SESSIONS = 20;
17578
+ var FILE_VERSION3 = 1;
17579
+ function describe7(err) {
17580
+ return err instanceof Error ? err.message : String(err);
17581
+ }
17582
+ var LastOpenSessions = class {
17583
+ constructor(filePath = lastSessionsPath()) {
17584
+ this.filePath = filePath;
17585
+ this.load();
17586
+ }
17587
+ filePath;
17588
+ entries = [];
17589
+ loadErrors = [];
17590
+ writeErrors = [];
17591
+ get(root) {
17592
+ const key = resolve(root);
17593
+ return this.entries.find((e) => samePath(e.root, key))?.sessionId ?? null;
17594
+ }
17595
+ remember(root, sessionId, now) {
17596
+ const key = resolve(root);
17597
+ const head = this.entries[0];
17598
+ if (head && samePath(head.root, key) && head.sessionId === sessionId) return;
17599
+ const rest = this.entries.filter((e) => !samePath(e.root, key));
17600
+ this.entries = [{ root: key, sessionId, at: now }, ...rest].slice(0, MAX_LAST_OPEN_SESSIONS);
17601
+ this.save();
17602
+ }
17603
+ forget(root) {
17604
+ const key = resolve(root);
17605
+ const next = this.entries.filter((e) => !samePath(e.root, key));
17606
+ if (next.length === this.entries.length) return;
17607
+ this.entries = next;
17608
+ this.save();
17609
+ }
17610
+ load() {
17611
+ this.entries = [];
17612
+ if (!existsSync(this.filePath)) return;
17613
+ let parsed;
17614
+ try {
17615
+ parsed = JSON.parse(readFileSync(this.filePath, "utf-8"));
17616
+ } catch (err) {
17617
+ this.loadErrors.push(
17618
+ (lang) => t("last_session.unreadable", { path: this.filePath, reason: describe7(err) }, lang)
17619
+ );
17620
+ return;
17621
+ }
17622
+ this.adopt(parsed);
17623
+ }
17624
+ adopt(parsed) {
17625
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return;
17626
+ const file = parsed;
17627
+ if (file.version !== FILE_VERSION3) return;
17628
+ if (!Array.isArray(file.sessions)) return;
17629
+ this.entries = file.sessions.filter(isLastOpenSession).sort((a, b) => b.at - a.at).slice(0, MAX_LAST_OPEN_SESSIONS);
17630
+ }
17631
+ save() {
17632
+ const body2 = JSON.stringify(
17633
+ { version: FILE_VERSION3, sessions: this.entries },
17634
+ null,
17635
+ 2
17636
+ );
17637
+ const tmp = `${this.filePath}.${process.pid}.tmp`;
17638
+ try {
17639
+ mkdirSync(dirname(this.filePath), { recursive: true });
17640
+ writeFileSync(tmp, body2, { encoding: "utf-8", mode: 384 });
17641
+ renameSync(tmp, this.filePath);
17642
+ } catch (err) {
17643
+ rmSync(tmp, { force: true });
17644
+ this.writeErrors.push(
17645
+ (lang) => t("last_session.write_failed", { path: this.filePath, reason: describe7(err) }, lang)
17646
+ );
17647
+ }
17648
+ }
17649
+ };
17650
+ function isLastOpenSession(value) {
17651
+ if (typeof value !== "object" || value === null) return false;
17652
+ const v = value;
17653
+ return typeof v["root"] === "string" && v["root"].length > 0 && typeof v["sessionId"] === "string" && v["sessionId"].length > 0 && typeof v["at"] === "number";
17654
+ }
17655
+ function ruleAskActive(level) {
17656
+ return level !== "bypass";
17657
+ }
17220
17658
  function checkCodeExec(isolation) {
17221
17659
  if (isolation === "os") {
17222
17660
  return { allowed: true, reason: t("permission_reason.sandbox_os"), code: "sandbox-isolation" };
@@ -17228,8 +17666,7 @@ function checkCodeExec(isolation) {
17228
17666
  code: "sandbox-isolation"
17229
17667
  };
17230
17668
  }
17231
- function checkAuto(operation, isolation) {
17232
- if (operation.type === "code_exec") return checkCodeExec(isolation);
17669
+ function checkAuto() {
17233
17670
  return { allowed: true, code: "level-default" };
17234
17671
  }
17235
17672
  function checkPlan(operation) {
@@ -17287,7 +17724,7 @@ function decideByLevel(level, operation, isolation, extraRoots = []) {
17287
17724
  case "bypass":
17288
17725
  return { allowed: true, code: "level-default" };
17289
17726
  case "auto":
17290
- return checkAuto(operation, isolation);
17727
+ return checkAuto();
17291
17728
  case "plan":
17292
17729
  return checkPlan(operation);
17293
17730
  case "acceptEdits":
@@ -17465,11 +17902,11 @@ var ApprovalCache = class {
17465
17902
  return !rel.startsWith("..") && !isAbsolute(rel);
17466
17903
  }
17467
17904
  normalizeTarget(target) {
17468
- const t78 = target.trim();
17469
- if (!t78) return "";
17470
- const unix = t78.replace(/\\/g, "/");
17905
+ const t81 = target.trim();
17906
+ if (!t81) return "";
17907
+ const unix = t81.replace(/\\/g, "/");
17471
17908
  if (unix.startsWith("/") || /^[A-Za-z]:\//.test(unix)) return resolve(unix);
17472
- return t78;
17909
+ return t81;
17473
17910
  }
17474
17911
  load() {
17475
17912
  try {
@@ -17572,9 +18009,9 @@ function createSharedPermissionState(cache) {
17572
18009
  };
17573
18010
  }
17574
18011
  function cacheKeyFor(raw) {
17575
- const t78 = raw.trim();
17576
- if (!t78) return null;
17577
- return t78.slice(0, 500);
18012
+ const t81 = raw.trim();
18013
+ if (!t81) return null;
18014
+ return t81.slice(0, 500);
17578
18015
  }
17579
18016
  // src/permission/manager.ts
17580
18017
  var log3 = createLogger("permission");
@@ -17747,16 +18184,22 @@ var PermissionManager = class _PermissionManager {
17747
18184
  }
17748
18185
  const cached = this.approvalCacheActive() ? this.cachedDecision(operation) : null;
17749
18186
  if (cached) return cached;
17750
- if (listMatch?.verdict === "ask") {
17751
- return {
17752
- allowed: false,
17753
- requireApproval: true,
17754
- reason: t("permission_reason.rule_ask", { rule: listMatch.rule }),
17755
- code: "rule-match",
17756
- ...this.rememberFlag()
17757
- };
18187
+ const asked = listMatch?.verdict === "ask" ? {
18188
+ allowed: false,
18189
+ requireApproval: true,
18190
+ reason: t("permission_reason.rule_ask", { rule: listMatch.rule }),
18191
+ code: "rule-match"
18192
+ } : ruleDecision?.requireApproval ?? false ? ruleDecision : null;
18193
+ if (asked) {
18194
+ if (!ruleAskActive(this.level)) {
18195
+ return {
18196
+ allowed: true,
18197
+ reason: t("permission_reason.bypass_rule_ask", { reason: asked.reason ?? "" }),
18198
+ code: asked.code
18199
+ };
18200
+ }
18201
+ return { ...asked, ...this.rememberFlag() };
17758
18202
  }
17759
- if (ruleDecision?.requireApproval) return { ...ruleDecision, ...this.rememberFlag() };
17760
18203
  if (listMatch?.verdict === "allow") {
17761
18204
  return {
17762
18205
  allowed: true,
@@ -17904,10 +18347,13 @@ function byRule(rules, probe) {
17904
18347
  }
17905
18348
  return hit ? { ...hit, conditional } : { verdict: null, conditional };
17906
18349
  }
18350
+ function effectiveRules(rules, level) {
18351
+ return ruleAskActive(level) ? rules : { ...rules, ask: [] };
18352
+ }
17907
18353
  function gateForTool(tool, rules, level, isolation) {
17908
18354
  const type = mapOperation(tool);
17909
18355
  const probe = { type, toolName: tool.name };
17910
- const rule = byRule(rules, probe);
18356
+ const rule = byRule(effectiveRules(rules, level), probe);
17911
18357
  if (rule.verdict) {
17912
18358
  return {
17913
18359
  type,
@@ -18380,6 +18826,24 @@ function acquireScheduleLock(db, scheduleId, clock2 = Date.now) {
18380
18826
  }
18381
18827
  };
18382
18828
  }
18829
+ function isLive(holder, now) {
18830
+ if (holder.heartbeatAt < now - LOCK_STALE_MS) return false;
18831
+ return holder.host !== hostname() || pidAlive(holder.pid);
18832
+ }
18833
+ function listRunningSchedules(db, clock2 = Date.now) {
18834
+ const now = clock2();
18835
+ const rows = db.prepare(
18836
+ `SELECT schedule_id AS scheduleId, pid, host,
18837
+ acquired_at AS acquiredAt, heartbeat_at AS heartbeatAt
18838
+ FROM schedule_locks`
18839
+ ).all();
18840
+ return rows.filter((row) => isLive(row, now)).map((row) => ({
18841
+ scheduleId: row.scheduleId,
18842
+ startedAt: row.acquiredAt,
18843
+ pid: row.pid,
18844
+ host: row.host
18845
+ }));
18846
+ }
18383
18847
  function readHolder(db, scheduleId) {
18384
18848
  const row = db.prepare(
18385
18849
  "SELECT pid, host, acquired_at AS acquiredAt, heartbeat_at AS heartbeatAt FROM schedule_locks WHERE schedule_id = ?"
@@ -18481,6 +18945,12 @@ function pruneRecordings(dir, opts = {}) {
18481
18945
  }
18482
18946
  return { removed: removed.filter((p) => !existsSync(p)), remainingBytes: Math.max(0, total) };
18483
18947
  }
18948
+ function removeRecordings(dir) {
18949
+ try {
18950
+ rmSync(dir, { recursive: true, force: true });
18951
+ } catch {
18952
+ }
18953
+ }
18484
18954
  function readRecording(path) {
18485
18955
  if (!existsSync(path)) return [];
18486
18956
  const out = [];
@@ -18620,9 +19090,15 @@ var ScheduleRegistrar = class {
18620
19090
  this.opts.store.setEnabled(def.id, enabled);
18621
19091
  return { ok: false, reason: "unsupported-platform" };
18622
19092
  }
18623
- if (enabled) this.opts.store.setEnabled(def.id, true);
18624
- const res = def.osTaskId ? await backend.setEnabled(def.osTaskId, enabled) : { ok: true };
18625
- if (!enabled) this.opts.store.setEnabled(def.id, false);
19093
+ if (enabled) {
19094
+ this.opts.store.setEnabled(def.id, true);
19095
+ const on = { ...def, enabled: true };
19096
+ if (!def.osTaskId) return this.register(on);
19097
+ const res2 = await backend.setEnabled(def.osTaskId, true);
19098
+ return res2.ok ? { ok: true, warnings: [] } : this.register(on);
19099
+ }
19100
+ const res = def.osTaskId ? await backend.setEnabled(def.osTaskId, false) : { ok: true };
19101
+ this.opts.store.setEnabled(def.id, false);
18626
19102
  return res.ok ? { ok: true, warnings: [] } : { ok: false, reason: "backend-error", detail: res.detail };
18627
19103
  }
18628
19104
  async retire(def) {
@@ -19733,7 +20209,7 @@ function runCommandHook(config, event, workDir) {
19733
20209
  const baseEnv = sanitizeEnvironment(process.env);
19734
20210
  const injectedEnv = injectEpochEnv(event, config.pluginRoot);
19735
20211
  const hookEnv = { ...baseEnv, ...injectedEnv, ...config.env };
19736
- return new Promise((resolve15) => {
20212
+ return new Promise((resolve16) => {
19737
20213
  const child = spawn(config.command, {
19738
20214
  shell: true,
19739
20215
  cwd: workDir,
@@ -19747,7 +20223,7 @@ function runCommandHook(config, event, workDir) {
19747
20223
  if (!settled) {
19748
20224
  settled = true;
19749
20225
  child.kill("SIGKILL");
19750
- resolve15({
20226
+ resolve16({
19751
20227
  exitCode: -1,
19752
20228
  stdout,
19753
20229
  stderr,
@@ -19783,7 +20259,7 @@ function runCommandHook(config, event, workDir) {
19783
20259
  }
19784
20260
  } catch {
19785
20261
  }
19786
- resolve15({
20262
+ resolve16({
19787
20263
  exitCode,
19788
20264
  stdout: stdout.trim(),
19789
20265
  stderr: stderr.trim(),
@@ -19796,7 +20272,7 @@ function runCommandHook(config, event, workDir) {
19796
20272
  clearTimeout(timer);
19797
20273
  if (settled) return;
19798
20274
  settled = true;
19799
- resolve15({
20275
+ resolve16({
19800
20276
  exitCode: -1,
19801
20277
  stdout,
19802
20278
  stderr,
@@ -19909,7 +20385,7 @@ var HookManager = class {
19909
20385
  return { blocked: true, reason: result.rejectReason || t("hook_load.rejected") };
19910
20386
  }
19911
20387
  } catch (err) {
19912
- this.log("warn", `[HookManager] ${type} \u7684 command hook \u6267\u884C\u5F02\u5E38: ${describe7(err)}`, {
20388
+ this.log("warn", `[HookManager] ${type} \u7684 command hook \u6267\u884C\u5F02\u5E38: ${describe9(err)}`, {
19913
20389
  hookType: type,
19914
20390
  command: config.command
19915
20391
  });
@@ -19927,7 +20403,7 @@ var HookManager = class {
19927
20403
  (_, reject2) => setTimeout(() => reject2(new Error("Hook timeout")), HOOK_TIMEOUT_MS)
19928
20404
  )
19929
20405
  ]).catch((err) => {
19930
- this.log("warn", `[HookManager] ${type} (${reg.plugin}) \u5931\u8D25: ${describe7(err)}`, {
20406
+ this.log("warn", `[HookManager] ${type} (${reg.plugin}) \u5931\u8D25: ${describe9(err)}`, {
19931
20407
  hookType: type,
19932
20408
  plugin: reg.plugin
19933
20409
  });
@@ -19939,7 +20415,7 @@ var HookManager = class {
19939
20415
  if (!matchesHook(entry.matcher, event)) continue;
19940
20416
  for (const config of entry.configs) {
19941
20417
  runCommandHook(config, event, ctx.workDir).then((result) => reportIfNeverRan(this.log, type, config, result)).catch((err) => {
19942
- this.log("warn", `[HookManager] ${type} \u7684 command hook \u5F02\u6B65\u5F02\u5E38: ${describe7(err)}`, {
20418
+ this.log("warn", `[HookManager] ${type} \u7684 command hook \u5F02\u6B65\u5F02\u5E38: ${describe9(err)}`, {
19943
20419
  hookType: type,
19944
20420
  command: config.command
19945
20421
  });
@@ -19960,7 +20436,7 @@ var HookManager = class {
19960
20436
  ]);
19961
20437
  if (result !== null && result !== void 0) return result;
19962
20438
  } catch (err) {
19963
- this.log("warn", `[HookManager] ${type} (${reg.plugin}) \u5931\u8D25: ${describe7(err)}`, {
20439
+ this.log("warn", `[HookManager] ${type} (${reg.plugin}) \u5931\u8D25: ${describe9(err)}`, {
19964
20440
  hookType: type,
19965
20441
  plugin: reg.plugin
19966
20442
  });
@@ -19981,7 +20457,7 @@ var HookManager = class {
19981
20457
  ]);
19982
20458
  if (result) results.push(result);
19983
20459
  } catch (err) {
19984
- this.log("warn", `[HookManager] ${type} (${reg.plugin}) \u5931\u8D25: ${describe7(err)}`, {
20460
+ this.log("warn", `[HookManager] ${type} (${reg.plugin}) \u5931\u8D25: ${describe9(err)}`, {
19985
20461
  hookType: type,
19986
20462
  plugin: reg.plugin
19987
20463
  });
@@ -19998,7 +20474,7 @@ var HookManager = class {
19998
20474
  const verdict = verdictOf2(result);
19999
20475
  if (verdict) results.push(verdict);
20000
20476
  } catch (err) {
20001
- this.log("warn", `[HookManager] ${type} \u7684 command hook \u6267\u884C\u5F02\u5E38: ${describe7(err)}`, {
20477
+ this.log("warn", `[HookManager] ${type} \u7684 command hook \u6267\u884C\u5F02\u5E38: ${describe9(err)}`, {
20002
20478
  hookType: type,
20003
20479
  command: config.command
20004
20480
  });
@@ -20014,7 +20490,7 @@ var HookManager = class {
20014
20490
  return [...list].sort((a, b) => a.priority - b.priority);
20015
20491
  }
20016
20492
  };
20017
- function describe7(err) {
20493
+ function describe9(err) {
20018
20494
  return err instanceof Error ? err.message : String(err);
20019
20495
  }
20020
20496
  function verdictOf2(result) {
@@ -21311,7 +21787,7 @@ async function withStaged(source, opts, fn) {
21311
21787
  shape = existsSync(join(unpacked, SKILL_FILE)) ? "skill-dir" : "tree";
21312
21788
  }
21313
21789
  const staged = stageImport(root, staging, shape, opts.lang);
21314
- const preview3 = describe8(source, form, staged.skills, staged.issues, opts.existing, opts.lang);
21790
+ const preview3 = describe10(source, form, staged.skills, staged.issues, opts.existing, opts.lang);
21315
21791
  if (preview3.skills.length === 0) {
21316
21792
  const detail = t("skill.import_empty", { path: source }, opts.lang);
21317
21793
  return { ok: false, reason: "empty", detail, issues: preview3.issues };
@@ -21322,7 +21798,7 @@ async function withStaged(source, opts, fn) {
21322
21798
  rmSync(unpacked, { recursive: true, force: true });
21323
21799
  }
21324
21800
  }
21325
- function describe8(source, form, staged, issues, existing, lang) {
21801
+ function describe10(source, form, staged, issues, existing, lang) {
21326
21802
  const byName = new Map(existing.map((s) => [s.name, s.scope]));
21327
21803
  const entries2 = [];
21328
21804
  const taken = /* @__PURE__ */ new Set();
@@ -21992,6 +22468,19 @@ var ContextCompressor = class {
21992
22468
  };
21993
22469
  }
21994
22470
  const { head, middle, tail } = this.determineBoundaries(pruned.messages, config);
22471
+ if (middle.length === 0) {
22472
+ const kept = this.cleanupOrphans(pruned.messages);
22473
+ this.turnsSinceCompress = 0;
22474
+ return {
22475
+ messages: kept,
22476
+ summary: "",
22477
+ ...prunedCounters,
22478
+ summarizedMessages: 0,
22479
+ newTokenCount: this.estimateTokens(kept),
22480
+ droppedOrphans: pruned.messages.length - kept.length,
22481
+ summarySkipped: true
22482
+ };
22483
+ }
21995
22484
  const nl = "\n";
21996
22485
  const middleText = middle.map((m) => `${m.role}: ${m.content}`).join(nl);
21997
22486
  const summarized = await this.generateSummary(
@@ -22027,6 +22516,7 @@ var ContextCompressor = class {
22027
22516
  summarizedMessages: middle.length,
22028
22517
  newTokenCount: this.estimateTokens(result),
22029
22518
  droppedOrphans,
22519
+ ...summary && droppedOrphans === 0 && middle.length > 0 ? { carriedHead: head.length, carriedTail: tail.length } : {},
22030
22520
  ...summarized?.usage ? { usage: summarized.usage } : {},
22031
22521
  ...summarized?.model ? { model: summarized.model } : {}
22032
22522
  };
@@ -22158,10 +22648,10 @@ ${extra}` : withGoal;
22158
22648
  return messages.reduce((sum, m) => sum + estimateTokens(m.content), 0);
22159
22649
  }
22160
22650
  };
22161
- var FILE_VERSION3 = 1;
22651
+ var FILE_VERSION4 = 1;
22162
22652
  var LEVELS = ["trusted", "untrusted"];
22163
22653
  var SCOPES = ["directory", "directory-tree"];
22164
- function describe9(err) {
22654
+ function describe11(err) {
22165
22655
  return err instanceof Error ? err.message : String(err);
22166
22656
  }
22167
22657
  function covers(base, target, scope) {
@@ -22170,9 +22660,6 @@ function covers(base, target, scope) {
22170
22660
  const rel = relative(base, target);
22171
22661
  return !rel.startsWith("..") && !isAbsolute(rel);
22172
22662
  }
22173
- function samePath(a, b) {
22174
- return relative(a, b) === "";
22175
- }
22176
22663
  var TrustManager = class {
22177
22664
  constructor(filePath = trustPath()) {
22178
22665
  this.filePath = filePath;
@@ -22238,7 +22725,7 @@ var TrustManager = class {
22238
22725
  raw = readFileSync(this.filePath, "utf-8");
22239
22726
  } catch (err) {
22240
22727
  this.loadErrors.push(
22241
- t("trust_gate.record_read_failed", { path: this.filePath, reason: describe9(err) })
22728
+ t("trust_gate.record_read_failed", { path: this.filePath, reason: describe11(err) })
22242
22729
  );
22243
22730
  return;
22244
22731
  }
@@ -22247,7 +22734,7 @@ var TrustManager = class {
22247
22734
  parsed = JSON.parse(raw);
22248
22735
  } catch (err) {
22249
22736
  this.loadErrors.push(
22250
- t("trust_gate.record_bad_json", { path: this.filePath, reason: describe9(err) })
22737
+ t("trust_gate.record_bad_json", { path: this.filePath, reason: describe11(err) })
22251
22738
  );
22252
22739
  return;
22253
22740
  }
@@ -22259,12 +22746,12 @@ var TrustManager = class {
22259
22746
  return;
22260
22747
  }
22261
22748
  const file = parsed;
22262
- if (file.version !== FILE_VERSION3) {
22749
+ if (file.version !== FILE_VERSION4) {
22263
22750
  this.loadErrors.push(
22264
22751
  t("trust_gate.record_bad_version", {
22265
22752
  path: this.filePath,
22266
22753
  found: String(file.version),
22267
- expected: FILE_VERSION3
22754
+ expected: FILE_VERSION4
22268
22755
  })
22269
22756
  );
22270
22757
  return;
@@ -22285,7 +22772,7 @@ var TrustManager = class {
22285
22772
  save() {
22286
22773
  mkdirSync(dirname(this.filePath), { recursive: true });
22287
22774
  const body2 = JSON.stringify(
22288
- { version: FILE_VERSION3, records: this.records },
22775
+ { version: FILE_VERSION4, records: this.records },
22289
22776
  null,
22290
22777
  2
22291
22778
  );
@@ -22296,7 +22783,7 @@ var TrustManager = class {
22296
22783
  } catch (err) {
22297
22784
  rmSync(tmp, { force: true });
22298
22785
  throw new Error(
22299
- t("trust_gate.record_write_failed", { path: this.filePath, reason: describe9(err) })
22786
+ t("trust_gate.record_write_failed", { path: this.filePath, reason: describe11(err) })
22300
22787
  );
22301
22788
  }
22302
22789
  }
@@ -22539,7 +23026,7 @@ var CodeSandbox = class {
22539
23026
  ...IS_WINDOWS ? { windowsHide: true } : {}
22540
23027
  };
22541
23028
  const child = spawn(command, args, spawnOpts);
22542
- return new Promise((resolve15) => {
23029
+ return new Promise((resolve16) => {
22543
23030
  let stdout = "";
22544
23031
  let stderr = "";
22545
23032
  let killedForOutput = false;
@@ -22565,7 +23052,7 @@ var CodeSandbox = class {
22565
23052
  child.on("error", (err) => {
22566
23053
  opts.signal?.removeEventListener("abort", onAbort);
22567
23054
  if (err.code === "ENOENT") {
22568
- resolve15({
23055
+ resolve16({
22569
23056
  success: false,
22570
23057
  output: "",
22571
23058
  error: `[\u9519\u8BEF] \u627E\u4E0D\u5230\u89E3\u91CA\u5668: ${command}`,
@@ -22574,7 +23061,7 @@ var CodeSandbox = class {
22574
23061
  });
22575
23062
  return;
22576
23063
  }
22577
- resolve15({
23064
+ resolve16({
22578
23065
  success: false,
22579
23066
  output: "",
22580
23067
  error: `[\u9519\u8BEF] ${err.message}`,
@@ -22588,7 +23075,7 @@ var CodeSandbox = class {
22588
23075
  if (stderr.length < MAX_OUTPUT) stderr += errDecoder?.end() ?? "";
22589
23076
  const duration = Date.now() - start;
22590
23077
  if (killedForOutput) {
22591
- resolve15({
23078
+ resolve16({
22592
23079
  success: false,
22593
23080
  output: trunc(stdout, stderr),
22594
23081
  error: `[\u8F93\u51FA\u8D85\u9650] \u8D85\u8FC7 ${MAX_OUTPUT} \u5B57\u8282\uFF0C\u5DF2\u7EC8\u6B62`,
@@ -22598,7 +23085,7 @@ var CodeSandbox = class {
22598
23085
  return;
22599
23086
  }
22600
23087
  if (sig) {
22601
- resolve15({
23088
+ resolve16({
22602
23089
  success: false,
22603
23090
  output: trunc(stdout, stderr),
22604
23091
  error: opts.signal?.aborted ? "[\u5DF2\u53D6\u6D88]" : "[\u8D85\u65F6] \u6267\u884C\u8D85\u65F6",
@@ -22610,7 +23097,7 @@ var CodeSandbox = class {
22610
23097
  const output = trunc(stdout, stderr);
22611
23098
  if (code !== 0 && code !== null) {
22612
23099
  const oom = /heap out of memory|allocation failed/i.test(stderr);
22613
- resolve15({
23100
+ resolve16({
22614
23101
  success: false,
22615
23102
  output,
22616
23103
  error: oom ? `[\u5185\u5B58\u8D85\u9650] \u8D85\u8FC7 ${MAX_MEMORY}MB` : `[\u8FD0\u884C\u65F6\u9519\u8BEF] exit ${code}: ${stderr.slice(0, 200)}`,
@@ -22619,7 +23106,7 @@ var CodeSandbox = class {
22619
23106
  });
22620
23107
  return;
22621
23108
  }
22622
- resolve15({ success: true, output, duration });
23109
+ resolve16({ success: true, output, duration });
22623
23110
  });
22624
23111
  });
22625
23112
  }
@@ -22679,4 +23166,4 @@ function trunc(stdout, stderr) {
22679
23166
  * `--tree` 的命令帮助里,让用户自己知道 `--tree` 意味着什么。
22680
23167
  */
22681
23168
 
22682
- export { AGENT_ROLE_DIAG_MODULE, ARTIFACT_MAX_TOTAL_BYTES, ARTIFACT_RETENTION_DEFAULTS, ATTACHMENT_MAX_TOTAL_BYTES, ATTACHMENT_RETENTION_DEFAULTS, AgentLoop, 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, 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, MARKETPLACE_DISPLAY_FIELDS, MARKETPLACE_FILE, MAX_AUDIT_ENTRIES, MAX_COMMAND_DEPTH, MAX_GOAL_MAX_ROUNDS, MAX_IMPORT_DEPTH, MAX_OBJECTIVE_CHARS, MAX_REASON_CHARS, MAX_RECENT_WORKSPACES, MODEL_GIVE_UP_THRESHOLD, MULTIMODAL_DEFAULTS, ManagedPolicyError, ManagedSettingsSchema, MemoryManager, MemoryReviewer, ModelFailureTracker, NOMINAL_TOTAL_BYTES, NO_REVEALED_TOOLS, PACK_EXCLUDES, PACK_MAX_BYTES, PACK_MAX_FILES, PERMISSION_AUDIT_CODES, PLUGIN_LAYOUT, PLUGIN_MANIFEST_FILE, PLUGIN_NAME_PATTERN, PLUGIN_ROOT_ENV, PLUGIN_ROOT_TOKEN, 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_CREATE_TOOL, SKILL_EDIT_TOOL, 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, Workspace, acquireScheduleLock, addMarketplace, addUsage, admitArtifact, admitArtifacts, affectedPaths, artifactLaunchArgv, artifactOpenRefusal, assertLevelAllowed, blockedRoleTools, buildContextBreakdown, buildFireArgv, buildFtsMatchQuery, buildSchemaExports, buildSystemPrompt, buildTrigramMatchQuery, builtinRoles, checkEpochVersion, checkFtsHealth, checkShadowing, classifyProviderError, clearModelCache, coalesceRecording, codeModeWorkerPath, commandNameFromRelPath, compileRuleLists, compressionOptions, computeCost, computeCostMicros, computeExecHash, countRules, createAllowAllGate, createAllowAllImportGate, createAskQuestionTool, createCodeExecTool, createDelegateTool, createDenyAllGate, createDenyAllImportGate, createGoalTool, createImportGate, createMemoryTool, createPlanModeTools, createRoleFile, createRoleScope, createRunCodeTool, createScheduleDraftTool, createSessionMessagesReadTool, createSessionMessagesSearchTool, createSessionSearchTool, createSessionSearchTools, createSessionTraceTool, createSkillViewTool, createSkillWriteTools, createTodoTool, createToolRevealState, createToolScope, createToolSearchTool, createTrustGate, currentEpochVersion, decideImport, decideTrust, defaultConfig, defaultModelOf, describeArtifactRefusal, describeBackgroundTask, describeHeadlessPolicy, describeIsolation, describeJsonError, diagnoseSchedules, discoverMarkdown, discoverModels, discoverProject, displayCurrency, draftCommandLine, draftWidening, escapeRuleContent, estimateImageTokens, estimateRunTokens, estimateTokens, evaluateSelection, expandCommand, expandImports, explainSetting, extractArchive, findInstructionFiles, findProjectInstructions, findRole, formatBytes, formatSkillIndex, formatUsd, gateForTool, getCapability, getConfigIssues, getConfigOrigins, getImportGate, getTrustGate, hasDedicatedExecContent, hasExecTierContent, hasPromptCaching, hasProviderCredentials, hasReadTierContent, imageFromBase64, imageFromPath, imagePartTokens, importSkills, installPlugin, instructionDirs, instructionNotices, intervalSlots, inventoryProjectExtensions, inventoryTotal, isBlockCode, isCodeModeDeferred, isEmptyRules, isGoalPhase, isNonInteractive, isReadOnlySubCall, isSettingWriteLayer, isValidPluginName, isWithinWindow, isWritableSettingKey, labelSlug, layerRank, listSessionCandidates, listWorkspaceFiles, loadCommandDefinitions, loadCommandFile, loadCommands, loadConfig, loadHookSources, loadKeybindings, loadLexiconDir, loadLexiconFiles, loadPlugins, loadPolicyFiles, loadPolicyRules, loadRoleDefinitions, loadRoleDir, loadedImports, localDateString, managedSwitchNotes, mapClaudeToolName, mapEpochToolName, mapOperationType, matchPreauthorization, matchRuleLists, matchesHook, mentionsPluginRoot, mergeHeadlessPolicy, mergeRoles, mergeSchedulePatch, microsToUsd, modelListCandidates, needsAllowlist, nextFallbackModel, nextRunAt, noConfigOrigins, noManagedPolicy, noPlugins, openArtifact, originOf, packFileName, packPlugin, parseClaudeSettingsHooks, parseClock, parseDate, parseFrontmatter, parseHooksConfig, parseHooksConfigVerbose, parseImportLine, parseModelList, parseRoleDefinition, parseScheduleDraft, parseSkillFrontmatter, parseTrigger, pendingImageTokens, persistParts, persistToolResults, persistedUsage, planPack, previewSkillImport, pricingFor, projectEntryForDisplay, pruneArtifacts, pruneAttachments, pruneRecordings, pruneSchedules, readImageSize, readMarketplaces, readPluginManifest, readPluginRecords, readProviderKeyEnv, readRecording, readSessionSurface, reclaimFtsSpace, redactLine, refreshOpenRouterMetadata, removeMarketplace, removeSessionArtifacts, removeSessionAttachments, renderImportTree, renderProjectContext, renderSdkDeclaration, renderSelfIndex, repairSchedules, 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, scanInstructions, scanPluginDir, scanSkillDirs, searchMarketplaces, setDisplayCurrency, setImportGate, setPluginEnabled, setTrustGate, settingValueChoices, settingValueKind, settingWriteApply, settingWriteLayers, settingWriteTargets, skillIndexDescription, skillIndexResidency, skillIndexStats, sniffMediaType, splitFrontmatter, staticToolProvider, stripArtifactData, substitutePluginRoot, suggestRuleFromApproval, systemOpenArgv, systemPromptSegments, toPosix, toolDefinitionTokens, toolMatches, toolTableTokens, totalTokens, traceSession, triggerPeriodMs, unescapeRuleContent, uninstallPlugin, unknownRoleSkills, unknownRoleTools, unloadedInstructionFiles, updateMarketplace, updatePlugin, usdToMicros, validateSchedule, validateTrigger, validateWindow, withGoalCompression, withGoalPrompt, workspaceDisplayPath, writeSettingValue };
23169
+ export { AGENT_ROLE_DIAG_MODULE, ARTIFACT_MAX_TOTAL_BYTES, ARTIFACT_RETENTION_DEFAULTS, ATTACHMENT_MAX_TOTAL_BYTES, ATTACHMENT_RETENTION_DEFAULTS, AgentLoop, 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, 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_GIVE_UP_THRESHOLD, MULTIMODAL_DEFAULTS, ManagedPolicyError, ManagedSettingsSchema, MemoryManager, MemoryReviewer, ModelFailureTracker, NOMINAL_TOTAL_BYTES, NO_REVEALED_TOOLS, PACK_EXCLUDES, PACK_MAX_BYTES, PACK_MAX_FILES, PERMISSION_AUDIT_CODES, 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_CREATE_TOOL, SKILL_EDIT_TOOL, 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, Workspace, acquireScheduleLock, addMarketplace, addUsage, admitArtifact, admitArtifacts, affectedPaths, artifactLaunchArgv, artifactOpenRefusal, assertLevelAllowed, blockedRoleTools, buildContextBreakdown, buildFireArgv, buildFtsMatchQuery, buildSchemaExports, buildSystemPrompt, buildTrigramMatchQuery, builtinRoles, checkEpochVersion, checkFtsHealth, checkShadowing, classifyProviderError, clearModelCache, coalesceRecording, codeModeWorkerPath, commandNameFromRelPath, compileRuleLists, compressionOptions, computeCost, computeCostMicros, computeExecHash, countRules, createAllowAllGate, createAllowAllImportGate, createAskQuestionTool, createCodeExecTool, createDelegateTool, createDenyAllGate, createDenyAllImportGate, createGoalTool, createImportGate, createMemoryTool, createPlanModeTools, createRoleFile, createRoleScope, createRunCodeTool, createScheduleDraftTool, createSessionMessagesReadTool, createSessionMessagesSearchTool, createSessionSearchTool, createSessionSearchTools, createSessionTraceTool, createSkillViewTool, createSkillWriteTools, createTodoTool, createToolRevealState, createToolScope, createToolSearchTool, createTrustGate, currentEpochVersion, decideImport, decideTrust, defaultConfig, defaultModelOf, describeArtifactRefusal, describeBackgroundTask, describeHeadlessPolicy, describeIsolation, describeJsonError, diagnoseSchedules, discoverMarkdown, discoverModels, discoverProject, displayCurrency, draftCommandLine, draftWidening, escapeRuleContent, estimateImageTokens, estimateRunTokens, estimateTokens, evaluateSelection, expandCommand, expandImports, explainSetting, extractArchive, findInstructionFiles, findProjectInstructions, findRole, formatBytes, formatSkillIndex, formatUsd, gateForTool, getCapability, getConfigIssues, getConfigOrigins, getImportGate, getTrustGate, hasDedicatedExecContent, hasExecTierContent, hasPromptCaching, hasProviderCredentials, hasReadTierContent, imageFromBase64, imageFromPath, imagePartTokens, importSkills, installPlugin, instructionDirs, instructionNotices, intervalSlots, inventoryProjectExtensions, inventoryTotal, isBlockCode, isCodeModeDeferred, isEmptyRules, isGoalPhase, isNonInteractive, isReadOnlySubCall, isSettingWriteLayer, isValidPluginName, isWithinWindow, isWritableSettingKey, labelSlug, layerRank, listRunningSchedules, listSessionCandidates, listWorkspaceFiles, loadCommandDefinitions, loadCommandFile, loadCommands, loadConfig, loadHookSources, loadKeybindings, loadLexiconDir, loadLexiconFiles, loadPlugins, loadPolicyFiles, loadPolicyRules, loadRoleDefinitions, loadRoleDir, loadedImports, localDateString, managedSwitchNotes, mapClaudeToolName, mapEpochToolName, mapOperationType, matchPreauthorization, matchRuleLists, matchesHook, mentionsPluginRoot, mergeHeadlessPolicy, mergeRoles, mergeSchedulePatch, microsToUsd, modelListCandidates, needsAllowlist, nextFallbackModel, nextRunAt, noConfigOrigins, noManagedPolicy, noPlugins, openArtifact, originOf, packFileName, packPlugin, parseClaudeSettingsHooks, parseClock, parseDate, parseFrontmatter, parseHooksConfig, parseHooksConfigVerbose, parseImportLine, parseModelList, parseRoleDefinition, parseScheduleDraft, parseSkillFrontmatter, parseTrigger, pendingImageTokens, persistParts, persistToolResults, persistedUsage, planPack, previewSkillImport, pricingFor, projectEntryForDisplay, pruneArtifacts, pruneAttachments, pruneRecordings, pruneSchedules, readImageSize, readMarketplaces, readPluginManifest, readPluginRecords, readProviderKeyEnv, readRecording, readSessionSurface, reclaimFtsSpace, redactLine, refreshOpenRouterMetadata, removeMarketplace, removeRecordings, removeRoleFile, removeSessionArtifacts, removeSessionAttachments, renderImportTree, renderProjectContext, renderSdkDeclaration, renderSelfIndex, repairSchedules, 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, scanInstructions, scanPluginDir, scanSkillDirs, searchMarketplaces, setDisplayCurrency, setImportGate, setPluginEnabled, setTrustGate, settingValueChoices, settingValueKind, settingWriteApply, settingWriteLayers, settingWriteTargets, skillIndexDescription, skillIndexResidency, skillIndexStats, sniffMediaType, splitFrontmatter, staticToolProvider, stripArtifactData, substitutePluginRoot, suggestRuleFromApproval, systemOpenArgv, systemPromptSegments, toPosix, toolDefinitionTokens, toolMatches, toolTableTokens, totalTokens, traceSession, triggerPeriodMs, unescapeRuleContent, uninstallPlugin, unknownRoleSkills, unknownRoleTools, unloadedInstructionFiles, updateMarketplace, updatePlugin, usdToMicros, validateSchedule, validateTrigger, validateWindow, withGoalCompression, withGoalPrompt, workspaceDisplayPath, writeSettingValue };