flavor-code 1.2.18 → 1.2.20

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.
@@ -3449,7 +3449,8 @@ var FlavorSession = class {
3449
3449
  version: 1,
3450
3450
  type: "SessionStart",
3451
3451
  payload: { workspace: this.#services.workspace }
3452
- }).then(() => {
3452
+ }).then(async (decision) => {
3453
+ if (decision.additionalContext !== void 0) await this.#services.addContext?.(decision.additionalContext);
3453
3454
  this.#started = true;
3454
3455
  });
3455
3456
  return this.#startPromise;
@@ -8057,7 +8058,7 @@ function createIncidentReporter(options) {
8057
8058
  import { spawn as spawn5 } from "child_process";
8058
8059
  import { writeFile as writeFile8 } from "fs/promises";
8059
8060
  import { join as join10 } from "path";
8060
- import { z as z12 } from "zod";
8061
+ import { z as z13 } from "zod";
8061
8062
 
8062
8063
  // src/evolve/loader.ts
8063
8064
  import { cp, mkdir as mkdir8, mkdtemp, readdir as readdir4, rm as rm2, stat as stat4, writeFile as writeFile6 } from "fs/promises";
@@ -8066,9 +8067,10 @@ import { join as join8, resolve as resolve9 } from "path";
8066
8067
 
8067
8068
  // src/plugins/host.ts
8068
8069
  import { lstatSync, realpathSync as realpathSync2 } from "fs";
8069
- import { lstat as lstat5, open as open5, readdir as readdir3, realpath as realpath3, stat as stat3, writeFile as writeFile5 } from "fs/promises";
8070
+ import { lstat as lstat5, open as open5, readdir as readdir3, realpath as realpath4, stat as stat3, writeFile as writeFile5 } from "fs/promises";
8070
8071
  import { isAbsolute as isAbsolute5, relative as relative7, resolve as resolve8, sep as sep7 } from "path";
8071
8072
  import { pathToFileURL } from "url";
8073
+ import { z as z12 } from "zod";
8072
8074
 
8073
8075
  // src/plugins/types.ts
8074
8076
  import { z as z11 } from "zod";
@@ -8098,10 +8100,188 @@ var PluginManifestSchema = z11.object({
8098
8100
  }).strict()
8099
8101
  }).strict();
8100
8102
 
8103
+ // src/plugins/worker-host.ts
8104
+ import { realpath as realpath3 } from "fs/promises";
8105
+ import { dirname as dirname10 } from "path";
8106
+ import { Worker } from "worker_threads";
8107
+ var DEFAULT_ACTIVATION_TIMEOUT_MS = 1e4;
8108
+ var DEFAULT_INVOCATION_TIMEOUT_MS = 3e4;
8109
+ var DEFAULT_MAX_OLD_SPACE_MB = 128;
8110
+ var DEFAULT_SHUTDOWN_TIMEOUT_MS = 5e3;
8111
+ async function startPluginSandbox(options) {
8112
+ const entryPath = await realpath3(options.entryPath);
8113
+ const pluginRoot = await realpath3(options.pluginRoot ?? dirname10(entryPath));
8114
+ const activationTimeoutMs = options.activationTimeoutMs ?? DEFAULT_ACTIVATION_TIMEOUT_MS;
8115
+ const invocationTimeoutMs = options.invocationTimeoutMs ?? DEFAULT_INVOCATION_TIMEOUT_MS;
8116
+ let configJson;
8117
+ try {
8118
+ configJson = JSON.stringify(options.config ?? {});
8119
+ } catch (error) {
8120
+ throw new Error(`Plugin sandbox config is not serializable: ${String(error)}`);
8121
+ }
8122
+ const workerEntry = new URL(import.meta.url.endsWith(".ts") ? "./plugin-worker-entry.ts" : "./plugin-worker-entry.js", import.meta.url);
8123
+ const worker = new Worker(workerEntry, {
8124
+ workerData: { entryPath, pluginRoot, pluginName: options.pluginName, pluginVersion: options.pluginVersion, configJson },
8125
+ execArgv: ["--experimental-vm-modules", "--no-warnings"],
8126
+ resourceLimits: {
8127
+ maxOldGenerationSizeMb: options.maxOldSpaceMb ?? DEFAULT_MAX_OLD_SPACE_MB,
8128
+ maxYoungGenerationSizeMb: 16,
8129
+ codeRangeSizeMb: 16,
8130
+ stackSizeMb: 4
8131
+ }
8132
+ });
8133
+ let closed = false;
8134
+ let nextId = 1;
8135
+ const pending = /* @__PURE__ */ new Map();
8136
+ let disposeResolve;
8137
+ let disposeReject;
8138
+ let failWorker;
8139
+ const ready = await new Promise((resolveReady, rejectReady) => {
8140
+ let settled = false;
8141
+ const timer = setTimeout(() => {
8142
+ settled = true;
8143
+ closed = true;
8144
+ void worker.terminate();
8145
+ rejectReady(new Error(`Plugin activation sandbox timed out after ${activationTimeoutMs}ms`));
8146
+ }, activationTimeoutMs);
8147
+ const fail = (error) => {
8148
+ if (closed && settled) return;
8149
+ closed = true;
8150
+ clearTimeout(timer);
8151
+ for (const request of pending.values()) {
8152
+ clearTimeout(request.timer);
8153
+ request.reject(error);
8154
+ }
8155
+ pending.clear();
8156
+ disposeReject?.(error);
8157
+ if (!settled) {
8158
+ settled = true;
8159
+ rejectReady(error);
8160
+ }
8161
+ void worker.terminate();
8162
+ };
8163
+ failWorker = fail;
8164
+ worker.on("message", (raw) => {
8165
+ if (!isWorkerMessage(raw)) {
8166
+ fail(new Error("Plugin sandbox sent an invalid protocol message"));
8167
+ return;
8168
+ }
8169
+ const message2 = raw;
8170
+ if (message2.type === "fatal") {
8171
+ fail(new Error(message2.error));
8172
+ return;
8173
+ }
8174
+ if (message2.type === "ready") {
8175
+ if (settled || !isSandboxResult(message2.result)) {
8176
+ fail(new Error("Plugin sandbox sent an invalid or duplicate ready message"));
8177
+ return;
8178
+ }
8179
+ settled = true;
8180
+ clearTimeout(timer);
8181
+ resolveReady(message2.result);
8182
+ return;
8183
+ }
8184
+ if (!settled) {
8185
+ fail(new Error(`Plugin sandbox sent ${message2.type} before ready`));
8186
+ return;
8187
+ }
8188
+ if (message2.type === "response") {
8189
+ const request = pending.get(message2.id);
8190
+ if (request === void 0) {
8191
+ fail(new Error("Plugin sandbox sent a response for an unknown request"));
8192
+ return;
8193
+ }
8194
+ pending.delete(message2.id);
8195
+ clearTimeout(request.timer);
8196
+ if (message2.ok) {
8197
+ try {
8198
+ request.resolve(JSON.parse(message2.valueJson));
8199
+ } catch {
8200
+ fail(new Error("Plugin sandbox returned invalid JSON"));
8201
+ }
8202
+ } else request.reject(new Error(message2.error));
8203
+ return;
8204
+ }
8205
+ if (message2.type === "disposed") {
8206
+ closed = true;
8207
+ disposeResolve?.();
8208
+ void worker.terminate();
8209
+ }
8210
+ });
8211
+ worker.once("error", fail);
8212
+ worker.once("exit", (code) => {
8213
+ if (!closed) fail(new Error(`Plugin worker exited with code ${code}`));
8214
+ });
8215
+ });
8216
+ return {
8217
+ result: ready,
8218
+ invoke(kind, name, args) {
8219
+ if (closed) return Promise.reject(new Error("Plugin sandbox is closed"));
8220
+ let argsJson;
8221
+ try {
8222
+ argsJson = JSON.stringify(args);
8223
+ } catch (error) {
8224
+ return Promise.reject(new Error(`Plugin sandbox arguments are not serializable: ${String(error)}`));
8225
+ }
8226
+ const id = nextId++;
8227
+ return new Promise((resolveInvoke, rejectInvoke) => {
8228
+ const timer = setTimeout(() => {
8229
+ const error = new Error(`Plugin sandbox invocation timed out after ${invocationTimeoutMs}ms`);
8230
+ failWorker(error);
8231
+ }, invocationTimeoutMs);
8232
+ pending.set(id, { resolve: (value) => resolveInvoke(value), reject: rejectInvoke, timer });
8233
+ worker.postMessage({ type: "invoke", id, kind, name, argsJson });
8234
+ });
8235
+ },
8236
+ dispose() {
8237
+ if (closed) return Promise.resolve();
8238
+ return new Promise((resolveDispose, rejectDispose) => {
8239
+ const timer = setTimeout(() => {
8240
+ const error = new Error(`Plugin sandbox shutdown timed out after ${DEFAULT_SHUTDOWN_TIMEOUT_MS}ms`);
8241
+ failWorker(error);
8242
+ }, DEFAULT_SHUTDOWN_TIMEOUT_MS);
8243
+ disposeResolve = () => {
8244
+ clearTimeout(timer);
8245
+ resolveDispose();
8246
+ };
8247
+ disposeReject = (error) => {
8248
+ clearTimeout(timer);
8249
+ rejectDispose(error);
8250
+ };
8251
+ worker.postMessage({ type: "shutdown" });
8252
+ });
8253
+ }
8254
+ };
8255
+ }
8256
+ function isWorkerMessage(value) {
8257
+ if (typeof value !== "object" || value === null || !("type" in value)) return false;
8258
+ const type = value.type;
8259
+ if (type === "disposed") return true;
8260
+ if (type === "fatal") return typeof value.error === "string";
8261
+ if (type === "ready") return "result" in value;
8262
+ if (type !== "response") return false;
8263
+ const response = value;
8264
+ return Number.isSafeInteger(response.id) && typeof response.ok === "boolean" && (response.ok ? typeof response.valueJson === "string" : typeof response.error === "string");
8265
+ }
8266
+ function isSandboxResult(value) {
8267
+ if (typeof value !== "object" || value === null) return false;
8268
+ const result = value;
8269
+ if (!(result.ok === true && typeof result.name === "string" && typeof result.version === "string" && Array.isArray(result.registeredTools) && result.registeredTools.every((item) => typeof item === "string") && Array.isArray(result.registeredCommands) && result.registeredCommands.every((item) => typeof item === "string") && Array.isArray(result.registeredHooks) && result.registeredHooks.every((item) => typeof item === "string") && Array.isArray(result.registeredSkillRoots) && result.registeredSkillRoots.every((item) => typeof item === "string") && Array.isArray(result.registeredModelAdapters) && result.registeredModelAdapters.every((item) => typeof item === "string") && typeof result.contributions === "object" && result.contributions !== null)) return false;
8270
+ const contributions = result.contributions;
8271
+ const named = (item) => typeof item === "object" && item !== null && typeof item.name === "string";
8272
+ if (!Array.isArray(contributions.commands) || !contributions.commands.every((item) => named(item) && (item.description === void 0 || typeof item.description === "string"))) return false;
8273
+ if (!Array.isArray(contributions.tools) || !contributions.tools.every((item) => named(item) && typeof item.toolName === "string" && typeof item.description === "string" && (item.modelInputSchema === void 0 || typeof item.modelInputSchema === "object" && item.modelInputSchema !== null) && (item.readOnly === void 0 || typeof item.readOnly === "boolean"))) return false;
8274
+ if (!Array.isArray(contributions.hooks) || !contributions.hooks.every(named)) return false;
8275
+ if (!Array.isArray(contributions.skillRoots) || !contributions.skillRoots.every((item) => named(item) && typeof item.root === "string")) return false;
8276
+ if (!Array.isArray(contributions.modelAdapters) || !contributions.modelAdapters.every(named)) return false;
8277
+ const same = (left, right) => left.length === right.length && left.every((name, index) => name === right[index]?.name);
8278
+ return same(result.registeredCommands, contributions.commands) && same(result.registeredTools, contributions.tools) && same(result.registeredHooks, contributions.hooks) && same(result.registeredSkillRoots, contributions.skillRoots) && same(result.registeredModelAdapters, contributions.modelAdapters);
8279
+ }
8280
+
8101
8281
  // src/plugins/host.ts
8102
8282
  var MANIFEST = "flavor-plugin.json";
8103
8283
  var MAX_MANIFEST_BYTES2 = 64 * 1024;
8104
- var DEFAULT_ACTIVATION_TIMEOUT_MS = 1e4;
8284
+ var DEFAULT_ACTIVATION_TIMEOUT_MS2 = 1e4;
8105
8285
  var DEFAULT_UNLOAD_TIMEOUT_MS = 5e3;
