@cortexkit/aft-opencode 0.64.0 → 0.65.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bg-notifications.d.ts.map +1 -1
- package/dist/config-live-reload.d.ts +2 -14
- package/dist/config-live-reload.d.ts.map +1 -1
- package/dist/config.d.ts +4 -16
- package/dist/config.d.ts.map +1 -1
- package/dist/entry/server.js +1271 -583
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1271 -583
- package/dist/shared/session-directory.d.ts +7 -2
- package/dist/shared/session-directory.d.ts.map +1 -1
- package/dist/shared/status.d.ts +2 -2
- package/dist/shared/status.d.ts.map +1 -1
- package/dist/tool-registration.d.ts +1 -1
- package/dist/tool-registration.d.ts.map +1 -1
- package/dist/tools/bash.d.ts.map +1 -1
- package/dist/tools/bash_watch.d.ts.map +1 -1
- package/dist/tools/definitions/v2.d.ts +1 -1
- package/dist/tools/definitions/v2.d.ts.map +1 -1
- package/dist/tui/shared-sidebar.d.ts +4 -0
- package/dist/tui/shared-sidebar.d.ts.map +1 -0
- package/dist/v2-session-lifecycle.d.ts.map +1 -1
- package/dist/workflow-hints.d.ts +1 -5
- package/dist/workflow-hints.d.ts.map +1 -1
- package/package.json +14 -12
- package/src/shared/session-directory.ts +80 -12
- package/src/shared/status.ts +4 -4
- package/src/tui/index.tsx +7 -3
- package/src/tui/shared-sidebar.ts +14 -0
- package/src/tui/sidebar-view.tsx +256 -245
- package/src/tui-compiled/index.tsx +4 -3
- package/src/tui-compiled/shared-sidebar-host.tsx +816 -0
- package/src/tui-compiled/shared-sidebar-local.tsx +816 -0
- package/src/tui-compiled/shared-sidebar.LICENSE +21 -0
- package/src/tui-compiled/shared-sidebar.ts +14 -0
- package/src/tui-compiled/sidebar-view.tsx +183 -221
- package/src/tui-compiled/sidebar.tsx +1 -0
- package/src/tui-compiled/v2.tsx +1 -0
package/dist/entry/server.js
CHANGED
|
@@ -8709,7 +8709,14 @@ var TERMINAL_BASH_STATUSES = new Set(TERMINAL_BG_TASK_STATUSES);
|
|
|
8709
8709
|
function isTerminalBashStatus(status, compatibilityAliases = false) {
|
|
8710
8710
|
return typeof status === "string" && (TERMINAL_BASH_STATUSES.has(status) || compatibilityAliases && (status === "cancelled" || status === "timeout"));
|
|
8711
8711
|
}
|
|
8712
|
+
|
|
8712
8713
|
// ../aft-bridge/dist/bash-format.js
|
|
8714
|
+
function formatUnknownPtyExit(taskId, data) {
|
|
8715
|
+
if (data.status !== "fate_unknown" || data.status_reason !== "AFT could not read how it ended") {
|
|
8716
|
+
return;
|
|
8717
|
+
}
|
|
8718
|
+
return `Task ${taskId}: exit status unknown (AFT could not read how it ended)`;
|
|
8719
|
+
}
|
|
8713
8720
|
function isTerminalStatus(status) {
|
|
8714
8721
|
return isTerminalBashStatus(status);
|
|
8715
8722
|
}
|
|
@@ -8733,6 +8740,79 @@ function relativePathEscapesRoot(rel, platform = process.platform) {
|
|
|
8733
8740
|
return rel === ".." || rel.startsWith("../") || platform === "win32" && rel.startsWith("..\\") || (platform === "win32" ? win32.isAbsolute(rel) : posix.isAbsolute(rel));
|
|
8734
8741
|
}
|
|
8735
8742
|
|
|
8743
|
+
// ../aft-bridge/dist/wait-clock.js
|
|
8744
|
+
var SUSPEND_SKEW_MS = 1000;
|
|
8745
|
+
var RESUME_ALLOWANCE_MS = 1e4;
|
|
8746
|
+
var DEADLINE_POLL_MS = 250;
|
|
8747
|
+
|
|
8748
|
+
class WaitClock {
|
|
8749
|
+
wallNow;
|
|
8750
|
+
awakeNow;
|
|
8751
|
+
wall;
|
|
8752
|
+
awake;
|
|
8753
|
+
skew = 0;
|
|
8754
|
+
elapsed;
|
|
8755
|
+
suspendCount = 0;
|
|
8756
|
+
lastSuspendEnd = Number.NEGATIVE_INFINITY;
|
|
8757
|
+
constructor(wallNow = Date.now, awakeNow = () => performance.now()) {
|
|
8758
|
+
this.wallNow = wallNow;
|
|
8759
|
+
this.awakeNow = awakeNow;
|
|
8760
|
+
this.wall = wallNow();
|
|
8761
|
+
this.awake = awakeNow();
|
|
8762
|
+
this.elapsed = this.awake;
|
|
8763
|
+
}
|
|
8764
|
+
now() {
|
|
8765
|
+
const wall = this.wallNow();
|
|
8766
|
+
const awake = this.awakeNow();
|
|
8767
|
+
const active = Math.max(0, awake - this.awake);
|
|
8768
|
+
this.skew = Math.max(0, this.skew + wall - this.wall - active);
|
|
8769
|
+
this.elapsed += active;
|
|
8770
|
+
if (this.skew >= SUSPEND_SKEW_MS) {
|
|
8771
|
+
this.elapsed += this.skew;
|
|
8772
|
+
this.lastSuspendEnd = this.elapsed;
|
|
8773
|
+
this.skew = 0;
|
|
8774
|
+
this.suspendCount++;
|
|
8775
|
+
}
|
|
8776
|
+
this.wall = wall;
|
|
8777
|
+
this.awake = awake;
|
|
8778
|
+
return this.elapsed;
|
|
8779
|
+
}
|
|
8780
|
+
}
|
|
8781
|
+
|
|
8782
|
+
class RequestDeadline {
|
|
8783
|
+
clock;
|
|
8784
|
+
allowResume;
|
|
8785
|
+
deadline;
|
|
8786
|
+
suspendCount;
|
|
8787
|
+
resumed = false;
|
|
8788
|
+
constructor(clock, timeoutMs, allowResume = true) {
|
|
8789
|
+
this.clock = clock;
|
|
8790
|
+
this.allowResume = allowResume;
|
|
8791
|
+
this.deadline = clock.now() + timeoutMs;
|
|
8792
|
+
this.suspendCount = clock.suspendCount;
|
|
8793
|
+
}
|
|
8794
|
+
remaining() {
|
|
8795
|
+
const now = this.clock.now();
|
|
8796
|
+
if (now >= this.deadline && this.allowResume && !this.resumed && this.clock.suspendCount > this.suspendCount && this.clock.lastSuspendEnd >= this.deadline) {
|
|
8797
|
+
this.resumed = true;
|
|
8798
|
+
this.deadline = now + RESUME_ALLOWANCE_MS;
|
|
8799
|
+
}
|
|
8800
|
+
return Math.max(0, this.deadline - now);
|
|
8801
|
+
}
|
|
8802
|
+
}
|
|
8803
|
+
function deadlineTimer(scheduler, remaining, expired) {
|
|
8804
|
+
let timer;
|
|
8805
|
+
const check = () => {
|
|
8806
|
+
const left = remaining();
|
|
8807
|
+
if (left <= 0)
|
|
8808
|
+
expired();
|
|
8809
|
+
else
|
|
8810
|
+
timer = scheduler.setTimeout(check, Math.min(left, DEADLINE_POLL_MS));
|
|
8811
|
+
};
|
|
8812
|
+
check();
|
|
8813
|
+
return () => scheduler.clearTimeout(timer);
|
|
8814
|
+
}
|
|
8815
|
+
|
|
8736
8816
|
// ../aft-bridge/dist/bash-hints.js
|
|
8737
8817
|
var DEFAULT_PRIMARY_WATCH_TIMEOUT_MS = 30000;
|
|
8738
8818
|
var MAX_WATCH_TIMEOUT_MS = 1800000;
|
|
@@ -8760,7 +8840,8 @@ function watchPollDelayMs(elapsedMs) {
|
|
|
8760
8840
|
return 1000;
|
|
8761
8841
|
}
|
|
8762
8842
|
var watchClock = {
|
|
8763
|
-
|
|
8843
|
+
source: new WaitClock,
|
|
8844
|
+
now: () => watchClock.source.now(),
|
|
8764
8845
|
sleep: abortableSleep
|
|
8765
8846
|
};
|
|
8766
8847
|
function abortableSleep(ms, signal) {
|
|
@@ -8906,6 +8987,7 @@ var GREP_SEARCH_AFT_SEARCH_HINT = "DO NOT search code by running grep/rg in bash
|
|
|
8906
8987
|
var GREP_SEARCH_GREP_HINT = "DO NOT search code by running grep/rg in bash — it is unindexed, unranked, and serial. Use the `grep` tool instead (indexed and ranked).";
|
|
8907
8988
|
var GREP_SEARCH_HINT_PREFIX = "DO NOT search code by running grep/rg in bash —";
|
|
8908
8989
|
var GREP_SEARCH_FRESHNESS_WINDOW_MS = 60000;
|
|
8990
|
+
var MTIME_CLOCK_SLACK_MS = 1;
|
|
8909
8991
|
function maybeAppendConflictsHint(output) {
|
|
8910
8992
|
if (!output.includes("Automatic merge failed; fix conflicts"))
|
|
8911
8993
|
return output;
|
|
@@ -8913,15 +8995,15 @@ function maybeAppendConflictsHint(output) {
|
|
|
8913
8995
|
return output;
|
|
8914
8996
|
return output + CONFLICT_HINT;
|
|
8915
8997
|
}
|
|
8916
|
-
function commandInvokesCodeSearch(command) {
|
|
8917
|
-
const statements = splitTopLevelStatements(command);
|
|
8998
|
+
function commandInvokesCodeSearch(command, platform = process.platform) {
|
|
8999
|
+
const statements = splitTopLevelStatements(command, platform);
|
|
8918
9000
|
if (statements === null)
|
|
8919
9001
|
return false;
|
|
8920
9002
|
for (const statement of statements) {
|
|
8921
|
-
const firstStage = firstPipelineStage(statement);
|
|
9003
|
+
const firstStage = firstPipelineStage(statement, platform);
|
|
8922
9004
|
if (firstStage === null)
|
|
8923
9005
|
continue;
|
|
8924
|
-
const firstToken = readShellToken(firstStage, skipSpaces(firstStage, 0));
|
|
9006
|
+
const firstToken = readShellToken(firstStage, skipSpaces(firstStage, 0), platform);
|
|
8925
9007
|
if (firstToken === null)
|
|
8926
9008
|
continue;
|
|
8927
9009
|
if (firstToken.token === "grep" || firstToken.token === "rg")
|
|
@@ -8929,42 +9011,43 @@ function commandInvokesCodeSearch(command) {
|
|
|
8929
9011
|
}
|
|
8930
9012
|
return false;
|
|
8931
9013
|
}
|
|
8932
|
-
function maybeAppendGrepSearchHint(output, command, aftSearchRegistered, projectRoot) {
|
|
9014
|
+
function maybeAppendGrepSearchHint(output, command, aftSearchRegistered, projectRoot, platform = process.platform, workdir) {
|
|
8933
9015
|
if (output === "")
|
|
8934
9016
|
return output;
|
|
8935
|
-
if (!commandInvokesCodeSearch(command))
|
|
9017
|
+
if (!commandInvokesCodeSearch(command, platform))
|
|
8936
9018
|
return output;
|
|
8937
9019
|
if (output.includes(GREP_SEARCH_HINT_PREFIX))
|
|
8938
9020
|
return output;
|
|
8939
|
-
if (shouldSuppressGrepSearchHint(command, projectRoot))
|
|
9021
|
+
if (shouldSuppressGrepSearchHint(command, projectRoot, platform, workdir))
|
|
8940
9022
|
return output;
|
|
8941
9023
|
const hint = aftSearchRegistered ? GREP_SEARCH_AFT_SEARCH_HINT : GREP_SEARCH_GREP_HINT;
|
|
8942
9024
|
return `${output}
|
|
8943
9025
|
|
|
8944
9026
|
${hint}`;
|
|
8945
9027
|
}
|
|
8946
|
-
function shouldSuppressGrepSearchHint(command, projectRoot) {
|
|
8947
|
-
const statements = splitTopLevelStatements(command);
|
|
9028
|
+
function shouldSuppressGrepSearchHint(command, projectRoot, platform, workdir) {
|
|
9029
|
+
const statements = splitTopLevelStatements(command, platform);
|
|
8948
9030
|
if (statements === null)
|
|
8949
9031
|
return false;
|
|
8950
|
-
if (allSearchPathOperandsAreDynamic(statements))
|
|
9032
|
+
if (allSearchPathOperandsAreDynamic(statements, platform))
|
|
8951
9033
|
return true;
|
|
8952
9034
|
const root = projectRoot?.trim();
|
|
8953
9035
|
if (!root)
|
|
8954
9036
|
return false;
|
|
8955
|
-
const
|
|
8956
|
-
|
|
9037
|
+
const paths = platform === "win32" ? path.win32 : path.posix;
|
|
9038
|
+
const resolvedRoot = paths.resolve(root);
|
|
9039
|
+
let effectiveCwd = paths.resolve(resolvedRoot, workdir ?? ".");
|
|
8957
9040
|
let sawCodeSearchStatement = false;
|
|
8958
9041
|
for (const statement of statements) {
|
|
8959
|
-
const firstStage = firstPipelineStage(statement);
|
|
9042
|
+
const firstStage = firstPipelineStage(statement, platform);
|
|
8960
9043
|
if (firstStage === null)
|
|
8961
9044
|
continue;
|
|
8962
|
-
const firstToken = readShellToken(firstStage, skipSpaces(firstStage, 0));
|
|
9045
|
+
const firstToken = readShellToken(firstStage, skipSpaces(firstStage, 0), platform);
|
|
8963
9046
|
if (firstToken === null)
|
|
8964
9047
|
continue;
|
|
8965
9048
|
const head = firstToken.token;
|
|
8966
9049
|
if (head === "cd") {
|
|
8967
|
-
effectiveCwd = nextCwdAfterCd(effectiveCwd, firstStage, firstToken.end);
|
|
9050
|
+
effectiveCwd = nextCwdAfterCd(effectiveCwd, firstStage, firstToken.end, platform);
|
|
8968
9051
|
continue;
|
|
8969
9052
|
}
|
|
8970
9053
|
if (head !== "grep" && head !== "rg")
|
|
@@ -8972,20 +9055,23 @@ function shouldSuppressGrepSearchHint(command, projectRoot) {
|
|
|
8972
9055
|
sawCodeSearchStatement = true;
|
|
8973
9056
|
if (effectiveCwd === null)
|
|
8974
9057
|
continue;
|
|
8975
|
-
if (!isDirInsideProject(resolvedRoot, effectiveCwd))
|
|
9058
|
+
if (!isDirInsideProject(resolvedRoot, effectiveCwd, platform))
|
|
8976
9059
|
continue;
|
|
8977
|
-
const operands = collectPathOperands(firstStage, firstToken.end);
|
|
9060
|
+
const operands = collectPathOperands(firstStage, firstToken.end, platform);
|
|
8978
9061
|
if (operands.length === 0)
|
|
8979
9062
|
return false;
|
|
8980
9063
|
let sawInProjectOperand = false;
|
|
8981
9064
|
for (const operand of operands) {
|
|
8982
9065
|
if (isDynamicPathOperand(operand))
|
|
8983
9066
|
continue;
|
|
8984
|
-
const resolvedOperand = resolvePathOperand(effectiveCwd, operand);
|
|
8985
|
-
if (!isPathInsideProject(resolvedRoot, effectiveCwd, operand))
|
|
9067
|
+
const resolvedOperand = resolvePathOperand(effectiveCwd, operand, platform);
|
|
9068
|
+
if (!isPathInsideProject(resolvedRoot, effectiveCwd, operand, platform))
|
|
9069
|
+
continue;
|
|
9070
|
+
const suppress = shouldSuppressResolvedPath(resolvedOperand);
|
|
9071
|
+
if (suppress === undefined)
|
|
8986
9072
|
continue;
|
|
8987
9073
|
sawInProjectOperand = true;
|
|
8988
|
-
if (
|
|
9074
|
+
if (suppress)
|
|
8989
9075
|
return true;
|
|
8990
9076
|
}
|
|
8991
9077
|
if (sawInProjectOperand)
|
|
@@ -8993,19 +9079,19 @@ function shouldSuppressGrepSearchHint(command, projectRoot) {
|
|
|
8993
9079
|
}
|
|
8994
9080
|
return sawCodeSearchStatement;
|
|
8995
9081
|
}
|
|
8996
|
-
function allSearchPathOperandsAreDynamic(statements) {
|
|
9082
|
+
function allSearchPathOperandsAreDynamic(statements, platform) {
|
|
8997
9083
|
let sawDynamicOnlySearch = false;
|
|
8998
9084
|
for (const statement of statements) {
|
|
8999
|
-
const firstStage = firstPipelineStage(statement);
|
|
9085
|
+
const firstStage = firstPipelineStage(statement, platform);
|
|
9000
9086
|
if (firstStage === null)
|
|
9001
9087
|
continue;
|
|
9002
|
-
const firstToken = readShellToken(firstStage, skipSpaces(firstStage, 0));
|
|
9088
|
+
const firstToken = readShellToken(firstStage, skipSpaces(firstStage, 0), platform);
|
|
9003
9089
|
if (firstToken === null)
|
|
9004
9090
|
continue;
|
|
9005
9091
|
const head = firstToken.token;
|
|
9006
9092
|
if (head !== "grep" && head !== "rg")
|
|
9007
9093
|
continue;
|
|
9008
|
-
const operands = collectPathOperands(firstStage, firstToken.end);
|
|
9094
|
+
const operands = collectPathOperands(firstStage, firstToken.end, platform);
|
|
9009
9095
|
if (operands.length === 0)
|
|
9010
9096
|
return false;
|
|
9011
9097
|
if (operands.some((operand) => !isDynamicPathOperand(operand)))
|
|
@@ -9014,11 +9100,12 @@ function allSearchPathOperandsAreDynamic(statements) {
|
|
|
9014
9100
|
}
|
|
9015
9101
|
return sawDynamicOnlySearch;
|
|
9016
9102
|
}
|
|
9017
|
-
function nextCwdAfterCd(currentCwd, firstStage, afterCd) {
|
|
9103
|
+
function nextCwdAfterCd(currentCwd, firstStage, afterCd, platform) {
|
|
9104
|
+
const paths = platform === "win32" ? path.win32 : path.posix;
|
|
9018
9105
|
let index = skipSpaces(firstStage, afterCd);
|
|
9019
9106
|
let target = null;
|
|
9020
9107
|
while (index < firstStage.length) {
|
|
9021
|
-
const tokenResult = readShellToken(firstStage, index);
|
|
9108
|
+
const tokenResult = readShellToken(firstStage, index, platform);
|
|
9022
9109
|
if (tokenResult === null)
|
|
9023
9110
|
break;
|
|
9024
9111
|
const { token, end } = tokenResult;
|
|
@@ -9033,28 +9120,29 @@ function nextCwdAfterCd(currentCwd, firstStage, afterCd) {
|
|
|
9033
9120
|
break;
|
|
9034
9121
|
}
|
|
9035
9122
|
if (target === null)
|
|
9036
|
-
return
|
|
9123
|
+
return paths.resolve(os.homedir());
|
|
9037
9124
|
if (target.includes("$") || target.includes("`"))
|
|
9038
9125
|
return null;
|
|
9039
|
-
const expanded = expandTilde(target);
|
|
9040
|
-
if (
|
|
9041
|
-
return
|
|
9126
|
+
const expanded = expandTilde(target, platform);
|
|
9127
|
+
if (paths.isAbsolute(expanded))
|
|
9128
|
+
return paths.resolve(expanded);
|
|
9042
9129
|
if (currentCwd === null)
|
|
9043
9130
|
return null;
|
|
9044
|
-
return
|
|
9131
|
+
return paths.resolve(currentCwd, expanded);
|
|
9045
9132
|
}
|
|
9046
|
-
function isDirInsideProject(resolvedRoot, dir) {
|
|
9047
|
-
const
|
|
9048
|
-
|
|
9133
|
+
function isDirInsideProject(resolvedRoot, dir, platform) {
|
|
9134
|
+
const paths = platform === "win32" ? path.win32 : path.posix;
|
|
9135
|
+
const rel = paths.relative(resolvedRoot, paths.resolve(dir));
|
|
9136
|
+
return !relativePathEscapesRoot(rel, platform);
|
|
9049
9137
|
}
|
|
9050
|
-
function collectPathOperands(firstStage, startAfterCommand) {
|
|
9138
|
+
function collectPathOperands(firstStage, startAfterCommand, platform) {
|
|
9051
9139
|
const operands = [];
|
|
9052
9140
|
let index = skipSpaces(firstStage, startAfterCommand);
|
|
9053
9141
|
let sawPattern = false;
|
|
9054
9142
|
let optionsEnded = false;
|
|
9055
9143
|
let optionValue;
|
|
9056
9144
|
while (index < firstStage.length) {
|
|
9057
|
-
const tokenResult = readShellToken(firstStage, index);
|
|
9145
|
+
const tokenResult = readShellToken(firstStage, index, platform);
|
|
9058
9146
|
if (tokenResult === null)
|
|
9059
9147
|
break;
|
|
9060
9148
|
const { token, end } = tokenResult;
|
|
@@ -9113,22 +9201,25 @@ function collectPathOperands(firstStage, startAfterCommand) {
|
|
|
9113
9201
|
function isDynamicPathOperand(token) {
|
|
9114
9202
|
return token.startsWith("~") || token.includes("$") || token.includes("`");
|
|
9115
9203
|
}
|
|
9116
|
-
function expandTilde(target) {
|
|
9204
|
+
function expandTilde(target, platform) {
|
|
9117
9205
|
if (!target.startsWith("~"))
|
|
9118
9206
|
return target;
|
|
9119
9207
|
if (target === "~" || target.startsWith("~/")) {
|
|
9120
|
-
|
|
9208
|
+
const paths = platform === "win32" ? path.win32 : path.posix;
|
|
9209
|
+
return paths.join(os.homedir(), target.slice(1));
|
|
9121
9210
|
}
|
|
9122
9211
|
return target;
|
|
9123
9212
|
}
|
|
9124
|
-
function resolvePathOperand(projectRoot, operand) {
|
|
9125
|
-
const
|
|
9126
|
-
|
|
9213
|
+
function resolvePathOperand(projectRoot, operand, platform) {
|
|
9214
|
+
const paths = platform === "win32" ? path.win32 : path.posix;
|
|
9215
|
+
const expanded = expandTilde(operand, platform);
|
|
9216
|
+
return paths.isAbsolute(expanded) ? paths.resolve(expanded) : paths.resolve(projectRoot, expanded);
|
|
9127
9217
|
}
|
|
9128
|
-
function isPathInsideProject(resolvedRoot, baseCwd, operand) {
|
|
9129
|
-
const
|
|
9130
|
-
const
|
|
9131
|
-
|
|
9218
|
+
function isPathInsideProject(resolvedRoot, baseCwd, operand, platform) {
|
|
9219
|
+
const paths = platform === "win32" ? path.win32 : path.posix;
|
|
9220
|
+
const resolved = resolvePathOperand(baseCwd, operand, platform);
|
|
9221
|
+
const rel = paths.relative(resolvedRoot, resolved);
|
|
9222
|
+
return !relativePathEscapesRoot(rel, platform);
|
|
9132
9223
|
}
|
|
9133
9224
|
function shouldSuppressResolvedPath(resolved) {
|
|
9134
9225
|
try {
|
|
@@ -9136,12 +9227,12 @@ function shouldSuppressResolvedPath(resolved) {
|
|
|
9136
9227
|
if (stats.isFile())
|
|
9137
9228
|
return true;
|
|
9138
9229
|
const ageMs = Date.now() - stats.mtimeMs;
|
|
9139
|
-
return ageMs
|
|
9230
|
+
return ageMs > -MTIME_CLOCK_SLACK_MS && ageMs < GREP_SEARCH_FRESHNESS_WINDOW_MS;
|
|
9140
9231
|
} catch {
|
|
9141
|
-
return
|
|
9232
|
+
return;
|
|
9142
9233
|
}
|
|
9143
9234
|
}
|
|
9144
|
-
function splitTopLevelStatements(command) {
|
|
9235
|
+
function splitTopLevelStatements(command, platform = process.platform) {
|
|
9145
9236
|
const statements = [];
|
|
9146
9237
|
let start = 0;
|
|
9147
9238
|
let quote = "none";
|
|
@@ -9160,7 +9251,7 @@ function splitTopLevelStatements(command) {
|
|
|
9160
9251
|
continue;
|
|
9161
9252
|
}
|
|
9162
9253
|
if (quote === "double") {
|
|
9163
|
-
if (ch === "\\")
|
|
9254
|
+
if (ch === "\\" && backslashEscapesNext(command[index + 1], quote, platform))
|
|
9164
9255
|
escaped = true;
|
|
9165
9256
|
else if (ch === '"')
|
|
9166
9257
|
quote = "none";
|
|
@@ -9171,7 +9262,7 @@ function splitTopLevelStatements(command) {
|
|
|
9171
9262
|
inBacktick = false;
|
|
9172
9263
|
continue;
|
|
9173
9264
|
}
|
|
9174
|
-
if (ch === "\\") {
|
|
9265
|
+
if (ch === "\\" && backslashEscapesNext(command[index + 1], quote, platform)) {
|
|
9175
9266
|
escaped = true;
|
|
9176
9267
|
continue;
|
|
9177
9268
|
}
|
|
@@ -9214,7 +9305,7 @@ function splitTopLevelStatements(command) {
|
|
|
9214
9305
|
statements.push(command.slice(start));
|
|
9215
9306
|
return statements;
|
|
9216
9307
|
}
|
|
9217
|
-
function firstPipelineStage(command) {
|
|
9308
|
+
function firstPipelineStage(command, platform = process.platform) {
|
|
9218
9309
|
let quote = "none";
|
|
9219
9310
|
let firstPipeIndex;
|
|
9220
9311
|
for (let index = 0;index < command.length; index++) {
|
|
@@ -9227,7 +9318,7 @@ function firstPipelineStage(command) {
|
|
|
9227
9318
|
if (quote === "double") {
|
|
9228
9319
|
if (ch === '"') {
|
|
9229
9320
|
quote = "none";
|
|
9230
|
-
} else if (ch === "\\") {
|
|
9321
|
+
} else if (ch === "\\" && backslashEscapesNext(command[index + 1], quote, platform)) {
|
|
9231
9322
|
index++;
|
|
9232
9323
|
} else if (ch === "`") {
|
|
9233
9324
|
return null;
|
|
@@ -9238,7 +9329,7 @@ function firstPipelineStage(command) {
|
|
|
9238
9329
|
quote = "single";
|
|
9239
9330
|
} else if (ch === '"') {
|
|
9240
9331
|
quote = "double";
|
|
9241
|
-
} else if (ch === "\\") {
|
|
9332
|
+
} else if (ch === "\\" && backslashEscapesNext(command[index + 1], quote, platform)) {
|
|
9242
9333
|
index++;
|
|
9243
9334
|
} else if (ch === "`") {
|
|
9244
9335
|
return null;
|
|
@@ -9254,7 +9345,7 @@ function firstPipelineStage(command) {
|
|
|
9254
9345
|
return null;
|
|
9255
9346
|
return command.slice(0, firstPipeIndex ?? command.length).trim();
|
|
9256
9347
|
}
|
|
9257
|
-
function readShellToken(command, start) {
|
|
9348
|
+
function readShellToken(command, start, platform = process.platform) {
|
|
9258
9349
|
let quote = "none";
|
|
9259
9350
|
let token = "";
|
|
9260
9351
|
let index = start;
|
|
@@ -9271,9 +9362,11 @@ function readShellToken(command, start) {
|
|
|
9271
9362
|
if (quote === "double") {
|
|
9272
9363
|
if (ch === '"') {
|
|
9273
9364
|
quote = "none";
|
|
9274
|
-
} else if (ch === "\\") {
|
|
9365
|
+
} else if (ch === "\\" && backslashEscapesNext(command[index + 1], quote, platform)) {
|
|
9275
9366
|
index++;
|
|
9276
|
-
|
|
9367
|
+
if (command[index] !== `
|
|
9368
|
+
`)
|
|
9369
|
+
token += command[index];
|
|
9277
9370
|
} else if (ch === "`") {
|
|
9278
9371
|
return null;
|
|
9279
9372
|
} else {
|
|
@@ -9289,7 +9382,7 @@ function readShellToken(command, start) {
|
|
|
9289
9382
|
quote = "single";
|
|
9290
9383
|
} else if (ch === '"') {
|
|
9291
9384
|
quote = "double";
|
|
9292
|
-
} else if (ch === "\\") {
|
|
9385
|
+
} else if (ch === "\\" && backslashEscapesNext(command[index + 1], quote, platform)) {
|
|
9293
9386
|
index++;
|
|
9294
9387
|
token += command[index] ?? "\\";
|
|
9295
9388
|
} else if (ch === "`") {
|
|
@@ -9302,6 +9395,11 @@ function readShellToken(command, start) {
|
|
|
9302
9395
|
return null;
|
|
9303
9396
|
return { token, end: index };
|
|
9304
9397
|
}
|
|
9398
|
+
function backslashEscapesNext(next, quote, platform) {
|
|
9399
|
+
if (quote === "double")
|
|
9400
|
+
return next !== undefined && '$`"\\\n'.includes(next);
|
|
9401
|
+
return platform !== "win32";
|
|
9402
|
+
}
|
|
9305
9403
|
function isTokenBoundary(ch) {
|
|
9306
9404
|
return ch === "|" || ch === ";" || ch === "&" || ch === "<" || ch === ">";
|
|
9307
9405
|
}
|
|
@@ -9313,7 +9411,7 @@ function skipSpaces(input, start) {
|
|
|
9313
9411
|
}
|
|
9314
9412
|
// ../aft-bridge/dist/bash-host-fallback.js
|
|
9315
9413
|
import { existsSync } from "node:fs";
|
|
9316
|
-
import { join as
|
|
9414
|
+
import { join as join3 } from "node:path";
|
|
9317
9415
|
|
|
9318
9416
|
// ../aft-bridge/dist/child-process.js
|
|
9319
9417
|
import { execFile as nodeExecFile, execFileSync as nodeExecFileSync, execSync as nodeExecSync, spawn as nodeSpawn, spawnSync as nodeSpawnSync } from "node:child_process";
|
|
@@ -9321,7 +9419,7 @@ import { execFile as nodeExecFile, execFileSync as nodeExecFileSync, execSync as
|
|
|
9321
9419
|
// ../aft-bridge/dist/test-child-environment.js
|
|
9322
9420
|
import { mkdirSync, realpathSync } from "node:fs";
|
|
9323
9421
|
import { homedir as homedir2, tmpdir } from "node:os";
|
|
9324
|
-
import { dirname, isAbsolute
|
|
9422
|
+
import { dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
9325
9423
|
var DIRECTORIES = [
|
|
9326
9424
|
"HOME",
|
|
9327
9425
|
"USERPROFILE",
|
|
@@ -9341,8 +9439,8 @@ function toolchainHomes(inherited) {
|
|
|
9341
9439
|
if (!global[TOOLCHAINS]) {
|
|
9342
9440
|
const home = process.platform === "win32" ? inherited.USERPROFILE || inherited.HOME || homedir2() : inherited.HOME || homedir2();
|
|
9343
9441
|
global[TOOLCHAINS] = {
|
|
9344
|
-
RUSTUP_HOME: inherited.RUSTUP_HOME ||
|
|
9345
|
-
CARGO_HOME: inherited.CARGO_HOME ||
|
|
9442
|
+
RUSTUP_HOME: inherited.RUSTUP_HOME || join(home, ".rustup"),
|
|
9443
|
+
CARGO_HOME: inherited.CARGO_HOME || join(home, ".cargo")
|
|
9346
9444
|
};
|
|
9347
9445
|
}
|
|
9348
9446
|
return global[TOOLCHAINS];
|
|
@@ -9369,31 +9467,31 @@ function isolatedAftEnvironment(root, inherited = process.env) {
|
|
|
9369
9467
|
"aft-cache"
|
|
9370
9468
|
];
|
|
9371
9469
|
for (const [index, key] of DIRECTORIES.entries()) {
|
|
9372
|
-
env[key] =
|
|
9470
|
+
env[key] = join(root, names[index]);
|
|
9373
9471
|
mkdirSync(env[key], { recursive: true });
|
|
9374
9472
|
}
|
|
9375
9473
|
delete env.AFT_ALLOW_PRODUCTION_MIGRATION;
|
|
9376
|
-
createdRoots().add(
|
|
9474
|
+
createdRoots().add(resolve(root));
|
|
9377
9475
|
return env;
|
|
9378
9476
|
}
|
|
9379
9477
|
function canonical(path) {
|
|
9380
|
-
let ancestor =
|
|
9478
|
+
let ancestor = resolve(path);
|
|
9381
9479
|
const tail = [];
|
|
9382
9480
|
while (true) {
|
|
9383
9481
|
try {
|
|
9384
|
-
return
|
|
9482
|
+
return join(realpathSync(ancestor), ...tail);
|
|
9385
9483
|
} catch {
|
|
9386
9484
|
const parent = dirname(ancestor);
|
|
9387
9485
|
if (parent === ancestor)
|
|
9388
|
-
return
|
|
9389
|
-
tail.unshift(
|
|
9486
|
+
return resolve(path);
|
|
9487
|
+
tail.unshift(relative(parent, ancestor));
|
|
9390
9488
|
ancestor = parent;
|
|
9391
9489
|
}
|
|
9392
9490
|
}
|
|
9393
9491
|
}
|
|
9394
9492
|
function within(path, root) {
|
|
9395
|
-
const tail =
|
|
9396
|
-
return tail === "" || !tail.startsWith("..") && !
|
|
9493
|
+
const tail = relative(canonical(root), canonical(path));
|
|
9494
|
+
return tail === "" || !tail.startsWith("..") && !isAbsolute(tail);
|
|
9397
9495
|
}
|
|
9398
9496
|
function testChildEnvironment(env) {
|
|
9399
9497
|
const root = process.env.AFT_TEST_ISOLATION_ROOT;
|
|
@@ -9469,7 +9567,7 @@ function withPathPrepended(env, dir, platform = process.platform) {
|
|
|
9469
9567
|
|
|
9470
9568
|
// ../aft-bridge/dist/storage-paths.js
|
|
9471
9569
|
import { homedir as homedir3, tmpdir as tmpdir2 } from "node:os";
|
|
9472
|
-
import { join as
|
|
9570
|
+
import { join as join2, resolve as resolve2 } from "node:path";
|
|
9473
9571
|
function environmentValue(context, name) {
|
|
9474
9572
|
const value = (context.lookup ?? ((key) => process.env[key]))(name);
|
|
9475
9573
|
return value !== undefined && value.length > 0 ? value : undefined;
|
|
@@ -9491,21 +9589,21 @@ function resolveDataHome(context = {}) {
|
|
|
9491
9589
|
return localAppData;
|
|
9492
9590
|
const userProfile = environmentValue(context, "USERPROFILE");
|
|
9493
9591
|
if (userProfile)
|
|
9494
|
-
return
|
|
9592
|
+
return join2(userProfile, "AppData", "Local");
|
|
9495
9593
|
}
|
|
9496
9594
|
const home = environmentValue(context, "HOME");
|
|
9497
9595
|
if (home)
|
|
9498
|
-
return
|
|
9499
|
-
return
|
|
9596
|
+
return join2(home, ".local", "share");
|
|
9597
|
+
return join2(".local", "share");
|
|
9500
9598
|
}
|
|
9501
9599
|
function resolveStoragePath(raw, context = {}) {
|
|
9502
9600
|
let expanded = raw;
|
|
9503
9601
|
if (raw === "~") {
|
|
9504
9602
|
expanded = homeDir(context);
|
|
9505
9603
|
} else if (raw.startsWith("~/") || raw.startsWith("~\\")) {
|
|
9506
|
-
expanded =
|
|
9604
|
+
expanded = join2(homeDir(context), raw.slice(2));
|
|
9507
9605
|
}
|
|
9508
|
-
return
|
|
9606
|
+
return resolve2(context.currentDirectory ?? process.cwd(), expanded);
|
|
9509
9607
|
}
|
|
9510
9608
|
function resolveCortexKitStorageRoot(context = {}) {
|
|
9511
9609
|
const override = environmentValue(context, "AFT_STORAGE_DIR");
|
|
@@ -9513,8 +9611,8 @@ function resolveCortexKitStorageRoot(context = {}) {
|
|
|
9513
9611
|
return resolveStoragePath(override, context);
|
|
9514
9612
|
const legacyCache = environmentValue(context, "AFT_CACHE_DIR");
|
|
9515
9613
|
if (legacyCache)
|
|
9516
|
-
return
|
|
9517
|
-
return resolveStoragePath(
|
|
9614
|
+
return join2(resolveStoragePath(legacyCache, context), "aft");
|
|
9615
|
+
return resolveStoragePath(join2(resolveDataHome(context), "cortexkit", "aft"), context);
|
|
9518
9616
|
}
|
|
9519
9617
|
function resolveAftStorageRoot(configuredRoot, context = {}) {
|
|
9520
9618
|
if (environmentValue(context, "AFT_STORAGE_DIR")) {
|
|
@@ -9525,14 +9623,14 @@ function resolveAftStorageRoot(configuredRoot, context = {}) {
|
|
|
9525
9623
|
return resolveCortexKitStorageRoot(context);
|
|
9526
9624
|
}
|
|
9527
9625
|
function resolveAftLogPath(filename, configuredRoot, context = {}) {
|
|
9528
|
-
return
|
|
9626
|
+
return join2(resolveAftStorageRoot(configuredRoot, context), "logs", filename);
|
|
9529
9627
|
}
|
|
9530
9628
|
function isTestEnvironment(context = {}) {
|
|
9531
9629
|
return environmentValue(context, "BUN_TEST") === "1" || environmentValue(context, "NODE_ENV") === "test";
|
|
9532
9630
|
}
|
|
9533
9631
|
function resolvePluginLogPath(context = {}) {
|
|
9534
9632
|
if (isTestEnvironment(context)) {
|
|
9535
|
-
return
|
|
9633
|
+
return join2(environmentValue(context, "TMPDIR") ?? tmpdir2(), `aft-plugin-tests-${process.pid}`, "logs", "aft-plugin-test.log");
|
|
9536
9634
|
}
|
|
9537
9635
|
return resolveAftLogPath("aft-plugin.log", undefined, context);
|
|
9538
9636
|
}
|
|
@@ -9567,8 +9665,8 @@ function hostFallbackEnvWithShims(env, platform) {
|
|
|
9567
9665
|
const pathKey = pathKeyForPlatform(normalized, platform);
|
|
9568
9666
|
const inherited = pathKey === undefined ? undefined : normalized[pathKey];
|
|
9569
9667
|
const storageRoot = normalized.AFT_STORAGE_DIR ? resolveStoragePath(normalized.AFT_STORAGE_DIR) : resolveCortexKitStorageRoot();
|
|
9570
|
-
const shimsDir =
|
|
9571
|
-
if (!existsSync(
|
|
9668
|
+
const shimsDir = join3(storageRoot, "shims");
|
|
9669
|
+
if (!existsSync(join3(shimsDir, platform === "win32" ? "gh.cmd" : "gh")))
|
|
9572
9670
|
return normalized;
|
|
9573
9671
|
const separator = platform === "win32" ? ";" : ":";
|
|
9574
9672
|
const entries = (inherited ?? "").split(separator).filter((entry) => entry.length > 0);
|
|
@@ -10344,7 +10442,7 @@ async function cachedFileSha256(path) {
|
|
|
10344
10442
|
}
|
|
10345
10443
|
// ../aft-bridge/dist/bridge.js
|
|
10346
10444
|
import { homedir as homedir4 } from "node:os";
|
|
10347
|
-
import { join as
|
|
10445
|
+
import { join as join4 } from "node:path";
|
|
10348
10446
|
import { StringDecoder } from "node:string_decoder";
|
|
10349
10447
|
|
|
10350
10448
|
// ../aft-bridge/dist/command-timeouts.js
|
|
@@ -10482,6 +10580,7 @@ function compareSemver(a, b) {
|
|
|
10482
10580
|
}
|
|
10483
10581
|
var SYSTEM_CLOCK = {
|
|
10484
10582
|
now: () => Date.now(),
|
|
10583
|
+
awakeNow: () => performance.now(),
|
|
10485
10584
|
setTimeout: (callback, ms) => setTimeout(callback, ms),
|
|
10486
10585
|
clearTimeout: (timer) => clearTimeout(timer)
|
|
10487
10586
|
};
|
|
@@ -10598,6 +10697,7 @@ class BinaryBridge {
|
|
|
10598
10697
|
hangWindowMinMs;
|
|
10599
10698
|
hangProbeTimeoutMs;
|
|
10600
10699
|
clock;
|
|
10700
|
+
waitClock;
|
|
10601
10701
|
lateShellReplyGraceMs;
|
|
10602
10702
|
maxRestarts;
|
|
10603
10703
|
configured = false;
|
|
@@ -10634,6 +10734,7 @@ class BinaryBridge {
|
|
|
10634
10734
|
this.hangWindowMinMs = options?.hangWindowMinMs ?? DEFAULT_MIN_HANG_WINDOW_MS;
|
|
10635
10735
|
this.hangProbeTimeoutMs = options?.hangProbeTimeoutMs ?? DEFAULT_HANG_PROBE_TIMEOUT_MS;
|
|
10636
10736
|
this.clock = options?.clock ?? SYSTEM_CLOCK;
|
|
10737
|
+
this.waitClock = new WaitClock(() => this.clock.now(), () => this.clock.awakeNow?.() ?? this.clock.now());
|
|
10637
10738
|
this.lateShellReplyGraceMs = options?.lateShellReplyGraceMs ?? DEFAULT_LATE_SHELL_REPLY_GRACE_MS;
|
|
10638
10739
|
this.maxRestarts = options?.maxRestarts ?? 3;
|
|
10639
10740
|
this.errorPrefix = options?.errorPrefix ?? "[aft-bridge]";
|
|
@@ -11000,11 +11101,17 @@ class BinaryBridge {
|
|
|
11000
11101
|
const keepBridgeOnTimeout = passive || command === "bash_drain_completions" || options?.keepBridgeOnTimeout === true;
|
|
11001
11102
|
const child = this.process;
|
|
11002
11103
|
const response = await new Promise((resolve, reject) => {
|
|
11003
|
-
const
|
|
11104
|
+
const deadline = new RequestDeadline(this.waitClock, effectiveTimeoutMs);
|
|
11105
|
+
const expire = () => {
|
|
11004
11106
|
const entry = this.pending.get(id);
|
|
11005
11107
|
if (!entry)
|
|
11006
11108
|
return;
|
|
11007
|
-
|
|
11109
|
+
const remaining = deadline.remaining();
|
|
11110
|
+
if (remaining > 0) {
|
|
11111
|
+
entry.timer = this.clock.setTimeout(expire, Math.min(remaining, DEADLINE_POLL_MS));
|
|
11112
|
+
return;
|
|
11113
|
+
}
|
|
11114
|
+
if (keepBridgeOnTimeout && !deadline.resumed && this.holdForLateShellReply(id, entry, effectiveTimeoutMs, requestSessionId)) {
|
|
11008
11115
|
return;
|
|
11009
11116
|
}
|
|
11010
11117
|
this.pending.delete(id);
|
|
@@ -11017,11 +11124,12 @@ class BinaryBridge {
|
|
|
11017
11124
|
this.warnVia(timeoutMsg);
|
|
11018
11125
|
}
|
|
11019
11126
|
if (keepBridgeOnTimeout) {
|
|
11020
|
-
entry.reject(new BridgeTransportTimeoutError(command, effectiveTimeoutMs, `${this.errorPrefix} Request "${command}" (id=${id}) timed out after ${effectiveTimeoutMs}ms
|
|
11127
|
+
entry.reject(new BridgeTransportTimeoutError(command, effectiveTimeoutMs, `${this.errorPrefix} Request "${command}" (id=${id}) timed out after ${effectiveTimeoutMs}ms`, deadline.resumed && SHELL_TASK_COMMANDS.has(command) ? { kind: "unknown" } : undefined));
|
|
11021
11128
|
return;
|
|
11022
11129
|
}
|
|
11023
11130
|
entry.reject(new Error(`${this.errorPrefix} request "${command}" timed out after ${effectiveTimeoutMs}ms (bridge busy/under load); bridge kept warm — retry. A timed-out mutation may still complete; inspect before repeating it.`));
|
|
11024
|
-
}
|
|
11131
|
+
};
|
|
11132
|
+
const timer = this.clock.setTimeout(expire, Math.min(effectiveTimeoutMs, DEADLINE_POLL_MS));
|
|
11025
11133
|
const entry = {
|
|
11026
11134
|
resolve,
|
|
11027
11135
|
reject,
|
|
@@ -11252,11 +11360,11 @@ class BinaryBridge {
|
|
|
11252
11360
|
})();
|
|
11253
11361
|
const useFastembedBackend = semanticBackend === undefined || semanticBackend === "fastembed" || semanticBackend === "";
|
|
11254
11362
|
const ortDir = typeof this.configOverrides._ort_dylib_dir === "string" && useFastembedBackend ? this.configOverrides._ort_dylib_dir : null;
|
|
11255
|
-
const ortLibraryPath = ortDir == null ? null :
|
|
11363
|
+
const ortLibraryPath = ortDir == null ? null : join4(ortDir, this.platform === "win32" ? "onnxruntime.dll" : this.platform === "darwin" ? "libonnxruntime.dylib" : "libonnxruntime.so");
|
|
11256
11364
|
const env = { ...process.env };
|
|
11257
11365
|
this.logVia(`bridge.spawnProcess: useFastembedBackend=${useFastembedBackend}, ` + `parentORT=${process.env.ORT_DYLIB_PATH ?? "(unset)"}, ` + `ortLibraryPath=${ortLibraryPath ?? "(none)"}`);
|
|
11258
11366
|
if (useFastembedBackend) {
|
|
11259
|
-
env.FASTEMBED_CACHE_DIR = process.env.FASTEMBED_CACHE_DIR || (typeof this.configOverrides.storage_dir === "string" ?
|
|
11367
|
+
env.FASTEMBED_CACHE_DIR = process.env.FASTEMBED_CACHE_DIR || (typeof this.configOverrides.storage_dir === "string" ? join4(this.configOverrides.storage_dir, "semantic", "models") : join4(homedir4() || "", ".cache", "fastembed"));
|
|
11260
11368
|
if (process.env.ORT_DYLIB_PATH) {
|
|
11261
11369
|
this.logVia(`ORT_DYLIB_PATH inherited from parent env: ${process.env.ORT_DYLIB_PATH}`);
|
|
11262
11370
|
} else if (ortLibraryPath) {
|
|
@@ -11577,14 +11685,21 @@ class BinaryBridge {
|
|
|
11577
11685
|
};
|
|
11578
11686
|
entry.resolve = (response) => settle(shellOutcomeFromLateReply(response));
|
|
11579
11687
|
this.clock.clearTimeout(entry.timer);
|
|
11580
|
-
|
|
11688
|
+
const deadline = new RequestDeadline(this.waitClock, graceMs, false);
|
|
11689
|
+
const expire = () => {
|
|
11581
11690
|
if (this.pending.get(id) !== entry)
|
|
11582
11691
|
return;
|
|
11692
|
+
const remaining = deadline.remaining();
|
|
11693
|
+
if (remaining > 0) {
|
|
11694
|
+
entry.timer = this.clock.setTimeout(expire, Math.min(remaining, DEADLINE_POLL_MS));
|
|
11695
|
+
return;
|
|
11696
|
+
}
|
|
11583
11697
|
this.pending.delete(id);
|
|
11584
11698
|
entry.onSettled?.();
|
|
11585
11699
|
this.warnVia(`Request "${entry.command}" (id=${id}) got no reply within ${graceMs}ms after its deadline`);
|
|
11586
11700
|
settle({ kind: "unknown" });
|
|
11587
|
-
}
|
|
11701
|
+
};
|
|
11702
|
+
entry.timer = this.clock.setTimeout(expire, Math.min(graceMs, DEADLINE_POLL_MS));
|
|
11588
11703
|
return true;
|
|
11589
11704
|
}
|
|
11590
11705
|
accountForBashTaskResponse(command, response) {
|
|
@@ -11832,34 +11947,34 @@ class BinaryBridge {
|
|
|
11832
11947
|
}
|
|
11833
11948
|
// ../aft-bridge/dist/cache-paths.js
|
|
11834
11949
|
import { homedir as homedir5 } from "node:os";
|
|
11835
|
-
import { join as
|
|
11950
|
+
import { join as join5 } from "node:path";
|
|
11836
11951
|
function homeDir2(env) {
|
|
11837
11952
|
return (process.platform === "win32" ? env.USERPROFILE || env.HOME : env.HOME) || homedir5();
|
|
11838
11953
|
}
|
|
11839
11954
|
function getOpenCodeCacheRoot(env = process.env, home = homedir5()) {
|
|
11840
|
-
return
|
|
11955
|
+
return join5(env.XDG_CACHE_HOME || join5(home, ".cache"), "opencode");
|
|
11841
11956
|
}
|
|
11842
11957
|
function getOpenCodeConfigRoot(env = process.env, home = homedir5()) {
|
|
11843
|
-
return
|
|
11958
|
+
return join5(env.XDG_CONFIG_HOME || join5(home, ".config"), "opencode");
|
|
11844
11959
|
}
|
|
11845
11960
|
function getAftCacheRoot(env = process.env) {
|
|
11846
11961
|
if (env.AFT_CACHE_DIR)
|
|
11847
11962
|
return env.AFT_CACHE_DIR;
|
|
11848
11963
|
if (process.platform === "win32") {
|
|
11849
|
-
const base = env.LOCALAPPDATA || env.APPDATA ||
|
|
11850
|
-
return
|
|
11964
|
+
const base = env.LOCALAPPDATA || env.APPDATA || join5(homeDir2(env), "AppData", "Local");
|
|
11965
|
+
return join5(base, "aft");
|
|
11851
11966
|
}
|
|
11852
|
-
const base = env.XDG_CACHE_HOME ||
|
|
11853
|
-
return
|
|
11967
|
+
const base = env.XDG_CACHE_HOME || join5(homeDir2(env), ".cache");
|
|
11968
|
+
return join5(base, "aft");
|
|
11854
11969
|
}
|
|
11855
11970
|
function getAftBinaryCacheDir(env = process.env) {
|
|
11856
|
-
return
|
|
11971
|
+
return join5(getAftCacheRoot(env), "bin");
|
|
11857
11972
|
}
|
|
11858
11973
|
function getAftLspPackagesDir(env = process.env) {
|
|
11859
|
-
return
|
|
11974
|
+
return join5(getAftCacheRoot(env), "lsp-packages");
|
|
11860
11975
|
}
|
|
11861
11976
|
function getAftLspBinariesDir(env = process.env) {
|
|
11862
|
-
return
|
|
11977
|
+
return join5(getAftCacheRoot(env), "lsp-binaries");
|
|
11863
11978
|
}
|
|
11864
11979
|
// ../aft-bridge/dist/coerce.js
|
|
11865
11980
|
function coerceStringArray(value) {
|
|
@@ -12004,7 +12119,7 @@ function isFindReplaceOnlyEdit(args) {
|
|
|
12004
12119
|
}
|
|
12005
12120
|
// ../aft-bridge/dist/config-error.js
|
|
12006
12121
|
import { homedir as homedir6 } from "node:os";
|
|
12007
|
-
import { isAbsolute as
|
|
12122
|
+
import { isAbsolute as isAbsolute2, join as join6 } from "node:path";
|
|
12008
12123
|
var CONFIG_ERROR_RESTART_NOTE = "AFT reads its config only at startup, so restart the host after fixing it.";
|
|
12009
12124
|
function formatConfigErrorMessage(detail) {
|
|
12010
12125
|
const trimmed = detail.trim();
|
|
@@ -12014,10 +12129,10 @@ function formatConfigErrorMessage(detail) {
|
|
|
12014
12129
|
function resolveSubcConnectionFilePath(raw, home = homedir6()) {
|
|
12015
12130
|
const trimmed = raw.trim();
|
|
12016
12131
|
if (trimmed.startsWith("~"))
|
|
12017
|
-
return
|
|
12018
|
-
if (
|
|
12132
|
+
return join6(home, trimmed.slice(1).replace(/^[/\\]/, ""));
|
|
12133
|
+
if (isAbsolute2(trimmed))
|
|
12019
12134
|
return trimmed;
|
|
12020
|
-
return
|
|
12135
|
+
return join6(home, trimmed);
|
|
12021
12136
|
}
|
|
12022
12137
|
function formatSubcConnectionMissingMessage(raw, resolved) {
|
|
12023
12138
|
return `subc.connection_file is set to "${raw.trim()}" (resolved: ${resolved}) but no subc ` + `connection file exists there. Start the Subconscious daemon, correct the path, ` + `or remove subc.connection_file from your user config to use the standalone bridge.`;
|
|
@@ -12087,7 +12202,7 @@ function stripHarnessSpecificConfigKeys(value, keys) {
|
|
|
12087
12202
|
}
|
|
12088
12203
|
// ../aft-bridge/dist/config-tiers.js
|
|
12089
12204
|
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
|
|
12090
|
-
import { resolve as
|
|
12205
|
+
import { resolve as resolve3 } from "node:path";
|
|
12091
12206
|
function readConfigTiers(opts) {
|
|
12092
12207
|
const tiers = [];
|
|
12093
12208
|
try {
|
|
@@ -12095,7 +12210,7 @@ function readConfigTiers(opts) {
|
|
|
12095
12210
|
const doc = readFileSync2(opts.userConfigPath, "utf-8");
|
|
12096
12211
|
tiers.push({
|
|
12097
12212
|
tier: "user",
|
|
12098
|
-
source:
|
|
12213
|
+
source: resolve3(opts.userConfigPath),
|
|
12099
12214
|
doc
|
|
12100
12215
|
});
|
|
12101
12216
|
}
|
|
@@ -12105,7 +12220,7 @@ function readConfigTiers(opts) {
|
|
|
12105
12220
|
const doc = readFileSync2(opts.projectConfigPath, "utf-8");
|
|
12106
12221
|
tiers.push({
|
|
12107
12222
|
tier: "project",
|
|
12108
|
-
source:
|
|
12223
|
+
source: resolve3(opts.projectConfigPath),
|
|
12109
12224
|
doc
|
|
12110
12225
|
});
|
|
12111
12226
|
}
|
|
@@ -12121,7 +12236,7 @@ function formatDroppedKeyWarnings(dropped) {
|
|
|
12121
12236
|
// ../aft-bridge/dist/config-watch.js
|
|
12122
12237
|
import { createHash as createHash2 } from "node:crypto";
|
|
12123
12238
|
import { closeSync as closeSync2, fstatSync, openSync as openSync2, readFileSync as readFileSync3, readSync as readSync2, realpathSync as realpathSync2, statSync as statSync3, watch } from "node:fs";
|
|
12124
|
-
import { basename, dirname as dirname2, resolve as
|
|
12239
|
+
import { basename, dirname as dirname2, resolve as resolve4 } from "node:path";
|
|
12125
12240
|
var CONFIG_WATCH_DEBOUNCE_MS = 150;
|
|
12126
12241
|
var CONFIG_LIVE_KEEP_NOTE = "AFT keeps using the last valid configuration until the file is fixed.";
|
|
12127
12242
|
function pathKey(name) {
|
|
@@ -12176,6 +12291,7 @@ function aftLiveConfigKeys(resolveBash) {
|
|
|
12176
12291
|
pathKey("revision_reads"),
|
|
12177
12292
|
pathKey("inspect.diagnostics_timeout_ms"),
|
|
12178
12293
|
pathKey("lsp.idle_minutes"),
|
|
12294
|
+
pathKey("lsp.max_servers"),
|
|
12179
12295
|
...[
|
|
12180
12296
|
"diagnostics",
|
|
12181
12297
|
"todos",
|
|
@@ -12288,7 +12404,7 @@ function canonicalDirectory(dir) {
|
|
|
12288
12404
|
try {
|
|
12289
12405
|
return realpathSync2(dir);
|
|
12290
12406
|
} catch {
|
|
12291
|
-
return
|
|
12407
|
+
return resolve4(dir);
|
|
12292
12408
|
}
|
|
12293
12409
|
}
|
|
12294
12410
|
function watchAftConfigFiles(options) {
|
|
@@ -12308,6 +12424,7 @@ function watchAftConfigFiles(options) {
|
|
|
12308
12424
|
const fallbackSeen = new Map;
|
|
12309
12425
|
const watchImpl = options.watchImpl ?? watch;
|
|
12310
12426
|
let rejectedRetries = 0;
|
|
12427
|
+
let recheckAfterArming = false;
|
|
12311
12428
|
const check = () => {
|
|
12312
12429
|
if (retryTimer)
|
|
12313
12430
|
clearTimeout(retryTimer);
|
|
@@ -12316,7 +12433,8 @@ function watchAftConfigFiles(options) {
|
|
|
12316
12433
|
firstPendingAt = null;
|
|
12317
12434
|
if (stopped)
|
|
12318
12435
|
return;
|
|
12319
|
-
revalidate()
|
|
12436
|
+
if (revalidate())
|
|
12437
|
+
recheckAfterArming = true;
|
|
12320
12438
|
const seen = new Map;
|
|
12321
12439
|
for (const path of options.paths) {
|
|
12322
12440
|
const text = readTextOrNull(path);
|
|
@@ -12374,7 +12492,7 @@ function watchAftConfigFiles(options) {
|
|
|
12374
12492
|
for (const path of options.paths) {
|
|
12375
12493
|
try {
|
|
12376
12494
|
const resolved = realpathSync2(path);
|
|
12377
|
-
const target = resolved ===
|
|
12495
|
+
const target = resolved === resolve4(path) ? undefined : resolved;
|
|
12378
12496
|
if (targets.get(path) !== target) {
|
|
12379
12497
|
if (target)
|
|
12380
12498
|
targets.set(path, target);
|
|
@@ -12438,12 +12556,16 @@ function watchAftConfigFiles(options) {
|
|
|
12438
12556
|
}
|
|
12439
12557
|
return moved;
|
|
12440
12558
|
}
|
|
12441
|
-
revalidate();
|
|
12559
|
+
recheckAfterArming = revalidate();
|
|
12442
12560
|
if (options.checkAtStart)
|
|
12443
12561
|
check();
|
|
12444
12562
|
const revalidateTimer = setInterval(() => {
|
|
12445
|
-
if (
|
|
12563
|
+
if (stopped)
|
|
12564
|
+
return;
|
|
12565
|
+
const moved = revalidate();
|
|
12566
|
+
if (moved || recheckAfterArming)
|
|
12446
12567
|
schedule();
|
|
12568
|
+
recheckAfterArming = moved;
|
|
12447
12569
|
}, CONFIG_WATCH_REVALIDATE_MS);
|
|
12448
12570
|
revalidateTimer.unref?.();
|
|
12449
12571
|
return () => {
|
|
@@ -12486,6 +12608,10 @@ function aftLiveSecurityKeys(keys) {
|
|
|
12486
12608
|
return minutes(next) > minutes(current);
|
|
12487
12609
|
}
|
|
12488
12610
|
},
|
|
12611
|
+
{
|
|
12612
|
+
key: pick("lsp.max_servers"),
|
|
12613
|
+
loosens: (current, next) => (typeof next === "number" ? next : 8) > (typeof current === "number" ? current : 8)
|
|
12614
|
+
},
|
|
12489
12615
|
...[
|
|
12490
12616
|
"diagnostics",
|
|
12491
12617
|
"todos",
|
|
@@ -12595,7 +12721,7 @@ function startLiveConfigReload(options) {
|
|
|
12595
12721
|
import { createHash as createHash3, randomUUID } from "node:crypto";
|
|
12596
12722
|
import { chmodSync, closeSync as closeSync3, copyFileSync, createWriteStream, existsSync as existsSync3, mkdirSync as mkdirSync2, openSync as openSync3, readdirSync, readFileSync as readFileSync4, renameSync as renameSync2, rmSync, statSync as statSync4, unlinkSync as unlinkSync2, writeSync } from "node:fs";
|
|
12597
12723
|
import { hostname } from "node:os";
|
|
12598
|
-
import { join as
|
|
12724
|
+
import { join as join7 } from "node:path";
|
|
12599
12725
|
import { Readable } from "node:stream";
|
|
12600
12726
|
import { pipeline } from "node:stream/promises";
|
|
12601
12727
|
|
|
@@ -12711,7 +12837,7 @@ function getBinaryName() {
|
|
|
12711
12837
|
function getCachedBinaryPath(version) {
|
|
12712
12838
|
if (!version)
|
|
12713
12839
|
return null;
|
|
12714
|
-
const binaryPath =
|
|
12840
|
+
const binaryPath = join7(getAftBinaryCacheDir(), version, getBinaryName());
|
|
12715
12841
|
return existsSync3(binaryPath) ? binaryPath : null;
|
|
12716
12842
|
}
|
|
12717
12843
|
async function downloadBinary(version) {
|
|
@@ -12728,16 +12854,16 @@ async function downloadBinary(version) {
|
|
|
12728
12854
|
return null;
|
|
12729
12855
|
}
|
|
12730
12856
|
const tag = rawTag.startsWith("v") ? rawTag : `v${rawTag}`;
|
|
12731
|
-
const versionedCacheDir =
|
|
12857
|
+
const versionedCacheDir = join7(getAftBinaryCacheDir(), tag);
|
|
12732
12858
|
const binaryName = getBinaryName();
|
|
12733
|
-
const binaryPath =
|
|
12859
|
+
const binaryPath = join7(versionedCacheDir, binaryName);
|
|
12734
12860
|
if (existsSync3(binaryPath) && await isExpectedCachedBinary(binaryPath, tag)) {
|
|
12735
12861
|
return binaryPath;
|
|
12736
12862
|
}
|
|
12737
12863
|
const downloadUrl = `https://github.com/${REPO}/releases/download/${tag}/${assetName}`;
|
|
12738
12864
|
const checksumUrl = `https://github.com/${REPO}/releases/download/${tag}/checksums.sha256`;
|
|
12739
12865
|
log(`Downloading AFT binary (${tag}) for ${platformKey}...`);
|
|
12740
|
-
const lockPath =
|
|
12866
|
+
const lockPath = join7(versionedCacheDir, ".download.lock");
|
|
12741
12867
|
let releaseLock = null;
|
|
12742
12868
|
let binaryController = null;
|
|
12743
12869
|
let checksumController = null;
|
|
@@ -12963,7 +13089,7 @@ function sweepStaleDownloadTemps(versionedCacheDir, binaryName) {
|
|
|
12963
13089
|
if (!entry.isFile() || !entry.name.startsWith(tempPrefix) || !entry.name.endsWith(".tmp")) {
|
|
12964
13090
|
continue;
|
|
12965
13091
|
}
|
|
12966
|
-
const tempPath =
|
|
13092
|
+
const tempPath = join7(versionedCacheDir, entry.name);
|
|
12967
13093
|
const ageMs = Date.now() - statSync4(tempPath).mtimeMs;
|
|
12968
13094
|
if (Math.abs(ageMs) > DOWNLOAD_LOCK_STALE_MS)
|
|
12969
13095
|
unlinkSync2(tempPath);
|
|
@@ -13054,7 +13180,7 @@ import { dirname as dirname3 } from "node:path";
|
|
|
13054
13180
|
|
|
13055
13181
|
// ../aft-bridge/dist/private-storage.js
|
|
13056
13182
|
import { closeSync as closeSync4, constants, copyFileSync as copyFileSync2, fchmodSync, fstatSync as fstatSync2, lstatSync, mkdirSync as mkdirSync3, openSync as openSync4, readSync as readSync3, writeSync as writeSync2 } from "node:fs";
|
|
13057
|
-
import { isAbsolute as
|
|
13183
|
+
import { isAbsolute as isAbsolute3, join as join8, parse, relative as relative2, resolve as resolve5, sep } from "node:path";
|
|
13058
13184
|
var PRIVATE_FILE_MODE = 384;
|
|
13059
13185
|
var PRIVATE_DIRECTORY_MODE = 448;
|
|
13060
13186
|
function privateMkdirSync(path, recursive = true) {
|
|
@@ -13089,19 +13215,19 @@ function privateCopyFileSync(source, destination) {
|
|
|
13089
13215
|
}
|
|
13090
13216
|
var warned = new Set;
|
|
13091
13217
|
function openPrivateStorageDir(root, path = root) {
|
|
13092
|
-
const base =
|
|
13218
|
+
const base = resolve5(root);
|
|
13093
13219
|
if (!root || base === parse(base).root) {
|
|
13094
13220
|
throw new Error(`refusing filesystem root as private storage: ${base}`);
|
|
13095
13221
|
}
|
|
13096
|
-
const rel =
|
|
13097
|
-
if (rel === ".." || rel.startsWith(`..${sep}`) ||
|
|
13222
|
+
const rel = relative2(base, resolve5(path));
|
|
13223
|
+
if (rel === ".." || rel.startsWith(`..${sep}`) || isAbsolute3(rel))
|
|
13098
13224
|
return;
|
|
13099
13225
|
privateMkdirSync(path);
|
|
13100
13226
|
if (process.platform === "win32")
|
|
13101
13227
|
return;
|
|
13102
13228
|
let current = base;
|
|
13103
13229
|
for (const component of ["", ...rel.split(sep).filter(Boolean)]) {
|
|
13104
|
-
current =
|
|
13230
|
+
current = join8(current, component);
|
|
13105
13231
|
let fd;
|
|
13106
13232
|
try {
|
|
13107
13233
|
if (lstatSync(current).isSymbolicLink())
|
|
@@ -13295,21 +13421,23 @@ async function renameIfPresent(from, to) {
|
|
|
13295
13421
|
throw error;
|
|
13296
13422
|
}
|
|
13297
13423
|
}
|
|
13298
|
-
// ../../node_modules/.bun/@cortexkit+subc-client@0.
|
|
13424
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.24.5/node_modules/@cortexkit/subc-client/dist/client.js
|
|
13299
13425
|
import { promises as fs3 } from "node:fs";
|
|
13426
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
13300
13427
|
import { debuglog } from "node:util";
|
|
13301
13428
|
|
|
13302
|
-
// ../../node_modules/.bun/@cortexkit+subc-client@0.
|
|
13429
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.24.5/node_modules/@cortexkit/subc-client/dist/auth.js
|
|
13303
13430
|
import { createHmac, randomBytes, timingSafeEqual } from "node:crypto";
|
|
13304
13431
|
|
|
13305
|
-
// ../../node_modules/.bun/@cortexkit+subc-client@0.
|
|
13432
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.24.5/node_modules/@cortexkit/subc-client/dist/socket.js
|
|
13306
13433
|
import net from "node:net";
|
|
13307
13434
|
|
|
13308
|
-
// ../../node_modules/.bun/@cortexkit+subc-client@0.
|
|
13435
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.24.5/node_modules/@cortexkit/subc-client/dist/envelope.js
|
|
13309
13436
|
var PROTOCOL_VERSION = 2;
|
|
13310
13437
|
var HEADER_LEN = 21;
|
|
13311
13438
|
var FROZEN_PREFIX_LEN = 5;
|
|
13312
13439
|
var MAX_FRAME_BODY_LEN = 64 * 1024 * 1024;
|
|
13440
|
+
var MAX_DELIVERED_FRAME_LEN = 4 * 1024 * 1024;
|
|
13313
13441
|
var FrameType;
|
|
13314
13442
|
(function(FrameType) {
|
|
13315
13443
|
FrameType[FrameType["Request"] = 0] = "Request";
|
|
@@ -13347,6 +13475,8 @@ var FLAG_PRIORITY_SHIFT = 1;
|
|
|
13347
13475
|
var FLAG_LAST = 8;
|
|
13348
13476
|
var FLAG_ADMISSION_MASK = 48;
|
|
13349
13477
|
var FLAG_ADMISSION_SHIFT = 4;
|
|
13478
|
+
var DAEMON_ORIGIN_FLAG = 64;
|
|
13479
|
+
var SUBSCRIPTION_FLAG = 128;
|
|
13350
13480
|
var FLAG_RESERVED_MASK = 0;
|
|
13351
13481
|
function buildFlags(binary, priority, last, admissionClass = AdmissionClass.Normal) {
|
|
13352
13482
|
let flags = 0;
|
|
@@ -13481,7 +13611,7 @@ function encodeFrame(frame) {
|
|
|
13481
13611
|
return output;
|
|
13482
13612
|
}
|
|
13483
13613
|
|
|
13484
|
-
// ../../node_modules/.bun/@cortexkit+subc-client@0.
|
|
13614
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.24.5/node_modules/@cortexkit/subc-client/dist/socket.js
|
|
13485
13615
|
class SocketClosedError extends Error {
|
|
13486
13616
|
}
|
|
13487
13617
|
|
|
@@ -13531,14 +13661,12 @@ class SubcSocket {
|
|
|
13531
13661
|
sock.on("data", (chunk) => {
|
|
13532
13662
|
this.chunks.push(chunk);
|
|
13533
13663
|
this.buffered += chunk.length;
|
|
13534
|
-
if (this.waiter) {
|
|
13664
|
+
if (this.waiter && this.waiter.extendOnProgress && this.buffered < this.waiter.need) {
|
|
13535
13665
|
if (this.waiter.immediate) {
|
|
13536
13666
|
clearImmediate(this.waiter.immediate);
|
|
13537
13667
|
this.waiter.immediate = null;
|
|
13538
13668
|
}
|
|
13539
|
-
|
|
13540
|
-
this.armWaiterTimer(this.waiter);
|
|
13541
|
-
}
|
|
13669
|
+
this.armWaiterTimer(this.waiter);
|
|
13542
13670
|
}
|
|
13543
13671
|
this.tryServe();
|
|
13544
13672
|
});
|
|
@@ -13555,12 +13683,18 @@ class SubcSocket {
|
|
|
13555
13683
|
return this.sock.localPort ?? null;
|
|
13556
13684
|
}
|
|
13557
13685
|
static connect(host, port, deadlineMs) {
|
|
13686
|
+
return SubcSocket.connectTo({ host, port }, `${host}:${port}`, deadlineMs);
|
|
13687
|
+
}
|
|
13688
|
+
static connectLocal(path, deadlineMs) {
|
|
13689
|
+
return SubcSocket.connectTo({ path }, path, deadlineMs);
|
|
13690
|
+
}
|
|
13691
|
+
static connectTo(options, endpoint, deadlineMs) {
|
|
13558
13692
|
return new Promise((resolve, reject) => {
|
|
13559
|
-
const sock = net.connect(
|
|
13693
|
+
const sock = net.connect(options);
|
|
13560
13694
|
sock.setNoDelay(true);
|
|
13561
13695
|
const timer = setTimeout(() => {
|
|
13562
13696
|
sock.destroy();
|
|
13563
|
-
reject(new SocketTimeoutError(`timed out connecting to ${
|
|
13697
|
+
reject(new SocketTimeoutError(`timed out connecting to ${endpoint}`));
|
|
13564
13698
|
}, Math.max(0, deadlineMs - Date.now()));
|
|
13565
13699
|
sock.once("connect", () => {
|
|
13566
13700
|
clearTimeout(timer);
|
|
@@ -13777,7 +13911,7 @@ class SubcSocket {
|
|
|
13777
13911
|
}
|
|
13778
13912
|
}
|
|
13779
13913
|
|
|
13780
|
-
// ../../node_modules/.bun/@cortexkit+subc-client@0.
|
|
13914
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.24.5/node_modules/@cortexkit/subc-client/dist/auth.js
|
|
13781
13915
|
var NONCE_LEN = 32;
|
|
13782
13916
|
var MAX_AUTH_MESSAGE_LEN = 4096;
|
|
13783
13917
|
var SERVER_PROOF_DOMAIN = "subc-server-v1";
|
|
@@ -13851,7 +13985,7 @@ async function authenticateClient(sock, conn, deadlineMs) {
|
|
|
13851
13985
|
await writeMessage(sock, { client_auth: Array.from(clientAuth) }, deadlineMs);
|
|
13852
13986
|
}
|
|
13853
13987
|
|
|
13854
|
-
// ../../node_modules/.bun/@cortexkit+subc-client@0.
|
|
13988
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.24.5/node_modules/@cortexkit/subc-client/dist/connection-file.js
|
|
13855
13989
|
import { promises as fs2 } from "node:fs";
|
|
13856
13990
|
var SCHEMA_VERSION = 1;
|
|
13857
13991
|
var MIN_KEY_LEN = 32;
|
|
@@ -13898,7 +14032,10 @@ function verifyOwnerOnly(path, stat, expectedUid) {
|
|
|
13898
14032
|
async function readConnectionFile(path) {
|
|
13899
14033
|
return readConnectionFileForUid(path, process.geteuid?.());
|
|
13900
14034
|
}
|
|
13901
|
-
async function
|
|
14035
|
+
async function readConnectionFileWithLocalEndpoint(path) {
|
|
14036
|
+
return readConnectionFileForUid(path, process.geteuid?.(), true);
|
|
14037
|
+
}
|
|
14038
|
+
async function readConnectionFileForUid(path, expectedUid, includeLocalEndpoint = false) {
|
|
13902
14039
|
const handle = await fs2.open(path, "r");
|
|
13903
14040
|
let raw;
|
|
13904
14041
|
try {
|
|
@@ -13937,13 +14074,26 @@ async function readConnectionFileForUid(path, expectedUid) {
|
|
|
13937
14074
|
daemonVer: parsed.daemon_ver ?? ""
|
|
13938
14075
|
};
|
|
13939
14076
|
validate(info);
|
|
14077
|
+
if (includeLocalEndpoint && parsed.local_endpoint != null) {
|
|
14078
|
+
const endpoint = parsed.local_endpoint;
|
|
14079
|
+
if (endpoint.kind === "unix" && typeof endpoint.path === "string" && endpoint.path.length > 0) {
|
|
14080
|
+
info.localEndpoint = { kind: "unix", path: endpoint.path };
|
|
14081
|
+
} else if (endpoint.kind === "pipe" && typeof endpoint.name === "string" && endpoint.name.length > 0) {
|
|
14082
|
+
info.localEndpoint = { kind: "pipe", name: endpoint.name };
|
|
14083
|
+
} else {
|
|
14084
|
+
throw new ConnectionFileError("connection file local_endpoint must name a unix path or pipe name");
|
|
14085
|
+
}
|
|
14086
|
+
}
|
|
13940
14087
|
return info;
|
|
13941
14088
|
}
|
|
13942
14089
|
|
|
13943
|
-
// ../../node_modules/.bun/@cortexkit+subc-client@0.
|
|
14090
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.24.5/node_modules/@cortexkit/subc-client/dist/launch-nonce.js
|
|
13944
14091
|
import { closeSync as closeSync5, fstatSync as fstatSync3, readSync as readSync4 } from "node:fs";
|
|
14092
|
+
import { connect } from "node:net";
|
|
13945
14093
|
var SUBC_LAUNCH_NONCE_ENV = "SUBC_LAUNCH_NONCE";
|
|
13946
14094
|
var SUBC_LAUNCH_NONCE_FD_ENV = "SUBC_LAUNCH_NONCE_FD";
|
|
14095
|
+
var SUBC_LAUNCH_NONCE_PIPE_ENV = "SUBC_LAUNCH_NONCE_PIPE";
|
|
14096
|
+
var SUBC_LAUNCH_NONCE_PIPE_FALLBACK_ENV = "SUBC_LAUNCH_NONCE_PIPE_FALLBACK";
|
|
13947
14097
|
class LaunchNonceError extends Error {
|
|
13948
14098
|
name = "LaunchNonceError";
|
|
13949
14099
|
kind;
|
|
@@ -13962,9 +14112,21 @@ class LaunchNonceError extends Error {
|
|
|
13962
14112
|
this.foundInode = details.foundInode;
|
|
13963
14113
|
}
|
|
13964
14114
|
}
|
|
13965
|
-
function
|
|
13966
|
-
|
|
13967
|
-
|
|
14115
|
+
function isLaunchNonceError(error) {
|
|
14116
|
+
return error instanceof Error && error.name === "LaunchNonceError" && typeof error.kind === "string";
|
|
14117
|
+
}
|
|
14118
|
+
async function launchNonceAsync() {
|
|
14119
|
+
const cell = processCell();
|
|
14120
|
+
return unwrap(await (cell.resultAsync?.() ?? cell.result()));
|
|
14121
|
+
}
|
|
14122
|
+
async function launchNonceOrUndefinedAsync() {
|
|
14123
|
+
try {
|
|
14124
|
+
return await launchNonceAsync();
|
|
14125
|
+
} catch (error) {
|
|
14126
|
+
if (isLaunchNonceError(error))
|
|
14127
|
+
return;
|
|
14128
|
+
throw error;
|
|
14129
|
+
}
|
|
13968
14130
|
}
|
|
13969
14131
|
var PROCESS_CELL_KEY = Symbol.for("@cortexkit/subc-client/launch-nonce/v1");
|
|
13970
14132
|
function processCell() {
|
|
@@ -13984,20 +14146,60 @@ function unwrap(result) {
|
|
|
13984
14146
|
|
|
13985
14147
|
class LaunchNonceCell {
|
|
13986
14148
|
cached;
|
|
14149
|
+
pending;
|
|
13987
14150
|
descriptorReads = 0;
|
|
13988
14151
|
lookup;
|
|
13989
14152
|
platform;
|
|
13990
14153
|
stat;
|
|
13991
|
-
|
|
14154
|
+
pipeReader;
|
|
14155
|
+
constructor(lookup, platform = process.platform, stat = (fd) => fstatSync3(fd, { bigint: true }), pipeReader = readLaunchNoncePipe) {
|
|
13992
14156
|
this.lookup = lookup;
|
|
13993
14157
|
this.platform = platform;
|
|
13994
14158
|
this.stat = stat;
|
|
14159
|
+
this.pipeReader = pipeReader;
|
|
13995
14160
|
}
|
|
13996
14161
|
result() {
|
|
14162
|
+
if (this.cached === undefined && this.platform === "win32" && this.lookup(SUBC_LAUNCH_NONCE_PIPE_ENV) !== undefined) {
|
|
14163
|
+
const fallback = this.permittedPipeFallback();
|
|
14164
|
+
if (fallback === undefined) {
|
|
14165
|
+
throw new LaunchNonceError("PipeNeedsAsync", "call launchNonceAsync() before the synchronous reader when SUBC_LAUNCH_NONCE_PIPE is set");
|
|
14166
|
+
}
|
|
14167
|
+
this.cached = { ok: true, nonce: fallback };
|
|
14168
|
+
}
|
|
13997
14169
|
if (this.cached === undefined)
|
|
13998
14170
|
this.cached = this.read();
|
|
13999
14171
|
return this.cached;
|
|
14000
14172
|
}
|
|
14173
|
+
async resultAsync() {
|
|
14174
|
+
if (this.cached !== undefined)
|
|
14175
|
+
return this.cached;
|
|
14176
|
+
if (this.pending !== undefined)
|
|
14177
|
+
return this.pending;
|
|
14178
|
+
const named = this.platform === "win32" ? this.lookup(SUBC_LAUNCH_NONCE_PIPE_ENV) : undefined;
|
|
14179
|
+
if (named === undefined)
|
|
14180
|
+
return this.result();
|
|
14181
|
+
const fallback = this.permittedPipeFallback();
|
|
14182
|
+
this.pending = this.pipeReader(named).then((nonce) => ({ ok: true, nonce: fallback !== undefined && nonce.value !== fallback.value ? fallback : nonce }), (error) => {
|
|
14183
|
+
if (fallback !== undefined)
|
|
14184
|
+
return { ok: true, nonce: fallback };
|
|
14185
|
+
if (!isLaunchNonceError(error))
|
|
14186
|
+
throw error;
|
|
14187
|
+
return { ok: false, error };
|
|
14188
|
+
}).then((result) => {
|
|
14189
|
+
this.cached ??= result;
|
|
14190
|
+
return this.cached;
|
|
14191
|
+
});
|
|
14192
|
+
return this.pending;
|
|
14193
|
+
}
|
|
14194
|
+
permittedPipeFallback() {
|
|
14195
|
+
if (this.lookup(SUBC_LAUNCH_NONCE_PIPE_FALLBACK_ENV) !== "env")
|
|
14196
|
+
return;
|
|
14197
|
+
const value = this.lookup(SUBC_LAUNCH_NONCE_ENV);
|
|
14198
|
+
return value ? makeLaunchNonce(value, "env") : undefined;
|
|
14199
|
+
}
|
|
14200
|
+
async getAsync() {
|
|
14201
|
+
return unwrap(await this.resultAsync());
|
|
14202
|
+
}
|
|
14001
14203
|
get() {
|
|
14002
14204
|
return unwrap(this.result());
|
|
14003
14205
|
}
|
|
@@ -14128,8 +14330,198 @@ function closeQuietly(fd) {
|
|
|
14128
14330
|
closeSync5(fd);
|
|
14129
14331
|
} catch {}
|
|
14130
14332
|
}
|
|
14333
|
+
async function readLaunchNoncePipe(name, connector = (path) => connect(path), openWindowMs = 500, readWindowMs = 2000) {
|
|
14334
|
+
const deadline = Date.now() + openWindowMs;
|
|
14335
|
+
for (;; ) {
|
|
14336
|
+
try {
|
|
14337
|
+
const bytes = await pipeAttempt(name, connector, Math.max(1, deadline - Date.now()), readWindowMs);
|
|
14338
|
+
if (bytes.length === 0)
|
|
14339
|
+
throw new LaunchNonceError("PipeEmpty", "the launch nonce named pipe is empty");
|
|
14340
|
+
let value;
|
|
14341
|
+
try {
|
|
14342
|
+
value = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
|
|
14343
|
+
} catch {
|
|
14344
|
+
throw new LaunchNonceError("PipeNotUtf8", "the launch nonce named pipe held bytes that are not UTF-8");
|
|
14345
|
+
}
|
|
14346
|
+
return makeLaunchNonce(value, "pipe");
|
|
14347
|
+
} catch (error) {
|
|
14348
|
+
if (isLaunchNonceError(error))
|
|
14349
|
+
throw error;
|
|
14350
|
+
const busy = error?.code === "EBUSY" || errnoOf(error) === 231;
|
|
14351
|
+
if (!busy || Date.now() >= deadline) {
|
|
14352
|
+
throw new LaunchNonceError("PipeNotOpen", "SUBC_LAUNCH_NONCE_PIPE names a pipe that could not be opened", { errno: errnoOf(error) });
|
|
14353
|
+
}
|
|
14354
|
+
await new Promise((resolve) => setTimeout(resolve, Math.min(10, Math.max(1, deadline - Date.now()))));
|
|
14355
|
+
}
|
|
14356
|
+
}
|
|
14357
|
+
}
|
|
14358
|
+
function pipeAttempt(name, connector, openWindowMs, readWindowMs) {
|
|
14359
|
+
return new Promise((resolve, reject) => {
|
|
14360
|
+
let socket;
|
|
14361
|
+
try {
|
|
14362
|
+
socket = connector(name);
|
|
14363
|
+
} catch (error) {
|
|
14364
|
+
reject(error);
|
|
14365
|
+
return;
|
|
14366
|
+
}
|
|
14367
|
+
let connected = false;
|
|
14368
|
+
let settled = false;
|
|
14369
|
+
let size = 0;
|
|
14370
|
+
const chunks = [];
|
|
14371
|
+
let timer = setTimeout(() => finish(new LaunchNonceError("PipeNotOpen", "launch nonce pipe open timed out")), openWindowMs);
|
|
14372
|
+
function finish(error) {
|
|
14373
|
+
if (settled)
|
|
14374
|
+
return;
|
|
14375
|
+
settled = true;
|
|
14376
|
+
clearTimeout(timer);
|
|
14377
|
+
socket.destroy();
|
|
14378
|
+
if (error !== undefined)
|
|
14379
|
+
reject(error);
|
|
14380
|
+
else
|
|
14381
|
+
resolve(Buffer.concat(chunks));
|
|
14382
|
+
}
|
|
14383
|
+
socket.once("connect", () => {
|
|
14384
|
+
connected = true;
|
|
14385
|
+
clearTimeout(timer);
|
|
14386
|
+
timer = setTimeout(() => finish(new LaunchNonceError("PipeUnreadable", "launch nonce pipe read timed out")), readWindowMs);
|
|
14387
|
+
});
|
|
14388
|
+
socket.on("data", (chunk) => {
|
|
14389
|
+
size += chunk.length;
|
|
14390
|
+
if (size > 4096) {
|
|
14391
|
+
finish(new LaunchNonceError("PipeUnreadable", "launch nonce pipe exceeded its byte limit"));
|
|
14392
|
+
return;
|
|
14393
|
+
}
|
|
14394
|
+
chunks.push(Buffer.from(chunk));
|
|
14395
|
+
});
|
|
14396
|
+
socket.once("end", () => finish());
|
|
14397
|
+
socket.once("error", (error) => finish(connected ? new LaunchNonceError("PipeUnreadable", "could not read the launch nonce from the named pipe", { errno: errnoOf(error) }) : error));
|
|
14398
|
+
socket.once("close", () => {
|
|
14399
|
+
if (!settled)
|
|
14400
|
+
finish(new LaunchNonceError("PipeUnreadable", "launch nonce pipe closed before EOF"));
|
|
14401
|
+
});
|
|
14402
|
+
});
|
|
14403
|
+
}
|
|
14404
|
+
|
|
14405
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.24.5/node_modules/@cortexkit/subc-client/dist/request-gate.js
|
|
14406
|
+
class Lane {
|
|
14407
|
+
limit;
|
|
14408
|
+
used = 0;
|
|
14409
|
+
waiters = [];
|
|
14410
|
+
failure;
|
|
14411
|
+
constructor(limit) {
|
|
14412
|
+
this.limit = limit;
|
|
14413
|
+
}
|
|
14414
|
+
acquire(timeoutMs, signal) {
|
|
14415
|
+
if (this.failure)
|
|
14416
|
+
return Promise.reject(this.failure);
|
|
14417
|
+
if (signal?.aborted)
|
|
14418
|
+
return Promise.reject(new Error("request cancelled before write"));
|
|
14419
|
+
if (timeoutMs !== undefined && timeoutMs <= 0)
|
|
14420
|
+
return Promise.reject(new Error("request deadline elapsed waiting for a slot"));
|
|
14421
|
+
if (this.used < this.limit && this.waiters.length === 0) {
|
|
14422
|
+
this.used++;
|
|
14423
|
+
return Promise.resolve(this.releaser());
|
|
14424
|
+
}
|
|
14425
|
+
return new Promise((resolve, reject) => {
|
|
14426
|
+
let timer;
|
|
14427
|
+
const clean = () => {
|
|
14428
|
+
if (timer !== undefined)
|
|
14429
|
+
clearTimeout(timer);
|
|
14430
|
+
signal?.removeEventListener("abort", abort);
|
|
14431
|
+
};
|
|
14432
|
+
const waiter = {
|
|
14433
|
+
grant: () => {
|
|
14434
|
+
clean();
|
|
14435
|
+
resolve(this.releaser());
|
|
14436
|
+
},
|
|
14437
|
+
fail: (error) => {
|
|
14438
|
+
clean();
|
|
14439
|
+
reject(error);
|
|
14440
|
+
}
|
|
14441
|
+
};
|
|
14442
|
+
const abort = () => {
|
|
14443
|
+
const index = this.waiters.indexOf(waiter);
|
|
14444
|
+
if (index < 0)
|
|
14445
|
+
return;
|
|
14446
|
+
this.waiters.splice(index, 1);
|
|
14447
|
+
waiter.fail(new Error("request cancelled before write"));
|
|
14448
|
+
};
|
|
14449
|
+
this.waiters.push(waiter);
|
|
14450
|
+
signal?.addEventListener("abort", abort, { once: true });
|
|
14451
|
+
if (timeoutMs !== undefined)
|
|
14452
|
+
timer = setTimeout(() => {
|
|
14453
|
+
const index = this.waiters.indexOf(waiter);
|
|
14454
|
+
if (index < 0)
|
|
14455
|
+
return;
|
|
14456
|
+
this.waiters.splice(index, 1);
|
|
14457
|
+
waiter.fail(new Error("request deadline elapsed waiting for a slot"));
|
|
14458
|
+
}, timeoutMs);
|
|
14459
|
+
});
|
|
14460
|
+
}
|
|
14461
|
+
close(error) {
|
|
14462
|
+
this.failure = error;
|
|
14463
|
+
for (const waiter of this.waiters.splice(0))
|
|
14464
|
+
waiter.fail(error);
|
|
14465
|
+
}
|
|
14466
|
+
releaser() {
|
|
14467
|
+
let released = false;
|
|
14468
|
+
return () => {
|
|
14469
|
+
if (released)
|
|
14470
|
+
return;
|
|
14471
|
+
released = true;
|
|
14472
|
+
const waiter = this.waiters.shift();
|
|
14473
|
+
if (waiter)
|
|
14474
|
+
waiter.grant();
|
|
14475
|
+
else
|
|
14476
|
+
this.used--;
|
|
14477
|
+
};
|
|
14478
|
+
}
|
|
14479
|
+
}
|
|
14131
14480
|
|
|
14132
|
-
|
|
14481
|
+
class RequestGate {
|
|
14482
|
+
total;
|
|
14483
|
+
watches;
|
|
14484
|
+
slots = new Set;
|
|
14485
|
+
closed = new AbortController;
|
|
14486
|
+
get signal() {
|
|
14487
|
+
return this.closed.signal;
|
|
14488
|
+
}
|
|
14489
|
+
constructor(requestWindow, watchWindow) {
|
|
14490
|
+
this.total = new Lane(requestWindow);
|
|
14491
|
+
if (watchWindow !== undefined)
|
|
14492
|
+
this.watches = new Lane(watchWindow);
|
|
14493
|
+
}
|
|
14494
|
+
async acquire(watch, timeoutMs, signal) {
|
|
14495
|
+
const deadline = timeoutMs === undefined ? undefined : Date.now() + timeoutMs;
|
|
14496
|
+
const watchRelease = watch && this.watches ? await this.watches.acquire(timeoutMs, signal) : undefined;
|
|
14497
|
+
try {
|
|
14498
|
+
const totalRelease = await this.total.acquire(deadline === undefined ? undefined : deadline - Date.now(), signal);
|
|
14499
|
+
const slot = {
|
|
14500
|
+
inFlight: false,
|
|
14501
|
+
release: () => {
|
|
14502
|
+
if (!this.slots.delete(slot))
|
|
14503
|
+
return;
|
|
14504
|
+
totalRelease();
|
|
14505
|
+
watchRelease?.();
|
|
14506
|
+
}
|
|
14507
|
+
};
|
|
14508
|
+
this.slots.add(slot);
|
|
14509
|
+
return slot;
|
|
14510
|
+
} catch (error) {
|
|
14511
|
+
watchRelease?.();
|
|
14512
|
+
throw error;
|
|
14513
|
+
}
|
|
14514
|
+
}
|
|
14515
|
+
close(error) {
|
|
14516
|
+
this.total.close(error);
|
|
14517
|
+
this.watches?.close(error);
|
|
14518
|
+
this.closed.abort(error);
|
|
14519
|
+
for (const slot of this.slots)
|
|
14520
|
+
slot.release();
|
|
14521
|
+
}
|
|
14522
|
+
}
|
|
14523
|
+
|
|
14524
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.24.5/node_modules/@cortexkit/subc-client/dist/route-handle.js
|
|
14133
14525
|
var connectionToken = new WeakMap;
|
|
14134
14526
|
var reverseRequests = new WeakMap;
|
|
14135
14527
|
|
|
@@ -14222,10 +14614,13 @@ function sameRouteHandle(left, right) {
|
|
|
14222
14614
|
return left === right;
|
|
14223
14615
|
}
|
|
14224
14616
|
|
|
14225
|
-
// ../../node_modules/.bun/@cortexkit+subc-client@0.
|
|
14617
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.24.5/node_modules/@cortexkit/subc-client/dist/client.js
|
|
14226
14618
|
var debug = debuglog("subc-client");
|
|
14227
14619
|
var DEFAULT_HANDSHAKE_TIMEOUT_MS = 1e4;
|
|
14228
14620
|
var DEFAULT_REQUEST_TIMEOUT_MS = 30000;
|
|
14621
|
+
var DEFAULT_SLEEP_GRACE_MS = 15000;
|
|
14622
|
+
var SLEEP_DETECTION_THRESHOLD_MS = 2000;
|
|
14623
|
+
var MIN_REQUEST_BUDGET_MS = 1;
|
|
14229
14624
|
var TIMEOUT_ARBITRATION_GRACE_MS = 50;
|
|
14230
14625
|
var LIVENESS_PROBE_WINDOW_MS = 2000;
|
|
14231
14626
|
var REQUEST_DEADLINE_MARKER = "request_deadline";
|
|
@@ -14261,6 +14656,14 @@ class SubcCallError extends Error {
|
|
|
14261
14656
|
}
|
|
14262
14657
|
}
|
|
14263
14658
|
|
|
14659
|
+
class DaemonUnavailableError extends SubcCallError {
|
|
14660
|
+
recovery = "user_action_required";
|
|
14661
|
+
constructor(cause) {
|
|
14662
|
+
super("not_sent", "CortexKit's daemon is not running or can't be reached on this computer, so this tool call was not sent. Retrying won't start it. Stop calling CortexKit tools and ask the user to start the daemon (run `ck setup`, or restart the CortexKit service), then try again after they confirm it is running.", errorCode(cause), cause);
|
|
14663
|
+
this.name = "DaemonUnavailableError";
|
|
14664
|
+
}
|
|
14665
|
+
}
|
|
14666
|
+
|
|
14264
14667
|
class SubcError extends Error {
|
|
14265
14668
|
code;
|
|
14266
14669
|
detail;
|
|
@@ -14385,6 +14788,14 @@ class SubcClient {
|
|
|
14385
14788
|
reconnecting = null;
|
|
14386
14789
|
generation = 1;
|
|
14387
14790
|
routeOpenGateInstance;
|
|
14791
|
+
requestGates;
|
|
14792
|
+
wireSlots;
|
|
14793
|
+
get gates() {
|
|
14794
|
+
return this.requestGates ??= new Map;
|
|
14795
|
+
}
|
|
14796
|
+
get slots() {
|
|
14797
|
+
return this.wireSlots ??= new Map;
|
|
14798
|
+
}
|
|
14388
14799
|
readerActive = false;
|
|
14389
14800
|
constructor(sock, currentConn, opts) {
|
|
14390
14801
|
this.sock = sock;
|
|
@@ -14400,8 +14811,15 @@ class SubcClient {
|
|
|
14400
14811
|
}
|
|
14401
14812
|
static async connect(opts) {
|
|
14402
14813
|
const normalized = normalizeConnectOptions(opts);
|
|
14403
|
-
|
|
14404
|
-
|
|
14814
|
+
try {
|
|
14815
|
+
const opened = await SubcClient.openConnection(normalized);
|
|
14816
|
+
return new SubcClient(opened.sock, opened.conn, normalized);
|
|
14817
|
+
} catch (err) {
|
|
14818
|
+
if (errorCode(err) === "ENOENT" || errorCode(err) === "ECONNREFUSED") {
|
|
14819
|
+
throw new DaemonUnavailableError(err);
|
|
14820
|
+
}
|
|
14821
|
+
throw err;
|
|
14822
|
+
}
|
|
14405
14823
|
}
|
|
14406
14824
|
async catalogList(moduleId) {
|
|
14407
14825
|
const body = this.encode(moduleId === undefined ? { op: "catalog.list" } : { op: "catalog.list", module_id: moduleId });
|
|
@@ -14437,17 +14855,23 @@ class SubcClient {
|
|
|
14437
14855
|
}
|
|
14438
14856
|
async sendRouteOpen(target, identity, opts = {}) {
|
|
14439
14857
|
const scope = validatedRouteScope(opts.scope);
|
|
14440
|
-
const consumerIdentity = routeOpenConsumerIdentity(opts);
|
|
14858
|
+
const consumerIdentity = await routeOpenConsumerIdentity(opts);
|
|
14441
14859
|
const reverseRequests = opts.reverseRequests ?? new ReverseRequestRegistry;
|
|
14442
14860
|
reverseRequests.seal();
|
|
14443
14861
|
const consumerCapabilities = reverseRequests.capabilities();
|
|
14444
14862
|
const body = this.encode({
|
|
14445
14863
|
op: "route.open",
|
|
14864
|
+
busy_refusals: true,
|
|
14446
14865
|
target,
|
|
14447
14866
|
identity,
|
|
14448
14867
|
...consumerIdentity ? { consumer_identity: consumerIdentity } : {},
|
|
14449
14868
|
...consumerCapabilities.length > 0 ? { consumer_capabilities: consumerCapabilities } : {},
|
|
14450
|
-
...scope ? { scope: {
|
|
14869
|
+
...scope ? { scope: {
|
|
14870
|
+
owner: scope.owner,
|
|
14871
|
+
ref: scope.ref,
|
|
14872
|
+
scope_epoch: scope.scopeEpoch,
|
|
14873
|
+
...scope.bindProof !== undefined ? { bind_proof: scope.bindProof } : {}
|
|
14874
|
+
} } : {}
|
|
14451
14875
|
});
|
|
14452
14876
|
let installed = null;
|
|
14453
14877
|
const install = (frame) => {
|
|
@@ -14458,6 +14882,8 @@ class SubcClient {
|
|
|
14458
14882
|
throw new SubcError(`route.open returned no route handle: ${JSON.stringify(parsed)}`);
|
|
14459
14883
|
}
|
|
14460
14884
|
installed = this.installRoute(parsed.route_channel, parsed.route_epoch, reverseRequests);
|
|
14885
|
+
if (parsed.request_window !== undefined)
|
|
14886
|
+
this.gates.set(installed, new RequestGate(parsed.request_window, parsed.watch_window));
|
|
14461
14887
|
this.routeModules.set(parsed.route_channel, target.module_id);
|
|
14462
14888
|
return true;
|
|
14463
14889
|
};
|
|
@@ -14487,7 +14913,7 @@ class SubcClient {
|
|
|
14487
14913
|
const bytes = binary ? requireBinaryBody(body) : body instanceof Uint8Array ? body : this.encode(body);
|
|
14488
14914
|
const priority = opts.priority ?? Priority.Interactive;
|
|
14489
14915
|
const admission = opts.admissionClass ?? AdmissionClass.Normal;
|
|
14490
|
-
const reply = await this.send(handle, bytes, priority, admission, opts.timeoutMs, opts.onProgress, undefined, undefined, binary, opts.signal);
|
|
14916
|
+
const reply = await this.send(handle, bytes, priority, admission, opts.timeoutMs, opts.onProgress, undefined, undefined, binary, opts.signal, validatedSleepGraceMs(opts.sleepGraceMs ?? this.opts.sleepGraceMs ?? DEFAULT_SLEEP_GRACE_MS));
|
|
14491
14917
|
return this.decodeReply(reply);
|
|
14492
14918
|
}
|
|
14493
14919
|
async call(moduleId, method, params, opts = {}) {
|
|
@@ -14503,10 +14929,12 @@ class SubcClient {
|
|
|
14503
14929
|
}
|
|
14504
14930
|
async managedCall(moduleId, body, opts) {
|
|
14505
14931
|
let retriedUnknownChannel = false;
|
|
14932
|
+
const startedAt = opts.timeoutMs === undefined ? undefined : this.opts.now();
|
|
14933
|
+
let attemptOpts = opts;
|
|
14506
14934
|
for (;; ) {
|
|
14507
|
-
const routeHandle = await this.cachedRouteHandle(moduleId,
|
|
14935
|
+
const routeHandle = await this.cachedRouteHandle(moduleId, attemptOpts);
|
|
14508
14936
|
try {
|
|
14509
|
-
return await this.managedRequest(routeHandle, body,
|
|
14937
|
+
return await this.managedRequest(routeHandle, body, attemptOpts);
|
|
14510
14938
|
} catch (err) {
|
|
14511
14939
|
if (!(err instanceof SubcCallError))
|
|
14512
14940
|
throw this.terminalCallError("managed call failed", err);
|
|
@@ -14516,6 +14944,15 @@ class SubcClient {
|
|
|
14516
14944
|
this.evictRouteHandle(routeHandle);
|
|
14517
14945
|
continue;
|
|
14518
14946
|
}
|
|
14947
|
+
if (isDataPlaneDrainRefusal(err.code) && !retriedUnknownChannel && !this.closeStarted && !opts.signal?.aborted) {
|
|
14948
|
+
const remainingMs = opts.timeoutMs === undefined || startedAt === undefined ? undefined : opts.timeoutMs - (this.opts.now() - startedAt);
|
|
14949
|
+
if (remainingMs === undefined || remainingMs > 0) {
|
|
14950
|
+
retriedUnknownChannel = true;
|
|
14951
|
+
this.evictRouteHandle(routeHandle);
|
|
14952
|
+
attemptOpts = remainingMs === undefined ? opts : { ...opts, timeoutMs: remainingMs };
|
|
14953
|
+
continue;
|
|
14954
|
+
}
|
|
14955
|
+
}
|
|
14519
14956
|
if (deadBindCode && retriedUnknownChannel) {
|
|
14520
14957
|
this.evictRouteHandle(routeHandle);
|
|
14521
14958
|
}
|
|
@@ -14545,6 +14982,8 @@ class SubcClient {
|
|
|
14545
14982
|
}
|
|
14546
14983
|
subscribe(handle, body, onEvent, opts = {}) {
|
|
14547
14984
|
this.assertLiveHandle(handle);
|
|
14985
|
+
if (this.gates.has(handle))
|
|
14986
|
+
return this.subscribeGated(handle, body, onEvent, opts);
|
|
14548
14987
|
const bytes = body instanceof Uint8Array ? body : this.encode(body);
|
|
14549
14988
|
const priority = opts.priority ?? Priority.Interactive;
|
|
14550
14989
|
const admission = opts.admissionClass ?? AdmissionClass.Normal;
|
|
@@ -14552,22 +14991,43 @@ class SubcClient {
|
|
|
14552
14991
|
const key = pendingKey(handle, corr);
|
|
14553
14992
|
let subscriptionPending = null;
|
|
14554
14993
|
let resolveClosed = null;
|
|
14994
|
+
let resolveEnded;
|
|
14995
|
+
const ended = new Promise((resolve) => {
|
|
14996
|
+
resolveEnded = resolve;
|
|
14997
|
+
});
|
|
14998
|
+
const endFailure = (err, frame) => {
|
|
14999
|
+
if (frame?.header.ty === FrameType.Error) {
|
|
15000
|
+
const error = err;
|
|
15001
|
+
resolveEnded({ kind: "error", code: error.code, message: error.message, detail: error.detail });
|
|
15002
|
+
} else if (err instanceof SubcError && err.closeReason && err.closeReason !== "connection_lost") {
|
|
15003
|
+
resolveEnded({ kind: "route_closed", reason: err.closeReason });
|
|
15004
|
+
} else {
|
|
15005
|
+
resolveEnded({ kind: "connection_lost" });
|
|
15006
|
+
}
|
|
15007
|
+
};
|
|
14555
15008
|
const closed = new Promise((resolve, reject) => {
|
|
14556
15009
|
if (this.closedErr) {
|
|
15010
|
+
endFailure(this.closedErr);
|
|
14557
15011
|
reject(this.closedErr);
|
|
14558
15012
|
return;
|
|
14559
15013
|
}
|
|
14560
15014
|
resolveClosed = resolve;
|
|
14561
15015
|
subscriptionPending = {
|
|
14562
15016
|
handle,
|
|
14563
|
-
resolve: () =>
|
|
14564
|
-
|
|
15017
|
+
resolve: (frame) => {
|
|
15018
|
+
resolveEnded(frame.header.ty === FrameType.Response ? { kind: "response", body: frame.body } : { kind: "stream_end" });
|
|
15019
|
+
resolve();
|
|
15020
|
+
},
|
|
15021
|
+
reject: (err, frame) => {
|
|
15022
|
+
endFailure(err, frame);
|
|
15023
|
+
reject(err);
|
|
15024
|
+
},
|
|
14565
15025
|
onProgress: onEvent,
|
|
14566
15026
|
timer: null,
|
|
14567
15027
|
subscription: true
|
|
14568
15028
|
};
|
|
14569
15029
|
this.pending.set(key, subscriptionPending);
|
|
14570
|
-
const frame = buildFrame(FrameType.Request, buildFlags(false, priority, false, admission), handle.channel, handle.epoch, corr, bytes);
|
|
15030
|
+
const frame = buildFrame(FrameType.Request, buildFlags(false, priority, false, admission) | SUBSCRIPTION_FLAG, handle.channel, handle.epoch, corr, bytes);
|
|
14571
15031
|
writeBorrowed(this.sock, encodeFrame(frame), Date.now() + DEFAULT_REQUEST_TIMEOUT_MS).catch((err) => {
|
|
14572
15032
|
const pending = this.pending.get(key);
|
|
14573
15033
|
if (pending)
|
|
@@ -14580,11 +15040,14 @@ class SubcClient {
|
|
|
14580
15040
|
return;
|
|
14581
15041
|
cancelled = true;
|
|
14582
15042
|
if (subscriptionPending && resolveClosed)
|
|
14583
|
-
this.settle(key, subscriptionPending,
|
|
15043
|
+
this.settle(key, subscriptionPending, () => {
|
|
15044
|
+
resolveEnded({ kind: "cancelled" });
|
|
15045
|
+
resolveClosed?.();
|
|
15046
|
+
});
|
|
14584
15047
|
if (this.isLiveHandle(handle))
|
|
14585
15048
|
this.cancel(handle, corr, priority);
|
|
14586
15049
|
};
|
|
14587
|
-
return { unsubscribe, closed };
|
|
15050
|
+
return { unsubscribe, closed, ended };
|
|
14588
15051
|
}
|
|
14589
15052
|
attachCancelSignal(signal, key, handle, corr, priority) {
|
|
14590
15053
|
if (!handle)
|
|
@@ -14650,7 +15113,7 @@ class SubcClient {
|
|
|
14650
15113
|
this.sendRouteGoodbye(handle);
|
|
14651
15114
|
}
|
|
14652
15115
|
async closeManagedRoute(target, identity, opts = {}) {
|
|
14653
|
-
const key = routeCacheKey(target, identity, routeOpenConsumerIdentity(opts), (opts.reverseRequests ?? new ReverseRequestRegistry).capabilities(), validatedRouteScope(opts.scope));
|
|
15116
|
+
const key = routeCacheKey(target, identity, await routeOpenConsumerIdentity(opts), (opts.reverseRequests ?? new ReverseRequestRegistry).capabilities(), validatedRouteScope(opts.scope));
|
|
14654
15117
|
const cached = this.routes.get(key);
|
|
14655
15118
|
if (!cached)
|
|
14656
15119
|
return;
|
|
@@ -14703,10 +15166,21 @@ class SubcClient {
|
|
|
14703
15166
|
});
|
|
14704
15167
|
}
|
|
14705
15168
|
static async openConnection(opts) {
|
|
14706
|
-
const conn = await readConnectionFile(opts.connectionFile);
|
|
15169
|
+
const conn = opts.transport === "local" ? await readConnectionFileWithLocalEndpoint(opts.connectionFile) : await readConnectionFile(opts.connectionFile);
|
|
14707
15170
|
const deadline = Date.now() + (opts.handshakeTimeoutMs ?? DEFAULT_HANDSHAKE_TIMEOUT_MS);
|
|
14708
15171
|
const endpoint = conn.endpoints[0];
|
|
14709
|
-
|
|
15172
|
+
let sock;
|
|
15173
|
+
if (opts.transport === "local") {
|
|
15174
|
+
const local = conn.localEndpoint;
|
|
15175
|
+
if (!local)
|
|
15176
|
+
throw new SubcError("connection file has no local_endpoint", "local_endpoint_absent");
|
|
15177
|
+
if (local.kind === "unix" !== (process.platform !== "win32")) {
|
|
15178
|
+
throw new SubcError("unsupported local endpoint kind on this platform", "local_endpoint_unsupported");
|
|
15179
|
+
}
|
|
15180
|
+
sock = await SubcSocket.connectLocal(local.kind === "unix" ? local.path : local.name, deadline);
|
|
15181
|
+
} else {
|
|
15182
|
+
sock = await SubcSocket.connect(endpoint.host, endpoint.port, deadline);
|
|
15183
|
+
}
|
|
14710
15184
|
try {
|
|
14711
15185
|
await authenticateClient(sock, conn, deadline);
|
|
14712
15186
|
} catch (err) {
|
|
@@ -14718,7 +15192,125 @@ class SubcClient {
|
|
|
14718
15192
|
async controlRpc(body, acceptFrame, onLateResponse) {
|
|
14719
15193
|
return this.send(null, body, Priority.Interactive, AdmissionClass.Normal, undefined, undefined, acceptFrame, onLateResponse);
|
|
14720
15194
|
}
|
|
14721
|
-
send(
|
|
15195
|
+
send(...args) {
|
|
15196
|
+
const [handle, body, priority, admission, timeoutMs, onProgress, acceptFrame, onLateResponse, binary, signal, sleepGraceMs] = args;
|
|
15197
|
+
if (!handle || !this.gates.has(handle))
|
|
15198
|
+
return this.sendAttempt(...args);
|
|
15199
|
+
return this.gatedRequest(handle, false, timeoutMs, signal, (slot, remaining) => this.sendAttempt(handle, body, priority, admission, remaining, onProgress, acceptFrame, onLateResponse, binary, signal, sleepGraceMs, slot));
|
|
15200
|
+
}
|
|
15201
|
+
async gatedRequest(handle, watch, timeoutMs, signal, attempt) {
|
|
15202
|
+
const gate = this.gates.get(handle);
|
|
15203
|
+
const deadline = this.opts.now() + (timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS);
|
|
15204
|
+
let slot;
|
|
15205
|
+
try {
|
|
15206
|
+
slot = await gate.acquire(watch, deadline - this.opts.now(), signal);
|
|
15207
|
+
} catch (error) {
|
|
15208
|
+
throw this.notSentCallError("request was not sent while waiting for a route slot", error);
|
|
15209
|
+
}
|
|
15210
|
+
let delay = 25;
|
|
15211
|
+
let busyDeadlineError;
|
|
15212
|
+
try {
|
|
15213
|
+
for (;; ) {
|
|
15214
|
+
if (gate.signal.aborted)
|
|
15215
|
+
throw gate.signal.reason;
|
|
15216
|
+
if (signal?.aborted)
|
|
15217
|
+
throw this.notSentCallError("request cancelled before write", signal.reason);
|
|
15218
|
+
this.assertLiveHandle(handle);
|
|
15219
|
+
const budget = deadline - this.opts.now();
|
|
15220
|
+
if (budget < MIN_REQUEST_BUDGET_MS)
|
|
15221
|
+
throw busyDeadlineError ?? this.notSentCallError("request deadline elapsed before write", new Error("less than 1ms remains before the request deadline"));
|
|
15222
|
+
try {
|
|
15223
|
+
return await attempt(slot, budget);
|
|
15224
|
+
} catch (error) {
|
|
15225
|
+
const refusal = error instanceof SubcError ? error : error instanceof SubcCallError && error.cause instanceof SubcError ? error.cause : undefined;
|
|
15226
|
+
if (!refusal || !isRouteBusyRetryable(errorFrameFlags.get(refusal) ?? 0, refusal.code, this.gates.get(handle) === gate))
|
|
15227
|
+
throw error;
|
|
15228
|
+
const exhausted = () => new SubcCallError("not_sent", `daemon refused before forwarding: ${refusal.message}`, "route_busy", refusal);
|
|
15229
|
+
busyDeadlineError = exhausted();
|
|
15230
|
+
const remaining = deadline - this.opts.now();
|
|
15231
|
+
if (remaining <= 0 || signal?.aborted)
|
|
15232
|
+
throw exhausted();
|
|
15233
|
+
const ms = Math.min(remaining, delay * (0.5 + this.opts.random() * 0.5));
|
|
15234
|
+
delay = Math.min(1000, delay * 2);
|
|
15235
|
+
const proceed = await this.busySleep(ms, gate.signal, signal);
|
|
15236
|
+
if (gate.signal.aborted)
|
|
15237
|
+
throw gate.signal.reason;
|
|
15238
|
+
if (!proceed || this.opts.now() >= deadline)
|
|
15239
|
+
throw exhausted();
|
|
15240
|
+
}
|
|
15241
|
+
}
|
|
15242
|
+
} finally {
|
|
15243
|
+
if (!slot.inFlight)
|
|
15244
|
+
slot.release();
|
|
15245
|
+
}
|
|
15246
|
+
}
|
|
15247
|
+
async busySleep(ms, closed, signal) {
|
|
15248
|
+
if (closed.aborted || signal?.aborted)
|
|
15249
|
+
return false;
|
|
15250
|
+
let abort;
|
|
15251
|
+
const cancelled = new Promise((resolve) => {
|
|
15252
|
+
abort = () => resolve(false);
|
|
15253
|
+
});
|
|
15254
|
+
closed.addEventListener("abort", abort, { once: true });
|
|
15255
|
+
signal?.addEventListener("abort", abort, { once: true });
|
|
15256
|
+
try {
|
|
15257
|
+
return await Promise.race([this.opts.sleep(ms).then(() => true), cancelled]);
|
|
15258
|
+
} finally {
|
|
15259
|
+
closed.removeEventListener("abort", abort);
|
|
15260
|
+
signal?.removeEventListener("abort", abort);
|
|
15261
|
+
}
|
|
15262
|
+
}
|
|
15263
|
+
subscribeGated(handle, body, onEvent, opts) {
|
|
15264
|
+
const bytes = body instanceof Uint8Array ? body : this.encode(body);
|
|
15265
|
+
const priority = opts.priority ?? Priority.Interactive;
|
|
15266
|
+
const admission = opts.admissionClass ?? AdmissionClass.Normal;
|
|
15267
|
+
const abort = new AbortController;
|
|
15268
|
+
let current;
|
|
15269
|
+
let cancelled = false;
|
|
15270
|
+
let resolveClosed;
|
|
15271
|
+
let rejectClosed;
|
|
15272
|
+
let resolveEnded;
|
|
15273
|
+
const closed = new Promise((resolve, reject) => {
|
|
15274
|
+
resolveClosed = resolve;
|
|
15275
|
+
rejectClosed = reject;
|
|
15276
|
+
});
|
|
15277
|
+
const ended = new Promise((resolve) => {
|
|
15278
|
+
resolveEnded = resolve;
|
|
15279
|
+
});
|
|
15280
|
+
this.gatedRequest(handle, true, undefined, abort.signal, (slot, remaining) => this.sendAttempt(handle, bytes, priority, admission, remaining, onEvent, undefined, undefined, false, undefined, undefined, slot, true, (key, pending, corr) => {
|
|
15281
|
+
current = { key, pending, corr };
|
|
15282
|
+
})).then((frame) => {
|
|
15283
|
+
if (cancelled)
|
|
15284
|
+
return;
|
|
15285
|
+
resolveEnded(frame.header.ty === FrameType.Response ? { kind: "response", body: frame.body } : { kind: "stream_end" });
|
|
15286
|
+
resolveClosed();
|
|
15287
|
+
}, (error) => {
|
|
15288
|
+
if (cancelled)
|
|
15289
|
+
return;
|
|
15290
|
+
if (error instanceof SubcError && error.closeReason)
|
|
15291
|
+
resolveEnded(error.closeReason === "connection_lost" ? { kind: "connection_lost" } : { kind: "route_closed", reason: error.closeReason });
|
|
15292
|
+
else if (error instanceof SubcError || error instanceof SubcCallError)
|
|
15293
|
+
resolveEnded({ kind: "error", code: error.code, message: error.message, detail: error.detail });
|
|
15294
|
+
else
|
|
15295
|
+
resolveEnded({ kind: "connection_lost" });
|
|
15296
|
+
rejectClosed(error);
|
|
15297
|
+
});
|
|
15298
|
+
return { closed, ended, unsubscribe: () => {
|
|
15299
|
+
if (cancelled)
|
|
15300
|
+
return;
|
|
15301
|
+
cancelled = true;
|
|
15302
|
+
abort.abort();
|
|
15303
|
+
if (current && this.pending.get(current.key) === current.pending) {
|
|
15304
|
+
const { key, pending, corr } = current;
|
|
15305
|
+
this.settle(key, pending, () => pending.reject(new SubcError("subscription cancelled")));
|
|
15306
|
+
if (this.isLiveHandle(handle))
|
|
15307
|
+
this.cancel(handle, corr, priority);
|
|
15308
|
+
}
|
|
15309
|
+
resolveEnded({ kind: "cancelled" });
|
|
15310
|
+
resolveClosed();
|
|
15311
|
+
} };
|
|
15312
|
+
}
|
|
15313
|
+
sendAttempt(handle, body, priority, admission, timeoutMs, onProgress, acceptFrame, onLateResponse, binary = false, signal, sleepGraceMs = this.opts.sleepGraceMs ?? DEFAULT_SLEEP_GRACE_MS, slot, subscription = false, registered) {
|
|
14722
15314
|
if (handle)
|
|
14723
15315
|
this.assertLiveHandle(handle);
|
|
14724
15316
|
if (this.closedErr)
|
|
@@ -14732,7 +15324,7 @@ class SubcClient {
|
|
|
14732
15324
|
const key = pendingKey(handle, corr);
|
|
14733
15325
|
const channel = handle?.channel ?? 0;
|
|
14734
15326
|
const epoch = handle?.epoch ?? 0;
|
|
14735
|
-
const frame = buildFrame(FrameType.Request, buildFlags(binary, priority, false, admission), channel, epoch, corr, body);
|
|
15327
|
+
const frame = buildFrame(FrameType.Request, buildFlags(binary, priority, false, admission) | (subscription ? SUBSCRIPTION_FLAG : 0), channel, epoch, corr, body);
|
|
14736
15328
|
return new Promise((resolve, reject) => {
|
|
14737
15329
|
const ms = timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
|
|
14738
15330
|
const pending = {
|
|
@@ -14742,11 +15334,27 @@ class SubcClient {
|
|
|
14742
15334
|
onProgress,
|
|
14743
15335
|
timer: null,
|
|
14744
15336
|
acceptFrame,
|
|
14745
|
-
onLateResponse
|
|
15337
|
+
onLateResponse,
|
|
15338
|
+
slot,
|
|
15339
|
+
subscription
|
|
14746
15340
|
};
|
|
14747
|
-
|
|
15341
|
+
if (!subscription)
|
|
15342
|
+
this.armRequestTimeout(key, pending, channel, corr, ms, sleepGraceMs);
|
|
14748
15343
|
this.pending.set(key, pending);
|
|
14749
|
-
|
|
15344
|
+
registered?.(key, pending, corr);
|
|
15345
|
+
if (slot && handle) {
|
|
15346
|
+
slot.inFlight = true;
|
|
15347
|
+
this.slots.set(key, { handle, slot });
|
|
15348
|
+
}
|
|
15349
|
+
const write = writeTrackedBorrowed(this.sock, encodeFrame(frame), Date.now() + ms);
|
|
15350
|
+
if (slot && !write.queued) {
|
|
15351
|
+
this.slots.delete(key);
|
|
15352
|
+
slot.inFlight = false;
|
|
15353
|
+
slot.release();
|
|
15354
|
+
}
|
|
15355
|
+
write.completed.catch((error) => {
|
|
15356
|
+
if (error instanceof SocketWriteNotQueuedError || error instanceof SocketWriteQueuedError)
|
|
15357
|
+
error = error.cause ?? error;
|
|
14750
15358
|
const current = this.pending.get(key);
|
|
14751
15359
|
if (current)
|
|
14752
15360
|
this.rejectPending(key, current, error instanceof Error ? error : new SubcError(String(error)));
|
|
@@ -14755,10 +15363,16 @@ class SubcClient {
|
|
|
14755
15363
|
this.attachCancelSignal(signal, key, handle, corr, priority);
|
|
14756
15364
|
});
|
|
14757
15365
|
}
|
|
15366
|
+
armRequestTimeout(key, pending, channel, corr, ms, sleepGraceMs) {
|
|
15367
|
+
pending.sleepGrace = { wallStartMs: Date.now(), awakeStartMs: performance.now(), ms: sleepGraceMs, used: false };
|
|
15368
|
+
pending.timer = setTimeout(() => this.arbitrateTimeout(key, pending, channel, corr, ms), ms);
|
|
15369
|
+
}
|
|
14758
15370
|
arbitrateTimeout(key, pending, channel, corr, ms) {
|
|
14759
15371
|
const settleAsTimeout = () => {
|
|
14760
15372
|
if (pending.onLateResponse)
|
|
14761
15373
|
this.lateResponses.set(key, pending.onLateResponse);
|
|
15374
|
+
if (pending.slot?.inFlight && pending.handle && this.isLiveHandle(pending.handle))
|
|
15375
|
+
this.cancel(pending.handle, corr);
|
|
14762
15376
|
this.rejectPending(key, pending, new SubcError(this.timeoutMessage(channel, corr, ms), REQUEST_DEADLINE_MARKER));
|
|
14763
15377
|
};
|
|
14764
15378
|
const graceDeadline = Date.now() + this.opts.timeoutArbitrationGraceMs;
|
|
@@ -14770,6 +15384,17 @@ class SubcClient {
|
|
|
14770
15384
|
setImmediate(arbitrate);
|
|
14771
15385
|
return;
|
|
14772
15386
|
}
|
|
15387
|
+
const sleep = pending.sleepGrace;
|
|
15388
|
+
if (sleep && !sleep.used && sleep.ms > 0) {
|
|
15389
|
+
const wallElapsed = Date.now() - sleep.wallStartMs;
|
|
15390
|
+
const awakeElapsed = performance.now() - sleep.awakeStartMs;
|
|
15391
|
+
const sleptMs = wallElapsed - awakeElapsed;
|
|
15392
|
+
if (sleptMs > SLEEP_DETECTION_THRESHOLD_MS) {
|
|
15393
|
+
sleep.used = true;
|
|
15394
|
+
pending.timer = setTimeout(() => this.arbitrateTimeout(key, pending, channel, corr, ms), sleep.ms);
|
|
15395
|
+
return;
|
|
15396
|
+
}
|
|
15397
|
+
}
|
|
14773
15398
|
settleAsTimeout();
|
|
14774
15399
|
};
|
|
14775
15400
|
setImmediate(arbitrate);
|
|
@@ -14780,7 +15405,7 @@ class SubcClient {
|
|
|
14780
15405
|
const priority = opts.priority ?? Priority.Interactive;
|
|
14781
15406
|
const admission = opts.admissionClass ?? AdmissionClass.Normal;
|
|
14782
15407
|
try {
|
|
14783
|
-
const reply = await this.sendManaged(handle, bytes, priority, admission, opts.timeoutMs, opts.onProgress, binary, opts.signal);
|
|
15408
|
+
const reply = await this.sendManaged(handle, bytes, priority, admission, opts.timeoutMs, opts.onProgress, binary, opts.signal, validatedSleepGraceMs(opts.sleepGraceMs ?? this.opts.sleepGraceMs ?? DEFAULT_SLEEP_GRACE_MS));
|
|
14784
15409
|
return this.decodeReply(reply);
|
|
14785
15410
|
} catch (error) {
|
|
14786
15411
|
if (error instanceof SubcCallError)
|
|
@@ -14788,7 +15413,13 @@ class SubcClient {
|
|
|
14788
15413
|
throw this.terminalCallError("managed call failed", error);
|
|
14789
15414
|
}
|
|
14790
15415
|
}
|
|
14791
|
-
sendManaged(
|
|
15416
|
+
sendManaged(...args) {
|
|
15417
|
+
const [handle, body, priority, admission, timeoutMs, onProgress, binary, signal, sleepGraceMs] = args;
|
|
15418
|
+
if (!this.gates.has(handle))
|
|
15419
|
+
return this.sendManagedAttempt(...args);
|
|
15420
|
+
return this.gatedRequest(handle, false, timeoutMs, signal, (slot, remaining) => this.sendManagedAttempt(handle, body, priority, admission, remaining, onProgress, binary, signal, sleepGraceMs, slot));
|
|
15421
|
+
}
|
|
15422
|
+
sendManagedAttempt(handle, body, priority, admission, timeoutMs, onProgress, binary = false, signal, sleepGraceMs = this.opts.sleepGraceMs ?? DEFAULT_SLEEP_GRACE_MS, slot) {
|
|
14792
15423
|
try {
|
|
14793
15424
|
this.assertLiveHandle(handle);
|
|
14794
15425
|
} catch (error) {
|
|
@@ -14822,12 +15453,22 @@ class SubcClient {
|
|
|
14822
15453
|
reject,
|
|
14823
15454
|
onProgress,
|
|
14824
15455
|
timer: null,
|
|
14825
|
-
classifyFailure
|
|
15456
|
+
classifyFailure,
|
|
15457
|
+
slot
|
|
14826
15458
|
};
|
|
14827
|
-
|
|
15459
|
+
this.armRequestTimeout(key, pending, handle.channel, corr, ms, sleepGraceMs);
|
|
14828
15460
|
this.pending.set(key, pending);
|
|
15461
|
+
if (slot) {
|
|
15462
|
+
slot.inFlight = true;
|
|
15463
|
+
this.slots.set(key, { handle, slot });
|
|
15464
|
+
}
|
|
14829
15465
|
const write = writeTrackedBorrowed(this.sock, encodeFrame(frame), Date.now() + ms);
|
|
14830
15466
|
handedToSocket = write.queued;
|
|
15467
|
+
if (slot && !write.queued) {
|
|
15468
|
+
this.slots.delete(key);
|
|
15469
|
+
slot.inFlight = false;
|
|
15470
|
+
slot.release();
|
|
15471
|
+
}
|
|
14831
15472
|
write.completed.catch((error) => {
|
|
14832
15473
|
const current = this.pending.get(key);
|
|
14833
15474
|
if (current)
|
|
@@ -14844,7 +15485,7 @@ class SubcClient {
|
|
|
14844
15485
|
throw new SubcCallError("terminal", "managed call requires a BindIdentity in SubcClient.connect({ identity }) or call(..., { identity })", "missing_identity");
|
|
14845
15486
|
}
|
|
14846
15487
|
const target = { kind: opts.targetKind ?? this.opts.targetKind, module_id: moduleId };
|
|
14847
|
-
const consumerIdentity = routeOpenConsumerIdentity(opts);
|
|
15488
|
+
const consumerIdentity = await routeOpenConsumerIdentity(opts);
|
|
14848
15489
|
const reverseRequests = opts.reverseRequests ?? new ReverseRequestRegistry;
|
|
14849
15490
|
reverseRequests.seal();
|
|
14850
15491
|
const key = routeCacheKey(target, identity, consumerIdentity, reverseRequests.capabilities(), scope);
|
|
@@ -14929,6 +15570,7 @@ class SubcClient {
|
|
|
14929
15570
|
if ("handle" in outcome) {
|
|
14930
15571
|
const { handle } = outcome;
|
|
14931
15572
|
if (cached.closed) {
|
|
15573
|
+
this.failHandle(handle, new SubcError("route closed during route.open", "route_closed", undefined, "closed_by_caller"));
|
|
14932
15574
|
this.liveRoutes.delete(handle.channel);
|
|
14933
15575
|
this.sendRouteGoodbye(handle);
|
|
14934
15576
|
throw this.routeClosedDuringOpen();
|
|
@@ -15052,6 +15694,9 @@ class SubcClient {
|
|
|
15052
15694
|
return;
|
|
15053
15695
|
} catch (err) {
|
|
15054
15696
|
if (!isConsumerReconnectTransient(err) || attempt >= this.opts.reconnectBackoff.maxAttempts) {
|
|
15697
|
+
if (isConsumerReconnectTransient(err) && !(err instanceof AuthError)) {
|
|
15698
|
+
throw new DaemonUnavailableError(err);
|
|
15699
|
+
}
|
|
15055
15700
|
if (err instanceof AuthError && attempt > 1) {
|
|
15056
15701
|
throw new AuthError(`reconnect gave up after ${attempt} attempts: ${err.message} — the connection file and the daemon's key disagree persistently ` + `(daemon restarting in a loop, split connection-file paths, or a genuinely foreign daemon on this port); ` + `check the daemon, then restart this host app`);
|
|
15057
15702
|
}
|
|
@@ -15174,6 +15819,16 @@ class SubcClient {
|
|
|
15174
15819
|
}
|
|
15175
15820
|
const key = pendingKey(handle, frame.header.corr);
|
|
15176
15821
|
const pending = this.pending.get(key);
|
|
15822
|
+
if (frame.header.ty === FrameType.Response || frame.header.ty === FrameType.Error || frame.header.ty === FrameType.StreamEnd) {
|
|
15823
|
+
const record = this.slots.get(key);
|
|
15824
|
+
if (record) {
|
|
15825
|
+
this.slots.delete(key);
|
|
15826
|
+
record.slot.inFlight = false;
|
|
15827
|
+
const busy = frame.header.ty === FrameType.Error && pending?.slot === record.slot && isRouteBusyRetryable(frame.header.flags, this.errorFromFrame(frame).code, !!handle && this.gates.has(handle));
|
|
15828
|
+
if (!busy)
|
|
15829
|
+
record.slot.release();
|
|
15830
|
+
}
|
|
15831
|
+
}
|
|
15177
15832
|
if (pending) {
|
|
15178
15833
|
if (pending.acceptFrame && !pending.acceptFrame(frame))
|
|
15179
15834
|
return;
|
|
@@ -15189,7 +15844,7 @@ class SubcClient {
|
|
|
15189
15844
|
this.settle(key, pending, () => pending.resolve(frame));
|
|
15190
15845
|
return;
|
|
15191
15846
|
case FrameType.Error:
|
|
15192
|
-
this.settle(key, pending, () => pending.reject(this.errorFromFrame(frame)));
|
|
15847
|
+
this.settle(key, pending, () => pending.reject(this.errorFromFrame(frame), frame));
|
|
15193
15848
|
return;
|
|
15194
15849
|
default:
|
|
15195
15850
|
return;
|
|
@@ -15326,6 +15981,14 @@ class SubcClient {
|
|
|
15326
15981
|
return this.legacyChannelReasons.get(channel) ?? "unknown";
|
|
15327
15982
|
}
|
|
15328
15983
|
failHandle(handle, error) {
|
|
15984
|
+
this.gates.get(handle)?.close(error);
|
|
15985
|
+
this.gates.delete(handle);
|
|
15986
|
+
for (const [key, record] of this.slots) {
|
|
15987
|
+
if (sameRouteHandle(record.handle, handle)) {
|
|
15988
|
+
record.slot.release();
|
|
15989
|
+
this.slots.delete(key);
|
|
15990
|
+
}
|
|
15991
|
+
}
|
|
15329
15992
|
for (const [key, pending] of this.pending) {
|
|
15330
15993
|
if (pending.handle && sameRouteHandle(pending.handle, handle))
|
|
15331
15994
|
this.rejectPending(key, pending, error);
|
|
@@ -15335,6 +15998,10 @@ class SubcClient {
|
|
|
15335
15998
|
const routeError = err instanceof SubcError && err.closeReason ? err : new SubcError(err.message, errorCode(err), undefined, this.closeStarted ? "closed_by_caller" : "connection_lost");
|
|
15336
15999
|
if (!this.closedErr)
|
|
15337
16000
|
this.closedErr = err;
|
|
16001
|
+
for (const gate of this.gates.values())
|
|
16002
|
+
gate.close(routeError);
|
|
16003
|
+
this.gates.clear();
|
|
16004
|
+
this.slots.clear();
|
|
15338
16005
|
this.routeEndReasons.clear();
|
|
15339
16006
|
this.legacyChannelReasons.clear();
|
|
15340
16007
|
this.routeModules.clear();
|
|
@@ -15368,6 +16035,9 @@ class SubcClient {
|
|
|
15368
16035
|
return this.ingressEpochDropCount;
|
|
15369
16036
|
}
|
|
15370
16037
|
installRoute(channel, epoch, reverseRequests = new ReverseRequestRegistry) {
|
|
16038
|
+
const previous = this.liveRoutes.get(channel);
|
|
16039
|
+
if (previous && this.gates.has(previous))
|
|
16040
|
+
this.failHandle(previous, new SubcError("route replaced", "route_closed", undefined, "closed_by_caller"));
|
|
15371
16041
|
const handle = createRouteHandle(channel, epoch, this.connectionToken, reverseRequests);
|
|
15372
16042
|
this.routeEndReasons.delete(channel);
|
|
15373
16043
|
this.legacyChannelReasons.delete(channel);
|
|
@@ -15438,9 +16108,15 @@ function isRetryableRouteOpenCode(code) {
|
|
|
15438
16108
|
return false;
|
|
15439
16109
|
if (code === "target_flow_unsupported")
|
|
15440
16110
|
return false;
|
|
16111
|
+
if (code === "target_federated_unsupported")
|
|
16112
|
+
return false;
|
|
15441
16113
|
if (code === "target_agent_run_unsupported")
|
|
15442
16114
|
return false;
|
|
15443
|
-
|
|
16115
|
+
if (code === "scope_bind_proof_required" || code === "scope_bind_proof_mismatch")
|
|
16116
|
+
return false;
|
|
16117
|
+
if (code === "scope_epoch_in_use")
|
|
16118
|
+
return false;
|
|
16119
|
+
return code === "module_reloading" || code === "module_warming" || code === "target_unavailable" || code === "module_timeout" || code === "scope_not_synced" || code === "scope_changed" || code === "session_address_unavailable" || code === "bind_busy";
|
|
15444
16120
|
}
|
|
15445
16121
|
function equalJitter(delayMs, random) {
|
|
15446
16122
|
const half = delayMs / 2;
|
|
@@ -15477,6 +16153,12 @@ var STALE_ROUTE_EPOCH = "stale_route_epoch";
|
|
|
15477
16153
|
function isEstablishedRouteDead(_flags, code) {
|
|
15478
16154
|
return code === UNKNOWN_CHANNEL || code === STALE_ROUTE_EPOCH;
|
|
15479
16155
|
}
|
|
16156
|
+
function isRouteBusyRetryable(flags, code, routeOptedIn) {
|
|
16157
|
+
return routeOptedIn && (flags & DAEMON_ORIGIN_FLAG) !== 0 && code === "route_busy";
|
|
16158
|
+
}
|
|
16159
|
+
function isDataPlaneDrainRefusal(code) {
|
|
16160
|
+
return code === "module_reloading";
|
|
16161
|
+
}
|
|
15480
16162
|
async function connectionFileExists(path) {
|
|
15481
16163
|
try {
|
|
15482
16164
|
await fs3.access(path);
|
|
@@ -15488,6 +16170,7 @@ async function connectionFileExists(path) {
|
|
|
15488
16170
|
function normalizeConnectOptions(opts) {
|
|
15489
16171
|
return {
|
|
15490
16172
|
connectionFile: opts.connectionFile,
|
|
16173
|
+
transport: opts.transport ?? "tcp",
|
|
15491
16174
|
handshakeTimeoutMs: opts.handshakeTimeoutMs,
|
|
15492
16175
|
identity: opts.identity,
|
|
15493
16176
|
targetKind: opts.targetKind ?? DEFAULT_MANAGED_TARGET_KIND,
|
|
@@ -15497,11 +16180,18 @@ function normalizeConnectOptions(opts) {
|
|
|
15497
16180
|
random: opts.random ?? Math.random,
|
|
15498
16181
|
routeOpenRetryDeadlineMs: opts.routeOpenRetryDeadlineMs ?? ROUTE_OPEN_RETRY_DEADLINE_MS,
|
|
15499
16182
|
timeoutArbitrationGraceMs: opts.timeoutArbitrationGraceMs ?? TIMEOUT_ARBITRATION_GRACE_MS,
|
|
16183
|
+
sleepGraceMs: validatedSleepGraceMs(opts.sleepGraceMs ?? DEFAULT_SLEEP_GRACE_MS),
|
|
15500
16184
|
bodyReadTimeoutMs: opts.bodyReadTimeoutMs,
|
|
15501
16185
|
livenessProbeWindowMs: opts.livenessProbeWindowMs ?? LIVENESS_PROBE_WINDOW_MS,
|
|
15502
16186
|
onControlPush: opts.onControlPush
|
|
15503
16187
|
};
|
|
15504
16188
|
}
|
|
16189
|
+
function validatedSleepGraceMs(ms) {
|
|
16190
|
+
if (!Number.isFinite(ms) || ms < 0 || ms > 2147483647) {
|
|
16191
|
+
throw new RangeError("sleepGraceMs must be finite and in 0..2147483647 milliseconds");
|
|
16192
|
+
}
|
|
16193
|
+
return ms;
|
|
16194
|
+
}
|
|
15505
16195
|
function isValidCapabilityIdentifier(identifier) {
|
|
15506
16196
|
if (/\s/u.test(identifier))
|
|
15507
16197
|
return false;
|
|
@@ -15524,7 +16214,13 @@ function isValidCapabilityIdentifier(identifier) {
|
|
|
15524
16214
|
function routeCacheKey(target, identity, consumerIdentity, consumerCapabilities, scope) {
|
|
15525
16215
|
const consumerPart = consumerIdentity ? `${consumerIdentity.module_id}\x00${consumerIdentity.launch_nonce}` : "";
|
|
15526
16216
|
const capabilitiesPart = [...consumerCapabilities].sort().join("\x00");
|
|
15527
|
-
const scopePart = scope ? JSON.stringify([
|
|
16217
|
+
const scopePart = scope ? JSON.stringify([
|
|
16218
|
+
scope.owner.kind,
|
|
16219
|
+
scope.owner.kind === "reserved" ? scope.owner.module_id : null,
|
|
16220
|
+
scope.ref,
|
|
16221
|
+
scope.scopeEpoch,
|
|
16222
|
+
scope.bindProof === undefined ? null : createHash4("sha256").update(scope.bindProof).digest("hex")
|
|
16223
|
+
]) : "";
|
|
15528
16224
|
return `${target.kind}\x00${target.module_id}\x00${identity.project_root}\x00${identity.harness}\x00${identity.session}\x00${consumerPart}\x00${capabilitiesPart}\x00${scopePart}`;
|
|
15529
16225
|
}
|
|
15530
16226
|
function validatedRouteScope(scope) {
|
|
@@ -15542,13 +16238,18 @@ function validatedRouteScope(scope) {
|
|
|
15542
16238
|
if (!Number.isSafeInteger(scope.scopeEpoch) || scope.scopeEpoch < 0) {
|
|
15543
16239
|
throw new SubcError("scope.scopeEpoch must be a safe non-negative integer", "invalid_scope");
|
|
15544
16240
|
}
|
|
15545
|
-
return {
|
|
16241
|
+
return {
|
|
16242
|
+
owner: { ...scope.owner },
|
|
16243
|
+
ref: scope.ref,
|
|
16244
|
+
scopeEpoch: scope.scopeEpoch,
|
|
16245
|
+
...scope.bindProof !== undefined ? { bindProof: scope.bindProof } : {}
|
|
16246
|
+
};
|
|
15546
16247
|
}
|
|
15547
|
-
function routeOpenConsumerIdentity(opts = {}) {
|
|
16248
|
+
async function routeOpenConsumerIdentity(opts = {}) {
|
|
15548
16249
|
if (opts.consumerIdentity !== undefined)
|
|
15549
16250
|
return opts.consumerIdentity ?? undefined;
|
|
15550
16251
|
const moduleId = process.env[SUBC_MODULE_ID_ENV];
|
|
15551
|
-
const launchNonce =
|
|
16252
|
+
const launchNonce = (await launchNonceOrUndefinedAsync())?.value;
|
|
15552
16253
|
if (!moduleId || !launchNonce)
|
|
15553
16254
|
return;
|
|
15554
16255
|
return { module_id: moduleId, launch_nonce: launchNonce };
|
|
@@ -16000,21 +16701,21 @@ function getLifecycleRegistry() {
|
|
|
16000
16701
|
}
|
|
16001
16702
|
|
|
16002
16703
|
// ../aft-bridge/dist/project-identity.js
|
|
16003
|
-
import { createHash as
|
|
16704
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
16004
16705
|
import { realpathSync as realpathSync3 } from "node:fs";
|
|
16005
|
-
import { posix as
|
|
16706
|
+
import { posix as posix3, resolve as resolve6, win32 as win323 } from "node:path";
|
|
16006
16707
|
function canonicalizeProjectRoot(dir) {
|
|
16007
16708
|
const trimmed = trimProjectRootSeparators(dir);
|
|
16008
16709
|
let canonical;
|
|
16009
16710
|
try {
|
|
16010
16711
|
canonical = realpathSync3(trimmed);
|
|
16011
16712
|
} catch {
|
|
16012
|
-
canonical =
|
|
16713
|
+
canonical = resolve6(trimmed);
|
|
16013
16714
|
}
|
|
16014
16715
|
return normalizeWindowsRoot(canonical);
|
|
16015
16716
|
}
|
|
16016
16717
|
function trimProjectRootSeparators(dir, platform = process.platform) {
|
|
16017
|
-
const root = (platform === "win32" ?
|
|
16718
|
+
const root = (platform === "win32" ? win323 : posix3).parse(dir).root;
|
|
16018
16719
|
const trimmed = dir.replace(/[/\\]+$/, "");
|
|
16019
16720
|
return trimmed.length < root.length ? root : trimmed;
|
|
16020
16721
|
}
|
|
@@ -16049,7 +16750,7 @@ function hasDotComponent(path) {
|
|
|
16049
16750
|
return path.split(/[\\/]/).some((component) => component === "." || component === "..");
|
|
16050
16751
|
}
|
|
16051
16752
|
function projectRootKeyHash(dir) {
|
|
16052
|
-
return
|
|
16753
|
+
return createHash5("sha256").update(canonicalizeProjectRoot(dir)).digest("hex").slice(0, 16);
|
|
16053
16754
|
}
|
|
16054
16755
|
|
|
16055
16756
|
// ../aft-bridge/dist/subc-transport.js
|
|
@@ -16816,6 +17517,8 @@ class SubcTransportPool {
|
|
|
16816
17517
|
harness;
|
|
16817
17518
|
connectionFile;
|
|
16818
17519
|
handshakeTimeoutMs;
|
|
17520
|
+
clock;
|
|
17521
|
+
waitClock;
|
|
16819
17522
|
consumerIdentity;
|
|
16820
17523
|
hostScopes;
|
|
16821
17524
|
hostScopeCache = new Map;
|
|
@@ -16858,6 +17561,13 @@ class SubcTransportPool {
|
|
|
16858
17561
|
editSlotSurvives;
|
|
16859
17562
|
editSlotSurvivesCaptured = false;
|
|
16860
17563
|
constructor(options) {
|
|
17564
|
+
this.clock = options.clock ?? {
|
|
17565
|
+
now: () => Date.now(),
|
|
17566
|
+
awakeNow: () => performance.now(),
|
|
17567
|
+
setTimeout: (callback, ms) => setTimeout(callback, ms),
|
|
17568
|
+
clearTimeout: (timer) => clearTimeout(timer)
|
|
17569
|
+
};
|
|
17570
|
+
this.waitClock = new WaitClock(() => this.clock.now(), () => this.clock.awakeNow?.() ?? this.clock.now());
|
|
16861
17571
|
this.connectionFile = options.connectionFile;
|
|
16862
17572
|
this.harness = options.harness;
|
|
16863
17573
|
this.handshakeTimeoutMs = options.handshakeTimeoutMs;
|
|
@@ -17484,11 +18194,12 @@ class SubcTransportPool {
|
|
|
17484
18194
|
this.stopUnusedHostScopeRetry(record.identity.session);
|
|
17485
18195
|
}
|
|
17486
18196
|
async routeRequest(identity, body, timeoutMs, onProgress, expectedGeneration, abortSignal) {
|
|
17487
|
-
const callStartedAt =
|
|
18197
|
+
const callStartedAt = this.waitClock.now();
|
|
17488
18198
|
const callDeadlineMs = timeoutMs ?? SUBC_DEFAULT_REQUEST_TIMEOUT_MS;
|
|
18199
|
+
const deadline = new RequestDeadline(this.waitClock, callDeadlineMs);
|
|
17489
18200
|
let scheduledDelayMs = 0;
|
|
17490
|
-
const spentMs = () => Math.max(
|
|
17491
|
-
const remainingMs = () =>
|
|
18201
|
+
const spentMs = () => Math.max(this.waitClock.now() - callStartedAt, scheduledDelayMs);
|
|
18202
|
+
const remainingMs = () => deadline.remaining() - Math.max(0, scheduledDelayMs - (this.waitClock.now() - callStartedAt));
|
|
17492
18203
|
const root = asCanonicalRootPath(identity.project_root);
|
|
17493
18204
|
let generation = expectedGeneration;
|
|
17494
18205
|
if (this.lifecycleEnabled()) {
|
|
@@ -17509,12 +18220,12 @@ class SubcTransportPool {
|
|
|
17509
18220
|
const remaining = remainingMs();
|
|
17510
18221
|
if (remaining <= 0)
|
|
17511
18222
|
throw keyChanged ?? callDeadlinePassedError(undefined, callDeadlineMs);
|
|
17512
|
-
let
|
|
18223
|
+
let cancelTimer;
|
|
17513
18224
|
try {
|
|
17514
18225
|
const acquired = await Promise.race([
|
|
17515
18226
|
this.ensureClient(),
|
|
17516
18227
|
new Promise((resolve) => {
|
|
17517
|
-
|
|
18228
|
+
cancelTimer = deadlineTimer(this.clock, remainingMs, () => resolve(CALL_DEADLINE_EXPIRED));
|
|
17518
18229
|
})
|
|
17519
18230
|
]);
|
|
17520
18231
|
if (acquired === CALL_DEADLINE_EXPIRED) {
|
|
@@ -17529,22 +18240,22 @@ class SubcTransportPool {
|
|
|
17529
18240
|
if (spentMs() + this.nextRouteReopenDelayMs() >= callDeadlineMs)
|
|
17530
18241
|
throw error;
|
|
17531
18242
|
} finally {
|
|
17532
|
-
|
|
18243
|
+
cancelTimer?.();
|
|
17533
18244
|
}
|
|
17534
18245
|
const { delayMs, wait } = this.waitForRouteReopenBackoff();
|
|
17535
18246
|
scheduledDelayMs = spentMs() + delayMs;
|
|
17536
|
-
let
|
|
18247
|
+
let cancelRetryTimer;
|
|
17537
18248
|
try {
|
|
17538
18249
|
const waited = await Promise.race([
|
|
17539
18250
|
wait,
|
|
17540
18251
|
new Promise((resolve) => {
|
|
17541
|
-
|
|
18252
|
+
cancelRetryTimer = deadlineTimer(this.clock, remainingMs, () => resolve(CALL_DEADLINE_EXPIRED));
|
|
17542
18253
|
})
|
|
17543
18254
|
]);
|
|
17544
18255
|
if (waited === CALL_DEADLINE_EXPIRED)
|
|
17545
18256
|
throw keyChanged;
|
|
17546
18257
|
} finally {
|
|
17547
|
-
|
|
18258
|
+
cancelRetryTimer?.();
|
|
17548
18259
|
}
|
|
17549
18260
|
}
|
|
17550
18261
|
this.assertRecordLive(record);
|
|
@@ -17587,9 +18298,9 @@ class SubcTransportPool {
|
|
|
17587
18298
|
const remaining = remainingMs();
|
|
17588
18299
|
if (remaining <= 0)
|
|
17589
18300
|
throw callDeadlinePassedError(lastRefusal, callDeadlineMs);
|
|
17590
|
-
let
|
|
18301
|
+
let cancelTimer;
|
|
17591
18302
|
const expired = new Promise((resolve) => {
|
|
17592
|
-
|
|
18303
|
+
cancelTimer = deadlineTimer(this.clock, remainingMs, () => resolve(CALL_DEADLINE_EXPIRED));
|
|
17593
18304
|
});
|
|
17594
18305
|
try {
|
|
17595
18306
|
const opened = await Promise.race([openRoute(), expired]);
|
|
@@ -17598,7 +18309,7 @@ class SubcTransportPool {
|
|
|
17598
18309
|
}
|
|
17599
18310
|
return opened;
|
|
17600
18311
|
} finally {
|
|
17601
|
-
|
|
18312
|
+
cancelTimer?.();
|
|
17602
18313
|
}
|
|
17603
18314
|
};
|
|
17604
18315
|
const openRouteAfterReloadWindow = async () => {
|
|
@@ -17677,6 +18388,7 @@ class SubcTransportPool {
|
|
|
17677
18388
|
try {
|
|
17678
18389
|
request = client.request(route, body, {
|
|
17679
18390
|
timeoutMs: Math.ceil(requestTimeoutMs),
|
|
18391
|
+
...deadline.resumed ? { sleepGraceMs: 0 } : {},
|
|
17680
18392
|
onProgress
|
|
17681
18393
|
});
|
|
17682
18394
|
} catch (error) {
|
|
@@ -17804,6 +18516,7 @@ class SubcTransportPool {
|
|
|
17804
18516
|
this.connecting = this.connectFn({
|
|
17805
18517
|
connectionFile: this.connectionFile,
|
|
17806
18518
|
handshakeTimeoutMs: this.handshakeTimeoutMs,
|
|
18519
|
+
sleepGraceMs: RESUME_ALLOWANCE_MS,
|
|
17807
18520
|
onControlPush: (push) => {
|
|
17808
18521
|
if (owner && this.client === owner)
|
|
17809
18522
|
this.onScopeRouteClose(push);
|
|
@@ -18805,7 +19518,7 @@ function taskIdFromError(error) {
|
|
|
18805
19518
|
return;
|
|
18806
19519
|
}
|
|
18807
19520
|
// ../aft-bridge/dist/feature-config.js
|
|
18808
|
-
import { createHash as
|
|
19521
|
+
import { createHash as createHash6 } from "node:crypto";
|
|
18809
19522
|
import { createRequire } from "node:module";
|
|
18810
19523
|
var CANONICAL_TOOLS = [
|
|
18811
19524
|
"aft_callgraph",
|
|
@@ -18866,12 +19579,7 @@ var RETIRED_IDLE_CHECKOUT_HOURS = [
|
|
|
18866
19579
|
"idle.checkout_hours"
|
|
18867
19580
|
];
|
|
18868
19581
|
var DATA_LAYER_KEYS_REFUSED_FROM = [0, 65];
|
|
18869
|
-
var DATA_LAYER_RETIRED_PATHS = [
|
|
18870
|
-
"views.callgraph_copies",
|
|
18871
|
-
"views.enabled",
|
|
18872
|
-
"views.idle_checkout_hours",
|
|
18873
|
-
"worktree.ram_overlay"
|
|
18874
|
-
];
|
|
19582
|
+
var DATA_LAYER_RETIRED_PATHS = ["views.idle_checkout_hours"];
|
|
18875
19583
|
var IDLE_CHECKOUT_HOURS_DEFAULT = 168;
|
|
18876
19584
|
var IDLE_CHECKOUT_HOURS_MIN = 1;
|
|
18877
19585
|
var IDLE_CHECKOUT_HOURS_MAX = 24 * 365;
|
|
@@ -18898,7 +19606,10 @@ function readRunningRelease() {
|
|
|
18898
19606
|
return [0, 0];
|
|
18899
19607
|
}
|
|
18900
19608
|
var runningRelease;
|
|
19609
|
+
var runningReleaseOverrideForTest;
|
|
18901
19610
|
function getRunningRelease() {
|
|
19611
|
+
if (runningReleaseOverrideForTest)
|
|
19612
|
+
return runningReleaseOverrideForTest;
|
|
18902
19613
|
runningRelease ??= readRunningRelease();
|
|
18903
19614
|
return runningRelease;
|
|
18904
19615
|
}
|
|
@@ -18927,7 +19638,7 @@ function removedBlockKeyErrors(value, release, refuseRetired) {
|
|
|
18927
19638
|
const paths = REMOVED_OPENCODE_PATHS.filter((path) => hasPath(value, path));
|
|
18928
19639
|
if (refuseRetired)
|
|
18929
19640
|
paths.push(...refusedRetiredNames(value));
|
|
18930
|
-
if (releaseAtLeast(release, DATA_LAYER_KEYS_REFUSED_FROM))
|
|
19641
|
+
if (refuseRetired && releaseAtLeast(release, DATA_LAYER_KEYS_REFUSED_FROM))
|
|
18931
19642
|
paths.push(...DATA_LAYER_RETIRED_PATHS.filter((path) => hasPath(value, path)));
|
|
18932
19643
|
return paths.map((path) => `removed_config_key:${path}; run npx @cortexkit/aft doctor --fix`);
|
|
18933
19644
|
}
|
|
@@ -18951,7 +19662,10 @@ var REFUSED_RETIRED_PATHS = [
|
|
|
18951
19662
|
"experimental.bash",
|
|
18952
19663
|
"idle.lsp_ttl_minutes",
|
|
18953
19664
|
"inspect.tier2_soft_deadline_ms",
|
|
18954
|
-
"inspect.max_drill_down_items"
|
|
19665
|
+
"inspect.max_drill_down_items",
|
|
19666
|
+
"views.callgraph_copies",
|
|
19667
|
+
"views.enabled",
|
|
19668
|
+
"worktree.ram_overlay"
|
|
18955
19669
|
];
|
|
18956
19670
|
function refusedRetiredNames(block) {
|
|
18957
19671
|
const names = REFUSED_RETIRED_PATHS.filter((path) => hasPath(block, path));
|
|
@@ -19143,8 +19857,9 @@ function translateDataLayerPaths(map, prefix, out) {
|
|
|
19143
19857
|
}
|
|
19144
19858
|
}
|
|
19145
19859
|
for (const path of REMOVED_DATA_LAYER_PATHS) {
|
|
19146
|
-
|
|
19147
|
-
|
|
19860
|
+
const [container, leaf] = path.split(".");
|
|
19861
|
+
if (container && leaf && takeNested(map, container, leaf).found)
|
|
19862
|
+
recordRetired(out, prefix, path);
|
|
19148
19863
|
}
|
|
19149
19864
|
}
|
|
19150
19865
|
function translateExperimentalPaths(map, prefix, out) {
|
|
@@ -19394,7 +20109,7 @@ var NO_EFFECT_RETIRED_NOTES = [
|
|
|
19394
20109
|
]
|
|
19395
20110
|
];
|
|
19396
20111
|
function noEffectNote(key) {
|
|
19397
|
-
return NO_EFFECT_RETIRED_NOTES.find(([path]) => namesPath(key, path))?.[1];
|
|
20112
|
+
return [...NO_EFFECT_RETIRED_NOTES, ...REMOVED_DATA_LAYER_NOTES].find(([path]) => namesPath(key, path))?.[1];
|
|
19398
20113
|
}
|
|
19399
20114
|
function namesPath(key, path) {
|
|
19400
20115
|
return key === path || key.endsWith(`.${path}`);
|
|
@@ -19415,26 +20130,7 @@ var REMOVED_DATA_LAYER_NOTES = [
|
|
|
19415
20130
|
];
|
|
19416
20131
|
function retiredIdleCheckoutHoursNote() {
|
|
19417
20132
|
const [retired, replacement] = RETIRED_IDLE_CHECKOUT_HOURS;
|
|
19418
|
-
return `${retired} is now ${replacement}; from ${refusedFromVersion()} AFT refuses a config file that still sets ${retired}.`;
|
|
19419
|
-
}
|
|
19420
|
-
function removedConfigKeysNoticeMessage(configPath, translation) {
|
|
19421
|
-
const removed = translation.removedKeys ?? [];
|
|
19422
|
-
if (removed.length === 0)
|
|
19423
|
-
return "";
|
|
19424
|
-
const parts = [
|
|
19425
|
-
`${configPath} sets removed keys (${removed.join(", ")}); AFT ignores them, and from ${refusedFromVersion()} it refuses a config file that sets them. Run \`npx @cortexkit/aft doctor --fix\` to remove them.`
|
|
19426
|
-
];
|
|
19427
|
-
for (const [path, note] of REMOVED_DATA_LAYER_NOTES) {
|
|
19428
|
-
if (removed.some((key) => namesPath(key, path)))
|
|
19429
|
-
parts.push(note);
|
|
19430
|
-
}
|
|
19431
|
-
return parts.join(" ");
|
|
19432
|
-
}
|
|
19433
|
-
function removedConfigKeysNoticeDigest(translation) {
|
|
19434
|
-
return noticeDigest({
|
|
19435
|
-
notice: "removed_data_layer_keys_v1",
|
|
19436
|
-
keys: sortedUnique(translation.removedKeys)
|
|
19437
|
-
});
|
|
20133
|
+
return `${retired} is now ${replacement}; from ${refusedFromVersion()} AFT refuses a user config file that still sets ${retired}.`;
|
|
19438
20134
|
}
|
|
19439
20135
|
function legacyConfigNoticeMessage(configPath, translation) {
|
|
19440
20136
|
const equivalents = translation.retiredKeys.filter((key) => noEffectNote(key) === undefined);
|
|
@@ -19448,13 +20144,10 @@ function legacyConfigNoticeMessage(configPath, translation) {
|
|
|
19448
20144
|
parts.push(retiredIdleCheckoutHoursNote());
|
|
19449
20145
|
}
|
|
19450
20146
|
}
|
|
19451
|
-
for (const [, note] of NO_EFFECT_RETIRED_NOTES) {
|
|
20147
|
+
for (const [, note] of [...NO_EFFECT_RETIRED_NOTES, ...REMOVED_DATA_LAYER_NOTES]) {
|
|
19452
20148
|
if (noEffect.has(note))
|
|
19453
20149
|
parts.push(note);
|
|
19454
20150
|
}
|
|
19455
|
-
const removed = removedConfigKeysNoticeMessage(configPath, translation);
|
|
19456
|
-
if (removed)
|
|
19457
|
-
parts.push(removed);
|
|
19458
20151
|
return parts.join(" ");
|
|
19459
20152
|
}
|
|
19460
20153
|
function translateConfigDocument(map, tier) {
|
|
@@ -19462,7 +20155,6 @@ function translateConfigDocument(map, tier) {
|
|
|
19462
20155
|
warnings: [],
|
|
19463
20156
|
legacyInput: false,
|
|
19464
20157
|
retiredKeys: [],
|
|
19465
|
-
removedKeys: [],
|
|
19466
20158
|
retiredEnabledFalse: false
|
|
19467
20159
|
};
|
|
19468
20160
|
translateBlock(map, tier === "user", "base", out);
|
|
@@ -19473,7 +20165,6 @@ function translateConfigDocument(map, tier) {
|
|
|
19473
20165
|
}
|
|
19474
20166
|
}
|
|
19475
20167
|
out.retiredKeys = sortedUnique(out.retiredKeys);
|
|
19476
|
-
out.removedKeys = sortedUnique(out.removedKeys);
|
|
19477
20168
|
return out;
|
|
19478
20169
|
}
|
|
19479
20170
|
function unknownDisabledTools(disabled) {
|
|
@@ -19512,7 +20203,8 @@ function projectBlock(block) {
|
|
|
19512
20203
|
for (const path of [
|
|
19513
20204
|
...RETIRED_PATHS.map(([retired]) => retired),
|
|
19514
20205
|
...REMOVED_NO_EFFECT_PATHS,
|
|
19515
|
-
...DATA_LAYER_RETIRED_PATHS
|
|
20206
|
+
...DATA_LAYER_RETIRED_PATHS,
|
|
20207
|
+
...REMOVED_DATA_LAYER_PATHS
|
|
19516
20208
|
]) {
|
|
19517
20209
|
const dot = path.indexOf(".");
|
|
19518
20210
|
if (dot < 0) {
|
|
@@ -19592,7 +20284,7 @@ function canonicalJson(value) {
|
|
|
19592
20284
|
return JSON.stringify(value);
|
|
19593
20285
|
}
|
|
19594
20286
|
function noticeDigest(projection) {
|
|
19595
|
-
return
|
|
20287
|
+
return createHash6("sha256").update(canonicalJson(projection), "utf8").digest("hex");
|
|
19596
20288
|
}
|
|
19597
20289
|
var SEMANTIC_COST_NOTICE = "AFT indexes now default on; the local semantic backend may download an ONNX runtime and model and use CPU. Run npx @cortexkit/aft setup to change indexes.semantic.";
|
|
19598
20290
|
var SEMANTIC_COST_NOTICE_DIGEST = noticeDigest({ notice: "semantic_default_cost_v1" });
|
|
@@ -20630,9 +21322,9 @@ async function releaseBridge(pool) {
|
|
|
20630
21322
|
await pool.shutdown();
|
|
20631
21323
|
}
|
|
20632
21324
|
// ../aft-bridge/dist/lsp-github-install.js
|
|
20633
|
-
import { createHash as
|
|
21325
|
+
import { createHash as createHash7, randomBytes as randomBytes2 } from "node:crypto";
|
|
20634
21326
|
import { closeSync as closeSync6, copyFileSync as copyFileSync3, createReadStream as createReadStream2, createWriteStream as createWriteStream2, existsSync as existsSync6, lstatSync as lstatSync2, mkdirSync as mkdirSync4, openSync as openSync5, readdirSync as readdirSync2, readFileSync as readFileSync5, readlinkSync, readSync as readSync5, realpathSync as realpathSync4, renameSync as renameSync3, rmSync as rmSync2, statSync as statSync6, unlinkSync as unlinkSync3, writeFileSync as writeFileSync2 } from "node:fs";
|
|
20635
|
-
import { dirname as dirname4, join as
|
|
21327
|
+
import { dirname as dirname4, join as join10, relative as relative3, resolve as resolve7 } from "node:path";
|
|
20636
21328
|
import { Readable as Readable2 } from "node:stream";
|
|
20637
21329
|
import { pipeline as pipeline2 } from "node:stream/promises";
|
|
20638
21330
|
|
|
@@ -20851,13 +21543,13 @@ function detectHostPlatform() {
|
|
|
20851
21543
|
|
|
20852
21544
|
// ../aft-bridge/dist/tar-executable.js
|
|
20853
21545
|
import { existsSync as existsSync5 } from "node:fs";
|
|
20854
|
-
import { join as
|
|
21546
|
+
import { join as join9 } from "node:path";
|
|
20855
21547
|
function windowsTarExecutable(options = {}) {
|
|
20856
21548
|
const platform = options.platform ?? process.platform;
|
|
20857
21549
|
if (platform !== "win32")
|
|
20858
21550
|
return "tar";
|
|
20859
21551
|
const env = options.env ?? process.env;
|
|
20860
|
-
const systemTar =
|
|
21552
|
+
const systemTar = join9(env.SystemRoot ?? "C:\\Windows", "System32", "tar.exe");
|
|
20861
21553
|
return (options.exists ?? existsSync5)(systemTar) ? systemTar : "tar";
|
|
20862
21554
|
}
|
|
20863
21555
|
function extractionCommand(args, privateStorage) {
|
|
@@ -20901,14 +21593,14 @@ function createGithubInstaller(services) {
|
|
|
20901
21593
|
return getAftLspBinariesDir();
|
|
20902
21594
|
}
|
|
20903
21595
|
function ghPackageDir(spec) {
|
|
20904
|
-
return
|
|
21596
|
+
return join10(ghCacheRoot(), spec.id);
|
|
20905
21597
|
}
|
|
20906
21598
|
function ghBinDir(spec) {
|
|
20907
21599
|
const platform = detectHostPlatform()?.platform ?? "linux";
|
|
20908
21600
|
return dirname4(ghBinaryPath(spec, platform));
|
|
20909
21601
|
}
|
|
20910
21602
|
function ghExtractDir(spec) {
|
|
20911
|
-
return
|
|
21603
|
+
return join10(ghPackageDir(spec), "extracted");
|
|
20912
21604
|
}
|
|
20913
21605
|
const INSTALLED_META_FILE = ".aft-installed";
|
|
20914
21606
|
const INSTALL_FAILED_FILE = ".aft-install-failed.json";
|
|
@@ -20916,8 +21608,9 @@ function createGithubInstaller(services) {
|
|
|
20916
21608
|
const INSTALL_LOCK_WAIT_MS = 10 * 60 * 1000;
|
|
20917
21609
|
const INSTALL_LOCK_POLL_INTERVAL_MS = 1000;
|
|
20918
21610
|
const INSTALL_LOCK_WAIT_TIMEOUT_REASON = "install lock held by another process for 10 minutes";
|
|
21611
|
+
const SMOKE_TIMEOUT_MS = 2000;
|
|
20919
21612
|
function installFailureMarkerPath(spec) {
|
|
20920
|
-
return
|
|
21613
|
+
return join10(ghPackageDir(spec), INSTALL_FAILED_FILE);
|
|
20921
21614
|
}
|
|
20922
21615
|
function readInstallFailureMarker(spec) {
|
|
20923
21616
|
try {
|
|
@@ -20961,15 +21654,15 @@ function createGithubInstaller(services) {
|
|
|
20961
21654
|
const meta = readGithubInstalledMetaIn(ghPackageDir(spec));
|
|
20962
21655
|
if (spec.layout === "distribution" && meta?.layout === "distribution" && isSafeVersion(meta.version)) {
|
|
20963
21656
|
const arch = detectHostPlatform()?.arch ?? "x64";
|
|
20964
|
-
return
|
|
21657
|
+
return join10(ghExtractDir(spec), spec.binaryPathInArchive(platform, arch, stripTagV(meta.version)));
|
|
20965
21658
|
}
|
|
20966
21659
|
const ext = platform === "win32" ? ".exe" : "";
|
|
20967
|
-
return
|
|
21660
|
+
return join10(ghPackageDir(spec), "bin", `${spec.binary}${ext}`);
|
|
20968
21661
|
}
|
|
20969
21662
|
function isGithubInstalled(spec, platform) {
|
|
20970
21663
|
for (const candidate of ghBinaryCandidates(spec, platform)) {
|
|
20971
21664
|
try {
|
|
20972
|
-
if (statSync6(
|
|
21665
|
+
if (statSync6(join10(ghBinDir(spec), candidate)).isFile())
|
|
20973
21666
|
return true;
|
|
20974
21667
|
} catch {}
|
|
20975
21668
|
}
|
|
@@ -20982,7 +21675,7 @@ function createGithubInstaller(services) {
|
|
|
20982
21675
|
}
|
|
20983
21676
|
function readGithubInstalledMetaIn(installDir) {
|
|
20984
21677
|
try {
|
|
20985
|
-
const path =
|
|
21678
|
+
const path = join10(installDir, INSTALLED_META_FILE);
|
|
20986
21679
|
if (!statSync6(path).isFile())
|
|
20987
21680
|
return null;
|
|
20988
21681
|
const parsed = JSON.parse(readFileSync5(path, "utf8"));
|
|
@@ -21013,7 +21706,7 @@ function createGithubInstaller(services) {
|
|
|
21013
21706
|
...layout ? { layout } : {},
|
|
21014
21707
|
...smoke ? { smoke } : {}
|
|
21015
21708
|
};
|
|
21016
|
-
const path =
|
|
21709
|
+
const path = join10(installDir, INSTALLED_META_FILE);
|
|
21017
21710
|
const tempPath = `${path}.tmp-${process.pid}-${randomBytes2(6).toString("hex")}`;
|
|
21018
21711
|
try {
|
|
21019
21712
|
writeFileSync2(tempPath, JSON.stringify(meta), { encoding: "utf8", flag: "wx" });
|
|
@@ -21029,7 +21722,7 @@ function createGithubInstaller(services) {
|
|
|
21029
21722
|
const MAX_EXTRACT_BYTES = 1024 * 1024 * 1024;
|
|
21030
21723
|
function sha256OfFile(path) {
|
|
21031
21724
|
return new Promise((resolve, reject) => {
|
|
21032
|
-
const hash =
|
|
21725
|
+
const hash = createHash7("sha256");
|
|
21033
21726
|
const stream = createReadStream2(path);
|
|
21034
21727
|
stream.on("error", reject);
|
|
21035
21728
|
stream.on("data", (chunk) => hash.update(chunk));
|
|
@@ -21037,7 +21730,7 @@ function createGithubInstaller(services) {
|
|
|
21037
21730
|
});
|
|
21038
21731
|
}
|
|
21039
21732
|
function sha256OfFileSync(path) {
|
|
21040
|
-
const hash =
|
|
21733
|
+
const hash = createHash7("sha256");
|
|
21041
21734
|
const fd = openSync5(path, "r");
|
|
21042
21735
|
try {
|
|
21043
21736
|
const buffer = Buffer.allocUnsafe(1024 * 1024);
|
|
@@ -21265,7 +21958,7 @@ function createGithubInstaller(services) {
|
|
|
21265
21958
|
throw new Error(`failed to read staging dir ${dir}: ${err}`);
|
|
21266
21959
|
}
|
|
21267
21960
|
for (const entry of entries) {
|
|
21268
|
-
const full =
|
|
21961
|
+
const full = join10(dir, entry);
|
|
21269
21962
|
let lst;
|
|
21270
21963
|
try {
|
|
21271
21964
|
lst = lstatSync2(full);
|
|
@@ -21277,7 +21970,7 @@ function createGithubInstaller(services) {
|
|
|
21277
21970
|
try {
|
|
21278
21971
|
target = readlinkSync(full);
|
|
21279
21972
|
} catch {}
|
|
21280
|
-
throw new Error(`archive contains symlink ${
|
|
21973
|
+
throw new Error(`archive contains symlink ${relative3(realStagingRoot, full)} → ${target}; rejecting (zip-slip defense)`);
|
|
21281
21974
|
}
|
|
21282
21975
|
let realFull;
|
|
21283
21976
|
try {
|
|
@@ -21285,8 +21978,8 @@ function createGithubInstaller(services) {
|
|
|
21285
21978
|
} catch (err) {
|
|
21286
21979
|
throw new Error(`failed to realpath ${full}: ${err}`);
|
|
21287
21980
|
}
|
|
21288
|
-
const rel =
|
|
21289
|
-
if (relativePathEscapesRoot(rel) ||
|
|
21981
|
+
const rel = relative3(realStagingRoot, realFull);
|
|
21982
|
+
if (relativePathEscapesRoot(rel) || resolve7(realStagingRoot, rel) !== realFull) {
|
|
21290
21983
|
throw new Error(`archive entry escapes staging root: ${full} → ${realFull} (zip-slip defense)`);
|
|
21291
21984
|
}
|
|
21292
21985
|
if (lst.isDirectory()) {
|
|
@@ -21426,7 +22119,7 @@ function createGithubInstaller(services) {
|
|
|
21426
22119
|
}
|
|
21427
22120
|
function quarantineCachedGithubInstall(spec, reason) {
|
|
21428
22121
|
const packageDir = ghPackageDir(spec);
|
|
21429
|
-
const dest =
|
|
22122
|
+
const dest = join10(ghCacheRoot(), ".quarantine", encodeURIComponent(spec.id), `${Date.now()}`);
|
|
21430
22123
|
warn(`[lsp] tofu_mismatch ${spec.id}: ${reason}; quarantining ${packageDir} -> ${dest}`);
|
|
21431
22124
|
try {
|
|
21432
22125
|
mkdirSync4(dirname4(dest), { recursive: true });
|
|
@@ -21436,7 +22129,7 @@ function createGithubInstaller(services) {
|
|
|
21436
22129
|
warn(`[lsp] tofu_mismatch ${spec.id}: failed to quarantine cache entry: ${err}`);
|
|
21437
22130
|
}
|
|
21438
22131
|
}
|
|
21439
|
-
async function smokeGithubBinary(spec, binaryPath) {
|
|
22132
|
+
async function smokeGithubBinary(spec, binaryPath, timeoutMs = SMOKE_TIMEOUT_MS) {
|
|
21440
22133
|
return new Promise((resolveSmoke) => {
|
|
21441
22134
|
let child;
|
|
21442
22135
|
let settled = false;
|
|
@@ -21456,8 +22149,8 @@ function createGithubInstaller(services) {
|
|
|
21456
22149
|
const timer = setTimeout(() => {
|
|
21457
22150
|
child?.kill("SIGKILL");
|
|
21458
22151
|
child?.unref();
|
|
21459
|
-
finish("timeout",
|
|
21460
|
-
},
|
|
22152
|
+
finish("timeout", `exceeded ${timeoutMs} ms; keeping install`);
|
|
22153
|
+
}, timeoutMs);
|
|
21461
22154
|
const capture = (chunk) => {
|
|
21462
22155
|
const bytes = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
21463
22156
|
const available = 64 * 1024 - output.length;
|
|
@@ -21481,19 +22174,19 @@ function createGithubInstaller(services) {
|
|
|
21481
22174
|
function hasRequiredRuntime(spec, extractDir, version) {
|
|
21482
22175
|
return (spec.requiredRuntimePaths?.(stripTagV(version)) ?? []).every(({ path, kind }) => {
|
|
21483
22176
|
try {
|
|
21484
|
-
const info = statSync6(
|
|
22177
|
+
const info = statSync6(join10(extractDir, path));
|
|
21485
22178
|
return kind === "file" ? info.isFile() : info.isDirectory();
|
|
21486
22179
|
} catch {
|
|
21487
22180
|
return false;
|
|
21488
22181
|
}
|
|
21489
22182
|
});
|
|
21490
22183
|
}
|
|
21491
|
-
function validateCachedGithubInstall(spec, platform) {
|
|
22184
|
+
function validateCachedGithubInstall(spec, platform, smokeTimeoutMs = SMOKE_TIMEOUT_MS) {
|
|
21492
22185
|
const lease = acquireInstallLock(spec.githubRepo);
|
|
21493
22186
|
if (!lease)
|
|
21494
22187
|
return null;
|
|
21495
22188
|
try {
|
|
21496
|
-
const validation = validateCachedGithubInstallUnderLock(spec, platform);
|
|
22189
|
+
const validation = validateCachedGithubInstallUnderLock(spec, platform, smokeTimeoutMs);
|
|
21497
22190
|
if (typeof validation !== "boolean")
|
|
21498
22191
|
return validation.finally(() => lease.release());
|
|
21499
22192
|
lease.release();
|
|
@@ -21503,10 +22196,10 @@ function createGithubInstaller(services) {
|
|
|
21503
22196
|
throw err;
|
|
21504
22197
|
}
|
|
21505
22198
|
}
|
|
21506
|
-
function validateCachedGithubInstallUnderLock(spec, platform) {
|
|
22199
|
+
function validateCachedGithubInstallUnderLock(spec, platform, smokeTimeoutMs = SMOKE_TIMEOUT_MS) {
|
|
21507
22200
|
const packageDir = ghPackageDir(spec);
|
|
21508
22201
|
const meta = readGithubInstalledMetaIn(packageDir);
|
|
21509
|
-
const binaryPath = ghBinaryCandidates(spec, platform).map((candidate) =>
|
|
22202
|
+
const binaryPath = ghBinaryCandidates(spec, platform).map((candidate) => join10(ghBinDir(spec), candidate)).find((candidate) => {
|
|
21510
22203
|
try {
|
|
21511
22204
|
return statSync6(candidate).isFile();
|
|
21512
22205
|
} catch {
|
|
@@ -21536,7 +22229,7 @@ function createGithubInstaller(services) {
|
|
|
21536
22229
|
quarantineCachedGithubInstall(spec, "missing required runtime files");
|
|
21537
22230
|
return false;
|
|
21538
22231
|
}
|
|
21539
|
-
const verdict = await smokeGithubBinary(spec, binaryPath);
|
|
22232
|
+
const verdict = await smokeGithubBinary(spec, binaryPath, smokeTimeoutMs);
|
|
21540
22233
|
if (verdict === "failed") {
|
|
21541
22234
|
quarantineCachedGithubInstall(spec, "cached binary failed runtime smoke check");
|
|
21542
22235
|
return false;
|
|
@@ -21582,7 +22275,7 @@ function createGithubInstaller(services) {
|
|
|
21582
22275
|
}
|
|
21583
22276
|
const pkgDir = ghPackageDir(spec);
|
|
21584
22277
|
const extractDir = ghExtractDir(spec);
|
|
21585
|
-
const archivePath =
|
|
22278
|
+
const archivePath = join10(pkgDir, expected.name);
|
|
21586
22279
|
log(`[lsp] downloading ${spec.id} ${tag} → ${matchingAsset.url}`);
|
|
21587
22280
|
try {
|
|
21588
22281
|
await downloadFile(matchingAsset.url, archivePath, fetchImpl, matchingAsset.size, signal);
|
|
@@ -21618,7 +22311,7 @@ function createGithubInstaller(services) {
|
|
|
21618
22311
|
const binaryRelativePath = spec.binaryPathInArchive(platform, arch, version);
|
|
21619
22312
|
try {
|
|
21620
22313
|
await extractArchiveSafely(archivePath, extractDir, expected.archive, async (stagingDir) => {
|
|
21621
|
-
const stagedBinary =
|
|
22314
|
+
const stagedBinary = join10(stagingDir, binaryRelativePath);
|
|
21622
22315
|
if (!existsSync6(stagedBinary) || !statSync6(stagedBinary).isFile()) {
|
|
21623
22316
|
throw new Error(`extracted binary not found at ${stagedBinary}`);
|
|
21624
22317
|
}
|
|
@@ -21648,7 +22341,7 @@ function createGithubInstaller(services) {
|
|
|
21648
22341
|
unlinkSync3(archivePath);
|
|
21649
22342
|
} catch {}
|
|
21650
22343
|
}
|
|
21651
|
-
const innerBinaryPath =
|
|
22344
|
+
const innerBinaryPath = join10(extractDir, binaryRelativePath);
|
|
21652
22345
|
const targetBinary = spec.layout === "distribution" ? innerBinaryPath : ghBinaryPath(spec, platform);
|
|
21653
22346
|
mkdirSync4(dirname4(targetBinary), { recursive: true });
|
|
21654
22347
|
try {
|
|
@@ -21775,6 +22468,7 @@ function createGithubInstaller(services) {
|
|
|
21775
22468
|
let installsStarted = 0;
|
|
21776
22469
|
const lockWaitTimeoutMs = Math.max(0, options.__lockWaitTimeoutMsForTests ?? INSTALL_LOCK_WAIT_MS);
|
|
21777
22470
|
const lockPollIntervalMs = Math.max(1, options.__lockPollIntervalMsForTests ?? INSTALL_LOCK_POLL_INTERVAL_MS);
|
|
22471
|
+
const smokeTimeoutMs = Math.max(1, options.__smokeTimeoutMsForTests ?? SMOKE_TIMEOUT_MS);
|
|
21778
22472
|
function notifyCachedBinDirsChanged(directory) {
|
|
21779
22473
|
try {
|
|
21780
22474
|
options.onCachedBinDirsChanged?.(directory);
|
|
@@ -21787,7 +22481,7 @@ function createGithubInstaller(services) {
|
|
|
21787
22481
|
while (true) {
|
|
21788
22482
|
if (signal.aborted)
|
|
21789
22483
|
return null;
|
|
21790
|
-
const validation = await withInstallLock(spec.githubRepo, async () => validateCachedGithubInstallUnderLock(spec, platform));
|
|
22484
|
+
const validation = await withInstallLock(spec.githubRepo, async () => validateCachedGithubInstallUnderLock(spec, platform, smokeTimeoutMs));
|
|
21791
22485
|
if (validation !== null)
|
|
21792
22486
|
return validation;
|
|
21793
22487
|
if (signal.aborted)
|
|
@@ -21816,7 +22510,7 @@ function createGithubInstaller(services) {
|
|
|
21816
22510
|
}
|
|
21817
22511
|
for (const spec of GITHUB_LSP_TABLE) {
|
|
21818
22512
|
const controller = new AbortController;
|
|
21819
|
-
const validation = isGithubInstalled(spec, host.platform) ? validateCachedGithubInstall(spec, host.platform) : false;
|
|
22513
|
+
const validation = isGithubInstalled(spec, host.platform) ? validateCachedGithubInstall(spec, host.platform, smokeTimeoutMs) : false;
|
|
21820
22514
|
if (validation === true)
|
|
21821
22515
|
cachedBinDirs.push(ghBinDir(spec));
|
|
21822
22516
|
const cacheReady = (validation === null ? retryBusyCacheValidation(spec, host.platform, controller.signal) : Promise.resolve(validation)).then((healthy) => {
|
|
@@ -21871,7 +22565,7 @@ function createGithubInstaller(services) {
|
|
|
21871
22565
|
const currentHost = detectHostPlatform();
|
|
21872
22566
|
if (!currentHost)
|
|
21873
22567
|
return [];
|
|
21874
|
-
const directories = await Promise.all(GITHUB_LSP_TABLE.map(async (spec) => isGithubInstalled(spec, currentHost.platform) && await validateCachedGithubInstall(spec, currentHost.platform) ? ghBinDir(spec) : null));
|
|
22568
|
+
const directories = await Promise.all(GITHUB_LSP_TABLE.map(async (spec) => isGithubInstalled(spec, currentHost.platform) && await validateCachedGithubInstall(spec, currentHost.platform, smokeTimeoutMs) ? ghBinDir(spec) : null));
|
|
21875
22569
|
return directories.filter((directory) => directory !== null);
|
|
21876
22570
|
}
|
|
21877
22571
|
};
|
|
@@ -21942,7 +22636,7 @@ import { stat as stat2 } from "node:fs/promises";
|
|
|
21942
22636
|
// ../aft-bridge/dist/npm-resolver.js
|
|
21943
22637
|
import { readdirSync as readdirSync3, statSync as statSync7 } from "node:fs";
|
|
21944
22638
|
import { homedir as homedir7 } from "node:os";
|
|
21945
|
-
import { dirname as dirname5, isAbsolute as
|
|
22639
|
+
import { dirname as dirname5, isAbsolute as isAbsolute4, join as join11 } from "node:path";
|
|
21946
22640
|
function defaultDeps() {
|
|
21947
22641
|
return {
|
|
21948
22642
|
platform: process.platform,
|
|
@@ -21969,16 +22663,16 @@ function npmFromPath(deps) {
|
|
|
21969
22663
|
const separator = deps.platform === "win32" ? ";" : ":";
|
|
21970
22664
|
for (const entry of raw.split(separator)) {
|
|
21971
22665
|
const dir = entry.trim().replace(/^"|"$/g, "");
|
|
21972
|
-
if (!dir || !
|
|
22666
|
+
if (!dir || !isAbsolute4(dir))
|
|
21973
22667
|
continue;
|
|
21974
|
-
if (isFile(
|
|
22668
|
+
if (isFile(join11(dir, name)))
|
|
21975
22669
|
return dir;
|
|
21976
22670
|
}
|
|
21977
22671
|
return null;
|
|
21978
22672
|
}
|
|
21979
22673
|
function npmAdjacentToNode(deps) {
|
|
21980
22674
|
const dir = dirname5(deps.execPath);
|
|
21981
|
-
return isFile(
|
|
22675
|
+
return isFile(join11(dir, npmBinaryName(deps.platform))) ? dir : null;
|
|
21982
22676
|
}
|
|
21983
22677
|
function highestVersionedNodeBin(installsDir, name) {
|
|
21984
22678
|
let entries;
|
|
@@ -21987,8 +22681,8 @@ function highestVersionedNodeBin(installsDir, name) {
|
|
|
21987
22681
|
} catch {
|
|
21988
22682
|
return null;
|
|
21989
22683
|
}
|
|
21990
|
-
const candidates = entries.filter((v) => isFile(
|
|
21991
|
-
return candidates.length > 0 ?
|
|
22684
|
+
const candidates = entries.filter((v) => isFile(join11(installsDir, v, "bin", name))).sort((a, b) => compareVersionsDesc(a, b));
|
|
22685
|
+
return candidates.length > 0 ? join11(installsDir, candidates[0], "bin") : null;
|
|
21992
22686
|
}
|
|
21993
22687
|
function compareVersionsDesc(a, b) {
|
|
21994
22688
|
const pa = a.replace(/^v/, "").split(".").map((n) => Number.parseInt(n, 10));
|
|
@@ -22013,22 +22707,22 @@ function wellKnownNpmDirs(deps) {
|
|
|
22013
22707
|
const programFiles = env.ProgramFiles || "C:\\Program Files";
|
|
22014
22708
|
const appData = env.APPDATA;
|
|
22015
22709
|
const localAppData = env.LOCALAPPDATA;
|
|
22016
|
-
push(
|
|
22710
|
+
push(join11(programFiles, "nodejs"));
|
|
22017
22711
|
if (appData)
|
|
22018
|
-
push(
|
|
22712
|
+
push(join11(appData, "npm"));
|
|
22019
22713
|
if (localAppData)
|
|
22020
|
-
push(
|
|
22714
|
+
push(join11(localAppData, "Volta", "bin"));
|
|
22021
22715
|
if (env.NVM_SYMLINK)
|
|
22022
22716
|
push(env.NVM_SYMLINK);
|
|
22023
22717
|
} else {
|
|
22024
22718
|
if (env.NVM_BIN)
|
|
22025
22719
|
push(env.NVM_BIN);
|
|
22026
|
-
push(highestVersionedNodeBin(
|
|
22027
|
-
push(highestVersionedNodeBin(
|
|
22028
|
-
push(highestVersionedNodeBin(
|
|
22029
|
-
push(
|
|
22030
|
-
push(
|
|
22031
|
-
const systemDirs = deps.systemNpmDirs ?? (platform === "darwin" ? ["/opt/homebrew/bin", "/usr/local/bin"] : ["/usr/local/bin", "/usr/bin",
|
|
22720
|
+
push(highestVersionedNodeBin(join11(home, ".nvm", "versions", "node"), name));
|
|
22721
|
+
push(highestVersionedNodeBin(join11(home, ".local", "share", "mise", "installs", "node"), name));
|
|
22722
|
+
push(highestVersionedNodeBin(join11(home, ".asdf", "installs", "nodejs"), name));
|
|
22723
|
+
push(join11(home, ".volta", "bin"));
|
|
22724
|
+
push(join11(home, ".asdf", "shims"));
|
|
22725
|
+
const systemDirs = deps.systemNpmDirs ?? (platform === "darwin" ? ["/opt/homebrew/bin", "/usr/local/bin"] : ["/usr/local/bin", "/usr/bin", join11(home, ".local", "bin")]);
|
|
22032
22726
|
for (const dir of systemDirs)
|
|
22033
22727
|
push(dir);
|
|
22034
22728
|
}
|
|
@@ -22038,12 +22732,12 @@ function resolveNpm(deps = defaultDeps()) {
|
|
|
22038
22732
|
const name = npmBinaryName(deps.platform);
|
|
22039
22733
|
const onPath = npmFromPath(deps);
|
|
22040
22734
|
if (onPath)
|
|
22041
|
-
return { command:
|
|
22735
|
+
return { command: join11(onPath, name), binDir: onPath };
|
|
22042
22736
|
const adjacent = npmAdjacentToNode(deps);
|
|
22043
22737
|
if (adjacent)
|
|
22044
|
-
return { command:
|
|
22738
|
+
return { command: join11(adjacent, name), binDir: adjacent };
|
|
22045
22739
|
for (const dir of wellKnownNpmDirs(deps)) {
|
|
22046
|
-
const candidate =
|
|
22740
|
+
const candidate = join11(dir, name);
|
|
22047
22741
|
if (isFile(candidate))
|
|
22048
22742
|
return { command: candidate, binDir: dir };
|
|
22049
22743
|
}
|
|
@@ -22052,15 +22746,15 @@ function resolveNpm(deps = defaultDeps()) {
|
|
|
22052
22746
|
function npmCandidates(deps = defaultDeps()) {
|
|
22053
22747
|
const name = npmBinaryName(deps.platform);
|
|
22054
22748
|
const dirs = [
|
|
22055
|
-
...(deps.env.PATH ?? "").split(deps.platform === "win32" ? ";" : ":").filter(
|
|
22749
|
+
...(deps.env.PATH ?? "").split(deps.platform === "win32" ? ";" : ":").filter(isAbsolute4),
|
|
22056
22750
|
dirname5(deps.execPath),
|
|
22057
22751
|
...wellKnownNpmDirs(deps)
|
|
22058
22752
|
];
|
|
22059
22753
|
return [...new Set(dirs)].flatMap((binDir) => {
|
|
22060
22754
|
return [
|
|
22061
|
-
|
|
22062
|
-
|
|
22063
|
-
|
|
22755
|
+
join11(binDir, name),
|
|
22756
|
+
join11(binDir, "node_modules", "npm", "bin", "npm-cli.js"),
|
|
22757
|
+
join11(binDir, "..", "lib", "node_modules", "npm", "bin", "npm-cli.js")
|
|
22064
22758
|
].filter(isFile).map((command) => ({ command, binDir }));
|
|
22065
22759
|
});
|
|
22066
22760
|
}
|
|
@@ -22229,7 +22923,7 @@ function terminateNpmProcessTree(child, invocation, env = process.env, gracePeri
|
|
|
22229
22923
|
};
|
|
22230
22924
|
child.once("exit", onChildExit);
|
|
22231
22925
|
const systemRoot = env.SystemRoot ?? env.SYSTEMROOT;
|
|
22232
|
-
const taskkill = systemRoot ?
|
|
22926
|
+
const taskkill = systemRoot ? join11(systemRoot, "System32", "taskkill.exe") : "taskkill.exe";
|
|
22233
22927
|
try {
|
|
22234
22928
|
killer = spawn(taskkill, ["/pid", String(child.pid), "/t", "/f"], {
|
|
22235
22929
|
stdio: "ignore",
|
|
@@ -22363,7 +23057,7 @@ async function lspNpmInstallInvocation(npm, target, before, clock = SYSTEM_CLOCK
|
|
|
22363
23057
|
}
|
|
22364
23058
|
// ../aft-bridge/dist/lsp-npm-selection.js
|
|
22365
23059
|
import { readFile, realpath, stat as stat3 } from "node:fs/promises";
|
|
22366
|
-
import { dirname as dirname6, join as
|
|
23060
|
+
import { dirname as dirname6, join as join12, resolve as resolve8 } from "node:path";
|
|
22367
23061
|
var LSP_NPM_REFUSAL = "AFT can't install language servers with the npm at <path> (<reason>). Put a real npm 7 or newer first on PATH; pinning a server version won't help.";
|
|
22368
23062
|
function lspNpmRefusal(path, reason) {
|
|
22369
23063
|
return LSP_NPM_REFUSAL.replace("<path>", path).replace("<reason>", reason);
|
|
@@ -22378,13 +23072,13 @@ async function genuineNpm(candidate) {
|
|
|
22378
23072
|
const windowsShim = /\.(?:cmd|bat)$/i.test(executable);
|
|
22379
23073
|
let current = dirname6(executable);
|
|
22380
23074
|
if (windowsShim)
|
|
22381
|
-
current =
|
|
23075
|
+
current = join12(current, "node_modules", "npm");
|
|
22382
23076
|
for (;; ) {
|
|
22383
23077
|
try {
|
|
22384
|
-
const pkg = JSON.parse(await readFile(
|
|
23078
|
+
const pkg = JSON.parse(await readFile(join12(current, "package.json"), "utf8"));
|
|
22385
23079
|
const bin = typeof pkg.bin === "string" ? pkg.bin : pkg.bin?.npm;
|
|
22386
23080
|
if (pkg.name === "npm" && typeof bin === "string") {
|
|
22387
|
-
const cli = await realpath(
|
|
23081
|
+
const cli = await realpath(resolve8(current, bin));
|
|
22388
23082
|
if (!windowsShim && cli !== executable)
|
|
22389
23083
|
return { reason: "not npm: command is not npm's declared CLI" };
|
|
22390
23084
|
const major = /^(\d+)\.\d+\.\d+$/.exec(pkg.version)?.[1];
|
|
@@ -22393,7 +23087,7 @@ async function genuineNpm(candidate) {
|
|
|
22393
23087
|
if (Number(major) < 7)
|
|
22394
23088
|
return { reason: `old npm: ${pkg.version} (requires npm 7 or newer)` };
|
|
22395
23089
|
if (windowsShim || process.platform === "win32" && /\.[cm]?js$/i.test(cli)) {
|
|
22396
|
-
const node =
|
|
23090
|
+
const node = join12(candidate.binDir ?? dirname6(executable), "node.exe");
|
|
22397
23091
|
if (!(await stat3(node)).isFile())
|
|
22398
23092
|
return { reason: "probe failed: adjacent Node is missing" };
|
|
22399
23093
|
return { npm: { command: node, binDir: dirname6(node), cliPath: cli }, reason: "" };
|
|
@@ -22485,12 +23179,12 @@ function shouldInterruptWaitsForMessage(detachOnUserMessage, operatorText) {
|
|
|
22485
23179
|
// ../aft-bridge/dist/migration.js
|
|
22486
23180
|
import { closeSync as closeSync8, existsSync as existsSync9, mkdirSync as mkdirSync5, openSync as openSync7, readFileSync as readFileSync8, renameSync as renameSync5, rmSync as rmSync3, statSync as statSync8, unlinkSync as unlinkSync4, writeFileSync as writeFileSync4 } from "node:fs";
|
|
22487
23181
|
import { homedir as homedir10, tmpdir as tmpdir3 } from "node:os";
|
|
22488
|
-
import { basename as basename2, dirname as dirname9, join as
|
|
23182
|
+
import { basename as basename2, dirname as dirname9, join as join15, resolve as resolve10 } from "node:path";
|
|
22489
23183
|
|
|
22490
23184
|
// ../aft-bridge/dist/paths.js
|
|
22491
23185
|
import { existsSync as existsSync7, readFileSync as readFileSync6, realpathSync as realpathSync5, renameSync as renameSync4, writeFileSync as writeFileSync3 } from "node:fs";
|
|
22492
23186
|
import { homedir as homedir8 } from "node:os";
|
|
22493
|
-
import { dirname as dirname7, isAbsolute as
|
|
23187
|
+
import { dirname as dirname7, isAbsolute as isAbsolute5, join as join13, resolve as resolve9 } from "node:path";
|
|
22494
23188
|
function homeDir3() {
|
|
22495
23189
|
if (process.platform === "win32")
|
|
22496
23190
|
return process.env.USERPROFILE || process.env.HOME || homedir8();
|
|
@@ -22498,18 +23192,18 @@ function homeDir3() {
|
|
|
22498
23192
|
}
|
|
22499
23193
|
function configHome() {
|
|
22500
23194
|
const xdg = process.env.XDG_CONFIG_HOME;
|
|
22501
|
-
if (xdg &&
|
|
23195
|
+
if (xdg && isAbsolute5(xdg))
|
|
22502
23196
|
return xdg;
|
|
22503
|
-
return
|
|
23197
|
+
return join13(homeDir3(), ".config");
|
|
22504
23198
|
}
|
|
22505
23199
|
function legacyOpenCodeConfigDir() {
|
|
22506
23200
|
const envDir = process.env.OPENCODE_CONFIG_DIR?.trim();
|
|
22507
23201
|
if (envDir)
|
|
22508
|
-
return
|
|
22509
|
-
return
|
|
23202
|
+
return resolve9(envDir);
|
|
23203
|
+
return join13(configHome(), "opencode");
|
|
22510
23204
|
}
|
|
22511
23205
|
function legacyPiAgentDir() {
|
|
22512
|
-
return
|
|
23206
|
+
return join13(homeDir3(), ".pi", "agent");
|
|
22513
23207
|
}
|
|
22514
23208
|
function legacySources(basePath, label, harness) {
|
|
22515
23209
|
return [
|
|
@@ -22518,10 +23212,10 @@ function legacySources(basePath, label, harness) {
|
|
|
22518
23212
|
];
|
|
22519
23213
|
}
|
|
22520
23214
|
function resolveCortexKitUserConfigPath() {
|
|
22521
|
-
return
|
|
23215
|
+
return join13(configHome(), "cortexkit", "aft.jsonc");
|
|
22522
23216
|
}
|
|
22523
23217
|
function resolveCortexKitProjectConfigPath(projectDirectory) {
|
|
22524
|
-
return
|
|
23218
|
+
return join13(projectDirectory, ".cortexkit", "aft.jsonc");
|
|
22525
23219
|
}
|
|
22526
23220
|
function resolveProjectConfigReadPath(projectDirectory, operatingHarness) {
|
|
22527
23221
|
const canonical = resolveCortexKitProjectConfigPath(projectDirectory);
|
|
@@ -22548,14 +23242,14 @@ function resolveCortexKitConfigPaths(projectDirectory) {
|
|
|
22548
23242
|
}
|
|
22549
23243
|
function resolveLegacyAftConfigSources(projectDirectory) {
|
|
22550
23244
|
const project = [
|
|
22551
|
-
...legacySources(
|
|
22552
|
-
...legacySources(
|
|
23245
|
+
...legacySources(join13(projectDirectory, ".opencode", "aft"), "OpenCode project", "opencode"),
|
|
23246
|
+
...legacySources(join13(projectDirectory, ".pi", "aft"), "Pi project", "pi")
|
|
22553
23247
|
];
|
|
22554
23248
|
const identity = (path) => {
|
|
22555
23249
|
try {
|
|
22556
23250
|
return realpathSync5(path);
|
|
22557
23251
|
} catch {
|
|
22558
|
-
return
|
|
23252
|
+
return resolve9(path);
|
|
22559
23253
|
}
|
|
22560
23254
|
};
|
|
22561
23255
|
const protectedPaths = new Set([
|
|
@@ -22564,18 +23258,18 @@ function resolveLegacyAftConfigSources(projectDirectory) {
|
|
|
22564
23258
|
].map(identity));
|
|
22565
23259
|
return {
|
|
22566
23260
|
user: [
|
|
22567
|
-
...legacySources(
|
|
22568
|
-
...legacySources(
|
|
23261
|
+
...legacySources(join13(legacyOpenCodeConfigDir(), "aft"), "OpenCode user", "opencode"),
|
|
23262
|
+
...legacySources(join13(legacyPiAgentDir(), "aft"), "Pi user", "pi")
|
|
22569
23263
|
].filter((source) => !protectedPaths.has(identity(source.path))),
|
|
22570
23264
|
project
|
|
22571
23265
|
};
|
|
22572
23266
|
}
|
|
22573
23267
|
function resolveHarnessStoragePath(storageRoot, harness, ...segments) {
|
|
22574
|
-
return
|
|
23268
|
+
return join13(storageRoot, harness, ...segments);
|
|
22575
23269
|
}
|
|
22576
23270
|
function repairRootScopedStorageFile(storageRoot, harness, fileName) {
|
|
22577
23271
|
const harnessPath = resolveHarnessStoragePath(storageRoot, harness, fileName);
|
|
22578
|
-
const rootPath =
|
|
23272
|
+
const rootPath = join13(storageRoot, fileName);
|
|
22579
23273
|
if (existsSync7(harnessPath) || !existsSync7(rootPath))
|
|
22580
23274
|
return harnessPath;
|
|
22581
23275
|
try {
|
|
@@ -22664,15 +23358,15 @@ function decodeFileUrl(target) {
|
|
|
22664
23358
|
import { closeSync as closeSync7, existsSync as existsSync8, promises as fsPromises, openSync as openSync6, readFileSync as readFileSync7, readSync as readSync6 } from "node:fs";
|
|
22665
23359
|
import { createRequire as createRequire2 } from "node:module";
|
|
22666
23360
|
import { homedir as homedir9 } from "node:os";
|
|
22667
|
-
import { delimiter, dirname as dirname8, isAbsolute as
|
|
23361
|
+
import { delimiter, dirname as dirname8, isAbsolute as isAbsolute6, join as join14 } from "node:path";
|
|
22668
23362
|
var ensureBinaryForResolver = ensureBinary;
|
|
22669
23363
|
var npmPlatformPackageReader = null;
|
|
22670
23364
|
var cacheCopiesInFlight = new Map;
|
|
22671
23365
|
function copyToVersionedCache(npmBinaryPath, version) {
|
|
22672
23366
|
const tag = version.startsWith("v") ? version : `v${version}`;
|
|
22673
23367
|
const ext = process.platform === "win32" ? ".exe" : "";
|
|
22674
|
-
const versionedDir =
|
|
22675
|
-
const cachedPath =
|
|
23368
|
+
const versionedDir = join14(getAftBinaryCacheDir(), tag);
|
|
23369
|
+
const cachedPath = join14(versionedDir, `aft${ext}`);
|
|
22676
23370
|
if (existsSync8(cachedPath) && isTrustedCachedBinary(cachedPath, version))
|
|
22677
23371
|
return { cachedPath };
|
|
22678
23372
|
const existing = cacheCopiesInFlight.get(cachedPath);
|
|
@@ -22718,7 +23412,7 @@ function homeDirFromEnv(env) {
|
|
|
22718
23412
|
return (process.platform === "win32" ? env.USERPROFILE || env.HOME : env.HOME) || homedir9();
|
|
22719
23413
|
}
|
|
22720
23414
|
function cachedBinaryPathFromEnv(version, env, ext) {
|
|
22721
|
-
const binaryPath =
|
|
23415
|
+
const binaryPath = join14(getAftBinaryCacheDir(env), version, `aft${ext}`);
|
|
22722
23416
|
return existsSync8(binaryPath) ? binaryPath : null;
|
|
22723
23417
|
}
|
|
22724
23418
|
async function probeBinaryCandidateOffThread(binaryPath, source, expectedVersion) {
|
|
@@ -22738,9 +23432,9 @@ function pathCandidates(env, ext) {
|
|
|
22738
23432
|
const seen = new Set;
|
|
22739
23433
|
const candidates = [];
|
|
22740
23434
|
for (const dir of rawPath.split(delimiter)) {
|
|
22741
|
-
if (!dir || !
|
|
23435
|
+
if (!dir || !isAbsolute6(dir))
|
|
22742
23436
|
continue;
|
|
22743
|
-
const candidate =
|
|
23437
|
+
const candidate = join14(dir, `aft${ext}`);
|
|
22744
23438
|
if (seen.has(candidate))
|
|
22745
23439
|
continue;
|
|
22746
23440
|
seen.add(candidate);
|
|
@@ -22818,7 +23512,7 @@ function npmPlatformPackage(ext) {
|
|
|
22818
23512
|
const req = createRequire2(import.meta.url);
|
|
22819
23513
|
const manifestPath = req.resolve(`@cortexkit/aft-${platformKey()}/package.json`);
|
|
22820
23514
|
const manifest = JSON.parse(readFileSync7(manifestPath, "utf8"));
|
|
22821
|
-
const binaryPath =
|
|
23515
|
+
const binaryPath = join14(dirname8(manifestPath), "bin", `aft${ext}`);
|
|
22822
23516
|
if (typeof manifest.version !== "string" || !existsSync8(binaryPath))
|
|
22823
23517
|
return null;
|
|
22824
23518
|
return { binaryPath, version: normalizeBareVersion(manifest.version) };
|
|
@@ -22885,7 +23579,7 @@ async function findProbedBinary(expectedVersion, env) {
|
|
|
22885
23579
|
if (usable)
|
|
22886
23580
|
return { path: usable, source: "PATH" };
|
|
22887
23581
|
}
|
|
22888
|
-
const cargoPath =
|
|
23582
|
+
const cargoPath = join14(homeDirFromEnv(env), ".cargo", "bin", `aft${ext}`);
|
|
22889
23583
|
if (existsSync8(cargoPath)) {
|
|
22890
23584
|
const usable = await probeBinaryCandidateOffThread(cargoPath, "cargo", pluginVersion);
|
|
22891
23585
|
if (usable)
|
|
@@ -22984,9 +23678,9 @@ function dataHome() {
|
|
|
22984
23678
|
if (process.env.XDG_DATA_HOME)
|
|
22985
23679
|
return process.env.XDG_DATA_HOME;
|
|
22986
23680
|
if (process.platform === "win32") {
|
|
22987
|
-
return process.env.LOCALAPPDATA || process.env.APPDATA ||
|
|
23681
|
+
return process.env.LOCALAPPDATA || process.env.APPDATA || join15(homeDir4(), "AppData", "Local");
|
|
22988
23682
|
}
|
|
22989
|
-
return
|
|
23683
|
+
return join15(homeDir4(), ".local", "share");
|
|
22990
23684
|
}
|
|
22991
23685
|
function homeDir4() {
|
|
22992
23686
|
if (process.platform === "win32")
|
|
@@ -22995,8 +23689,8 @@ function homeDir4() {
|
|
|
22995
23689
|
}
|
|
22996
23690
|
function resolveLegacyStorageRoot(harness) {
|
|
22997
23691
|
if (harness === "pi")
|
|
22998
|
-
return
|
|
22999
|
-
return
|
|
23692
|
+
return join15(homeDir4(), ".pi", "agent", "aft");
|
|
23693
|
+
return join15(dataHome(), "opencode", "storage", "plugin", "aft");
|
|
23000
23694
|
}
|
|
23001
23695
|
function stripJsoncForParse(input) {
|
|
23002
23696
|
let out = "";
|
|
@@ -23126,7 +23820,7 @@ function acquireConfigMigrationLock(lockDir) {
|
|
|
23126
23820
|
}
|
|
23127
23821
|
function atomicCopyConfigFile(sourcePath, targetPath) {
|
|
23128
23822
|
mkdirSync5(dirname9(targetPath), { recursive: true });
|
|
23129
|
-
const tmpPath =
|
|
23823
|
+
const tmpPath = join15(dirname9(targetPath), `.${basename2(targetPath)}.${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}.tmp`);
|
|
23130
23824
|
let fd = null;
|
|
23131
23825
|
try {
|
|
23132
23826
|
fd = openSync7(tmpPath, "wx", 384);
|
|
@@ -23148,7 +23842,7 @@ function atomicCopyConfigFile(sourcePath, targetPath) {
|
|
|
23148
23842
|
}
|
|
23149
23843
|
function atomicWriteConfigFile(targetPath, content) {
|
|
23150
23844
|
mkdirSync5(dirname9(targetPath), { recursive: true });
|
|
23151
|
-
const tmpPath =
|
|
23845
|
+
const tmpPath = join15(dirname9(targetPath), `.${basename2(targetPath)}.${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}.tmp`);
|
|
23152
23846
|
let fd = null;
|
|
23153
23847
|
try {
|
|
23154
23848
|
fd = openSync7(tmpPath, "wx", 384);
|
|
@@ -23267,8 +23961,8 @@ function visibleConfigMigrationWarning(scope, targetPath, paths, reason) {
|
|
|
23267
23961
|
}
|
|
23268
23962
|
function migrateAftConfigFile(opts) {
|
|
23269
23963
|
const warnings = [];
|
|
23270
|
-
const resolvedTarget =
|
|
23271
|
-
const existingSources = opts.legacySources.filter((source) => existsSync9(source.path) &&
|
|
23964
|
+
const resolvedTarget = resolve10(opts.targetPath);
|
|
23965
|
+
const existingSources = opts.legacySources.filter((source) => existsSync9(source.path) && resolve10(source.path) !== resolvedTarget);
|
|
23272
23966
|
const info = opts.logger?.info ?? opts.logger?.log;
|
|
23273
23967
|
if (existingSources.length === 0) {
|
|
23274
23968
|
return { migrated: false, conflict: false, targetPath: opts.targetPath, warnings };
|
|
@@ -23330,12 +24024,12 @@ function spawnErrorLabel(error) {
|
|
|
23330
24024
|
return [code, error.message].filter(Boolean).join(": ");
|
|
23331
24025
|
}
|
|
23332
24026
|
function migrationLogPath(newRoot, harness, logger) {
|
|
23333
|
-
const desired =
|
|
24027
|
+
const desired = join15(newRoot, "logs", "migration", `${harness}-${Date.now()}.jsonl`);
|
|
23334
24028
|
try {
|
|
23335
24029
|
mkdirSync5(dirname9(desired), { recursive: true });
|
|
23336
24030
|
return desired;
|
|
23337
24031
|
} catch (err) {
|
|
23338
|
-
const fallback =
|
|
24032
|
+
const fallback = join15(tmpdir3(), `aft-migration-${harness}-${Date.now()}.jsonl`);
|
|
23339
24033
|
logger?.warn?.(`Failed to create AFT migration log directory ${dirname9(desired)}: ${err instanceof Error ? err.message : String(err)}. ` + `Using fallback log path ${fallback}.`);
|
|
23340
24034
|
return fallback;
|
|
23341
24035
|
}
|
|
@@ -23395,13 +24089,13 @@ async function ensureStorageMigrated(opts) {
|
|
|
23395
24089
|
// ../aft-bridge/dist/migration-notices.js
|
|
23396
24090
|
import { readFileSync as readFileSync9, renameSync as renameSync6, rmdirSync, statSync as statSync9, writeFileSync as writeFileSync5 } from "node:fs";
|
|
23397
24091
|
import { homedir as homedir11 } from "node:os";
|
|
23398
|
-
import { dirname as dirname10, join as
|
|
24092
|
+
import { dirname as dirname10, join as join16, resolve as resolve11 } from "node:path";
|
|
23399
24093
|
function migrationNoticeStorePath(env = process.env) {
|
|
23400
|
-
const stateHome = env.XDG_STATE_HOME && env.XDG_STATE_HOME.length > 0 ? env.XDG_STATE_HOME :
|
|
23401
|
-
return
|
|
24094
|
+
const stateHome = env.XDG_STATE_HOME && env.XDG_STATE_HOME.length > 0 ? env.XDG_STATE_HOME : join16(homedir11(), ".local", "state");
|
|
24095
|
+
return join16(stateHome, "cortexkit", "aft", "migration-notices.json");
|
|
23402
24096
|
}
|
|
23403
24097
|
function noticeKey(configPath, digest) {
|
|
23404
|
-
return `${
|
|
24098
|
+
return `${resolve11(configPath)}|${MIGRATION_POLICY_ID}|${digest}`;
|
|
23405
24099
|
}
|
|
23406
24100
|
function readRecords(storePath) {
|
|
23407
24101
|
try {
|
|
@@ -23595,7 +24289,7 @@ function probeOnnxRuntimeLoadable(libPath, arch = process.arch) {
|
|
|
23595
24289
|
// ../aft-bridge/dist/onnx-runtime.js
|
|
23596
24290
|
import { randomBytes as randomBytes3 } from "node:crypto";
|
|
23597
24291
|
import { chmodSync as chmodSync2, closeSync as closeSync10, copyFileSync as copyFileSync4, createWriteStream as createWriteStream3, existsSync as existsSync11, lstatSync as lstatSync3, openSync as openSync9, readdirSync as readdirSync4, readFileSync as readFileSync10, readlinkSync as readlinkSync2, realpathSync as realpathSync7, renameSync as renameSync7, rmSync as rmSync4, statSync as statSync10, symlinkSync, unlinkSync as unlinkSync5, writeFileSync as writeFileSync6 } from "node:fs";
|
|
23598
|
-
import { basename as basename3, dirname as dirname11, isAbsolute as
|
|
24292
|
+
import { basename as basename3, dirname as dirname11, isAbsolute as isAbsolute7, join as join17, relative as relative4, resolve as resolve12, win32 as win324 } from "node:path";
|
|
23599
24293
|
import { Readable as Readable3 } from "node:stream";
|
|
23600
24294
|
import { pipeline as pipeline3 } from "node:stream/promises";
|
|
23601
24295
|
var ORT_VERSION = "1.24.4";
|
|
@@ -23686,7 +24380,7 @@ function resolveOnnxRuntime(storageDir, seams) {
|
|
|
23686
24380
|
}
|
|
23687
24381
|
async function findCachedOnnxRuntime(ortVersionDir, libName) {
|
|
23688
24382
|
const resolvedOrtDir = resolveCachedOnnxRuntimeDir(ortVersionDir, libName);
|
|
23689
|
-
const libPath =
|
|
24383
|
+
const libPath = join17(resolvedOrtDir, libName);
|
|
23690
24384
|
if (existsSync11(libPath)) {
|
|
23691
24385
|
const meta = readOnnxInstalledMeta(ortVersionDir);
|
|
23692
24386
|
if (meta?.sha256) {
|
|
@@ -23711,7 +24405,7 @@ async function findCachedOnnxRuntime(ortVersionDir, libName) {
|
|
|
23711
24405
|
}
|
|
23712
24406
|
async function resolveOnnxRuntimeUncoalesced(storageDir, seams) {
|
|
23713
24407
|
const info = seams.platformInfo !== undefined ? seams.platformInfo : getPlatformInfo();
|
|
23714
|
-
const ortVersionDir =
|
|
24408
|
+
const ortVersionDir = join17(storageDir, "onnxruntime", ORT_VERSION);
|
|
23715
24409
|
const libName = info?.libName ?? "libonnxruntime.dylib";
|
|
23716
24410
|
const cached = await findCachedOnnxRuntime(ortVersionDir, libName);
|
|
23717
24411
|
if (cached)
|
|
@@ -23725,9 +24419,9 @@ async function resolveOnnxRuntimeUncoalesced(storageDir, seams) {
|
|
|
23725
24419
|
warn(`ONNX Runtime auto-download not available for ${process.platform}/${process.arch}. Install manually: ${getManualInstallHint()}`);
|
|
23726
24420
|
return null;
|
|
23727
24421
|
}
|
|
23728
|
-
const onnxBaseDir =
|
|
24422
|
+
const onnxBaseDir = join17(storageDir, "onnxruntime");
|
|
23729
24423
|
openPrivateStorageDir(storageDir, onnxBaseDir);
|
|
23730
|
-
const lockPath =
|
|
24424
|
+
const lockPath = join17(onnxBaseDir, ONNX_LOCK_FILE);
|
|
23731
24425
|
const pollMs = seams.lockPollMs ?? LOCK_POLL_MS;
|
|
23732
24426
|
const deadline = Date.now() + LOCK_WAIT_MS;
|
|
23733
24427
|
let announcedWait = false;
|
|
@@ -23772,7 +24466,7 @@ function cleanupAbandonedStagingDirs(onnxBaseDir) {
|
|
|
23772
24466
|
for (const entry of entries) {
|
|
23773
24467
|
if (!entry.startsWith(`${ORT_VERSION}.tmp.`))
|
|
23774
24468
|
continue;
|
|
23775
|
-
const stagingDir =
|
|
24469
|
+
const stagingDir = join17(onnxBaseDir, entry);
|
|
23776
24470
|
const parts = entry.split(".");
|
|
23777
24471
|
const pidStr = parts[parts.length - 2];
|
|
23778
24472
|
const pid = pidStr ? Number.parseInt(pidStr, 10) : NaN;
|
|
@@ -23809,7 +24503,7 @@ function cleanupAbandonedStagingDirs(onnxBaseDir) {
|
|
|
23809
24503
|
}
|
|
23810
24504
|
function cleanupIncompleteTargetIfUnowned(ortDir) {
|
|
23811
24505
|
try {
|
|
23812
|
-
if (existsSync11(ortDir) && !existsSync11(
|
|
24506
|
+
if (existsSync11(ortDir) && !existsSync11(join17(ortDir, ONNX_INSTALLED_META_FILE))) {
|
|
23813
24507
|
log(`[onnx] removing half-populated install dir ${ortDir} (no meta file)`);
|
|
23814
24508
|
rmSync4(ortDir, { recursive: true, force: true });
|
|
23815
24509
|
}
|
|
@@ -23837,14 +24531,14 @@ function parseOnnxVersionFromDirectoryPath(value) {
|
|
|
23837
24531
|
return null;
|
|
23838
24532
|
}
|
|
23839
24533
|
function isPathInsideRoot(root, candidate) {
|
|
23840
|
-
const rel =
|
|
23841
|
-
return rel === "" || !rel.startsWith("../") && !rel.startsWith("..\\") && rel !== ".." && !
|
|
24534
|
+
const rel = relative4(root, candidate);
|
|
24535
|
+
return rel === "" || !rel.startsWith("../") && !rel.startsWith("..\\") && rel !== ".." && !isAbsolute7(rel) && !win324.isAbsolute(rel);
|
|
23842
24536
|
}
|
|
23843
24537
|
function detectOnnxVersion(libDir, libName) {
|
|
23844
24538
|
try {
|
|
23845
24539
|
const entries = readdirSync4(libDir);
|
|
23846
24540
|
try {
|
|
23847
|
-
const resolved = parseOnnxVersionFromPath(realpathSync7(
|
|
24541
|
+
const resolved = parseOnnxVersionFromPath(realpathSync7(join17(libDir, libName)));
|
|
23848
24542
|
if (resolved && resolved !== INVALID_ORT_VERSION)
|
|
23849
24543
|
return resolved;
|
|
23850
24544
|
} catch {}
|
|
@@ -23858,7 +24552,7 @@ function detectOnnxVersion(libDir, libName) {
|
|
|
23858
24552
|
if (version)
|
|
23859
24553
|
return version;
|
|
23860
24554
|
}
|
|
23861
|
-
const base =
|
|
24555
|
+
const base = join17(libDir, libName);
|
|
23862
24556
|
if (existsSync11(base)) {
|
|
23863
24557
|
try {
|
|
23864
24558
|
const real = realpathSync7(base);
|
|
@@ -23898,18 +24592,18 @@ function pathEntriesForPlatform() {
|
|
|
23898
24592
|
return pathEnvValue().split(delimiter).map((entry) => entry.trim().replace(/^"|"$/g, "")).filter((entry) => {
|
|
23899
24593
|
if (!entry || entry === "." || entry.includes("\x00"))
|
|
23900
24594
|
return false;
|
|
23901
|
-
return
|
|
24595
|
+
return isAbsolute7(entry) || win324.isAbsolute(entry);
|
|
23902
24596
|
});
|
|
23903
24597
|
}
|
|
23904
24598
|
function isWindowsSystem32Directory(dir) {
|
|
23905
24599
|
if (process.platform !== "win32")
|
|
23906
24600
|
return false;
|
|
23907
|
-
const normalizedDir =
|
|
24601
|
+
const normalizedDir = win324.resolve(dir).replace(/[\\/]+$/, "").toLowerCase();
|
|
23908
24602
|
const windowsRoots = [process.env.SystemRoot, process.env.windir, "C:\\Windows"];
|
|
23909
24603
|
return windowsRoots.some((root) => {
|
|
23910
24604
|
if (!root)
|
|
23911
24605
|
return false;
|
|
23912
|
-
return normalizedDir ===
|
|
24606
|
+
return normalizedDir === win324.resolve(root, "System32").replace(/[\\/]+$/, "").toLowerCase();
|
|
23913
24607
|
});
|
|
23914
24608
|
}
|
|
23915
24609
|
function directoryContainsLibrary(dir, libName) {
|
|
@@ -23925,10 +24619,10 @@ function directoryContainsLibrary(dir, libName) {
|
|
|
23925
24619
|
}
|
|
23926
24620
|
}
|
|
23927
24621
|
function resolveCachedOnnxRuntimeDir(ortVersionDir, libName) {
|
|
23928
|
-
if (existsSync11(
|
|
24622
|
+
if (existsSync11(join17(ortVersionDir, libName)))
|
|
23929
24623
|
return ortVersionDir;
|
|
23930
|
-
const libSubdir =
|
|
23931
|
-
if (existsSync11(
|
|
24624
|
+
const libSubdir = join17(ortVersionDir, "lib");
|
|
24625
|
+
if (existsSync11(join17(libSubdir, libName)))
|
|
23932
24626
|
return libSubdir;
|
|
23933
24627
|
return ortVersionDir;
|
|
23934
24628
|
}
|
|
@@ -23943,12 +24637,12 @@ function findSystemOnnxRuntime(libName, searchPathsOverride) {
|
|
|
23943
24637
|
} else if (process.platform === "win32") {
|
|
23944
24638
|
const programFiles = process.env.ProgramFiles ?? "C:\\Program Files";
|
|
23945
24639
|
const programFilesX86 = process.env["ProgramFiles(x86)"] ?? "C:\\Program Files (x86)";
|
|
23946
|
-
searchPaths.push(
|
|
24640
|
+
searchPaths.push(join17(programFiles, "onnxruntime", "lib"), join17(programFiles, "Microsoft ONNX Runtime", "lib"), join17(programFiles, "Microsoft Machine Learning", "lib"), join17(programFilesX86, "onnxruntime", "lib"), ...(() => {
|
|
23947
24641
|
const nugetPaths = [];
|
|
23948
24642
|
const userProfile = process.env.USERPROFILE ?? "";
|
|
23949
24643
|
if (!userProfile)
|
|
23950
24644
|
return nugetPaths;
|
|
23951
|
-
const nugetPackageDir =
|
|
24645
|
+
const nugetPackageDir = join17(userProfile, ".nuget", "packages", "microsoft.ml.onnxruntime");
|
|
23952
24646
|
if (!existsSync11(nugetPackageDir))
|
|
23953
24647
|
return nugetPaths;
|
|
23954
24648
|
try {
|
|
@@ -23957,7 +24651,7 @@ function findSystemOnnxRuntime(libName, searchPathsOverride) {
|
|
|
23957
24651
|
continue;
|
|
23958
24652
|
if (entry.name === "__globalPackagesFolder" || entry.name.startsWith("."))
|
|
23959
24653
|
continue;
|
|
23960
|
-
nugetPaths.push(
|
|
24654
|
+
nugetPaths.push(join17(nugetPackageDir, entry.name, "runtimes", "win-x64", "native"), join17(nugetPackageDir, entry.name, "runtimes", "win-arm64", "native"));
|
|
23961
24655
|
}
|
|
23962
24656
|
} catch (err) {
|
|
23963
24657
|
warn(`Failed to scan NuGet ONNX Runtime cache ${nugetPackageDir}: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -23969,7 +24663,7 @@ function findSystemOnnxRuntime(libName, searchPathsOverride) {
|
|
|
23969
24663
|
const normalizeCase = process.platform === "win32" || process.platform === "darwin";
|
|
23970
24664
|
const seen = new Set;
|
|
23971
24665
|
const uniquePaths = searchPaths.filter((p) => {
|
|
23972
|
-
let key =
|
|
24666
|
+
let key = resolve12(p).replace(/[/\\]+$/, "");
|
|
23973
24667
|
if (normalizeCase)
|
|
23974
24668
|
key = key.toLowerCase();
|
|
23975
24669
|
if (seen.has(key))
|
|
@@ -23979,7 +24673,7 @@ function findSystemOnnxRuntime(libName, searchPathsOverride) {
|
|
|
23979
24673
|
});
|
|
23980
24674
|
const unknownVersionPaths = [];
|
|
23981
24675
|
for (const dir of uniquePaths) {
|
|
23982
|
-
const libPath =
|
|
24676
|
+
const libPath = join17(dir, libName);
|
|
23983
24677
|
if (process.platform === "win32") {
|
|
23984
24678
|
if (!directoryContainsLibrary(dir, libName))
|
|
23985
24679
|
continue;
|
|
@@ -24058,19 +24752,19 @@ function validateExtractedTree(stagingRoot) {
|
|
|
24058
24752
|
const walk = (dir) => {
|
|
24059
24753
|
const entries = readdirSync4(dir);
|
|
24060
24754
|
for (const entry of entries) {
|
|
24061
|
-
const fullPath =
|
|
24755
|
+
const fullPath = join17(dir, entry);
|
|
24062
24756
|
const lst = lstatSync3(fullPath);
|
|
24063
24757
|
if (lst.isSymbolicLink()) {
|
|
24064
24758
|
const linkTarget = readlinkSync2(fullPath);
|
|
24065
|
-
const resolvedTarget =
|
|
24066
|
-
const rel =
|
|
24067
|
-
if (relativePathEscapesRoot(rel) ||
|
|
24759
|
+
const resolvedTarget = resolve12(dirname11(fullPath), linkTarget);
|
|
24760
|
+
const rel = relative4(realRoot, resolvedTarget);
|
|
24761
|
+
if (relativePathEscapesRoot(rel) || win324.isAbsolute(rel)) {
|
|
24068
24762
|
throw new Error(`extracted symlink ${fullPath} points outside staging root: ${linkTarget}`);
|
|
24069
24763
|
}
|
|
24070
24764
|
continue;
|
|
24071
24765
|
}
|
|
24072
|
-
const rel =
|
|
24073
|
-
if (relativePathEscapesRoot(rel) ||
|
|
24766
|
+
const rel = relative4(realRoot, fullPath);
|
|
24767
|
+
if (relativePathEscapesRoot(rel) || win324.isAbsolute(rel)) {
|
|
24074
24768
|
throw new Error(`extracted entry ${fullPath} escapes staging root`);
|
|
24075
24769
|
}
|
|
24076
24770
|
if (lst.isDirectory()) {
|
|
@@ -24095,11 +24789,11 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
24095
24789
|
const url = `https://github.com/${ORT_REPO}/releases/download/v${ORT_VERSION}/${info.assetName}.${info.archiveType === "tgz" ? "tgz" : "zip"}`;
|
|
24096
24790
|
log(`Downloading ONNX Runtime v${ORT_VERSION} for ${process.platform}/${process.arch}...`);
|
|
24097
24791
|
const tmpDir = `${targetDir}.tmp.${process.pid}.${Date.now().toString(36)}${randomBytes3(4).toString("hex")}`;
|
|
24098
|
-
const extractionRoot =
|
|
24099
|
-
const stagedInstallDir =
|
|
24792
|
+
const extractionRoot = join17(tmpDir, "extract");
|
|
24793
|
+
const stagedInstallDir = join17(tmpDir, "install");
|
|
24100
24794
|
try {
|
|
24101
24795
|
privateMkdirSync(extractionRoot);
|
|
24102
|
-
const archivePath =
|
|
24796
|
+
const archivePath = join17(tmpDir, `onnxruntime.${info.archiveType}`);
|
|
24103
24797
|
await downloadFileWithCap(url, archivePath);
|
|
24104
24798
|
const archiveSha256 = await sha256File(archivePath);
|
|
24105
24799
|
log(`ONNX Runtime archive sha256=${archiveSha256}`);
|
|
@@ -24112,7 +24806,7 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
24112
24806
|
unlinkSync5(archivePath);
|
|
24113
24807
|
} catch {}
|
|
24114
24808
|
validateExtractedTree(extractionRoot);
|
|
24115
|
-
const extractedDir =
|
|
24809
|
+
const extractedDir = join17(extractionRoot, info.assetName, "lib");
|
|
24116
24810
|
if (!existsSync11(extractedDir)) {
|
|
24117
24811
|
throw new Error(`Expected directory not found: ${extractedDir}`);
|
|
24118
24812
|
}
|
|
@@ -24120,7 +24814,7 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
24120
24814
|
const realFiles = [];
|
|
24121
24815
|
const symlinks = [];
|
|
24122
24816
|
for (const libFile of libFiles) {
|
|
24123
|
-
const src =
|
|
24817
|
+
const src = join17(extractedDir, libFile);
|
|
24124
24818
|
try {
|
|
24125
24819
|
const stat = lstatSync3(src);
|
|
24126
24820
|
log(`ORT extract: ${libFile} — isSymlink=${stat.isSymbolicLink()}, isFile=${stat.isFile()}, size=${stat.size}`);
|
|
@@ -24135,14 +24829,14 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
24135
24829
|
}
|
|
24136
24830
|
}
|
|
24137
24831
|
copyOnnxLibraries(info, extractedDir, stagedInstallDir, realFiles, symlinks);
|
|
24138
|
-
const libPath =
|
|
24832
|
+
const libPath = join17(stagedInstallDir, info.libName);
|
|
24139
24833
|
const libHash = await sha256File(libPath);
|
|
24140
24834
|
if (libHash !== info.librarySha256) {
|
|
24141
24835
|
throw new Error(`onnx runtime library hash mismatch at ${libPath}: sha256 ${libHash}, ` + `expected the pinned ${info.librarySha256} for ${info.assetName}`);
|
|
24142
24836
|
}
|
|
24143
24837
|
writeOnnxInstalledMeta(stagedInstallDir, ORT_VERSION, libHash, archiveSha256);
|
|
24144
24838
|
publishOnnxRuntime(stagedInstallDir, targetDir);
|
|
24145
|
-
writeStampedFileDigest(
|
|
24839
|
+
writeStampedFileDigest(join17(targetDir, info.libName), libHash);
|
|
24146
24840
|
rmSync4(tmpDir, { recursive: true, force: true });
|
|
24147
24841
|
log(`ONNX Runtime v${ORT_VERSION} installed to ${targetDir}`);
|
|
24148
24842
|
return targetDir;
|
|
@@ -24184,8 +24878,8 @@ function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, c
|
|
|
24184
24878
|
const requiredLibs = new Set([info.libName]);
|
|
24185
24879
|
privateMkdirSync(targetDir);
|
|
24186
24880
|
for (const libFile of realFiles) {
|
|
24187
|
-
const src =
|
|
24188
|
-
const dst =
|
|
24881
|
+
const src = join17(extractedDir, libFile);
|
|
24882
|
+
const dst = join17(targetDir, libFile);
|
|
24189
24883
|
try {
|
|
24190
24884
|
if (copyFile === copyFileSync4)
|
|
24191
24885
|
privateCopyFileSync(src, dst);
|
|
@@ -24204,12 +24898,12 @@ function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, c
|
|
|
24204
24898
|
}
|
|
24205
24899
|
const targetRoot = realpathSync7(targetDir);
|
|
24206
24900
|
for (const link of symlinks) {
|
|
24207
|
-
const dst =
|
|
24901
|
+
const dst = join17(targetDir, link.name);
|
|
24208
24902
|
try {
|
|
24209
24903
|
unlinkSync5(dst);
|
|
24210
24904
|
} catch {}
|
|
24211
|
-
const dstForContainment =
|
|
24212
|
-
const resolvedTarget =
|
|
24905
|
+
const dstForContainment = join17(targetRoot, link.name);
|
|
24906
|
+
const resolvedTarget = resolve12(dirname11(dstForContainment), link.target);
|
|
24213
24907
|
if (!isPathInsideRoot(targetRoot, resolvedTarget)) {
|
|
24214
24908
|
const message = `ONNX Runtime symlink ${link.name} points outside install dir: ${link.target}`;
|
|
24215
24909
|
if (requiredLibs.has(link.name)) {
|
|
@@ -24229,7 +24923,7 @@ function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, c
|
|
|
24229
24923
|
log(`ORT extract: failed to symlink optional ${link.name}: ${symlinkErr}`);
|
|
24230
24924
|
}
|
|
24231
24925
|
}
|
|
24232
|
-
const requiredPath =
|
|
24926
|
+
const requiredPath = join17(targetDir, info.libName);
|
|
24233
24927
|
if (!existsSync11(requiredPath)) {
|
|
24234
24928
|
rmSync4(targetDir, { recursive: true, force: true });
|
|
24235
24929
|
throw new Error(`Required ONNX Runtime library missing after install: ${requiredPath}`);
|
|
@@ -24257,7 +24951,7 @@ function writeOnnxInstalledMeta(installDir, version, sha256, archiveSha256) {
|
|
|
24257
24951
|
...sha256 ? { sha256 } : {},
|
|
24258
24952
|
archiveSha256
|
|
24259
24953
|
};
|
|
24260
|
-
writeFileSync6(
|
|
24954
|
+
writeFileSync6(join17(installDir, ONNX_INSTALLED_META_FILE), JSON.stringify(meta), {
|
|
24261
24955
|
encoding: "utf8",
|
|
24262
24956
|
mode: PRIVATE_FILE_MODE
|
|
24263
24957
|
});
|
|
@@ -24266,7 +24960,7 @@ function writeOnnxInstalledMeta(installDir, version, sha256, archiveSha256) {
|
|
|
24266
24960
|
}
|
|
24267
24961
|
}
|
|
24268
24962
|
function readOnnxInstalledMeta(installDir) {
|
|
24269
|
-
const path =
|
|
24963
|
+
const path = join17(installDir, ONNX_INSTALLED_META_FILE);
|
|
24270
24964
|
try {
|
|
24271
24965
|
if (!statSync10(path).isFile())
|
|
24272
24966
|
return null;
|
|
@@ -25071,7 +25765,7 @@ function formatSemanticIndexStatus(status, stage, error, backend) {
|
|
|
25071
25765
|
// src/config.ts
|
|
25072
25766
|
import { existsSync as existsSync12, readFileSync as readFileSync11, statSync as statSync11 } from "node:fs";
|
|
25073
25767
|
import { homedir as homedir12 } from "node:os";
|
|
25074
|
-
import { isAbsolute as
|
|
25768
|
+
import { isAbsolute as isAbsolute8, parse as parsePath, resolve as resolvePath } from "node:path";
|
|
25075
25769
|
var import_comment_json = __toESM(require_src2(), 1);
|
|
25076
25770
|
|
|
25077
25771
|
// ../../node_modules/.bun/zod@4.4.3/node_modules/zod/v4/core/core.js
|
|
@@ -29957,9 +30651,9 @@ var SemanticBackendEnum = _enum(["fastembed", "openai_compatible", "ollama", "sy
|
|
|
29957
30651
|
var IndexKindSchema = _enum(["search", "semantic", "callgraph"]);
|
|
29958
30652
|
function isSupportedAbsoluteIndexPath(path) {
|
|
29959
30653
|
if (path === "~" || path.startsWith("~/") || path.startsWith("~\\")) {
|
|
29960
|
-
return
|
|
30654
|
+
return isAbsolute8(homedir12());
|
|
29961
30655
|
}
|
|
29962
|
-
return
|
|
30656
|
+
return isAbsolute8(path);
|
|
29963
30657
|
}
|
|
29964
30658
|
var IndexRootSchema = object({
|
|
29965
30659
|
path: string2().refine(isSupportedAbsoluteIndexPath, {
|
|
@@ -30016,6 +30710,7 @@ var LspServerEntrySchema = object({
|
|
|
30016
30710
|
initialization_options: unknown().optional()
|
|
30017
30711
|
});
|
|
30018
30712
|
var LspConfigSchema = object({
|
|
30713
|
+
max_servers: number2().int().nonnegative().optional(),
|
|
30019
30714
|
idle_minutes: union([
|
|
30020
30715
|
number2().int().transform((value) => Math.min(1440, Math.max(5, value))),
|
|
30021
30716
|
literal("never")
|
|
@@ -30099,7 +30794,7 @@ var SubcConfigSchema = object({
|
|
|
30099
30794
|
client_reaper: boolean2().optional()
|
|
30100
30795
|
});
|
|
30101
30796
|
var GhShimConfigSchema = object({
|
|
30102
|
-
binary_path: string2().trim().refine(
|
|
30797
|
+
binary_path: string2().trim().refine(isAbsolute8, "gh_shim.binary_path must be absolute").optional()
|
|
30103
30798
|
});
|
|
30104
30799
|
var RemoteExecConfigSchema = object({
|
|
30105
30800
|
enabled: boolean2().optional(),
|
|
@@ -30152,13 +30847,6 @@ var IdleConfigSchema = object({
|
|
|
30152
30847
|
root_ttl_minutes: number2().int().optional().transform((value) => value === undefined ? undefined : clampIdleRootTtlMinutes(value)),
|
|
30153
30848
|
checkout_hours: number2().int().optional().transform((value) => value === undefined ? undefined : clampIdleCheckoutHours(value))
|
|
30154
30849
|
});
|
|
30155
|
-
var ViewsConfigSchema = object({
|
|
30156
|
-
enabled: boolean2().optional(),
|
|
30157
|
-
callgraph_copies: number2().int().optional()
|
|
30158
|
-
});
|
|
30159
|
-
var WorktreeConfigSchema = object({
|
|
30160
|
-
ram_overlay: boolean2().optional()
|
|
30161
|
-
});
|
|
30162
30850
|
var BackupConfigSchema = object({
|
|
30163
30851
|
enabled: boolean2().optional(),
|
|
30164
30852
|
max_depth: number2().int().positive().optional(),
|
|
@@ -30184,12 +30872,10 @@ var AftConfigFieldsSchema = object({
|
|
|
30184
30872
|
indexes: IndexesConfigSchema.optional(),
|
|
30185
30873
|
index: IndexConfigSchema.optional(),
|
|
30186
30874
|
storage: object({ cache_dir: string2().nullable().optional() }).optional(),
|
|
30187
|
-
views: ViewsConfigSchema.optional(),
|
|
30188
30875
|
callgraph_chunk_size: number2().optional(),
|
|
30189
30876
|
inspect: InspectConfigSchema.optional(),
|
|
30190
30877
|
idle: IdleConfigSchema.optional(),
|
|
30191
30878
|
backup: BackupConfigSchema.optional(),
|
|
30192
|
-
worktree: WorktreeConfigSchema.optional(),
|
|
30193
30879
|
sandbox: SandboxConfigSchema.optional(),
|
|
30194
30880
|
bash: BashConfigSchema.optional(),
|
|
30195
30881
|
experimental: ExperimentalConfigSchema.optional(),
|
|
@@ -30472,6 +31158,9 @@ function loadConfigFromPath(configPath, tier) {
|
|
|
30472
31158
|
throw new ConfigRejectedError(["invalid_config_document"], configPath);
|
|
30473
31159
|
}
|
|
30474
31160
|
const removed = removedConfigKeyErrors(cleanConfig, undefined, false);
|
|
31161
|
+
if (tier === "user") {
|
|
31162
|
+
removed.push(...removedConfigKeyErrors(cleanConfig).filter((error) => [...REMOVED_DATA_LAYER_PATHS, ...DATA_LAYER_RETIRED_PATHS].some((path) => error.endsWith(`${path}; run npx @cortexkit/aft doctor --fix`))));
|
|
31163
|
+
}
|
|
30475
31164
|
if (removed.length) {
|
|
30476
31165
|
throw new ConfigRejectedError(removed);
|
|
30477
31166
|
}
|
|
@@ -30498,14 +31187,7 @@ function loadConfigFromPath(configPath, tier) {
|
|
|
30498
31187
|
if (translation.legacyInput) {
|
|
30499
31188
|
log2(`Config ${configPath} uses retired keys (${translation.retiredKeys.join(", ")}); applied their current equivalents in memory`);
|
|
30500
31189
|
}
|
|
30501
|
-
|
|
30502
|
-
configLoadNotices.push({
|
|
30503
|
-
configPath,
|
|
30504
|
-
digest: removedConfigKeysNoticeDigest(translation),
|
|
30505
|
-
message: removedConfigKeysNoticeMessage(configPath, translation)
|
|
30506
|
-
});
|
|
30507
|
-
}
|
|
30508
|
-
} else if (translation.legacyInput || translation.removedKeys.length > 0) {
|
|
31190
|
+
} else if (translation.legacyInput) {
|
|
30509
31191
|
configLoadNotices.push({
|
|
30510
31192
|
configPath,
|
|
30511
31193
|
digest: noticeDigest(projection),
|
|
@@ -30560,6 +31242,9 @@ function mergeSemanticConfig(baseSemantic, overrideSemantic) {
|
|
|
30560
31242
|
}
|
|
30561
31243
|
function mergeLspConfig(baseLsp, overrideLsp) {
|
|
30562
31244
|
const projectLsp = {};
|
|
31245
|
+
if (overrideLsp?.max_servers !== undefined && overrideLsp.max_servers <= (baseLsp?.max_servers ?? 8)) {
|
|
31246
|
+
projectLsp.max_servers = overrideLsp.max_servers;
|
|
31247
|
+
}
|
|
30563
31248
|
if (overrideLsp?.python !== undefined)
|
|
30564
31249
|
projectLsp.python = overrideLsp.python;
|
|
30565
31250
|
if (overrideLsp?.diagnostics_on_edit !== undefined) {
|
|
@@ -30581,15 +31266,6 @@ function mergeLspConfig(baseLsp, overrideLsp) {
|
|
|
30581
31266
|
}
|
|
30582
31267
|
return Object.fromEntries(Object.entries(lsp).filter(([, value]) => value !== undefined));
|
|
30583
31268
|
}
|
|
30584
|
-
function mergeWorktreeConfig(baseWorktree, overrideWorktree) {
|
|
30585
|
-
if (baseWorktree === undefined && overrideWorktree === undefined)
|
|
30586
|
-
return;
|
|
30587
|
-
if (overrideWorktree === undefined)
|
|
30588
|
-
return baseWorktree;
|
|
30589
|
-
if (baseWorktree === undefined)
|
|
30590
|
-
return overrideWorktree;
|
|
30591
|
-
return { ...baseWorktree, ...overrideWorktree };
|
|
30592
|
-
}
|
|
30593
31269
|
function mergeIdleConfig(baseIdle, overrideIdle) {
|
|
30594
31270
|
const merged = {
|
|
30595
31271
|
root_ttl_minutes: overrideIdle?.root_ttl_minutes ?? baseIdle?.root_ttl_minutes,
|
|
@@ -30726,11 +31402,9 @@ var PROJECT_SAFE_TOP_LEVEL_FIELDS = new Set([
|
|
|
30726
31402
|
"revision_reads",
|
|
30727
31403
|
"validate_on_edit",
|
|
30728
31404
|
"configure_warnings_delivery",
|
|
30729
|
-
"views",
|
|
30730
31405
|
"callgraph_chunk_size",
|
|
30731
31406
|
"inspect",
|
|
30732
31407
|
"idle",
|
|
30733
|
-
"worktree",
|
|
30734
31408
|
"git",
|
|
30735
31409
|
"pi",
|
|
30736
31410
|
"experimental",
|
|
@@ -30847,22 +31521,18 @@ function mergeConfigs(base, override) {
|
|
|
30847
31521
|
bash.project_env = projectEnv;
|
|
30848
31522
|
}
|
|
30849
31523
|
const inspect = mergeInspectConfig(base.inspect, override.inspect);
|
|
30850
|
-
const worktree = mergeWorktreeConfig(base.worktree, override.worktree);
|
|
30851
31524
|
const idle = mergeIdleConfig(base.idle, override.idle);
|
|
30852
31525
|
const sandbox = mergeSandboxConfig(base.sandbox, override.sandbox);
|
|
30853
31526
|
const remoteExec = mergeRemoteExecConfig(base.remote_exec, override.remote_exec);
|
|
30854
31527
|
const backup = mergeProjectBackupConfig(base.backup, override.backup);
|
|
30855
31528
|
const pi = mergePiConfig(base.pi, override.pi);
|
|
30856
|
-
const views = base.views !== undefined || override.views !== undefined ? { ...base.views, ...override.views } : undefined;
|
|
30857
31529
|
const bridge = base.bridge;
|
|
30858
31530
|
const safeOverride = pickProjectSafeFields(override);
|
|
30859
31531
|
delete safeOverride.indexes;
|
|
30860
31532
|
delete safeOverride.bash;
|
|
30861
31533
|
delete safeOverride.inspect;
|
|
30862
|
-
delete safeOverride.worktree;
|
|
30863
31534
|
delete safeOverride.idle;
|
|
30864
31535
|
delete safeOverride.pi;
|
|
30865
|
-
delete safeOverride.views;
|
|
30866
31536
|
return {
|
|
30867
31537
|
...base,
|
|
30868
31538
|
...safeOverride,
|
|
@@ -30871,13 +31541,11 @@ function mergeConfigs(base, override) {
|
|
|
30871
31541
|
...lsp ? { lsp } : {},
|
|
30872
31542
|
...bash !== undefined ? { bash } : {},
|
|
30873
31543
|
...inspect !== undefined ? { inspect } : {},
|
|
30874
|
-
...worktree !== undefined ? { worktree } : {},
|
|
30875
31544
|
...idle !== undefined ? { idle } : {},
|
|
30876
31545
|
...sandbox !== undefined ? { sandbox } : {},
|
|
30877
31546
|
...remoteExec !== undefined ? { remote_exec: remoteExec } : {},
|
|
30878
31547
|
...backup !== undefined ? { backup } : {},
|
|
30879
31548
|
...pi !== undefined ? { pi } : {},
|
|
30880
|
-
...views !== undefined ? { views } : {},
|
|
30881
31549
|
experimental,
|
|
30882
31550
|
semantic,
|
|
30883
31551
|
search,
|
|
@@ -31281,7 +31949,7 @@ async function signalActiveBridges(pool, projectRoot, sessionID, request) {
|
|
|
31281
31949
|
}
|
|
31282
31950
|
|
|
31283
31951
|
// src/bg-notifications.ts
|
|
31284
|
-
import { createHash as
|
|
31952
|
+
import { createHash as createHash8, randomBytes as randomBytes4, randomUUID as randomUUID2 } from "node:crypto";
|
|
31285
31953
|
|
|
31286
31954
|
// src/shared/last-assistant-model.ts
|
|
31287
31955
|
function isRecord3(value) {
|
|
@@ -31605,7 +32273,7 @@ async function awaitWakeAdmission(options) {
|
|
|
31605
32273
|
|
|
31606
32274
|
// src/bg-notifications.ts
|
|
31607
32275
|
function hashReminder(text) {
|
|
31608
|
-
return
|
|
32276
|
+
return createHash8("sha256").update(text).digest("hex").slice(0, 16);
|
|
31609
32277
|
}
|
|
31610
32278
|
var CONSUMED_TASKIDS_CAP = 256;
|
|
31611
32279
|
var DELIVERED_AWAITING_ACK_CAP = 4096;
|
|
@@ -33105,7 +33773,7 @@ function shorten(value, limit) {
|
|
|
33105
33773
|
function formatCompletion(completion) {
|
|
33106
33774
|
const status = formatStatus(completion);
|
|
33107
33775
|
const duration = formatDuration(completion);
|
|
33108
|
-
const header = `- task ${completion.task_id} (${status}${duration ? `, ${duration}` : ""})`;
|
|
33776
|
+
const header = formatUnknownPtyExit(completion.task_id, completion) ?? `- task ${completion.task_id} (${status}${duration ? `, ${duration}` : ""})`;
|
|
33109
33777
|
const previewBlock = formatOutputPreview(completion);
|
|
33110
33778
|
const descendantWarning = completion.live_descendants_summary ? ` ${completion.live_descendants_summary}` : "";
|
|
33111
33779
|
const captureWarning = completion.output_incomplete || completion.status === "failed" && completion.status_reason ? ` [${completion.status_reason || "PTY output may be incomplete"}]` : "";
|
|
@@ -33161,7 +33829,7 @@ async function runDetachedBgHandler(work, onError) {
|
|
|
33161
33829
|
|
|
33162
33830
|
// src/lsp-auto-install.ts
|
|
33163
33831
|
import { existsSync as existsSync14, mkdirSync as mkdirSync7, renameSync as renameSync9, rmSync as rmSync6, statSync as statSync13, writeFileSync as writeFileSync8 } from "node:fs";
|
|
33164
|
-
import { join as
|
|
33832
|
+
import { join as join20 } from "node:path";
|
|
33165
33833
|
|
|
33166
33834
|
// src/lsp-cache.ts
|
|
33167
33835
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
@@ -33176,7 +33844,7 @@ import {
|
|
|
33176
33844
|
unlinkSync as unlinkSync6,
|
|
33177
33845
|
writeFileSync as writeFileSync7
|
|
33178
33846
|
} from "node:fs";
|
|
33179
|
-
import { join as
|
|
33847
|
+
import { join as join18 } from "node:path";
|
|
33180
33848
|
function aftCacheBase() {
|
|
33181
33849
|
return getAftCacheRoot();
|
|
33182
33850
|
}
|
|
@@ -33184,18 +33852,18 @@ function lspCacheRoot() {
|
|
|
33184
33852
|
return getAftLspPackagesDir();
|
|
33185
33853
|
}
|
|
33186
33854
|
function lspPackageDir(npmPackage) {
|
|
33187
|
-
return
|
|
33855
|
+
return join18(lspCacheRoot(), encodeURIComponent(npmPackage));
|
|
33188
33856
|
}
|
|
33189
33857
|
function lspBinaryPath(npmPackage, binary) {
|
|
33190
|
-
return
|
|
33858
|
+
return join18(lspPackageDir(npmPackage), "node_modules", ".bin", binary);
|
|
33191
33859
|
}
|
|
33192
33860
|
function lspBinDir(npmPackage) {
|
|
33193
|
-
return
|
|
33861
|
+
return join18(lspPackageDir(npmPackage), "node_modules", ".bin");
|
|
33194
33862
|
}
|
|
33195
33863
|
function isInstalled(npmPackage, binary) {
|
|
33196
33864
|
for (const candidate of lspBinaryCandidates(binary)) {
|
|
33197
33865
|
try {
|
|
33198
|
-
if (statSync12(
|
|
33866
|
+
if (statSync12(join18(lspBinDir(npmPackage), candidate)).isFile())
|
|
33199
33867
|
return true;
|
|
33200
33868
|
} catch {}
|
|
33201
33869
|
}
|
|
@@ -33215,13 +33883,13 @@ function writeInstalledMetaIn(installDir, version, sha256) {
|
|
|
33215
33883
|
installedAt: new Date().toISOString(),
|
|
33216
33884
|
...sha256 ? { sha256 } : {}
|
|
33217
33885
|
};
|
|
33218
|
-
writeFileSync7(
|
|
33886
|
+
writeFileSync7(join18(installDir, INSTALLED_META_FILE), JSON.stringify(meta), "utf8");
|
|
33219
33887
|
} catch (err) {
|
|
33220
33888
|
log2(`[lsp-cache] failed to write installed-meta in ${installDir}: ${err}`);
|
|
33221
33889
|
}
|
|
33222
33890
|
}
|
|
33223
33891
|
function readInstalledMetaIn(installDir) {
|
|
33224
|
-
const path =
|
|
33892
|
+
const path = join18(installDir, INSTALLED_META_FILE);
|
|
33225
33893
|
try {
|
|
33226
33894
|
if (!statSync12(path).isFile())
|
|
33227
33895
|
return null;
|
|
@@ -33245,7 +33913,7 @@ function readInstalledMeta(packageKey) {
|
|
|
33245
33913
|
return readInstalledMetaIn(lspPackageDir(packageKey));
|
|
33246
33914
|
}
|
|
33247
33915
|
function lockPath(npmPackage) {
|
|
33248
|
-
return
|
|
33916
|
+
return join18(lspPackageDir(npmPackage), ".aft-installing");
|
|
33249
33917
|
}
|
|
33250
33918
|
var STALE_LOCK_MS2 = 30 * 60 * 1000;
|
|
33251
33919
|
function acquireInstallLock(lockKey) {
|
|
@@ -33376,7 +34044,7 @@ var AUTO_INSTALL_STAMP_FILE = "last-lsp-autoinstall.json";
|
|
|
33376
34044
|
var AUTO_INSTALL_WINDOW_MS = 60 * 1000;
|
|
33377
34045
|
var AUTO_INSTALL_LOCK_STALE_MS = 30 * 60 * 1000;
|
|
33378
34046
|
function autoInstallStampPath() {
|
|
33379
|
-
return
|
|
34047
|
+
return join18(aftCacheBase(), AUTO_INSTALL_STAMP_FILE);
|
|
33380
34048
|
}
|
|
33381
34049
|
function hasRecentAutoInstallStamp(path) {
|
|
33382
34050
|
try {
|
|
@@ -33477,7 +34145,7 @@ function claimLspAutoInstallPass() {
|
|
|
33477
34145
|
}
|
|
33478
34146
|
var VERSION_CHECK_FILE = ".aft-version-check";
|
|
33479
34147
|
function readVersionCheck(npmPackage) {
|
|
33480
|
-
const file =
|
|
34148
|
+
const file = join18(lspPackageDir(npmPackage), VERSION_CHECK_FILE);
|
|
33481
34149
|
try {
|
|
33482
34150
|
const raw = readFileSync12(file, "utf8");
|
|
33483
34151
|
const parsed = JSON.parse(raw);
|
|
@@ -33494,7 +34162,7 @@ function readVersionCheck(npmPackage) {
|
|
|
33494
34162
|
}
|
|
33495
34163
|
function writeVersionCheck(npmPackage, latest) {
|
|
33496
34164
|
mkdirSync6(lspPackageDir(npmPackage), { recursive: true });
|
|
33497
|
-
const file =
|
|
34165
|
+
const file = join18(lspPackageDir(npmPackage), VERSION_CHECK_FILE);
|
|
33498
34166
|
const record = {
|
|
33499
34167
|
last_checked: new Date().toISOString(),
|
|
33500
34168
|
latest_eligible: latest
|
|
@@ -33611,7 +34279,7 @@ function isVersionSupported(spec, version) {
|
|
|
33611
34279
|
|
|
33612
34280
|
// src/lsp-project-relevance.ts
|
|
33613
34281
|
import { existsSync as existsSync13, readdirSync as readdirSync5, readFileSync as readFileSync13 } from "node:fs";
|
|
33614
|
-
import { join as
|
|
34282
|
+
import { join as join19 } from "node:path";
|
|
33615
34283
|
var MAX_WALK_DIRS = 200;
|
|
33616
34284
|
var MAX_WALK_DEPTH = 4;
|
|
33617
34285
|
var NOISE_DIRS = new Set([
|
|
@@ -33628,7 +34296,7 @@ function hasRootMarker(projectRoot, rootMarkers) {
|
|
|
33628
34296
|
if (!rootMarkers)
|
|
33629
34297
|
return false;
|
|
33630
34298
|
for (const marker of rootMarkers) {
|
|
33631
|
-
if (existsSync13(
|
|
34299
|
+
if (existsSync13(join19(projectRoot, marker)))
|
|
33632
34300
|
return true;
|
|
33633
34301
|
}
|
|
33634
34302
|
return false;
|
|
@@ -33652,7 +34320,7 @@ function hasPackageJsonDep(projectRoot, depNames) {
|
|
|
33652
34320
|
}
|
|
33653
34321
|
function readPackageJson(projectRoot) {
|
|
33654
34322
|
try {
|
|
33655
|
-
const raw = readFileSync13(
|
|
34323
|
+
const raw = readFileSync13(join19(projectRoot, "package.json"), "utf8");
|
|
33656
34324
|
const parsed = JSON.parse(raw);
|
|
33657
34325
|
if (typeof parsed !== "object" || parsed === null)
|
|
33658
34326
|
return null;
|
|
@@ -33682,7 +34350,7 @@ function relevantExtensionsInProject(projectRoot, extToServer) {
|
|
|
33682
34350
|
for (const entry of entries) {
|
|
33683
34351
|
if (entry.isDirectory()) {
|
|
33684
34352
|
if (current.depth < MAX_WALK_DEPTH && !NOISE_DIRS.has(entry.name.toLowerCase())) {
|
|
33685
|
-
queue.push({ dir:
|
|
34353
|
+
queue.push({ dir: join19(current.dir, entry.name), depth: current.depth + 1 });
|
|
33686
34354
|
}
|
|
33687
34355
|
continue;
|
|
33688
34356
|
}
|
|
@@ -33815,7 +34483,7 @@ async function resolveTargetVersion(spec, config, fetchImpl = fetch) {
|
|
|
33815
34483
|
}
|
|
33816
34484
|
function ensureInstallAnchor(cwd) {
|
|
33817
34485
|
try {
|
|
33818
|
-
const stub =
|
|
34486
|
+
const stub = join20(cwd, "package.json");
|
|
33819
34487
|
if (!existsSync14(stub)) {
|
|
33820
34488
|
writeFileSync8(stub, `${JSON.stringify({ name: "aft-lsp-cache", version: "0.0.0", private: true })}
|
|
33821
34489
|
`);
|
|
@@ -34036,10 +34704,10 @@ function sha256OfFileSync(path) {
|
|
|
34036
34704
|
}
|
|
34037
34705
|
function quarantineCachedNpmInstall(spec, reason) {
|
|
34038
34706
|
const packageDir = lspPackageDir(spec.npm);
|
|
34039
|
-
const dest =
|
|
34707
|
+
const dest = join20(packageDir, "..", ".quarantine", encodeURIComponent(spec.npm), `${Date.now()}`);
|
|
34040
34708
|
warn2(`[lsp] tofu_mismatch ${spec.npm}: ${reason}; quarantining ${packageDir} -> ${dest}`);
|
|
34041
34709
|
try {
|
|
34042
|
-
mkdirSync7(
|
|
34710
|
+
mkdirSync7(join20(dest, ".."), { recursive: true });
|
|
34043
34711
|
rmSync6(dest, { recursive: true, force: true });
|
|
34044
34712
|
renameSync9(packageDir, dest);
|
|
34045
34713
|
} catch (err) {
|
|
@@ -45786,7 +46454,7 @@ function date6(params) {
|
|
|
45786
46454
|
|
|
45787
46455
|
// ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/classic/external.js
|
|
45788
46456
|
config2(en_default());
|
|
45789
|
-
// ../../node_modules/.bun/@opencode-ai+plugin@1.17.11+
|
|
46457
|
+
// ../../node_modules/.bun/@opencode-ai+plugin@1.17.11+a24dd7ca87f30650/node_modules/@opencode-ai/plugin/dist/tool.js
|
|
45790
46458
|
function tool(input) {
|
|
45791
46459
|
return input;
|
|
45792
46460
|
}
|
|
@@ -45900,6 +46568,31 @@ async function getSessionDirectory(client, sessionId, fallbackDirectory) {
|
|
|
45900
46568
|
inflight.set(sessionId, lookup);
|
|
45901
46569
|
return lookup;
|
|
45902
46570
|
}
|
|
46571
|
+
async function getSessionDirectoryForEvent(client, sessionId, instanceDirectory) {
|
|
46572
|
+
const directory = await getSessionDirectory(client, sessionId, instanceDirectory);
|
|
46573
|
+
if (isV2PluginContext(client) && (directory !== client.location.directory || cache.get(sessionId)?.location?.workspaceID !== client.location.workspaceID))
|
|
46574
|
+
return null;
|
|
46575
|
+
return directory;
|
|
46576
|
+
}
|
|
46577
|
+
function getSessionDirectoryForDeletedEvent(client, sessionId, eventLocation) {
|
|
46578
|
+
if (!sessionId || !isV2PluginContext(client))
|
|
46579
|
+
return null;
|
|
46580
|
+
let location;
|
|
46581
|
+
if (eventLocation === undefined) {
|
|
46582
|
+
location = cache.get(sessionId)?.location;
|
|
46583
|
+
} else {
|
|
46584
|
+
if (!eventLocation || typeof eventLocation !== "object")
|
|
46585
|
+
return null;
|
|
46586
|
+
const ref = eventLocation;
|
|
46587
|
+
if (typeof ref.directory !== "string" || !ref.directory || ref.workspaceID !== undefined && typeof ref.workspaceID !== "string")
|
|
46588
|
+
return null;
|
|
46589
|
+
location = { directory: ref.directory, workspaceID: ref.workspaceID };
|
|
46590
|
+
setCache(sessionId, location.directory, location);
|
|
46591
|
+
}
|
|
46592
|
+
if (!location || location.directory !== client.location.directory || location.workspaceID !== client.location.workspaceID)
|
|
46593
|
+
return null;
|
|
46594
|
+
return location.directory;
|
|
46595
|
+
}
|
|
45903
46596
|
async function boundedLookup(client, sessionId, fallbackDirectory) {
|
|
45904
46597
|
const generation = {};
|
|
45905
46598
|
lookupGenerations.set(sessionId, generation);
|
|
@@ -45909,6 +46602,7 @@ async function boundedLookup(client, sessionId, fallbackDirectory) {
|
|
|
45909
46602
|
lookupGenerations.delete(oldest);
|
|
45910
46603
|
}
|
|
45911
46604
|
let timer;
|
|
46605
|
+
let location;
|
|
45912
46606
|
try {
|
|
45913
46607
|
const timeout = new Promise((resolve) => {
|
|
45914
46608
|
timer = setTimeout(() => {
|
|
@@ -45917,9 +46611,11 @@ async function boundedLookup(client, sessionId, fallbackDirectory) {
|
|
|
45917
46611
|
}, LOOKUP_TIMEOUT_MS);
|
|
45918
46612
|
});
|
|
45919
46613
|
const directory = await Promise.race([
|
|
45920
|
-
lookupSessionDirectory(client, sessionId, fallbackDirectory
|
|
46614
|
+
lookupSessionDirectory(client, sessionId, fallbackDirectory, (ref) => {
|
|
46615
|
+
location = ref;
|
|
46616
|
+
}).then((directory) => {
|
|
45921
46617
|
if (lookupGenerations.get(sessionId) === generation && directory !== null) {
|
|
45922
|
-
setCache(sessionId, directory);
|
|
46618
|
+
setCache(sessionId, directory, location);
|
|
45923
46619
|
}
|
|
45924
46620
|
return directory;
|
|
45925
46621
|
}).finally(() => {
|
|
@@ -45928,15 +46624,15 @@ async function boundedLookup(client, sessionId, fallbackDirectory) {
|
|
|
45928
46624
|
}),
|
|
45929
46625
|
timeout
|
|
45930
46626
|
]);
|
|
45931
|
-
setCache(sessionId, directory);
|
|
46627
|
+
setCache(sessionId, directory, location);
|
|
45932
46628
|
return directory;
|
|
45933
46629
|
} finally {
|
|
45934
46630
|
clearTimeout(timer);
|
|
45935
46631
|
}
|
|
45936
46632
|
}
|
|
45937
|
-
async function lookupSessionDirectory(client, sessionId, fallbackDirectory) {
|
|
46633
|
+
async function lookupSessionDirectory(client, sessionId, fallbackDirectory, onLocation) {
|
|
45938
46634
|
if (isV2PluginContext(client))
|
|
45939
|
-
return lookupV2SessionDirectory(client, sessionId);
|
|
46635
|
+
return lookupV2SessionDirectory(client, sessionId, onLocation);
|
|
45940
46636
|
const c = client;
|
|
45941
46637
|
const sessionApi = c?.session;
|
|
45942
46638
|
if (!sessionApi || typeof sessionApi.get !== "function") {
|
|
@@ -45955,15 +46651,16 @@ async function lookupSessionDirectory(client, sessionId, fallbackDirectory) {
|
|
|
45955
46651
|
}
|
|
45956
46652
|
return dir;
|
|
45957
46653
|
}
|
|
45958
|
-
async function lookupV2SessionDirectory(context, sessionId) {
|
|
46654
|
+
async function lookupV2SessionDirectory(context, sessionId, onLocation) {
|
|
45959
46655
|
let dir = null;
|
|
45960
46656
|
let failure;
|
|
45961
46657
|
try {
|
|
45962
46658
|
const session = await Effect.runPromise(Effect.timeout(context.session.get({ sessionID: sessionId }), V2_SESSION_LOOKUP_TIMEOUT_MS));
|
|
45963
46659
|
const directory = session?.location?.directory;
|
|
45964
|
-
if (typeof directory === "string" && directory.length > 0)
|
|
46660
|
+
if (typeof directory === "string" && directory.length > 0) {
|
|
45965
46661
|
dir = directory;
|
|
45966
|
-
|
|
46662
|
+
onLocation({ directory, workspaceID: session?.location?.workspaceID });
|
|
46663
|
+
} else
|
|
45967
46664
|
failure = "the session record has no location.directory";
|
|
45968
46665
|
} catch (err) {
|
|
45969
46666
|
failure = err instanceof Error ? err.message || err.name : String(err);
|
|
@@ -45973,10 +46670,10 @@ async function lookupV2SessionDirectory(context, sessionId) {
|
|
|
45973
46670
|
}
|
|
45974
46671
|
return dir;
|
|
45975
46672
|
}
|
|
45976
|
-
function setCache(sessionId, directory) {
|
|
46673
|
+
function setCache(sessionId, directory, location) {
|
|
45977
46674
|
if (cache.has(sessionId))
|
|
45978
46675
|
cache.delete(sessionId);
|
|
45979
|
-
cache.set(sessionId, { directory, recordedAt: Date.now() });
|
|
46676
|
+
cache.set(sessionId, { directory, location, recordedAt: Date.now() });
|
|
45980
46677
|
if (cache.size > CACHE_MAX_ENTRIES) {
|
|
45981
46678
|
const oldest = cache.keys().next().value;
|
|
45982
46679
|
if (oldest !== undefined)
|
|
@@ -47243,7 +47940,7 @@ async function trackV2BackgroundTask(ctx, runtime, taskId, startedEpoch) {
|
|
|
47243
47940
|
}
|
|
47244
47941
|
state.tasks.set(taskId, kill);
|
|
47245
47942
|
}
|
|
47246
|
-
async function killStoppedBackgroundTasks(client, sessionID, ctx, startedBeforeMs) {
|
|
47943
|
+
async function killStoppedBackgroundTasks(client, sessionID, ctx, startedBeforeMs, deletedEvent) {
|
|
47247
47944
|
const kills = [];
|
|
47248
47945
|
const visited = new Set;
|
|
47249
47946
|
const dispatch = (taskId, kill) => {
|
|
@@ -47263,10 +47960,11 @@ async function killStoppedBackgroundTasks(client, sessionID, ctx, startedBeforeM
|
|
|
47263
47960
|
dispatch(taskId, kill);
|
|
47264
47961
|
}
|
|
47265
47962
|
}
|
|
47266
|
-
|
|
47963
|
+
const directory = ctx ? deletedEvent ? getSessionDirectoryForDeletedEvent(client, sessionID, deletedEvent.location) : await getSessionDirectoryForEvent(client, sessionID, client.location.directory) : null;
|
|
47964
|
+
if (ctx && directory) {
|
|
47267
47965
|
const runtime = {
|
|
47268
47966
|
sessionID,
|
|
47269
|
-
directory
|
|
47967
|
+
directory,
|
|
47270
47968
|
directoryIsSessionRoot: true
|
|
47271
47969
|
};
|
|
47272
47970
|
try {
|
|
@@ -47340,7 +48038,7 @@ function registerV2SessionLifecycle(context, ctx) {
|
|
|
47340
48038
|
}
|
|
47341
48039
|
if (event.type === "session.deleted") {
|
|
47342
48040
|
const state = sessions.get(sessionID);
|
|
47343
|
-
const kills = killStoppedBackgroundTasks(context, sessionID, ctx);
|
|
48041
|
+
const kills = killStoppedBackgroundTasks(context, sessionID, ctx, undefined, event);
|
|
47344
48042
|
rememberDeleted(context, sessionID);
|
|
47345
48043
|
sessions.delete(sessionID);
|
|
47346
48044
|
releaseSessionState(sessionID);
|
|
@@ -47688,7 +48386,8 @@ ${BASH_RUNON_GUIDANCE}`, "");
|
|
|
47688
48386
|
const metadata = metadataUpdater(context);
|
|
47689
48387
|
const rawCommand = args.command;
|
|
47690
48388
|
const command = rawCommand;
|
|
47691
|
-
const
|
|
48389
|
+
const workdir = args.workdir;
|
|
48390
|
+
const cwd = workdir ?? context.directory;
|
|
47692
48391
|
const subagentStatus = await resolveSubagentStatus(ctx.client, context.sessionID, context.directory);
|
|
47693
48392
|
const isSubagent = subagentStatus === true;
|
|
47694
48393
|
const backgroundDisabled = !bashCfg.background;
|
|
@@ -47732,7 +48431,7 @@ ${BASH_RUNON_GUIDANCE}`, "");
|
|
|
47732
48431
|
data = await withPermissionLoop(ctx, context, {
|
|
47733
48432
|
command,
|
|
47734
48433
|
timeout: rawTimeout,
|
|
47735
|
-
workdir
|
|
48434
|
+
workdir,
|
|
47736
48435
|
env: shellEnv?.env ?? {},
|
|
47737
48436
|
description,
|
|
47738
48437
|
background: effectiveBackground,
|
|
@@ -47818,7 +48517,7 @@ ${BASH_RUNON_GUIDANCE}`, "");
|
|
|
47818
48517
|
return { output: rendered, title: uiTitle, metadata: metadataPayload };
|
|
47819
48518
|
}
|
|
47820
48519
|
const output = data.output ?? "";
|
|
47821
|
-
const rendered = usedHostFallback ? output : maybeAppendGrepSearchHint(output, command, aftSearchRegistered, projectRootFor(context));
|
|
48520
|
+
const rendered = usedHostFallback ? output : maybeAppendGrepSearchHint(output, command, aftSearchRegistered, projectRootFor(context), undefined, workdir);
|
|
47822
48521
|
const metadataPayload = foregroundMetadata(description, data, rendered);
|
|
47823
48522
|
await metadata(metadataPayload);
|
|
47824
48523
|
return {
|
|
@@ -47894,7 +48593,7 @@ async function formatBashStatusText(runtime, taskId, data, requestedOutputMode,
|
|
|
47894
48593
|
const status = data.status;
|
|
47895
48594
|
const exit = typeof data.exit_code === "number" ? ` (exit ${data.exit_code})` : "";
|
|
47896
48595
|
const dur = typeof data.duration_ms === "number" ? ` ${Math.round(data.duration_ms / 1000)}s` : "";
|
|
47897
|
-
let text = `Task ${taskId}: ${status}${exit}${dur}`;
|
|
48596
|
+
let text = formatUnknownPtyExit(taskId, data) ?? `Task ${taskId}: ${status}${exit}${dur}`;
|
|
47898
48597
|
if (typeof data.live_descendants_summary === "string") {
|
|
47899
48598
|
text += ` · ${data.live_descendants_summary}`;
|
|
47900
48599
|
}
|
|
@@ -49845,7 +50544,7 @@ function createDeleteTool(ctx) {
|
|
|
49845
50544
|
recursive
|
|
49846
50545
|
});
|
|
49847
50546
|
if (response.success === false) {
|
|
49848
|
-
throw
|
|
50547
|
+
throw toolErrorFromResponse("delete", response);
|
|
49849
50548
|
}
|
|
49850
50549
|
const deletedEntries = response.deleted ?? [];
|
|
49851
50550
|
const skipped = response.skipped_files ?? [];
|
|
@@ -51151,6 +51850,15 @@ function semanticTools(ctx) {
|
|
|
51151
51850
|
|
|
51152
51851
|
// src/tool-registration.ts
|
|
51153
51852
|
var V2_BUILTIN_REPLACEMENTS = new Set(["read", "edit", "write", "apply_patch"]);
|
|
51853
|
+
var V2_CODEMODE_NAMES = {
|
|
51854
|
+
read: "read",
|
|
51855
|
+
grep: "grep",
|
|
51856
|
+
glob: "glob",
|
|
51857
|
+
aft_search: "search",
|
|
51858
|
+
aft_outline: "outline",
|
|
51859
|
+
aft_zoom: "zoom",
|
|
51860
|
+
aft_callgraph: "callgraph"
|
|
51861
|
+
};
|
|
51154
51862
|
function openCodeEditSlotSurvives(config) {
|
|
51155
51863
|
return !resolvedDisabledTools(config).includes("edit");
|
|
51156
51864
|
}
|
|
@@ -51217,6 +51925,25 @@ function registerAftTools(context, location, definitions, consumers = {}) {
|
|
|
51217
51925
|
if (V2_BUILTIN_REPLACEMENTS.has(name))
|
|
51218
51926
|
editor.remove(projected.name);
|
|
51219
51927
|
editor.add(projected);
|
|
51928
|
+
const codeModeName = V2_CODEMODE_NAMES[name];
|
|
51929
|
+
if (codeModeName) {
|
|
51930
|
+
editor.add({
|
|
51931
|
+
name: codeModeName,
|
|
51932
|
+
get description() {
|
|
51933
|
+
return projected.description;
|
|
51934
|
+
},
|
|
51935
|
+
get input() {
|
|
51936
|
+
return projected.input;
|
|
51937
|
+
},
|
|
51938
|
+
options: {
|
|
51939
|
+
...projected.options,
|
|
51940
|
+
namespace: "aft.code",
|
|
51941
|
+
permission: projected.name,
|
|
51942
|
+
codemode: true
|
|
51943
|
+
},
|
|
51944
|
+
execute: projected.execute
|
|
51945
|
+
});
|
|
51946
|
+
}
|
|
51220
51947
|
}
|
|
51221
51948
|
});
|
|
51222
51949
|
}
|
|
@@ -51672,7 +52399,7 @@ function startOpenCodeLiveConfigReload(options) {
|
|
|
51672
52399
|
// src/notifications.ts
|
|
51673
52400
|
import { existsSync as existsSync17, readFileSync as readFileSync14 } from "node:fs";
|
|
51674
52401
|
import { homedir as homedir14, platform } from "node:os";
|
|
51675
|
-
import { join as
|
|
52402
|
+
import { join as join23 } from "node:path";
|
|
51676
52403
|
function isTuiMode() {
|
|
51677
52404
|
return process.env.OPENCODE_CLIENT === "cli";
|
|
51678
52405
|
}
|
|
@@ -51694,15 +52421,15 @@ function getDesktopStatePath() {
|
|
|
51694
52421
|
const os = platform();
|
|
51695
52422
|
const home = homedir14();
|
|
51696
52423
|
if (os === "darwin") {
|
|
51697
|
-
return
|
|
52424
|
+
return join23(home, "Library", "Application Support", "ai.opencode.desktop", "opencode.global.dat");
|
|
51698
52425
|
}
|
|
51699
52426
|
if (os === "linux") {
|
|
51700
|
-
const xdgConfig = process.env.XDG_CONFIG_HOME ||
|
|
51701
|
-
return
|
|
52427
|
+
const xdgConfig = process.env.XDG_CONFIG_HOME || join23(home, ".config");
|
|
52428
|
+
return join23(xdgConfig, "ai.opencode.desktop", "opencode.global.dat");
|
|
51702
52429
|
}
|
|
51703
52430
|
if (os === "win32") {
|
|
51704
|
-
const appData = process.env.APPDATA ||
|
|
51705
|
-
return
|
|
52431
|
+
const appData = process.env.APPDATA || join23(home, "AppData", "Roaming");
|
|
52432
|
+
return join23(appData, "ai.opencode.desktop", "opencode.global.dat");
|
|
51706
52433
|
}
|
|
51707
52434
|
return null;
|
|
51708
52435
|
}
|
|
@@ -52231,30 +52958,30 @@ import { dirname as dirname16 } from "node:path";
|
|
|
52231
52958
|
// src/hooks/auto-update-checker/cache.ts
|
|
52232
52959
|
import { cpSync, existsSync as existsSync19, mkdtempSync, readFileSync as readFileSync16, rmSync as rmSync7, writeFileSync as writeFileSync10 } from "node:fs";
|
|
52233
52960
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
52234
|
-
import { basename as basename5, dirname as dirname15, join as
|
|
52961
|
+
import { basename as basename5, dirname as dirname15, join as join26 } from "node:path";
|
|
52235
52962
|
var import_comment_json3 = __toESM(require_src2(), 1);
|
|
52236
52963
|
|
|
52237
52964
|
// src/hooks/auto-update-checker/checker.ts
|
|
52238
52965
|
import { existsSync as existsSync18, readFileSync as readFileSync15, statSync as statSync16, writeFileSync as writeFileSync9 } from "node:fs";
|
|
52239
52966
|
import { readFile as readFile2 } from "node:fs/promises";
|
|
52240
52967
|
import { homedir as homedir15 } from "node:os";
|
|
52241
|
-
import { dirname as dirname14, isAbsolute as
|
|
52968
|
+
import { dirname as dirname14, isAbsolute as isAbsolute13, join as join25, resolve as resolve16 } from "node:path";
|
|
52242
52969
|
import { fileURLToPath } from "node:url";
|
|
52243
52970
|
var import_comment_json2 = __toESM(require_src2(), 1);
|
|
52244
52971
|
|
|
52245
52972
|
// src/hooks/auto-update-checker/constants.ts
|
|
52246
|
-
import { join as
|
|
52973
|
+
import { join as join24 } from "node:path";
|
|
52247
52974
|
var PACKAGE_NAME = "@cortexkit/aft-opencode";
|
|
52248
52975
|
var NPM_REGISTRY_URL = "https://registry.npmjs.org";
|
|
52249
52976
|
var NPM_FETCH_TIMEOUT = 1e4;
|
|
52250
52977
|
function cacheDir() {
|
|
52251
|
-
return
|
|
52978
|
+
return join24(getOpenCodeCacheRoot(), "packages");
|
|
52252
52979
|
}
|
|
52253
52980
|
function userOpenCodeConfig() {
|
|
52254
|
-
return
|
|
52981
|
+
return join24(getOpenCodeConfigRoot(), "opencode.json");
|
|
52255
52982
|
}
|
|
52256
52983
|
function userOpenCodeConfigJsonc() {
|
|
52257
|
-
return
|
|
52984
|
+
return join24(getOpenCodeConfigRoot(), "opencode.jsonc");
|
|
52258
52985
|
}
|
|
52259
52986
|
|
|
52260
52987
|
// src/hooks/auto-update-checker/types.ts
|
|
@@ -52313,8 +53040,8 @@ function extractChannel(version) {
|
|
|
52313
53040
|
}
|
|
52314
53041
|
function getConfigPaths(directory) {
|
|
52315
53042
|
return [
|
|
52316
|
-
|
|
52317
|
-
|
|
53043
|
+
join25(directory, ".opencode", "opencode.json"),
|
|
53044
|
+
join25(directory, ".opencode", "opencode.jsonc"),
|
|
52318
53045
|
userOpenCodeConfig(),
|
|
52319
53046
|
userOpenCodeConfigJsonc()
|
|
52320
53047
|
];
|
|
@@ -52327,9 +53054,9 @@ function resolvePathPluginSpec(spec, configPath) {
|
|
|
52327
53054
|
return spec.replace(/^file:\/\//, "");
|
|
52328
53055
|
}
|
|
52329
53056
|
}
|
|
52330
|
-
if (
|
|
53057
|
+
if (isAbsolute13(spec) || /^[A-Za-z]:[\\/]/.test(spec))
|
|
52331
53058
|
return spec;
|
|
52332
|
-
return
|
|
53059
|
+
return resolve16(dirname14(configPath), spec);
|
|
52333
53060
|
}
|
|
52334
53061
|
function getLocalDevPath(directory) {
|
|
52335
53062
|
for (const configPath of getConfigPaths(directory)) {
|
|
@@ -52341,7 +53068,7 @@ function getLocalDevPath(directory) {
|
|
|
52341
53068
|
for (const entry of plugins) {
|
|
52342
53069
|
if (entry === PACKAGE_NAME || entry.startsWith(`${PACKAGE_NAME}@`))
|
|
52343
53070
|
continue;
|
|
52344
|
-
if (entry.startsWith("file://") || entry.startsWith(".") ||
|
|
53071
|
+
if (entry.startsWith("file://") || entry.startsWith(".") || isAbsolute13(entry)) {
|
|
52345
53072
|
const localPath = resolvePathPluginSpec(entry, configPath);
|
|
52346
53073
|
const pkgPath = findPackageJsonUp(localPath);
|
|
52347
53074
|
if (!pkgPath)
|
|
@@ -52360,7 +53087,7 @@ function findPackageJsonUp(startPath) {
|
|
|
52360
53087
|
const stat = statSync16(startPath);
|
|
52361
53088
|
let dir = stat.isDirectory() ? startPath : dirname14(startPath);
|
|
52362
53089
|
for (let i = 0;i < 10; i++) {
|
|
52363
|
-
const pkgPath =
|
|
53090
|
+
const pkgPath = join25(dir, "package.json");
|
|
52364
53091
|
if (existsSync18(pkgPath)) {
|
|
52365
53092
|
try {
|
|
52366
53093
|
const pkg = PackageJsonSchema.safeParse(JSON.parse(readFileSync15(pkgPath, "utf-8")));
|
|
@@ -52426,7 +53153,7 @@ function findPluginEntry(directory) {
|
|
|
52426
53153
|
}
|
|
52427
53154
|
var cachedPackageVersion = null;
|
|
52428
53155
|
function getSpecCachePackageJsonPath(spec) {
|
|
52429
|
-
return
|
|
53156
|
+
return join25(cacheDir(), spec, "node_modules", PACKAGE_NAME, "package.json");
|
|
52430
53157
|
}
|
|
52431
53158
|
function getCachedVersion(spec) {
|
|
52432
53159
|
if (!spec && cachedPackageVersion)
|
|
@@ -52435,7 +53162,7 @@ function getCachedVersion(spec) {
|
|
|
52435
53162
|
getCurrentRuntimePackageJsonPath(),
|
|
52436
53163
|
spec ? getSpecCachePackageJsonPath(spec) : null,
|
|
52437
53164
|
getSpecCachePackageJsonPath(`${PACKAGE_NAME}@latest`),
|
|
52438
|
-
|
|
53165
|
+
join25(getOpenCodeCacheRoot(), "node_modules", PACKAGE_NAME, "package.json")
|
|
52439
53166
|
].filter(isString);
|
|
52440
53167
|
for (const packageJsonPath of candidates) {
|
|
52441
53168
|
try {
|
|
@@ -52506,7 +53233,7 @@ async function registryWithoutNpm(directory) {
|
|
|
52506
53233
|
for (let current = directory;; current = dirname14(current)) {
|
|
52507
53234
|
if (scoped)
|
|
52508
53235
|
break;
|
|
52509
|
-
const path =
|
|
53236
|
+
const path = join25(current, ".npmrc");
|
|
52510
53237
|
visited.add(path);
|
|
52511
53238
|
const settings = await readRegistrySettings(path);
|
|
52512
53239
|
scoped ??= settings["@cortexkit:registry"];
|
|
@@ -52516,7 +53243,7 @@ async function registryWithoutNpm(directory) {
|
|
|
52516
53243
|
}
|
|
52517
53244
|
const explicitUserConfig = process.env.npm_config_userconfig ?? process.env.NPM_CONFIG_USERCONFIG;
|
|
52518
53245
|
const home = (process.platform === "win32" ? process.env.USERPROFILE : process.env.HOME) ?? homedir15();
|
|
52519
|
-
const userConfig = explicitUserConfig ??
|
|
53246
|
+
const userConfig = explicitUserConfig ?? join25(home, ".npmrc");
|
|
52520
53247
|
if (!scoped && !visited.has(userConfig)) {
|
|
52521
53248
|
const settings = await readRegistrySettings(userConfig, explicitUserConfig !== undefined);
|
|
52522
53249
|
scoped = settings["@cortexkit:registry"];
|
|
@@ -52538,14 +53265,14 @@ function validateRegistry(registry) {
|
|
|
52538
53265
|
}
|
|
52539
53266
|
var reportedRegistryFailures = new Set;
|
|
52540
53267
|
function reportRegistryFailure(directory) {
|
|
52541
|
-
const key =
|
|
53268
|
+
const key = resolve16(directory);
|
|
52542
53269
|
if (reportedRegistryFailures.has(key))
|
|
52543
53270
|
return;
|
|
52544
53271
|
reportedRegistryFailures.add(key);
|
|
52545
53272
|
debug2("[auto-update-checker] Configured npm registry could not be resolved or used; skipping update check.");
|
|
52546
53273
|
}
|
|
52547
53274
|
function resolveRegistry(directory) {
|
|
52548
|
-
const key =
|
|
53275
|
+
const key = resolve16(directory);
|
|
52549
53276
|
let pending = registryCache.get(key);
|
|
52550
53277
|
if (!pending) {
|
|
52551
53278
|
pending = (async () => {
|
|
@@ -52602,10 +53329,10 @@ async function getLatestVersion(channel = "latest", options = {}) {
|
|
|
52602
53329
|
var pendingSnapshots = new Map;
|
|
52603
53330
|
var quarantinedInstallDirs = new Set;
|
|
52604
53331
|
function createAutoUpdateSnapshot(installDir, packageJsonPath, packageName) {
|
|
52605
|
-
const packageDir =
|
|
52606
|
-
const lockfilePath =
|
|
52607
|
-
const tempDir = mkdtempSync(
|
|
52608
|
-
const stagedPackageDir = existsSync19(packageDir) ?
|
|
53332
|
+
const packageDir = join26(installDir, "node_modules", packageName);
|
|
53333
|
+
const lockfilePath = join26(installDir, "package-lock.json");
|
|
53334
|
+
const tempDir = mkdtempSync(join26(tmpdir4(), "aft-auto-update-"));
|
|
53335
|
+
const stagedPackageDir = existsSync19(packageDir) ? join26(tempDir, "package") : null;
|
|
52609
53336
|
if (stagedPackageDir)
|
|
52610
53337
|
cpSync(packageDir, stagedPackageDir, { recursive: true });
|
|
52611
53338
|
return {
|
|
@@ -52646,7 +53373,7 @@ function stripPackageNameFromPath(pathValue, packageName) {
|
|
|
52646
53373
|
return current;
|
|
52647
53374
|
}
|
|
52648
53375
|
function removeFromPackageLock(installDir, packageName) {
|
|
52649
|
-
const lockPath =
|
|
53376
|
+
const lockPath = join26(installDir, "package-lock.json");
|
|
52650
53377
|
if (!existsSync19(lockPath))
|
|
52651
53378
|
return false;
|
|
52652
53379
|
try {
|
|
@@ -52702,7 +53429,7 @@ function restorePendingSnapshot(installDir) {
|
|
|
52702
53429
|
restoreAutoUpdateSnapshot(snapshot);
|
|
52703
53430
|
}
|
|
52704
53431
|
function removeInstalledPackage(installDir, packageName) {
|
|
52705
|
-
const packageDir =
|
|
53432
|
+
const packageDir = join26(installDir, "node_modules", packageName);
|
|
52706
53433
|
if (!existsSync19(packageDir))
|
|
52707
53434
|
return false;
|
|
52708
53435
|
rmSync7(packageDir, { recursive: true, force: true });
|
|
@@ -52715,14 +53442,14 @@ function resolveInstallContext(runtimePackageJsonPath = getCurrentRuntimePackage
|
|
|
52715
53442
|
const nodeModulesDir = stripPackageNameFromPath(packageDir, PACKAGE_NAME);
|
|
52716
53443
|
if (nodeModulesDir && basename5(nodeModulesDir) === "node_modules") {
|
|
52717
53444
|
const installDir = dirname15(nodeModulesDir);
|
|
52718
|
-
const packageJsonPath =
|
|
53445
|
+
const packageJsonPath = join26(installDir, "package.json");
|
|
52719
53446
|
if (existsSync19(packageJsonPath))
|
|
52720
53447
|
return { installDir, packageJsonPath };
|
|
52721
53448
|
}
|
|
52722
53449
|
return null;
|
|
52723
53450
|
}
|
|
52724
53451
|
const cacheRoot = dirname15(cacheDir());
|
|
52725
|
-
const legacyPackageJsonPath =
|
|
53452
|
+
const legacyPackageJsonPath = join26(cacheRoot, "package.json");
|
|
52726
53453
|
if (existsSync19(legacyPackageJsonPath)) {
|
|
52727
53454
|
return { installDir: cacheRoot, packageJsonPath: legacyPackageJsonPath };
|
|
52728
53455
|
}
|
|
@@ -53348,16 +54075,16 @@ import {
|
|
|
53348
54075
|
writeFileSync as writeFileSync12
|
|
53349
54076
|
} from "node:fs";
|
|
53350
54077
|
import { createServer } from "node:http";
|
|
53351
|
-
import { dirname as dirname17, join as
|
|
54078
|
+
import { dirname as dirname17, join as join28 } from "node:path";
|
|
53352
54079
|
|
|
53353
54080
|
// src/shared/rpc-utils.ts
|
|
53354
|
-
import { join as
|
|
54081
|
+
import { join as join27 } from "node:path";
|
|
53355
54082
|
function projectHash(directory) {
|
|
53356
54083
|
return projectRootKeyHash(directory);
|
|
53357
54084
|
}
|
|
53358
54085
|
function rpcPortFileDir(storageDir, directory) {
|
|
53359
54086
|
const hash = projectHash(directory);
|
|
53360
|
-
return
|
|
54087
|
+
return join27(storageDir, "rpc", hash, "ports");
|
|
53361
54088
|
}
|
|
53362
54089
|
function isPidAlive(pid) {
|
|
53363
54090
|
if (typeof pid !== "number" || !Number.isInteger(pid) || pid <= 0)
|
|
@@ -53434,7 +54161,7 @@ class AftRpcServer {
|
|
|
53434
54161
|
constructor(storageDir, directory) {
|
|
53435
54162
|
this.portsDir = rpcPortFileDir(storageDir, directory);
|
|
53436
54163
|
this.instanceId = randomBytes5(8).toString("hex");
|
|
53437
|
-
this.portFilePath =
|
|
54164
|
+
this.portFilePath = join28(this.portsDir, `${this.instanceId}.json`);
|
|
53438
54165
|
}
|
|
53439
54166
|
handle(method, handler) {
|
|
53440
54167
|
this.handlers.set(method, handler);
|
|
@@ -53533,13 +54260,13 @@ class AftRpcServer {
|
|
|
53533
54260
|
const temporary = entry.endsWith(".json.tmp");
|
|
53534
54261
|
if (!temporary && !entry.endsWith(".json"))
|
|
53535
54262
|
continue;
|
|
53536
|
-
const filePath =
|
|
54263
|
+
const filePath = join28(this.portsDir, entry);
|
|
53537
54264
|
if (filePath === this.portFilePath)
|
|
53538
54265
|
continue;
|
|
53539
54266
|
try {
|
|
53540
54267
|
const record = parseRpcPortRecord(readFileSync18(filePath, "utf-8"));
|
|
53541
54268
|
if (record === null) {
|
|
53542
|
-
if (!temporary || Date.now() - statSync18(
|
|
54269
|
+
if (!temporary || Date.now() - statSync18(join28(this.portsDir, entry)).mtimeMs >= UNREADABLE_TMP_MAX_AGE_MS) {
|
|
53543
54270
|
unlinkSync7(filePath);
|
|
53544
54271
|
}
|
|
53545
54272
|
continue;
|
|
@@ -53978,11 +54705,11 @@ function coerceAftStatus(response) {
|
|
|
53978
54705
|
warm_entries: readNumber(symbolCache.warm_entries)
|
|
53979
54706
|
},
|
|
53980
54707
|
storage_dir: readNullableString(response.storage_dir),
|
|
53981
|
-
checkpoints_total:
|
|
54708
|
+
checkpoints_total: readOptionalNumber(response.checkpoints_total),
|
|
53982
54709
|
session: {
|
|
53983
54710
|
id: readString(session.id, "__default__"),
|
|
53984
54711
|
tracked_files: readNumber(session.tracked_files),
|
|
53985
|
-
checkpoints:
|
|
54712
|
+
checkpoints: readOptionalNumber(session.checkpoints)
|
|
53986
54713
|
},
|
|
53987
54714
|
compression: readCompression(response.compression),
|
|
53988
54715
|
status_bar: readStatusBar(response.status_bar),
|
|
@@ -54180,95 +54907,52 @@ function registerShutdownCleanup(fn) {
|
|
|
54180
54907
|
}
|
|
54181
54908
|
|
|
54182
54909
|
// src/workflow-hints.ts
|
|
54183
|
-
var HEADING = "
|
|
54910
|
+
var HEADING = "# Agent Foundational Toolkit";
|
|
54184
54911
|
function hashlineTagSourceHint(bashRewritesMintTags, isRegistered = () => true) {
|
|
54185
54912
|
return `**Hashline edit tags**: ${hashlineTagSourceSentence(bashRewritesMintTags, isRegistered)}`;
|
|
54186
54913
|
}
|
|
54187
54914
|
var HASHLINE_TAG_SOURCE_HINT = hashlineTagSourceHint(true);
|
|
54188
54915
|
function buildWorkflowHints(opts) {
|
|
54189
|
-
const
|
|
54190
|
-
const
|
|
54191
|
-
const
|
|
54192
|
-
const
|
|
54193
|
-
|
|
54194
|
-
|
|
54195
|
-
const hasZoom = !opts.disabledTools.has("aft_zoom");
|
|
54196
|
-
const readName = "read";
|
|
54197
|
-
const hasRead = !opts.disabledTools.has(readName);
|
|
54198
|
-
const hasGrep = !opts.disabledTools.has(grepName);
|
|
54199
|
-
const hasSearch = !opts.disabledTools.has("aft_search");
|
|
54200
|
-
const hasNavigate = !opts.disabledTools.has("aft_callgraph");
|
|
54201
|
-
const hasInspect = !opts.disabledTools.has("aft_inspect");
|
|
54202
|
-
const hasBash = !opts.disabledTools.has(bashName);
|
|
54203
|
-
const hasBgBash = hasBash && opts.bashBackgroundEnabled && !opts.disabledTools.has(bashStatusName);
|
|
54204
|
-
const hasWatch = !opts.disabledTools.has("bash_watch");
|
|
54205
|
-
const hasWrite = !opts.disabledTools.has(bashWriteName);
|
|
54206
|
-
if (hasBash && opts.bashCompressionEnabled) {
|
|
54207
|
-
sections.push([
|
|
54208
|
-
"**Test/build output**: bash output is auto-compressed for non-piped commands. Piped commands run verbatim and show the pipeline's output. For AFT's test/build summary, run the runner without filters:",
|
|
54209
|
-
"- `bun test | grep fail` → run `bun test`",
|
|
54210
|
-
"- `cargo test 2>&1 | tail -20` → run `cargo test`",
|
|
54211
|
-
"- `npm run build | head -50` → run `npm run build`"
|
|
54212
|
-
].join(`
|
|
54213
|
-
`));
|
|
54916
|
+
const has = (name) => !opts.disabledTools.has(name);
|
|
54917
|
+
const hasBash = has("bash");
|
|
54918
|
+
const hasBackground = hasBash && opts.bashBackgroundEnabled && has("bash_watch") && has("bash_status");
|
|
54919
|
+
const finding = [];
|
|
54920
|
+
if (has("aft_search")) {
|
|
54921
|
+
finding.push("start with aft_search; it takes concepts, identifiers, regex and literals.");
|
|
54214
54922
|
}
|
|
54215
|
-
if (
|
|
54216
|
-
|
|
54217
|
-
}
|
|
54218
|
-
if (hasOutline && (hasGrep || hasSearch) && (hasZoom || hasRead)) {
|
|
54219
|
-
const searchName = hasSearch ? "aft_search" : grepName;
|
|
54220
|
-
const locate = hasSearch ? "`aft_search` is the primary code-search tool: one call auto-routes concepts, identifiers, regex, error strings, and literals." : `\`${grepName}\` (the tool — indexed and ranked) locates code.`;
|
|
54221
|
-
const zoomSteer = hasZoom ? ", or aft_zoom" : "";
|
|
54222
|
-
const searchSteer = hasSearch ? `use aft_search (concepts, identifiers, regex, literals), ${readName}, aft_outline${zoomSteer} instead` : `use the ${grepName} tool, ${readName}, aft_outline${zoomSteer} instead`;
|
|
54223
|
-
const bashSteer = hasBash ? ` If you are about to run grep, rg, sed, awk, find, or cat through ${bashName} to locate or read code: STOP — ${searchSteer}.` : "";
|
|
54224
|
-
sections.push([
|
|
54225
|
-
`**Code exploration**: ${locate} Then \`aft_outline\` for structure → \`${hasZoom ? "aft_zoom" : readName}\` for symbol(s). DO NOT run \`grep\`/\`rg\`/\`find\`/\`sed\`/\`cat\` through \`bash\` to locate or read code — the bash path is unindexed, unranked, serial, and routinely surfaces the wrong hit. Keep \`bash\` for shell facts (git state, file metadata, processes).${bashSteer} Reflex translations:`,
|
|
54226
|
-
`- \`grep -rn "handleAuth" src/\` in bash → \`${searchName}({ query: "handleAuth" })\``,
|
|
54227
|
-
`- \`find . -name "*.ts" | xargs grep watcher\` in bash → \`${searchName}({ query: "watcher invalidation" })\` (concepts work too)`,
|
|
54228
|
-
`- \`sed -n '100,160p' app.ts\` / \`cat app.ts\` in bash → \`${readName}({ path: "app.ts", startLine: 100, endLine: 160 })\``
|
|
54229
|
-
].join(`
|
|
54230
|
-
`));
|
|
54231
|
-
}
|
|
54232
|
-
if (hasInspect) {
|
|
54233
|
-
sections.push("**Codebase health & diagnostics**: AFT does not surface compile/type errors automatically after edits — pull them with `aft_inspect`. Run it after a batch of edits and before you run tests or commit, when starting in unfamiliar code, or before a refactor/review. One call summarizes diagnostics (compile/type errors), TODOs, metrics, dead code, unused exports, and duplicates; pass `sections` for focused drill-down and `scope` to actively pull diagnostics for a specific file or directory. Its diagnostics are a fast checkpoint, not the authority — a clean `tsc` / `cargo check` / `pyright` run is the real gate. Dead code, unused exports, duplicates, cycles and complexity are computed only when you call aft_inspect, and the call waits until they are current; nothing refreshes them in the background, so run it again after further edits instead of polling.");
|
|
54234
|
-
sections.push("**AFT status bar**: tool results may end with a one-line health bar `[AFT E<errors> W<warnings> | T<todos>]` — an IDE-style glance that appears when a count changes. `E`/`W` are live LSP diagnostics for files touched this session (your universal compile-error signal across every language with an LSP). Dead code, unused exports and duplicates are not on the bar; run `aft_inspect` for them. A `?` in place of a number means that count has no value yet (not zero). When `E>0`, you likely just introduced errors; investigate before moving on.");
|
|
54235
|
-
}
|
|
54236
|
-
if (hasNavigate) {
|
|
54237
|
-
sections.push([
|
|
54238
|
-
"Use `aft_callgraph` for code-relationship questions instead of grep + read chains:",
|
|
54239
|
-
"- `callers` — find all call sites before changing a function signature",
|
|
54240
|
-
"- `impact` — blast radius (which functions/files will need updates)",
|
|
54241
|
-
"- `trace_to` — how execution reaches this code; each path runs back to a root labelled main, test, attribute, public API, or no caller found",
|
|
54242
|
-
"- `trace_to_symbol` — shortest call path from one symbol to another",
|
|
54243
|
-
"- `trace_data` — follow a value through assignments and parameters across files"
|
|
54244
|
-
].join(`
|
|
54245
|
-
`));
|
|
54923
|
+
if (has("aft_outline") && has("aft_zoom") && has("read")) {
|
|
54924
|
+
finding.push(`${finding.length ? "Then " : ""}aft_outline for structure, aft_zoom for named symbols, read for line ranges.`);
|
|
54246
54925
|
}
|
|
54247
|
-
if (
|
|
54248
|
-
|
|
54249
|
-
`**Long-running commands** (builds, installs, full test suites): run them in the FOREGROUND — use \`${bashName}({ command, wait: true })\` when you know it is long and need the result before anything else; if you send a new message, the wait detaches to background; otherwise omit \`wait\` so auto-promote can hand you a reminder while you work.`,
|
|
54250
|
-
"- `background: true` is ONLY for when you have OTHER useful work to do while it runs: start it, do the other work, and the completion reminder delivers the result (or spawn a subagent for the side work). Do NOT background a command and then immediately `bash_watch` it — that spends a whole extra turn waiting for something foreground returns in one.",
|
|
54251
|
-
"- `bash_watch` is for blocking on an ALREADY-backgrounded task once you've run out of parallel work (sync — the user can interrupt), or reacting to a specific early output line (async: background:true + pattern). Never loop `bash_status` to wait — it's a one-shot inspector."
|
|
54252
|
-
].join(`
|
|
54253
|
-
`));
|
|
54926
|
+
if (hasBash) {
|
|
54927
|
+
finding.push("Don't find or read code with grep, find, sed or cat in bash.");
|
|
54254
54928
|
}
|
|
54255
|
-
|
|
54256
|
-
|
|
54929
|
+
const commands = [];
|
|
54930
|
+
if (hasBash && opts.bashCompressionEnabled) {
|
|
54931
|
+
commands.push("don't pipe test or build output into tail, grep or head; AFT already shortens it.");
|
|
54257
54932
|
}
|
|
54258
|
-
if (
|
|
54259
|
-
|
|
54933
|
+
if (hasBackground) {
|
|
54934
|
+
commands.push("Pass wait: true when you need a long command's result before anything else; a new message from the user detaches the wait.", "Otherwise a long command moves to the background and a reminder brings its result.", "Block on it with bash_watch only when nothing else is left; bash_watch with background: true and a pattern tells you when a line appears.", "Never loop bash_status.");
|
|
54260
54935
|
}
|
|
54261
|
-
|
|
54936
|
+
const sections = [
|
|
54937
|
+
finding.length ? `**Finding code**: ${finding.join(" ")}` : "",
|
|
54938
|
+
has("aft_callgraph") ? "**Relationships**: aft_callgraph for callers, impact, and execution or data-flow traces." : "",
|
|
54939
|
+
has("aft_outline") && has("aft_zoom") ? "**Web pages**: aft_outline with a URL as target, then aft_zoom on a heading." : "",
|
|
54940
|
+
"",
|
|
54941
|
+
has("aft_inspect") ? "**After edits**: run aft_inspect for diagnostics; the project's typecheck and tests are the final check." : "",
|
|
54942
|
+
has("aft_inspect") ? "**Status bar**: `[AFT E.. W.. | T..]` appears when a count changes. E above 0 usually means your last edit broke something; `?` means unknown, not zero." : "",
|
|
54943
|
+
commands.length ? `**Commands**: ${commands.join(" ")}` : ""
|
|
54944
|
+
];
|
|
54945
|
+
const hashline = opts.hashlineEffective === true ? hashlineTagSourceHint(hasBash && opts.bashRewriteEnabled !== false, has) : "";
|
|
54946
|
+
if (!sections.some(Boolean) && !hashline)
|
|
54262
54947
|
return null;
|
|
54263
|
-
|
|
54264
|
-
|
|
54265
|
-
|
|
54266
|
-
**Parallel tool calls**: when several read-only operations are independent, emit them in ONE response instead of serializing — file reads, structure and symbol lookups, code search, diagnostics, and git status/diff/log. Sequence only when a call depends on a prior result or when a command mutates state.`);
|
|
54267
|
-
return `${HEADING}
|
|
54268
|
-
|
|
54269
|
-
${sections.join(`
|
|
54948
|
+
sections[3] = "**Parallel calls**: send independent read-only calls in one response.";
|
|
54949
|
+
const text = `${HEADING}
|
|
54270
54950
|
|
|
54951
|
+
${sections.filter(Boolean).join(`
|
|
54271
54952
|
`)}`;
|
|
54953
|
+
return hashline ? `${text}
|
|
54954
|
+
|
|
54955
|
+
${hashline}` : text;
|
|
54272
54956
|
}
|
|
54273
54957
|
function buildHintsFromConfig(config, disabledTools, hashlineEffective = false) {
|
|
54274
54958
|
const bashCfg = resolveBashConfig(config);
|
|
@@ -54330,12 +55014,12 @@ function throwSentinel(command) {
|
|
|
54330
55014
|
throw sentinel;
|
|
54331
55015
|
}
|
|
54332
55016
|
var PLUGIN_VERSION = resolvePluginVersion(import.meta.url);
|
|
54333
|
-
var ANNOUNCEMENT_VERSION = "0.
|
|
55017
|
+
var ANNOUNCEMENT_VERSION = "0.65.0";
|
|
54334
55018
|
var ANNOUNCEMENT_FEATURES = [
|
|
54335
|
-
"
|
|
54336
|
-
"
|
|
54337
|
-
"
|
|
54338
|
-
"
|
|
55019
|
+
"OpenCode 2: AFT's read-only tools also work inside Code Mode as `tools.aft.code.*`.",
|
|
55020
|
+
"TypeScript monorepos run one language server per TypeScript version instead of one per package; `lsp.max_servers` caps the total.",
|
|
55021
|
+
"Search and grep stay light on large growing files, and shell waits survive the computer going to sleep.",
|
|
55022
|
+
"`views.enabled`, `views.callgraph_copies` and `worktree.ram_overlay` are now refused in user config; `npx @cortexkit/aft doctor --fix` removes them."
|
|
54339
55023
|
];
|
|
54340
55024
|
var ANNOUNCEMENT_FOOTER = "Join us on Discord: https://discord.gg/DSa65w8wuf";
|
|
54341
55025
|
var plugin = async (input) => initializePluginForDirectory(input);
|
|
@@ -54705,14 +55389,19 @@ Install: ${getManualInstallHint()}`);
|
|
|
54705
55389
|
event: async (eventInput) => {
|
|
54706
55390
|
await autoUpdateEventHook(eventInput);
|
|
54707
55391
|
const eventType = eventInput.event.type;
|
|
54708
|
-
observeOpenCodeBgNotificationEvent(eventInput.event);
|
|
54709
55392
|
const sessionID = extractSessionID(eventInput.event.properties);
|
|
55393
|
+
let sessionDir = null;
|
|
55394
|
+
if (sessionID && (eventType === "session.created" || eventType === "session.idle" || eventType === "session.status")) {
|
|
55395
|
+
sessionDir = await getSessionDirectoryForEvent(input.client, sessionID, input.directory);
|
|
55396
|
+
if (!sessionDir)
|
|
55397
|
+
return;
|
|
55398
|
+
}
|
|
55399
|
+
observeOpenCodeBgNotificationEvent(eventInput.event);
|
|
54710
55400
|
if (eventType === "session.moved" && sessionID) {
|
|
54711
55401
|
clearSessionDirectory(sessionID);
|
|
54712
55402
|
return;
|
|
54713
55403
|
}
|
|
54714
|
-
if (eventType === "session.created" && sessionID) {
|
|
54715
|
-
const sessionDir = await getSessionDirectory(input.client, sessionID, input.directory) ?? input.directory;
|
|
55404
|
+
if (eventType === "session.created" && sessionID && sessionDir) {
|
|
54716
55405
|
observeFreshSessionStart(pool, sessionDir, sessionID, "new");
|
|
54717
55406
|
}
|
|
54718
55407
|
if (eventType === "session.deleted" && sessionID) {
|
|
@@ -54722,9 +55411,8 @@ Install: ${getManualInstallHint()}`);
|
|
|
54722
55411
|
}
|
|
54723
55412
|
if (eventType !== "session.idle")
|
|
54724
55413
|
return;
|
|
54725
|
-
if (!sessionID)
|
|
55414
|
+
if (!sessionID || !sessionDir)
|
|
54726
55415
|
return;
|
|
54727
|
-
const sessionDir = await getSessionDirectory(input.client, sessionID, input.directory) ?? input.directory;
|
|
54728
55416
|
if (!isProjectEnabled(sessionDir))
|
|
54729
55417
|
return;
|
|
54730
55418
|
await handleIdleBgCompletions({
|