billion-context 0.1.39 → 0.1.40
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 +56 -1
- package/README.zh-CN.md +50 -1
- package/dist/index.js +346 -106
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -43595,9 +43595,11 @@ function prune(messages, state, options = {}) {
|
|
|
43595
43595
|
const indexById = /* @__PURE__ */ new Map();
|
|
43596
43596
|
messages.forEach((message, index) => indexById.set(message.id, index));
|
|
43597
43597
|
const anchors = inject ? collectSummaryAnchors(state, indexById) : [];
|
|
43598
|
-
return
|
|
43599
|
-
|
|
43600
|
-
|
|
43598
|
+
return stripOrphanedReasoning(
|
|
43599
|
+
stripOrphanedToolResults(
|
|
43600
|
+
stripOrphanedToolCalls(
|
|
43601
|
+
rebuildMessages(messages, covered, firstUserIndex, anchors)
|
|
43602
|
+
)
|
|
43601
43603
|
)
|
|
43602
43604
|
);
|
|
43603
43605
|
}
|
|
@@ -43674,6 +43676,24 @@ function stripOrphanedToolCalls(messages) {
|
|
|
43674
43676
|
(m2) => m2.contentType !== "tool-call" || !m2.toolCallId || m2.toolName === "compress" || knownResultIds.has(m2.toolCallId)
|
|
43675
43677
|
);
|
|
43676
43678
|
}
|
|
43679
|
+
function stripOrphanedReasoning(messages) {
|
|
43680
|
+
const drop = /* @__PURE__ */ new Set();
|
|
43681
|
+
for (let i = 0; i < messages.length; i++) {
|
|
43682
|
+
if (drop.has(i)) continue;
|
|
43683
|
+
if (messages[i].contentType !== "reasoning") continue;
|
|
43684
|
+
let j2 = i;
|
|
43685
|
+
while (j2 + 1 < messages.length && messages[j2 + 1].contentType === "reasoning") {
|
|
43686
|
+
j2++;
|
|
43687
|
+
}
|
|
43688
|
+
const companion = messages[j2 + 1];
|
|
43689
|
+
const hasCompanion = companion !== void 0 && companion.role === "assistant" && (companion.contentType === "text" || companion.contentType === "tool-call");
|
|
43690
|
+
if (!hasCompanion) {
|
|
43691
|
+
for (let k2 = i; k2 <= j2; k2++) drop.add(k2);
|
|
43692
|
+
}
|
|
43693
|
+
}
|
|
43694
|
+
if (drop.size === 0) return messages;
|
|
43695
|
+
return messages.filter((_2, i) => !drop.has(i));
|
|
43696
|
+
}
|
|
43677
43697
|
function syncBlocks(messages, state) {
|
|
43678
43698
|
const presentIds = new Set(messages.map((message) => message.id));
|
|
43679
43699
|
const deactivated = [];
|
|
@@ -43730,7 +43750,7 @@ function defaultConfig(modelContextLimit, overrides = {}) {
|
|
|
43730
43750
|
const base = {
|
|
43731
43751
|
tiers: { enabled: true, tier2Trigger: 5, tier3Trigger: 10 },
|
|
43732
43752
|
nudge: {
|
|
43733
|
-
maxContextLimitPct: 0.
|
|
43753
|
+
maxContextLimitPct: 0.75,
|
|
43734
43754
|
minContextLimitPct: 0.45,
|
|
43735
43755
|
frequency: 5,
|
|
43736
43756
|
iterationThreshold: 15,
|
|
@@ -43740,10 +43760,10 @@ function defaultConfig(modelContextLimit, overrides = {}) {
|
|
|
43740
43760
|
growthCap: 5e4,
|
|
43741
43761
|
minGrowthFloor: 2e4,
|
|
43742
43762
|
minGrowthRatio: 0.45,
|
|
43743
|
-
emergencyThresholdPct: 0.
|
|
43763
|
+
emergencyThresholdPct: 0.95
|
|
43744
43764
|
},
|
|
43745
43765
|
promotionThreshold: 5,
|
|
43746
|
-
truncate: { threshold:
|
|
43766
|
+
truncate: { threshold: 0.95 },
|
|
43747
43767
|
compress: {
|
|
43748
43768
|
minCompressRange: 5e3,
|
|
43749
43769
|
maxSummaryLength: 2e4,
|
|
@@ -43773,6 +43793,11 @@ function validateConfig(config) {
|
|
|
43773
43793
|
"nudge.minContextLimitPct must not exceed nudge.maxContextLimitPct"
|
|
43774
43794
|
);
|
|
43775
43795
|
}
|
|
43796
|
+
if (config.nudge.maxContextLimitPct > config.nudge.emergencyThresholdPct) {
|
|
43797
|
+
errors.push(
|
|
43798
|
+
"nudge.maxContextLimitPct must not exceed nudge.emergencyThresholdPct"
|
|
43799
|
+
);
|
|
43800
|
+
}
|
|
43776
43801
|
if (config.promotionThreshold < 1) {
|
|
43777
43802
|
errors.push("promotionThreshold must be >= 1");
|
|
43778
43803
|
}
|
|
@@ -43805,6 +43830,18 @@ function parseBoundary(ref) {
|
|
|
43805
43830
|
}
|
|
43806
43831
|
return null;
|
|
43807
43832
|
}
|
|
43833
|
+
var BoundaryNotFoundError = class extends Error {
|
|
43834
|
+
code = "BOUNDARY_NOT_FOUND";
|
|
43835
|
+
kind;
|
|
43836
|
+
endpoint;
|
|
43837
|
+
constructor(kind, endpoint, message) {
|
|
43838
|
+
super(message);
|
|
43839
|
+
this.name = "BoundaryNotFoundError";
|
|
43840
|
+
this.code = "BOUNDARY_NOT_FOUND";
|
|
43841
|
+
this.kind = kind;
|
|
43842
|
+
this.endpoint = endpoint;
|
|
43843
|
+
}
|
|
43844
|
+
};
|
|
43808
43845
|
function resolveBoundaries(input) {
|
|
43809
43846
|
const start = parseBoundary(input.startRef);
|
|
43810
43847
|
const end = parseBoundary(input.endRef);
|
|
@@ -43817,13 +43854,8 @@ function resolveBoundaries(input) {
|
|
|
43817
43854
|
input.messages.forEach(
|
|
43818
43855
|
(message, index) => indexByRawId.set(message.id, index)
|
|
43819
43856
|
);
|
|
43820
|
-
let startIndex = resolveAnchorIndex(start, input.state, indexByRawId);
|
|
43821
|
-
let endIndex = resolveAnchorIndex(end, input.state, indexByRawId);
|
|
43822
|
-
if (startIndex === null || endIndex === null) {
|
|
43823
|
-
throw new Error(
|
|
43824
|
-
`Boundary not found in visible context (likely consumed by an existing block). startId="${input.startRef}", endId="${input.endRef}".`
|
|
43825
|
-
);
|
|
43826
|
-
}
|
|
43857
|
+
let startIndex = resolveAnchorIndex(start, input.state, indexByRawId, "start");
|
|
43858
|
+
let endIndex = resolveAnchorIndex(end, input.state, indexByRawId, "end");
|
|
43827
43859
|
if (startIndex > endIndex) {
|
|
43828
43860
|
[startIndex, endIndex] = [endIndex, startIndex];
|
|
43829
43861
|
}
|
|
@@ -43854,16 +43886,51 @@ function resolveBoundaries(input) {
|
|
|
43854
43886
|
protectedGaps
|
|
43855
43887
|
};
|
|
43856
43888
|
}
|
|
43857
|
-
function resolveAnchorIndex(boundary, state, indexByRawId) {
|
|
43889
|
+
function resolveAnchorIndex(boundary, state, indexByRawId, endpoint) {
|
|
43890
|
+
const label = endpoint === "start" ? "startId" : "endId";
|
|
43858
43891
|
if (boundary.kind === "message") {
|
|
43859
43892
|
const rawId = state.messageRefs.byRef[boundary.raw] ?? state.messageRefs.byRef[formatPaddedRef(boundary.numericId)];
|
|
43860
|
-
if (!rawId)
|
|
43893
|
+
if (!rawId) {
|
|
43894
|
+
throw new BoundaryNotFoundError(
|
|
43895
|
+
"unknown",
|
|
43896
|
+
endpoint,
|
|
43897
|
+
`${label}="${boundary.raw}" does not exist in this session (typo or wrong session) \u2014 run acp_status for current refs.`
|
|
43898
|
+
);
|
|
43899
|
+
}
|
|
43861
43900
|
const index = indexByRawId.get(rawId);
|
|
43862
|
-
|
|
43901
|
+
if (index === void 0) {
|
|
43902
|
+
throw new BoundaryNotFoundError(
|
|
43903
|
+
"consumed",
|
|
43904
|
+
endpoint,
|
|
43905
|
+
`${label}="${boundary.raw}" not found in visible context (likely consumed by an existing block).`
|
|
43906
|
+
);
|
|
43907
|
+
}
|
|
43908
|
+
return index;
|
|
43863
43909
|
}
|
|
43864
43910
|
const block = blockById(state, `b${boundary.numericId}`);
|
|
43865
|
-
if (!block
|
|
43866
|
-
|
|
43911
|
+
if (!block) {
|
|
43912
|
+
throw new BoundaryNotFoundError(
|
|
43913
|
+
"unknown",
|
|
43914
|
+
endpoint,
|
|
43915
|
+
`${label}="b${boundary.numericId}" does not exist in this session (typo or wrong session) \u2014 run acp_status for current refs.`
|
|
43916
|
+
);
|
|
43917
|
+
}
|
|
43918
|
+
if (!block.active) {
|
|
43919
|
+
throw new BoundaryNotFoundError(
|
|
43920
|
+
"consumed",
|
|
43921
|
+
endpoint,
|
|
43922
|
+
`${label}="b${boundary.numericId}" not found in visible context (block distilled/consumed by a higher-tier block).`
|
|
43923
|
+
);
|
|
43924
|
+
}
|
|
43925
|
+
const anchor = earliestIndexOfIds(block.effectiveMessageIds, indexByRawId);
|
|
43926
|
+
if (anchor === null) {
|
|
43927
|
+
throw new BoundaryNotFoundError(
|
|
43928
|
+
"consumed",
|
|
43929
|
+
endpoint,
|
|
43930
|
+
`${label}="b${boundary.numericId}" not found in visible context (block messages consumed by a higher-tier block).`
|
|
43931
|
+
);
|
|
43932
|
+
}
|
|
43933
|
+
return anchor;
|
|
43867
43934
|
}
|
|
43868
43935
|
function formatPaddedRef(index) {
|
|
43869
43936
|
return `m${String(index).padStart(5, "0")}`;
|
|
@@ -44240,6 +44307,38 @@ function adjustBoundariesForToolPairs(startIndex, endIndex, messages, maxScan =
|
|
|
44240
44307
|
}
|
|
44241
44308
|
return { startIndex: newStartIndex, endIndex: newEndIndex };
|
|
44242
44309
|
}
|
|
44310
|
+
function adjustBoundariesForReasoningPairs(startIndex, endIndex, messages) {
|
|
44311
|
+
if (startIndex > endIndex) {
|
|
44312
|
+
return { startIndex, endIndex };
|
|
44313
|
+
}
|
|
44314
|
+
let newStartIndex = startIndex;
|
|
44315
|
+
let newEndIndex = endIndex;
|
|
44316
|
+
for (let i = startIndex; i <= endIndex && i < messages.length; i++) {
|
|
44317
|
+
const msg2 = messages[i];
|
|
44318
|
+
if (!msg2) continue;
|
|
44319
|
+
if (msg2.contentType === "reasoning") {
|
|
44320
|
+
let j2 = i;
|
|
44321
|
+
while (j2 + 1 < messages.length && messages[j2 + 1].contentType === "reasoning") {
|
|
44322
|
+
j2++;
|
|
44323
|
+
}
|
|
44324
|
+
const companion = messages[j2 + 1];
|
|
44325
|
+
if (companion !== void 0 && companion.role === "assistant" && (companion.contentType === "text" || companion.contentType === "tool-call") && j2 + 1 > newEndIndex) {
|
|
44326
|
+
newEndIndex = j2 + 1;
|
|
44327
|
+
}
|
|
44328
|
+
}
|
|
44329
|
+
if (msg2.role === "assistant" && (msg2.contentType === "text" || msg2.contentType === "tool-call")) {
|
|
44330
|
+
let k2 = i - 1;
|
|
44331
|
+
while (k2 >= 0 && messages[k2].contentType === "reasoning") {
|
|
44332
|
+
k2--;
|
|
44333
|
+
}
|
|
44334
|
+
const runStart = k2 + 1;
|
|
44335
|
+
if (runStart < i && runStart >= 0 && messages[runStart].contentType === "reasoning" && runStart < newStartIndex) {
|
|
44336
|
+
newStartIndex = runStart;
|
|
44337
|
+
}
|
|
44338
|
+
}
|
|
44339
|
+
}
|
|
44340
|
+
return { startIndex: newStartIndex, endIndex: newEndIndex };
|
|
44341
|
+
}
|
|
44243
44342
|
function refNum(ref) {
|
|
44244
44343
|
const n = parseInt(ref.slice(1), 10);
|
|
44245
44344
|
return Number.isNaN(n) ? -1 : n;
|
|
@@ -44394,6 +44493,9 @@ function runPipeline(nodes, initial, ctx) {
|
|
|
44394
44493
|
}
|
|
44395
44494
|
return io2;
|
|
44396
44495
|
}
|
|
44496
|
+
function rangeError(spec, message) {
|
|
44497
|
+
return `range ${spec.startRef}..${spec.endRef}: ${message}`;
|
|
44498
|
+
}
|
|
44397
44499
|
function createCore(ports = {}) {
|
|
44398
44500
|
const countTokens = ports.countTokens ?? defaultCountTokens;
|
|
44399
44501
|
function applyCompression(input) {
|
|
@@ -44405,20 +44507,44 @@ function createCore(ports = {}) {
|
|
|
44405
44507
|
const warnings = [];
|
|
44406
44508
|
const protectedMessageIds = input.protectedMessageIds ?? computeProtectedRefs(input.messages, input.state, input.config, countTokens);
|
|
44407
44509
|
const preExistingCoverage = collectCoverage(state);
|
|
44408
|
-
const
|
|
44510
|
+
const classifications = /* @__PURE__ */ new Map();
|
|
44511
|
+
const classificationErrors = [];
|
|
44512
|
+
const consumedRanges = [];
|
|
44409
44513
|
for (const spec of input.ranges) {
|
|
44410
|
-
let resolved;
|
|
44411
44514
|
try {
|
|
44412
|
-
resolved = resolveBoundaries({
|
|
44515
|
+
const resolved = resolveBoundaries({
|
|
44413
44516
|
startRef: spec.startRef,
|
|
44414
44517
|
endRef: spec.endRef,
|
|
44415
44518
|
messages: input.messages,
|
|
44416
44519
|
state
|
|
44417
44520
|
});
|
|
44418
|
-
|
|
44419
|
-
|
|
44521
|
+
classifications.set(spec, { status: "ok", resolved });
|
|
44522
|
+
} catch (error) {
|
|
44523
|
+
if (error instanceof BoundaryNotFoundError) {
|
|
44524
|
+
classifications.set(
|
|
44525
|
+
spec,
|
|
44526
|
+
error.kind === "unknown" ? { status: "unknown", error } : { status: "consumed", error }
|
|
44527
|
+
);
|
|
44528
|
+
if (error.kind === "consumed") {
|
|
44529
|
+
consumedRanges.push(spec);
|
|
44530
|
+
} else {
|
|
44531
|
+
classificationErrors.push(rangeError(spec, error.message));
|
|
44532
|
+
}
|
|
44533
|
+
} else {
|
|
44534
|
+
classifications.set(spec, {
|
|
44535
|
+
status: "invalid",
|
|
44536
|
+
error: error instanceof Error ? error : new Error(String(error))
|
|
44537
|
+
});
|
|
44538
|
+
classificationErrors.push(
|
|
44539
|
+
rangeError(spec, error instanceof Error ? error.message : String(error))
|
|
44540
|
+
);
|
|
44541
|
+
}
|
|
44420
44542
|
}
|
|
44421
|
-
|
|
44543
|
+
}
|
|
44544
|
+
const rangeIndexSets = [];
|
|
44545
|
+
for (const [spec, resolution] of classifications) {
|
|
44546
|
+
if (resolution.status !== "ok") continue;
|
|
44547
|
+
const indices = resolution.resolved.messageIds.map(
|
|
44422
44548
|
(id) => input.messages.findIndex((m2) => m2.id === id)
|
|
44423
44549
|
).filter((i) => i >= 0);
|
|
44424
44550
|
rangeIndexSets.push({ spec, indices });
|
|
@@ -44445,37 +44571,27 @@ function createCore(ports = {}) {
|
|
|
44445
44571
|
if (input.config.compress.minCompressRange > 0 && input.ranges.length > 0) {
|
|
44446
44572
|
let totalRangeChars = 0;
|
|
44447
44573
|
let hasBlockBoundaryRange = false;
|
|
44448
|
-
|
|
44449
|
-
|
|
44450
|
-
|
|
44451
|
-
|
|
44452
|
-
resolved = resolveBoundaries({
|
|
44453
|
-
startRef: spec.startRef,
|
|
44454
|
-
endRef: spec.endRef,
|
|
44455
|
-
messages: input.messages,
|
|
44456
|
-
state
|
|
44457
|
-
});
|
|
44458
|
-
} catch {
|
|
44459
|
-
continue;
|
|
44460
|
-
}
|
|
44461
|
-
if (resolved.boundaryKind === "block") {
|
|
44574
|
+
let countedRanges = 0;
|
|
44575
|
+
for (const [spec, resolution] of classifications) {
|
|
44576
|
+
if (resolution.status !== "ok" || skipSpecs.has(spec)) continue;
|
|
44577
|
+
if (resolution.resolved.boundaryKind === "block") {
|
|
44462
44578
|
hasBlockBoundaryRange = true;
|
|
44463
44579
|
continue;
|
|
44464
44580
|
}
|
|
44465
|
-
|
|
44581
|
+
countedRanges++;
|
|
44582
|
+
for (const id of resolution.resolved.messageIds) {
|
|
44466
44583
|
const msg2 = input.messages.find((m2) => m2.id === id);
|
|
44467
44584
|
totalRangeChars += msg2?.text?.length ?? 0;
|
|
44468
44585
|
}
|
|
44469
44586
|
}
|
|
44470
44587
|
if (!hasBlockBoundaryRange && totalRangeChars < input.config.compress.minCompressRange) {
|
|
44588
|
+
const gateMessage = consumedRanges.length > 0 ? `Requested range(s) already compressed (e.g. ${consumedRanges[0].startRef}..${consumedRanges[0].endRef}); remaining compressible content ${totalRangeChars} chars < min ${input.config.compress.minCompressRange}. Nothing to do \u2014 run acp_status to see current compressible ranges.` : `Total compressible content too small (${totalRangeChars} chars across ${countedRanges} range(s), min ${input.config.compress.minCompressRange}). Combine more messages into your range(s) to meet the threshold.`;
|
|
44471
44589
|
return {
|
|
44472
44590
|
state: input.state,
|
|
44473
44591
|
result: {
|
|
44474
44592
|
blocksCreated: 0,
|
|
44475
44593
|
tokensCompressed: 0,
|
|
44476
|
-
errors: [
|
|
44477
|
-
`Total compressible content too small (${totalRangeChars} chars across ${input.ranges.length} range(s), min ${input.config.compress.minCompressRange}). Combine more messages into your range(s) to meet the threshold.`
|
|
44478
|
-
],
|
|
44594
|
+
errors: [gateMessage, ...classificationErrors],
|
|
44479
44595
|
warnings: []
|
|
44480
44596
|
}
|
|
44481
44597
|
};
|
|
@@ -44483,6 +44599,18 @@ function createCore(ports = {}) {
|
|
|
44483
44599
|
}
|
|
44484
44600
|
for (const spec of input.ranges) {
|
|
44485
44601
|
if (skipSpecs.has(spec)) continue;
|
|
44602
|
+
const resolution = classifications.get(spec);
|
|
44603
|
+
if (resolution === void 0) continue;
|
|
44604
|
+
if (resolution.status === "consumed") {
|
|
44605
|
+
warnings.push(
|
|
44606
|
+
`Skipped range (${spec.startRef}..${spec.endRef}) \u2014 already compressed (messages consumed by existing block(s)); nothing to compress.`
|
|
44607
|
+
);
|
|
44608
|
+
continue;
|
|
44609
|
+
}
|
|
44610
|
+
if (resolution.status === "unknown" || resolution.status === "invalid") {
|
|
44611
|
+
errors.push(rangeError(spec, resolution.error.message));
|
|
44612
|
+
continue;
|
|
44613
|
+
}
|
|
44486
44614
|
try {
|
|
44487
44615
|
const outcome = applySingleRange({
|
|
44488
44616
|
spec,
|
|
@@ -44498,7 +44626,7 @@ function createCore(ports = {}) {
|
|
|
44498
44626
|
tokensCompressed += outcome.tokens;
|
|
44499
44627
|
warnings.push(...outcome.warnings);
|
|
44500
44628
|
} catch (error) {
|
|
44501
|
-
errors.push(error instanceof Error ? error.message : String(error));
|
|
44629
|
+
errors.push(rangeError(spec, error instanceof Error ? error.message : String(error)));
|
|
44502
44630
|
}
|
|
44503
44631
|
}
|
|
44504
44632
|
state.stats.compressionCount += blocksCreated;
|
|
@@ -44706,7 +44834,7 @@ function applySingleRange(input) {
|
|
|
44706
44834
|
messages: input.messages,
|
|
44707
44835
|
state: input.state
|
|
44708
44836
|
});
|
|
44709
|
-
const rangeMessageIds =
|
|
44837
|
+
const rangeMessageIds = applyPairBoundaryAdjustments(
|
|
44710
44838
|
resolved,
|
|
44711
44839
|
input.messages
|
|
44712
44840
|
);
|
|
@@ -44820,20 +44948,33 @@ function applySingleRange(input) {
|
|
|
44820
44948
|
}
|
|
44821
44949
|
return { tokens: compressedTokens, warnings };
|
|
44822
44950
|
}
|
|
44823
|
-
function
|
|
44951
|
+
function applyPairBoundaryAdjustments(resolved, messages) {
|
|
44824
44952
|
if (resolved.boundaryKind === "block") {
|
|
44825
44953
|
return resolved.messageIds;
|
|
44826
44954
|
}
|
|
44827
|
-
|
|
44828
|
-
|
|
44829
|
-
|
|
44830
|
-
|
|
44831
|
-
|
|
44832
|
-
|
|
44955
|
+
let startIndex = resolved.startIndex;
|
|
44956
|
+
let endIndex = resolved.endIndex;
|
|
44957
|
+
for (let pass = 0; pass < 2; pass++) {
|
|
44958
|
+
const reasoningAdjusted = adjustBoundariesForReasoningPairs(
|
|
44959
|
+
startIndex,
|
|
44960
|
+
endIndex,
|
|
44961
|
+
messages
|
|
44962
|
+
);
|
|
44963
|
+
const toolAdjusted = adjustBoundariesForToolPairs(
|
|
44964
|
+
reasoningAdjusted.startIndex,
|
|
44965
|
+
reasoningAdjusted.endIndex,
|
|
44966
|
+
messages
|
|
44967
|
+
);
|
|
44968
|
+
const changed = toolAdjusted.startIndex !== startIndex || toolAdjusted.endIndex !== endIndex;
|
|
44969
|
+
startIndex = toolAdjusted.startIndex;
|
|
44970
|
+
endIndex = toolAdjusted.endIndex;
|
|
44971
|
+
if (!changed) break;
|
|
44972
|
+
}
|
|
44973
|
+
if (startIndex === resolved.startIndex && endIndex === resolved.endIndex) {
|
|
44833
44974
|
return resolved.messageIds;
|
|
44834
44975
|
}
|
|
44835
44976
|
const ids = [];
|
|
44836
|
-
for (let i =
|
|
44977
|
+
for (let i = startIndex; i <= endIndex; i++) {
|
|
44837
44978
|
const msg2 = messages[i];
|
|
44838
44979
|
if (msg2) ids.push(msg2.id);
|
|
44839
44980
|
}
|
|
@@ -44933,6 +45074,7 @@ function decideNudge(input) {
|
|
|
44933
45074
|
const limit = config.modelContextLimit;
|
|
44934
45075
|
const usage = limit > 0 ? tokenCount / limit : 0;
|
|
44935
45076
|
const nudgeGrowthTokens = resolveAdaptiveGrowth(limit, config.nudge);
|
|
45077
|
+
const overLimit = usage >= config.nudge.maxContextLimitPct;
|
|
44936
45078
|
const emergencyOverride = usage >= config.nudge.emergencyThresholdPct;
|
|
44937
45079
|
const baseline = state.nudge.lastPerMessageNudgeTokens;
|
|
44938
45080
|
const hadPendingNudge = state.nudge.lastNudgeShownTokens > 0;
|
|
@@ -44949,7 +45091,7 @@ function decideNudge(input) {
|
|
|
44949
45091
|
let injectedTier = null;
|
|
44950
45092
|
let injectedReason = "";
|
|
44951
45093
|
const growthReady = growthSinceReference >= growthFloor;
|
|
44952
|
-
if (!
|
|
45094
|
+
if (!overLimit && growthReady) {
|
|
44953
45095
|
for (const tier of [1, 2, 3]) {
|
|
44954
45096
|
if (!config.tiers.enabled && tier > 1) break;
|
|
44955
45097
|
const info = tiers[tier];
|
|
@@ -44961,11 +45103,26 @@ function decideNudge(input) {
|
|
|
44961
45103
|
injectedReason = tier === 1 ? `T1 compressible ${info.pending} >= ${nudgeGrowthTokens}, growth ${growthSinceReference}, usage ${Math.round(usage * 100)}%` : `T${tier} distill ready: ${info.targetBlocks.length} tier-${tier - 1} blocks (${info.pending} tokens) >= ${nudgeGrowthTokens}, usage ${Math.round(usage * 100)}%`;
|
|
44962
45104
|
break;
|
|
44963
45105
|
}
|
|
45106
|
+
} else if (overLimit) {
|
|
45107
|
+
for (const tier of [1, 2, 3]) {
|
|
45108
|
+
if (!config.tiers.enabled && tier > 1) break;
|
|
45109
|
+
const info = tiers[tier];
|
|
45110
|
+
if (!info || info.pending < config.compress.minCompressRange) continue;
|
|
45111
|
+
injectedTier = tier;
|
|
45112
|
+
injectedReason = emergencyOverride ? `EMERGENCY: usage ${Math.round(usage * 100)}% >= ${Math.round(config.nudge.emergencyThresholdPct * 100)}%, T${tier} pending ${info.pending}` : `OVER-LIMIT: usage ${Math.round(usage * 100)}% >= ${Math.round(config.nudge.maxContextLimitPct * 100)}%, T${tier} pending ${info.pending}`;
|
|
45113
|
+
break;
|
|
45114
|
+
}
|
|
44964
45115
|
}
|
|
44965
|
-
const shouldInject =
|
|
45116
|
+
const shouldInject = injectedTier !== null || overLimit && (rec?.recommendedRanges?.length ?? 0) > 0;
|
|
44966
45117
|
let reason;
|
|
44967
|
-
if (emergencyOverride) {
|
|
44968
|
-
reason =
|
|
45118
|
+
if (emergencyOverride && injectedTier !== null) {
|
|
45119
|
+
reason = injectedReason;
|
|
45120
|
+
} else if (emergencyOverride) {
|
|
45121
|
+
reason = `EMERGENCY: usage ${Math.round(usage * 100)}% >= ${Math.round(config.nudge.emergencyThresholdPct * 100)}% (no compressible content)`;
|
|
45122
|
+
} else if (overLimit && injectedTier !== null) {
|
|
45123
|
+
reason = injectedReason;
|
|
45124
|
+
} else if (overLimit) {
|
|
45125
|
+
reason = `OVER-LIMIT: usage ${Math.round(usage * 100)}% >= ${Math.round(config.nudge.maxContextLimitPct * 100)}% (no compressible content)`;
|
|
44969
45126
|
} else if (injectedTier !== null) {
|
|
44970
45127
|
reason = injectedReason;
|
|
44971
45128
|
} else {
|
|
@@ -45001,6 +45158,7 @@ function decideNudge(input) {
|
|
|
45001
45158
|
nudgeGrowthTokens,
|
|
45002
45159
|
growthFloor,
|
|
45003
45160
|
hasPendingNudge: hasPendingNudge ? 1 : 0,
|
|
45161
|
+
overLimit: overLimit ? 1 : 0,
|
|
45004
45162
|
emergencyOverride: emergencyOverride ? 1 : 0,
|
|
45005
45163
|
pendingT1: tiers[1].pending,
|
|
45006
45164
|
pendingT2: tiers[2].pending,
|
|
@@ -45172,12 +45330,22 @@ DROP:
|
|
|
45172
45330
|
- Anything marked [OBSOLETE] or [SUPERSEDED] \u2014 drop entirely, note "[N blocks obsolete]" in the summary.
|
|
45173
45331
|
|
|
45174
45332
|
SIZE TARGET: 30-60 tokens per source block (including header). For a batch of N source blocks, total output \u2248 N \xD7 40 tokens. If a source block has only one trivial fact, output just the header + one line.`;
|
|
45175
|
-
var
|
|
45333
|
+
var defaultPrompts = Object.freeze({
|
|
45334
|
+
compressPhilosophy: COMPRESS_PHILOSOPHY,
|
|
45335
|
+
howToCompressRules: HOW_TO_COMPRESS_RULES,
|
|
45336
|
+
tier2DistillRules: TIER2_DISTILL_RULES,
|
|
45337
|
+
tier3CondenseRules: TIER3_CONDENSE_RULES
|
|
45338
|
+
});
|
|
45339
|
+
function efficiencyNote(prompts) {
|
|
45340
|
+
return `This is an efficiency nudge to compress early and keep context lean \u2014 not an overflow warning. A separate, stronger alert will appear if the context is actually full.
|
|
45176
45341
|
|
|
45177
|
-
${
|
|
45178
|
-
|
|
45342
|
+
${prompts.compressPhilosophy}`;
|
|
45343
|
+
}
|
|
45344
|
+
function emergencyHeader(prompts) {
|
|
45345
|
+
return `\u26A0\uFE0F Context limit reached \u2014 compress now. Prioritize consumed tool outputs.
|
|
45179
45346
|
|
|
45180
|
-
${
|
|
45347
|
+
${prompts.compressPhilosophy}`;
|
|
45348
|
+
}
|
|
45181
45349
|
function formatK(n) {
|
|
45182
45350
|
if (n >= 1e3) return `${(n / 1e3).toFixed(1)}K`;
|
|
45183
45351
|
return `${n}`;
|
|
@@ -45285,7 +45453,7 @@ function formatRanges(compressible, protectedRanges) {
|
|
|
45285
45453
|
return `Compressible ranges (${merged.length}, oldest first):
|
|
45286
45454
|
${lines.join("\n")}`;
|
|
45287
45455
|
}
|
|
45288
|
-
function renderNudgeText(decision) {
|
|
45456
|
+
function renderNudgeText(decision, prompts = defaultPrompts) {
|
|
45289
45457
|
const breakdownStr = formatBreakdown(decision.contextBreakdown);
|
|
45290
45458
|
const rangesStr = formatRanges(decision.compressibleRanges, decision.protectedRanges ?? []);
|
|
45291
45459
|
if (decision.tier !== null && decision.tier >= 2) {
|
|
@@ -45297,7 +45465,7 @@ function renderNudgeText(decision) {
|
|
|
45297
45465
|
return {
|
|
45298
45466
|
voice: "gentle",
|
|
45299
45467
|
text: [
|
|
45300
|
-
|
|
45468
|
+
efficiencyNote(prompts),
|
|
45301
45469
|
"",
|
|
45302
45470
|
breakdownStr,
|
|
45303
45471
|
"",
|
|
@@ -45306,22 +45474,22 @@ function renderNudgeText(decision) {
|
|
|
45306
45474
|
blockList,
|
|
45307
45475
|
`Example: compress({ content: [{ startId: "${startId}", endId: "${endId}", summary: "..." }] })`,
|
|
45308
45476
|
"",
|
|
45309
|
-
|
|
45477
|
+
prompts.howToCompressRules,
|
|
45310
45478
|
"",
|
|
45311
|
-
isT2 ?
|
|
45479
|
+
isT2 ? prompts.tier2DistillRules : prompts.tier3CondenseRules
|
|
45312
45480
|
].join("\n")
|
|
45313
45481
|
};
|
|
45314
45482
|
}
|
|
45315
|
-
const isEmergency = !!decision.breakdown?.emergencyOverride;
|
|
45483
|
+
const isEmergency = !!decision.breakdown?.emergencyOverride || !!decision.breakdown?.overLimit;
|
|
45316
45484
|
if (isEmergency) {
|
|
45317
45485
|
return {
|
|
45318
45486
|
voice: "emergency",
|
|
45319
45487
|
text: [
|
|
45320
|
-
|
|
45488
|
+
emergencyHeader(prompts),
|
|
45321
45489
|
"",
|
|
45322
45490
|
breakdownStr,
|
|
45323
45491
|
"",
|
|
45324
|
-
|
|
45492
|
+
prompts.howToCompressRules,
|
|
45325
45493
|
"",
|
|
45326
45494
|
`{ "topic": "...", "content": [{ "startId": "<ID>", "endId": "<ID>", "summary": "..." }] }`,
|
|
45327
45495
|
"Only use IDs from visible messages above. Compress older work first.",
|
|
@@ -45333,11 +45501,11 @@ function renderNudgeText(decision) {
|
|
|
45333
45501
|
return {
|
|
45334
45502
|
voice: "gentle",
|
|
45335
45503
|
text: [
|
|
45336
|
-
|
|
45504
|
+
efficiencyNote(prompts),
|
|
45337
45505
|
"",
|
|
45338
45506
|
breakdownStr,
|
|
45339
45507
|
"",
|
|
45340
|
-
|
|
45508
|
+
prompts.howToCompressRules,
|
|
45341
45509
|
"",
|
|
45342
45510
|
rangesStr,
|
|
45343
45511
|
"",
|
|
@@ -46290,29 +46458,24 @@ function lookupContextLimit(model) {
|
|
|
46290
46458
|
function resolveContextLimit(routes, upstreamUrl, model) {
|
|
46291
46459
|
return resolveConfiguredContextLimit(routes, upstreamUrl, model) ?? lookupContextLimit(model);
|
|
46292
46460
|
}
|
|
46293
|
-
function
|
|
46294
|
-
if (!
|
|
46461
|
+
function findRoute(routes, upstreamUrl) {
|
|
46462
|
+
if (!upstreamUrl) return void 0;
|
|
46295
46463
|
let bestKey = "";
|
|
46296
46464
|
for (const key of Object.keys(routes)) {
|
|
46297
46465
|
if (upstreamUrl === key || upstreamUrl.startsWith(key + "/")) {
|
|
46298
46466
|
if (key.length > bestKey.length) bestKey = key;
|
|
46299
46467
|
}
|
|
46300
46468
|
}
|
|
46301
|
-
|
|
46302
|
-
|
|
46303
|
-
|
|
46304
|
-
|
|
46469
|
+
return bestKey ? routes[bestKey] : void 0;
|
|
46470
|
+
}
|
|
46471
|
+
function resolveConfiguredContextLimit(routes, upstreamUrl, model) {
|
|
46472
|
+
if (!model || !upstreamUrl) return void 0;
|
|
46473
|
+
const m2 = findRoute(routes, upstreamUrl)?.models?.[model];
|
|
46474
|
+
if (m2?.context && m2.context > 0) return m2.context;
|
|
46305
46475
|
return void 0;
|
|
46306
46476
|
}
|
|
46307
46477
|
function resolveCompressProtocol(routes, upstreamUrl) {
|
|
46308
|
-
|
|
46309
|
-
let bestKey = "";
|
|
46310
|
-
for (const key of Object.keys(routes)) {
|
|
46311
|
-
if (upstreamUrl === key || upstreamUrl.startsWith(key + "/")) {
|
|
46312
|
-
if (key.length > bestKey.length) bestKey = key;
|
|
46313
|
-
}
|
|
46314
|
-
}
|
|
46315
|
-
return bestKey ? routes[bestKey].compressProtocol : void 0;
|
|
46478
|
+
return findRoute(routes, upstreamUrl)?.compressProtocol;
|
|
46316
46479
|
}
|
|
46317
46480
|
function loadRoutes(env = process.env) {
|
|
46318
46481
|
const fileConfig = loadConfigFile();
|
|
@@ -46388,6 +46551,7 @@ function loadOptions(env = process.env) {
|
|
|
46388
46551
|
modelContextLimit,
|
|
46389
46552
|
kernelConfig: defaultConfig(modelContextLimit),
|
|
46390
46553
|
compress: {
|
|
46554
|
+
...fileConfig.compress ?? {},
|
|
46391
46555
|
injectTool: (env.ACP_COMPRESS_TOOL ?? (fileConfig.compress?.injectTool === false ? "0" : "1")) !== "0",
|
|
46392
46556
|
injectNudge: (env.ACP_COMPRESS_NUDGE ?? (fileConfig.compress?.injectNudge === false ? "0" : "1")) !== "0"
|
|
46393
46557
|
},
|
|
@@ -46461,6 +46625,7 @@ function parseRouteEntry(v2) {
|
|
|
46461
46625
|
const route = { models: obj.models };
|
|
46462
46626
|
if (typeof obj.proxy === "string") route.proxy = obj.proxy;
|
|
46463
46627
|
if (obj.compressProtocol === "marker" || obj.compressProtocol === "tools") route.compressProtocol = obj.compressProtocol;
|
|
46628
|
+
if (obj.compress) route.compress = obj.compress;
|
|
46464
46629
|
return route;
|
|
46465
46630
|
}
|
|
46466
46631
|
if (v2 === null) return {};
|
|
@@ -46483,6 +46648,73 @@ function rejectLegacyRoute(key, value) {
|
|
|
46483
46648
|
import http from "http";
|
|
46484
46649
|
import fs5 from "fs";
|
|
46485
46650
|
|
|
46651
|
+
// src/compress-settings.ts
|
|
46652
|
+
function resolveContextLimitValue(raw, nativeLimit) {
|
|
46653
|
+
if (typeof raw === "number" && Number.isFinite(raw) && raw > 0) return Math.max(1, Math.floor(raw));
|
|
46654
|
+
if (typeof raw === "string") {
|
|
46655
|
+
const pct2 = /^(\d+(?:\.\d+)?)\s*%$/.exec(raw.trim());
|
|
46656
|
+
if (pct2) return Math.max(1, Math.floor(nativeLimit * Number(pct2[1]) / 100));
|
|
46657
|
+
const n = Number(raw);
|
|
46658
|
+
if (Number.isFinite(n) && n > 0) return Math.floor(n);
|
|
46659
|
+
}
|
|
46660
|
+
return Math.max(1, Math.floor(nativeLimit));
|
|
46661
|
+
}
|
|
46662
|
+
function mergeCompress(global2, provider, model) {
|
|
46663
|
+
const pick2 = (k2) => model?.[k2] ?? provider?.[k2] ?? global2?.[k2];
|
|
46664
|
+
return {
|
|
46665
|
+
modelContextLimit: pick2("modelContextLimit"),
|
|
46666
|
+
maxContextLimit: pick2("maxContextLimit"),
|
|
46667
|
+
emergencyThresholdPercent: pick2("emergencyThresholdPercent"),
|
|
46668
|
+
nudgeGrowthTokens: pick2("nudgeGrowthTokens"),
|
|
46669
|
+
preserveRecentMessages: pick2("preserveRecentMessages"),
|
|
46670
|
+
preserveRecentTokens: pick2("preserveRecentTokens"),
|
|
46671
|
+
minCompressRange: pick2("minCompressRange"),
|
|
46672
|
+
tiers: pick2("tiers")
|
|
46673
|
+
};
|
|
46674
|
+
}
|
|
46675
|
+
function resolveCompress(routes, upstreamUrl, model, global2) {
|
|
46676
|
+
const route = findRoute(routes, upstreamUrl);
|
|
46677
|
+
return mergeCompress(global2, route?.compress, model ? route?.models?.[model]?.compress : void 0);
|
|
46678
|
+
}
|
|
46679
|
+
function hasCompressSettings(s3) {
|
|
46680
|
+
return Object.values(s3).some((v2) => v2 !== void 0);
|
|
46681
|
+
}
|
|
46682
|
+
function applyCompressSettings(base, limit, s3) {
|
|
46683
|
+
const nudge = { ...base.nudge };
|
|
46684
|
+
const truncate = { ...base.truncate };
|
|
46685
|
+
if (s3.maxContextLimit !== void 0) nudge.maxContextLimitPct = parsePercent(s3.maxContextLimit);
|
|
46686
|
+
if (s3.emergencyThresholdPercent !== void 0) {
|
|
46687
|
+
const pct2 = parsePercent(s3.emergencyThresholdPercent);
|
|
46688
|
+
nudge.emergencyThresholdPct = pct2;
|
|
46689
|
+
truncate.threshold = pct2;
|
|
46690
|
+
}
|
|
46691
|
+
if (s3.nudgeGrowthTokens !== void 0 && s3.nudgeGrowthTokens > 0) {
|
|
46692
|
+
nudge.growthFloor = s3.nudgeGrowthTokens;
|
|
46693
|
+
nudge.growthCap = s3.nudgeGrowthTokens;
|
|
46694
|
+
}
|
|
46695
|
+
const tiers = { ...base.tiers };
|
|
46696
|
+
if (s3.tiers !== void 0) tiers.enabled = s3.tiers;
|
|
46697
|
+
return {
|
|
46698
|
+
...base,
|
|
46699
|
+
modelContextLimit: limit,
|
|
46700
|
+
nudge,
|
|
46701
|
+
truncate,
|
|
46702
|
+
tiers,
|
|
46703
|
+
preserveRecentMessages: s3.preserveRecentMessages ?? base.preserveRecentMessages,
|
|
46704
|
+
preserveRecentTokens: s3.preserveRecentTokens ?? base.preserveRecentTokens,
|
|
46705
|
+
compress: {
|
|
46706
|
+
...base.compress,
|
|
46707
|
+
minCompressRange: s3.minCompressRange ?? base.compress.minCompressRange
|
|
46708
|
+
}
|
|
46709
|
+
};
|
|
46710
|
+
}
|
|
46711
|
+
function parsePercent(v2) {
|
|
46712
|
+
if (typeof v2 === "number") return v2;
|
|
46713
|
+
const s3 = v2.trim();
|
|
46714
|
+
if (s3.endsWith("%")) return Number(s3.slice(0, -1)) / 100;
|
|
46715
|
+
return Number(s3);
|
|
46716
|
+
}
|
|
46717
|
+
|
|
46486
46718
|
// src/registry.ts
|
|
46487
46719
|
import { readFile, writeFile, mkdir } from "fs/promises";
|
|
46488
46720
|
import { existsSync as existsSync2, statSync as statSync2 } from "fs";
|
|
@@ -48978,7 +49210,7 @@ function createResponsesAdapter(textProtocol, projection) {
|
|
|
48978
49210
|
});
|
|
48979
49211
|
} else if (item?.type === "custom_tool_call") {
|
|
48980
49212
|
yield { kind: "meta", chunk: rawBuf, firstRoundOnly: false };
|
|
48981
|
-
} else if (!suppressTextLifecycle) {
|
|
49213
|
+
} else if (item?.type !== "message" || !suppressTextLifecycle) {
|
|
48982
49214
|
yield { kind: "meta", chunk: rawBuf, firstRoundOnly: true };
|
|
48983
49215
|
}
|
|
48984
49216
|
} else if (type === "response.content_part.added" || type === "response.content_part.done" || type === "response.output_text.done") {
|
|
@@ -49017,7 +49249,7 @@ function createResponsesAdapter(textProtocol, projection) {
|
|
|
49017
49249
|
}
|
|
49018
49250
|
} else if (item?.type === "custom_tool_call") {
|
|
49019
49251
|
yield { kind: "meta", chunk: rawBuf, firstRoundOnly: false };
|
|
49020
|
-
} else if (!suppressTextLifecycle) {
|
|
49252
|
+
} else if (item?.type !== "message" || !suppressTextLifecycle) {
|
|
49021
49253
|
yield { kind: "meta", chunk: rawBuf, firstRoundOnly: true };
|
|
49022
49254
|
}
|
|
49023
49255
|
} else if (type === "response.completed") {
|
|
@@ -51415,8 +51647,9 @@ ${bodyBuffer.toString("utf8")}`);
|
|
|
51415
51647
|
const model = parsed.model;
|
|
51416
51648
|
if (model) {
|
|
51417
51649
|
const embeddedUrl = route?.rewrittenUrl;
|
|
51418
|
-
|
|
51419
|
-
|
|
51650
|
+
const compress = resolveCompress(opts.routes, embeddedUrl, model, opts.compress);
|
|
51651
|
+
let native = resolveContextLimit(opts.routes, embeddedUrl, model);
|
|
51652
|
+
if (!native && embeddedUrl) {
|
|
51420
51653
|
const host = (() => {
|
|
51421
51654
|
try {
|
|
51422
51655
|
return new URL(embeddedUrl).host;
|
|
@@ -51424,10 +51657,12 @@ ${bodyBuffer.toString("utf8")}`);
|
|
|
51424
51657
|
return void 0;
|
|
51425
51658
|
}
|
|
51426
51659
|
})();
|
|
51427
|
-
|
|
51660
|
+
native = await contextFromRegistry(model, host);
|
|
51428
51661
|
}
|
|
51429
|
-
|
|
51430
|
-
|
|
51662
|
+
const limit = resolveContextLimitValue(compress.modelContextLimit, native ?? config.modelContextLimit);
|
|
51663
|
+
const tuned = hasCompressSettings(compress);
|
|
51664
|
+
if (tuned || limit !== config.modelContextLimit) {
|
|
51665
|
+
reqConfig = applyCompressSettings(config, limit, compress);
|
|
51431
51666
|
}
|
|
51432
51667
|
}
|
|
51433
51668
|
}
|
|
@@ -51523,7 +51758,7 @@ function prepareAnthropic(parsed, req, opts, core, config, log2, session) {
|
|
|
51523
51758
|
if (opts.compress.injectTool) {
|
|
51524
51759
|
toolsOut = injectTool(parsed.tools);
|
|
51525
51760
|
}
|
|
51526
|
-
if (turn.nudge?.shouldInject) {
|
|
51761
|
+
if (opts.compress.injectNudge && turn.nudge?.shouldInject) {
|
|
51527
51762
|
try {
|
|
51528
51763
|
const rendered = renderNudgeText(turn.nudge);
|
|
51529
51764
|
if (rendered.text) {
|
|
@@ -51575,7 +51810,7 @@ function prepareOpenai(parsed, req, opts, core, config, log2, session) {
|
|
|
51575
51810
|
if (shouldInject) {
|
|
51576
51811
|
toolsOut = injectOpenaiTool(parsed.tools);
|
|
51577
51812
|
}
|
|
51578
|
-
if (turn.nudge?.shouldInject && shouldInject) {
|
|
51813
|
+
if (opts.compress.injectNudge && turn.nudge?.shouldInject && shouldInject) {
|
|
51579
51814
|
try {
|
|
51580
51815
|
const rendered = renderNudgeText(turn.nudge);
|
|
51581
51816
|
if (rendered.text) {
|
|
@@ -51642,7 +51877,7 @@ function prepareResponses(parsed, req, opts, core, config, log2, session, identi
|
|
|
51642
51877
|
} else if (projection.systemParts.length > 0) {
|
|
51643
51878
|
rebuiltInput = injectResponsesDeveloperMessage(rebuiltInput, projection.systemParts.join("\n\n---\n\n"));
|
|
51644
51879
|
}
|
|
51645
|
-
if (turn.nudge?.shouldInject && shouldInject) {
|
|
51880
|
+
if (opts.compress.injectNudge && turn.nudge?.shouldInject && shouldInject) {
|
|
51646
51881
|
try {
|
|
51647
51882
|
const rendered = renderNudgeText(turn.nudge);
|
|
51648
51883
|
if (rendered.text) {
|
|
@@ -55725,7 +55960,7 @@ function stopProxy(handle2) {
|
|
|
55725
55960
|
function runClient(cmd, args, env, deps) {
|
|
55726
55961
|
const spawnImpl = deps?.spawnImpl ?? spawn;
|
|
55727
55962
|
return new Promise((resolve, reject) => {
|
|
55728
|
-
const child = spawnImpl(cmd, args, { stdio: "inherit", env });
|
|
55963
|
+
const child = spawnImpl(cmd, args, { stdio: "inherit", env, shell: process.platform === "win32" });
|
|
55729
55964
|
child.on?.("error", (...rest) => reject(rest[0]));
|
|
55730
55965
|
child.on?.("exit", (...rest) => {
|
|
55731
55966
|
const code = rest[0];
|
|
@@ -55734,31 +55969,36 @@ function runClient(cmd, args, env, deps) {
|
|
|
55734
55969
|
});
|
|
55735
55970
|
});
|
|
55736
55971
|
}
|
|
55737
|
-
|
|
55972
|
+
var PATH_EXTS = process.platform === "win32" ? [".cmd", ".bat", ".exe", ""] : [""];
|
|
55973
|
+
function resolveOnPath(name, env) {
|
|
55738
55974
|
const p2 = env.PATH;
|
|
55739
|
-
if (!p2) return
|
|
55740
|
-
|
|
55741
|
-
if (!dir)
|
|
55742
|
-
|
|
55743
|
-
const f2 = path9.join(dir, name);
|
|
55744
|
-
|
|
55745
|
-
|
|
55746
|
-
|
|
55975
|
+
if (!p2) return void 0;
|
|
55976
|
+
for (const dir of p2.split(path9.delimiter)) {
|
|
55977
|
+
if (!dir) continue;
|
|
55978
|
+
for (const ext of PATH_EXTS) {
|
|
55979
|
+
const f2 = path9.join(dir, name + ext);
|
|
55980
|
+
try {
|
|
55981
|
+
if (fs7.existsSync(f2) && fs7.statSync(f2).isFile()) return f2;
|
|
55982
|
+
} catch {
|
|
55983
|
+
}
|
|
55747
55984
|
}
|
|
55748
|
-
}
|
|
55985
|
+
}
|
|
55986
|
+
return void 0;
|
|
55749
55987
|
}
|
|
55750
55988
|
function resolveClientCommand(client, env) {
|
|
55751
55989
|
if (client === "pi") {
|
|
55752
55990
|
const piBin = env.PI_BIN?.trim();
|
|
55753
55991
|
if (piBin) return { command: piBin, prefixArgs: [] };
|
|
55754
|
-
|
|
55992
|
+
const piResolved = resolveOnPath("pi", env);
|
|
55993
|
+
if (piResolved) return { command: piResolved, prefixArgs: [] };
|
|
55755
55994
|
const cli = path9.join(
|
|
55756
55995
|
os4.homedir(),
|
|
55757
55996
|
".pi/agent/npm/node_modules/@earendil-works/pi-coding-agent/dist/cli.js"
|
|
55758
55997
|
);
|
|
55759
55998
|
return { command: process.execPath, prefixArgs: [cli] };
|
|
55760
55999
|
}
|
|
55761
|
-
|
|
56000
|
+
const resolved = resolveOnPath(client, env);
|
|
56001
|
+
return { command: resolved ?? client, prefixArgs: [] };
|
|
55762
56002
|
}
|
|
55763
56003
|
function parsePort(raw) {
|
|
55764
56004
|
const port = raw && raw.trim() ? parseInt(raw, 10) : LAUNCHER_DEFAULT_PORT;
|