@epoch-agent/core 0.10.1 → 0.11.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.
Files changed (3) hide show
  1. package/dist/index.d.ts +359 -3
  2. package/dist/index.js +404 -127
  3. package/package.json +3 -3
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: ${describe7(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: ${describe7(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 describe7(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 t79 of tools) this.addTool(t79, 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((t79) => this.exposureOf(t79) === ToolExposure.Direct);
682
682
  }
683
683
  byExposure(exposure) {
684
- return this.list().filter((t78) => this.exposureOf(t78) === exposure);
684
+ return this.list().filter((t79) => this.exposureOf(t79) === 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((t79) => isCodeModeDeferred(t79));
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((t79) => t79.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((t79) => ({ ...t79, role: t79.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((t79) => this.runSingleTask(t79, 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((t79) => String(t79["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((t79) => {
1308
+ const o = t79;
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((t79) => t79.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((t79) => t79.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(t79) {
1504
+ return typeof t79 === "string" && VALID_TARGETS.includes(t79);
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((t79) => t79.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 t79 of todos) {
4623
4631
  insertStmt.run({
4624
- id: t78.id,
4632
+ id: t79.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: t79.content,
4635
+ status: t79.status,
4636
+ reason: t79.reason || null,
4637
+ created_at: t79.created_at,
4638
+ updated_at: t79.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 t79 of todos) {
4661
+ const label = statusLabel[t79.status] || t79.status;
4662
+ lines.push(`- [${label}] ${t79.content}${t79.reason ? ` \u2014\u2014 ${t79.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((t79) => [t79.id, t79]));
4737
+ const todos = rawTodos.map((t79) => {
4738
+ const prev = t79.id ? existing.get(t79.id) : void 0;
4739
+ const status = isValidStatus(t79.status) ? t79.status : "pending";
4740
+ const reason9 = normalizeReason(status, t79.reason);
4733
4741
  return {
4734
- id: t78.id || generateShortId(),
4735
- content: String(t78.content || "").slice(0, 500),
4742
+ id: t79.id || generateShortId(),
4743
+ content: String(t79.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((t79) => isOpenTodo(t79.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((t79) => baseSet.has(t79));
5079
5087
  }
5080
5088
  function findRole(roles, name) {
5081
5089
  return roles.find((r) => r.name === name);
@@ -5161,7 +5169,7 @@ function roleScopedProvider(base, role, blocked) {
5161
5169
  return allow ? allow.has(name) : true;
5162
5170
  };
5163
5171
  return {
5164
- list: () => base.list().filter((t78) => permitted(t78.name)),
5172
+ list: () => base.list().filter((t79) => permitted(t79.name)),
5165
5173
  get: (name) => permitted(name) ? base.get(name) : void 0
5166
5174
  };
5167
5175
  }
@@ -5188,7 +5196,7 @@ function createRoleScope(base, sessionRole, blocked) {
5188
5196
  }
5189
5197
  function unknownRoleTools(base, role, blocked) {
5190
5198
  if (!role?.tools) return [];
5191
- const available2 = new Set(base.list().map((t78) => t78.name));
5199
+ const available2 = new Set(base.list().map((t79) => t79.name));
5192
5200
  const blockedSet = new Set(blocked);
5193
5201
  return role.tools.filter((name) => !available2.has(name) && !blockedSet.has(name));
5194
5202
  }
@@ -5308,7 +5316,7 @@ function loadCommandFile(file, source, prefix) {
5308
5316
  ]
5309
5317
  };
5310
5318
  }
5311
- const issues = unknownKeyIssues(FRONTMATTER_KEYS3, parsed.data, at);
5319
+ const issues = misspelledKeyIssues(FRONTMATTER_KEYS3, parsed.data, at);
5312
5320
  const checked = parseLenient(CommandFrontmatterSchema.optional(), parsed.data, void 0);
5313
5321
  if (!checked.value) {
5314
5322
  issues.push(
@@ -5524,7 +5532,7 @@ function createToolScope(base) {
5524
5532
  const permitted = (name) => allow ? allow.has(name) : true;
5525
5533
  return {
5526
5534
  provider: {
5527
- list: () => base.list().filter((t78) => permitted(t78.name)),
5535
+ list: () => base.list().filter((t79) => permitted(t79.name)),
5528
5536
  get: (name) => permitted(name) ? base.get(name) : void 0
5529
5537
  },
5530
5538
  enter: (next) => {
@@ -5694,7 +5702,7 @@ function scanHooks(dir, issues) {
5694
5702
  return [...parsed.entries].map(([type, list]) => ({
5695
5703
  type,
5696
5704
  count: list.reduce((sum, entry) => sum + entry.hooks.length, 0)
5697
- })).filter((t78) => t78.count > 0).sort((a, b) => a.type.localeCompare(b.type));
5705
+ })).filter((t79) => t79.count > 0).sort((a, b) => a.type.localeCompare(b.type));
5698
5706
  }
5699
5707
  function scanMcp(dir, plugin, issues) {
5700
5708
  const path = join(dir, PLUGIN_LAYOUT.mcp);
@@ -5781,6 +5789,7 @@ var PluginAuthorSchema = z.object({
5781
5789
  email: z.string().min(1).optional(),
5782
5790
  url: z.string().min(1).optional()
5783
5791
  });
5792
+ var PLUGIN_VISIBILITY = ["private", "public"];
5784
5793
  var ManifestSchema = z.object({
5785
5794
  name: z.string().min(1),
5786
5795
  version: z.string().min(1),
@@ -5788,9 +5797,14 @@ var ManifestSchema = z.object({
5788
5797
  author: PluginAuthorSchema.optional(),
5789
5798
  epochVersion: z.string().min(1).optional(),
5790
5799
  homepage: z.string().min(1).optional(),
5791
- keywords: z.array(z.string().min(1)).optional()
5800
+ keywords: z.array(z.string().min(1)).optional(),
5801
+ displayName: z.string().min(1).optional(),
5802
+ category: z.string().min(1).optional(),
5803
+ icon: z.string().min(1).optional(),
5804
+ changelog: z.string().min(1).optional(),
5805
+ visibility: z.enum(PLUGIN_VISIBILITY).optional().catch(void 0)
5792
5806
  });
5793
- var MANIFEST_KEYS = Object.keys(ManifestSchema.shape);
5807
+ var PLUGIN_MANIFEST_KEYS = Object.keys(ManifestSchema.shape);
5794
5808
  function readPluginManifest(dir) {
5795
5809
  const path = join(dir, PLUGIN_MANIFEST_FILE);
5796
5810
  let raw;
@@ -5815,7 +5829,17 @@ function readPluginManifest(dir) {
5815
5829
  issues: [{ path, message: t("plugin_manifest.bad_json", { reason: firstLine2(err) }) }]
5816
5830
  };
5817
5831
  }
5818
- const issues = unknownKeyIssues(MANIFEST_KEYS, parsed, PLUGIN_MANIFEST_FILE);
5832
+ const issues = unknownKeyIssues(PLUGIN_MANIFEST_KEYS, parsed, PLUGIN_MANIFEST_FILE);
5833
+ const rawVisibility = parsed?.visibility;
5834
+ if (rawVisibility !== void 0 && !PLUGIN_VISIBILITY.includes(rawVisibility)) {
5835
+ issues.push({
5836
+ path: `${path}.visibility`,
5837
+ message: t("plugin_manifest.bad_visibility", {
5838
+ raw: String(rawVisibility),
5839
+ allowed: PLUGIN_VISIBILITY.join(" / ")
5840
+ })
5841
+ });
5842
+ }
5819
5843
  const checked = parseLenient(ManifestSchema.optional(), parsed, void 0);
5820
5844
  if (!checked.value) {
5821
5845
  issues.push(
@@ -6095,7 +6119,7 @@ var PluginStore = class {
6095
6119
  }
6096
6120
  };
6097
6121
  function sleep(ms) {
6098
- return new Promise((resolve15) => setTimeout(resolve15, ms));
6122
+ return new Promise((resolve16) => setTimeout(resolve16, ms));
6099
6123
  }
6100
6124
  // src/plugin/loader.ts
6101
6125
  var MODULE = "Plugin";
@@ -6900,7 +6924,7 @@ var EntrySchema = z.object({
6900
6924
  changelog: z.string().min(1).optional(),
6901
6925
  size: z.number().int().positive().optional(),
6902
6926
  homepage: z.string().min(1).optional(),
6903
- visibility: z.enum(["private", "public"]).optional().catch(void 0),
6927
+ visibility: z.enum(PLUGIN_VISIBILITY).optional().catch(void 0),
6904
6928
  status: z.enum(["listed", "reviewing", "rejected", "offline"]).optional().catch(void 0)
6905
6929
  });
6906
6930
  var MARKETPLACE_DISPLAY_FIELDS = [
@@ -7403,14 +7427,14 @@ var CheckpointStore = class {
7403
7427
  }
7404
7428
  async enforceTotalSize(protectSession, protectTurnIndex) {
7405
7429
  const turns = await this.collectTurns();
7406
- let total = turns.reduce((sum, t78) => sum + t78.bytes, 0);
7430
+ let total = turns.reduce((sum, t79) => sum + t79.bytes, 0);
7407
7431
  if (total <= this.maxTotalBytes) return;
7408
7432
  turns.sort((a, b) => a.createdAt - b.createdAt);
7409
- for (const t78 of turns) {
7433
+ for (const t79 of turns) {
7410
7434
  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;
7435
+ if (t79.sessionId === protectSession && t79.turnIndex === protectTurnIndex) continue;
7436
+ await this.removeTurn(t79.sessionId, t79.turnIndex);
7437
+ total -= t79.bytes;
7414
7438
  }
7415
7439
  }
7416
7440
  async collectTurns() {
@@ -8116,8 +8140,8 @@ function sanitizeToolOutput(text) {
8116
8140
  if (!stripped.includes("\r")) return stripped;
8117
8141
  return stripped.split("\n").map((line) => line.includes("\r") ? line.slice(line.lastIndexOf("\r") + 1) : line).join("\n");
8118
8142
  }
8119
- var sleep2 = (ms) => new Promise((resolve15) => {
8120
- setTimeout(resolve15, ms);
8143
+ var sleep2 = (ms) => new Promise((resolve16) => {
8144
+ setTimeout(resolve16, ms);
8121
8145
  });
8122
8146
  async function* pumpToolOutput(target, start, options = {}) {
8123
8147
  const flushMs = options.flushMs ?? FLUSH_MS;
@@ -8185,8 +8209,8 @@ async function* pumpToolOutput(target, start, options = {}) {
8185
8209
  continue;
8186
8210
  }
8187
8211
  if (!running) break;
8188
- await new Promise((resolve15) => {
8189
- wake = resolve15;
8212
+ await new Promise((resolve16) => {
8213
+ wake = resolve16;
8190
8214
  });
8191
8215
  if (running && flushMs > 0) await sleep2(flushMs);
8192
8216
  }
@@ -10123,11 +10147,11 @@ var PromptBuilder = class {
10123
10147
  memoryInitialized = false;
10124
10148
  projectBlock(tools) {
10125
10149
  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");
10150
+ const hasPlanTool = tools.some((t79) => t79.name === "enter_plan_mode");
10151
+ const hasLspTool = tools.some((t79) => t79.name === "lsp_diagnostics");
10152
+ const hasAskTool = tools.some((t79) => t79.name === "ask_user_question");
10153
+ const hasTodoTool = tools.some((t79) => t79.name === "todo");
10154
+ const hasTerminal = tools.some((t79) => t79.name === "terminal");
10131
10155
  const needsCommandApproval = hasTerminal && permLevel === "default";
10132
10156
  const plan = this.deps.approvedPlan?.()?.trim();
10133
10157
  const codeSdk = renderSdkDeclaration(this.deps.codeModeTools?.() ?? []);
@@ -11006,8 +11030,8 @@ function imageParts(content) {
11006
11030
  return typeof content === "string" ? [] : content.filter((p) => p.type === "image");
11007
11031
  }
11008
11032
  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");
11033
+ const direct = tools.map((t79) => t79.name).join("\0");
11034
+ const declared = (config.codeModeTools?.() ?? []).map((t79) => t79.name).join("\0");
11011
11035
  return declared ? `${direct}|${declared}` : direct;
11012
11036
  }
11013
11037
  function modelSignatureOf(info) {
@@ -11801,7 +11825,12 @@ ${finalText}` };
11801
11825
  "epoch.summary_skipped": compressed.summarySkipped === true,
11802
11826
  "epoch.pruned_tokens": compressed.prunedTokens
11803
11827
  });
11804
- return { messages: compressed.messages.map((m) => unflattenMessage(m)), ...bill };
11828
+ return {
11829
+ messages: compressed.messages.map((m) => unflattenMessage(m)),
11830
+ ...bill,
11831
+ ...compressed.carriedHead === void 0 ? {} : { carriedHead: compressed.carriedHead },
11832
+ ...compressed.carriedTail === void 0 ? {} : { carriedTail: compressed.carriedTail }
11833
+ };
11805
11834
  } catch {
11806
11835
  return { messages };
11807
11836
  }
@@ -11955,6 +11984,11 @@ var ArtifactsSchema = z.object({
11955
11984
  maxAgeDays: z.int().positive().max(3650).default(ARTIFACT_RETENTION_DEFAULTS.maxAgeDays),
11956
11985
  maxTotalBytes: z.int().positive().default(ARTIFACT_RETENTION_DEFAULTS.maxTotalBytes)
11957
11986
  });
11987
+ var SessionsSchema = z.object({
11988
+ autoPrune: z.boolean().default(false),
11989
+ retentionDays: z.int().positive().max(3650).default(90),
11990
+ vacuumAfterPrune: z.boolean().default(true)
11991
+ });
11958
11992
  var TelemetrySchema = z.object({
11959
11993
  enabled: z.boolean().optional(),
11960
11994
  target: z.enum(["file", "console", "otlp"]).optional(),
@@ -11991,6 +12025,7 @@ var EpochConfigSchema = z.object({
11991
12025
  compression: CompressionSchema.prefault({}),
11992
12026
  memory: MemorySchema.prefault({}),
11993
12027
  artifacts: ArtifactsSchema.prefault({}),
12028
+ sessions: SessionsSchema.prefault({}),
11994
12029
  budget: BudgetSchema.optional(),
11995
12030
  compliance: ComplianceSchema.optional(),
11996
12031
  headless: HeadlessSchema.optional(),
@@ -12476,7 +12511,11 @@ function parseRawConfig(raw, issues, track) {
12476
12511
  const migrated = migrateRawConfig(expanded);
12477
12512
  issues.push(...migrated.issues);
12478
12513
  issues.push(...unknownKeyIssues(CONFIG_KEYS, migrated.raw));
12479
- const outcome = parseLenient(EpochConfigSchema, dropEmptySections(migrated.raw), defaultConfig());
12514
+ const outcome = parseLenient(
12515
+ EpochConfigSchema,
12516
+ dropEmptySections(migrated.raw),
12517
+ EpochConfigSchema.parse({})
12518
+ );
12480
12519
  issues.push(...outcome.issues);
12481
12520
  if (outcome.issues.length === 0) collectKeyPaths(migrated.raw, track.file);
12482
12521
  return outcome.value;
@@ -13086,6 +13125,7 @@ function getCapability(modelId, homeDir, provider) {
13086
13125
  }
13087
13126
  return {
13088
13127
  contextLength: DEFAULT_CONTEXT_LENGTH2,
13128
+ contextLengthUnknown: true,
13089
13129
  maxOutputTokens: 4096,
13090
13130
  supportsTools: true,
13091
13131
  ...images,
@@ -14042,6 +14082,9 @@ var SETTING_WRITE_KEYS = [
14042
14082
  "budget.maxTokens",
14043
14083
  "budget.warnAtPercent",
14044
14084
  "budget.onUnknownPricing",
14085
+ "sessions.autoPrune",
14086
+ "sessions.retentionDays",
14087
+ "sessions.vacuumAfterPrune",
14045
14088
  "permission"
14046
14089
  ];
14047
14090
  function isWritableSettingKey(value) {
@@ -14105,6 +14148,9 @@ var VALUE_SCHEMA = {
14105
14148
  "budget.maxTokens": EpochConfigSchema.shape.budget.unwrap().shape.maxTokens.unwrap(),
14106
14149
  "budget.warnAtPercent": EpochConfigSchema.shape.budget.unwrap().shape.warnAtPercent.unwrap(),
14107
14150
  "budget.onUnknownPricing": EpochConfigSchema.shape.budget.unwrap().shape.onUnknownPricing.unwrap(),
14151
+ "sessions.autoPrune": EpochConfigSchema.shape.sessions.unwrap().shape.autoPrune.unwrap(),
14152
+ "sessions.retentionDays": EpochConfigSchema.shape.sessions.unwrap().shape.retentionDays.unwrap(),
14153
+ "sessions.vacuumAfterPrune": EpochConfigSchema.shape.sessions.unwrap().shape.vacuumAfterPrune.unwrap(),
14108
14154
  permission: EpochConfigSchema.shape.permission.unwrap()
14109
14155
  };
14110
14156
  function settingValueKind(key) {
@@ -14513,11 +14559,11 @@ function buildSearchQuery(query) {
14513
14559
  }
14514
14560
  const latinPart = cleaned.replace(CJK_RUN, " ");
14515
14561
  for (const w of latinPart.split(/\s+/)) {
14516
- const t78 = w.trim();
14517
- if (t78.length >= 2) terms.add(t78);
14562
+ const t79 = w.trim();
14563
+ if (t79.length >= 2) terms.add(t79);
14518
14564
  }
14519
14565
  if (terms.size === 0) return null;
14520
- return [...terms].map((t78) => `"${t78.replace(/"/g, "")}"`).join(" OR ");
14566
+ return [...terms].map((t79) => `"${t79.replace(/"/g, "")}"`).join(" OR ");
14521
14567
  }
14522
14568
  // src/memory/db.ts
14523
14569
  var NS2 = "memory";
@@ -15846,6 +15892,19 @@ var SESSION_MIGRATIONS = [
15846
15892
  up: (db) => {
15847
15893
  db.exec(`ALTER TABLE sessions ADD COLUMN priced_call_count INTEGER NOT NULL DEFAULT 0;`);
15848
15894
  }
15895
+ },
15896
+ {
15897
+ id: "session-meta-kv",
15898
+ version: 11,
15899
+ description: "\u7EF4\u62A4\u7528\u7684 key/value \u8868\uFF08\u81EA\u52A8\u6E05\u7406\u7684\u8282\u6D41\u65F6\u523B\uFF0C2026-09-15\uFF09",
15900
+ up: (db) => {
15901
+ db.exec(`
15902
+ CREATE TABLE IF NOT EXISTS session_meta (
15903
+ key TEXT PRIMARY KEY,
15904
+ value TEXT NOT NULL
15905
+ );
15906
+ `);
15907
+ }
15849
15908
  }
15850
15909
  ];
15851
15910
  var FTS_EXTERNAL_SCHEMA = `
@@ -15896,7 +15955,7 @@ var FTS_EXTERNAL_SCHEMA = `
15896
15955
  var FTS_EXTERNAL_MIGRATIONS = [
15897
15956
  {
15898
15957
  id: "fts-external-content",
15899
- version: 10,
15958
+ version: 12,
15900
15959
  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
15960
  up: (db) => {
15902
15961
  db.exec(FTS_EXTERNAL_SCHEMA);
@@ -16199,6 +16258,46 @@ var SessionDB = class {
16199
16258
  }
16200
16259
  return { results };
16201
16260
  }
16261
+ pruneCandidates(input) {
16262
+ const clauses = ["ended_at IS NOT NULL", "updated_at < @cutoff"];
16263
+ const params = { cutoff: input.olderThanMs };
16264
+ if (typeof input.archived === "boolean") {
16265
+ clauses.push("archived = @archived");
16266
+ params["archived"] = input.archived ? 1 : 0;
16267
+ }
16268
+ if (!input.includePinned) clauses.push("COALESCE(pinned, 0) = 0");
16269
+ const rows = this.db.prepare(`SELECT * FROM sessions WHERE ${clauses.join(" AND ")} ORDER BY updated_at ASC`).all(params);
16270
+ return rows.map((r) => this.rowToMeta(r));
16271
+ }
16272
+ openPruneMatches(input) {
16273
+ const clauses = ["ended_at IS NULL", "updated_at < @cutoff"];
16274
+ if (!input.includePinned) clauses.push("COALESCE(pinned, 0) = 0");
16275
+ const row = this.db.prepare(`SELECT COUNT(*) AS n FROM sessions WHERE ${clauses.join(" AND ")}`).get({ cutoff: input.olderThanMs });
16276
+ return row.n;
16277
+ }
16278
+ freelistRatio() {
16279
+ const pages = Number(this.db.pragma("page_count", { simple: true }));
16280
+ if (pages <= 0) return 0;
16281
+ return Number(this.db.pragma("freelist_count", { simple: true })) / pages;
16282
+ }
16283
+ getMeta(key) {
16284
+ const row = this.db.prepare("SELECT value FROM session_meta WHERE key = ?").get(key);
16285
+ return row?.value ?? null;
16286
+ }
16287
+ setMeta(key, value) {
16288
+ this.db.prepare(
16289
+ "INSERT INTO session_meta (key, value) VALUES (@key, @value) ON CONFLICT(key) DO UPDATE SET value = @value"
16290
+ ).run({ key, value });
16291
+ }
16292
+ claimMaintenanceSlot(key, minIntervalMs, now) {
16293
+ const run = this.db.transaction(() => {
16294
+ const last = this.getMeta(key);
16295
+ if (last !== null && now - Number(last) < minIntervalMs) return false;
16296
+ this.setMeta(key, String(now));
16297
+ return true;
16298
+ });
16299
+ return run();
16300
+ }
16202
16301
  compact(sessionId, summary, beforeCount, keep) {
16203
16302
  const messages = this.db.prepare(
16204
16303
  "SELECT id FROM messages WHERE session_id = ? AND active = 1 ORDER BY timestamp DESC"
@@ -16217,6 +16316,29 @@ var SessionDB = class {
16217
16316
  duration: 0
16218
16317
  };
16219
16318
  }
16319
+ archiveAndCompact(sessionId, input) {
16320
+ const run = this.db.transaction(() => {
16321
+ const rows = this.db.prepare(
16322
+ "SELECT id, timestamp FROM messages WHERE session_id = ? AND active = 1 AND id <= ? ORDER BY timestamp ASC, id ASC"
16323
+ ).all(sessionId, input.watermark);
16324
+ const end = rows.length - input.tailCount;
16325
+ const middle = end > input.headCount ? rows.slice(input.headCount, end) : [];
16326
+ if (middle.length === 0) return null;
16327
+ const mark = this.db.prepare("UPDATE messages SET active = 0, compacted = 1 WHERE id = ?");
16328
+ for (const row of middle) mark.run(row.id);
16329
+ const summaryId = this.nextMessageId();
16330
+ this.insertMessage({
16331
+ sessionId,
16332
+ id: summaryId,
16333
+ role: "user",
16334
+ content: input.summary,
16335
+ timestamp: middle[0].timestamp
16336
+ });
16337
+ this.db.prepare("UPDATE sessions SET summary = @s WHERE id = @id").run({ s: input.summary, id: sessionId });
16338
+ return { archived: middle.length, summaryId };
16339
+ });
16340
+ return run();
16341
+ }
16220
16342
  getSummary(sessionId) {
16221
16343
  const row = this.db.prepare("SELECT summary FROM sessions WHERE id = ?").get(sessionId);
16222
16344
  return row?.summary ?? null;
@@ -16415,7 +16537,7 @@ function checkFtsHealth(db) {
16415
16537
  messages,
16416
16538
  tables,
16417
16539
  missingTriggers,
16418
- healthy: missingTriggers.length === 0 && tables.every((t78) => t78.error === null && t78.drift === null && t78.rows === messages),
16540
+ healthy: missingTriggers.length === 0 && tables.every((t79) => t79.error === null && t79.drift === null && t79.rows === messages),
16419
16541
  indexBytes: indexBytesOf(db),
16420
16542
  space: spaceOf(db)
16421
16543
  };
@@ -16561,6 +16683,7 @@ var SessionReferences = class {
16561
16683
  }
16562
16684
  };
16563
16685
  // src/session/manager.ts
16686
+ var AUTO_VACUUM_MIN_FREELIST_RATIO = 0.25;
16564
16687
  var SessionManager = class {
16565
16688
  db;
16566
16689
  queries;
@@ -16655,6 +16778,44 @@ var SessionManager = class {
16655
16778
  unarchive(id) {
16656
16779
  this.db.unarchiveSession(id);
16657
16780
  }
16781
+ pruneCandidates(input) {
16782
+ return this.db.pruneCandidates(input);
16783
+ }
16784
+ openPruneMatches(input) {
16785
+ return this.db.openPruneMatches(input);
16786
+ }
16787
+ freelistRatio() {
16788
+ return this.db.freelistRatio();
16789
+ }
16790
+ maybeAutoPrune(opts) {
16791
+ const result = { skipped: false, pruned: 0, vacuumed: false };
16792
+ if (!opts.enabled) return { ...result, skipped: true };
16793
+ const now = opts.now?.() ?? Date.now();
16794
+ const minInterval = opts.minIntervalMs ?? 24 * 60 * 60 * 1e3;
16795
+ const minVacuumInterval = opts.minVacuumIntervalMs ?? 30 * 24 * 60 * 60 * 1e3;
16796
+ try {
16797
+ if (!this.db.claimMaintenanceSlot("last_auto_prune", minInterval, now)) {
16798
+ return { ...result, skipped: true };
16799
+ }
16800
+ const cutoff = now - opts.retentionDays * 24 * 60 * 60 * 1e3;
16801
+ const victims = this.db.pruneCandidates({ olderThanMs: cutoff });
16802
+ let pruned = 0;
16803
+ for (const s of victims) if (this.db.deleteSession(s.id)) pruned++;
16804
+ let vacuumed = false;
16805
+ if (opts.vacuum && pruned > 0) {
16806
+ const lastVacuum = this.db.getMeta("last_vacuum");
16807
+ const vacuumDue = lastVacuum === null || now - Number(lastVacuum) >= minVacuumInterval;
16808
+ if (vacuumDue && this.db.freelistRatio() > AUTO_VACUUM_MIN_FREELIST_RATIO) {
16809
+ const report3 = reclaimFtsSpace(this.db.db, true);
16810
+ vacuumed = report3.vacuumed;
16811
+ if (vacuumed) this.db.setMeta("last_vacuum", String(now));
16812
+ }
16813
+ }
16814
+ return { skipped: false, pruned, vacuumed };
16815
+ } catch (cause) {
16816
+ return { ...result, error: cause instanceof Error ? cause.message : String(cause) };
16817
+ }
16818
+ }
16658
16819
  delete(id) {
16659
16820
  return this.db.deleteSession(id);
16660
16821
  }
@@ -16705,6 +16866,9 @@ var SessionManager = class {
16705
16866
  const summary = toSummarize.length === 0 ? "" : await this.buildSummary(toSummarize, summarize3) ?? outlineOf(toSummarize);
16706
16867
  return this.db.compact(sessionId, summary, beforeCount, IMPORTANT_ROUNDS * 2);
16707
16868
  }
16869
+ archiveAndCompact(sessionId, input) {
16870
+ return this.db.archiveAndCompact(sessionId, input);
16871
+ }
16708
16872
  async buildSummary(msgs, summarize3) {
16709
16873
  if (!summarize3) return null;
16710
16874
  const transcript = msgs.map((m) => `[${m.role}] ${m.content}`).join("\n\n");
@@ -17131,8 +17295,8 @@ var RecentWorkspaces = class {
17131
17295
  }
17132
17296
  remember(dir, now, name) {
17133
17297
  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);
17298
+ const kept = this.entries.find((e) => samePath(e.root, root))?.name;
17299
+ const rest = this.entries.filter((e) => !samePath(e.root, root));
17136
17300
  this.entries = [
17137
17301
  { root, name: name || kept || basename(root) || root, usedAt: now },
17138
17302
  ...rest
@@ -17141,7 +17305,7 @@ var RecentWorkspaces = class {
17141
17305
  }
17142
17306
  forget(dir) {
17143
17307
  const root = resolve(dir);
17144
- const next = this.entries.filter((e) => e.root !== root);
17308
+ const next = this.entries.filter((e) => !samePath(e.root, root));
17145
17309
  if (next.length === this.entries.length) return;
17146
17310
  this.entries = next;
17147
17311
  this.save();
@@ -17217,6 +17381,84 @@ function isRecentWorkspace(value) {
17217
17381
  const v = value;
17218
17382
  return typeof v["root"] === "string" && v["root"].length > 0 && typeof v["name"] === "string" && typeof v["usedAt"] === "number";
17219
17383
  }
17384
+ var MAX_LAST_OPEN_SESSIONS = 20;
17385
+ var FILE_VERSION3 = 1;
17386
+ function describe6(err) {
17387
+ return err instanceof Error ? err.message : String(err);
17388
+ }
17389
+ var LastOpenSessions = class {
17390
+ constructor(filePath = lastSessionsPath()) {
17391
+ this.filePath = filePath;
17392
+ this.load();
17393
+ }
17394
+ filePath;
17395
+ entries = [];
17396
+ loadErrors = [];
17397
+ writeErrors = [];
17398
+ get(root) {
17399
+ const key = resolve(root);
17400
+ return this.entries.find((e) => samePath(e.root, key))?.sessionId ?? null;
17401
+ }
17402
+ remember(root, sessionId, now) {
17403
+ const key = resolve(root);
17404
+ const head = this.entries[0];
17405
+ if (head && samePath(head.root, key) && head.sessionId === sessionId) return;
17406
+ const rest = this.entries.filter((e) => !samePath(e.root, key));
17407
+ this.entries = [{ root: key, sessionId, at: now }, ...rest].slice(0, MAX_LAST_OPEN_SESSIONS);
17408
+ this.save();
17409
+ }
17410
+ forget(root) {
17411
+ const key = resolve(root);
17412
+ const next = this.entries.filter((e) => !samePath(e.root, key));
17413
+ if (next.length === this.entries.length) return;
17414
+ this.entries = next;
17415
+ this.save();
17416
+ }
17417
+ load() {
17418
+ this.entries = [];
17419
+ if (!existsSync(this.filePath)) return;
17420
+ let parsed;
17421
+ try {
17422
+ parsed = JSON.parse(readFileSync(this.filePath, "utf-8"));
17423
+ } catch (err) {
17424
+ this.loadErrors.push(
17425
+ (lang) => t("last_session.unreadable", { path: this.filePath, reason: describe6(err) }, lang)
17426
+ );
17427
+ return;
17428
+ }
17429
+ this.adopt(parsed);
17430
+ }
17431
+ adopt(parsed) {
17432
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return;
17433
+ const file = parsed;
17434
+ if (file.version !== FILE_VERSION3) return;
17435
+ if (!Array.isArray(file.sessions)) return;
17436
+ this.entries = file.sessions.filter(isLastOpenSession).sort((a, b) => b.at - a.at).slice(0, MAX_LAST_OPEN_SESSIONS);
17437
+ }
17438
+ save() {
17439
+ const body2 = JSON.stringify(
17440
+ { version: FILE_VERSION3, sessions: this.entries },
17441
+ null,
17442
+ 2
17443
+ );
17444
+ const tmp = `${this.filePath}.${process.pid}.tmp`;
17445
+ try {
17446
+ mkdirSync(dirname(this.filePath), { recursive: true });
17447
+ writeFileSync(tmp, body2, { encoding: "utf-8", mode: 384 });
17448
+ renameSync(tmp, this.filePath);
17449
+ } catch (err) {
17450
+ rmSync(tmp, { force: true });
17451
+ this.writeErrors.push(
17452
+ (lang) => t("last_session.write_failed", { path: this.filePath, reason: describe6(err) }, lang)
17453
+ );
17454
+ }
17455
+ }
17456
+ };
17457
+ function isLastOpenSession(value) {
17458
+ if (typeof value !== "object" || value === null) return false;
17459
+ const v = value;
17460
+ return typeof v["root"] === "string" && v["root"].length > 0 && typeof v["sessionId"] === "string" && v["sessionId"].length > 0 && typeof v["at"] === "number";
17461
+ }
17220
17462
  function checkCodeExec(isolation) {
17221
17463
  if (isolation === "os") {
17222
17464
  return { allowed: true, reason: t("permission_reason.sandbox_os"), code: "sandbox-isolation" };
@@ -17465,11 +17707,11 @@ var ApprovalCache = class {
17465
17707
  return !rel.startsWith("..") && !isAbsolute(rel);
17466
17708
  }
17467
17709
  normalizeTarget(target) {
17468
- const t78 = target.trim();
17469
- if (!t78) return "";
17470
- const unix = t78.replace(/\\/g, "/");
17710
+ const t79 = target.trim();
17711
+ if (!t79) return "";
17712
+ const unix = t79.replace(/\\/g, "/");
17471
17713
  if (unix.startsWith("/") || /^[A-Za-z]:\//.test(unix)) return resolve(unix);
17472
- return t78;
17714
+ return t79;
17473
17715
  }
17474
17716
  load() {
17475
17717
  try {
@@ -17572,9 +17814,9 @@ function createSharedPermissionState(cache) {
17572
17814
  };
17573
17815
  }
17574
17816
  function cacheKeyFor(raw) {
17575
- const t78 = raw.trim();
17576
- if (!t78) return null;
17577
- return t78.slice(0, 500);
17817
+ const t79 = raw.trim();
17818
+ if (!t79) return null;
17819
+ return t79.slice(0, 500);
17578
17820
  }
17579
17821
  // src/permission/manager.ts
17580
17822
  var log3 = createLogger("permission");
@@ -18380,6 +18622,24 @@ function acquireScheduleLock(db, scheduleId, clock2 = Date.now) {
18380
18622
  }
18381
18623
  };
18382
18624
  }
18625
+ function isLive(holder, now) {
18626
+ if (holder.heartbeatAt < now - LOCK_STALE_MS) return false;
18627
+ return holder.host !== hostname() || pidAlive(holder.pid);
18628
+ }
18629
+ function listRunningSchedules(db, clock2 = Date.now) {
18630
+ const now = clock2();
18631
+ const rows = db.prepare(
18632
+ `SELECT schedule_id AS scheduleId, pid, host,
18633
+ acquired_at AS acquiredAt, heartbeat_at AS heartbeatAt
18634
+ FROM schedule_locks`
18635
+ ).all();
18636
+ return rows.filter((row) => isLive(row, now)).map((row) => ({
18637
+ scheduleId: row.scheduleId,
18638
+ startedAt: row.acquiredAt,
18639
+ pid: row.pid,
18640
+ host: row.host
18641
+ }));
18642
+ }
18383
18643
  function readHolder(db, scheduleId) {
18384
18644
  const row = db.prepare(
18385
18645
  "SELECT pid, host, acquired_at AS acquiredAt, heartbeat_at AS heartbeatAt FROM schedule_locks WHERE schedule_id = ?"
@@ -18620,9 +18880,15 @@ var ScheduleRegistrar = class {
18620
18880
  this.opts.store.setEnabled(def.id, enabled);
18621
18881
  return { ok: false, reason: "unsupported-platform" };
18622
18882
  }
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);
18883
+ if (enabled) {
18884
+ this.opts.store.setEnabled(def.id, true);
18885
+ const on = { ...def, enabled: true };
18886
+ if (!def.osTaskId) return this.register(on);
18887
+ const res2 = await backend.setEnabled(def.osTaskId, true);
18888
+ return res2.ok ? { ok: true, warnings: [] } : this.register(on);
18889
+ }
18890
+ const res = def.osTaskId ? await backend.setEnabled(def.osTaskId, false) : { ok: true };
18891
+ this.opts.store.setEnabled(def.id, false);
18626
18892
  return res.ok ? { ok: true, warnings: [] } : { ok: false, reason: "backend-error", detail: res.detail };
18627
18893
  }
18628
18894
  async retire(def) {
@@ -19733,7 +19999,7 @@ function runCommandHook(config, event, workDir) {
19733
19999
  const baseEnv = sanitizeEnvironment(process.env);
19734
20000
  const injectedEnv = injectEpochEnv(event, config.pluginRoot);
19735
20001
  const hookEnv = { ...baseEnv, ...injectedEnv, ...config.env };
19736
- return new Promise((resolve15) => {
20002
+ return new Promise((resolve16) => {
19737
20003
  const child = spawn(config.command, {
19738
20004
  shell: true,
19739
20005
  cwd: workDir,
@@ -19747,7 +20013,7 @@ function runCommandHook(config, event, workDir) {
19747
20013
  if (!settled) {
19748
20014
  settled = true;
19749
20015
  child.kill("SIGKILL");
19750
- resolve15({
20016
+ resolve16({
19751
20017
  exitCode: -1,
19752
20018
  stdout,
19753
20019
  stderr,
@@ -19783,7 +20049,7 @@ function runCommandHook(config, event, workDir) {
19783
20049
  }
19784
20050
  } catch {
19785
20051
  }
19786
- resolve15({
20052
+ resolve16({
19787
20053
  exitCode,
19788
20054
  stdout: stdout.trim(),
19789
20055
  stderr: stderr.trim(),
@@ -19796,7 +20062,7 @@ function runCommandHook(config, event, workDir) {
19796
20062
  clearTimeout(timer);
19797
20063
  if (settled) return;
19798
20064
  settled = true;
19799
- resolve15({
20065
+ resolve16({
19800
20066
  exitCode: -1,
19801
20067
  stdout,
19802
20068
  stderr,
@@ -19909,7 +20175,7 @@ var HookManager = class {
19909
20175
  return { blocked: true, reason: result.rejectReason || t("hook_load.rejected") };
19910
20176
  }
19911
20177
  } catch (err) {
19912
- this.log("warn", `[HookManager] ${type} \u7684 command hook \u6267\u884C\u5F02\u5E38: ${describe7(err)}`, {
20178
+ this.log("warn", `[HookManager] ${type} \u7684 command hook \u6267\u884C\u5F02\u5E38: ${describe8(err)}`, {
19913
20179
  hookType: type,
19914
20180
  command: config.command
19915
20181
  });
@@ -19927,7 +20193,7 @@ var HookManager = class {
19927
20193
  (_, reject2) => setTimeout(() => reject2(new Error("Hook timeout")), HOOK_TIMEOUT_MS)
19928
20194
  )
19929
20195
  ]).catch((err) => {
19930
- this.log("warn", `[HookManager] ${type} (${reg.plugin}) \u5931\u8D25: ${describe7(err)}`, {
20196
+ this.log("warn", `[HookManager] ${type} (${reg.plugin}) \u5931\u8D25: ${describe8(err)}`, {
19931
20197
  hookType: type,
19932
20198
  plugin: reg.plugin
19933
20199
  });
@@ -19939,7 +20205,7 @@ var HookManager = class {
19939
20205
  if (!matchesHook(entry.matcher, event)) continue;
19940
20206
  for (const config of entry.configs) {
19941
20207
  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)}`, {
20208
+ this.log("warn", `[HookManager] ${type} \u7684 command hook \u5F02\u6B65\u5F02\u5E38: ${describe8(err)}`, {
19943
20209
  hookType: type,
19944
20210
  command: config.command
19945
20211
  });
@@ -19960,7 +20226,7 @@ var HookManager = class {
19960
20226
  ]);
19961
20227
  if (result !== null && result !== void 0) return result;
19962
20228
  } catch (err) {
19963
- this.log("warn", `[HookManager] ${type} (${reg.plugin}) \u5931\u8D25: ${describe7(err)}`, {
20229
+ this.log("warn", `[HookManager] ${type} (${reg.plugin}) \u5931\u8D25: ${describe8(err)}`, {
19964
20230
  hookType: type,
19965
20231
  plugin: reg.plugin
19966
20232
  });
@@ -19981,7 +20247,7 @@ var HookManager = class {
19981
20247
  ]);
19982
20248
  if (result) results.push(result);
19983
20249
  } catch (err) {
19984
- this.log("warn", `[HookManager] ${type} (${reg.plugin}) \u5931\u8D25: ${describe7(err)}`, {
20250
+ this.log("warn", `[HookManager] ${type} (${reg.plugin}) \u5931\u8D25: ${describe8(err)}`, {
19985
20251
  hookType: type,
19986
20252
  plugin: reg.plugin
19987
20253
  });
@@ -19998,7 +20264,7 @@ var HookManager = class {
19998
20264
  const verdict = verdictOf2(result);
19999
20265
  if (verdict) results.push(verdict);
20000
20266
  } catch (err) {
20001
- this.log("warn", `[HookManager] ${type} \u7684 command hook \u6267\u884C\u5F02\u5E38: ${describe7(err)}`, {
20267
+ this.log("warn", `[HookManager] ${type} \u7684 command hook \u6267\u884C\u5F02\u5E38: ${describe8(err)}`, {
20002
20268
  hookType: type,
20003
20269
  command: config.command
20004
20270
  });
@@ -20014,7 +20280,7 @@ var HookManager = class {
20014
20280
  return [...list].sort((a, b) => a.priority - b.priority);
20015
20281
  }
20016
20282
  };
20017
- function describe7(err) {
20283
+ function describe8(err) {
20018
20284
  return err instanceof Error ? err.message : String(err);
20019
20285
  }
20020
20286
  function verdictOf2(result) {
@@ -21311,7 +21577,7 @@ async function withStaged(source, opts, fn) {
21311
21577
  shape = existsSync(join(unpacked, SKILL_FILE)) ? "skill-dir" : "tree";
21312
21578
  }
21313
21579
  const staged = stageImport(root, staging, shape, opts.lang);
21314
- const preview3 = describe8(source, form, staged.skills, staged.issues, opts.existing, opts.lang);
21580
+ const preview3 = describe9(source, form, staged.skills, staged.issues, opts.existing, opts.lang);
21315
21581
  if (preview3.skills.length === 0) {
21316
21582
  const detail = t("skill.import_empty", { path: source }, opts.lang);
21317
21583
  return { ok: false, reason: "empty", detail, issues: preview3.issues };
@@ -21322,7 +21588,7 @@ async function withStaged(source, opts, fn) {
21322
21588
  rmSync(unpacked, { recursive: true, force: true });
21323
21589
  }
21324
21590
  }
21325
- function describe8(source, form, staged, issues, existing, lang) {
21591
+ function describe9(source, form, staged, issues, existing, lang) {
21326
21592
  const byName = new Map(existing.map((s) => [s.name, s.scope]));
21327
21593
  const entries2 = [];
21328
21594
  const taken = /* @__PURE__ */ new Set();
@@ -21992,6 +22258,19 @@ var ContextCompressor = class {
21992
22258
  };
21993
22259
  }
21994
22260
  const { head, middle, tail } = this.determineBoundaries(pruned.messages, config);
22261
+ if (middle.length === 0) {
22262
+ const kept = this.cleanupOrphans(pruned.messages);
22263
+ this.turnsSinceCompress = 0;
22264
+ return {
22265
+ messages: kept,
22266
+ summary: "",
22267
+ ...prunedCounters,
22268
+ summarizedMessages: 0,
22269
+ newTokenCount: this.estimateTokens(kept),
22270
+ droppedOrphans: pruned.messages.length - kept.length,
22271
+ summarySkipped: true
22272
+ };
22273
+ }
21995
22274
  const nl = "\n";
21996
22275
  const middleText = middle.map((m) => `${m.role}: ${m.content}`).join(nl);
21997
22276
  const summarized = await this.generateSummary(
@@ -22027,6 +22306,7 @@ var ContextCompressor = class {
22027
22306
  summarizedMessages: middle.length,
22028
22307
  newTokenCount: this.estimateTokens(result),
22029
22308
  droppedOrphans,
22309
+ ...summary && droppedOrphans === 0 && middle.length > 0 ? { carriedHead: head.length, carriedTail: tail.length } : {},
22030
22310
  ...summarized?.usage ? { usage: summarized.usage } : {},
22031
22311
  ...summarized?.model ? { model: summarized.model } : {}
22032
22312
  };
@@ -22158,10 +22438,10 @@ ${extra}` : withGoal;
22158
22438
  return messages.reduce((sum, m) => sum + estimateTokens(m.content), 0);
22159
22439
  }
22160
22440
  };
22161
- var FILE_VERSION3 = 1;
22441
+ var FILE_VERSION4 = 1;
22162
22442
  var LEVELS = ["trusted", "untrusted"];
22163
22443
  var SCOPES = ["directory", "directory-tree"];
22164
- function describe9(err) {
22444
+ function describe10(err) {
22165
22445
  return err instanceof Error ? err.message : String(err);
22166
22446
  }
22167
22447
  function covers(base, target, scope) {
@@ -22170,9 +22450,6 @@ function covers(base, target, scope) {
22170
22450
  const rel = relative(base, target);
22171
22451
  return !rel.startsWith("..") && !isAbsolute(rel);
22172
22452
  }
22173
- function samePath(a, b) {
22174
- return relative(a, b) === "";
22175
- }
22176
22453
  var TrustManager = class {
22177
22454
  constructor(filePath = trustPath()) {
22178
22455
  this.filePath = filePath;
@@ -22238,7 +22515,7 @@ var TrustManager = class {
22238
22515
  raw = readFileSync(this.filePath, "utf-8");
22239
22516
  } catch (err) {
22240
22517
  this.loadErrors.push(
22241
- t("trust_gate.record_read_failed", { path: this.filePath, reason: describe9(err) })
22518
+ t("trust_gate.record_read_failed", { path: this.filePath, reason: describe10(err) })
22242
22519
  );
22243
22520
  return;
22244
22521
  }
@@ -22247,7 +22524,7 @@ var TrustManager = class {
22247
22524
  parsed = JSON.parse(raw);
22248
22525
  } catch (err) {
22249
22526
  this.loadErrors.push(
22250
- t("trust_gate.record_bad_json", { path: this.filePath, reason: describe9(err) })
22527
+ t("trust_gate.record_bad_json", { path: this.filePath, reason: describe10(err) })
22251
22528
  );
22252
22529
  return;
22253
22530
  }
@@ -22259,12 +22536,12 @@ var TrustManager = class {
22259
22536
  return;
22260
22537
  }
22261
22538
  const file = parsed;
22262
- if (file.version !== FILE_VERSION3) {
22539
+ if (file.version !== FILE_VERSION4) {
22263
22540
  this.loadErrors.push(
22264
22541
  t("trust_gate.record_bad_version", {
22265
22542
  path: this.filePath,
22266
22543
  found: String(file.version),
22267
- expected: FILE_VERSION3
22544
+ expected: FILE_VERSION4
22268
22545
  })
22269
22546
  );
22270
22547
  return;
@@ -22285,7 +22562,7 @@ var TrustManager = class {
22285
22562
  save() {
22286
22563
  mkdirSync(dirname(this.filePath), { recursive: true });
22287
22564
  const body2 = JSON.stringify(
22288
- { version: FILE_VERSION3, records: this.records },
22565
+ { version: FILE_VERSION4, records: this.records },
22289
22566
  null,
22290
22567
  2
22291
22568
  );
@@ -22296,7 +22573,7 @@ var TrustManager = class {
22296
22573
  } catch (err) {
22297
22574
  rmSync(tmp, { force: true });
22298
22575
  throw new Error(
22299
- t("trust_gate.record_write_failed", { path: this.filePath, reason: describe9(err) })
22576
+ t("trust_gate.record_write_failed", { path: this.filePath, reason: describe10(err) })
22300
22577
  );
22301
22578
  }
22302
22579
  }
@@ -22539,7 +22816,7 @@ var CodeSandbox = class {
22539
22816
  ...IS_WINDOWS ? { windowsHide: true } : {}
22540
22817
  };
22541
22818
  const child = spawn(command, args, spawnOpts);
22542
- return new Promise((resolve15) => {
22819
+ return new Promise((resolve16) => {
22543
22820
  let stdout = "";
22544
22821
  let stderr = "";
22545
22822
  let killedForOutput = false;
@@ -22565,7 +22842,7 @@ var CodeSandbox = class {
22565
22842
  child.on("error", (err) => {
22566
22843
  opts.signal?.removeEventListener("abort", onAbort);
22567
22844
  if (err.code === "ENOENT") {
22568
- resolve15({
22845
+ resolve16({
22569
22846
  success: false,
22570
22847
  output: "",
22571
22848
  error: `[\u9519\u8BEF] \u627E\u4E0D\u5230\u89E3\u91CA\u5668: ${command}`,
@@ -22574,7 +22851,7 @@ var CodeSandbox = class {
22574
22851
  });
22575
22852
  return;
22576
22853
  }
22577
- resolve15({
22854
+ resolve16({
22578
22855
  success: false,
22579
22856
  output: "",
22580
22857
  error: `[\u9519\u8BEF] ${err.message}`,
@@ -22588,7 +22865,7 @@ var CodeSandbox = class {
22588
22865
  if (stderr.length < MAX_OUTPUT) stderr += errDecoder?.end() ?? "";
22589
22866
  const duration = Date.now() - start;
22590
22867
  if (killedForOutput) {
22591
- resolve15({
22868
+ resolve16({
22592
22869
  success: false,
22593
22870
  output: trunc(stdout, stderr),
22594
22871
  error: `[\u8F93\u51FA\u8D85\u9650] \u8D85\u8FC7 ${MAX_OUTPUT} \u5B57\u8282\uFF0C\u5DF2\u7EC8\u6B62`,
@@ -22598,7 +22875,7 @@ var CodeSandbox = class {
22598
22875
  return;
22599
22876
  }
22600
22877
  if (sig) {
22601
- resolve15({
22878
+ resolve16({
22602
22879
  success: false,
22603
22880
  output: trunc(stdout, stderr),
22604
22881
  error: opts.signal?.aborted ? "[\u5DF2\u53D6\u6D88]" : "[\u8D85\u65F6] \u6267\u884C\u8D85\u65F6",
@@ -22610,7 +22887,7 @@ var CodeSandbox = class {
22610
22887
  const output = trunc(stdout, stderr);
22611
22888
  if (code !== 0 && code !== null) {
22612
22889
  const oom = /heap out of memory|allocation failed/i.test(stderr);
22613
- resolve15({
22890
+ resolve16({
22614
22891
  success: false,
22615
22892
  output,
22616
22893
  error: oom ? `[\u5185\u5B58\u8D85\u9650] \u8D85\u8FC7 ${MAX_MEMORY}MB` : `[\u8FD0\u884C\u65F6\u9519\u8BEF] exit ${code}: ${stderr.slice(0, 200)}`,
@@ -22619,7 +22896,7 @@ var CodeSandbox = class {
22619
22896
  });
22620
22897
  return;
22621
22898
  }
22622
- resolve15({ success: true, output, duration });
22899
+ resolve16({ success: true, output, duration });
22623
22900
  });
22624
22901
  });
22625
22902
  }
@@ -22679,4 +22956,4 @@ function trunc(stdout, stderr) {
22679
22956
  * `--tree` 的命令帮助里,让用户自己知道 `--tree` 意味着什么。
22680
22957
  */
22681
22958
 
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 };
22959
+ 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, 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 };