@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/README.md +17 -11
- package/dist/cli.js +263 -85
- package/dist/cli.js.map +1 -1
- package/docs/NEXT_STEPS.md +29 -9
- package/package.json +8 -1
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
|
|
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.
|
|
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((
|
|
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
|
-
|
|
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
|
|
3943
|
-
|
|
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
|
-
|
|
4489
|
-
const
|
|
4490
|
-
|
|
4491
|
-
|
|
4492
|
-
|
|
4493
|
-
|
|
4494
|
-
base,
|
|
4495
|
-
|
|
4496
|
-
|
|
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)
|
|
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
|
|
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 =
|
|
12108
|
+
this.workspace = resolve18(workspace);
|
|
11931
12109
|
this.managedDirectory = directory === void 0;
|
|
11932
|
-
this.directory = directory ?
|
|
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 ||
|
|
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,
|
|
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
|
|
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
|
-
|
|
12212
|
-
...workspaceRoots.map((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 (
|
|
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 =
|
|
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(
|
|
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(() =>
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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((
|
|
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:
|
|
18079
|
-
|
|
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
|
|
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
|
|
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 =
|
|
19700
|
-
const candidate = configured ?
|
|
19701
|
-
const roots = options.workspaceRoots?.length ? options.workspaceRoots.map((root) =>
|
|
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
|
|
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 =
|
|
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 =
|
|
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(
|
|
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 =
|
|
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,
|
|
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((
|
|
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", () =>
|
|
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
|
-
|
|
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(
|
|
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 =
|
|
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 =
|
|
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) =>
|
|
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
|
|
22084
|
+
return resolve25(value ?? rootOptions.workspace ?? process.cwd());
|
|
21907
22085
|
}
|
|
21908
22086
|
function runtimeOptions(options) {
|
|
21909
22087
|
const root = program.opts();
|