8106
8286
  var silentLogger = { debug() {
8107
8287
  }, info() {
@@ -8118,7 +8298,7 @@ var PluginHost = class {
8118
8298
  #loaded = false;
8119
8299
  constructor(options) {
8120
8300
  this.#options = options;
8121
- this.#activationTimeoutMs = positiveTimeout(options.activationTimeoutMs, DEFAULT_ACTIVATION_TIMEOUT_MS, "activationTimeoutMs");
8301
+ this.#activationTimeoutMs = positiveTimeout(options.activationTimeoutMs, DEFAULT_ACTIVATION_TIMEOUT_MS2, "activationTimeoutMs");
8122
8302
  this.#unloadTimeoutMs = positiveTimeout(options.unloadTimeoutMs, DEFAULT_UNLOAD_TIMEOUT_MS, "unloadTimeoutMs");
8123
8303
  }
8124
8304
  get diagnostics() {
@@ -8232,7 +8412,7 @@ var PluginHost = class {
8232
8412
  try {
8233
8413
  const rootInfo = await lstat5(inputRoot);
8234
8414
  if (!rootInfo.isDirectory() || rootInfo.isSymbolicLink()) throw new Error("Plugin root must be a static directory");
8235
- const root = await realpath3(inputRoot);
8415
+ const root = await realpath4(inputRoot);
8236
8416
  const rawManifest = await readManifest(resolve8(root, MANIFEST));
8237
8417
  if (typeof rawManifest === "object" && rawManifest !== null && "name" in rawManifest && typeof rawManifest.name === "string") {
8238
8418
  diagnosticLabel = rawManifest.name;
@@ -8252,18 +8432,79 @@ var PluginHost = class {
8252
8432
  const claimed = [];
8253
8433
  const state = { active: true, controller: new AbortController() };
8254
8434
  let activation;
8435
+ const useSandbox = this.#options.sandbox === true;
8255
8436
  try {
8256
8437
  await verifyEntry(candidate.root, candidate.entry, candidate.entrySnapshot);
8257
- const imported = import(`${pathToFileURL(candidate.entrySnapshot.physicalPath).href}?flavor=${encodeURIComponent(plugin)}&v=${Date.now()}`);
8258
- const module = await bounded(imported, this.#activationTimeoutMs, "Plugin import");
8259
- await verifyEntry(candidate.root, candidate.entry, candidate.entrySnapshot);
8260
- if (typeof module.activate !== "function") throw new Error("Plugin entry must export activate(context)");
8261
- const context = this.#context(candidate, disposers, claimed, state);
8262
- activation = Promise.resolve().then(() => module.activate(context));
8263
- const deactivate = await bounded(activation, this.#activationTimeoutMs, "Plugin activation");
8264
- if (deactivate !== void 0) {
8265
- if (typeof deactivate !== "function") throw new Error("Plugin activate result must be a disposer or undefined");
8266
- disposers.push(deactivate);
8438
+ if (useSandbox) {
8439
+ const session = await bounded(
8440
+ startPluginSandbox({
8441
+ entryPath: candidate.entrySnapshot.physicalPath,
8442
+ pluginRoot: candidate.root,
8443
+ pluginName: plugin,
8444
+ pluginVersion: candidate.manifest.version,
8445
+ config: redactConfig(this.#options.config ?? {}),
8446
+ activationTimeoutMs: this.#activationTimeoutMs
8447
+ }),
8448
+ this.#activationTimeoutMs + 1e3,
8449
+ "Plugin sandbox activation"
8450
+ );
8451
+ disposers.push(() => session.dispose());
8452
+ const result = session.result;
8453
+ if (!result.ok) throw new Error(result.error ?? `Plugin "${plugin}" sandbox execution failed`);
8454
+ const context = this.#context(candidate, disposers, claimed, state);
8455
+ for (const command of result.contributions.commands) {
8456
+ context.registerCommand(command.name, (args, commandContext) => session.invoke("command", command.name, [
8457
+ args,
8458
+ { workspace: commandContext.workspace }
8459
+ ]), command.description);
8460
+ }
8461
+ for (const contribution of result.contributions.tools) {
8462
+ const tool = {
8463
+ name: contribution.toolName,
8464
+ description: contribution.description,
8465
+ inputSchema: z12.unknown(),
8466
+ ...contribution.modelInputSchema === void 0 ? {} : { modelInputSchema: contribution.modelInputSchema },
8467
+ ...contribution.readOnly === void 0 ? {} : { readOnly: contribution.readOnly },
8468
+ paths: () => [],
8469
+ execute: (input, _signal, toolContext) => session.invoke("tool", contribution.name, [
8470
+ input,
8471
+ toolContext === void 0 ? void 0 : { agent: toolContext.agent, ownerId: toolContext.ownerId }
8472
+ ])
8473
+ };
8474
+ context.registerTool(contribution.name, tool);
8475
+ }
8476
+ for (const hook of result.contributions.hooks) {
8477
+ context.registerHook(
8478
+ hook.name,
8479
+ (event) => session.invoke("hook", hook.name, [event]),
8480
+ hook.options
8481
+ );
8482
+ }
8483
+ for (const skill of result.contributions.skillRoots) {
8484
+ context.registerSkillRoot(skill.name, skill.root);
8485
+ }
8486
+ for (const adapter of result.contributions.modelAdapters) {
8487
+ context.registerModelAdapter(adapter.name, {
8488
+ async *stream(request) {
8489
+ const safeRequest = { ...request, signal: void 0 };
8490
+ const events = await session.invoke("modelAdapter", adapter.name, [safeRequest]);
8491
+ for (const event of events) yield event;
8492
+ }
8493
+ });
8494
+ }
8495
+ await verifyEntry(candidate.root, candidate.entry, candidate.entrySnapshot);
8496
+ } else {
8497
+ const imported = import(`${pathToFileURL(candidate.entrySnapshot.physicalPath).href}?flavor=${encodeURIComponent(plugin)}&v=${Date.now()}`);
8498
+ const module = await bounded(imported, this.#activationTimeoutMs, "Plugin import");
8499
+ await verifyEntry(candidate.root, candidate.entry, candidate.entrySnapshot);
8500
+ if (typeof module.activate !== "function") throw new Error("Plugin entry must export activate(context)");
8501
+ const context = this.#context(candidate, disposers, claimed, state);
8502
+ activation = Promise.resolve().then(() => module.activate(context));
8503
+ const deactivate = await bounded(activation, this.#activationTimeoutMs, "Plugin activation");
8504
+ if (deactivate !== void 0) {
8505
+ if (typeof deactivate !== "function") throw new Error("Plugin activate result must be a disposer or undefined");
8506
+ disposers.push(deactivate);
8507
+ }
8267
8508
  }
8268
8509
  this.#assertAllDeclaredRegistered(candidate, claimed);
8269
8510
  const metadata = { name: plugin, version: candidate.manifest.version, source: candidate.source, root: candidate.root };
@@ -8427,7 +8668,7 @@ async function readManifest(path) {
8427
8668
  async function snapshotEntry(root, entry2) {
8428
8669
  const lexicalStats = await lstat5(entry2, { bigint: true });
8429
8670
  if (!lexicalStats.isFile() && !lexicalStats.isSymbolicLink()) throw new Error("Plugin entry must be a file");
8430
- const physicalPath = await realpath3(entry2);
8671
+ const physicalPath = await realpath4(entry2);
8431
8672
  assertContained(root, physicalPath, "Plugin entry symlink");
8432
8673
  const physicalStats = await stat3(physicalPath, { bigint: true });
8433
8674
  if (!physicalStats.isFile()) throw new Error("Plugin entry must resolve to a regular file");
@@ -8543,6 +8784,8 @@ var SCAFFOLD_ENTRY = (name) => `// ${name} \u2014 generated by /evolve improve <
8543
8784
  // - context: { signal, config, logger, services, registerCommand,
8544
8785
  // registerTool, registerHook, registerSkillRoot, registerModelAdapter }
8545
8786
  // - every contribution you register MUST be declared in contributes
8787
+ // - sandbox verification only permits relative JS modules inside this plugin root;
8788
+ // Node.js built-ins, package imports, filesystem, and network APIs are unavailable
8546
8789
  //
8547
8790
  // Implement your fix here. Example \u2014 observe tool failures:
8548
8791
  // ctx.registerHook("PostToolUseFailure", (event) => {
@@ -8582,7 +8825,9 @@ async function verifyFixPlugin(workspace, name) {
8582
8825
  await cp(pluginRoot, join8(sandbox, name), { recursive: true });
8583
8826
  const host = new PluginHost({
8584
8827
  projectPluginDirs: [sandbox],
8828
+ sandbox: true,
8585
8829
  config: {},
8830
+ activationTimeoutMs: 5e3,
8586
8831
  registrations: {
8587
8832
  command: (commandName) => {
8588
8833
  collected.commands.push(commandName);
@@ -8596,12 +8841,11 @@ async function verifyFixPlugin(workspace, name) {
8596
8841
  skillRoot: () => () => void 0,
8597
8842
  modelAdapter: () => () => void 0
8598
8843
  },
8599
- logger: {
8600
- debug: () => void 0,
8601
- info: () => void 0,
8602
- warn: () => void 0,
8603
- error: () => void 0
8604
- }
8844
+ logger: { debug() {
8845
+ }, info() {
8846
+ }, warn() {
8847
+ }, error() {
8848
+ } }
8605
8849
  });
8606
8850
  await host.loadAll();
8607
8851
  const loaded = host.loadedPlugins;
@@ -8660,7 +8904,7 @@ async function revertFixPlugin(workspace, name) {
8660
8904
  // src/evolve/store.ts
8661
8905
  import { createHash as createHash5 } from "crypto";
8662
8906
  import { appendFile, mkdir as mkdir9, readFile as readFile7, rm as rm3, writeFile as writeFile7 } from "fs/promises";
8663
- import { dirname as dirname10, join as join9 } from "path";
8907
+ import { dirname as dirname11, join as join9 } from "path";
8664
8908
  function normalizeError(message2) {
8665
8909
  return String(message2 ?? "").replace(/\s+/g, " ").replace(/"[^"]*"/g, '"\u2026"').replace(/`[^`]*`/g, '"\u2026"').trim().slice(0, 160);
8666
8910
  }
@@ -8689,7 +8933,7 @@ async function readJsonLines(file) {
8689
8933
  }
8690
8934
  }
8691
8935
  async function writeJsonLines(file, records) {
8692
- await mkdir9(dirname10(file), { recursive: true, mode: 448 });
8936
+ await mkdir9(dirname11(file), { recursive: true, mode: 448 });
8693
8937
  const body = records.map((record) => JSON.stringify(record)).join("\n");
8694
8938
  await writeFile7(file, body.length > 0 ? `${body}
8695
8939
  ` : "", { encoding: "utf8", mode: 384 });
@@ -8717,7 +8961,7 @@ async function readRules(file) {
8717
8961
  }
8718
8962
  }
8719
8963
  async function writeRules(file, rules) {
8720
- await mkdir9(dirname10(file), { recursive: true, mode: 448 });
8964
+ await mkdir9(dirname11(file), { recursive: true, mode: 448 });
8721
8965
  await writeFile7(file, JSON.stringify(rules, null, 2), { encoding: "utf8", mode: 384 });
8722
8966
  }
8723
8967
  var EvolveStore = class {
@@ -9339,10 +9583,10 @@ ${result.stderr.slice(-4e3)}` : ""}`;
9339
9583
  return USAGE;
9340
9584
  },
9341
9585
  toolDefinition() {
9342
- const inputSchema = z12.object({
9343
- suggestionId: z12.string().min(1).describe("Signal id from the evolve suggestions"),
9344
- implementation: z12.string().min(1).describe("Concise description of the fix to implement (plugin plan, or the guardrail rule text when kind is prompt_rule)"),
9345
- kind: z12.enum(["plugin", "prompt_rule"]).optional().describe(
9586
+ const inputSchema = z13.object({
9587
+ suggestionId: z13.string().min(1).describe("Signal id from the evolve suggestions"),
9588
+ implementation: z13.string().min(1).describe("Concise description of the fix to implement (plugin plan, or the guardrail rule text when kind is prompt_rule)"),
9589
+ kind: z13.enum(["plugin", "prompt_rule"]).optional().describe(
9346
9590
  "plugin (default): scaffold a fix plugin; prompt_rule: store a guardrail rule that is injected into future system prompts"
9347
9591
  )
9348
9592
  });
@@ -9408,8 +9652,8 @@ function buildLoopCyclePrompt(input) {
9408
9652
  }
9409
9653
 
9410
9654
  // src/loop/types.ts
9411
- import { z as z13 } from "zod";
9412
- var LoopStatusSchema = z13.enum([
9655
+ import { z as z14 } from "zod";
9656
+ var LoopStatusSchema = z14.enum([
9413
9657
  "running",
9414
9658
  "succeeded",
9415
9659
  "failed",
@@ -9419,65 +9663,65 @@ var LoopStatusSchema = z13.enum([
9419
9663
  "no_progress",
9420
9664
  "needs_human"
9421
9665
  ]);
9422
- var LoopApprovalSchema = z13.object({
9423
- dimension: z13.enum(["cycles", "tokens"]),
9424
- previousCheckpoint: z13.number().int().nonnegative(),
9425
- newCheckpoint: z13.number().int().positive(),
9426
- usage: z13.number().int().nonnegative(),
9427
- approvedAt: z13.string().datetime({ offset: true })
9666
+ var LoopApprovalSchema = z14.object({
9667
+ dimension: z14.enum(["cycles", "tokens"]),
9668
+ previousCheckpoint: z14.number().int().nonnegative(),
9669
+ newCheckpoint: z14.number().int().positive(),
9670
+ usage: z14.number().int().nonnegative(),
9671
+ approvedAt: z14.string().datetime({ offset: true })
9428
9672
  }).strict();
9429
- var LoopVerificationCommandSchema = z13.object({
9430
- command: z13.string().min(1),
9431
- args: z13.array(z13.string()),
9432
- exitCode: z13.number().int().nullable(),
9433
- stdout: z13.string(),
9434
- stderr: z13.string(),
9435
- truncated: z13.boolean()
9673
+ var LoopVerificationCommandSchema = z14.object({
9674
+ command: z14.string().min(1),
9675
+ args: z14.array(z14.string()),
9676
+ exitCode: z14.number().int().nullable(),
9677
+ stdout: z14.string(),
9678
+ stderr: z14.string(),
9679
+ truncated: z14.boolean()
9436
9680
  }).strict();
9437
- var LoopVerificationEvidenceSchema = z13.object({
9438
- passed: z13.boolean(),
9439
- commands: z13.array(LoopVerificationCommandSchema),
9440
- summary: z13.string()
9681
+ var LoopVerificationEvidenceSchema = z14.object({
9682
+ passed: z14.boolean(),
9683
+ commands: z14.array(LoopVerificationCommandSchema),
9684
+ summary: z14.string()
9441
9685
  }).strict();
9442
- var LoopCycleEvidenceSchema = z13.object({
9443
- cycle: z13.number().int().positive(),
9444
- startedAt: z13.string().datetime({ offset: true }),
9445
- completedAt: z13.string().datetime({ offset: true }),
9446
- inputTokens: z13.number().int().nonnegative(),
9447
- outputTokens: z13.number().int().nonnegative(),
9448
- workspaceFingerprint: z13.string(),
9686
+ var LoopCycleEvidenceSchema = z14.object({
9687
+ cycle: z14.number().int().positive(),
9688
+ startedAt: z14.string().datetime({ offset: true }),
9689
+ completedAt: z14.string().datetime({ offset: true }),
9690
+ inputTokens: z14.number().int().nonnegative(),
9691
+ outputTokens: z14.number().int().nonnegative(),
9692
+ workspaceFingerprint: z14.string(),
9449
9693
  verification: LoopVerificationEvidenceSchema
9450
9694
  }).strict();
9451
- var LoopStateSchema = z13.object({
9452
- version: z13.literal(1),
9453
- loopId: z13.string().regex(/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/),
9454
- goal: z13.string().trim().min(1),
9455
- workspace: z13.string().min(1),
9456
- createdAt: z13.string().datetime({ offset: true }),
9457
- updatedAt: z13.string().datetime({ offset: true }),
9695
+ var LoopStateSchema = z14.object({
9696
+ version: z14.literal(1),
9697
+ loopId: z14.string().regex(/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/),
9698
+ goal: z14.string().trim().min(1),
9699
+ workspace: z14.string().min(1),
9700
+ createdAt: z14.string().datetime({ offset: true }),
9701
+ updatedAt: z14.string().datetime({ offset: true }),
9458
9702
  status: LoopStatusSchema,
9459
- config: z13.object({
9460
- cycleStep: z13.number().int().positive(),
9461
- tokenStep: z13.number().int().positive(),
9462
- isolation: z13.literal("auto")
9703
+ config: z14.object({
9704
+ cycleStep: z14.number().int().positive(),
9705
+ tokenStep: z14.number().int().positive(),
9706
+ isolation: z14.literal("auto")
9463
9707
  }).strict(),
9464
- budget: z13.object({
9465
- cyclesUsed: z13.number().int().nonnegative(),
9466
- inputTokens: z13.number().int().nonnegative(),
9467
- outputTokens: z13.number().int().nonnegative(),
9468
- cycleCheckpoint: z13.number().int().positive(),
9469
- tokenCheckpoint: z13.number().int().positive(),
9470
- approvals: z13.array(LoopApprovalSchema)
9708
+ budget: z14.object({
9709
+ cyclesUsed: z14.number().int().nonnegative(),
9710
+ inputTokens: z14.number().int().nonnegative(),
9711
+ outputTokens: z14.number().int().nonnegative(),
9712
+ cycleCheckpoint: z14.number().int().positive(),
9713
+ tokenCheckpoint: z14.number().int().positive(),
9714
+ approvals: z14.array(LoopApprovalSchema)
9471
9715
  }).strict(),
9472
- cycles: z13.array(LoopCycleEvidenceSchema),
9473
- terminalReason: z13.string().optional()
9716
+ cycles: z14.array(LoopCycleEvidenceSchema),
9717
+ terminalReason: z14.string().optional()
9474
9718
  }).strict();
9475
- var LoopEventSchema = z13.object({
9476
- version: z13.literal(1),
9477
- type: z13.enum(["created", "cycle_started", "cycle_completed", "verification", "budget_approved", "terminal"]),
9478
- timestamp: z13.string().datetime({ offset: true }),
9479
- loopId: z13.string().regex(/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/),
9480
- payload: z13.record(z13.string(), z13.unknown())
9719
+ var LoopEventSchema = z14.object({
9720
+ version: z14.literal(1),
9721
+ type: z14.enum(["created", "cycle_started", "cycle_completed", "verification", "budget_approved", "terminal"]),
9722
+ timestamp: z14.string().datetime({ offset: true }),
9723
+ loopId: z14.string().regex(/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/),
9724
+ payload: z14.record(z14.string(), z14.unknown())
9481
9725
  }).strict();
9482
9726
 
9483
9727
  // src/loop/budget.ts
@@ -9793,15 +10037,15 @@ import { writeFile as writeFile9, mkdir as mkdir10 } from "fs/promises";
9793
10037
  import { join as join12 } from "path";
9794
10038
 
9795
10039
  // src/goal/types.ts
9796
- import { z as z14 } from "zod";
9797
- var GoalPhaseSchema = z14.enum([
10040
+ import { z as z15 } from "zod";
10041
+ var GoalPhaseSchema = z15.enum([
9798
10042
  "idle",
9799
10043
  "planning",
9800
10044
  "executing",
9801
10045
  "verifying",
9802
10046
  "complete"
9803
10047
  ]);
9804
- var GoalStatusSchema = z14.enum([
10048
+ var GoalStatusSchema = z15.enum([
9805
10049
  "active",
9806
10050
  "paused",
9807
10051
  "achieved",
@@ -9809,43 +10053,43 @@ var GoalStatusSchema = z14.enum([
9809
10053
  "blocked",
9810
10054
  "failed"
9811
10055
  ]);
9812
- var AcceptanceCriterionSchema = z14.object({
9813
- id: z14.number().int().positive(),
9814
- description: z14.string().min(1),
9815
- type: z14.enum(["gating", "evidence"])
10056
+ var AcceptanceCriterionSchema = z15.object({
10057
+ id: z15.number().int().positive(),
10058
+ description: z15.string().min(1),
10059
+ type: z15.enum(["gating", "evidence"])
9816
10060
  }).strict();
9817
- var PlanSchema = z14.object({
9818
- kind: z14.enum(["code-change", "analysis", "research"]),
9819
- criteria: z14.array(AcceptanceCriterionSchema).min(1).max(32),
9820
- verificationPlan: z14.string().min(1),
9821
- nonGoals: z14.array(z14.string()).max(16),
9822
- assumedScope: z14.array(z14.string()).max(16),
9823
- approach: z14.string().optional(),
9824
- checklist: z14.array(z14.string()).max(32).optional()
10061
+ var PlanSchema = z15.object({
10062
+ kind: z15.enum(["code-change", "analysis", "research"]),
10063
+ criteria: z15.array(AcceptanceCriterionSchema).min(1).max(32),
10064
+ verificationPlan: z15.string().min(1),
10065
+ nonGoals: z15.array(z15.string()).max(16),
10066
+ assumedScope: z15.array(z15.string()).max(16),
10067
+ approach: z15.string().optional(),
10068
+ checklist: z15.array(z15.string()).max(32).optional()
9825
10069
  }).strict();
9826
- var GapSchema = z14.object({
9827
- criterion: z14.string().min(1),
9828
- description: z14.string().min(1),
9829
- blocking: z14.enum(["model_fixable", "contradiction", "unverifiable"])
10070
+ var GapSchema = z15.object({
10071
+ criterion: z15.string().min(1),
10072
+ description: z15.string().min(1),
10073
+ blocking: z15.enum(["model_fixable", "contradiction", "unverifiable"])
9830
10074
  }).strict();
9831
- var VerdictSchema = z14.object({
9832
- refuted: z14.boolean(),
9833
- gaps: z14.array(GapSchema)
10075
+ var VerdictSchema = z15.object({
10076
+ refuted: z15.boolean(),
10077
+ gaps: z15.array(GapSchema)
9834
10078
  }).strict();
9835
- var GoalStateSchema = z14.object({
9836
- id: z14.string().regex(/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/),
9837
- objective: z14.string().min(1),
10079
+ var GoalStateSchema = z15.object({
10080
+ id: z15.string().regex(/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/),
10081
+ objective: z15.string().min(1),
9838
10082
  phase: GoalPhaseSchema,
9839
10083
  status: GoalStatusSchema,
9840
10084
  plan: PlanSchema.nullable(),
9841
- planPath: z14.string().nullable(),
9842
- verifyRounds: z14.number().int().min(0),
9843
- workerRounds: z14.number().int().min(0),
9844
- lastGaps: z14.array(GapSchema),
9845
- gapFingerprint: z14.string(),
9846
- stallStreak: z14.number().int().min(0),
9847
- createdAt: z14.string().datetime({ offset: true }),
9848
- updatedAt: z14.string().datetime({ offset: true })
10085
+ planPath: z15.string().nullable(),
10086
+ verifyRounds: z15.number().int().min(0),
10087
+ workerRounds: z15.number().int().min(0),
10088
+ lastGaps: z15.array(GapSchema),
10089
+ gapFingerprint: z15.string(),
10090
+ stallStreak: z15.number().int().min(0),
10091
+ createdAt: z15.string().datetime({ offset: true }),
10092
+ updatedAt: z15.string().datetime({ offset: true })
9849
10093
  }).strict();
9850
10094
 
9851
10095
  // src/goal/planner.ts
@@ -10406,7 +10650,7 @@ function formatPriorGaps(gaps) {
10406
10650
  import { constants } from "fs";
10407
10651
  import { randomUUID as randomUUID7 } from "crypto";
10408
10652
  import { lstat as lstat6, mkdir as mkdir11, open as open6, rename as rename4, rm as rm4 } from "fs/promises";
10409
- import { dirname as dirname11, join as join13, relative as relative9, resolve as resolve10, sep as sep8 } from "path";
10653
+ import { dirname as dirname12, join as join13, relative as relative9, resolve as resolve10, sep as sep8 } from "path";
10410
10654
  var DEFAULT_MAX_BYTES = 1024 * 1024;
10411
10655
  var GoalStore = class {
10412
10656
  #workspace;
@@ -10419,7 +10663,7 @@ var GoalStore = class {
10419
10663
  }
10420
10664
  async save(input) {
10421
10665
  const state = GoalStateSchema.parse(input);
10422
- await assertNoSymlink(this.#workspace, dirname11(this.#root));
10666
+ await assertNoSymlink(this.#workspace, dirname12(this.#root));
10423
10667
  await mkdir11(this.#root, { recursive: true, mode: 448 });
10424
10668
  await assertNoSymlink(this.#workspace, this.#root);
10425
10669
  const target = join13(this.#root, `${state.id}.json`);
@@ -10453,7 +10697,7 @@ async function assertNoSymlink(root, target) {
10453
10697
  const chain = [];
10454
10698
  while (cursor !== stop) {
10455
10699
  chain.push(cursor);
10456
- cursor = dirname11(cursor);
10700
+ cursor = dirname12(cursor);
10457
10701
  }
10458
10702
  for (const path of chain.reverse()) {
10459
10703
  try {
@@ -10539,8 +10783,8 @@ async function ensureWorktreeDirectoryIgnored(root) {
10539
10783
 
10540
10784
  // src/loop/store.ts
10541
10785
  import { constants as constants2 } from "fs";
10542
- import { lstat as lstat7, mkdir as mkdir13, open as open7, readFile as readFile10, realpath as realpath4, rename as rename5, rm as rm5, stat as stat5 } from "fs/promises";
10543
- import { dirname as dirname12, join as join15, relative as relative10, resolve as resolve12, sep as sep9 } from "path";
10786
+ import { lstat as lstat7, mkdir as mkdir13, open as open7, readFile as readFile10, realpath as realpath5, rename as rename5, rm as rm5, stat as stat5 } from "fs/promises";
10787
+ import { dirname as dirname13, join as join15, relative as relative10, resolve as resolve12, sep as sep9 } from "path";
10544
10788
  import { randomUUID as randomUUID8 } from "crypto";
10545
10789
  var LOOP_ID = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
10546
10790
  var DEFAULT_MAX_BYTES2 = 5 * 1024 * 1024;
@@ -10622,7 +10866,7 @@ var LoopStore = class {
10622
10866
  }
10623
10867
  async #prepare(loopId) {
10624
10868
  validateId(loopId);
10625
- await assertNoSymlink2(this.#workspace, dirname12(this.#root));
10869
+ await assertNoSymlink2(this.#workspace, dirname13(this.#root));
10626
10870
  await mkdir13(this.#root, { recursive: true, mode: 448 });
10627
10871
  await assertNoSymlink2(this.#workspace, this.#root);
10628
10872
  const directory = join15(this.#root, loopId);
@@ -10655,7 +10899,7 @@ async function assertNoSymlink2(root, target) {
10655
10899
  const chain = [];
10656
10900
  while (cursor !== stop) {
10657
10901
  chain.push(cursor);
10658
- cursor = dirname12(cursor);
10902
+ cursor = dirname13(cursor);
10659
10903
  }
10660
10904
  for (const path of chain.reverse()) {
10661
10905
  try {
@@ -10671,7 +10915,7 @@ function isWithin2(root, path) {
10671
10915
  }
10672
10916
  async function canonical(path) {
10673
10917
  try {
10674
- return await realpath4(resolve12(path));
10918
+ return await realpath5(resolve12(path));
10675
10919
  } catch {
10676
10920
  return resolve12(path);
10677
10921
  }
@@ -10687,19 +10931,19 @@ import { join as join16 } from "path";
10687
10931
  // src/tools/shell.ts
10688
10932
  import { spawn as spawn6, spawnSync } from "child_process";
10689
10933
  import { isAbsolute as isAbsolute6, relative as relative11, resolve as resolve13, sep as sep10 } from "path";
10690
- import { z as z16 } from "zod";
10934
+ import { z as z17 } from "zod";
10691
10935
 
10692
10936
  // src/tools/jobs.ts
10693
- import { z as z15 } from "zod";
10694
- var JobId = z15.string().regex(/^job-[a-f0-9-]+$/);
10695
- var ReadInput = z15.object({ id: JobId, cursor: z15.coerce.number().int().min(0).optional() });
10696
- var IdInput = z15.object({ id: JobId });
10937
+ import { z as z16 } from "zod";
10938
+ var JobId = z16.string().regex(/^job-[a-f0-9-]+$/);
10939
+ var ReadInput = z16.object({ id: JobId, cursor: z16.coerce.number().int().min(0).optional() });
10940
+ var IdInput = z16.object({ id: JobId });
10697
10941
  function createJobTools(registry) {
10698
10942
  const tools = [
10699
10943
  {
10700
10944
  name: "JobList",
10701
10945
  description: "List background jobs owned by this agent",
10702
- inputSchema: z15.object({}),
10946
+ inputSchema: z16.object({}),
10703
10947
  paths: () => [],
10704
10948
  execute: async (_input, _signal, context) => registry.list(owner(context)),
10705
10949
  presentResult: (output) => jobListPresentation(output)
@@ -10774,14 +11018,14 @@ var ELLIPSIS = "\u2026";
10774
11018
  var TERMINATION_GRACE_MS = 250;
10775
11019
  var TERMINATION_FAILURE_MS = 5e3;
10776
11020
  var STREAM_CLOSE_GRACE_MS = 500;
10777
- var ShellInput = z16.object({
10778
- command: z16.string().min(1),
10779
- args: z16.array(z16.string()),
10780
- cwd: z16.string().min(1).nullable().optional(),
10781
- timeoutMs: z16.coerce.number().int().positive().max(864e5).nullable().optional(),
11021
+ var ShellInput = z17.object({
11022
+ command: z17.string().min(1),
11023
+ args: z17.array(z17.string()),
11024
+ cwd: z17.string().min(1).nullable().optional(),
11025
+ timeoutMs: z17.coerce.number().int().positive().max(864e5).nullable().optional(),
10782
11026
  // Accepts booleans and their string forms (weak-typed models emit "true");
10783
11027
  // kept transform-free so the schema converts to JSON Schema for providers.
10784
- background: z16.union([z16.boolean(), z16.string().refine((value) => value === "true" || value === "false")]).optional()
11028
+ background: z17.union([z17.boolean(), z17.string().refine((value) => value === "true" || value === "false")]).optional()
10785
11029
  });
10786
11030
  function normalizeShellCommand(input) {
10787
11031
  const { command, args } = input;
@@ -11950,7 +12194,7 @@ var ModelRegistry = class {
11950
12194
 
11951
12195
  // src/mcp/client.ts
11952
12196
  import { createHash as createHash7 } from "crypto";
11953
- import { z as z17 } from "zod";
12197
+ import { z as z18 } from "zod";
11954
12198
  var McpManager = class {
11955
12199
  #workspace;
11956
12200
  #clientFactory;
@@ -12086,7 +12330,7 @@ async function listAllTools(client) {
12086
12330
  function createMcpToolDefinition(serverName, timeoutMs, client, remote) {
12087
12331
  if (remote.name.length === 0) throw new Error("MCP tool name must not be empty");
12088
12332
  if (!isRecord3(remote.inputSchema)) throw new Error(`MCP tool "${remote.name}" has no JSON object input schema`);
12089
- const inputSchema = z17.fromJSONSchema(
12333
+ const inputSchema = z18.fromJSONSchema(
12090
12334
  remote.inputSchema
12091
12335
  );
12092
12336
  return {
@@ -12496,7 +12740,7 @@ function escapeHtml(text) {
12496
12740
  }
12497
12741
 
12498
12742
  // src/auth/store.ts
12499
- import { dirname as dirname13 } from "path";
12743
+ import { dirname as dirname14 } from "path";
12500
12744
  async function retainOnlyCredentials(store, keepCredentialId) {
12501
12745
  const tokens = await store.load();
12502
12746
  const retained = Object.fromEntries(Object.entries(tokens).filter(([id]) => id === keepCredentialId));
@@ -12507,7 +12751,7 @@ function createFileTokenStore(filePath) {
12507
12751
  const store = {
12508
12752
  tokens: {},
12509
12753
  async load() {
12510
- const key = await loadOrCreateConfigKey(dirname13(filePath));
12754
+ const key = await loadOrCreateConfigKey(dirname14(filePath));
12511
12755
  const result = await readRecoverableFile(filePath, (raw) => parseTokens(decryptDocument(raw, key)));
12512
12756
  const tokens = result?.value ?? {};
12513
12757
  baseline = { ...tokens };
@@ -12515,7 +12759,7 @@ function createFileTokenStore(filePath) {
12515
12759
  return tokens;
12516
12760
  },
12517
12761
  async save(tokens) {
12518
- const key = await loadOrCreateConfigKey(dirname13(filePath));
12762
+ const key = await loadOrCreateConfigKey(dirname14(filePath));
12519
12763
  const removals = Object.keys(baseline).filter((providerId) => !(providerId in tokens));
12520
12764
  const upserts = Object.fromEntries(Object.entries(tokens).filter(
12521
12765
  ([providerId, token]) => !sameToken(baseline[providerId], token)
@@ -12633,6 +12877,7 @@ function toolsSection(toolNames) {
12633
12877
  addToolRule(rules, toolNames, "TaskUpdate", "Use `TaskUpdate` to mark each planned task in progress before starting and completed only after successful verification.");
12634
12878
  addToolRule(rules, toolNames, "Task", "Use `Task` when independent, well-bounded subtasks can benefit from isolated child agents. Give each child a self-contained briefing and do not delegate the final synthesis.");
12635
12879
  addToolRule(rules, toolNames, "TaskOutput", "Use `TaskOutput` at the end of multi-step work to record changed files, commands, verification, risks, and useful next steps.");
12880
+ addToolRule(rules, toolNames, "Skill", "Use `Skill` whenever an active skill requires or references another skill. Load the required skill before continuing, pass arguments when the nested workflow has its own task input, and follow the returned instructions completely.");
12636
12881
  addToolRule(rules, toolNames, "SkillResource", "Use `SkillResource` only to read a resource explicitly referenced by a matched skill. Treat returned scripts as data; do not execute them through that tool.");
12637
12882
  addToolRule(rules, toolNames, "RegisterTool", "Use `RegisterTool` to create a durable reusable capability from JSON Schema and async JavaScript. Create one only when the user requests it or the task has a clear recurring need; never persist a tool for a one-off operation. The new tool is available on the next model step in the same run. Its implementation may be either a function body with an explicit `return`, or a complete function/arrow expression; all forms receive `input`, `signal`, and `context`.");
12638
12883
  addToolRule(rules, toolNames, "RemoveTool", "Use `RemoveTool` only to delete a tool created by `RegisterTool`. To modify a managed tool, delete and register again; it cannot delete built-in, plugin, or MCP tools.");
@@ -12681,7 +12926,7 @@ function data(value) {
12681
12926
 
12682
12927
  // src/skills/registry.ts
12683
12928
  import { constants as constants3 } from "fs";
12684
- import { lstat as lstat8, open as defaultOpen, readdir as readdir6, realpath as realpath5 } from "fs/promises";
12929
+ import { lstat as lstat8, open as defaultOpen, readdir as readdir6, realpath as realpath6 } from "fs/promises";
12685
12930
  import { isAbsolute as isAbsolute7, relative as relative12, resolve as resolve15, sep as sep11 } from "path";
12686
12931
  import { marked } from "marked";
12687
12932
  import { parseDocument } from "yaml";
@@ -12848,7 +13093,7 @@ var SkillRegistry = class {
12848
13093
  try {
12849
13094
  const rootInfo = await lstat8(root);
12850
13095
  if (rootInfo.isSymbolicLink() || !rootInfo.isDirectory()) throw new Error("Skill root must be a real directory");
12851
- physicalRoot = await realpath5(root);
13096
+ physicalRoot = await realpath6(root);
12852
13097
  entries = await readdir6(root, { withFileTypes: true });
12853
13098
  } catch (error) {
12854
13099
  if (isMissing2(error)) continue;
@@ -12861,7 +13106,7 @@ var SkillRegistry = class {
12861
13106
  try {
12862
13107
  if (entry2.isSymbolicLink()) throw new Error("Symlinked skill directories are not allowed");
12863
13108
  if (!entry2.isDirectory()) continue;
12864
- const physicalSkillRoot = await realpath5(skillRoot);
13109
+ const physicalSkillRoot = await realpath6(skillRoot);
12865
13110
  if (!isWithin3(physicalRoot, physicalSkillRoot)) throw new Error("Skill directory escapes its registry root");
12866
13111
  const skillFile = resolve15(skillRoot, "SKILL.md");
12867
13112
  const parsed = await readFrontmatterFile(
@@ -13003,7 +13248,7 @@ async function openVerifiedFile(path, root, label, opener, expected) {
13003
13248
  const initial = await lstat8(path, { bigint: true });
13004
13249
  if (initial.isSymbolicLink()) throw new Error(`${label} symlinks are not allowed`);
13005
13250
  assertRegular(initial, label);
13006
- const canonical3 = await realpath5(path);
13251
+ const canonical3 = await realpath6(path);
13007
13252
  if (!isWithin3(root, canonical3)) throw new Error(`${label} escapes the skill root`);
13008
13253
  const noFollow = typeof constants3.O_NOFOLLOW === "number" ? constants3.O_NOFOLLOW : 0;
13009
13254
  const handle = await opener(canonical3, constants3.O_RDONLY | noFollow);
@@ -13112,11 +13357,97 @@ function score(metadata, query) {
13112
13357
  }
13113
13358
 
13114
13359
  // src/skills/tool.ts
13115
- import { z as z18 } from "zod";
13116
- var SkillResourceInput = z18.object({
13117
- skill: z18.string().min(1),
13118
- reference: z18.string().min(1)
13360
+ import { z as z19 } from "zod";
13361
+
13362
+ // src/skills/arguments.ts
13363
+ function expandSkillArguments(body, argumentsText) {
13364
+ const values = splitSkillArguments(argumentsText);
13365
+ const hasPlaceholder = /\$ARGUMENTS(?:\[\d+\])?|\$\d+/.test(body);
13366
+ let expanded = body.replace(/\$ARGUMENTS\[(\d+)\]/g, (_match, index) => values[Number(index)] ?? "");
13367
+ expanded = expanded.replace(/\$(\d+)/g, (_match, index) => values[Number(index)] ?? "");
13368
+ expanded = expanded.replace(/\$ARGUMENTS/g, argumentsText);
13369
+ if (!hasPlaceholder && argumentsText.trim() !== "") {
13370
+ expanded = `${expanded.trimEnd()}
13371
+
13372
+ ARGUMENTS: ${argumentsText}`;
13373
+ }
13374
+ return expanded;
13375
+ }
13376
+ function splitSkillArguments(input) {
13377
+ const result = [];
13378
+ let current = "";
13379
+ let quote;
13380
+ let started = false;
13381
+ for (let index = 0; index < input.length; index += 1) {
13382
+ const character = input[index] ?? "";
13383
+ const next = input[index + 1];
13384
+ if (character === "\\" && quote !== "'" && next !== void 0 && (/\s/u.test(next) || next === "\\" || next === '"' || quote === void 0 && next === "'")) {
13385
+ current += next;
13386
+ index += 1;
13387
+ started = true;
13388
+ continue;
13389
+ }
13390
+ if (quote !== void 0) {
13391
+ if (character === quote) quote = void 0;
13392
+ else current += character;
13393
+ started = true;
13394
+ continue;
13395
+ }
13396
+ if (character === "'" || character === '"') {
13397
+ quote = character;
13398
+ started = true;
13399
+ continue;
13400
+ }
13401
+ if (/\s/u.test(character)) {
13402
+ if (started) {
13403
+ result.push(current);
13404
+ current = "";
13405
+ started = false;
13406
+ }
13407
+ continue;
13408
+ }
13409
+ current += character;
13410
+ started = true;
13411
+ }
13412
+ if (started) result.push(current);
13413
+ return result;
13414
+ }
13415
+
13416
+ // src/skills/tool.ts
13417
+ var SkillInput = z19.object({
13418
+ skill: z19.string().min(1),
13419
+ arguments: z19.string().optional()
13119
13420
  }).strict();
13421
+ var SkillResourceInput = z19.object({
13422
+ skill: z19.string().min(1),
13423
+ reference: z19.string().min(1)
13424
+ }).strict();
13425
+ function createSkillTool(registry) {
13426
+ return {
13427
+ name: "Skill",
13428
+ description: "Load another discovered skill by name so composable workflows can follow its complete instructions; optional arguments use Claude-compatible $ARGUMENTS substitution",
13429
+ inputSchema: SkillInput,
13430
+ readOnly: true,
13431
+ paths: () => [],
13432
+ summarize: ({ skill }) => skill,
13433
+ renderForModel: (output) => {
13434
+ const value = output;
13435
+ return `Matched skill: ${value.skill}
13436
+ ${value.content}`;
13437
+ },
13438
+ execute: async (input, signal) => {
13439
+ signal.throwIfAborted();
13440
+ const discovered = await registry.discover();
13441
+ const requested = input.skill.trim();
13442
+ const alias = requested.includes(":") ? requested.slice(requested.lastIndexOf(":") + 1) : requested;
13443
+ const skill = discovered.find((candidate) => candidate.name === requested) ?? discovered.find((candidate) => candidate.name === alias);
13444
+ if (skill === void 0) throw new Error(`Unknown skill: ${input.skill}`);
13445
+ const content = expandSkillArguments(await registry.loadBody(skill), input.arguments ?? "");
13446
+ signal.throwIfAborted();
13447
+ return { skill: skill.name, content };
13448
+ }
13449
+ };
13450
+ }
13120
13451
  function createSkillResourceTool(registry) {
13121
13452
  return {
13122
13453
  name: "SkillResource",
@@ -13142,97 +13473,97 @@ function createSkillResourceTool(registry) {
13142
13473
 
13143
13474
  // src/session/store.ts
13144
13475
  import { constants as constants4 } from "fs";
13145
- import { lstat as lstat9, mkdir as mkdir14, open as open8, readFile as readFile14, readdir as readdir7, realpath as realpath6, rename as rename6, rm as rm6, stat as stat6 } from "fs/promises";
13146
- import { basename as basename3, dirname as dirname14, join as join17, relative as relative13, resolve as resolve16, sep as sep12 } from "path";
13476
+ import { lstat as lstat9, mkdir as mkdir14, open as open8, readFile as readFile14, readdir as readdir7, realpath as realpath7, rename as rename6, rm as rm6, stat as stat6 } from "fs/promises";
13477
+ import { basename as basename3, dirname as dirname15, join as join17, relative as relative13, resolve as resolve16, sep as sep12 } from "path";
13147
13478
  import { randomUUID as randomUUID9 } from "crypto";
13148
- import { z as z19 } from "zod";
13479
+ import { z as z20 } from "zod";
13149
13480
  var SESSION_VERSION = 3;
13150
13481
  var DEFAULT_MAX_SESSION_BYTES = 5 * 1024 * 1024;
13151
- var SessionIdSchema = z19.string().regex(/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/, "Invalid session id");
13152
- var IsoDateSchema = z19.string().datetime({ offset: true });
13153
- var ToolCallSchema = z19.object({
13154
- id: z19.string().min(1).max(256),
13155
- name: z19.string().min(1).max(256),
13156
- input: z19.unknown()
13482
+ var SessionIdSchema = z20.string().regex(/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/, "Invalid session id");
13483
+ var IsoDateSchema = z20.string().datetime({ offset: true });
13484
+ var ToolCallSchema = z20.object({
13485
+ id: z20.string().min(1).max(256),
13486
+ name: z20.string().min(1).max(256),
13487
+ input: z20.unknown()
13157
13488
  }).strict();
13158
- var TextContentBlockSchema = z19.object({
13159
- type: z19.literal("text"),
13160
- text: z19.string().max(DEFAULT_MAX_SESSION_BYTES)
13489
+ var TextContentBlockSchema = z20.object({
13490
+ type: z20.literal("text"),
13491
+ text: z20.string().max(DEFAULT_MAX_SESSION_BYTES)
13161
13492
  }).strict();
13162
- var ImageContentBlockSchema = z19.object({
13163
- type: z19.literal("image"),
13164
- source: z19.object({ type: z19.literal("file"), path: z19.string().min(1).max(32768) }).strict(),
13165
- mediaType: z19.enum(["image/png", "image/jpeg", "image/webp"]),
13166
- sha256: z19.string().regex(/^[a-f0-9]{64}$/),
13167
- bytes: z19.number().int().positive().max(20 * 1024 * 1024),
13168
- name: z19.string().min(1).max(255).optional()
13493
+ var ImageContentBlockSchema = z20.object({
13494
+ type: z20.literal("image"),
13495
+ source: z20.object({ type: z20.literal("file"), path: z20.string().min(1).max(32768) }).strict(),
13496
+ mediaType: z20.enum(["image/png", "image/jpeg", "image/webp"]),
13497
+ sha256: z20.string().regex(/^[a-f0-9]{64}$/),
13498
+ bytes: z20.number().int().positive().max(20 * 1024 * 1024),
13499
+ name: z20.string().min(1).max(255).optional()
13169
13500
  }).strict();
13170
- var UserContentSchema = z19.union([
13171
- z19.string().max(DEFAULT_MAX_SESSION_BYTES),
13172
- z19.array(z19.discriminatedUnion("type", [TextContentBlockSchema, ImageContentBlockSchema])).min(1).max(100)
13501
+ var UserContentSchema = z20.union([
13502
+ z20.string().max(DEFAULT_MAX_SESSION_BYTES),
13503
+ z20.array(z20.discriminatedUnion("type", [TextContentBlockSchema, ImageContentBlockSchema])).min(1).max(100)
13173
13504
  ]);
13174
13505
  var MessageMetadataShape = {
13175
- toolCallId: z19.string().min(1).max(256).optional(),
13176
- toolCalls: z19.array(ToolCallSchema).max(1e3).optional()
13506
+ toolCallId: z20.string().min(1).max(256).optional(),
13507
+ toolCalls: z20.array(ToolCallSchema).max(1e3).optional()
13177
13508
  };
13178
- var MessageSchema = z19.discriminatedUnion("role", [
13179
- z19.object({ role: z19.literal("user"), content: UserContentSchema, ...MessageMetadataShape }).strict(),
13180
- z19.object({ role: z19.literal("assistant"), content: z19.string().max(DEFAULT_MAX_SESSION_BYTES), ...MessageMetadataShape }).strict(),
13181
- z19.object({ role: z19.literal("tool"), content: z19.string().max(DEFAULT_MAX_SESSION_BYTES), ...MessageMetadataShape }).strict()
13509
+ var MessageSchema = z20.discriminatedUnion("role", [
13510
+ z20.object({ role: z20.literal("user"), content: UserContentSchema, ...MessageMetadataShape }).strict(),
13511
+ z20.object({ role: z20.literal("assistant"), content: z20.string().max(DEFAULT_MAX_SESSION_BYTES), ...MessageMetadataShape }).strict(),
13512
+ z20.object({ role: z20.literal("tool"), content: z20.string().max(DEFAULT_MAX_SESSION_BYTES), ...MessageMetadataShape }).strict()
13182
13513
  ]);
13183
- var LegacySummarySchema = z19.object({ role: z19.literal("system"), content: z19.string().max(DEFAULT_MAX_SESSION_BYTES) }).strict();
13184
- var CompactBoundarySchema = z19.object({
13185
- summary: z19.string().min(1).max(DEFAULT_MAX_SESSION_BYTES),
13514
+ var LegacySummarySchema = z20.object({ role: z20.literal("system"), content: z20.string().max(DEFAULT_MAX_SESSION_BYTES) }).strict();
13515
+ var CompactBoundarySchema = z20.object({
13516
+ summary: z20.string().min(1).max(DEFAULT_MAX_SESSION_BYTES),
13186
13517
  compactedAt: IsoDateSchema
13187
13518
  }).strict();
13188
- var StateSchema = z19.enum(["pending", "running", "completed", "failed", "blocked", "cancelled"]);
13189
- var MemoryLifecycleSchema = z19.object({
13190
- status: z19.enum(["active", "completed", "abandoned"]),
13191
- taskId: z19.string().regex(/^memory-[A-Za-z0-9._-]{1,120}$/).optional(),
13192
- messageStart: z19.number().int().min(0).max(5e4).optional(),
13519
+ var StateSchema = z20.enum(["pending", "running", "completed", "failed", "blocked", "cancelled"]);
13520
+ var MemoryLifecycleSchema = z20.object({
13521
+ status: z20.enum(["active", "completed", "abandoned"]),
13522
+ taskId: z20.string().regex(/^memory-[A-Za-z0-9._-]{1,120}$/).optional(),
13523
+ messageStart: z20.number().int().min(0).max(5e4).optional(),
13193
13524
  finalizedAt: IsoDateSchema.optional(),
13194
- transcriptHash: z19.string().regex(/^[a-f0-9]{64}$/).optional()
13525
+ transcriptHash: z20.string().regex(/^[a-f0-9]{64}$/).optional()
13195
13526
  }).strict();
13196
- var SessionBaseSchema = z19.object({
13527
+ var SessionBaseSchema = z20.object({
13197
13528
  sessionId: SessionIdSchema,
13198
13529
  createdAt: IsoDateSchema,
13199
13530
  updatedAt: IsoDateSchema,
13200
- workspace: z19.object({ path: z19.string().min(1).max(32768) }).strict(),
13201
- tasks: z19.object({
13531
+ workspace: z20.object({ path: z20.string().min(1).max(32768) }).strict(),
13532
+ tasks: z20.object({
13202
13533
  plan: TaskPlanSchema.optional(),
13203
13534
  graph: TaskGraphSchema.optional(),
13204
- states: z19.record(z19.string(), StateSchema),
13205
- results: z19.record(z19.string(), SubagentResultSchema)
13535
+ states: z20.record(z20.string(), StateSchema),
13536
+ results: z20.record(z20.string(), SubagentResultSchema)
13206
13537
  }).strict(),
13207
- models: z19.object({ main: z19.string().min(1).max(1024), subagent: z19.string().min(1).max(1024) }).strict(),
13538
+ models: z20.object({ main: z20.string().min(1).max(1024), subagent: z20.string().min(1).max(1024) }).strict(),
13208
13539
  permissionMode: PermissionModeSchema,
13209
13540
  memory: MemoryLifecycleSchema.optional()
13210
13541
  }).strict();
13211
13542
  var SessionDocumentV1Schema = SessionBaseSchema.extend({
13212
- version: z19.literal(1),
13213
- conversation: z19.object({
13543
+ version: z20.literal(1),
13544
+ conversation: z20.object({
13214
13545
  summary: LegacySummarySchema.optional(),
13215
- messages: z19.array(MessageSchema).max(5e4)
13546
+ messages: z20.array(MessageSchema).max(5e4)
13216
13547
  }).strict()
13217
13548
  }).strict();
13218
- var ConversationSchema = z19.object({
13549
+ var ConversationSchema = z20.object({
13219
13550
  compact: CompactBoundarySchema.optional(),
13220
- messages: z19.array(MessageSchema).max(5e4)
13551
+ messages: z20.array(MessageSchema).max(5e4)
13221
13552
  }).strict();
13222
13553
  var SessionDocumentV2Schema = SessionBaseSchema.extend({
13223
- version: z19.literal(2),
13554
+ version: z20.literal(2),
13224
13555
  conversation: ConversationSchema
13225
13556
  }).strict();
13226
- var TranscriptStateSchema = z19.custom(isTranscriptState, "Invalid transcript state");
13227
- var TimelineSchema = z19.object({
13228
- version: z19.literal(1),
13557
+ var TranscriptStateSchema = z20.custom(isTranscriptState, "Invalid transcript state");
13558
+ var TimelineSchema = z20.object({
13559
+ version: z20.literal(1),
13229
13560
  state: TranscriptStateSchema
13230
13561
  }).strict();
13231
13562
  var SessionDocumentSchema = SessionBaseSchema.extend({
13232
- version: z19.literal(SESSION_VERSION),
13233
- conversation: z19.object({
13563
+ version: z20.literal(SESSION_VERSION),
13564
+ conversation: z20.object({
13234
13565
  compact: CompactBoundarySchema.optional(),
13235
- messages: z19.array(MessageSchema).max(5e4)
13566
+ messages: z20.array(MessageSchema).max(5e4)
13236
13567
  }).strict(),
13237
13568
  timeline: TimelineSchema
13238
13569
  }).strict();
@@ -13408,14 +13739,14 @@ var SessionStore = class {
13408
13739
  }
13409
13740
  }
13410
13741
  async #prepareDirectory() {
13411
- await assertNoSymlink3(this.#workspace, dirname14(this.#sessions));
13742
+ await assertNoSymlink3(this.#workspace, dirname15(this.#sessions));
13412
13743
  await mkdir14(this.#sessions, { recursive: true, mode: 448 });
13413
13744
  await this.#assertSafeExistingDirectory();
13414
13745
  }
13415
13746
  async #assertSafeExistingDirectory() {
13416
13747
  await assertNoSymlink3(this.#workspace, this.#sessions);
13417
- const canonicalRoot = await realpath6(this.#workspace);
13418
- const canonicalSessions = await realpath6(this.#sessions);
13748
+ const canonicalRoot = await realpath7(this.#workspace);
13749
+ const canonicalSessions = await realpath7(this.#sessions);
13419
13750
  if (!isWithin4(canonicalRoot, canonicalSessions)) throw new Error("Session directory escapes the workspace");
13420
13751
  }
13421
13752
  async #quarantine(path) {
@@ -13572,7 +13903,7 @@ async function assertNoSymlink3(root, target) {
13572
13903
  const chain = [];
13573
13904
  while (cursor !== stop) {
13574
13905
  chain.push(cursor);
13575
- cursor = dirname14(cursor);
13906
+ cursor = dirname15(cursor);
13576
13907
  }
13577
13908
  for (const path of chain.reverse()) {
13578
13909
  try {
@@ -13588,7 +13919,7 @@ function isWithin4(root, path) {
13588
13919
  }
13589
13920
  async function canonical2(path) {
13590
13921
  try {
13591
- return await realpath6(resolve16(path));
13922
+ return await realpath7(resolve16(path));
13592
13923
  } catch {
13593
13924
  return resolve16(path);
13594
13925
  }
@@ -13617,45 +13948,45 @@ function sanitize2(input, seen = /* @__PURE__ */ new WeakSet()) {
13617
13948
  // src/sleep/organizer.ts
13618
13949
  import { constants as constants5 } from "fs";
13619
13950
  import { randomUUID as randomUUID10 } from "crypto";
13620
- import { lstat as lstat10, mkdir as mkdir15, open as open9, readdir as readdir8, realpath as realpath7, rename as rename7, rm as rm7 } from "fs/promises";
13951
+ import { lstat as lstat10, mkdir as mkdir15, open as open9, readdir as readdir8, realpath as realpath8, rename as rename7, rm as rm7 } from "fs/promises";
13621
13952
  import { isAbsolute as isAbsolute8, join as join18, relative as relative14, resolve as resolve17, sep as sep13 } from "path";
13622
- import { z as z20 } from "zod";
13623
- var DateKeySchema = z20.string().regex(/^\d{4}-\d{2}-\d{2}$/);
13624
- var ReviewSchema = z20.object({
13625
- title: z20.string().min(1).max(120),
13626
- taskSummary: z20.array(z20.string().min(1)).min(1).max(20),
13627
- executionReflection: z20.array(z20.string().min(1)).min(1).max(20),
13628
- decisionsAndLearnings: z20.array(z20.string().min(1)).max(20),
13629
- openQuestionsAndRisks: z20.array(z20.string().min(1)).max(20),
13630
- tomorrowPlan: z20.array(z20.string().min(1)).min(1).max(20),
13631
- toolUsage: z20.object({
13632
- totalCalls: z20.number().int().min(0),
13633
- shell: z20.number().int().min(0),
13634
- fileRead: z20.number().int().min(0),
13635
- fileWrite: z20.number().int().min(0),
13636
- search: z20.number().int().min(0),
13637
- lsp: z20.number().int().min(0),
13638
- subagent: z20.number().int().min(0),
13639
- other: z20.number().int().min(0)
13953
+ import { z as z21 } from "zod";
13954
+ var DateKeySchema = z21.string().regex(/^\d{4}-\d{2}-\d{2}$/);
13955
+ var ReviewSchema = z21.object({
13956
+ title: z21.string().min(1).max(120),
13957
+ taskSummary: z21.array(z21.string().min(1)).min(1).max(20),
13958
+ executionReflection: z21.array(z21.string().min(1)).min(1).max(20),
13959
+ decisionsAndLearnings: z21.array(z21.string().min(1)).max(20),
13960
+ openQuestionsAndRisks: z21.array(z21.string().min(1)).max(20),
13961
+ tomorrowPlan: z21.array(z21.string().min(1)).min(1).max(20),
13962
+ toolUsage: z21.object({
13963
+ totalCalls: z21.number().int().min(0),
13964
+ shell: z21.number().int().min(0),
13965
+ fileRead: z21.number().int().min(0),
13966
+ fileWrite: z21.number().int().min(0),
13967
+ search: z21.number().int().min(0),
13968
+ lsp: z21.number().int().min(0),
13969
+ subagent: z21.number().int().min(0),
13970
+ other: z21.number().int().min(0)
13640
13971
  }).strict(),
13641
- tokenEstimate: z20.object({
13642
- estimatedInput: z20.number().int().min(0),
13643
- estimatedOutput: z20.number().int().min(0),
13644
- notes: z20.string().max(200)
13972
+ tokenEstimate: z21.object({
13973
+ estimatedInput: z21.number().int().min(0),
13974
+ estimatedOutput: z21.number().int().min(0),
13975
+ notes: z21.string().max(200)
13645
13976
  }).strict(),
13646
- humanIntervention: z20.object({
13647
- approvalRequests: z20.number().int().min(0),
13648
- questionsAsked: z20.number().int().min(0),
13649
- summary: z20.string().max(300)
13977
+ humanIntervention: z21.object({
13978
+ approvalRequests: z21.number().int().min(0),
13979
+ questionsAsked: z21.number().int().min(0),
13980
+ summary: z21.string().max(300)
13650
13981
  }).strict(),
13651
- qualityIndicators: z20.object({
13652
- hallucinationAlerts: z20.array(z20.string().min(1)).max(10),
13653
- failuresAndRetries: z20.array(z20.string().min(1)).max(10),
13654
- codeChangeSummary: z20.string().max(500),
13655
- overallAssessment: z20.string().max(200)
13982
+ qualityIndicators: z21.object({
13983
+ hallucinationAlerts: z21.array(z21.string().min(1)).max(10),
13984
+ failuresAndRetries: z21.array(z21.string().min(1)).max(10),
13985
+ codeChangeSummary: z21.string().max(500),
13986
+ overallAssessment: z21.string().max(200)
13656
13987
  }).strict(),
13657
- knowledgeDeposits: z20.object({
13658
- worthRemembering: z20.array(z20.string().min(1)).max(10)
13988
+ knowledgeDeposits: z21.object({
13989
+ worthRemembering: z21.array(z21.string().min(1)).max(10)
13659
13990
  }).strict()
13660
13991
  }).strict();
13661
13992
  function localDateKey(date) {
@@ -13764,8 +14095,8 @@ Previous output was invalid. Repair it and return strict JSON only.`;
13764
14095
  await mkdir15(flavorDirectory, { recursive: true, mode: 448 });
13765
14096
  await assertNotSymlink(this.#sleepDirectory);
13766
14097
  await mkdir15(this.#sleepDirectory, { recursive: true, mode: 448 });
13767
- const root = await realpath7(this.#workspace);
13768
- const target = await realpath7(this.#sleepDirectory);
14098
+ const root = await realpath8(this.#workspace);
14099
+ const target = await realpath8(this.#sleepDirectory);
13769
14100
  if (!isWithin5(root, target)) throw new Error("Sleep directory escapes the workspace");
13770
14101
  }
13771
14102
  async #hasReport(date) {
@@ -14147,10 +14478,10 @@ function computeSessionStats(documents) {
14147
14478
 
14148
14479
  // src/tools/files.ts
14149
14480
  import { constants as constants6 } from "fs";
14150
- import { mkdir as mkdir16, open as open10, readFile as readFile15, realpath as realpath8, rename as rename8, rm as rm8, stat as stat7 } from "fs/promises";
14151
- import { dirname as dirname15, isAbsolute as isAbsolute9, relative as relative15, resolve as resolve18, sep as sep14 } from "path";
14481
+ import { mkdir as mkdir16, open as open10, readFile as readFile15, realpath as realpath9, rename as rename8, rm as rm8, stat as stat7 } from "fs/promises";
14482
+ import { dirname as dirname16, isAbsolute as isAbsolute9, relative as relative15, resolve as resolve18, sep as sep14 } from "path";
14152
14483
  import { randomUUID as randomUUID11 } from "crypto";
14153
- import { z as z21 } from "zod";
14484
+ import { z as z22 } from "zod";
14154
14485
 
14155
14486
  // src/tools/file-diff.ts
14156
14487
  var MAX_DIFF_PREVIEW_LINES = 120;
@@ -14256,18 +14587,18 @@ function truncateLines(lines) {
14256
14587
 
14257
14588
  // src/tools/files.ts
14258
14589
  var MAX_READ_BYTES = 1048576;
14259
- var ReadInput2 = z21.object({
14260
- path: z21.string().min(1),
14261
- maxBytes: z21.coerce.number().int().positive().max(MAX_READ_BYTES).nullable().optional(),
14262
- startLine: z21.coerce.number().int().positive().nullable().optional(),
14263
- endLine: z21.coerce.number().int().positive().nullable().optional(),
14590
+ var ReadInput2 = z22.object({
14591
+ path: z22.string().min(1),
14592
+ maxBytes: z22.coerce.number().int().positive().max(MAX_READ_BYTES).nullable().optional(),
14593
+ startLine: z22.coerce.number().int().positive().nullable().optional(),
14594
+ endLine: z22.coerce.number().int().positive().nullable().optional(),
14264
14595
  // Accepts booleans and their string forms (weak-typed models emit "true");
14265
14596
  // kept transform-free so the schema converts to JSON Schema for providers.
14266
- force: z21.union([z21.boolean(), z21.string().refine((value) => value === "true" || value === "false")]).nullable().optional()
14597
+ force: z22.union([z22.boolean(), z22.string().refine((value) => value === "true" || value === "false")]).nullable().optional()
14267
14598
  });
14268
- var WriteInput = z21.object({ path: z21.string().min(1), content: z21.string() });
14269
- var EditInput = z21.object({ path: z21.string().min(1), oldText: z21.string().min(1), newText: z21.string() });
14270
- var ApplyPatchInput = z21.object({ patch: z21.string().min(1) });
14599
+ var WriteInput = z22.object({ path: z22.string().min(1), content: z22.string() });
14600
+ var EditInput = z22.object({ path: z22.string().min(1), oldText: z22.string().min(1), newText: z22.string() });
14601
+ var ApplyPatchInput = z22.object({ patch: z22.string().min(1) });
14271
14602
  var FileObservationStore = class {
14272
14603
  #versions = /* @__PURE__ */ new Map();
14273
14604
  get(path) {
@@ -14475,22 +14806,22 @@ function createPathGuard(workspace) {
14475
14806
  lexical,
14476
14807
  existing: async (input) => {
14477
14808
  const candidate = lexical(input);
14478
- const physical = await realpath8(candidate);
14479
- if (!within2(await realpath8(root), physical)) throw new Error("Path escapes the workspace through a symlink");
14809
+ const physical = await realpath9(candidate);
14810
+ if (!within2(await realpath9(root), physical)) throw new Error("Path escapes the workspace through a symlink");
14480
14811
  return physical;
14481
14812
  },
14482
14813
  destination: async (input) => {
14483
14814
  const candidate = lexical(input);
14484
- const physicalRoot = await realpath8(root);
14815
+ const physicalRoot = await realpath9(root);
14485
14816
  let ancestor = candidate;
14486
14817
  while (true) {
14487
14818
  try {
14488
- const physical = await realpath8(ancestor);
14819
+ const physical = await realpath9(ancestor);
14489
14820
  if (!within2(physicalRoot, physical)) throw new Error("Path escapes the workspace through a symlink");
14490
14821
  break;
14491
14822
  } catch (error) {
14492
14823
  if (!isMissing3(error)) throw error;
14493
- const parent = dirname15(ancestor);
14824
+ const parent = dirname16(ancestor);
14494
14825
  if (parent === ancestor) throw error;
14495
14826
  ancestor = parent;
14496
14827
  }
@@ -14501,7 +14832,7 @@ function createPathGuard(workspace) {
14501
14832
  }
14502
14833
  async function atomicWrite(path, content, signal, expectedVersion) {
14503
14834
  abortIfNeeded(signal);
14504
- await mkdir16(dirname15(path), { recursive: true });
14835
+ await mkdir16(dirname16(path), { recursive: true });
14505
14836
  const temporary = `${path}.${randomUUID11()}.tmp`;
14506
14837
  try {
14507
14838
  const handle = await open10(temporary, constants6.O_CREAT | constants6.O_EXCL | constants6.O_WRONLY, 384);
@@ -14863,22 +15194,22 @@ import { lookup } from "dns/promises";
14863
15194
  import { isIP } from "net";
14864
15195
  import { request as httpRequest } from "http";
14865
15196
  import { request as httpsRequest } from "https";
14866
- import { z as z22 } from "zod";
14867
- var WebFetchInput = z22.object({
14868
- url: z22.string().url().max(8192),
14869
- timeoutMs: z22.coerce.number().int().positive().max(12e4).optional(),
14870
- maxBytes: z22.coerce.number().int().positive().max(10 * 1024 * 1024).optional()
15197
+ import { z as z23 } from "zod";
15198
+ var WebFetchInput = z23.object({
15199
+ url: z23.string().url().max(8192),
15200
+ timeoutMs: z23.coerce.number().int().positive().max(12e4).optional(),
15201
+ maxBytes: z23.coerce.number().int().positive().max(10 * 1024 * 1024).optional()
14871
15202
  });
14872
- var WebSearchInput = z22.object({
14873
- query: z22.string().trim().min(1).max(1e3),
14874
- maxResults: z22.coerce.number().int().min(1).max(20).optional()
15203
+ var WebSearchInput = z23.object({
15204
+ query: z23.string().trim().min(1).max(1e3),
15205
+ maxResults: z23.coerce.number().int().min(1).max(20).optional()
14875
15206
  });
14876
15207
  function createWebFetchTool() {
14877
15208
  return {
14878
15209
  name: "WebFetch",
14879
15210
  description: "Fetch a public HTTP(S) page with SSRF protection and return readable text",
14880
15211
  inputSchema: WebFetchInput,
14881
- outputSchema: z22.object({ url: z22.string(), status: z22.number(), contentType: z22.string(), content: z22.string(), truncated: z22.boolean() }),
15212
+ outputSchema: z23.object({ url: z23.string(), status: z23.number(), contentType: z23.string(), content: z23.string(), truncated: z23.boolean() }),
14882
15213
  paths: () => [],
14883
15214
  summarize: (input) => input.url,
14884
15215
  presentCall: (input) => ({ kind: "web", title: `Fetching ${new URL(input.url).hostname}`, url: input.url }),
@@ -14904,7 +15235,7 @@ function createWebSearchTool(provider = createDefaultWebSearchProvider()) {
14904
15235
  name: "WebSearch",
14905
15236
  description: "Search the public web and return titles, URLs, and snippets",
14906
15237
  inputSchema: WebSearchInput,
14907
- outputSchema: z22.object({ query: z22.string(), results: z22.array(z22.object({ title: z22.string(), url: z22.string(), snippet: z22.string() })) }),
15238
+ outputSchema: z23.object({ query: z23.string(), results: z23.array(z23.object({ title: z23.string(), url: z23.string(), snippet: z23.string() })) }),
14908
15239
  paths: () => [],
14909
15240
  summarize: (input) => input.query,
14910
15241
  presentCall: (input) => ({ kind: "web", title: `Searching: ${input.query}` }),
@@ -15170,9 +15501,9 @@ function charset(contentType) {
15170
15501
  import { spawn as spawn7 } from "child_process";
15171
15502
  import { existsSync as existsSync2 } from "fs";
15172
15503
  import { access, constants as constants7, readFile as readFile16 } from "fs/promises";
15173
- import { basename as basename4, dirname as dirname16, extname, isAbsolute as isAbsolute10, relative as relative16, resolve as resolve19, sep as sep15 } from "path";
15504
+ import { basename as basename4, dirname as dirname17, extname, isAbsolute as isAbsolute10, relative as relative16, resolve as resolve19, sep as sep15 } from "path";
15174
15505
  import { fileURLToPath as fileURLToPath3, pathToFileURL as pathToFileURL2 } from "url";
15175
- import { z as z23 } from "zod";
15506
+ import { z as z24 } from "zod";
15176
15507
  var LSP_REQUEST_TIMEOUT_MS = 15e3;
15177
15508
  var LspConnection = class {
15178
15509
  #process;
@@ -15387,7 +15718,7 @@ var LspBuffer = class {
15387
15718
  }
15388
15719
  };
15389
15720
  var TYPESCRIPT_CLI = resolve19(
15390
- dirname16(fileURLToPath3(import.meta.resolve("typescript/package.json"))),
15721
+ dirname17(fileURLToPath3(import.meta.resolve("typescript/package.json"))),
15391
15722
  "lib",
15392
15723
  "tsc.js"
15393
15724
  );
@@ -15506,18 +15837,18 @@ var RealLspManager = class {
15506
15837
  return connection;
15507
15838
  }
15508
15839
  };
15509
- var LspFindRefsInput = z23.object({
15510
- file: z23.string().min(1),
15511
- line: z23.coerce.number().int().nonnegative(),
15512
- character: z23.coerce.number().int().nonnegative()
15840
+ var LspFindRefsInput = z24.object({
15841
+ file: z24.string().min(1),
15842
+ line: z24.coerce.number().int().nonnegative(),
15843
+ character: z24.coerce.number().int().nonnegative()
15513
15844
  });
15514
- var LspHoverInput = z23.object({
15515
- file: z23.string().min(1),
15516
- line: z23.coerce.number().int().nonnegative(),
15517
- character: z23.coerce.number().int().nonnegative()
15845
+ var LspHoverInput = z24.object({
15846
+ file: z24.string().min(1),
15847
+ line: z24.coerce.number().int().nonnegative(),
15848
+ character: z24.coerce.number().int().nonnegative()
15518
15849
  });
15519
- var LspDiagnosticsInput = z23.object({
15520
- file: z23.string().min(1)
15850
+ var LspDiagnosticsInput = z24.object({
15851
+ file: z24.string().min(1)
15521
15852
  });
15522
15853
  function createLspTools(workspace, options = {}) {
15523
15854
  const root = resolve19(workspace);
@@ -15743,7 +16074,7 @@ async function gitMarker(workspace) {
15743
16074
  }
15744
16075
 
15745
16076
  // src/git/insights.ts
15746
- import { z as z24 } from "zod";
16077
+ import { z as z25 } from "zod";
15747
16078
  async function suggestCommitMessage(options, input, signal) {
15748
16079
  const prompt = [
15749
16080
  "Write a git commit message for the staged changes below.",
@@ -15782,17 +16113,17 @@ function cleanCommitMessage(raw) {
15782
16113
  }
15783
16114
  return kept.join("\n").trim().slice(0, 2e3);
15784
16115
  }
15785
- var ReviewFindingSchema = z24.object({
15786
- severity: z24.enum(["critical", "warning", "nit"]),
15787
- file: z24.string(),
15788
- line: z24.string().describe('Line number or hunk header the finding refers to, e.g. "42" or "@@ -10,4 +10,6 @@"'),
15789
- issue: z24.string(),
15790
- suggestion: z24.string()
16116
+ var ReviewFindingSchema = z25.object({
16117
+ severity: z25.enum(["critical", "warning", "nit"]),
16118
+ file: z25.string(),
16119
+ line: z25.string().describe('Line number or hunk header the finding refers to, e.g. "42" or "@@ -10,4 +10,6 @@"'),
16120
+ issue: z25.string(),
16121
+ suggestion: z25.string()
15791
16122
  }).strict();
15792
- var ReviewReportSchema = z24.object({
15793
- summary: z24.string().describe("One-paragraph overall assessment of the change"),
15794
- verdict: z24.enum(["ship", "ship-with-fixes", "needs-work"]),
15795
- findings: z24.array(ReviewFindingSchema).max(20)
16123
+ var ReviewReportSchema = z25.object({
16124
+ summary: z25.string().describe("One-paragraph overall assessment of the change"),
16125
+ verdict: z25.enum(["ship", "ship-with-fixes", "needs-work"]),
16126
+ findings: z25.array(ReviewFindingSchema).max(20)
15796
16127
  }).strict();
15797
16128
  async function reviewDiff(options, input, signal) {
15798
16129
  const prompt = [
@@ -15836,10 +16167,10 @@ function formatReviewReport(report) {
15836
16167
  }
15837
16168
 
15838
16169
  // src/git/tools.ts
15839
- import { z as z25 } from "zod";
15840
- var GitHistoryInput = z25.object({
15841
- path: z25.string().describe("File to inspect; omit for the whole repository history").optional(),
15842
- limit: z25.number().int().min(1).max(50).describe("Maximum number of commits to return (default 20)").optional()
16170
+ import { z as z26 } from "zod";
16171
+ var GitHistoryInput = z26.object({
16172
+ path: z26.string().describe("File to inspect; omit for the whole repository history").optional(),
16173
+ limit: z26.number().int().min(1).max(50).describe("Maximum number of commits to return (default 20)").optional()
15843
16174
  });
15844
16175
  function createGitHistoryTool(workspace) {
15845
16176
  return {
@@ -15868,18 +16199,18 @@ function createGitHistoryTool(workspace) {
15868
16199
  }
15869
16200
 
15870
16201
  // src/tools/ask-user-question.ts
15871
- import { z as z26 } from "zod";
15872
- var QuestionOptionSchema = z26.object({
15873
- label: z26.string().trim().min(1),
15874
- description: z26.string().trim().min(1)
16202
+ import { z as z27 } from "zod";
16203
+ var QuestionOptionSchema = z27.object({
16204
+ label: z27.string().trim().min(1),
16205
+ description: z27.string().trim().min(1)
15875
16206
  });
15876
- var QuestionSchema = z26.object({
15877
- question: z26.string().trim().min(1),
15878
- header: z26.string().trim().min(1),
15879
- options: z26.array(QuestionOptionSchema).min(1).max(4)
16207
+ var QuestionSchema = z27.object({
16208
+ question: z27.string().trim().min(1),
16209
+ header: z27.string().trim().min(1),
16210
+ options: z27.array(QuestionOptionSchema).min(1).max(4)
15880
16211
  });
15881
- var AskUserQuestionInput = z26.object({
15882
- questions: z26.array(QuestionSchema).min(1).max(4)
16212
+ var AskUserQuestionInput = z27.object({
16213
+ questions: z27.array(QuestionSchema).min(1).max(4)
15883
16214
  });
15884
16215
  function hookAnswersFromUpdatedInput(updatedInput, questions) {
15885
16216
  if (typeof updatedInput !== "object" || updatedInput === null) return void 0;
@@ -15963,20 +16294,20 @@ function createAskUserQuestionTool(handler) {
15963
16294
  }
15964
16295
 
15965
16296
  // src/tools/todo-write.ts
15966
- import { z as z27 } from "zod";
15967
- var TodoStatusSchema = z27.enum([
16297
+ import { z as z28 } from "zod";
16298
+ var TodoStatusSchema = z28.enum([
15968
16299
  "pending",
15969
16300
  "in_progress",
15970
16301
  "completed",
15971
16302
  "cancelled"
15972
16303
  ]);
15973
- var TodoItemSchema = z27.object({
15974
- content: z27.string().trim().min(1),
16304
+ var TodoItemSchema = z28.object({
16305
+ content: z28.string().trim().min(1),
15975
16306
  status: TodoStatusSchema,
15976
- activeForm: z27.string().trim().min(1)
16307
+ activeForm: z28.string().trim().min(1)
15977
16308
  });
15978
- var TodoWriteInput = z27.object({
15979
- todos: z27.array(TodoItemSchema).min(1).max(50)
16309
+ var TodoWriteInput = z28.object({
16310
+ todos: z28.array(TodoItemSchema).min(1).max(50)
15980
16311
  });
15981
16312
  function createTodoWriteTool() {
15982
16313
  return {
@@ -16012,37 +16343,37 @@ function createTodoWriteTool() {
16012
16343
  // src/tools/managed.ts
16013
16344
  import { randomUUID as randomUUID12 } from "crypto";
16014
16345
  import { link as link2, lstat as lstat11, mkdir as mkdir17, readFile as readFile17, readdir as readdir9, unlink as unlink4, writeFile as writeFile10 } from "fs/promises";
16015
- import { dirname as dirname17, join as join19, resolve as resolve20 } from "path";
16016
- import { z as z28 } from "zod";
16346
+ import { dirname as dirname18, join as join19, resolve as resolve20 } from "path";
16347
+ import { z as z29 } from "zod";
16017
16348
  var MANAGED_TOOL_VERSION = 1;
16018
16349
  var MAX_RECORD_BYTES = 256 * 1024;
16019
16350
  var TOOL_NAME = /^[A-Za-z][A-Za-z0-9_]{0,63}$/;
16020
- var JsonSchemaObject = z28.record(z28.string(), z28.unknown()).superRefine((schema, context) => {
16351
+ var JsonSchemaObject = z29.record(z29.string(), z29.unknown()).superRefine((schema, context) => {
16021
16352
  if (schema.type !== "object") {
16022
16353
  context.addIssue({ code: "custom", message: "Tool input JSON Schema must have type object" });
16023
16354
  }
16024
16355
  });
16025
- var RegisterManagedToolInputSchema = z28.object({
16026
- name: z28.string().regex(TOOL_NAME).describe("Unique callable tool name using letters, digits, and underscores"),
16027
- description: z28.string().min(1).max(4096).describe("Purpose and appropriate use of the generated tool"),
16356
+ var RegisterManagedToolInputSchema = z29.object({
16357
+ name: z29.string().regex(TOOL_NAME).describe("Unique callable tool name using letters, digits, and underscores"),
16358
+ description: z29.string().min(1).max(4096).describe("Purpose and appropriate use of the generated tool"),
16028
16359
  inputSchema: JsonSchemaObject.describe("Provider-facing JSON Schema with an object at the root"),
16029
- implementation: z28.string().min(1).max(64 * 1024).describe(
16360
+ implementation: z29.string().min(1).max(64 * 1024).describe(
16030
16361
  "Async JavaScript function body, or complete function/arrow expression, receiving input, signal, and context; return the tool result"
16031
16362
  ),
16032
- scope: z28.enum(["project", "global"]).default("project").describe(
16363
+ scope: z29.enum(["project", "global"]).default("project").describe(
16033
16364
  "Project persists in the current workspace; global persists for every workspace"
16034
16365
  ),
16035
- agents: z28.array(z28.enum(["main", "subagent"])).min(1).max(2).optional().describe(
16366
+ agents: z29.array(z29.enum(["main", "subagent"])).min(1).max(2).optional().describe(
16036
16367
  "Agent roles allowed to call the generated tool; omit to allow both"
16037
16368
  )
16038
16369
  }).strict();
16039
- var RemoveManagedToolInputSchema = z28.object({
16040
- name: z28.string().regex(TOOL_NAME).describe("Managed tool name to remove"),
16041
- scope: z28.enum(["project", "global"]).optional().describe("Required only when the same name exists in both scopes")
16370
+ var RemoveManagedToolInputSchema = z29.object({
16371
+ name: z29.string().regex(TOOL_NAME).describe("Managed tool name to remove"),
16372
+ scope: z29.enum(["project", "global"]).optional().describe("Required only when the same name exists in both scopes")
16042
16373
  }).strict();
16043
16374
  var ManagedToolRecordSchema = RegisterManagedToolInputSchema.extend({
16044
- version: z28.literal(MANAGED_TOOL_VERSION),
16045
- createdAt: z28.string().datetime()
16375
+ version: z29.literal(MANAGED_TOOL_VERSION),
16376
+ createdAt: z29.string().datetime()
16046
16377
  }).strict();
16047
16378
  var AsyncFunction = Object.getPrototypeOf(async function() {
16048
16379
  }).constructor;
@@ -16229,7 +16560,7 @@ function createManagedToolManagementTools(options) {
16229
16560
  const listTools = {
16230
16561
  name: "ListRegisteredTools",
16231
16562
  description: "List durable tools created through RegisterTool, including scope, path, and active precedence",
16232
- inputSchema: z28.object({}).strict(),
16563
+ inputSchema: z29.object({}).strict(),
16233
16564
  agents: mainOnly,
16234
16565
  paths: () => [],
16235
16566
  execute: async (_input, signal) => {
@@ -16242,7 +16573,7 @@ function createManagedToolManagementTools(options) {
16242
16573
  function compileDefinition(record, scope2, workspace) {
16243
16574
  let inputSchema;
16244
16575
  try {
16245
- inputSchema = z28.fromJSONSchema(record.inputSchema);
16576
+ inputSchema = z29.fromJSONSchema(record.inputSchema);
16246
16577
  } catch (error) {
16247
16578
  throw new Error(`Invalid input schema for managed tool "${record.name}": ${message(error)}`);
16248
16579
  }
@@ -16296,7 +16627,7 @@ ${sourceUrl}`
16296
16627
  }
16297
16628
  }
16298
16629
  async function writeExclusive(path, content) {
16299
- await mkdir17(dirname17(path), { recursive: true });
16630
+ await mkdir17(dirname18(path), { recursive: true });
16300
16631
  const temporary = `${path}.${randomUUID12()}.tmp`;
16301
16632
  try {
16302
16633
  await writeFile10(temporary, content, { encoding: "utf8", flag: "wx", mode: 384 });
@@ -16342,7 +16673,7 @@ function isMissing4(error) {
16342
16673
  }
16343
16674
 
16344
16675
  // src/hallucination/confidence.ts
16345
- import { z as z29 } from "zod";
16676
+ import { z as z30 } from "zod";
16346
16677
 
16347
16678
  // src/hallucination/types.ts
16348
16679
  var DEFAULT_SLIDING_WINDOW_SIZE = 20;
@@ -16355,12 +16686,12 @@ var DEFAULT_EVALUATION_TIMEOUT_MS = 2e3;
16355
16686
  var MAX_QUERY_CHARS = 5e3;
16356
16687
  var MAX_OUTPUT_CHARS = 1e4;
16357
16688
  var MAX_EVIDENCE_CHARS = 6e3;
16358
- var ConfidenceSchema = z29.object({
16359
- taskAlignment: z29.number(),
16360
- evidenceGrounding: z29.number(),
16361
- processReliability: z29.number(),
16362
- reason: z29.string(),
16363
- unsupportedClaims: z29.array(z29.string()).max(3)
16689
+ var ConfidenceSchema = z30.object({
16690
+ taskAlignment: z30.number(),
16691
+ evidenceGrounding: z30.number(),
16692
+ processReliability: z30.number(),
16693
+ reason: z30.string(),
16694
+ unsupportedClaims: z30.array(z30.string()).max(3)
16364
16695
  });
16365
16696
  var PROMPT = `You are a fast, evidence-aware task-completion verifier.
16366
16697
 
@@ -18359,15 +18690,15 @@ function workspacePath(root, input) {
18359
18690
  }
18360
18691
 
18361
18692
  // src/tools/terminal.ts
18362
- import { z as z30 } from "zod";
18693
+ import { z as z31 } from "zod";
18363
18694
  import { resolve as resolve24 } from "path";
18364
- var Id = z30.string().regex(/^term-[a-f0-9-]+$/);
18365
- var OpenInput = z30.object({ cwd: z30.string().optional(), shell: z30.string().optional(), args: z30.array(z30.string()).optional(), columns: z30.coerce.number().int().min(10).max(500).optional(), rows: z30.coerce.number().int().min(2).max(300).optional() });
18366
- var OptionalBoolean = z30.union([z30.boolean(), z30.string().refine((value) => value === "true" || value === "false")]);
18367
- var WriteInput2 = z30.object({ id: Id, data: z30.string().max(1e5), enter: OptionalBoolean.optional() });
18368
- var ReadInput3 = z30.object({ id: Id, cursor: z30.coerce.number().int().min(0).optional() });
18369
- var ResizeInput = z30.object({ id: Id, columns: z30.coerce.number().int().min(10).max(500), rows: z30.coerce.number().int().min(2).max(300) });
18370
- var CloseInput = z30.object({ id: Id });
18695
+ var Id = z31.string().regex(/^term-[a-f0-9-]+$/);
18696
+ var OpenInput = z31.object({ cwd: z31.string().optional(), shell: z31.string().optional(), args: z31.array(z31.string()).optional(), columns: z31.coerce.number().int().min(10).max(500).optional(), rows: z31.coerce.number().int().min(2).max(300).optional() });
18697
+ var OptionalBoolean = z31.union([z31.boolean(), z31.string().refine((value) => value === "true" || value === "false")]);
18698
+ var WriteInput2 = z31.object({ id: Id, data: z31.string().max(1e5), enter: OptionalBoolean.optional() });
18699
+ var ReadInput3 = z31.object({ id: Id, cursor: z31.coerce.number().int().min(0).optional() });
18700
+ var ResizeInput = z31.object({ id: Id, columns: z31.coerce.number().int().min(10).max(500), rows: z31.coerce.number().int().min(2).max(300) });
18701
+ var CloseInput = z31.object({ id: Id });
18371
18702
  function createTerminalTools(terminals, workspace = process.cwd()) {
18372
18703
  const tools = [
18373
18704
  {
@@ -18443,7 +18774,7 @@ function createTerminalTools(terminals, workspace = process.cwd()) {
18443
18774
  {
18444
18775
  name: "TerminalList",
18445
18776
  description: "List persistent terminals owned by this agent",
18446
- inputSchema: z30.object({}),
18777
+ inputSchema: z31.object({}),
18447
18778
  paths: () => [],
18448
18779
  execute: async (_input, _signal, context) => terminals.list(owner(context))
18449
18780
  }
@@ -18822,7 +19153,7 @@ var PalClient = class {
18822
19153
  };
18823
19154
 
18824
19155
  // src/pals/tools.ts
18825
- import { z as z31 } from "zod";
19156
+ import { z as z32 } from "zod";
18826
19157
  var DEFAULT_SHARE_BUDGET_BYTES = 128 * 1024;
18827
19158
  var CollaborationShareGuard = class {
18828
19159
  redact;
@@ -18843,25 +19174,25 @@ var CollaborationShareGuard = class {
18843
19174
  return redacted;
18844
19175
  }
18845
19176
  };
18846
- var Uuid = z31.uuid();
18847
- var Hash = z31.string().regex(/^[a-f0-9]{64}$/);
19177
+ var Uuid = z32.uuid();
19178
+ var Hash = z32.string().regex(/^[a-f0-9]{64}$/);
18848
19179
  var Target = PalTargetSchema;
18849
- var BoundedText = z31.string().trim().min(1).refine(
19180
+ var BoundedText = z32.string().trim().min(1).refine(
18850
19181
  (value) => Buffer.byteLength(value, "utf8") <= MAX_MESSAGE_BYTES,
18851
19182
  `Text must not exceed ${MAX_MESSAGE_BYTES} UTF-8 bytes`
18852
19183
  );
18853
- var CompletionEvidence = z31.string().trim().min(1).refine(
19184
+ var CompletionEvidence = z32.string().trim().min(1).refine(
18854
19185
  (value) => Buffer.byteLength(value, "utf8") <= MAX_COMPLETION_DETAIL_BYTES,
18855
19186
  `Completion evidence must not exceed ${MAX_COMPLETION_DETAIL_BYTES} UTF-8 bytes`
18856
19187
  );
18857
- var EmptyInput = z31.object({}).strict();
18858
- var StateInput = z31.object({ coWorkId: Uuid }).strict();
18859
- var TokenInput = z31.object({ coWorkId: Uuid, epoch: z31.number().int().positive(), planHash: Hash }).strict();
18860
- var SendInput = z31.object({ target: Target, message: BoundedText, coWorkId: Uuid.optional() }).strict();
18861
- var PlanInput = z31.object({ plan: CoWorkPlanSchema }).strict();
18862
- var ProgressInput = z31.object({ coWorkId: Uuid, target: Target, detail: BoundedText }).strict();
18863
- var CompleteInput = TokenInput.extend({ passed: z31.boolean(), detail: CompletionEvidence }).strict();
18864
- var IntegrateInput = TokenInput.extend({ passed: z31.boolean(), evidence: CompletionEvidence }).strict();
19188
+ var EmptyInput = z32.object({}).strict();
19189
+ var StateInput = z32.object({ coWorkId: Uuid }).strict();
19190
+ var TokenInput = z32.object({ coWorkId: Uuid, epoch: z32.number().int().positive(), planHash: Hash }).strict();
19191
+ var SendInput = z32.object({ target: Target, message: BoundedText, coWorkId: Uuid.optional() }).strict();
19192
+ var PlanInput = z32.object({ plan: CoWorkPlanSchema }).strict();
19193
+ var ProgressInput = z32.object({ coWorkId: Uuid, target: Target, detail: BoundedText }).strict();
19194
+ var CompleteInput = TokenInput.extend({ passed: z32.boolean(), detail: CompletionEvidence }).strict();
19195
+ var IntegrateInput = TokenInput.extend({ passed: z32.boolean(), evidence: CompletionEvidence }).strict();
18865
19196
  var sharedBytes = (...values) => values.reduce((total, value) => total + Buffer.byteLength(value, "utf8"), 0);
18866
19197
  function resolvePresence(presences, target) {
18867
19198
  const normalized = normalizePalIdentity(target);
@@ -19478,7 +19809,7 @@ async function createProductionRuntime(options) {
19478
19809
  });
19479
19810
  const skillsReady = skills.discover();
19480
19811
  skillsReady.catch(() => void 0);
19481
- tools.push(createSkillResourceTool(skills));
19812
+ tools.push(createSkillTool(skills), createSkillResourceTool(skills));
19482
19813
  if (options.extraTools !== void 0) tools.push(...options.extraTools);
19483
19814
  const flavor = await optionalText2(join22(workspace, "FLAVOR.md"));
19484
19815
  const instructionBaseline = await workspaceInstructions.baseline();
@@ -20180,6 +20511,10 @@ async function createProductionRuntime(options) {
20180
20511
  subagentModel: () => childModel,
20181
20512
  llmServiceName: () => effectiveLlm?.serviceName,
20182
20513
  permissionMode: () => harness.permissionMode,
20514
+ addContext: (content) => {
20515
+ const duplicate = harness.main.context.snapshot().messages.some((entry2) => entry2.role === "system" && entry2.content === content);
20516
+ if (!duplicate) harness.main.context.append({ role: "system", content });
20517
+ },
20183
20518
  ...palServices === void 0 ? {} : { pals: palServices },
20184
20519
  run: (prompt, signal, runOptions) => {
20185
20520
  interruptedTaskPlanNeedsReassessment = false;
@@ -20793,7 +21128,7 @@ async function* runMain(harness, skills, prompt, signal, setupError, memory, get
20793
21128
  if (ideContext !== void 0) contexts.push(ideContext);
20794
21129
  const skill = await skills.match(prompt);
20795
21130
  if (skill !== void 0) contexts.push(`Matched skill: ${skill.name}
20796
- ${await skills.loadBody(skill)}`);
21131
+ ${expandSkillArguments(await skills.loadBody(skill), prompt)}`);
20797
21132
  const additionalContext = contexts.length === 0 ? void 0 : contexts.join("\n\n");
20798
21133
  for await (const event of harness.main.loop.run({
20799
21134
  prompt,
@@ -20828,7 +21163,7 @@ async function* runExplicitSkill(harness, skills, skillName, prompt, signal, set
20828
21163
  }
20829
21164
  const userPrompt = prompt || `Apply the ${skillName} skill.`;
20830
21165
  const additionalContext = `Matched skill: ${skill.name}
20831
- ${await skills.loadBody(skill)}`;
21166
+ ${expandSkillArguments(await skills.loadBody(skill), prompt)}`;
20832
21167
  yield* harness.main.loop.run({ prompt: userPrompt, signal, additionalContext });
20833
21168
  } catch (error) {
20834
21169
  yield { type: "error", error: { code: "unknown", message: message(error) } };