@skein-code/cli 0.3.20 → 0.3.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -4,7 +4,7 @@
4
4
  import { createInterface as createInterface2 } from "node:readline/promises";
5
5
  import { stdin as input, stdout as output } from "node:process";
6
6
  import { writeFile as writeFile3 } from "node:fs/promises";
7
- import { basename as basename13, resolve as resolve24 } from "node:path";
7
+ import { basename as basename13, resolve as resolve25 } from "node:path";
8
8
  import { Command, Option } from "commander";
9
9
  import chalk4 from "chalk";
10
10
 
@@ -220,7 +220,7 @@ function isSqliteBusy(error) {
220
220
  // package.json
221
221
  var package_default = {
222
222
  name: "@skein-code/cli",
223
- version: "0.3.20",
223
+ version: "0.3.22",
224
224
  description: "A context-first, model-agnostic coding agent with an auditable terminal workspace.",
225
225
  type: "module",
226
226
  license: "MIT",
@@ -236,6 +236,13 @@ var package_default = {
236
236
  },
237
237
  skein: {
238
238
  releaseNotes: [
239
+ "OpenAI, Anthropic, and Gemini usage now normalizes cached input, cache-write input, and reasoning tokens when reported",
240
+ "Token Ledger, session totals, and structured usage events preserve provider cache and reasoning counts without prompt content",
241
+ "Streaming, non-streaming, explicit-zero, and legacy-session compatibility paths are covered without claiming cache activation",
242
+ "Failed configured verification output yields bounded current-run diagnostic ranking without persisting paths",
243
+ "Diagnostic hints cannot create zero-relevance hits and are cleared on success or the next agent run",
244
+ "Python absolute and relative module imports now contribute deterministic offline graph adjacency",
245
+ "Context provenance exposes the diagnostic score alongside graph and isolated Git recency signals",
239
246
  "Local index v3 records TypeScript AST definitions, calls, and relative import adjacency for graph-assisted retrieval",
240
247
  "Context hits expose generation, content hash, matched terms, and bm25/path/symbol/phrase/graph score provenance",
241
248
  "Context benchmark v2 locks multilingual recall, MRR, useful-token, stale-hit, incremental-index, and warm-latency gates",
@@ -3113,7 +3120,7 @@ function executableNames(command2) {
3113
3120
  return [command2, ...extensions.map((extension) => `${command2}${extension}`)];
3114
3121
  }
3115
3122
  function runProcess(command2, args, options) {
3116
- return new Promise((resolve25, reject) => {
3123
+ return new Promise((resolve26, reject) => {
3117
3124
  const started = Date.now();
3118
3125
  const environment = options.inheritEnv === false ? {} : { ...process.env };
3119
3126
  for (const name of options.unsetEnv ?? []) delete environment[name];
@@ -3205,7 +3212,7 @@ function runProcess(command2, args, options) {
3205
3212
  reject(callbackError);
3206
3213
  return;
3207
3214
  }
3208
- resolve25({
3215
+ resolve26({
3209
3216
  command: [command2, ...args].join(" "),
3210
3217
  exitCode: code ?? (timedOut ? 124 : 1),
3211
3218
  stdout,
@@ -3474,6 +3481,8 @@ var MAX_QUERY_CACHE_ENTRIES = 64;
3474
3481
  var CHUNK_LINES = 100;
3475
3482
  var CHUNK_OVERLAP = 15;
3476
3483
  var MIN_STRUCTURAL_CHUNK_LINES = 12;
3484
+ var MAX_DIAGNOSTIC_SCORE = 0.05;
3485
+ var MAX_DIAGNOSTIC_HINTS_PER_COMMAND = 16;
3477
3486
  var LocalContextIndex = class {
3478
3487
  constructor(roots) {
3479
3488
  this.roots = roots;
@@ -3487,6 +3496,8 @@ var LocalContextIndex = class {
3487
3496
  workspace;
3488
3497
  queryCache = /* @__PURE__ */ new Map();
3489
3498
  gitRecency;
3499
+ diagnosticsByCommand = /* @__PURE__ */ new Map();
3500
+ diagnosticScores = /* @__PURE__ */ new Map();
3490
3501
  queryCacheHits = 0;
3491
3502
  queryCacheMisses = 0;
3492
3503
  fingerprintCache;
@@ -3605,6 +3616,23 @@ var LocalContextIndex = class {
3605
3616
  if (paths.length) this.queryCache.clear();
3606
3617
  if (this.dirtyPaths.size) this.refreshState = "dirty";
3607
3618
  }
3619
+ recordDiagnostics(update) {
3620
+ const paths = /* @__PURE__ */ new Set();
3621
+ for (const candidate of update.paths.slice(0, MAX_DIAGNOSTIC_HINTS_PER_COMMAND)) {
3622
+ const path = this.resolveDiagnosticPath(candidate);
3623
+ if (path) paths.add(path);
3624
+ }
3625
+ if (paths.size) this.diagnosticsByCommand.set(update.commandKey, paths);
3626
+ else this.diagnosticsByCommand.delete(update.commandKey);
3627
+ this.refreshDiagnosticScores();
3628
+ this.queryCache.clear();
3629
+ }
3630
+ resetDiagnostics() {
3631
+ if (!this.diagnosticsByCommand.size) return;
3632
+ this.diagnosticsByCommand.clear();
3633
+ this.diagnosticScores.clear();
3634
+ this.queryCache.clear();
3635
+ }
3608
3636
  async flushDirty() {
3609
3637
  if (!this.dirtyPaths.size) {
3610
3638
  return {
@@ -3690,6 +3718,7 @@ var LocalContextIndex = class {
3690
3718
  queryCacheEntries: this.queryCache.size,
3691
3719
  queryCacheHits: this.queryCacheHits,
3692
3720
  queryCacheMisses: this.queryCacheMisses,
3721
+ diagnosticHints: this.diagnosticScores.size,
3693
3722
  refreshState: this.refreshState,
3694
3723
  dirtyPaths: this.dirtyPaths.size,
3695
3724
  ...this.refreshError ? { refreshError: this.refreshError } : {},
@@ -3939,11 +3968,12 @@ var LocalContextIndex = class {
3939
3968
  );
3940
3969
  const graph = graphBoosts.get(chunk.absolutePath)?.score ?? 0;
3941
3970
  const recency = recencyScores.get(chunk.absolutePath) ?? 0;
3942
- const score = lexical.bm25 + lexical.path + lexical.symbol + lexical.phrase + graph + recency;
3943
- return { chunk, lexical, graph, recency, score };
3971
+ const diagnostic = this.diagnosticScores.get(chunk.absolutePath) ?? 0;
3972
+ const score = lexical.bm25 + lexical.path + lexical.symbol + lexical.phrase + graph + recency + diagnostic;
3973
+ return { chunk, lexical, graph, recency, diagnostic, score };
3944
3974
  }).filter(({ lexical, graph }) => lexical.bm25 + lexical.path + lexical.symbol + lexical.phrase + graph > 0).sort((left, right) => right.score - left.score || left.chunk.absolutePath.localeCompare(right.chunk.absolutePath));
3945
3975
  const covered = scored.filter(({ lexical, graph }) => graph > 0 || hasSufficientQueryCoverage(lexical.matchedTerms, coverageTerms));
3946
- return (covered.length ? covered : scored).slice(0, topK).map(({ chunk, lexical, graph, recency, score }) => {
3976
+ return (covered.length ? covered : scored).slice(0, topK).map(({ chunk, lexical, graph, recency, diagnostic, score }) => {
3947
3977
  const file = filesByPath.get(chunk.absolutePath);
3948
3978
  const breakdown = {
3949
3979
  bm25: roundScore(lexical.bm25),
@@ -3952,6 +3982,7 @@ var LocalContextIndex = class {
3952
3982
  phrase: roundScore(lexical.phrase),
3953
3983
  graph: roundScore(graph),
3954
3984
  recency: roundScore(recency),
3985
+ diagnostic: roundScore(diagnostic),
3955
3986
  total: roundScore(score)
3956
3987
  };
3957
3988
  const provenance = {
@@ -3967,7 +3998,7 @@ var LocalContextIndex = class {
3967
3998
  endLine: chunk.endLine,
3968
3999
  content: chunk.content,
3969
4000
  score,
3970
- source: "local-bm25+path+symbol+graph+recency",
4001
+ source: "local-bm25+path+symbol+graph+recency+diagnostic",
3971
4002
  ...chunk.symbol ? { symbol: chunk.symbol } : {},
3972
4003
  provenance
3973
4004
  };
@@ -4023,6 +4054,22 @@ var LocalContextIndex = class {
4023
4054
  this.queryCache.delete(oldest);
4024
4055
  }
4025
4056
  }
4057
+ resolveDiagnosticPath(candidate) {
4058
+ if (!candidate || candidate.includes("\0")) return void 0;
4059
+ const absolute = isAbsolute4(candidate) ? resolve10(candidate) : void 0;
4060
+ if (absolute && this.roots.some((root) => isWithinRoot(root, absolute))) return absolute;
4061
+ for (const root of this.roots) {
4062
+ const path = resolve10(root, candidate);
4063
+ if (isWithinRoot(root, path)) return path;
4064
+ }
4065
+ return void 0;
4066
+ }
4067
+ refreshDiagnosticScores() {
4068
+ this.diagnosticScores.clear();
4069
+ for (const paths of this.diagnosticsByCommand.values()) {
4070
+ for (const path of paths) this.diagnosticScores.set(path, MAX_DIAGNOSTIC_SCORE);
4071
+ }
4072
+ }
4026
4073
  };
4027
4074
  function isWithinRoot(root, path) {
4028
4075
  const offset = relative5(root, path);
@@ -4158,7 +4205,7 @@ function packContextHits(hits, roots, maxTokens, engine) {
4158
4205
  const text = selected.map((hit) => {
4159
4206
  const shownPath = workspaceAliasPath(hit.path, roots);
4160
4207
  const symbol = hit.symbol ? ` symbol="${escapeAttribute(hit.symbol)}"` : "";
4161
- const provenance = hit.provenance ? ` source="${escapeAttribute(hit.source)}" hash="${hit.provenance.contentHash.slice(0, 12)}" graph-score="${hit.provenance.score.graph.toFixed(3)}" recency-score="${hit.provenance.score.recency.toFixed(6)}"` : "";
4208
+ const provenance = hit.provenance ? ` source="${escapeAttribute(hit.source)}" hash="${hit.provenance.contentHash.slice(0, 12)}" graph-score="${hit.provenance.score.graph.toFixed(3)}" recency-score="${hit.provenance.score.recency.toFixed(6)}" diagnostic-score="${hit.provenance.score.diagnostic.toFixed(3)}"` : "";
4162
4209
  return `<code path="${escapeAttribute(shownPath)}" lines="${hit.startLine}-${hit.endLine}" score="${hit.score.toFixed(3)}"${symbol}${provenance}>
4163
4210
  ${hit.content}
4164
4211
  </code>`;
@@ -4485,18 +4532,37 @@ function definitionMatchesQuery(definitionTerms, queryTerms) {
4485
4532
  return shared.length >= required;
4486
4533
  }
4487
4534
  function resolveImportTargets(importer, specifier, files) {
4488
- if (!specifier.startsWith(".")) return [];
4489
- const base = posix.normalize(posix.join(posix.dirname(importer.path), specifier));
4490
- const extensions = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
4491
- const importedExtension = posix.extname(base);
4492
- const extensionless = extensions.includes(importedExtension) ? base.slice(0, -importedExtension.length) : base;
4493
- const candidates = /* @__PURE__ */ new Set([
4494
- base,
4495
- ...extensions.map((extension) => `${extensionless}${extension}`),
4496
- ...extensions.map((extension) => posix.join(extensionless, `index${extension}`))
4497
- ]);
4535
+ const candidates = /* @__PURE__ */ new Set();
4536
+ const extension = extname2(importer.path).toLocaleLowerCase();
4537
+ if (specifier.startsWith(".")) {
4538
+ const base = posix.normalize(posix.join(posix.dirname(importer.path), specifier));
4539
+ const extensions = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
4540
+ const importedExtension = posix.extname(base);
4541
+ const extensionless = extensions.includes(importedExtension) ? base.slice(0, -importedExtension.length) : base;
4542
+ candidates.add(base);
4543
+ for (const candidateExtension of extensions) {
4544
+ candidates.add(`${extensionless}${candidateExtension}`);
4545
+ candidates.add(posix.join(extensionless, `index${candidateExtension}`));
4546
+ }
4547
+ }
4548
+ if (extension === ".py") {
4549
+ const modulePath = resolvePythonModulePath(importer.path, specifier);
4550
+ if (modulePath) {
4551
+ candidates.add(`${modulePath}.py`);
4552
+ candidates.add(posix.join(modulePath, "__init__.py"));
4553
+ }
4554
+ }
4498
4555
  return files.filter((file) => file.root === importer.root && candidates.has(file.path)).map((file) => file.absolutePath);
4499
4556
  }
4557
+ function resolvePythonModulePath(importerPath, specifier) {
4558
+ const match = specifier.match(/^(\.+)(.*)$/u);
4559
+ if (!match) return specifier.split(".").filter(Boolean).join("/");
4560
+ const [, dots, remainder] = match;
4561
+ if (!dots || !remainder) return void 0;
4562
+ let base = posix.dirname(importerPath);
4563
+ for (let level = 1; level < dots.length; level += 1) base = posix.dirname(base);
4564
+ return posix.normalize(posix.join(base, remainder.split(".").filter(Boolean).join("/")));
4565
+ }
4500
4566
  function scoreChunk(chunk, terms, rawQuery, documentFrequency, documentCount, averageLength) {
4501
4567
  const frequencies = /* @__PURE__ */ new Map();
4502
4568
  for (const token of chunk.tokens) frequencies.set(token, (frequencies.get(token) ?? 0) + 1);
@@ -4587,6 +4653,12 @@ var ContextEngine = class {
4587
4653
  invalidate(paths) {
4588
4654
  this.local.invalidate(paths);
4589
4655
  }
4656
+ recordDiagnostics(update) {
4657
+ this.local.recordDiagnostics(update);
4658
+ }
4659
+ resetDiagnostics() {
4660
+ this.local.resetDiagnostics();
4661
+ }
4590
4662
  async flushDirty() {
4591
4663
  try {
4592
4664
  const result = await this.local.flushDirty();
@@ -4633,7 +4705,7 @@ function formatContextHits(hits, roots) {
4633
4705
  const path = workspaceAliasPath(hit.path, roots);
4634
4706
  const symbol = hit.symbol ? ` ${hit.symbol}` : "";
4635
4707
  const score = hit.provenance?.score;
4636
- const breakdown = score ? ` bm25=${score.bm25.toFixed(2)} path=${score.path.toFixed(2)} symbol=${score.symbol.toFixed(2)} graph=${score.graph.toFixed(2)} recency=${score.recency.toFixed(6)}` : "";
4708
+ const breakdown = score ? ` bm25=${score.bm25.toFixed(2)} path=${score.path.toFixed(2)} symbol=${score.symbol.toFixed(2)} graph=${score.graph.toFixed(2)} recency=${score.recency.toFixed(6)} diagnostic=${score.diagnostic.toFixed(3)}` : "";
4637
4709
  const hash4 = hit.provenance?.contentHash.slice(0, 12);
4638
4710
  return `[${hit.source} ${hit.score.toFixed(3)}${breakdown}${hash4 ? ` hash=${hash4}` : ""}]${symbol} ${path}:${hit.startLine}-${hit.endLine}`;
4639
4711
  }).join("\n");
@@ -5280,10 +5352,7 @@ var AnthropicProvider = class {
5280
5352
  name: block.name ?? "unknown",
5281
5353
  arguments: safeJsonArguments(block.input)
5282
5354
  })),
5283
- usage: {
5284
- ...data.usage?.input_tokens !== void 0 ? { inputTokens: data.usage.input_tokens } : {},
5285
- ...data.usage?.output_tokens !== void 0 ? { outputTokens: data.usage.output_tokens } : {}
5286
- },
5355
+ usage: normalizeAnthropicUsage(data.usage),
5287
5356
  ...data.stop_reason ? { stopReason: data.stop_reason } : {}
5288
5357
  };
5289
5358
  }
@@ -5324,6 +5393,8 @@ var AnthropicProvider = class {
5324
5393
  let content = "";
5325
5394
  let inputTokens;
5326
5395
  let outputTokens;
5396
+ let cachedInputTokens;
5397
+ let cacheWriteInputTokens;
5327
5398
  let stopReason;
5328
5399
  const calls = /* @__PURE__ */ new Map();
5329
5400
  for await (const event of parseServerSentEvents(response)) {
@@ -5333,6 +5404,13 @@ var AnthropicProvider = class {
5333
5404
  }
5334
5405
  if (chunk.usage?.input_tokens !== void 0) inputTokens = chunk.usage.input_tokens;
5335
5406
  if (chunk.usage?.output_tokens !== void 0) outputTokens = chunk.usage.output_tokens;
5407
+ const usage = chunk.usage ?? chunk.message?.usage;
5408
+ if (usage?.cache_read_input_tokens !== void 0) {
5409
+ cachedInputTokens = usage.cache_read_input_tokens;
5410
+ }
5411
+ if (usage?.cache_creation_input_tokens !== void 0) {
5412
+ cacheWriteInputTokens = usage.cache_creation_input_tokens;
5413
+ }
5336
5414
  if (chunk.delta?.stop_reason) stopReason = chunk.delta.stop_reason;
5337
5415
  const index = chunk.index ?? 0;
5338
5416
  if (chunk.type === "content_block_start" && chunk.content_block?.type === "text") {
@@ -5371,7 +5449,9 @@ var AnthropicProvider = class {
5371
5449
  })),
5372
5450
  usage: {
5373
5451
  ...inputTokens !== void 0 ? { inputTokens } : {},
5374
- ...outputTokens !== void 0 ? { outputTokens } : {}
5452
+ ...outputTokens !== void 0 ? { outputTokens } : {},
5453
+ ...cachedInputTokens !== void 0 ? { cachedInputTokens } : {},
5454
+ ...cacheWriteInputTokens !== void 0 ? { cacheWriteInputTokens } : {}
5375
5455
  },
5376
5456
  ...stopReason ? { stopReason } : {}
5377
5457
  }
@@ -5387,13 +5467,18 @@ function normalizeAnthropicResponse(data) {
5387
5467
  name: block.name ?? "unknown",
5388
5468
  arguments: safeJsonArguments(block.input)
5389
5469
  })),
5390
- usage: {
5391
- ...data.usage?.input_tokens !== void 0 ? { inputTokens: data.usage.input_tokens } : {},
5392
- ...data.usage?.output_tokens !== void 0 ? { outputTokens: data.usage.output_tokens } : {}
5393
- },
5470
+ usage: normalizeAnthropicUsage(data.usage),
5394
5471
  ...data.stop_reason ? { stopReason: data.stop_reason } : {}
5395
5472
  };
5396
5473
  }
5474
+ function normalizeAnthropicUsage(usage) {
5475
+ return {
5476
+ ...usage?.input_tokens !== void 0 ? { inputTokens: usage.input_tokens } : {},
5477
+ ...usage?.output_tokens !== void 0 ? { outputTokens: usage.output_tokens } : {},
5478
+ ...usage?.cache_read_input_tokens !== void 0 ? { cachedInputTokens: usage.cache_read_input_tokens } : {},
5479
+ ...usage?.cache_creation_input_tokens !== void 0 ? { cacheWriteInputTokens: usage.cache_creation_input_tokens } : {}
5480
+ };
5481
+ }
5397
5482
  function toAnthropicMessage(message2) {
5398
5483
  if (message2.role === "tool") {
5399
5484
  return {
@@ -5467,10 +5552,7 @@ var GeminiProvider = class {
5467
5552
  name: part.functionCall?.name ?? "unknown",
5468
5553
  arguments: safeJsonArguments(part.functionCall?.args)
5469
5554
  })),
5470
- usage: {
5471
- ...data.usageMetadata?.promptTokenCount !== void 0 ? { inputTokens: data.usageMetadata.promptTokenCount } : {},
5472
- ...data.usageMetadata?.candidatesTokenCount !== void 0 ? { outputTokens: data.usageMetadata.candidatesTokenCount } : {}
5473
- },
5555
+ usage: normalizeGeminiUsage(data.usageMetadata),
5474
5556
  ...candidate?.finishReason ? { stopReason: candidate.finishReason } : {}
5475
5557
  };
5476
5558
  }
@@ -5510,6 +5592,8 @@ var GeminiProvider = class {
5510
5592
  let content = "";
5511
5593
  let inputTokens;
5512
5594
  let outputTokens;
5595
+ let cachedInputTokens;
5596
+ let reasoningTokens;
5513
5597
  let stopReason;
5514
5598
  const toolCalls = [];
5515
5599
  for await (const event of parseServerSentEvents(response)) {
@@ -5521,6 +5605,12 @@ var GeminiProvider = class {
5521
5605
  if (chunk.usageMetadata?.candidatesTokenCount !== void 0) {
5522
5606
  outputTokens = chunk.usageMetadata.candidatesTokenCount;
5523
5607
  }
5608
+ if (chunk.usageMetadata?.cachedContentTokenCount !== void 0) {
5609
+ cachedInputTokens = chunk.usageMetadata.cachedContentTokenCount;
5610
+ }
5611
+ if (chunk.usageMetadata?.thoughtsTokenCount !== void 0) {
5612
+ reasoningTokens = chunk.usageMetadata.thoughtsTokenCount;
5613
+ }
5524
5614
  const candidate = chunk.candidates?.[0];
5525
5615
  if (candidate?.finishReason) stopReason = candidate.finishReason;
5526
5616
  for (const part of candidate?.content?.parts ?? []) {
@@ -5544,7 +5634,9 @@ var GeminiProvider = class {
5544
5634
  toolCalls,
5545
5635
  usage: {
5546
5636
  ...inputTokens !== void 0 ? { inputTokens } : {},
5547
- ...outputTokens !== void 0 ? { outputTokens } : {}
5637
+ ...outputTokens !== void 0 ? { outputTokens } : {},
5638
+ ...cachedInputTokens !== void 0 ? { cachedInputTokens } : {},
5639
+ ...reasoningTokens !== void 0 ? { reasoningTokens } : {}
5548
5640
  },
5549
5641
  ...stopReason ? { stopReason } : {}
5550
5642
  }
@@ -5561,13 +5653,18 @@ function normalizeGeminiResponse(data) {
5561
5653
  name: part.functionCall?.name ?? "unknown",
5562
5654
  arguments: safeJsonArguments(part.functionCall?.args)
5563
5655
  })),
5564
- usage: {
5565
- ...data.usageMetadata?.promptTokenCount !== void 0 ? { inputTokens: data.usageMetadata.promptTokenCount } : {},
5566
- ...data.usageMetadata?.candidatesTokenCount !== void 0 ? { outputTokens: data.usageMetadata.candidatesTokenCount } : {}
5567
- },
5656
+ usage: normalizeGeminiUsage(data.usageMetadata),
5568
5657
  ...candidate?.finishReason ? { stopReason: candidate.finishReason } : {}
5569
5658
  };
5570
5659
  }
5660
+ function normalizeGeminiUsage(usage) {
5661
+ return {
5662
+ ...usage?.promptTokenCount !== void 0 ? { inputTokens: usage.promptTokenCount } : {},
5663
+ ...usage?.candidatesTokenCount !== void 0 ? { outputTokens: usage.candidatesTokenCount } : {},
5664
+ ...usage?.cachedContentTokenCount !== void 0 ? { cachedInputTokens: usage.cachedContentTokenCount } : {},
5665
+ ...usage?.thoughtsTokenCount !== void 0 ? { reasoningTokens: usage.thoughtsTokenCount } : {}
5666
+ };
5667
+ }
5571
5668
  function toGeminiMessage(message2) {
5572
5669
  if (message2.role === "tool") {
5573
5670
  return {
@@ -5695,6 +5792,8 @@ var OpenAIProvider = class {
5695
5792
  let content = "";
5696
5793
  let inputTokens;
5697
5794
  let outputTokens;
5795
+ let cachedInputTokens;
5796
+ let reasoningTokens;
5698
5797
  let stopReason;
5699
5798
  const calls = /* @__PURE__ */ new Map();
5700
5799
  for await (const event of parseServerSentEvents(response)) {
@@ -5702,6 +5801,12 @@ var OpenAIProvider = class {
5702
5801
  const chunk = JSON.parse(event.data);
5703
5802
  if (chunk.usage?.prompt_tokens !== void 0) inputTokens = chunk.usage.prompt_tokens;
5704
5803
  if (chunk.usage?.completion_tokens !== void 0) outputTokens = chunk.usage.completion_tokens;
5804
+ if (chunk.usage?.prompt_tokens_details?.cached_tokens !== void 0) {
5805
+ cachedInputTokens = chunk.usage.prompt_tokens_details.cached_tokens;
5806
+ }
5807
+ if (chunk.usage?.completion_tokens_details?.reasoning_tokens !== void 0) {
5808
+ reasoningTokens = chunk.usage.completion_tokens_details.reasoning_tokens;
5809
+ }
5705
5810
  const choice = chunk.choices?.[0];
5706
5811
  if (choice?.finish_reason) stopReason = choice.finish_reason;
5707
5812
  const delta = choice?.delta;
@@ -5729,7 +5834,9 @@ var OpenAIProvider = class {
5729
5834
  })),
5730
5835
  usage: {
5731
5836
  ...inputTokens !== void 0 ? { inputTokens } : {},
5732
- ...outputTokens !== void 0 ? { outputTokens } : {}
5837
+ ...outputTokens !== void 0 ? { outputTokens } : {},
5838
+ ...cachedInputTokens !== void 0 ? { cachedInputTokens } : {},
5839
+ ...reasoningTokens !== void 0 ? { reasoningTokens } : {}
5733
5840
  },
5734
5841
  ...stopReason ? { stopReason } : {}
5735
5842
  }
@@ -5747,13 +5854,18 @@ function normalizeOpenAIResponse(data) {
5747
5854
  name: call.function?.name ?? "unknown",
5748
5855
  arguments: safeJsonArguments(call.function?.arguments)
5749
5856
  })),
5750
- usage: {
5751
- ...data.usage?.prompt_tokens !== void 0 ? { inputTokens: data.usage.prompt_tokens } : {},
5752
- ...data.usage?.completion_tokens !== void 0 ? { outputTokens: data.usage.completion_tokens } : {}
5753
- },
5857
+ usage: normalizeOpenAIUsage(data.usage),
5754
5858
  ...choice?.finish_reason ? { stopReason: choice.finish_reason } : {}
5755
5859
  };
5756
5860
  }
5861
+ function normalizeOpenAIUsage(usage) {
5862
+ return {
5863
+ ...usage?.prompt_tokens !== void 0 ? { inputTokens: usage.prompt_tokens } : {},
5864
+ ...usage?.completion_tokens !== void 0 ? { outputTokens: usage.completion_tokens } : {},
5865
+ ...usage?.prompt_tokens_details?.cached_tokens !== void 0 ? { cachedInputTokens: usage.prompt_tokens_details.cached_tokens } : {},
5866
+ ...usage?.completion_tokens_details?.reasoning_tokens !== void 0 ? { reasoningTokens: usage.completion_tokens_details.reasoning_tokens } : {}
5867
+ };
5868
+ }
5757
5869
  function toOpenAIMessage(message2) {
5758
5870
  if (message2.role === "tool") {
5759
5871
  return {
@@ -6330,6 +6442,9 @@ var sessionSchema = z5.object({
6330
6442
  outputSource: z5.enum(["actual", "estimated", "mixed", "unknown"]).optional(),
6331
6443
  actualInputTokens: z5.number().nonnegative().optional(),
6332
6444
  actualOutputTokens: z5.number().nonnegative().optional(),
6445
+ actualCachedInputTokens: z5.number().nonnegative().optional(),
6446
+ actualCacheWriteInputTokens: z5.number().nonnegative().optional(),
6447
+ actualReasoningTokens: z5.number().nonnegative().optional(),
6333
6448
  estimatedInputTokens: z5.number().nonnegative().optional(),
6334
6449
  estimatedOutputTokens: z5.number().nonnegative().optional()
6335
6450
  }).strict(),
@@ -6350,7 +6465,10 @@ var sessionSchema = z5.object({
6350
6465
  }).strict(),
6351
6466
  actual: z5.object({
6352
6467
  inputTokens: z5.number().nonnegative().optional(),
6353
- outputTokens: z5.number().nonnegative().optional()
6468
+ outputTokens: z5.number().nonnegative().optional(),
6469
+ cachedInputTokens: z5.number().nonnegative().optional(),
6470
+ cacheWriteInputTokens: z5.number().nonnegative().optional(),
6471
+ reasoningTokens: z5.number().nonnegative().optional()
6354
6472
  }).strict(),
6355
6473
  inputSource: z5.enum(["actual", "estimated"]),
6356
6474
  outputSource: z5.enum(["actual", "estimated"]),
@@ -8585,6 +8703,7 @@ function compact(value, limit) {
8585
8703
 
8586
8704
  // src/agent/completion-gate.ts
8587
8705
  import { createHash as createHash12 } from "node:crypto";
8706
+ import { isAbsolute as isAbsolute6, resolve as resolve17 } from "node:path";
8588
8707
 
8589
8708
  // src/tools/permissions.ts
8590
8709
  import { createHash as createHash11, createHmac, randomBytes } from "node:crypto";
@@ -8788,6 +8907,37 @@ function captureVerification(call, result, changeSequence, configuredCommands) {
8788
8907
  commandKey: createHash12("sha256").update(normalized).digest("hex")
8789
8908
  };
8790
8909
  }
8910
+ function verificationDiagnosticPaths(result, workspaceRoots) {
8911
+ if (result.ok || result.metadata?.sourceTruncated === true || typeof result.metadata?.exitCode !== "number" || result.metadata.exitCode === 0) return [];
8912
+ const roots = workspaceRoots.map((root) => resolve17(root));
8913
+ const cwd = typeof result.metadata.cwd === "string" ? resolve17(result.metadata.cwd) : void 0;
8914
+ const bases = cwd ? [cwd, ...roots] : roots;
8915
+ const candidates = /* @__PURE__ */ new Set();
8916
+ const pathPattern = String.raw`((?:[./][^\s():]+|[^\s():]+)\.[A-Za-z0-9]{1,10})`;
8917
+ const patterns = [
8918
+ new RegExp(`${pathPattern}\\(\\d+,\\d+\\):\\s*(?:error|warning|fatal)\\b`, "gimu"),
8919
+ new RegExp(`${pathPattern}:\\d+:\\d+:\\s*(?:error|warning|fatal)\\b`, "gimu"),
8920
+ new RegExp(`^\\s*(?:FAIL|ERROR)\\s+${pathPattern}`, "gimu")
8921
+ ];
8922
+ const output2 = result.content.slice(0, 2e5).split(/\r?\n/u).filter((line) => !/^\s*Command:/u.test(line)).join("\n");
8923
+ for (const pattern of patterns) {
8924
+ for (const match of output2.matchAll(pattern)) {
8925
+ const candidate = match[1];
8926
+ if (!candidate) continue;
8927
+ const path = resolveDiagnosticPath(candidate, bases, roots);
8928
+ if (path) candidates.add(path);
8929
+ if (candidates.size >= 16) return [...candidates];
8930
+ }
8931
+ }
8932
+ return [...candidates];
8933
+ }
8934
+ function resolveDiagnosticPath(candidate, bases, roots) {
8935
+ for (const base of bases) {
8936
+ const path = isAbsolute6(candidate) ? resolve17(candidate) : resolve17(base, candidate);
8937
+ if (roots.some((root) => isInside(root, path))) return path;
8938
+ }
8939
+ return void 0;
8940
+ }
8791
8941
  function buildRunCompletion(changedFiles, evidence, currentChangeSequence, mutationTracking = "complete", taskContract, audit = [], duplication) {
8792
8942
  const files = [...new Set(changedFiles)];
8793
8943
  const acceptance = taskContract ? buildAcceptance(taskContract, audit, evidence, currentChangeSequence) : void 0;
@@ -10500,6 +10650,7 @@ var AgentRunner = class {
10500
10650
  throw new Error("User input is too large; pass a focused request or attach files with @path.");
10501
10651
  }
10502
10652
  this.running = true;
10653
+ this.contextEngine.resetDiagnostics?.();
10503
10654
  const emit = async (event) => {
10504
10655
  await options.onEvent?.(event);
10505
10656
  };
@@ -10526,7 +10677,13 @@ var AgentRunner = class {
10526
10677
  this.changeSequence,
10527
10678
  this.config.agent.verifyCommands
10528
10679
  );
10529
- if (evidence) verificationEvidence.push(evidence);
10680
+ if (evidence) {
10681
+ verificationEvidence.push(evidence);
10682
+ this.contextEngine.recordDiagnostics?.({
10683
+ commandKey: evidence.commandKey,
10684
+ paths: verificationDiagnosticPaths(result, this.workspace.roots)
10685
+ });
10686
+ }
10530
10687
  };
10531
10688
  const completionReport = () => {
10532
10689
  const completion = buildRunCompletion(
@@ -10722,6 +10879,9 @@ var AgentRunner = class {
10722
10879
  const { inputTokens, outputTokens } = turnUsage;
10723
10880
  const actualInputTokens = validTokenCount(response.usage?.inputTokens);
10724
10881
  const actualOutputTokens = validTokenCount(response.usage?.outputTokens);
10882
+ const actualCachedInputTokens = validTokenCount(response.usage?.cachedInputTokens);
10883
+ const actualCacheWriteInputTokens = validTokenCount(response.usage?.cacheWriteInputTokens);
10884
+ const actualReasoningTokens = validTokenCount(response.usage?.reasoningTokens);
10725
10885
  const receipt = recordTokenLedger(this.session, {
10726
10886
  requestId: userMessage.id,
10727
10887
  turn,
@@ -10732,7 +10892,10 @@ var AgentRunner = class {
10732
10892
  },
10733
10893
  actual: {
10734
10894
  ...actualInputTokens === void 0 ? {} : { inputTokens: actualInputTokens },
10735
- ...actualOutputTokens === void 0 ? {} : { outputTokens: actualOutputTokens }
10895
+ ...actualOutputTokens === void 0 ? {} : { outputTokens: actualOutputTokens },
10896
+ ...actualCachedInputTokens === void 0 ? {} : { cachedInputTokens: actualCachedInputTokens },
10897
+ ...actualCacheWriteInputTokens === void 0 ? {} : { cacheWriteInputTokens: actualCacheWriteInputTokens },
10898
+ ...actualReasoningTokens === void 0 ? {} : { reasoningTokens: actualReasoningTokens }
10736
10899
  },
10737
10900
  inputSource: actualInputTokens === void 0 ? "estimated" : "actual",
10738
10901
  outputSource: actualOutputTokens === void 0 ? "estimated" : "actual",
@@ -10751,7 +10914,10 @@ var AgentRunner = class {
10751
10914
  outputSource: this.session.usage.outputSource ?? "unknown",
10752
10915
  actual: {
10753
10916
  inputTokens: this.session.usage.actualInputTokens ?? 0,
10754
- outputTokens: this.session.usage.actualOutputTokens ?? 0
10917
+ outputTokens: this.session.usage.actualOutputTokens ?? 0,
10918
+ ...this.session.usage.actualCachedInputTokens === void 0 ? {} : { cachedInputTokens: this.session.usage.actualCachedInputTokens },
10919
+ ...this.session.usage.actualCacheWriteInputTokens === void 0 ? {} : { cacheWriteInputTokens: this.session.usage.actualCacheWriteInputTokens },
10920
+ ...this.session.usage.actualReasoningTokens === void 0 ? {} : { reasoningTokens: this.session.usage.actualReasoningTokens }
10755
10921
  },
10756
10922
  estimated: {
10757
10923
  inputTokens: this.session.usage.estimatedInputTokens ?? 0,
@@ -11452,6 +11618,18 @@ function recordTokenUsage(session, providerUsage, estimatedInputTokens, estimate
11452
11618
  } else {
11453
11619
  session.usage.estimatedOutputTokens = (session.usage.estimatedOutputTokens ?? 0) + outputTokens;
11454
11620
  }
11621
+ const cachedInputActual = validTokenCount(providerUsage?.cachedInputTokens);
11622
+ const cacheWriteInputActual = validTokenCount(providerUsage?.cacheWriteInputTokens);
11623
+ const reasoningActual = validTokenCount(providerUsage?.reasoningTokens);
11624
+ if (cachedInputActual !== void 0) {
11625
+ session.usage.actualCachedInputTokens = (session.usage.actualCachedInputTokens ?? 0) + cachedInputActual;
11626
+ }
11627
+ if (cacheWriteInputActual !== void 0) {
11628
+ session.usage.actualCacheWriteInputTokens = (session.usage.actualCacheWriteInputTokens ?? 0) + cacheWriteInputActual;
11629
+ }
11630
+ if (reasoningActual !== void 0) {
11631
+ session.usage.actualReasoningTokens = (session.usage.actualReasoningTokens ?? 0) + reasoningActual;
11632
+ }
11455
11633
  session.usage.inputSource = mergeMeasurementSource(
11456
11634
  priorInputSource,
11457
11635
  inputActual === void 0 ? "estimated" : "actual",
@@ -11843,7 +12021,7 @@ function numeric(...values) {
11843
12021
  // src/agent/team-store.ts
11844
12022
  import { createHash as createHash16, randomUUID as randomUUID13 } from "node:crypto";
11845
12023
  import { lstat as lstat18, readFile as readFile17, readdir as readdir7, rm as rm3 } from "node:fs/promises";
11846
- import { join as join16, resolve as resolve17 } from "node:path";
12024
+ import { join as join16, resolve as resolve18 } from "node:path";
11847
12025
  import { z as z18 } from "zod";
11848
12026
  var runIdSchema = z18.string().uuid();
11849
12027
  var hashSchema = z18.string().regex(/^[a-f0-9]{64}$/u);
@@ -11927,9 +12105,9 @@ var TeamRunStore = class {
11927
12105
  managedDirectory;
11928
12106
  writes = Promise.resolve();
11929
12107
  constructor(workspace, directory) {
11930
- this.workspace = resolve17(workspace);
12108
+ this.workspace = resolve18(workspace);
11931
12109
  this.managedDirectory = directory === void 0;
11932
- this.directory = directory ? resolve17(directory) : join16(resolveProjectNamespaceSync(this.workspace).active, "team-runs");
12110
+ this.directory = directory ? resolve18(directory) : join16(resolveProjectNamespaceSync(this.workspace).active, "team-runs");
11933
12111
  }
11934
12112
  async create(input2) {
11935
12113
  const now = (/* @__PURE__ */ new Date()).toISOString();
@@ -12016,7 +12194,7 @@ var TeamRunStore = class {
12016
12194
  const path = join16(this.runDirectory(runId), "manifest.json");
12017
12195
  await this.assertRegularFile(path);
12018
12196
  const manifest = manifestSchema2.parse(JSON.parse(await readFile17(path, "utf8")));
12019
- if (manifest.id !== runId || resolve17(manifest.workspace) !== this.workspace) {
12197
+ if (manifest.id !== runId || resolve18(manifest.workspace) !== this.workspace) {
12020
12198
  throw new Error("Team run manifest identity does not match its location.");
12021
12199
  }
12022
12200
  if (verify) {
@@ -12147,7 +12325,7 @@ var TeamRunStore = class {
12147
12325
  if (!info.isDirectory() || info.isSymbolicLink()) throw new Error("Team run storage is not a regular directory.");
12148
12326
  }
12149
12327
  async assertRegularFile(path) {
12150
- await assertNoSymlinkPath(this.workspace, resolve17(path, ".."));
12328
+ await assertNoSymlinkPath(this.workspace, resolve18(path, ".."));
12151
12329
  const info = await lstat18(path);
12152
12330
  if (!info.isFile() || info.isSymbolicLink()) throw new Error(`Team run file is not a regular file: ${path}`);
12153
12331
  }
@@ -12195,7 +12373,7 @@ function resolveAgentModelRoute(team, parent, profile) {
12195
12373
  import { createHash as createHash17 } from "node:crypto";
12196
12374
  import { lstat as lstat19, mkdtemp, realpath as realpath7, rm as rm4 } from "node:fs/promises";
12197
12375
  import { tmpdir as tmpdir2 } from "node:os";
12198
- import { isAbsolute as isAbsolute6, join as join17, resolve as resolve18 } from "node:path";
12376
+ import { isAbsolute as isAbsolute7, join as join17, resolve as resolve19 } from "node:path";
12199
12377
  var WriterLaneApplyError = class extends Error {
12200
12378
  constructor(message2, attempted, cause) {
12201
12379
  super(message2, cause === void 0 ? void 0 : { cause });
@@ -12208,8 +12386,8 @@ var WriterLane = class {
12208
12386
  workspace;
12209
12387
  constructor(workspace, workspaceRoots) {
12210
12388
  this.workspace = new WorkspaceAccess([
12211
- resolve18(workspace),
12212
- ...workspaceRoots.map((root) => resolve18(root))
12389
+ resolve19(workspace),
12390
+ ...workspaceRoots.map((root) => resolve19(root))
12213
12391
  ]);
12214
12392
  }
12215
12393
  async createDraft(maxPatchBytes, operation, signal) {
@@ -12414,7 +12592,7 @@ var WriterLane = class {
12414
12592
  const files = unique2(parseNumstatPaths(numstat.stdout));
12415
12593
  if (!files.length) throw new Error("Writer patch contains no file changes.");
12416
12594
  for (const file of files) {
12417
- if (isAbsolute6(file) || file === ".git" || file.startsWith(".git/") || file.includes("\0")) {
12595
+ if (isAbsolute7(file) || file === ".git" || file.startsWith(".git/") || file.includes("\0")) {
12418
12596
  throw new Error(`Writer patch contains an unsafe path: ${file}`);
12419
12597
  }
12420
12598
  await this.workspace.resolvePath(join17(repository.root, file), { allowMissing: true });
@@ -12432,7 +12610,7 @@ var WriterLane = class {
12432
12610
  if (topLevel.exitCode !== 0 || !topLevel.stdout.trim()) {
12433
12611
  throw new Error("The primary workspace must be a Git repository root for writer lanes.");
12434
12612
  }
12435
- const discoveredRoot = resolve18(topLevel.stdout.trim());
12613
+ const discoveredRoot = resolve19(topLevel.stdout.trim());
12436
12614
  if (await realpath7(discoveredRoot) !== await realpath7(root)) {
12437
12615
  throw new Error("The primary workspace must be the Git repository root for writer lanes.");
12438
12616
  }
@@ -12441,7 +12619,7 @@ var WriterLane = class {
12441
12619
  if (common.exitCode !== 0 || !common.stdout.trim()) {
12442
12620
  throw new Error(`Unable to resolve the Git common directory: ${processDetail(common)}`);
12443
12621
  }
12444
- const commonDirectory = await realpath7(isAbsolute6(common.stdout.trim()) ? common.stdout.trim() : resolve18(repositoryRoot, common.stdout.trim()));
12622
+ const commonDirectory = await realpath7(isAbsolute7(common.stdout.trim()) ? common.stdout.trim() : resolve19(repositoryRoot, common.stdout.trim()));
12445
12623
  return { root: repositoryRoot, commonDirectory, runtime };
12446
12624
  }
12447
12625
  async head(repository) {
@@ -12453,7 +12631,7 @@ var WriterLane = class {
12453
12631
  return value;
12454
12632
  }
12455
12633
  async cleanupWorktree(repository, worktree, added) {
12456
- const physicalWorktree = await realpath7(worktree).catch(() => resolve18(worktree));
12634
+ const physicalWorktree = await realpath7(worktree).catch(() => resolve19(worktree));
12457
12635
  if (added) {
12458
12636
  await runIsolatedGit(repository.runtime, [
12459
12637
  "worktree",
@@ -14379,7 +14557,7 @@ function formatResultDetail(result, paint = chalk2, glyphs = resolveCliGlyphs())
14379
14557
  }
14380
14558
 
14381
14559
  // src/cli/namespace-leases.ts
14382
- import { resolve as resolve19 } from "node:path";
14560
+ import { resolve as resolve20 } from "node:path";
14383
14561
  function cliNamespaceLeaseScopes(actionCommand) {
14384
14562
  const names = commandNames(actionCommand);
14385
14563
  const topLevel = names[1];
@@ -14401,7 +14579,7 @@ async function acquireCliNamespaceLeases(actionCommand) {
14401
14579
  const scopes = cliNamespaceLeaseScopes(actionCommand);
14402
14580
  const localOptions = actionCommand.opts();
14403
14581
  const globalOptions = actionCommand.optsWithGlobals();
14404
- const workspace = resolve19(localOptions.workspace ?? globalOptions.workspace ?? process.cwd());
14582
+ const workspace = resolve20(localOptions.workspace ?? globalOptions.workspace ?? process.cwd());
14405
14583
  const targets = scopes.map((scope) => scope === "project" ? projectNamespacePaths(workspace).canonical : homeNamespacePaths().canonical);
14406
14584
  const leases = [];
14407
14585
  try {
@@ -14653,7 +14831,7 @@ function graphemes(value) {
14653
14831
 
14654
14832
  // src/ui/theme.ts
14655
14833
  import { lstat as lstat20, readdir as readdir8, readFile as readFile18 } from "node:fs/promises";
14656
- import { basename as basename10, join as join19, resolve as resolve20 } from "node:path";
14834
+ import { basename as basename10, join as join19, resolve as resolve21 } from "node:path";
14657
14835
  import React, { createContext, useContext } from "react";
14658
14836
  function defineTheme(seed) {
14659
14837
  return {
@@ -14775,7 +14953,7 @@ async function reloadUserThemes(directory = userThemeDirectory()) {
14775
14953
  userThemeNames.clear();
14776
14954
  const loaded = [];
14777
14955
  const errors = [];
14778
- const resolvedDirectory = resolve20(directory);
14956
+ const resolvedDirectory = resolve21(directory);
14779
14957
  let entries;
14780
14958
  try {
14781
14959
  entries = await readdir8(resolvedDirectory, { encoding: "utf8" });
@@ -17239,7 +17417,7 @@ function SkeinApp({ runner, config, extensions, initialPrompt, askMode = false,
17239
17417
  return () => clearInterval(timer);
17240
17418
  }, [busy]);
17241
17419
  const requestPermission = useCallback((call, category) => {
17242
- return new Promise((resolve25) => setPermission({ call, category, resolve: resolve25 }));
17420
+ return new Promise((resolve26) => setPermission({ call, category, resolve: resolve26 }));
17243
17421
  }, []);
17244
17422
  const onEvent = useCallback((event) => {
17245
17423
  switch (event.type) {
@@ -18075,8 +18253,8 @@ function SkeinApp({ runner, config, extensions, initialPrompt, askMode = false,
18075
18253
  }, [append]);
18076
18254
  function settlePermission(grant, stop = false) {
18077
18255
  if (!permission) return;
18078
- const { call, category, resolve: resolve25 } = permission;
18079
- resolve25(grant);
18256
+ const { call, category, resolve: resolve26 } = permission;
18257
+ resolve26(grant);
18080
18258
  setPermission(void 0);
18081
18259
  if (grant === "session") {
18082
18260
  append({
@@ -19411,7 +19589,7 @@ async function runFirstRunOnboarding(initialConfig, options = {}) {
19411
19589
  }
19412
19590
 
19413
19591
  // src/runtime/extensions.ts
19414
- import { resolve as resolve23 } from "node:path";
19592
+ import { resolve as resolve24 } from "node:path";
19415
19593
 
19416
19594
  // src/mcp/manager.ts
19417
19595
  import { Client } from "@modelcontextprotocol/sdk/client/index.js";
@@ -19624,7 +19802,7 @@ function isRecord2(value) {
19624
19802
 
19625
19803
  // src/mcp/validation.ts
19626
19804
  import { stat as stat11, realpath as realpath8 } from "node:fs/promises";
19627
- import { isAbsolute as isAbsolute7, resolve as resolve21 } from "node:path";
19805
+ import { isAbsolute as isAbsolute8, resolve as resolve22 } from "node:path";
19628
19806
  var SERVER_NAME = /^[a-z][a-z0-9_-]{0,63}$/;
19629
19807
  var ENV_NAME = /^[A-Za-z_][A-Za-z0-9_]*$/;
19630
19808
  var HEADER_NAME = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;
@@ -19696,9 +19874,9 @@ async function validateCwd(configured, options) {
19696
19874
  if (configured !== void 0 && (configured.length > 4e3 || CONTROL_CHARACTERS.test(configured))) {
19697
19875
  throw new Error("MCP working directory is invalid or too long");
19698
19876
  }
19699
- const defaultCwd = resolve21(options.cwd ?? process.cwd());
19700
- const candidate = configured ? isAbsolute7(configured) ? resolve21(configured) : resolve21(defaultCwd, configured) : defaultCwd;
19701
- const roots = options.workspaceRoots?.length ? options.workspaceRoots.map((root) => resolve21(root)) : [defaultCwd];
19877
+ const defaultCwd = resolve22(options.cwd ?? process.cwd());
19878
+ const candidate = configured ? isAbsolute8(configured) ? resolve22(configured) : resolve22(defaultCwd, configured) : defaultCwd;
19879
+ const roots = options.workspaceRoots?.length ? options.workspaceRoots.map((root) => resolve22(root)) : [defaultCwd];
19702
19880
  const resolvedCandidate = await realpath8(candidate).catch(() => {
19703
19881
  throw new Error(`MCP working directory does not exist: ${candidate}`);
19704
19882
  });
@@ -20352,7 +20530,7 @@ function scopeKey(scope, context) {
20352
20530
  // src/skills/catalog.ts
20353
20531
  import { lstat as lstat21, readFile as readFile20, readdir as readdir9, realpath as realpath9 } from "node:fs/promises";
20354
20532
  import { homedir as homedir4 } from "node:os";
20355
- import { basename as basename12, join as join21, resolve as resolve22 } from "node:path";
20533
+ import { basename as basename12, join as join21, resolve as resolve23 } from "node:path";
20356
20534
  import { parse as parseYaml3 } from "yaml";
20357
20535
  var SkillCatalog = class {
20358
20536
  constructor(workspace, config) {
@@ -20421,14 +20599,14 @@ ${skill.content}
20421
20599
  }
20422
20600
  function discoveryLocations(workspace, configured) {
20423
20601
  const home = homedir4();
20424
- const workspaceRoot = resolve22(workspace);
20602
+ const workspaceRoot = resolve23(workspace);
20425
20603
  return [
20426
20604
  { path: join21(home, ".agents", "skills"), scope: "user", trusted: true },
20427
20605
  { path: join21(home, ".claude", "skills"), scope: "user", trusted: true },
20428
20606
  { path: join21(home, ".augment", "skills"), scope: "user", trusted: true },
20429
20607
  { path: join21(resolveHomeNamespace(), "skills"), scope: "user", trusted: true },
20430
20608
  ...configured.map((path) => {
20431
- const resolved = resolve22(workspaceRoot, path);
20609
+ const resolved = resolve23(workspaceRoot, path);
20432
20610
  return {
20433
20611
  path: resolved,
20434
20612
  scope: "configured",
@@ -20457,7 +20635,7 @@ async function readMetadata(path) {
20457
20635
  const { frontmatter } = splitFrontmatter(raw);
20458
20636
  if (!frontmatter) return void 0;
20459
20637
  const parsed = parseYaml3(frontmatter);
20460
- const name = typeof parsed?.name === "string" ? parsed.name.trim() : basename12(resolve22(path, ".."));
20638
+ const name = typeof parsed?.name === "string" ? parsed.name.trim() : basename12(resolve23(path, ".."));
20461
20639
  const description = typeof parsed?.description === "string" ? parsed.description.trim() : "";
20462
20640
  if (!/^[a-z][a-z0-9_-]{0,63}$/.test(name) || !description || description.length > 1e3) {
20463
20641
  return void 0;
@@ -20478,7 +20656,7 @@ async function safeRead(path, maxBytes) {
20478
20656
  try {
20479
20657
  const info = await lstat21(path);
20480
20658
  if (!info.isFile() || info.isSymbolicLink() || info.size > maxBytes) return void 0;
20481
- const parent = resolve22(path, "..");
20659
+ const parent = resolve23(path, "..");
20482
20660
  const resolvedParent = await realpath9(parent);
20483
20661
  const resolvedPath = await realpath9(path);
20484
20662
  if (!resolvedPath.startsWith(`${resolvedParent}/`)) return void 0;
@@ -20663,7 +20841,7 @@ var ExtensionRuntime = class _ExtensionRuntime {
20663
20841
  delegation;
20664
20842
  initialized = false;
20665
20843
  static async create(config, registry, options = {}) {
20666
- const runtime = new _ExtensionRuntime(config, resolve23(config.workspaceRoots[0] ?? process.cwd()), options);
20844
+ const runtime = new _ExtensionRuntime(config, resolve24(config.workspaceRoots[0] ?? process.cwd()), options);
20667
20845
  try {
20668
20846
  await runtime.initialize(registry, options.signal);
20669
20847
  return runtime;
@@ -20868,15 +21046,15 @@ function upgradeCommandOverride(env = process.env) {
20868
21046
  return trimmed ? trimmed : void 0;
20869
21047
  }
20870
21048
  function runUpgrade(plan) {
20871
- return new Promise((resolve25) => {
21049
+ return new Promise((resolve26) => {
20872
21050
  const child = spawn2(plan.command, plan.args, {
20873
21051
  stdio: "inherit",
20874
21052
  shell: plan.shell ?? false
20875
21053
  });
20876
- child.on("error", () => resolve25({ ok: false, exitCode: 127, display: plan.display }));
21054
+ child.on("error", () => resolve26({ ok: false, exitCode: 127, display: plan.display }));
20877
21055
  child.on("close", (code) => {
20878
21056
  const exitCode = code ?? 1;
20879
- resolve25({ ok: exitCode === 0, exitCode, display: plan.display });
21057
+ resolve26({ ok: exitCode === 0, exitCode, display: plan.display });
20880
21058
  });
20881
21059
  });
20882
21060
  }
@@ -21138,7 +21316,7 @@ sessionCommand.command("export <id>").description("Export a session as Markdown"
21138
21316
  const store = new SessionStore(workspaceOption(options.workspace));
21139
21317
  const session = await requireSessionSelector(store, id);
21140
21318
  const markdown = sessionMarkdown(session);
21141
- if (options.output) await writeFile3(resolve24(options.output), markdown, "utf8");
21319
+ if (options.output) await writeFile3(resolve25(options.output), markdown, "utf8");
21142
21320
  else process.stdout.write(markdown);
21143
21321
  });
21144
21322
  var checkpointCommand = program.command("checkpoint").description("Inspect and restore pre-mutation snapshots");
@@ -21515,7 +21693,7 @@ async function runChat(prompts, options) {
21515
21693
  const stdinPrompt = !process.stdin.isTTY ? await readStdin() : "";
21516
21694
  const firstPrompt = [...prompts, stdinPrompt].filter(Boolean).join("\n\n").trim();
21517
21695
  if (shouldPrint && !firstPrompt) throw new Error("Provide a prompt argument or pipe input on stdin.");
21518
- const workspace = resolve24(options.workspace);
21696
+ const workspace = resolve25(options.workspace);
21519
21697
  let config = await runtimeConfig(workspace, options);
21520
21698
  let completedOnboarding = false;
21521
21699
  if (!shouldPrint && needsFirstRunOnboarding(config)) {
@@ -21740,14 +21918,14 @@ async function runAgentSetup(options) {
21740
21918
  `);
21741
21919
  }
21742
21920
  async function runtimeConfig(workspaceInput, options) {
21743
- const workspace = resolve24(workspaceInput);
21921
+ const workspace = resolve25(workspaceInput);
21744
21922
  const loaded = await loadConfig(workspace, options.config, {
21745
21923
  trustProjectConfig: options.trustProjectConfig === true
21746
21924
  });
21747
21925
  const roots = [
21748
21926
  workspace,
21749
21927
  ...loaded.workspaceRoots,
21750
- ...(options.addWorkspace ?? []).map((root) => resolve24(workspace, root))
21928
+ ...(options.addWorkspace ?? []).map((root) => resolve25(workspace, root))
21751
21929
  ];
21752
21930
  const provider = options.provider ? validateProvider(options.provider) : loaded.model.provider;
21753
21931
  return {
@@ -21903,7 +22081,7 @@ function collect(value, previous) {
21903
22081
  }
21904
22082
  function workspaceOption(value) {
21905
22083
  const rootOptions = program.opts();
21906
- return resolve24(value ?? rootOptions.workspace ?? process.cwd());
22084
+ return resolve25(value ?? rootOptions.workspace ?? process.cwd());
21907
22085
  }
21908
22086
  function runtimeOptions(options) {
21909
22087
  const root = program.opts();