pi-smart-compact 9.6.0 → 9.6.1
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/ARCHITECTURE.md +7 -5
- package/CHANGELOG.md +20 -0
- package/README.md +3 -2
- package/dist/app/run-context.d.ts +3 -3
- package/dist/app/run-context.d.ts.map +1 -1
- package/dist/app/steps/tier.d.ts +5 -4
- package/dist/app/steps/tier.d.ts.map +1 -1
- package/dist/constants.d.ts +1 -1
- package/dist/domain/tool-semantics.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +249 -43
- package/dist/infra/ai-messages.d.ts.map +1 -1
- package/dist/phases/explore.d.ts.map +1 -1
- package/dist/phases/synthesize.d.ts +5 -0
- package/dist/phases/synthesize.d.ts.map +1 -1
- package/dist/phases/verify.d.ts.map +1 -1
- package/dist/provider-eval.js +125 -22
- package/dist/provider-scenario-eval.js +130 -25
- package/dist/telemetry-report.js +125 -22
- package/dist/ui/overlays.d.ts.map +1 -1
- package/dist/utils/file-needles.d.ts +24 -0
- package/dist/utils/file-needles.d.ts.map +1 -1
- package/dist/utils/file-ref-detect.d.ts +6 -1
- package/dist/utils/file-ref-detect.d.ts.map +1 -1
- package/dist/utils/helpers.d.ts +1 -0
- package/dist/utils/helpers.d.ts.map +1 -1
- package/package.json +4 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-messages.d.ts","sourceRoot":"","sources":["../../src/infra/ai-messages.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAEzD;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"ai-messages.d.ts","sourceRoot":"","sources":["../../src/infra/ai-messages.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAEzD;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,OAAO,EAAE,CAIpE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,QAAQ,EAAE,cAAc,GAAG,UAAU,EAAE,CAE3F"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"explore.d.ts","sourceRoot":"","sources":["../../src/phases/explore.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,KAAK,EACL,GAAG,EAKH,eAAe,EAChB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,KAAK,EACV,UAAU,EACV,oBAAoB,EACpB,iBAAiB,EAElB,MAAM,aAAa,CAAC;AAcrB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAIjE,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAuBpD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,oBAAoB,GAAG,OAAO,CAqBvE;
|
|
1
|
+
{"version":3,"file":"explore.d.ts","sourceRoot":"","sources":["../../src/phases/explore.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,KAAK,EACL,GAAG,EAKH,eAAe,EAChB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,KAAK,EACV,UAAU,EACV,oBAAoB,EACpB,iBAAiB,EAElB,MAAM,aAAa,CAAC;AAcrB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAIjE,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAuBpD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,oBAAoB,GAAG,OAAO,CAqBvE;AAsHD,wBAAgB,sBAAsB,CACpC,IAAI,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,EAC1D,WAAW,EAAE,UAAU,EAAE,EACzB,QAAQ,iBAAuB,GAC9B,MAAM,CA6MR;AAED,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,UAAU,EAAE,GACxB,iBAAiB,CAkDnB;AA6DD,wBAAgB,gCAAgC,CAC9C,MAAM,EAAE,OAAO,EACf,WAAW,EAAE,UAAU,EAAE,GACxB,iBAAiB,CAgCnB;AAED,wBAAgB,yBAAyB,CACvC,WAAW,EAAE,UAAU,EAAE,GACxB,iBAAiB,CAWnB;AAED;;;;;;;GAOG;AACH,wBAAsB,mBAAmB,CACvC,WAAW,EAAE,UAAU,EAAE,EACzB,UAAU,EAAE,oBAAoB,EAChC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EACjB,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,eAAe,CAAA;CAAE,EACnD,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,MAAM,CAAC,EAAE,WAAW,EACpB,SAAS,SAAyB,EAClC,MAAM,CAAC,EAAE,CACP,GAAG,EAAE,MAAM,EACX,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,KAC5C,IAAI,EACT,QAAQ,CAAC,EAAE,oBAAoB,GAC9B,OAAO,CAAC;IACT,MAAM,EAAE,iBAAiB,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,OAAO,CAAC;CACxB,CAAC,CAkTD"}
|
|
@@ -5,6 +5,11 @@ import type { Model, Api, ProviderHeaders } from "@earendil-works/pi-ai";
|
|
|
5
5
|
import type { LlmMessage, LlmChunk, ChunkSummary, StructuredExtraction, ExplorationReport, ProfileConfig, CompactionState } from "../types.ts";
|
|
6
6
|
import { type TokenEstimator } from "../utils/tokens.ts";
|
|
7
7
|
import type { SmartCompactServices } from "../infra/services.ts";
|
|
8
|
+
/** A provider response completed, but did not satisfy the batch-output contract. */
|
|
9
|
+
export declare class BatchSummaryFormatError extends Error {
|
|
10
|
+
readonly name = "BatchSummaryFormatError";
|
|
11
|
+
constructor(reason: string);
|
|
12
|
+
}
|
|
8
13
|
export declare function chunkLlmMessages(msgs: LlmMessage[], boundaries: import("../types.ts").TopicBoundary[], pc: ProfileConfig, estimator?: TokenEstimator, focus?: string): LlmChunk[];
|
|
9
14
|
export declare function singlePassCompact(convText: string, extraction: StructuredExtraction, report: ExplorationReport | null, prevContext: string, model: Model<Api>, auth: {
|
|
10
15
|
apiKey: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"synthesize.d.ts","sourceRoot":"","sources":["../../src/phases/synthesize.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACzE,OAAO,KAAK,EACX,UAAU,EACV,QAAQ,EACR,YAAY,EACZ,oBAAoB,EACpB,iBAAiB,EACjB,aAAa,EACb,eAAe,EACf,MAAM,aAAa,CAAC;AAYrB,OAAO,EAGN,KAAK,cAAc,EACnB,MAAM,oBAAoB,CAAC;AAU5B,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"synthesize.d.ts","sourceRoot":"","sources":["../../src/phases/synthesize.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACzE,OAAO,KAAK,EACX,UAAU,EACV,QAAQ,EACR,YAAY,EACZ,oBAAoB,EACpB,iBAAiB,EACjB,aAAa,EACb,eAAe,EACf,MAAM,aAAa,CAAC;AAYrB,OAAO,EAGN,KAAK,cAAc,EACnB,MAAM,oBAAoB,CAAC;AAU5B,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AA0BjE,oFAAoF;AACpF,qBAAa,uBAAwB,SAAQ,KAAK;IACjD,QAAQ,CAAC,IAAI,6BAA6B;IAE1C,YAAY,MAAM,EAAE,MAAM,EAEzB;CACD;AAoRD,wBAAgB,gBAAgB,CAC/B,IAAI,EAAE,UAAU,EAAE,EAClB,UAAU,EAAE,OAAO,aAAa,EAAE,aAAa,EAAE,EACjD,EAAE,EAAE,aAAa,EACjB,SAAS,GAAE,cAAqC,EAChD,KAAK,CAAC,EAAE,MAAM,GACZ,QAAQ,EAAE,CAwGZ;AAED,wBAAsB,iBAAiB,CACtC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,oBAAoB,EAChC,MAAM,EAAE,iBAAiB,GAAG,IAAI,EAChC,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EACjB,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,eAAe,CAAA;CAAE,EACnD,YAAY,EAAE,MAAM,EACpB,MAAM,CAAC,EAAE,WAAW,EACpB,QAAQ,CAAC,EAAE,oBAAoB,EAC/B,KAAK,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,CAAC,CAAA;CAAE,CAAC,CA2D3C;AAED,wBAAsB,cAAc,CACnC,KAAK,EAAE,QAAQ,EAAE,EACjB,UAAU,EAAE,oBAAoB,EAChC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EACjB,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,eAAe,CAAA;CAAE,EACnD,MAAM,CAAC,EAAE,WAAW,EACpB,QAAQ,CAAC,EAAE,oBAAoB,EAC/B,eAAe,CAAC,EAAE,MAAM,EACxB,UAAU,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,YAAY,EAAE,CAAC,CAyKzB;AA6BD,wBAAsB,WAAW,CAChC,SAAS,EAAE,YAAY,EAAE,EACzB,UAAU,EAAE,oBAAoB,EAChC,MAAM,EAAE,iBAAiB,GAAG,IAAI,EAChC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EACjB,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,eAAe,CAAA;CAAE,EACnD,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,MAAM,CAAC,EAAE,WAAW,EACpB,QAAQ,CAAC,EAAE,oBAAoB,EAC/B,KAAK,CAAC,EAAE,MAAM,EACd,UAAU,GAAE,eAAe,GAAG,IAAW,GACvC,OAAO,CAAC,MAAM,CAAC,CAmDjB;AAED,wBAAgB,gBAAgB,CAC/B,SAAS,EAAE,YAAY,EAAE,EACzB,UAAU,EAAE,oBAAoB,EAChC,QAAQ,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAO,EAChD,YAAY,GAAE,MAAc,EAC5B,UAAU,GAAE,eAAe,GAAG,IAAW,GACvC,MAAM,CAwIR;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,QAAQ,GAAG,YAAY,CAiB7D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../src/phases/verify.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACX,KAAK,EACL,GAAG,EACH,eAAe,EAEf,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EACX,eAAe,EACf,oBAAoB,EACpB,eAAe,EACf,qBAAqB,EACrB,kBAAkB,EAClB,UAAU,EACV,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../src/phases/verify.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACX,KAAK,EACL,GAAG,EACH,eAAe,EAEf,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EACX,eAAe,EACf,oBAAoB,EACpB,eAAe,EACf,qBAAqB,EACrB,kBAAkB,EAClB,UAAU,EACV,MAAM,aAAa,CAAC;AAoCrB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AACjE,MAAM,WAAW,oBAAoB;IACpC,cAAc,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;IACvC,QAAQ,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC7B;AA8SD,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,eAAe,GAAG,MAAM,CAkClE;AAED,wBAAgB,0BAA0B,CACzC,MAAM,EAAE,kBAAkB,GACxB,MAAM,GAAG,IAAI,CAcf;AAED,wFAAwF;AACxF,qBAAa,qBAAsB,SAAQ,KAAK;IAC/C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC,MAAM,CAAC,EAAE,CAAC;IAC7C,QAAQ,CAAC,KAAK,EAAE,qBAAqB,CAAC;IACtC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B,YACC,MAAM,EAAE,kBAAkB,EAC1B,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,qBAAqB,EAW5B;CACD;AAwUD,wBAAgB,4BAA4B,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAK1E;AAED,qGAAqG;AACrG,wBAAgB,8BAA8B,CAC7C,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,kBAAkB,EAC1B,UAAU,EAAE,oBAAoB,EAChC,UAAU,GAAE,eAAe,GAAG,IAAW,EACzC,QAAQ,GAAE,oBAAyB,EACnC,SAAS,SAAI,GACX;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,kBAAkB,CAAC;IAAC,OAAO,EAAE,eAAe,EAAE,CAAA;CAAE,CAyB7E;AAiYD,wBAAgB,aAAa,CAC5B,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,oBAAoB,EAChC,UAAU,GAAE,eAAe,GAAG,IAAW,EACzC,QAAQ,GAAE,oBAAyB,GACjC,kBAAkB,CA2CpB;AAED,iHAAiH;AACjH,wBAAgB,kBAAkB,CACjC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,eAAe,EAAE,EACvB,UAAU,EAAE,oBAAoB,EAChC,UAAU,GAAE,eAAe,GAAG,IAAW,EACzC,QAAQ,GAAE,oBAAyB,GACjC,MAAM,CA4MR;AA2CD,wBAAsB,YAAY,CACjC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,eAAe,EAAE,EACvB,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EACjB,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,eAAe,CAAA;CAAE,EACnD,MAAM,CAAC,EAAE,WAAW,EACpB,QAAQ,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,MAAM,CAAC,CA2DjB"}
|
package/dist/provider-eval.js
CHANGED
|
@@ -156,7 +156,7 @@ function formatProviderEvaluation(report) {
|
|
|
156
156
|
import fs2 from "fs";
|
|
157
157
|
|
|
158
158
|
// src/constants.ts
|
|
159
|
-
var VERSION = "9.6.
|
|
159
|
+
var VERSION = "9.6.1";
|
|
160
160
|
var SETTLED_TRIGGER_COOLDOWN_MS = 10 * 60000;
|
|
161
161
|
var COMPACT_SYSTEM_PREFIX = "You are an expert conversation summarizer for a coding agent. " + "Produce structured markdown summaries. " + "Follow output format exactly. " + "Use EXACT names \u2014 never paraphrase code identifiers. " + "Trust deterministic extraction data over intuition.";
|
|
162
162
|
var PROFILES = {
|
|
@@ -667,38 +667,117 @@ function buildPathNeedles(filePath) {
|
|
|
667
667
|
}
|
|
668
668
|
return needles;
|
|
669
669
|
}
|
|
670
|
-
|
|
671
|
-
|
|
670
|
+
var MAX_INDEXED_SUFFIX_CHARS = 1024;
|
|
671
|
+
function buildPathNeedleOwnershipIndex(allPaths) {
|
|
672
|
+
const owners = new Map;
|
|
673
|
+
const normalizedPaths = allPaths.map(normalizePath);
|
|
674
|
+
let hasUnindexedSuffixes = false;
|
|
675
|
+
for (const normalized of normalizedPaths) {
|
|
676
|
+
const suffixes = new Set([normalized]);
|
|
677
|
+
for (let index = 0;index < normalized.length; index++) {
|
|
678
|
+
if (normalized[index] !== "/")
|
|
679
|
+
continue;
|
|
680
|
+
if (normalized.length - index - 1 <= MAX_INDEXED_SUFFIX_CHARS) {
|
|
681
|
+
suffixes.add(normalized.slice(index + 1));
|
|
682
|
+
} else {
|
|
683
|
+
hasUnindexedSuffixes = true;
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
for (const suffix of suffixes) {
|
|
687
|
+
owners.set(suffix, (owners.get(suffix) ?? 0) + 1);
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
return { counts: owners, normalizedPaths, hasUnindexedSuffixes };
|
|
691
|
+
}
|
|
692
|
+
function buildUniquePathNeedlesFromIndex(filePath, owners) {
|
|
672
693
|
return buildPathNeedles(filePath).filter((needle) => {
|
|
673
|
-
|
|
674
|
-
|
|
694
|
+
if (!owners.hasUnindexedSuffixes)
|
|
695
|
+
return owners.counts.get(needle) === 1;
|
|
696
|
+
let count = 0;
|
|
697
|
+
for (const candidate of owners.normalizedPaths) {
|
|
675
698
|
if (candidate === needle || candidate.endsWith("/" + needle))
|
|
676
|
-
|
|
677
|
-
if (
|
|
699
|
+
count++;
|
|
700
|
+
if (count > 1)
|
|
678
701
|
return false;
|
|
679
702
|
}
|
|
680
|
-
return
|
|
703
|
+
return count === 1;
|
|
681
704
|
});
|
|
682
705
|
}
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
const
|
|
688
|
-
|
|
706
|
+
var PATH_CANDIDATE_CHAR_RE = /[\w./-]/;
|
|
707
|
+
function buildKnownPathReferenceIndex(knownPaths) {
|
|
708
|
+
const segmentSuffixes = new Set;
|
|
709
|
+
const boundarySuffixes = new Set;
|
|
710
|
+
const normalizedPaths = [];
|
|
711
|
+
let hasUnindexedSuffixes = false;
|
|
712
|
+
for (const path of knownPaths) {
|
|
689
713
|
const normalizedPath = normalizePath(path).replace(/^\/+/, "");
|
|
714
|
+
if (!normalizedPath)
|
|
715
|
+
continue;
|
|
716
|
+
normalizedPaths.push(normalizedPath);
|
|
717
|
+
segmentSuffixes.add(normalizedPath);
|
|
718
|
+
for (let index = 0;index < normalizedPath.length; index++) {
|
|
719
|
+
if (normalizedPath[index] === "/") {
|
|
720
|
+
if (normalizedPath.length - index - 1 <= MAX_INDEXED_SUFFIX_CHARS) {
|
|
721
|
+
segmentSuffixes.add(normalizedPath.slice(index + 1));
|
|
722
|
+
} else {
|
|
723
|
+
hasUnindexedSuffixes = true;
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
if (index > 0 && !PATH_CANDIDATE_CHAR_RE.test(normalizedPath[index - 1])) {
|
|
727
|
+
if (normalizedPath.length - index <= MAX_INDEXED_SUFFIX_CHARS) {
|
|
728
|
+
boundarySuffixes.add(normalizedPath.slice(index));
|
|
729
|
+
} else {
|
|
730
|
+
hasUnindexedSuffixes = true;
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
return {
|
|
736
|
+
segmentSuffixes,
|
|
737
|
+
sortedSegmentSuffixes: [...segmentSuffixes].sort(),
|
|
738
|
+
boundarySuffixes,
|
|
739
|
+
normalizedPaths,
|
|
740
|
+
hasUnindexedSuffixes
|
|
741
|
+
};
|
|
742
|
+
}
|
|
743
|
+
function matchesKnownPathReference(normalizedRef, normalizedPaths) {
|
|
744
|
+
const pathShaped = normalizedRef.includes("/");
|
|
745
|
+
return normalizedPaths.some((normalizedPath) => {
|
|
690
746
|
if (normalizedPath === normalizedRef || normalizedPath.endsWith("/" + normalizedRef))
|
|
691
747
|
return true;
|
|
692
748
|
if (normalizedPath.endsWith(normalizedRef)) {
|
|
693
749
|
const boundary = normalizedPath[normalizedPath.length - normalizedRef.length - 1];
|
|
694
|
-
if (boundary &&
|
|
750
|
+
if (boundary && !PATH_CANDIDATE_CHAR_RE.test(boundary))
|
|
695
751
|
return true;
|
|
696
752
|
}
|
|
697
753
|
if (!pathShaped)
|
|
698
754
|
return false;
|
|
699
|
-
return normalizedPath.
|
|
755
|
+
return normalizedPath.startsWith(normalizedRef + "/") || normalizedPath.includes("/" + normalizedRef + "/");
|
|
700
756
|
});
|
|
701
757
|
}
|
|
758
|
+
function sortedHasPrefix(values, prefix) {
|
|
759
|
+
let low = 0;
|
|
760
|
+
let high = values.length;
|
|
761
|
+
while (low < high) {
|
|
762
|
+
const middle = low + high >>> 1;
|
|
763
|
+
if (values[middle] < prefix)
|
|
764
|
+
low = middle + 1;
|
|
765
|
+
else
|
|
766
|
+
high = middle;
|
|
767
|
+
}
|
|
768
|
+
return values[low]?.startsWith(prefix) ?? false;
|
|
769
|
+
}
|
|
770
|
+
function isKnownPathReferenceInIndex(ref, index) {
|
|
771
|
+
const normalizedRef = normalizePath(ref).replace(/^\/+/, "");
|
|
772
|
+
if (!normalizedRef)
|
|
773
|
+
return false;
|
|
774
|
+
if (index.segmentSuffixes.has(normalizedRef) || index.boundarySuffixes.has(normalizedRef)) {
|
|
775
|
+
return true;
|
|
776
|
+
}
|
|
777
|
+
if (normalizedRef.includes("/") && sortedHasPrefix(index.sortedSegmentSuffixes, normalizedRef + "/"))
|
|
778
|
+
return true;
|
|
779
|
+
return index.hasUnindexedSuffixes ? matchesKnownPathReference(normalizedRef, index.normalizedPaths) : false;
|
|
780
|
+
}
|
|
702
781
|
|
|
703
782
|
// src/domain/tool-semantics.ts
|
|
704
783
|
var PATH_KEYS = [
|
|
@@ -832,7 +911,12 @@ function damageReportsFile() {
|
|
|
832
911
|
// src/utils/file-ref-detect.ts
|
|
833
912
|
var CODE_EXT_RE = /\.(ts|tsx|js|jsx|mjs|cjs|rs|py|go|java|rb|cs|cpp|c|h|hpp|swift|kt|scala|php|css|scss|html|json|yaml|yml|toml|md|mdx|sh|sql|tf|ini|env|lock|gradle|xml)$/i;
|
|
834
913
|
var VERSION_RE = /^v?\d+(?:\.\d+)+(?:[-+][\w.-]+)?$/i;
|
|
835
|
-
|
|
914
|
+
function isAsciiWordCode(code) {
|
|
915
|
+
return code >= 48 && code <= 57 || code >= 65 && code <= 90 || code === 95 || code >= 97 && code <= 122;
|
|
916
|
+
}
|
|
917
|
+
function isCandidateCode(code) {
|
|
918
|
+
return isAsciiWordCode(code) || code === 45 || code === 46 || code === 47;
|
|
919
|
+
}
|
|
836
920
|
function isLikelyFileRef(candidate) {
|
|
837
921
|
if (candidate.startsWith("//") || VERSION_RE.test(candidate))
|
|
838
922
|
return false;
|
|
@@ -843,13 +927,32 @@ function isLikelyFileRef(candidate) {
|
|
|
843
927
|
return CODE_EXT_RE.test(candidate);
|
|
844
928
|
}
|
|
845
929
|
function extractFileRefs(summary) {
|
|
846
|
-
const matcher = new RegExp(FILE_REF_CANDIDATE_RE.source, FILE_REF_CANDIDATE_RE.flags);
|
|
847
930
|
const refs = [];
|
|
848
|
-
|
|
849
|
-
|
|
931
|
+
let cursor = 0;
|
|
932
|
+
while (cursor < summary.length) {
|
|
933
|
+
while (cursor < summary.length && !isCandidateCode(summary.charCodeAt(cursor)))
|
|
934
|
+
cursor++;
|
|
935
|
+
const runStart = cursor;
|
|
936
|
+
while (cursor < summary.length && isCandidateCode(summary.charCodeAt(cursor)))
|
|
937
|
+
cursor++;
|
|
938
|
+
const runEnd = cursor;
|
|
939
|
+
let extensionDot = -1;
|
|
940
|
+
for (let index = runStart + 1;index + 1 < runEnd; index++) {
|
|
941
|
+
if (summary.charCodeAt(index) === 46 && isAsciiWordCode(summary.charCodeAt(index + 1))) {
|
|
942
|
+
extensionDot = index;
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
if (extensionDot < 0)
|
|
946
|
+
continue;
|
|
947
|
+
let matchEnd = extensionDot + 2;
|
|
948
|
+
while (matchEnd < runEnd && isAsciiWordCode(summary.charCodeAt(matchEnd))) {
|
|
949
|
+
matchEnd++;
|
|
950
|
+
}
|
|
951
|
+
const candidate = summary.slice(runStart, matchEnd);
|
|
952
|
+
if (/[\\/]/.test(summary[matchEnd] ?? ""))
|
|
850
953
|
continue;
|
|
851
|
-
if (isLikelyFileRef(
|
|
852
|
-
refs.push(
|
|
954
|
+
if (isLikelyFileRef(candidate))
|
|
955
|
+
refs.push(candidate);
|
|
853
956
|
}
|
|
854
957
|
return refs;
|
|
855
958
|
}
|
|
@@ -5,7 +5,7 @@ var __require = import.meta.require;
|
|
|
5
5
|
import { ModelRegistry, ModelRuntime } from "@earendil-works/pi-coding-agent";
|
|
6
6
|
|
|
7
7
|
// src/constants.ts
|
|
8
|
-
var VERSION = "9.6.
|
|
8
|
+
var VERSION = "9.6.1";
|
|
9
9
|
var SETTLED_TRIGGER_COOLDOWN_MS = 10 * 60000;
|
|
10
10
|
var COMPACT_SYSTEM_PREFIX = "You are an expert conversation summarizer for a coding agent. " + "Produce structured markdown summaries. " + "Follow output format exactly. " + "Use EXACT names \u2014 never paraphrase code identifiers. " + "Trust deterministic extraction data over intuition.";
|
|
11
11
|
var PROFILES = {
|
|
@@ -690,38 +690,117 @@ function buildPathNeedles(filePath) {
|
|
|
690
690
|
}
|
|
691
691
|
return needles;
|
|
692
692
|
}
|
|
693
|
-
|
|
694
|
-
|
|
693
|
+
var MAX_INDEXED_SUFFIX_CHARS = 1024;
|
|
694
|
+
function buildPathNeedleOwnershipIndex(allPaths) {
|
|
695
|
+
const owners = new Map;
|
|
696
|
+
const normalizedPaths = allPaths.map(normalizePath);
|
|
697
|
+
let hasUnindexedSuffixes = false;
|
|
698
|
+
for (const normalized of normalizedPaths) {
|
|
699
|
+
const suffixes = new Set([normalized]);
|
|
700
|
+
for (let index = 0;index < normalized.length; index++) {
|
|
701
|
+
if (normalized[index] !== "/")
|
|
702
|
+
continue;
|
|
703
|
+
if (normalized.length - index - 1 <= MAX_INDEXED_SUFFIX_CHARS) {
|
|
704
|
+
suffixes.add(normalized.slice(index + 1));
|
|
705
|
+
} else {
|
|
706
|
+
hasUnindexedSuffixes = true;
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
for (const suffix of suffixes) {
|
|
710
|
+
owners.set(suffix, (owners.get(suffix) ?? 0) + 1);
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
return { counts: owners, normalizedPaths, hasUnindexedSuffixes };
|
|
714
|
+
}
|
|
715
|
+
function buildUniquePathNeedlesFromIndex(filePath, owners) {
|
|
695
716
|
return buildPathNeedles(filePath).filter((needle) => {
|
|
696
|
-
|
|
697
|
-
|
|
717
|
+
if (!owners.hasUnindexedSuffixes)
|
|
718
|
+
return owners.counts.get(needle) === 1;
|
|
719
|
+
let count = 0;
|
|
720
|
+
for (const candidate of owners.normalizedPaths) {
|
|
698
721
|
if (candidate === needle || candidate.endsWith("/" + needle))
|
|
699
|
-
|
|
700
|
-
if (
|
|
722
|
+
count++;
|
|
723
|
+
if (count > 1)
|
|
701
724
|
return false;
|
|
702
725
|
}
|
|
703
|
-
return
|
|
726
|
+
return count === 1;
|
|
704
727
|
});
|
|
705
728
|
}
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
const
|
|
711
|
-
|
|
729
|
+
var PATH_CANDIDATE_CHAR_RE = /[\w./-]/;
|
|
730
|
+
function buildKnownPathReferenceIndex(knownPaths) {
|
|
731
|
+
const segmentSuffixes = new Set;
|
|
732
|
+
const boundarySuffixes = new Set;
|
|
733
|
+
const normalizedPaths = [];
|
|
734
|
+
let hasUnindexedSuffixes = false;
|
|
735
|
+
for (const path of knownPaths) {
|
|
712
736
|
const normalizedPath = normalizePath(path).replace(/^\/+/, "");
|
|
737
|
+
if (!normalizedPath)
|
|
738
|
+
continue;
|
|
739
|
+
normalizedPaths.push(normalizedPath);
|
|
740
|
+
segmentSuffixes.add(normalizedPath);
|
|
741
|
+
for (let index = 0;index < normalizedPath.length; index++) {
|
|
742
|
+
if (normalizedPath[index] === "/") {
|
|
743
|
+
if (normalizedPath.length - index - 1 <= MAX_INDEXED_SUFFIX_CHARS) {
|
|
744
|
+
segmentSuffixes.add(normalizedPath.slice(index + 1));
|
|
745
|
+
} else {
|
|
746
|
+
hasUnindexedSuffixes = true;
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
if (index > 0 && !PATH_CANDIDATE_CHAR_RE.test(normalizedPath[index - 1])) {
|
|
750
|
+
if (normalizedPath.length - index <= MAX_INDEXED_SUFFIX_CHARS) {
|
|
751
|
+
boundarySuffixes.add(normalizedPath.slice(index));
|
|
752
|
+
} else {
|
|
753
|
+
hasUnindexedSuffixes = true;
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
return {
|
|
759
|
+
segmentSuffixes,
|
|
760
|
+
sortedSegmentSuffixes: [...segmentSuffixes].sort(),
|
|
761
|
+
boundarySuffixes,
|
|
762
|
+
normalizedPaths,
|
|
763
|
+
hasUnindexedSuffixes
|
|
764
|
+
};
|
|
765
|
+
}
|
|
766
|
+
function matchesKnownPathReference(normalizedRef, normalizedPaths) {
|
|
767
|
+
const pathShaped = normalizedRef.includes("/");
|
|
768
|
+
return normalizedPaths.some((normalizedPath) => {
|
|
713
769
|
if (normalizedPath === normalizedRef || normalizedPath.endsWith("/" + normalizedRef))
|
|
714
770
|
return true;
|
|
715
771
|
if (normalizedPath.endsWith(normalizedRef)) {
|
|
716
772
|
const boundary = normalizedPath[normalizedPath.length - normalizedRef.length - 1];
|
|
717
|
-
if (boundary &&
|
|
773
|
+
if (boundary && !PATH_CANDIDATE_CHAR_RE.test(boundary))
|
|
718
774
|
return true;
|
|
719
775
|
}
|
|
720
776
|
if (!pathShaped)
|
|
721
777
|
return false;
|
|
722
|
-
return normalizedPath.
|
|
778
|
+
return normalizedPath.startsWith(normalizedRef + "/") || normalizedPath.includes("/" + normalizedRef + "/");
|
|
723
779
|
});
|
|
724
780
|
}
|
|
781
|
+
function sortedHasPrefix(values, prefix) {
|
|
782
|
+
let low = 0;
|
|
783
|
+
let high = values.length;
|
|
784
|
+
while (low < high) {
|
|
785
|
+
const middle = low + high >>> 1;
|
|
786
|
+
if (values[middle] < prefix)
|
|
787
|
+
low = middle + 1;
|
|
788
|
+
else
|
|
789
|
+
high = middle;
|
|
790
|
+
}
|
|
791
|
+
return values[low]?.startsWith(prefix) ?? false;
|
|
792
|
+
}
|
|
793
|
+
function isKnownPathReferenceInIndex(ref, index) {
|
|
794
|
+
const normalizedRef = normalizePath(ref).replace(/^\/+/, "");
|
|
795
|
+
if (!normalizedRef)
|
|
796
|
+
return false;
|
|
797
|
+
if (index.segmentSuffixes.has(normalizedRef) || index.boundarySuffixes.has(normalizedRef)) {
|
|
798
|
+
return true;
|
|
799
|
+
}
|
|
800
|
+
if (normalizedRef.includes("/") && sortedHasPrefix(index.sortedSegmentSuffixes, normalizedRef + "/"))
|
|
801
|
+
return true;
|
|
802
|
+
return index.hasUnindexedSuffixes ? matchesKnownPathReference(normalizedRef, index.normalizedPaths) : false;
|
|
803
|
+
}
|
|
725
804
|
|
|
726
805
|
// src/domain/tool-semantics.ts
|
|
727
806
|
var PATH_KEYS = [
|
|
@@ -855,7 +934,12 @@ function damageReportsFile() {
|
|
|
855
934
|
// src/utils/file-ref-detect.ts
|
|
856
935
|
var CODE_EXT_RE = /\.(ts|tsx|js|jsx|mjs|cjs|rs|py|go|java|rb|cs|cpp|c|h|hpp|swift|kt|scala|php|css|scss|html|json|yaml|yml|toml|md|mdx|sh|sql|tf|ini|env|lock|gradle|xml)$/i;
|
|
857
936
|
var VERSION_RE = /^v?\d+(?:\.\d+)+(?:[-+][\w.-]+)?$/i;
|
|
858
|
-
|
|
937
|
+
function isAsciiWordCode(code) {
|
|
938
|
+
return code >= 48 && code <= 57 || code >= 65 && code <= 90 || code === 95 || code >= 97 && code <= 122;
|
|
939
|
+
}
|
|
940
|
+
function isCandidateCode(code) {
|
|
941
|
+
return isAsciiWordCode(code) || code === 45 || code === 46 || code === 47;
|
|
942
|
+
}
|
|
859
943
|
function isLikelyFileRef(candidate) {
|
|
860
944
|
if (candidate.startsWith("//") || VERSION_RE.test(candidate))
|
|
861
945
|
return false;
|
|
@@ -866,13 +950,32 @@ function isLikelyFileRef(candidate) {
|
|
|
866
950
|
return CODE_EXT_RE.test(candidate);
|
|
867
951
|
}
|
|
868
952
|
function extractFileRefs(summary) {
|
|
869
|
-
const matcher = new RegExp(FILE_REF_CANDIDATE_RE.source, FILE_REF_CANDIDATE_RE.flags);
|
|
870
953
|
const refs = [];
|
|
871
|
-
|
|
872
|
-
|
|
954
|
+
let cursor = 0;
|
|
955
|
+
while (cursor < summary.length) {
|
|
956
|
+
while (cursor < summary.length && !isCandidateCode(summary.charCodeAt(cursor)))
|
|
957
|
+
cursor++;
|
|
958
|
+
const runStart = cursor;
|
|
959
|
+
while (cursor < summary.length && isCandidateCode(summary.charCodeAt(cursor)))
|
|
960
|
+
cursor++;
|
|
961
|
+
const runEnd = cursor;
|
|
962
|
+
let extensionDot = -1;
|
|
963
|
+
for (let index = runStart + 1;index + 1 < runEnd; index++) {
|
|
964
|
+
if (summary.charCodeAt(index) === 46 && isAsciiWordCode(summary.charCodeAt(index + 1))) {
|
|
965
|
+
extensionDot = index;
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
if (extensionDot < 0)
|
|
969
|
+
continue;
|
|
970
|
+
let matchEnd = extensionDot + 2;
|
|
971
|
+
while (matchEnd < runEnd && isAsciiWordCode(summary.charCodeAt(matchEnd))) {
|
|
972
|
+
matchEnd++;
|
|
973
|
+
}
|
|
974
|
+
const candidate = summary.slice(runStart, matchEnd);
|
|
975
|
+
if (/[\\/]/.test(summary[matchEnd] ?? ""))
|
|
873
976
|
continue;
|
|
874
|
-
if (isLikelyFileRef(
|
|
875
|
-
refs.push(
|
|
977
|
+
if (isLikelyFileRef(candidate))
|
|
978
|
+
refs.push(candidate);
|
|
876
979
|
}
|
|
877
980
|
return refs;
|
|
878
981
|
}
|
|
@@ -2220,8 +2323,9 @@ function verifyFileReferences(summary, extraction, continuity, evidence, collect
|
|
|
2220
2323
|
...(continuity?.unresolvedErrors ?? []).flatMap((error) => error.files),
|
|
2221
2324
|
...(continuity?.openLoops ?? []).flatMap((loop) => loop.files)
|
|
2222
2325
|
]));
|
|
2326
|
+
const knownFileIndex = buildKnownPathReferenceIndex(knownFiles);
|
|
2223
2327
|
for (const ref of new Set(extractFileRefs(summary))) {
|
|
2224
|
-
const grounded =
|
|
2328
|
+
const grounded = isKnownPathReferenceInIndex(ref, knownFileIndex) || Boolean(evidence.sourceMessages && sourceSupportsFileReference(ref, evidence.sourceMessages));
|
|
2225
2329
|
if (!grounded)
|
|
2226
2330
|
addGap(accumulator, { kind: "fabricated-file", ref }, 4);
|
|
2227
2331
|
}
|
|
@@ -2239,9 +2343,10 @@ function verifyProgressConsistency(parsed, extraction, collected, paths, accumul
|
|
|
2239
2343
|
}, 12);
|
|
2240
2344
|
}
|
|
2241
2345
|
const doneRefs = new Set(extractFileRefs(done).map(normalizePath));
|
|
2346
|
+
const modifiedPathOwners = buildPathNeedleOwnershipIndex(paths.modified);
|
|
2242
2347
|
for (const file of extraction.modifiedFiles) {
|
|
2243
|
-
const needles =
|
|
2244
|
-
if (!needles.some((needle) => doneRefs.has(
|
|
2348
|
+
const needles = buildUniquePathNeedlesFromIndex(file.path, modifiedPathOwners);
|
|
2349
|
+
if (!needles.some((needle) => doneRefs.has(needle)))
|
|
2245
2350
|
continue;
|
|
2246
2351
|
const unresolved = collected.unresolved.find((error) => {
|
|
2247
2352
|
const firstLine = error.message.split(/\r?\n/, 1)[0] ?? "";
|
package/dist/telemetry-report.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
var __require = import.meta.require;
|
|
3
3
|
|
|
4
4
|
// src/constants.ts
|
|
5
|
-
var VERSION = "9.6.
|
|
5
|
+
var VERSION = "9.6.1";
|
|
6
6
|
var SETTLED_TRIGGER_COOLDOWN_MS = 10 * 60000;
|
|
7
7
|
var COMPACT_SYSTEM_PREFIX = "You are an expert conversation summarizer for a coding agent. " + "Produce structured markdown summaries. " + "Follow output format exactly. " + "Use EXACT names \u2014 never paraphrase code identifiers. " + "Trust deterministic extraction data over intuition.";
|
|
8
8
|
var PROFILES = {
|
|
@@ -803,38 +803,117 @@ function buildPathNeedles(filePath) {
|
|
|
803
803
|
}
|
|
804
804
|
return needles;
|
|
805
805
|
}
|
|
806
|
-
|
|
807
|
-
|
|
806
|
+
var MAX_INDEXED_SUFFIX_CHARS = 1024;
|
|
807
|
+
function buildPathNeedleOwnershipIndex(allPaths) {
|
|
808
|
+
const owners = new Map;
|
|
809
|
+
const normalizedPaths = allPaths.map(normalizePath);
|
|
810
|
+
let hasUnindexedSuffixes = false;
|
|
811
|
+
for (const normalized of normalizedPaths) {
|
|
812
|
+
const suffixes = new Set([normalized]);
|
|
813
|
+
for (let index = 0;index < normalized.length; index++) {
|
|
814
|
+
if (normalized[index] !== "/")
|
|
815
|
+
continue;
|
|
816
|
+
if (normalized.length - index - 1 <= MAX_INDEXED_SUFFIX_CHARS) {
|
|
817
|
+
suffixes.add(normalized.slice(index + 1));
|
|
818
|
+
} else {
|
|
819
|
+
hasUnindexedSuffixes = true;
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
for (const suffix of suffixes) {
|
|
823
|
+
owners.set(suffix, (owners.get(suffix) ?? 0) + 1);
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
return { counts: owners, normalizedPaths, hasUnindexedSuffixes };
|
|
827
|
+
}
|
|
828
|
+
function buildUniquePathNeedlesFromIndex(filePath, owners) {
|
|
808
829
|
return buildPathNeedles(filePath).filter((needle) => {
|
|
809
|
-
|
|
810
|
-
|
|
830
|
+
if (!owners.hasUnindexedSuffixes)
|
|
831
|
+
return owners.counts.get(needle) === 1;
|
|
832
|
+
let count = 0;
|
|
833
|
+
for (const candidate of owners.normalizedPaths) {
|
|
811
834
|
if (candidate === needle || candidate.endsWith("/" + needle))
|
|
812
|
-
|
|
813
|
-
if (
|
|
835
|
+
count++;
|
|
836
|
+
if (count > 1)
|
|
814
837
|
return false;
|
|
815
838
|
}
|
|
816
|
-
return
|
|
839
|
+
return count === 1;
|
|
817
840
|
});
|
|
818
841
|
}
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
const
|
|
824
|
-
|
|
842
|
+
var PATH_CANDIDATE_CHAR_RE = /[\w./-]/;
|
|
843
|
+
function buildKnownPathReferenceIndex(knownPaths) {
|
|
844
|
+
const segmentSuffixes = new Set;
|
|
845
|
+
const boundarySuffixes = new Set;
|
|
846
|
+
const normalizedPaths = [];
|
|
847
|
+
let hasUnindexedSuffixes = false;
|
|
848
|
+
for (const path2 of knownPaths) {
|
|
825
849
|
const normalizedPath = normalizePath(path2).replace(/^\/+/, "");
|
|
850
|
+
if (!normalizedPath)
|
|
851
|
+
continue;
|
|
852
|
+
normalizedPaths.push(normalizedPath);
|
|
853
|
+
segmentSuffixes.add(normalizedPath);
|
|
854
|
+
for (let index = 0;index < normalizedPath.length; index++) {
|
|
855
|
+
if (normalizedPath[index] === "/") {
|
|
856
|
+
if (normalizedPath.length - index - 1 <= MAX_INDEXED_SUFFIX_CHARS) {
|
|
857
|
+
segmentSuffixes.add(normalizedPath.slice(index + 1));
|
|
858
|
+
} else {
|
|
859
|
+
hasUnindexedSuffixes = true;
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
if (index > 0 && !PATH_CANDIDATE_CHAR_RE.test(normalizedPath[index - 1])) {
|
|
863
|
+
if (normalizedPath.length - index <= MAX_INDEXED_SUFFIX_CHARS) {
|
|
864
|
+
boundarySuffixes.add(normalizedPath.slice(index));
|
|
865
|
+
} else {
|
|
866
|
+
hasUnindexedSuffixes = true;
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
return {
|
|
872
|
+
segmentSuffixes,
|
|
873
|
+
sortedSegmentSuffixes: [...segmentSuffixes].sort(),
|
|
874
|
+
boundarySuffixes,
|
|
875
|
+
normalizedPaths,
|
|
876
|
+
hasUnindexedSuffixes
|
|
877
|
+
};
|
|
878
|
+
}
|
|
879
|
+
function matchesKnownPathReference(normalizedRef, normalizedPaths) {
|
|
880
|
+
const pathShaped = normalizedRef.includes("/");
|
|
881
|
+
return normalizedPaths.some((normalizedPath) => {
|
|
826
882
|
if (normalizedPath === normalizedRef || normalizedPath.endsWith("/" + normalizedRef))
|
|
827
883
|
return true;
|
|
828
884
|
if (normalizedPath.endsWith(normalizedRef)) {
|
|
829
885
|
const boundary = normalizedPath[normalizedPath.length - normalizedRef.length - 1];
|
|
830
|
-
if (boundary &&
|
|
886
|
+
if (boundary && !PATH_CANDIDATE_CHAR_RE.test(boundary))
|
|
831
887
|
return true;
|
|
832
888
|
}
|
|
833
889
|
if (!pathShaped)
|
|
834
890
|
return false;
|
|
835
|
-
return normalizedPath.
|
|
891
|
+
return normalizedPath.startsWith(normalizedRef + "/") || normalizedPath.includes("/" + normalizedRef + "/");
|
|
836
892
|
});
|
|
837
893
|
}
|
|
894
|
+
function sortedHasPrefix(values, prefix) {
|
|
895
|
+
let low = 0;
|
|
896
|
+
let high = values.length;
|
|
897
|
+
while (low < high) {
|
|
898
|
+
const middle = low + high >>> 1;
|
|
899
|
+
if (values[middle] < prefix)
|
|
900
|
+
low = middle + 1;
|
|
901
|
+
else
|
|
902
|
+
high = middle;
|
|
903
|
+
}
|
|
904
|
+
return values[low]?.startsWith(prefix) ?? false;
|
|
905
|
+
}
|
|
906
|
+
function isKnownPathReferenceInIndex(ref, index) {
|
|
907
|
+
const normalizedRef = normalizePath(ref).replace(/^\/+/, "");
|
|
908
|
+
if (!normalizedRef)
|
|
909
|
+
return false;
|
|
910
|
+
if (index.segmentSuffixes.has(normalizedRef) || index.boundarySuffixes.has(normalizedRef)) {
|
|
911
|
+
return true;
|
|
912
|
+
}
|
|
913
|
+
if (normalizedRef.includes("/") && sortedHasPrefix(index.sortedSegmentSuffixes, normalizedRef + "/"))
|
|
914
|
+
return true;
|
|
915
|
+
return index.hasUnindexedSuffixes ? matchesKnownPathReference(normalizedRef, index.normalizedPaths) : false;
|
|
916
|
+
}
|
|
838
917
|
|
|
839
918
|
// src/domain/tool-semantics.ts
|
|
840
919
|
var PATH_KEYS = [
|
|
@@ -906,7 +985,12 @@ function classifyToolOperation(args, toolName) {
|
|
|
906
985
|
// src/utils/file-ref-detect.ts
|
|
907
986
|
var CODE_EXT_RE = /\.(ts|tsx|js|jsx|mjs|cjs|rs|py|go|java|rb|cs|cpp|c|h|hpp|swift|kt|scala|php|css|scss|html|json|yaml|yml|toml|md|mdx|sh|sql|tf|ini|env|lock|gradle|xml)$/i;
|
|
908
987
|
var VERSION_RE = /^v?\d+(?:\.\d+)+(?:[-+][\w.-]+)?$/i;
|
|
909
|
-
|
|
988
|
+
function isAsciiWordCode(code) {
|
|
989
|
+
return code >= 48 && code <= 57 || code >= 65 && code <= 90 || code === 95 || code >= 97 && code <= 122;
|
|
990
|
+
}
|
|
991
|
+
function isCandidateCode(code) {
|
|
992
|
+
return isAsciiWordCode(code) || code === 45 || code === 46 || code === 47;
|
|
993
|
+
}
|
|
910
994
|
function isLikelyFileRef(candidate) {
|
|
911
995
|
if (candidate.startsWith("//") || VERSION_RE.test(candidate))
|
|
912
996
|
return false;
|
|
@@ -917,13 +1001,32 @@ function isLikelyFileRef(candidate) {
|
|
|
917
1001
|
return CODE_EXT_RE.test(candidate);
|
|
918
1002
|
}
|
|
919
1003
|
function extractFileRefs(summary) {
|
|
920
|
-
const matcher = new RegExp(FILE_REF_CANDIDATE_RE.source, FILE_REF_CANDIDATE_RE.flags);
|
|
921
1004
|
const refs = [];
|
|
922
|
-
|
|
923
|
-
|
|
1005
|
+
let cursor = 0;
|
|
1006
|
+
while (cursor < summary.length) {
|
|
1007
|
+
while (cursor < summary.length && !isCandidateCode(summary.charCodeAt(cursor)))
|
|
1008
|
+
cursor++;
|
|
1009
|
+
const runStart = cursor;
|
|
1010
|
+
while (cursor < summary.length && isCandidateCode(summary.charCodeAt(cursor)))
|
|
1011
|
+
cursor++;
|
|
1012
|
+
const runEnd = cursor;
|
|
1013
|
+
let extensionDot = -1;
|
|
1014
|
+
for (let index = runStart + 1;index + 1 < runEnd; index++) {
|
|
1015
|
+
if (summary.charCodeAt(index) === 46 && isAsciiWordCode(summary.charCodeAt(index + 1))) {
|
|
1016
|
+
extensionDot = index;
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
if (extensionDot < 0)
|
|
1020
|
+
continue;
|
|
1021
|
+
let matchEnd = extensionDot + 2;
|
|
1022
|
+
while (matchEnd < runEnd && isAsciiWordCode(summary.charCodeAt(matchEnd))) {
|
|
1023
|
+
matchEnd++;
|
|
1024
|
+
}
|
|
1025
|
+
const candidate = summary.slice(runStart, matchEnd);
|
|
1026
|
+
if (/[\\/]/.test(summary[matchEnd] ?? ""))
|
|
924
1027
|
continue;
|
|
925
|
-
if (isLikelyFileRef(
|
|
926
|
-
refs.push(
|
|
1028
|
+
if (isLikelyFileRef(candidate))
|
|
1029
|
+
refs.push(candidate);
|
|
927
1030
|
}
|
|
928
1031
|
return refs;
|
|
929
1032
|
}
|