@cortexkit/aft-opencode 0.17.3 → 0.18.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bg-notifications.d.ts +41 -0
- package/dist/bg-notifications.d.ts.map +1 -0
- package/dist/bridge.d.ts +9 -1
- package/dist/bridge.d.ts.map +1 -1
- package/dist/config.d.ts +27 -4
- package/dist/config.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1259 -495
- package/dist/logger.d.ts +9 -0
- package/dist/logger.d.ts.map +1 -1
- package/dist/lsp-auto-install.d.ts +2 -0
- package/dist/lsp-auto-install.d.ts.map +1 -1
- package/dist/lsp-github-install.d.ts +2 -0
- package/dist/lsp-github-install.d.ts.map +1 -1
- package/dist/notifications.d.ts.map +1 -1
- package/dist/patch-parser.d.ts.map +1 -1
- package/dist/shared/status.d.ts +2 -2
- package/dist/shared/status.d.ts.map +1 -1
- package/dist/tools/_shared.d.ts +2 -2
- package/dist/tools/_shared.d.ts.map +1 -1
- package/dist/tools/ast.d.ts.map +1 -1
- package/dist/tools/bash.d.ts +4 -0
- package/dist/tools/bash.d.ts.map +1 -0
- package/dist/tools/hoisted.d.ts.map +1 -1
- package/dist/tui.js +377 -11
- package/dist/types.d.ts +15 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +6 -6
- package/src/shared/status.ts +10 -8
- package/src/tui/index.tsx +13 -0
- package/src/tui/sidebar.tsx +331 -0
package/dist/index.js
CHANGED
|
@@ -4583,45 +4583,45 @@ var require_esprima = __commonJS((exports, module) => {
|
|
|
4583
4583
|
this.errors = [];
|
|
4584
4584
|
this.tolerant = false;
|
|
4585
4585
|
}
|
|
4586
|
-
ErrorHandler2.prototype.recordError = function(
|
|
4587
|
-
this.errors.push(
|
|
4586
|
+
ErrorHandler2.prototype.recordError = function(error2) {
|
|
4587
|
+
this.errors.push(error2);
|
|
4588
4588
|
};
|
|
4589
|
-
ErrorHandler2.prototype.tolerate = function(
|
|
4589
|
+
ErrorHandler2.prototype.tolerate = function(error2) {
|
|
4590
4590
|
if (this.tolerant) {
|
|
4591
|
-
this.recordError(
|
|
4591
|
+
this.recordError(error2);
|
|
4592
4592
|
} else {
|
|
4593
|
-
throw
|
|
4593
|
+
throw error2;
|
|
4594
4594
|
}
|
|
4595
4595
|
};
|
|
4596
4596
|
ErrorHandler2.prototype.constructError = function(msg, column) {
|
|
4597
|
-
var
|
|
4597
|
+
var error2 = new Error(msg);
|
|
4598
4598
|
try {
|
|
4599
|
-
throw
|
|
4599
|
+
throw error2;
|
|
4600
4600
|
} catch (base) {
|
|
4601
4601
|
if (Object.create && Object.defineProperty) {
|
|
4602
|
-
|
|
4603
|
-
Object.defineProperty(
|
|
4602
|
+
error2 = Object.create(base);
|
|
4603
|
+
Object.defineProperty(error2, "column", { value: column });
|
|
4604
4604
|
}
|
|
4605
4605
|
}
|
|
4606
|
-
return
|
|
4606
|
+
return error2;
|
|
4607
4607
|
};
|
|
4608
4608
|
ErrorHandler2.prototype.createError = function(index, line, col, description) {
|
|
4609
4609
|
var msg = "Line " + line + ": " + description;
|
|
4610
|
-
var
|
|
4611
|
-
|
|
4612
|
-
|
|
4613
|
-
|
|
4614
|
-
return
|
|
4610
|
+
var error2 = this.constructError(msg, col);
|
|
4611
|
+
error2.index = index;
|
|
4612
|
+
error2.lineNumber = line;
|
|
4613
|
+
error2.description = description;
|
|
4614
|
+
return error2;
|
|
4615
4615
|
};
|
|
4616
4616
|
ErrorHandler2.prototype.throwError = function(index, line, col, description) {
|
|
4617
4617
|
throw this.createError(index, line, col, description);
|
|
4618
4618
|
};
|
|
4619
4619
|
ErrorHandler2.prototype.tolerateError = function(index, line, col, description) {
|
|
4620
|
-
var
|
|
4620
|
+
var error2 = this.createError(index, line, col, description);
|
|
4621
4621
|
if (this.tolerant) {
|
|
4622
|
-
this.recordError(
|
|
4622
|
+
this.recordError(error2);
|
|
4623
4623
|
} else {
|
|
4624
|
-
throw
|
|
4624
|
+
throw error2;
|
|
4625
4625
|
}
|
|
4626
4626
|
};
|
|
4627
4627
|
return ErrorHandler2;
|
|
@@ -7291,19 +7291,19 @@ var require_parse = __commonJS((exports, module) => {
|
|
|
7291
7291
|
var symbolFor = (prefix) => Symbol.for(last_prop !== UNDEFINED ? prefix + COLON + last_prop : prefix);
|
|
7292
7292
|
var transform = (k, { value, context = {} }) => reviver ? reviver(k, value, context) : value;
|
|
7293
7293
|
var unexpected = () => {
|
|
7294
|
-
const
|
|
7295
|
-
Object.assign(
|
|
7294
|
+
const error2 = new SyntaxError(`Unexpected token '${current.value.slice(0, 1)}', "${current_code}" is not valid JSON`);
|
|
7295
|
+
Object.assign(error2, current.loc.start);
|
|
7296
7296
|
free();
|
|
7297
|
-
throw
|
|
7297
|
+
throw error2;
|
|
7298
7298
|
};
|
|
7299
7299
|
var unexpected_end = () => {
|
|
7300
|
-
const
|
|
7301
|
-
Object.assign(
|
|
7300
|
+
const error2 = new SyntaxError("Unexpected end of JSON input");
|
|
7301
|
+
Object.assign(error2, last ? last.loc.end : {
|
|
7302
7302
|
line: 1,
|
|
7303
7303
|
column: 0
|
|
7304
7304
|
});
|
|
7305
7305
|
free();
|
|
7306
|
-
throw
|
|
7306
|
+
throw error2;
|
|
7307
7307
|
};
|
|
7308
7308
|
var next = () => {
|
|
7309
7309
|
const new_token = tokens[++index];
|
|
@@ -7652,10 +7652,10 @@ var require_stringify = __commonJS((exports, module) => {
|
|
|
7652
7652
|
replacer = null;
|
|
7653
7653
|
indent = EMPTY;
|
|
7654
7654
|
};
|
|
7655
|
-
var
|
|
7655
|
+
var join2 = (one, two, gap) => one ? two ? one + two.trim() + LF + gap : one.trimRight() + repeat_line_breaks(Math.max(1, count_trailing_line_breaks(one, gap)), gap) : two ? two.trimRight() + repeat_line_breaks(Math.max(1, count_trailing_line_breaks(two, gap)), gap) : EMPTY;
|
|
7656
7656
|
var join_content = (inside, value, gap) => {
|
|
7657
7657
|
const comment = process_comments(value, PREFIX_BEFORE, gap + indent, true);
|
|
7658
|
-
return
|
|
7658
|
+
return join2(comment, inside, gap);
|
|
7659
7659
|
};
|
|
7660
7660
|
var stringify_string = (holder, key, value) => {
|
|
7661
7661
|
const raw = get_raw_string_literal(holder, key);
|
|
@@ -7677,13 +7677,13 @@ var require_stringify = __commonJS((exports, module) => {
|
|
|
7677
7677
|
if (i !== 0) {
|
|
7678
7678
|
inside += COMMA;
|
|
7679
7679
|
}
|
|
7680
|
-
const before =
|
|
7680
|
+
const before = join2(after_comma, process_comments(value, BEFORE(i), deeper_gap), deeper_gap);
|
|
7681
7681
|
inside += before || LF + deeper_gap;
|
|
7682
7682
|
inside += stringify(i, value, deeper_gap) || STR_NULL;
|
|
7683
7683
|
inside += process_comments(value, AFTER_VALUE(i), deeper_gap);
|
|
7684
7684
|
after_comma = process_comments(value, AFTER(i), deeper_gap);
|
|
7685
7685
|
}
|
|
7686
|
-
inside +=
|
|
7686
|
+
inside += join2(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
|
|
7687
7687
|
return BRACKET_OPEN + join_content(inside, value, gap) + BRACKET_CLOSE;
|
|
7688
7688
|
};
|
|
7689
7689
|
var object_stringify = (value, gap) => {
|
|
@@ -7704,13 +7704,13 @@ var require_stringify = __commonJS((exports, module) => {
|
|
|
7704
7704
|
inside += COMMA;
|
|
7705
7705
|
}
|
|
7706
7706
|
first = false;
|
|
7707
|
-
const before =
|
|
7707
|
+
const before = join2(after_comma, process_comments(value, BEFORE(key), deeper_gap), deeper_gap);
|
|
7708
7708
|
inside += before || LF + deeper_gap;
|
|
7709
7709
|
inside += quote(key) + process_comments(value, AFTER_PROP(key), deeper_gap) + COLON + process_comments(value, AFTER_COLON(key), deeper_gap) + SPACE + sv + process_comments(value, AFTER_VALUE(key), deeper_gap);
|
|
7710
7710
|
after_comma = process_comments(value, AFTER(key), deeper_gap);
|
|
7711
7711
|
};
|
|
7712
7712
|
keys.forEach(iteratee);
|
|
7713
|
-
inside +=
|
|
7713
|
+
inside += join2(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
|
|
7714
7714
|
return CURLY_BRACKET_OPEN + join_content(inside, value, gap) + CURLY_BRACKET_CLOSE;
|
|
7715
7715
|
};
|
|
7716
7716
|
function stringify(key, holder, gap) {
|
|
@@ -7803,14 +7803,297 @@ var require_src2 = __commonJS((exports, module) => {
|
|
|
7803
7803
|
});
|
|
7804
7804
|
|
|
7805
7805
|
// src/index.ts
|
|
7806
|
-
import { existsSync as existsSync13, mkdirSync as mkdirSync10, readFileSync as readFileSync9, writeFileSync as
|
|
7806
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync10, readFileSync as readFileSync9, writeFileSync as writeFileSync10 } from "fs";
|
|
7807
7807
|
import { createRequire as createRequire2 } from "module";
|
|
7808
7808
|
import { homedir as homedir10 } from "os";
|
|
7809
7809
|
import { join as join19 } from "path";
|
|
7810
7810
|
|
|
7811
|
+
// src/logger.ts
|
|
7812
|
+
import * as fs from "fs";
|
|
7813
|
+
import * as os from "os";
|
|
7814
|
+
import * as path from "path";
|
|
7815
|
+
var TAG = "[aft-plugin]";
|
|
7816
|
+
var logFile = path.join(os.tmpdir(), "aft-plugin.log");
|
|
7817
|
+
var useStderr = process.env.AFT_LOG_STDERR === "1";
|
|
7818
|
+
var buffer = [];
|
|
7819
|
+
var flushTimer = null;
|
|
7820
|
+
var FLUSH_INTERVAL_MS = 500;
|
|
7821
|
+
var BUFFER_SIZE_LIMIT = 50;
|
|
7822
|
+
function flush() {
|
|
7823
|
+
if (buffer.length === 0)
|
|
7824
|
+
return;
|
|
7825
|
+
const data = buffer.join("");
|
|
7826
|
+
buffer = [];
|
|
7827
|
+
try {
|
|
7828
|
+
if (useStderr) {
|
|
7829
|
+
process.stderr.write(data);
|
|
7830
|
+
} else {
|
|
7831
|
+
fs.appendFileSync(logFile, data);
|
|
7832
|
+
}
|
|
7833
|
+
} catch {}
|
|
7834
|
+
}
|
|
7835
|
+
function scheduleFlush() {
|
|
7836
|
+
if (flushTimer)
|
|
7837
|
+
return;
|
|
7838
|
+
flushTimer = setTimeout(() => {
|
|
7839
|
+
flushTimer = null;
|
|
7840
|
+
flush();
|
|
7841
|
+
}, FLUSH_INTERVAL_MS);
|
|
7842
|
+
if (flushTimer && typeof flushTimer === "object" && "unref" in flushTimer) {
|
|
7843
|
+
flushTimer.unref();
|
|
7844
|
+
}
|
|
7845
|
+
}
|
|
7846
|
+
function write(level, message, data, sessionId) {
|
|
7847
|
+
try {
|
|
7848
|
+
const timestamp = new Date().toISOString();
|
|
7849
|
+
const serialized = data === undefined ? "" : ` ${JSON.stringify(data)}`;
|
|
7850
|
+
const sessionPrefix = sessionId ? ` [${sessionId}]` : "";
|
|
7851
|
+
const line = `[${timestamp}] ${level} ${TAG}${sessionPrefix} ${message}${serialized}
|
|
7852
|
+
`;
|
|
7853
|
+
if (useStderr) {
|
|
7854
|
+
process.stderr.write(line);
|
|
7855
|
+
return;
|
|
7856
|
+
}
|
|
7857
|
+
buffer.push(line);
|
|
7858
|
+
if (buffer.length >= BUFFER_SIZE_LIMIT) {
|
|
7859
|
+
flush();
|
|
7860
|
+
} else {
|
|
7861
|
+
scheduleFlush();
|
|
7862
|
+
}
|
|
7863
|
+
} catch {}
|
|
7864
|
+
}
|
|
7865
|
+
function log(message, data) {
|
|
7866
|
+
write("INFO", message, data);
|
|
7867
|
+
}
|
|
7868
|
+
function warn(message, data) {
|
|
7869
|
+
write("WARN", message, data);
|
|
7870
|
+
}
|
|
7871
|
+
function error(message, data) {
|
|
7872
|
+
write("ERROR", message, data);
|
|
7873
|
+
}
|
|
7874
|
+
function sessionWarn(sessionId, message, data) {
|
|
7875
|
+
write("WARN", message, data, sessionId);
|
|
7876
|
+
}
|
|
7877
|
+
function getLogFilePath() {
|
|
7878
|
+
return logFile;
|
|
7879
|
+
}
|
|
7880
|
+
|
|
7881
|
+
// src/bg-notifications.ts
|
|
7882
|
+
var sessionBgStates = new Map;
|
|
7883
|
+
var SESSION_BG_STATE_IDLE_TTL_MS = 60 * 60 * 1000;
|
|
7884
|
+
var DEBOUNCE_STEP_MS = 200;
|
|
7885
|
+
var DEBOUNCE_CAP_MS = 1000;
|
|
7886
|
+
var DEFAULT_SESSION_ID = "__default__";
|
|
7887
|
+
var LOG_PREFIX = "[aft-plugin] bg-notifications:";
|
|
7888
|
+
function trackBgTask(sessionID, taskId) {
|
|
7889
|
+
stateFor(sessionID).outstandingTaskIds.add(taskId);
|
|
7890
|
+
}
|
|
7891
|
+
function ingestBgCompletions(sessionID, completions) {
|
|
7892
|
+
if (!Array.isArray(completions) || completions.length === 0)
|
|
7893
|
+
return [];
|
|
7894
|
+
const state = stateFor(sessionID);
|
|
7895
|
+
const accepted = [];
|
|
7896
|
+
for (const completion of completions) {
|
|
7897
|
+
if (!isBgCompletion(completion))
|
|
7898
|
+
continue;
|
|
7899
|
+
if (!state.outstandingTaskIds.has(completion.task_id))
|
|
7900
|
+
continue;
|
|
7901
|
+
state.outstandingTaskIds.delete(completion.task_id);
|
|
7902
|
+
if (!state.pendingCompletions.some((pending) => pending.task_id === completion.task_id) && !accepted.some((pending) => pending.task_id === completion.task_id)) {
|
|
7903
|
+
accepted.push(completion);
|
|
7904
|
+
}
|
|
7905
|
+
}
|
|
7906
|
+
state.pendingCompletions.push(...accepted);
|
|
7907
|
+
return accepted;
|
|
7908
|
+
}
|
|
7909
|
+
async function appendInTurnBgCompletions(drainContext, output) {
|
|
7910
|
+
if (!output)
|
|
7911
|
+
return;
|
|
7912
|
+
const state = stateFor(drainContext.sessionID);
|
|
7913
|
+
if (state.outstandingTaskIds.size === 0 && state.pendingCompletions.length === 0)
|
|
7914
|
+
return;
|
|
7915
|
+
if (state.outstandingTaskIds.size > 0) {
|
|
7916
|
+
await drainCompletions(drainContext);
|
|
7917
|
+
}
|
|
7918
|
+
if (state.pendingCompletions.length === 0)
|
|
7919
|
+
return;
|
|
7920
|
+
const reminder = formatSystemReminder(state.pendingCompletions);
|
|
7921
|
+
output.output = appendReminder(output.output ?? "", reminder);
|
|
7922
|
+
state.pendingCompletions = [];
|
|
7923
|
+
}
|
|
7924
|
+
async function handleIdleBgCompletions(drainContext) {
|
|
7925
|
+
const state = stateFor(drainContext.sessionID);
|
|
7926
|
+
if (state.wakeFiredThisIdle)
|
|
7927
|
+
return;
|
|
7928
|
+
if (state.outstandingTaskIds.size > 0) {
|
|
7929
|
+
await drainCompletions(drainContext);
|
|
7930
|
+
}
|
|
7931
|
+
if (state.pendingCompletions.length === 0)
|
|
7932
|
+
return;
|
|
7933
|
+
scheduleWake(state, async (reminder) => {
|
|
7934
|
+
try {
|
|
7935
|
+
const client = drainContext.client;
|
|
7936
|
+
if (typeof client.session?.promptAsync !== "function") {
|
|
7937
|
+
throw new Error("client.session.promptAsync is unavailable");
|
|
7938
|
+
}
|
|
7939
|
+
await client.session.promptAsync({
|
|
7940
|
+
path: { id: drainContext.sessionID },
|
|
7941
|
+
body: {
|
|
7942
|
+
noReply: false,
|
|
7943
|
+
parts: [{ type: "text", text: reminder }]
|
|
7944
|
+
}
|
|
7945
|
+
});
|
|
7946
|
+
} catch (err) {
|
|
7947
|
+
warn(`${LOG_PREFIX} wake send failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
7948
|
+
}
|
|
7949
|
+
});
|
|
7950
|
+
}
|
|
7951
|
+
function resetBgWake(sessionID) {
|
|
7952
|
+
stateFor(sessionID).wakeFiredThisIdle = false;
|
|
7953
|
+
}
|
|
7954
|
+
function formatSystemReminder(completions) {
|
|
7955
|
+
const bullets = completions.map((completion) => `- ${formatCompletion(completion)}`).join(`
|
|
7956
|
+
`);
|
|
7957
|
+
return `<system-reminder>
|
|
7958
|
+
[BACKGROUND BASH COMPLETED]
|
|
7959
|
+
${bullets}
|
|
7960
|
+
|
|
7961
|
+
Use bash_status({ task_id: "..." }) to retrieve full output.
|
|
7962
|
+
</system-reminder>`;
|
|
7963
|
+
}
|
|
7964
|
+
function extractSessionID(value) {
|
|
7965
|
+
if (!value || typeof value !== "object")
|
|
7966
|
+
return;
|
|
7967
|
+
const record = value;
|
|
7968
|
+
for (const key of ["sessionID", "sessionId", "id"]) {
|
|
7969
|
+
if (typeof record[key] === "string")
|
|
7970
|
+
return record[key];
|
|
7971
|
+
}
|
|
7972
|
+
const info = record.info;
|
|
7973
|
+
if (info && typeof info === "object") {
|
|
7974
|
+
const nested = info;
|
|
7975
|
+
for (const key of ["sessionID", "sessionId", "id"]) {
|
|
7976
|
+
if (typeof nested[key] === "string")
|
|
7977
|
+
return nested[key];
|
|
7978
|
+
}
|
|
7979
|
+
}
|
|
7980
|
+
return;
|
|
7981
|
+
}
|
|
7982
|
+
async function drainCompletions({ ctx, directory, sessionID }) {
|
|
7983
|
+
try {
|
|
7984
|
+
const bridge = ctx.pool.getAnyActiveBridge(directory) ?? ctx.pool.getBridge(directory);
|
|
7985
|
+
const response = await bridge.send("bash_drain_completions", { session_id: sessionID });
|
|
7986
|
+
if (response.success === false) {
|
|
7987
|
+
warn(`${LOG_PREFIX} drain failed: ${String(response.message ?? "unknown error")}`);
|
|
7988
|
+
return;
|
|
7989
|
+
}
|
|
7990
|
+
ingestBgCompletions(sessionID, response.bg_completions);
|
|
7991
|
+
} catch (err) {
|
|
7992
|
+
warn(`${LOG_PREFIX} drain failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
7993
|
+
}
|
|
7994
|
+
}
|
|
7995
|
+
function scheduleWake(state, sendWake) {
|
|
7996
|
+
const now = Date.now();
|
|
7997
|
+
if (state.debounceTimer && state.pendingCompletions.length <= state.scheduledCompletionCount) {
|
|
7998
|
+
return;
|
|
7999
|
+
}
|
|
8000
|
+
if (state.firstCompletionAt === null) {
|
|
8001
|
+
state.firstCompletionAt = now;
|
|
8002
|
+
state.scheduledFireAt = now + DEBOUNCE_STEP_MS;
|
|
8003
|
+
} else {
|
|
8004
|
+
const previousFireAt = state.scheduledFireAt ?? now;
|
|
8005
|
+
state.scheduledFireAt = Math.min(previousFireAt + DEBOUNCE_STEP_MS, state.firstCompletionAt + DEBOUNCE_CAP_MS);
|
|
8006
|
+
}
|
|
8007
|
+
state.scheduledCompletionCount = state.pendingCompletions.length;
|
|
8008
|
+
if (state.debounceTimer)
|
|
8009
|
+
clearTimeout(state.debounceTimer);
|
|
8010
|
+
const delay = Math.max(0, (state.scheduledFireAt ?? now) - now);
|
|
8011
|
+
state.debounceTimer = setTimeout(() => {
|
|
8012
|
+
const reminder = formatSystemReminder(state.pendingCompletions);
|
|
8013
|
+
state.pendingCompletions = [];
|
|
8014
|
+
state.debounceTimer = null;
|
|
8015
|
+
state.wakeFiredThisIdle = true;
|
|
8016
|
+
state.firstCompletionAt = null;
|
|
8017
|
+
state.scheduledFireAt = null;
|
|
8018
|
+
state.scheduledCompletionCount = 0;
|
|
8019
|
+
sendWake(reminder);
|
|
8020
|
+
}, delay);
|
|
8021
|
+
state.debounceTimer.unref?.();
|
|
8022
|
+
}
|
|
8023
|
+
function stateFor(sessionID) {
|
|
8024
|
+
const now = Date.now();
|
|
8025
|
+
cleanupIdleSessionStates(now);
|
|
8026
|
+
const key = sessionID || DEFAULT_SESSION_ID;
|
|
8027
|
+
let state = sessionBgStates.get(key);
|
|
8028
|
+
if (!state) {
|
|
8029
|
+
state = {
|
|
8030
|
+
outstandingTaskIds: new Set,
|
|
8031
|
+
pendingCompletions: [],
|
|
8032
|
+
debounceTimer: null,
|
|
8033
|
+
wakeFiredThisIdle: false,
|
|
8034
|
+
firstCompletionAt: null,
|
|
8035
|
+
scheduledFireAt: null,
|
|
8036
|
+
scheduledCompletionCount: 0,
|
|
8037
|
+
lastSeenAt: now
|
|
8038
|
+
};
|
|
8039
|
+
sessionBgStates.set(key, state);
|
|
8040
|
+
} else {
|
|
8041
|
+
state.lastSeenAt = now;
|
|
8042
|
+
}
|
|
8043
|
+
return state;
|
|
8044
|
+
}
|
|
8045
|
+
function cleanupIdleSessionStates(now) {
|
|
8046
|
+
const cutoff = now - SESSION_BG_STATE_IDLE_TTL_MS;
|
|
8047
|
+
for (const [sessionID, state] of sessionBgStates) {
|
|
8048
|
+
if (state.outstandingTaskIds.size > 0)
|
|
8049
|
+
continue;
|
|
8050
|
+
if (state.lastSeenAt >= cutoff)
|
|
8051
|
+
continue;
|
|
8052
|
+
if (state.debounceTimer)
|
|
8053
|
+
clearTimeout(state.debounceTimer);
|
|
8054
|
+
sessionBgStates.delete(sessionID);
|
|
8055
|
+
}
|
|
8056
|
+
}
|
|
8057
|
+
function isBgCompletion(value) {
|
|
8058
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
8059
|
+
return false;
|
|
8060
|
+
const completion = value;
|
|
8061
|
+
return typeof completion.task_id === "string" && typeof completion.status === "string" && (typeof completion.exit_code === "number" || completion.exit_code === null) && typeof completion.command === "string";
|
|
8062
|
+
}
|
|
8063
|
+
function appendReminder(output, reminder) {
|
|
8064
|
+
return output.length > 0 ? `${output}
|
|
8065
|
+
|
|
8066
|
+
${reminder}` : reminder;
|
|
8067
|
+
}
|
|
8068
|
+
function formatCompletion(completion) {
|
|
8069
|
+
const status = formatStatus(completion);
|
|
8070
|
+
const duration = formatDuration(completion);
|
|
8071
|
+
return `task ${completion.task_id} (${status}${duration ? `, ${duration}` : ""}): ${completion.command}`;
|
|
8072
|
+
}
|
|
8073
|
+
function formatStatus(completion) {
|
|
8074
|
+
if (completion.status === "timeout")
|
|
8075
|
+
return "timed out";
|
|
8076
|
+
if (completion.status === "killed")
|
|
8077
|
+
return "killed";
|
|
8078
|
+
if (completion.exit_code !== null)
|
|
8079
|
+
return `exit ${completion.exit_code}`;
|
|
8080
|
+
return completion.status;
|
|
8081
|
+
}
|
|
8082
|
+
function formatDuration(completion) {
|
|
8083
|
+
const raw = completion.duration_ms ?? completion.runtime_ms ?? completion.runtime;
|
|
8084
|
+
if (typeof raw !== "number" || !Number.isFinite(raw) || raw < 0)
|
|
8085
|
+
return null;
|
|
8086
|
+
if (raw < 1000)
|
|
8087
|
+
return `${Math.round(raw)}ms`;
|
|
8088
|
+
const totalSeconds = Math.round(raw / 1000);
|
|
8089
|
+
const minutes = Math.floor(totalSeconds / 60);
|
|
8090
|
+
const seconds = totalSeconds % 60;
|
|
8091
|
+
return minutes > 0 ? `${minutes}m ${seconds}s` : `${seconds}s`;
|
|
8092
|
+
}
|
|
8093
|
+
|
|
7811
8094
|
// src/config.ts
|
|
7812
8095
|
var import_comment_json = __toESM(require_src2(), 1);
|
|
7813
|
-
import { existsSync, readFileSync } from "fs";
|
|
8096
|
+
import { existsSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "fs";
|
|
7814
8097
|
import { homedir } from "os";
|
|
7815
8098
|
import { join as join2 } from "path";
|
|
7816
8099
|
|
|
@@ -8579,10 +8862,10 @@ function mergeDefs(...defs) {
|
|
|
8579
8862
|
function cloneDef(schema) {
|
|
8580
8863
|
return mergeDefs(schema._zod.def);
|
|
8581
8864
|
}
|
|
8582
|
-
function getElementAtPath(obj,
|
|
8583
|
-
if (!
|
|
8865
|
+
function getElementAtPath(obj, path2) {
|
|
8866
|
+
if (!path2)
|
|
8584
8867
|
return obj;
|
|
8585
|
-
return
|
|
8868
|
+
return path2.reduce((acc, key) => acc?.[key], obj);
|
|
8586
8869
|
}
|
|
8587
8870
|
function promiseAllObject(promisesObj) {
|
|
8588
8871
|
const keys = Object.keys(promisesObj);
|
|
@@ -8963,11 +9246,11 @@ function aborted(x, startIndex = 0) {
|
|
|
8963
9246
|
}
|
|
8964
9247
|
return false;
|
|
8965
9248
|
}
|
|
8966
|
-
function prefixIssues(
|
|
9249
|
+
function prefixIssues(path2, issues) {
|
|
8967
9250
|
return issues.map((iss) => {
|
|
8968
9251
|
var _a;
|
|
8969
9252
|
(_a = iss).path ?? (_a.path = []);
|
|
8970
|
-
iss.path.unshift(
|
|
9253
|
+
iss.path.unshift(path2);
|
|
8971
9254
|
return iss;
|
|
8972
9255
|
});
|
|
8973
9256
|
}
|
|
@@ -9102,10 +9385,10 @@ var initializer = (inst, def) => {
|
|
|
9102
9385
|
};
|
|
9103
9386
|
var $ZodError = $constructor("$ZodError", initializer);
|
|
9104
9387
|
var $ZodRealError = $constructor("$ZodError", initializer, { Parent: Error });
|
|
9105
|
-
function flattenError(
|
|
9388
|
+
function flattenError(error2, mapper = (issue2) => issue2.message) {
|
|
9106
9389
|
const fieldErrors = {};
|
|
9107
9390
|
const formErrors = [];
|
|
9108
|
-
for (const sub of
|
|
9391
|
+
for (const sub of error2.issues) {
|
|
9109
9392
|
if (sub.path.length > 0) {
|
|
9110
9393
|
fieldErrors[sub.path[0]] = fieldErrors[sub.path[0]] || [];
|
|
9111
9394
|
fieldErrors[sub.path[0]].push(mapper(sub));
|
|
@@ -9115,10 +9398,10 @@ function flattenError(error, mapper = (issue2) => issue2.message) {
|
|
|
9115
9398
|
}
|
|
9116
9399
|
return { formErrors, fieldErrors };
|
|
9117
9400
|
}
|
|
9118
|
-
function formatError(
|
|
9401
|
+
function formatError(error2, mapper = (issue2) => issue2.message) {
|
|
9119
9402
|
const fieldErrors = { _errors: [] };
|
|
9120
|
-
const processError = (
|
|
9121
|
-
for (const issue2 of
|
|
9403
|
+
const processError = (error3) => {
|
|
9404
|
+
for (const issue2 of error3.issues) {
|
|
9122
9405
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
9123
9406
|
issue2.errors.map((issues) => processError({ issues }));
|
|
9124
9407
|
} else if (issue2.code === "invalid_key") {
|
|
@@ -9145,14 +9428,14 @@ function formatError(error, mapper = (issue2) => issue2.message) {
|
|
|
9145
9428
|
}
|
|
9146
9429
|
}
|
|
9147
9430
|
};
|
|
9148
|
-
processError(
|
|
9431
|
+
processError(error2);
|
|
9149
9432
|
return fieldErrors;
|
|
9150
9433
|
}
|
|
9151
|
-
function treeifyError(
|
|
9434
|
+
function treeifyError(error2, mapper = (issue2) => issue2.message) {
|
|
9152
9435
|
const result = { errors: [] };
|
|
9153
|
-
const processError = (
|
|
9436
|
+
const processError = (error3, path2 = []) => {
|
|
9154
9437
|
var _a, _b;
|
|
9155
|
-
for (const issue2 of
|
|
9438
|
+
for (const issue2 of error3.issues) {
|
|
9156
9439
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
9157
9440
|
issue2.errors.map((issues) => processError({ issues }, issue2.path));
|
|
9158
9441
|
} else if (issue2.code === "invalid_key") {
|
|
@@ -9160,7 +9443,7 @@ function treeifyError(error, mapper = (issue2) => issue2.message) {
|
|
|
9160
9443
|
} else if (issue2.code === "invalid_element") {
|
|
9161
9444
|
processError({ issues: issue2.issues }, issue2.path);
|
|
9162
9445
|
} else {
|
|
9163
|
-
const fullpath = [...
|
|
9446
|
+
const fullpath = [...path2, ...issue2.path];
|
|
9164
9447
|
if (fullpath.length === 0) {
|
|
9165
9448
|
result.errors.push(mapper(issue2));
|
|
9166
9449
|
continue;
|
|
@@ -9187,13 +9470,13 @@ function treeifyError(error, mapper = (issue2) => issue2.message) {
|
|
|
9187
9470
|
}
|
|
9188
9471
|
}
|
|
9189
9472
|
};
|
|
9190
|
-
processError(
|
|
9473
|
+
processError(error2);
|
|
9191
9474
|
return result;
|
|
9192
9475
|
}
|
|
9193
9476
|
function toDotPath(_path) {
|
|
9194
9477
|
const segs = [];
|
|
9195
|
-
const
|
|
9196
|
-
for (const seg of
|
|
9478
|
+
const path2 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
9479
|
+
for (const seg of path2) {
|
|
9197
9480
|
if (typeof seg === "number")
|
|
9198
9481
|
segs.push(`[${seg}]`);
|
|
9199
9482
|
else if (typeof seg === "symbol")
|
|
@@ -9208,9 +9491,9 @@ function toDotPath(_path) {
|
|
|
9208
9491
|
}
|
|
9209
9492
|
return segs.join("");
|
|
9210
9493
|
}
|
|
9211
|
-
function prettifyError(
|
|
9494
|
+
function prettifyError(error2) {
|
|
9212
9495
|
const lines = [];
|
|
9213
|
-
const issues = [...
|
|
9496
|
+
const issues = [...error2.issues].sort((a, b) => (a.path ?? []).length - (b.path ?? []).length);
|
|
9214
9497
|
for (const issue2 of issues) {
|
|
9215
9498
|
lines.push(`\u2716 ${issue2.message}`);
|
|
9216
9499
|
if (issue2.path?.length)
|
|
@@ -12073,7 +12356,7 @@ __export(exports_locales, {
|
|
|
12073
12356
|
});
|
|
12074
12357
|
|
|
12075
12358
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/ar.js
|
|
12076
|
-
var
|
|
12359
|
+
var error2 = () => {
|
|
12077
12360
|
const Sizable = {
|
|
12078
12361
|
string: { unit: "\u062D\u0631\u0641", verb: "\u0623\u0646 \u064A\u062D\u0648\u064A" },
|
|
12079
12362
|
file: { unit: "\u0628\u0627\u064A\u062A", verb: "\u0623\u0646 \u064A\u062D\u0648\u064A" },
|
|
@@ -12175,11 +12458,11 @@ var error = () => {
|
|
|
12175
12458
|
};
|
|
12176
12459
|
function ar_default() {
|
|
12177
12460
|
return {
|
|
12178
|
-
localeError:
|
|
12461
|
+
localeError: error2()
|
|
12179
12462
|
};
|
|
12180
12463
|
}
|
|
12181
12464
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/az.js
|
|
12182
|
-
var
|
|
12465
|
+
var error3 = () => {
|
|
12183
12466
|
const Sizable = {
|
|
12184
12467
|
string: { unit: "simvol", verb: "olmal\u0131d\u0131r" },
|
|
12185
12468
|
file: { unit: "bayt", verb: "olmal\u0131d\u0131r" },
|
|
@@ -12280,7 +12563,7 @@ var error2 = () => {
|
|
|
12280
12563
|
};
|
|
12281
12564
|
function az_default() {
|
|
12282
12565
|
return {
|
|
12283
|
-
localeError:
|
|
12566
|
+
localeError: error3()
|
|
12284
12567
|
};
|
|
12285
12568
|
}
|
|
12286
12569
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/be.js
|
|
@@ -12299,7 +12582,7 @@ function getBelarusianPlural(count, one, few, many) {
|
|
|
12299
12582
|
}
|
|
12300
12583
|
return many;
|
|
12301
12584
|
}
|
|
12302
|
-
var
|
|
12585
|
+
var error4 = () => {
|
|
12303
12586
|
const Sizable = {
|
|
12304
12587
|
string: {
|
|
12305
12588
|
unit: {
|
|
@@ -12436,11 +12719,11 @@ var error3 = () => {
|
|
|
12436
12719
|
};
|
|
12437
12720
|
function be_default() {
|
|
12438
12721
|
return {
|
|
12439
|
-
localeError:
|
|
12722
|
+
localeError: error4()
|
|
12440
12723
|
};
|
|
12441
12724
|
}
|
|
12442
12725
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/bg.js
|
|
12443
|
-
var
|
|
12726
|
+
var error5 = () => {
|
|
12444
12727
|
const Sizable = {
|
|
12445
12728
|
string: { unit: "\u0441\u0438\u043C\u0432\u043E\u043B\u0430", verb: "\u0434\u0430 \u0441\u044A\u0434\u044A\u0440\u0436\u0430" },
|
|
12446
12729
|
file: { unit: "\u0431\u0430\u0439\u0442\u0430", verb: "\u0434\u0430 \u0441\u044A\u0434\u044A\u0440\u0436\u0430" },
|
|
@@ -12556,11 +12839,11 @@ var error4 = () => {
|
|
|
12556
12839
|
};
|
|
12557
12840
|
function bg_default() {
|
|
12558
12841
|
return {
|
|
12559
|
-
localeError:
|
|
12842
|
+
localeError: error5()
|
|
12560
12843
|
};
|
|
12561
12844
|
}
|
|
12562
12845
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/ca.js
|
|
12563
|
-
var
|
|
12846
|
+
var error6 = () => {
|
|
12564
12847
|
const Sizable = {
|
|
12565
12848
|
string: { unit: "car\xE0cters", verb: "contenir" },
|
|
12566
12849
|
file: { unit: "bytes", verb: "contenir" },
|
|
@@ -12663,11 +12946,11 @@ var error5 = () => {
|
|
|
12663
12946
|
};
|
|
12664
12947
|
function ca_default() {
|
|
12665
12948
|
return {
|
|
12666
|
-
localeError:
|
|
12949
|
+
localeError: error6()
|
|
12667
12950
|
};
|
|
12668
12951
|
}
|
|
12669
12952
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/cs.js
|
|
12670
|
-
var
|
|
12953
|
+
var error7 = () => {
|
|
12671
12954
|
const Sizable = {
|
|
12672
12955
|
string: { unit: "znak\u016F", verb: "m\xEDt" },
|
|
12673
12956
|
file: { unit: "bajt\u016F", verb: "m\xEDt" },
|
|
@@ -12774,11 +13057,11 @@ var error6 = () => {
|
|
|
12774
13057
|
};
|
|
12775
13058
|
function cs_default() {
|
|
12776
13059
|
return {
|
|
12777
|
-
localeError:
|
|
13060
|
+
localeError: error7()
|
|
12778
13061
|
};
|
|
12779
13062
|
}
|
|
12780
13063
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/da.js
|
|
12781
|
-
var
|
|
13064
|
+
var error8 = () => {
|
|
12782
13065
|
const Sizable = {
|
|
12783
13066
|
string: { unit: "tegn", verb: "havde" },
|
|
12784
13067
|
file: { unit: "bytes", verb: "havde" },
|
|
@@ -12889,11 +13172,11 @@ var error7 = () => {
|
|
|
12889
13172
|
};
|
|
12890
13173
|
function da_default() {
|
|
12891
13174
|
return {
|
|
12892
|
-
localeError:
|
|
13175
|
+
localeError: error8()
|
|
12893
13176
|
};
|
|
12894
13177
|
}
|
|
12895
13178
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/de.js
|
|
12896
|
-
var
|
|
13179
|
+
var error9 = () => {
|
|
12897
13180
|
const Sizable = {
|
|
12898
13181
|
string: { unit: "Zeichen", verb: "zu haben" },
|
|
12899
13182
|
file: { unit: "Bytes", verb: "zu haben" },
|
|
@@ -12997,11 +13280,11 @@ var error8 = () => {
|
|
|
12997
13280
|
};
|
|
12998
13281
|
function de_default() {
|
|
12999
13282
|
return {
|
|
13000
|
-
localeError:
|
|
13283
|
+
localeError: error9()
|
|
13001
13284
|
};
|
|
13002
13285
|
}
|
|
13003
13286
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/en.js
|
|
13004
|
-
var
|
|
13287
|
+
var error10 = () => {
|
|
13005
13288
|
const Sizable = {
|
|
13006
13289
|
string: { unit: "characters", verb: "to have" },
|
|
13007
13290
|
file: { unit: "bytes", verb: "to have" },
|
|
@@ -13103,11 +13386,11 @@ var error9 = () => {
|
|
|
13103
13386
|
};
|
|
13104
13387
|
function en_default() {
|
|
13105
13388
|
return {
|
|
13106
|
-
localeError:
|
|
13389
|
+
localeError: error10()
|
|
13107
13390
|
};
|
|
13108
13391
|
}
|
|
13109
13392
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/eo.js
|
|
13110
|
-
var
|
|
13393
|
+
var error11 = () => {
|
|
13111
13394
|
const Sizable = {
|
|
13112
13395
|
string: { unit: "karaktrojn", verb: "havi" },
|
|
13113
13396
|
file: { unit: "bajtojn", verb: "havi" },
|
|
@@ -13212,11 +13495,11 @@ var error10 = () => {
|
|
|
13212
13495
|
};
|
|
13213
13496
|
function eo_default() {
|
|
13214
13497
|
return {
|
|
13215
|
-
localeError:
|
|
13498
|
+
localeError: error11()
|
|
13216
13499
|
};
|
|
13217
13500
|
}
|
|
13218
13501
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/es.js
|
|
13219
|
-
var
|
|
13502
|
+
var error12 = () => {
|
|
13220
13503
|
const Sizable = {
|
|
13221
13504
|
string: { unit: "caracteres", verb: "tener" },
|
|
13222
13505
|
file: { unit: "bytes", verb: "tener" },
|
|
@@ -13344,11 +13627,11 @@ var error11 = () => {
|
|
|
13344
13627
|
};
|
|
13345
13628
|
function es_default() {
|
|
13346
13629
|
return {
|
|
13347
|
-
localeError:
|
|
13630
|
+
localeError: error12()
|
|
13348
13631
|
};
|
|
13349
13632
|
}
|
|
13350
13633
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/fa.js
|
|
13351
|
-
var
|
|
13634
|
+
var error13 = () => {
|
|
13352
13635
|
const Sizable = {
|
|
13353
13636
|
string: { unit: "\u06A9\u0627\u0631\u0627\u06A9\u062A\u0631", verb: "\u062F\u0627\u0634\u062A\u0647 \u0628\u0627\u0634\u062F" },
|
|
13354
13637
|
file: { unit: "\u0628\u0627\u06CC\u062A", verb: "\u062F\u0627\u0634\u062A\u0647 \u0628\u0627\u0634\u062F" },
|
|
@@ -13458,11 +13741,11 @@ var error12 = () => {
|
|
|
13458
13741
|
};
|
|
13459
13742
|
function fa_default() {
|
|
13460
13743
|
return {
|
|
13461
|
-
localeError:
|
|
13744
|
+
localeError: error13()
|
|
13462
13745
|
};
|
|
13463
13746
|
}
|
|
13464
13747
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/fi.js
|
|
13465
|
-
var
|
|
13748
|
+
var error14 = () => {
|
|
13466
13749
|
const Sizable = {
|
|
13467
13750
|
string: { unit: "merkki\xE4", subject: "merkkijonon" },
|
|
13468
13751
|
file: { unit: "tavua", subject: "tiedoston" },
|
|
@@ -13570,11 +13853,11 @@ var error13 = () => {
|
|
|
13570
13853
|
};
|
|
13571
13854
|
function fi_default() {
|
|
13572
13855
|
return {
|
|
13573
|
-
localeError:
|
|
13856
|
+
localeError: error14()
|
|
13574
13857
|
};
|
|
13575
13858
|
}
|
|
13576
13859
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/fr.js
|
|
13577
|
-
var
|
|
13860
|
+
var error15 = () => {
|
|
13578
13861
|
const Sizable = {
|
|
13579
13862
|
string: { unit: "caract\xE8res", verb: "avoir" },
|
|
13580
13863
|
file: { unit: "octets", verb: "avoir" },
|
|
@@ -13678,11 +13961,11 @@ var error14 = () => {
|
|
|
13678
13961
|
};
|
|
13679
13962
|
function fr_default() {
|
|
13680
13963
|
return {
|
|
13681
|
-
localeError:
|
|
13964
|
+
localeError: error15()
|
|
13682
13965
|
};
|
|
13683
13966
|
}
|
|
13684
13967
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/fr-CA.js
|
|
13685
|
-
var
|
|
13968
|
+
var error16 = () => {
|
|
13686
13969
|
const Sizable = {
|
|
13687
13970
|
string: { unit: "caract\xE8res", verb: "avoir" },
|
|
13688
13971
|
file: { unit: "octets", verb: "avoir" },
|
|
@@ -13785,11 +14068,11 @@ var error15 = () => {
|
|
|
13785
14068
|
};
|
|
13786
14069
|
function fr_CA_default() {
|
|
13787
14070
|
return {
|
|
13788
|
-
localeError:
|
|
14071
|
+
localeError: error16()
|
|
13789
14072
|
};
|
|
13790
14073
|
}
|
|
13791
14074
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/he.js
|
|
13792
|
-
var
|
|
14075
|
+
var error17 = () => {
|
|
13793
14076
|
const TypeNames = {
|
|
13794
14077
|
string: { label: "\u05DE\u05D7\u05E8\u05D5\u05D6\u05EA", gender: "f" },
|
|
13795
14078
|
number: { label: "\u05DE\u05E1\u05E4\u05E8", gender: "m" },
|
|
@@ -13978,11 +14261,11 @@ var error16 = () => {
|
|
|
13978
14261
|
};
|
|
13979
14262
|
function he_default() {
|
|
13980
14263
|
return {
|
|
13981
|
-
localeError:
|
|
14264
|
+
localeError: error17()
|
|
13982
14265
|
};
|
|
13983
14266
|
}
|
|
13984
14267
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/hu.js
|
|
13985
|
-
var
|
|
14268
|
+
var error18 = () => {
|
|
13986
14269
|
const Sizable = {
|
|
13987
14270
|
string: { unit: "karakter", verb: "legyen" },
|
|
13988
14271
|
file: { unit: "byte", verb: "legyen" },
|
|
@@ -14086,7 +14369,7 @@ var error17 = () => {
|
|
|
14086
14369
|
};
|
|
14087
14370
|
function hu_default() {
|
|
14088
14371
|
return {
|
|
14089
|
-
localeError:
|
|
14372
|
+
localeError: error18()
|
|
14090
14373
|
};
|
|
14091
14374
|
}
|
|
14092
14375
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/hy.js
|
|
@@ -14100,7 +14383,7 @@ function withDefiniteArticle(word) {
|
|
|
14100
14383
|
const lastChar = word[word.length - 1];
|
|
14101
14384
|
return word + (vowels.includes(lastChar) ? "\u0576" : "\u0568");
|
|
14102
14385
|
}
|
|
14103
|
-
var
|
|
14386
|
+
var error19 = () => {
|
|
14104
14387
|
const Sizable = {
|
|
14105
14388
|
string: {
|
|
14106
14389
|
unit: {
|
|
@@ -14233,11 +14516,11 @@ var error18 = () => {
|
|
|
14233
14516
|
};
|
|
14234
14517
|
function hy_default() {
|
|
14235
14518
|
return {
|
|
14236
|
-
localeError:
|
|
14519
|
+
localeError: error19()
|
|
14237
14520
|
};
|
|
14238
14521
|
}
|
|
14239
14522
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/id.js
|
|
14240
|
-
var
|
|
14523
|
+
var error20 = () => {
|
|
14241
14524
|
const Sizable = {
|
|
14242
14525
|
string: { unit: "karakter", verb: "memiliki" },
|
|
14243
14526
|
file: { unit: "byte", verb: "memiliki" },
|
|
@@ -14339,11 +14622,11 @@ var error19 = () => {
|
|
|
14339
14622
|
};
|
|
14340
14623
|
function id_default() {
|
|
14341
14624
|
return {
|
|
14342
|
-
localeError:
|
|
14625
|
+
localeError: error20()
|
|
14343
14626
|
};
|
|
14344
14627
|
}
|
|
14345
14628
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/is.js
|
|
14346
|
-
var
|
|
14629
|
+
var error21 = () => {
|
|
14347
14630
|
const Sizable = {
|
|
14348
14631
|
string: { unit: "stafi", verb: "a\xF0 hafa" },
|
|
14349
14632
|
file: { unit: "b\xE6ti", verb: "a\xF0 hafa" },
|
|
@@ -14448,11 +14731,11 @@ var error20 = () => {
|
|
|
14448
14731
|
};
|
|
14449
14732
|
function is_default() {
|
|
14450
14733
|
return {
|
|
14451
|
-
localeError:
|
|
14734
|
+
localeError: error21()
|
|
14452
14735
|
};
|
|
14453
14736
|
}
|
|
14454
14737
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/it.js
|
|
14455
|
-
var
|
|
14738
|
+
var error22 = () => {
|
|
14456
14739
|
const Sizable = {
|
|
14457
14740
|
string: { unit: "caratteri", verb: "avere" },
|
|
14458
14741
|
file: { unit: "byte", verb: "avere" },
|
|
@@ -14556,11 +14839,11 @@ var error21 = () => {
|
|
|
14556
14839
|
};
|
|
14557
14840
|
function it_default() {
|
|
14558
14841
|
return {
|
|
14559
|
-
localeError:
|
|
14842
|
+
localeError: error22()
|
|
14560
14843
|
};
|
|
14561
14844
|
}
|
|
14562
14845
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/ja.js
|
|
14563
|
-
var
|
|
14846
|
+
var error23 = () => {
|
|
14564
14847
|
const Sizable = {
|
|
14565
14848
|
string: { unit: "\u6587\u5B57", verb: "\u3067\u3042\u308B" },
|
|
14566
14849
|
file: { unit: "\u30D0\u30A4\u30C8", verb: "\u3067\u3042\u308B" },
|
|
@@ -14663,11 +14946,11 @@ var error22 = () => {
|
|
|
14663
14946
|
};
|
|
14664
14947
|
function ja_default() {
|
|
14665
14948
|
return {
|
|
14666
|
-
localeError:
|
|
14949
|
+
localeError: error23()
|
|
14667
14950
|
};
|
|
14668
14951
|
}
|
|
14669
14952
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/ka.js
|
|
14670
|
-
var
|
|
14953
|
+
var error24 = () => {
|
|
14671
14954
|
const Sizable = {
|
|
14672
14955
|
string: { unit: "\u10E1\u10D8\u10DB\u10D1\u10DD\u10DA\u10DD", verb: "\u10E3\u10DC\u10D3\u10D0 \u10E8\u10D4\u10D8\u10EA\u10D0\u10D5\u10D3\u10D4\u10E1" },
|
|
14673
14956
|
file: { unit: "\u10D1\u10D0\u10D8\u10E2\u10D8", verb: "\u10E3\u10DC\u10D3\u10D0 \u10E8\u10D4\u10D8\u10EA\u10D0\u10D5\u10D3\u10D4\u10E1" },
|
|
@@ -14775,11 +15058,11 @@ var error23 = () => {
|
|
|
14775
15058
|
};
|
|
14776
15059
|
function ka_default() {
|
|
14777
15060
|
return {
|
|
14778
|
-
localeError:
|
|
15061
|
+
localeError: error24()
|
|
14779
15062
|
};
|
|
14780
15063
|
}
|
|
14781
15064
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/km.js
|
|
14782
|
-
var
|
|
15065
|
+
var error25 = () => {
|
|
14783
15066
|
const Sizable = {
|
|
14784
15067
|
string: { unit: "\u178F\u17BD\u17A2\u1780\u17D2\u179F\u179A", verb: "\u1782\u17BD\u179A\u1798\u17B6\u1793" },
|
|
14785
15068
|
file: { unit: "\u1794\u17C3", verb: "\u1782\u17BD\u179A\u1798\u17B6\u1793" },
|
|
@@ -14885,7 +15168,7 @@ var error24 = () => {
|
|
|
14885
15168
|
};
|
|
14886
15169
|
function km_default() {
|
|
14887
15170
|
return {
|
|
14888
|
-
localeError:
|
|
15171
|
+
localeError: error25()
|
|
14889
15172
|
};
|
|
14890
15173
|
}
|
|
14891
15174
|
|
|
@@ -14894,7 +15177,7 @@ function kh_default() {
|
|
|
14894
15177
|
return km_default();
|
|
14895
15178
|
}
|
|
14896
15179
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/ko.js
|
|
14897
|
-
var
|
|
15180
|
+
var error26 = () => {
|
|
14898
15181
|
const Sizable = {
|
|
14899
15182
|
string: { unit: "\uBB38\uC790", verb: "to have" },
|
|
14900
15183
|
file: { unit: "\uBC14\uC774\uD2B8", verb: "to have" },
|
|
@@ -15001,7 +15284,7 @@ var error25 = () => {
|
|
|
15001
15284
|
};
|
|
15002
15285
|
function ko_default() {
|
|
15003
15286
|
return {
|
|
15004
|
-
localeError:
|
|
15287
|
+
localeError: error26()
|
|
15005
15288
|
};
|
|
15006
15289
|
}
|
|
15007
15290
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/lt.js
|
|
@@ -15018,7 +15301,7 @@ function getUnitTypeFromNumber(number2) {
|
|
|
15018
15301
|
return "one";
|
|
15019
15302
|
return "few";
|
|
15020
15303
|
}
|
|
15021
|
-
var
|
|
15304
|
+
var error27 = () => {
|
|
15022
15305
|
const Sizable = {
|
|
15023
15306
|
string: {
|
|
15024
15307
|
unit: {
|
|
@@ -15204,11 +15487,11 @@ var error26 = () => {
|
|
|
15204
15487
|
};
|
|
15205
15488
|
function lt_default() {
|
|
15206
15489
|
return {
|
|
15207
|
-
localeError:
|
|
15490
|
+
localeError: error27()
|
|
15208
15491
|
};
|
|
15209
15492
|
}
|
|
15210
15493
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/mk.js
|
|
15211
|
-
var
|
|
15494
|
+
var error28 = () => {
|
|
15212
15495
|
const Sizable = {
|
|
15213
15496
|
string: { unit: "\u0437\u043D\u0430\u0446\u0438", verb: "\u0434\u0430 \u0438\u043C\u0430\u0430\u0442" },
|
|
15214
15497
|
file: { unit: "\u0431\u0430\u0458\u0442\u0438", verb: "\u0434\u0430 \u0438\u043C\u0430\u0430\u0442" },
|
|
@@ -15313,11 +15596,11 @@ var error27 = () => {
|
|
|
15313
15596
|
};
|
|
15314
15597
|
function mk_default() {
|
|
15315
15598
|
return {
|
|
15316
|
-
localeError:
|
|
15599
|
+
localeError: error28()
|
|
15317
15600
|
};
|
|
15318
15601
|
}
|
|
15319
15602
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/ms.js
|
|
15320
|
-
var
|
|
15603
|
+
var error29 = () => {
|
|
15321
15604
|
const Sizable = {
|
|
15322
15605
|
string: { unit: "aksara", verb: "mempunyai" },
|
|
15323
15606
|
file: { unit: "bait", verb: "mempunyai" },
|
|
@@ -15420,11 +15703,11 @@ var error28 = () => {
|
|
|
15420
15703
|
};
|
|
15421
15704
|
function ms_default() {
|
|
15422
15705
|
return {
|
|
15423
|
-
localeError:
|
|
15706
|
+
localeError: error29()
|
|
15424
15707
|
};
|
|
15425
15708
|
}
|
|
15426
15709
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/nl.js
|
|
15427
|
-
var
|
|
15710
|
+
var error30 = () => {
|
|
15428
15711
|
const Sizable = {
|
|
15429
15712
|
string: { unit: "tekens", verb: "heeft" },
|
|
15430
15713
|
file: { unit: "bytes", verb: "heeft" },
|
|
@@ -15530,11 +15813,11 @@ var error29 = () => {
|
|
|
15530
15813
|
};
|
|
15531
15814
|
function nl_default() {
|
|
15532
15815
|
return {
|
|
15533
|
-
localeError:
|
|
15816
|
+
localeError: error30()
|
|
15534
15817
|
};
|
|
15535
15818
|
}
|
|
15536
15819
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/no.js
|
|
15537
|
-
var
|
|
15820
|
+
var error31 = () => {
|
|
15538
15821
|
const Sizable = {
|
|
15539
15822
|
string: { unit: "tegn", verb: "\xE5 ha" },
|
|
15540
15823
|
file: { unit: "bytes", verb: "\xE5 ha" },
|
|
@@ -15638,11 +15921,11 @@ var error30 = () => {
|
|
|
15638
15921
|
};
|
|
15639
15922
|
function no_default() {
|
|
15640
15923
|
return {
|
|
15641
|
-
localeError:
|
|
15924
|
+
localeError: error31()
|
|
15642
15925
|
};
|
|
15643
15926
|
}
|
|
15644
15927
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/ota.js
|
|
15645
|
-
var
|
|
15928
|
+
var error32 = () => {
|
|
15646
15929
|
const Sizable = {
|
|
15647
15930
|
string: { unit: "harf", verb: "olmal\u0131d\u0131r" },
|
|
15648
15931
|
file: { unit: "bayt", verb: "olmal\u0131d\u0131r" },
|
|
@@ -15747,11 +16030,11 @@ var error31 = () => {
|
|
|
15747
16030
|
};
|
|
15748
16031
|
function ota_default() {
|
|
15749
16032
|
return {
|
|
15750
|
-
localeError:
|
|
16033
|
+
localeError: error32()
|
|
15751
16034
|
};
|
|
15752
16035
|
}
|
|
15753
16036
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/ps.js
|
|
15754
|
-
var
|
|
16037
|
+
var error33 = () => {
|
|
15755
16038
|
const Sizable = {
|
|
15756
16039
|
string: { unit: "\u062A\u0648\u06A9\u064A", verb: "\u0648\u0644\u0631\u064A" },
|
|
15757
16040
|
file: { unit: "\u0628\u0627\u06CC\u067C\u0633", verb: "\u0648\u0644\u0631\u064A" },
|
|
@@ -15861,11 +16144,11 @@ var error32 = () => {
|
|
|
15861
16144
|
};
|
|
15862
16145
|
function ps_default() {
|
|
15863
16146
|
return {
|
|
15864
|
-
localeError:
|
|
16147
|
+
localeError: error33()
|
|
15865
16148
|
};
|
|
15866
16149
|
}
|
|
15867
16150
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/pl.js
|
|
15868
|
-
var
|
|
16151
|
+
var error34 = () => {
|
|
15869
16152
|
const Sizable = {
|
|
15870
16153
|
string: { unit: "znak\xF3w", verb: "mie\u0107" },
|
|
15871
16154
|
file: { unit: "bajt\xF3w", verb: "mie\u0107" },
|
|
@@ -15970,11 +16253,11 @@ var error33 = () => {
|
|
|
15970
16253
|
};
|
|
15971
16254
|
function pl_default() {
|
|
15972
16255
|
return {
|
|
15973
|
-
localeError:
|
|
16256
|
+
localeError: error34()
|
|
15974
16257
|
};
|
|
15975
16258
|
}
|
|
15976
16259
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/pt.js
|
|
15977
|
-
var
|
|
16260
|
+
var error35 = () => {
|
|
15978
16261
|
const Sizable = {
|
|
15979
16262
|
string: { unit: "caracteres", verb: "ter" },
|
|
15980
16263
|
file: { unit: "bytes", verb: "ter" },
|
|
@@ -16078,7 +16361,7 @@ var error34 = () => {
|
|
|
16078
16361
|
};
|
|
16079
16362
|
function pt_default() {
|
|
16080
16363
|
return {
|
|
16081
|
-
localeError:
|
|
16364
|
+
localeError: error35()
|
|
16082
16365
|
};
|
|
16083
16366
|
}
|
|
16084
16367
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/ru.js
|
|
@@ -16097,7 +16380,7 @@ function getRussianPlural(count, one, few, many) {
|
|
|
16097
16380
|
}
|
|
16098
16381
|
return many;
|
|
16099
16382
|
}
|
|
16100
|
-
var
|
|
16383
|
+
var error36 = () => {
|
|
16101
16384
|
const Sizable = {
|
|
16102
16385
|
string: {
|
|
16103
16386
|
unit: {
|
|
@@ -16234,11 +16517,11 @@ var error35 = () => {
|
|
|
16234
16517
|
};
|
|
16235
16518
|
function ru_default() {
|
|
16236
16519
|
return {
|
|
16237
|
-
localeError:
|
|
16520
|
+
localeError: error36()
|
|
16238
16521
|
};
|
|
16239
16522
|
}
|
|
16240
16523
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/sl.js
|
|
16241
|
-
var
|
|
16524
|
+
var error37 = () => {
|
|
16242
16525
|
const Sizable = {
|
|
16243
16526
|
string: { unit: "znakov", verb: "imeti" },
|
|
16244
16527
|
file: { unit: "bajtov", verb: "imeti" },
|
|
@@ -16343,11 +16626,11 @@ var error36 = () => {
|
|
|
16343
16626
|
};
|
|
16344
16627
|
function sl_default() {
|
|
16345
16628
|
return {
|
|
16346
|
-
localeError:
|
|
16629
|
+
localeError: error37()
|
|
16347
16630
|
};
|
|
16348
16631
|
}
|
|
16349
16632
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/sv.js
|
|
16350
|
-
var
|
|
16633
|
+
var error38 = () => {
|
|
16351
16634
|
const Sizable = {
|
|
16352
16635
|
string: { unit: "tecken", verb: "att ha" },
|
|
16353
16636
|
file: { unit: "bytes", verb: "att ha" },
|
|
@@ -16453,11 +16736,11 @@ var error37 = () => {
|
|
|
16453
16736
|
};
|
|
16454
16737
|
function sv_default() {
|
|
16455
16738
|
return {
|
|
16456
|
-
localeError:
|
|
16739
|
+
localeError: error38()
|
|
16457
16740
|
};
|
|
16458
16741
|
}
|
|
16459
16742
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/ta.js
|
|
16460
|
-
var
|
|
16743
|
+
var error39 = () => {
|
|
16461
16744
|
const Sizable = {
|
|
16462
16745
|
string: { unit: "\u0B8E\u0BB4\u0BC1\u0BA4\u0BCD\u0BA4\u0BC1\u0B95\u0BCD\u0B95\u0BB3\u0BCD", verb: "\u0B95\u0BCA\u0BA3\u0BCD\u0B9F\u0BBF\u0BB0\u0BC1\u0B95\u0BCD\u0B95 \u0BB5\u0BC7\u0BA3\u0BCD\u0B9F\u0BC1\u0BAE\u0BCD" },
|
|
16463
16746
|
file: { unit: "\u0BAA\u0BC8\u0B9F\u0BCD\u0B9F\u0BC1\u0B95\u0BB3\u0BCD", verb: "\u0B95\u0BCA\u0BA3\u0BCD\u0B9F\u0BBF\u0BB0\u0BC1\u0B95\u0BCD\u0B95 \u0BB5\u0BC7\u0BA3\u0BCD\u0B9F\u0BC1\u0BAE\u0BCD" },
|
|
@@ -16563,11 +16846,11 @@ var error38 = () => {
|
|
|
16563
16846
|
};
|
|
16564
16847
|
function ta_default() {
|
|
16565
16848
|
return {
|
|
16566
|
-
localeError:
|
|
16849
|
+
localeError: error39()
|
|
16567
16850
|
};
|
|
16568
16851
|
}
|
|
16569
16852
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/th.js
|
|
16570
|
-
var
|
|
16853
|
+
var error40 = () => {
|
|
16571
16854
|
const Sizable = {
|
|
16572
16855
|
string: { unit: "\u0E15\u0E31\u0E27\u0E2D\u0E31\u0E01\u0E29\u0E23", verb: "\u0E04\u0E27\u0E23\u0E21\u0E35" },
|
|
16573
16856
|
file: { unit: "\u0E44\u0E1A\u0E15\u0E4C", verb: "\u0E04\u0E27\u0E23\u0E21\u0E35" },
|
|
@@ -16673,11 +16956,11 @@ var error39 = () => {
|
|
|
16673
16956
|
};
|
|
16674
16957
|
function th_default() {
|
|
16675
16958
|
return {
|
|
16676
|
-
localeError:
|
|
16959
|
+
localeError: error40()
|
|
16677
16960
|
};
|
|
16678
16961
|
}
|
|
16679
16962
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/tr.js
|
|
16680
|
-
var
|
|
16963
|
+
var error41 = () => {
|
|
16681
16964
|
const Sizable = {
|
|
16682
16965
|
string: { unit: "karakter", verb: "olmal\u0131" },
|
|
16683
16966
|
file: { unit: "bayt", verb: "olmal\u0131" },
|
|
@@ -16778,11 +17061,11 @@ var error40 = () => {
|
|
|
16778
17061
|
};
|
|
16779
17062
|
function tr_default() {
|
|
16780
17063
|
return {
|
|
16781
|
-
localeError:
|
|
17064
|
+
localeError: error41()
|
|
16782
17065
|
};
|
|
16783
17066
|
}
|
|
16784
17067
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/uk.js
|
|
16785
|
-
var
|
|
17068
|
+
var error42 = () => {
|
|
16786
17069
|
const Sizable = {
|
|
16787
17070
|
string: { unit: "\u0441\u0438\u043C\u0432\u043E\u043B\u0456\u0432", verb: "\u043C\u0430\u0442\u0438\u043C\u0435" },
|
|
16788
17071
|
file: { unit: "\u0431\u0430\u0439\u0442\u0456\u0432", verb: "\u043C\u0430\u0442\u0438\u043C\u0435" },
|
|
@@ -16886,7 +17169,7 @@ var error41 = () => {
|
|
|
16886
17169
|
};
|
|
16887
17170
|
function uk_default() {
|
|
16888
17171
|
return {
|
|
16889
|
-
localeError:
|
|
17172
|
+
localeError: error42()
|
|
16890
17173
|
};
|
|
16891
17174
|
}
|
|
16892
17175
|
|
|
@@ -16895,7 +17178,7 @@ function ua_default() {
|
|
|
16895
17178
|
return uk_default();
|
|
16896
17179
|
}
|
|
16897
17180
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/ur.js
|
|
16898
|
-
var
|
|
17181
|
+
var error43 = () => {
|
|
16899
17182
|
const Sizable = {
|
|
16900
17183
|
string: { unit: "\u062D\u0631\u0648\u0641", verb: "\u06C1\u0648\u0646\u0627" },
|
|
16901
17184
|
file: { unit: "\u0628\u0627\u0626\u0679\u0633", verb: "\u06C1\u0648\u0646\u0627" },
|
|
@@ -17001,11 +17284,11 @@ var error42 = () => {
|
|
|
17001
17284
|
};
|
|
17002
17285
|
function ur_default() {
|
|
17003
17286
|
return {
|
|
17004
|
-
localeError:
|
|
17287
|
+
localeError: error43()
|
|
17005
17288
|
};
|
|
17006
17289
|
}
|
|
17007
17290
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/uz.js
|
|
17008
|
-
var
|
|
17291
|
+
var error44 = () => {
|
|
17009
17292
|
const Sizable = {
|
|
17010
17293
|
string: { unit: "belgi", verb: "bo\u2018lishi kerak" },
|
|
17011
17294
|
file: { unit: "bayt", verb: "bo\u2018lishi kerak" },
|
|
@@ -17110,11 +17393,11 @@ var error43 = () => {
|
|
|
17110
17393
|
};
|
|
17111
17394
|
function uz_default() {
|
|
17112
17395
|
return {
|
|
17113
|
-
localeError:
|
|
17396
|
+
localeError: error44()
|
|
17114
17397
|
};
|
|
17115
17398
|
}
|
|
17116
17399
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/vi.js
|
|
17117
|
-
var
|
|
17400
|
+
var error45 = () => {
|
|
17118
17401
|
const Sizable = {
|
|
17119
17402
|
string: { unit: "k\xFD t\u1EF1", verb: "c\xF3" },
|
|
17120
17403
|
file: { unit: "byte", verb: "c\xF3" },
|
|
@@ -17218,11 +17501,11 @@ var error44 = () => {
|
|
|
17218
17501
|
};
|
|
17219
17502
|
function vi_default() {
|
|
17220
17503
|
return {
|
|
17221
|
-
localeError:
|
|
17504
|
+
localeError: error45()
|
|
17222
17505
|
};
|
|
17223
17506
|
}
|
|
17224
17507
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/zh-CN.js
|
|
17225
|
-
var
|
|
17508
|
+
var error46 = () => {
|
|
17226
17509
|
const Sizable = {
|
|
17227
17510
|
string: { unit: "\u5B57\u7B26", verb: "\u5305\u542B" },
|
|
17228
17511
|
file: { unit: "\u5B57\u8282", verb: "\u5305\u542B" },
|
|
@@ -17327,11 +17610,11 @@ var error45 = () => {
|
|
|
17327
17610
|
};
|
|
17328
17611
|
function zh_CN_default() {
|
|
17329
17612
|
return {
|
|
17330
|
-
localeError:
|
|
17613
|
+
localeError: error46()
|
|
17331
17614
|
};
|
|
17332
17615
|
}
|
|
17333
17616
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/zh-TW.js
|
|
17334
|
-
var
|
|
17617
|
+
var error47 = () => {
|
|
17335
17618
|
const Sizable = {
|
|
17336
17619
|
string: { unit: "\u5B57\u5143", verb: "\u64C1\u6709" },
|
|
17337
17620
|
file: { unit: "\u4F4D\u5143\u7D44", verb: "\u64C1\u6709" },
|
|
@@ -17434,11 +17717,11 @@ var error46 = () => {
|
|
|
17434
17717
|
};
|
|
17435
17718
|
function zh_TW_default() {
|
|
17436
17719
|
return {
|
|
17437
|
-
localeError:
|
|
17720
|
+
localeError: error47()
|
|
17438
17721
|
};
|
|
17439
17722
|
}
|
|
17440
17723
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/locales/yo.js
|
|
17441
|
-
var
|
|
17724
|
+
var error48 = () => {
|
|
17442
17725
|
const Sizable = {
|
|
17443
17726
|
string: { unit: "\xE0mi", verb: "n\xED" },
|
|
17444
17727
|
file: { unit: "bytes", verb: "n\xED" },
|
|
@@ -17541,7 +17824,7 @@ var error47 = () => {
|
|
|
17541
17824
|
};
|
|
17542
17825
|
function yo_default() {
|
|
17543
17826
|
return {
|
|
17544
|
-
localeError:
|
|
17827
|
+
localeError: error48()
|
|
17545
17828
|
};
|
|
17546
17829
|
}
|
|
17547
17830
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/core/registries.js
|
|
@@ -20940,13 +21223,13 @@ function resolveRef(ref, ctx) {
|
|
|
20940
21223
|
if (!ref.startsWith("#")) {
|
|
20941
21224
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
20942
21225
|
}
|
|
20943
|
-
const
|
|
20944
|
-
if (
|
|
21226
|
+
const path2 = ref.slice(1).split("/").filter(Boolean);
|
|
21227
|
+
if (path2.length === 0) {
|
|
20945
21228
|
return ctx.rootSchema;
|
|
20946
21229
|
}
|
|
20947
21230
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
20948
|
-
if (
|
|
20949
|
-
const key =
|
|
21231
|
+
if (path2[0] === defsKey) {
|
|
21232
|
+
const key = path2[1];
|
|
20950
21233
|
if (!key || !ctx.defs[key]) {
|
|
20951
21234
|
throw new Error(`Reference not found: ${ref}`);
|
|
20952
21235
|
}
|
|
@@ -21346,72 +21629,6 @@ function date4(params) {
|
|
|
21346
21629
|
|
|
21347
21630
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/classic/external.js
|
|
21348
21631
|
config(en_default());
|
|
21349
|
-
// src/logger.ts
|
|
21350
|
-
import * as fs from "fs";
|
|
21351
|
-
import * as os from "os";
|
|
21352
|
-
import * as path from "path";
|
|
21353
|
-
var TAG = "[aft-plugin]";
|
|
21354
|
-
var logFile = path.join(os.tmpdir(), "aft-plugin.log");
|
|
21355
|
-
var useStderr = process.env.AFT_LOG_STDERR === "1";
|
|
21356
|
-
var buffer = [];
|
|
21357
|
-
var flushTimer = null;
|
|
21358
|
-
var FLUSH_INTERVAL_MS = 500;
|
|
21359
|
-
var BUFFER_SIZE_LIMIT = 50;
|
|
21360
|
-
function flush() {
|
|
21361
|
-
if (buffer.length === 0)
|
|
21362
|
-
return;
|
|
21363
|
-
const data = buffer.join("");
|
|
21364
|
-
buffer = [];
|
|
21365
|
-
try {
|
|
21366
|
-
if (useStderr) {
|
|
21367
|
-
process.stderr.write(data);
|
|
21368
|
-
} else {
|
|
21369
|
-
fs.appendFileSync(logFile, data);
|
|
21370
|
-
}
|
|
21371
|
-
} catch {}
|
|
21372
|
-
}
|
|
21373
|
-
function scheduleFlush() {
|
|
21374
|
-
if (flushTimer)
|
|
21375
|
-
return;
|
|
21376
|
-
flushTimer = setTimeout(() => {
|
|
21377
|
-
flushTimer = null;
|
|
21378
|
-
flush();
|
|
21379
|
-
}, FLUSH_INTERVAL_MS);
|
|
21380
|
-
if (flushTimer && typeof flushTimer === "object" && "unref" in flushTimer) {
|
|
21381
|
-
flushTimer.unref();
|
|
21382
|
-
}
|
|
21383
|
-
}
|
|
21384
|
-
function write(level, message, data) {
|
|
21385
|
-
try {
|
|
21386
|
-
const timestamp = new Date().toISOString();
|
|
21387
|
-
const serialized = data === undefined ? "" : ` ${JSON.stringify(data)}`;
|
|
21388
|
-
const line = `[${timestamp}] ${level} ${TAG} ${message}${serialized}
|
|
21389
|
-
`;
|
|
21390
|
-
if (useStderr) {
|
|
21391
|
-
process.stderr.write(line);
|
|
21392
|
-
return;
|
|
21393
|
-
}
|
|
21394
|
-
buffer.push(line);
|
|
21395
|
-
if (buffer.length >= BUFFER_SIZE_LIMIT) {
|
|
21396
|
-
flush();
|
|
21397
|
-
} else {
|
|
21398
|
-
scheduleFlush();
|
|
21399
|
-
}
|
|
21400
|
-
} catch {}
|
|
21401
|
-
}
|
|
21402
|
-
function log(message, data) {
|
|
21403
|
-
write("INFO", message, data);
|
|
21404
|
-
}
|
|
21405
|
-
function warn(message, data) {
|
|
21406
|
-
write("WARN", message, data);
|
|
21407
|
-
}
|
|
21408
|
-
function error48(message, data) {
|
|
21409
|
-
write("ERROR", message, data);
|
|
21410
|
-
}
|
|
21411
|
-
function getLogFilePath() {
|
|
21412
|
-
return logFile;
|
|
21413
|
-
}
|
|
21414
|
-
|
|
21415
21632
|
// src/config.ts
|
|
21416
21633
|
var FormatterEnum = exports_external.enum([
|
|
21417
21634
|
"biome",
|
|
@@ -21466,6 +21683,14 @@ var LspConfigSchema = exports_external.object({
|
|
|
21466
21683
|
grace_days: exports_external.number().int().positive().optional(),
|
|
21467
21684
|
versions: exports_external.record(exports_external.string().trim().min(1), exports_external.string().trim().min(1)).optional()
|
|
21468
21685
|
});
|
|
21686
|
+
var ExperimentalConfigSchema = exports_external.object({
|
|
21687
|
+
bash: exports_external.object({
|
|
21688
|
+
rewrite: exports_external.boolean().optional(),
|
|
21689
|
+
compress: exports_external.boolean().optional(),
|
|
21690
|
+
background: exports_external.boolean().optional()
|
|
21691
|
+
}).optional(),
|
|
21692
|
+
lsp_ty: exports_external.boolean().optional()
|
|
21693
|
+
});
|
|
21469
21694
|
var AftConfigSchema = exports_external.object({
|
|
21470
21695
|
format_on_edit: exports_external.boolean().optional(),
|
|
21471
21696
|
validate_on_edit: exports_external.enum(["syntax", "full"]).optional(),
|
|
@@ -21475,22 +21700,22 @@ var AftConfigSchema = exports_external.object({
|
|
|
21475
21700
|
tool_surface: exports_external.enum(["minimal", "recommended", "all"]).optional(),
|
|
21476
21701
|
disabled_tools: exports_external.array(exports_external.string()).optional(),
|
|
21477
21702
|
restrict_to_project_root: exports_external.boolean().optional(),
|
|
21478
|
-
|
|
21479
|
-
|
|
21480
|
-
|
|
21703
|
+
search_index: exports_external.boolean().optional(),
|
|
21704
|
+
semantic_search: exports_external.boolean().optional(),
|
|
21705
|
+
experimental: ExperimentalConfigSchema.optional(),
|
|
21481
21706
|
lsp: LspConfigSchema.optional(),
|
|
21482
21707
|
url_fetch_allow_private: exports_external.boolean().optional(),
|
|
21483
21708
|
semantic: SemanticConfigSchema.optional(),
|
|
21484
21709
|
max_callgraph_files: exports_external.number().int().positive().optional(),
|
|
21485
21710
|
auto_update: exports_external.boolean().optional()
|
|
21486
|
-
});
|
|
21711
|
+
}).strict();
|
|
21487
21712
|
function normalizeLspExtension(extension) {
|
|
21488
21713
|
return extension.trim().replace(/^\.+/, "");
|
|
21489
21714
|
}
|
|
21490
21715
|
function resolveLspConfigForConfigure(config2) {
|
|
21491
21716
|
const overrides = {};
|
|
21492
21717
|
const disabled = new Set(config2.lsp?.disabled ?? []);
|
|
21493
|
-
let experimentalTy = config2.
|
|
21718
|
+
let experimentalTy = config2.experimental?.lsp_ty;
|
|
21494
21719
|
switch (config2.lsp?.python ?? "auto") {
|
|
21495
21720
|
case "ty":
|
|
21496
21721
|
experimentalTy = true;
|
|
@@ -21531,6 +21756,130 @@ function resolveLspConfigForConfigure(config2) {
|
|
|
21531
21756
|
}
|
|
21532
21757
|
return overrides;
|
|
21533
21758
|
}
|
|
21759
|
+
function resolveExperimentalConfigForConfigure(config2) {
|
|
21760
|
+
const overrides = {};
|
|
21761
|
+
if (config2.experimental?.bash?.rewrite !== undefined) {
|
|
21762
|
+
overrides.experimental_bash_rewrite = config2.experimental.bash.rewrite;
|
|
21763
|
+
}
|
|
21764
|
+
if (config2.experimental?.bash?.compress !== undefined) {
|
|
21765
|
+
overrides.experimental_bash_compress = config2.experimental.bash.compress;
|
|
21766
|
+
}
|
|
21767
|
+
if (config2.experimental?.bash?.background !== undefined) {
|
|
21768
|
+
overrides.experimental_bash_background = config2.experimental.bash.background;
|
|
21769
|
+
}
|
|
21770
|
+
if (config2.experimental?.lsp_ty !== undefined) {
|
|
21771
|
+
overrides.experimental_lsp_ty = config2.experimental.lsp_ty;
|
|
21772
|
+
}
|
|
21773
|
+
return overrides;
|
|
21774
|
+
}
|
|
21775
|
+
var CONFIG_MIGRATIONS = [
|
|
21776
|
+
{ oldKey: "experimental_search_index", newPath: ["search_index"] },
|
|
21777
|
+
{ oldKey: "experimental_semantic_search", newPath: ["semantic_search"] },
|
|
21778
|
+
{ oldKey: "experimental_lsp_ty", newPath: ["experimental", "lsp_ty"] },
|
|
21779
|
+
{ oldKey: "experimental_bash_rewrite", newPath: ["experimental", "bash", "rewrite"] },
|
|
21780
|
+
{ oldKey: "experimental_bash_compress", newPath: ["experimental", "bash", "compress"] },
|
|
21781
|
+
{ oldKey: "experimental_bash_background", newPath: ["experimental", "bash", "background"] }
|
|
21782
|
+
];
|
|
21783
|
+
function isWritableMigrationError(errorValue) {
|
|
21784
|
+
const code = errorValue?.code;
|
|
21785
|
+
return code === "EROFS" || code === "EACCES" || code === "EPERM";
|
|
21786
|
+
}
|
|
21787
|
+
function extractCommentsForPreservation(content) {
|
|
21788
|
+
const comments = [];
|
|
21789
|
+
const linePattern = /\/\/[^\n]*/g;
|
|
21790
|
+
for (const match of content.match(linePattern) ?? []) {
|
|
21791
|
+
comments.push(match.trim());
|
|
21792
|
+
}
|
|
21793
|
+
const blockPattern = /\/\*[\s\S]*?\*\//g;
|
|
21794
|
+
for (const match of content.match(blockPattern) ?? []) {
|
|
21795
|
+
comments.push(match.replace(/\s+/g, " ").trim());
|
|
21796
|
+
}
|
|
21797
|
+
return comments;
|
|
21798
|
+
}
|
|
21799
|
+
function ensureRecordAtPath(root, path2) {
|
|
21800
|
+
let current = root;
|
|
21801
|
+
for (const segment of path2) {
|
|
21802
|
+
const existing = current[segment];
|
|
21803
|
+
if (!existing || typeof existing !== "object" || Array.isArray(existing)) {
|
|
21804
|
+
current[segment] = {};
|
|
21805
|
+
}
|
|
21806
|
+
current = current[segment];
|
|
21807
|
+
}
|
|
21808
|
+
return current;
|
|
21809
|
+
}
|
|
21810
|
+
function hasPath(root, path2) {
|
|
21811
|
+
let current = root;
|
|
21812
|
+
for (const segment of path2) {
|
|
21813
|
+
if (!current || typeof current !== "object" || Array.isArray(current))
|
|
21814
|
+
return false;
|
|
21815
|
+
const record2 = current;
|
|
21816
|
+
if (!Object.hasOwn(record2, segment))
|
|
21817
|
+
return false;
|
|
21818
|
+
current = record2[segment];
|
|
21819
|
+
}
|
|
21820
|
+
return true;
|
|
21821
|
+
}
|
|
21822
|
+
function setPath(root, path2, value) {
|
|
21823
|
+
const parent = ensureRecordAtPath(root, path2.slice(0, -1));
|
|
21824
|
+
parent[path2[path2.length - 1]] = value;
|
|
21825
|
+
}
|
|
21826
|
+
function migrateRawConfig(rawConfig, configPath, logger) {
|
|
21827
|
+
const oldKeys = [];
|
|
21828
|
+
for (const migration of CONFIG_MIGRATIONS) {
|
|
21829
|
+
if (!Object.hasOwn(rawConfig, migration.oldKey))
|
|
21830
|
+
continue;
|
|
21831
|
+
if (hasPath(rawConfig, migration.newPath)) {
|
|
21832
|
+
logger?.warn(`Config migration conflict at ${configPath}: ${migration.oldKey} ignored because ${migration.newPath.join(".")} is already set`);
|
|
21833
|
+
} else {
|
|
21834
|
+
setPath(rawConfig, migration.newPath, rawConfig[migration.oldKey]);
|
|
21835
|
+
}
|
|
21836
|
+
delete rawConfig[migration.oldKey];
|
|
21837
|
+
oldKeys.push(migration.oldKey);
|
|
21838
|
+
}
|
|
21839
|
+
return oldKeys;
|
|
21840
|
+
}
|
|
21841
|
+
function migrateAftConfigFile(configPath, logger = { log, warn }) {
|
|
21842
|
+
if (!existsSync(configPath)) {
|
|
21843
|
+
return { migrated: false, oldKeys: [] };
|
|
21844
|
+
}
|
|
21845
|
+
let tmpPath = null;
|
|
21846
|
+
let oldKeys = [];
|
|
21847
|
+
try {
|
|
21848
|
+
const content = readFileSync(configPath, "utf-8");
|
|
21849
|
+
const rawConfig = import_comment_json.parse(content);
|
|
21850
|
+
if (!rawConfig || typeof rawConfig !== "object" || Array.isArray(rawConfig)) {
|
|
21851
|
+
return { migrated: false, oldKeys: [] };
|
|
21852
|
+
}
|
|
21853
|
+
oldKeys = migrateRawConfig(rawConfig, configPath, logger);
|
|
21854
|
+
if (oldKeys.length === 0) {
|
|
21855
|
+
return { migrated: false, oldKeys: [] };
|
|
21856
|
+
}
|
|
21857
|
+
const serialized = `${import_comment_json.stringify(rawConfig, null, 2)}
|
|
21858
|
+
`;
|
|
21859
|
+
const originalComments = extractCommentsForPreservation(content);
|
|
21860
|
+
const droppedComments = originalComments.filter((comment) => !serialized.includes(comment.trim()));
|
|
21861
|
+
const nextContent = droppedComments.length > 0 ? `${droppedComments.join(`
|
|
21862
|
+
`)}
|
|
21863
|
+
${serialized}` : serialized;
|
|
21864
|
+
tmpPath = `${configPath}.tmp.${process.pid}`;
|
|
21865
|
+
writeFileSync(tmpPath, nextContent, "utf-8");
|
|
21866
|
+
renameSync(tmpPath, configPath);
|
|
21867
|
+
logger.log(`Migrated config at ${configPath}: removed ${oldKeys.join(", ")}`);
|
|
21868
|
+
return { migrated: true, oldKeys };
|
|
21869
|
+
} catch (err) {
|
|
21870
|
+
if (tmpPath) {
|
|
21871
|
+
try {
|
|
21872
|
+
unlinkSync(tmpPath);
|
|
21873
|
+
} catch {}
|
|
21874
|
+
}
|
|
21875
|
+
if (isWritableMigrationError(err)) {
|
|
21876
|
+
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
21877
|
+
logger.warn(`Config migration could not write ${configPath} (${errorMsg}); using migrated config in memory`);
|
|
21878
|
+
return { migrated: oldKeys.length > 0, oldKeys };
|
|
21879
|
+
}
|
|
21880
|
+
return { migrated: false, oldKeys: [] };
|
|
21881
|
+
}
|
|
21882
|
+
}
|
|
21534
21883
|
function detectConfigFile(basePath) {
|
|
21535
21884
|
const jsoncPath = `${basePath}.jsonc`;
|
|
21536
21885
|
const jsonPath = `${basePath}.json`;
|
|
@@ -21575,6 +21924,7 @@ function loadConfigFromPath(configPath) {
|
|
|
21575
21924
|
}
|
|
21576
21925
|
const content = readFileSync(configPath, "utf-8");
|
|
21577
21926
|
const rawConfig = import_comment_json.parse(content);
|
|
21927
|
+
migrateRawConfig(rawConfig, configPath, { log, warn });
|
|
21578
21928
|
const result = AftConfigSchema.safeParse(rawConfig);
|
|
21579
21929
|
if (result.success) {
|
|
21580
21930
|
log(`Config loaded from ${configPath}`);
|
|
@@ -21585,7 +21935,7 @@ function loadConfigFromPath(configPath) {
|
|
|
21585
21935
|
return parseConfigPartially(rawConfig);
|
|
21586
21936
|
} catch (err) {
|
|
21587
21937
|
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
21588
|
-
|
|
21938
|
+
error(`Error loading config from ${configPath}: ${errorMsg}`);
|
|
21589
21939
|
return null;
|
|
21590
21940
|
}
|
|
21591
21941
|
}
|
|
@@ -21623,6 +21973,25 @@ function mergeLspConfig(baseLsp, overrideLsp) {
|
|
|
21623
21973
|
}
|
|
21624
21974
|
return Object.fromEntries(Object.entries(lsp).filter(([, value]) => value !== undefined));
|
|
21625
21975
|
}
|
|
21976
|
+
function mergeExperimentalConfig(baseExperimental, overrideExperimental) {
|
|
21977
|
+
const bash = {
|
|
21978
|
+
...baseExperimental?.bash,
|
|
21979
|
+
...overrideExperimental?.bash
|
|
21980
|
+
};
|
|
21981
|
+
const experimental = {
|
|
21982
|
+
...baseExperimental,
|
|
21983
|
+
...overrideExperimental
|
|
21984
|
+
};
|
|
21985
|
+
if (Object.values(bash).some((value) => value !== undefined)) {
|
|
21986
|
+
experimental.bash = bash;
|
|
21987
|
+
} else {
|
|
21988
|
+
delete experimental.bash;
|
|
21989
|
+
}
|
|
21990
|
+
if (Object.values(experimental).every((value) => value === undefined)) {
|
|
21991
|
+
return;
|
|
21992
|
+
}
|
|
21993
|
+
return Object.fromEntries(Object.entries(experimental).filter(([, value]) => value !== undefined));
|
|
21994
|
+
}
|
|
21626
21995
|
function getProjectLspStrippedKeys(lsp) {
|
|
21627
21996
|
if (!lsp) {
|
|
21628
21997
|
return [];
|
|
@@ -21645,9 +22014,9 @@ var PROJECT_SAFE_TOP_LEVEL_FIELDS = new Set([
|
|
|
21645
22014
|
"hoist_builtin_tools",
|
|
21646
22015
|
"format_on_edit",
|
|
21647
22016
|
"validate_on_edit",
|
|
21648
|
-
"
|
|
21649
|
-
"
|
|
21650
|
-
"
|
|
22017
|
+
"search_index",
|
|
22018
|
+
"semantic_search",
|
|
22019
|
+
"experimental"
|
|
21651
22020
|
]);
|
|
21652
22021
|
function pickProjectSafeFields(override) {
|
|
21653
22022
|
const safe = {};
|
|
@@ -21676,6 +22045,7 @@ function mergeConfigs(base, override) {
|
|
|
21676
22045
|
const checker = { ...base.checker, ...override.checker };
|
|
21677
22046
|
const semantic = mergeSemanticConfig(base.semantic, override.semantic);
|
|
21678
22047
|
const lsp = mergeLspConfig(base.lsp, override.lsp);
|
|
22048
|
+
const experimental = mergeExperimentalConfig(base.experimental, override.experimental);
|
|
21679
22049
|
const safeOverride = pickProjectSafeFields(override);
|
|
21680
22050
|
return {
|
|
21681
22051
|
...base,
|
|
@@ -21683,6 +22053,7 @@ function mergeConfigs(base, override) {
|
|
|
21683
22053
|
...Object.keys(formatter).length > 0 ? { formatter } : {},
|
|
21684
22054
|
...Object.keys(checker).length > 0 ? { checker } : {},
|
|
21685
22055
|
...lsp ? { lsp } : {},
|
|
22056
|
+
experimental,
|
|
21686
22057
|
semantic,
|
|
21687
22058
|
...disabledTools.length > 0 ? { disabled_tools: [...new Set(disabledTools)] } : {}
|
|
21688
22059
|
};
|
|
@@ -21698,9 +22069,13 @@ function getOpenCodeConfigDir() {
|
|
|
21698
22069
|
function loadAftConfig(projectDirectory) {
|
|
21699
22070
|
const configDir = getOpenCodeConfigDir();
|
|
21700
22071
|
const userBasePath = join2(configDir, "aft");
|
|
22072
|
+
migrateAftConfigFile(`${userBasePath}.jsonc`);
|
|
22073
|
+
migrateAftConfigFile(`${userBasePath}.json`);
|
|
21701
22074
|
const userDetected = detectConfigFile(userBasePath);
|
|
21702
22075
|
const userConfigPath = userDetected.format !== "none" ? userDetected.path : `${userBasePath}.json`;
|
|
21703
22076
|
const projectBasePath = join2(projectDirectory, ".opencode", "aft");
|
|
22077
|
+
migrateAftConfigFile(`${projectBasePath}.jsonc`);
|
|
22078
|
+
migrateAftConfigFile(`${projectBasePath}.json`);
|
|
21704
22079
|
const projectDetected = detectConfigFile(projectBasePath);
|
|
21705
22080
|
const projectConfigPath = projectDetected.format !== "none" ? projectDetected.path : `${projectBasePath}.json`;
|
|
21706
22081
|
let config2 = loadConfigFromPath(userConfigPath) ?? {};
|
|
@@ -21723,7 +22098,7 @@ function loadAftConfig(projectDirectory) {
|
|
|
21723
22098
|
}
|
|
21724
22099
|
|
|
21725
22100
|
// src/downloader.ts
|
|
21726
|
-
import { chmodSync, existsSync as existsSync2, mkdirSync, unlinkSync } from "fs";
|
|
22101
|
+
import { chmodSync, existsSync as existsSync2, mkdirSync, unlinkSync as unlinkSync2 } from "fs";
|
|
21727
22102
|
import { homedir as homedir2 } from "os";
|
|
21728
22103
|
import { join as join3 } from "path";
|
|
21729
22104
|
|
|
@@ -21765,12 +22140,12 @@ async function downloadBinary(version2) {
|
|
|
21765
22140
|
const platformKey = `${process.platform}-${process.arch}`;
|
|
21766
22141
|
const assetName = PLATFORM_ASSET_MAP[platformKey];
|
|
21767
22142
|
if (!assetName) {
|
|
21768
|
-
|
|
22143
|
+
error(`Unsupported platform: ${platformKey}`);
|
|
21769
22144
|
return null;
|
|
21770
22145
|
}
|
|
21771
22146
|
const tag = version2 ?? await fetchLatestTag();
|
|
21772
22147
|
if (!tag) {
|
|
21773
|
-
|
|
22148
|
+
error("Could not determine latest release version.");
|
|
21774
22149
|
return null;
|
|
21775
22150
|
}
|
|
21776
22151
|
const versionedCacheDir = join3(getCacheDir(), tag);
|
|
@@ -21811,22 +22186,22 @@ async function downloadBinary(version2) {
|
|
|
21811
22186
|
}
|
|
21812
22187
|
log(`Checksum verified (SHA-256: ${actualHash.slice(0, 16)}...)`);
|
|
21813
22188
|
const tmpPath = `${binaryPath}.tmp`;
|
|
21814
|
-
const { writeFileSync } = await import("fs");
|
|
21815
|
-
|
|
22189
|
+
const { writeFileSync: writeFileSync2 } = await import("fs");
|
|
22190
|
+
writeFileSync2(tmpPath, Buffer.from(arrayBuffer));
|
|
21816
22191
|
if (process.platform !== "win32") {
|
|
21817
22192
|
chmodSync(tmpPath, 493);
|
|
21818
22193
|
}
|
|
21819
|
-
const { renameSync } = await import("fs");
|
|
21820
|
-
|
|
22194
|
+
const { renameSync: renameSync2 } = await import("fs");
|
|
22195
|
+
renameSync2(tmpPath, binaryPath);
|
|
21821
22196
|
log(`AFT binary ready at ${binaryPath}`);
|
|
21822
22197
|
return binaryPath;
|
|
21823
22198
|
} catch (err) {
|
|
21824
22199
|
const msg = err instanceof Error ? err.message : String(err);
|
|
21825
|
-
|
|
22200
|
+
error(`Failed to download AFT binary: ${msg}`);
|
|
21826
22201
|
const tmpPath = `${binaryPath}.tmp`;
|
|
21827
22202
|
if (existsSync2(tmpPath)) {
|
|
21828
22203
|
try {
|
|
21829
|
-
|
|
22204
|
+
unlinkSync2(tmpPath);
|
|
21830
22205
|
} catch {}
|
|
21831
22206
|
}
|
|
21832
22207
|
return null;
|
|
@@ -21875,12 +22250,12 @@ async function fetchLatestTag() {
|
|
|
21875
22250
|
// src/hooks/auto-update-checker/cache.ts
|
|
21876
22251
|
var import_comment_json3 = __toESM(require_src2(), 1);
|
|
21877
22252
|
import { spawn } from "child_process";
|
|
21878
|
-
import { existsSync as existsSync4, readFileSync as readFileSync3, rmSync, writeFileSync as
|
|
22253
|
+
import { existsSync as existsSync4, readFileSync as readFileSync3, rmSync, writeFileSync as writeFileSync3 } from "fs";
|
|
21879
22254
|
import { basename, dirname as dirname2, join as join6 } from "path";
|
|
21880
22255
|
|
|
21881
22256
|
// src/hooks/auto-update-checker/checker.ts
|
|
21882
22257
|
var import_comment_json2 = __toESM(require_src2(), 1);
|
|
21883
|
-
import { existsSync as existsSync3, readFileSync as readFileSync2, statSync, writeFileSync } from "fs";
|
|
22258
|
+
import { existsSync as existsSync3, readFileSync as readFileSync2, statSync, writeFileSync as writeFileSync2 } from "fs";
|
|
21884
22259
|
import { homedir as homedir4 } from "os";
|
|
21885
22260
|
import { dirname, isAbsolute, join as join5, resolve } from "path";
|
|
21886
22261
|
import { fileURLToPath } from "url";
|
|
@@ -22151,7 +22526,7 @@ function removeFromBunLock(installDir, packageName) {
|
|
|
22151
22526
|
modified = true;
|
|
22152
22527
|
}
|
|
22153
22528
|
if (modified) {
|
|
22154
|
-
|
|
22529
|
+
writeFileSync3(lockPath, JSON.stringify(lock, null, 2));
|
|
22155
22530
|
log(`[auto-update-checker] Removed from bun.lock: ${packageName}`);
|
|
22156
22531
|
}
|
|
22157
22532
|
return modified;
|
|
@@ -22173,7 +22548,7 @@ function ensureDependencyVersion(packageJsonPath, packageName, version2) {
|
|
|
22173
22548
|
return true;
|
|
22174
22549
|
dependencies[packageName] = version2;
|
|
22175
22550
|
nextPackageJson.dependencies = dependencies;
|
|
22176
|
-
|
|
22551
|
+
writeFileSync3(packageJsonPath, JSON.stringify(nextPackageJson, null, 2));
|
|
22177
22552
|
log(`[auto-update-checker] Updated dependency in package.json: ${packageName} \u2192 ${version2}`);
|
|
22178
22553
|
return true;
|
|
22179
22554
|
} catch (err) {
|
|
@@ -22398,8 +22773,8 @@ import {
|
|
|
22398
22773
|
openSync,
|
|
22399
22774
|
readFileSync as readFileSync4,
|
|
22400
22775
|
statSync as statSync2,
|
|
22401
|
-
unlinkSync as
|
|
22402
|
-
writeFileSync as
|
|
22776
|
+
unlinkSync as unlinkSync3,
|
|
22777
|
+
writeFileSync as writeFileSync4
|
|
22403
22778
|
} from "fs";
|
|
22404
22779
|
import { homedir as homedir5 } from "os";
|
|
22405
22780
|
import { join as join7 } from "path";
|
|
@@ -22450,7 +22825,7 @@ function writeInstalledMetaIn(installDir, version2, sha256) {
|
|
|
22450
22825
|
installedAt: new Date().toISOString(),
|
|
22451
22826
|
...sha256 ? { sha256 } : {}
|
|
22452
22827
|
};
|
|
22453
|
-
|
|
22828
|
+
writeFileSync4(join7(installDir, INSTALLED_META_FILE), JSON.stringify(meta3), "utf8");
|
|
22454
22829
|
} catch (err) {
|
|
22455
22830
|
log(`[lsp-cache] failed to write installed-meta in ${installDir}: ${err}`);
|
|
22456
22831
|
}
|
|
@@ -22490,7 +22865,7 @@ function acquireInstallLock(lockKey) {
|
|
|
22490
22865
|
try {
|
|
22491
22866
|
const fd = openSync(lock, "wx");
|
|
22492
22867
|
try {
|
|
22493
|
-
|
|
22868
|
+
writeFileSync4(fd, `${process.pid}
|
|
22494
22869
|
${new Date().toISOString()}
|
|
22495
22870
|
`);
|
|
22496
22871
|
} finally {
|
|
@@ -22528,7 +22903,7 @@ ${new Date().toISOString()}
|
|
|
22528
22903
|
}
|
|
22529
22904
|
log(`[lsp] reclaiming install lock for ${lockKey} (owner_pid=${owningPid ?? "unknown"}, alive=${ownerAlive}, age_ms=${age})`);
|
|
22530
22905
|
try {
|
|
22531
|
-
|
|
22906
|
+
unlinkSync3(lock);
|
|
22532
22907
|
} catch {}
|
|
22533
22908
|
return tryClaim();
|
|
22534
22909
|
}
|
|
@@ -22565,7 +22940,7 @@ function releaseInstallLock(lockKey) {
|
|
|
22565
22940
|
return;
|
|
22566
22941
|
}
|
|
22567
22942
|
try {
|
|
22568
|
-
|
|
22943
|
+
unlinkSync3(lock);
|
|
22569
22944
|
} catch (unlinkErr) {
|
|
22570
22945
|
const code = unlinkErr.code;
|
|
22571
22946
|
if (code !== "ENOENT") {
|
|
@@ -22609,7 +22984,7 @@ function writeVersionCheck(npmPackage, latest) {
|
|
|
22609
22984
|
last_checked: new Date().toISOString(),
|
|
22610
22985
|
latest_eligible: latest
|
|
22611
22986
|
};
|
|
22612
|
-
|
|
22987
|
+
writeFileSync4(file2, JSON.stringify(record2, null, 2));
|
|
22613
22988
|
}
|
|
22614
22989
|
function shouldRecheckVersion(record2, weeklyCheckIntervalMs = 7 * 24 * 60 * 60 * 1000) {
|
|
22615
22990
|
if (!record2)
|
|
@@ -22968,7 +23343,7 @@ function runInstall(spec, version2, cwd, signal) {
|
|
|
22968
23343
|
}
|
|
22969
23344
|
});
|
|
22970
23345
|
child.on("error", (err) => {
|
|
22971
|
-
|
|
23346
|
+
error(`[lsp] install ${target} failed to spawn: ${err}`);
|
|
22972
23347
|
finish(false);
|
|
22973
23348
|
});
|
|
22974
23349
|
child.on("exit", (code) => {
|
|
@@ -22976,7 +23351,7 @@ function runInstall(spec, version2, cwd, signal) {
|
|
|
22976
23351
|
log(`[lsp] installed ${target}`);
|
|
22977
23352
|
finish(true);
|
|
22978
23353
|
} else {
|
|
22979
|
-
|
|
23354
|
+
error(`[lsp] install ${target} exited with code ${code}; last stderr:
|
|
22980
23355
|
${stderrBuf.trim()}`);
|
|
22981
23356
|
finish(false);
|
|
22982
23357
|
}
|
|
@@ -23005,7 +23380,7 @@ async function ensureServerInstalled(spec, config2, fetchImpl, signal) {
|
|
|
23005
23380
|
return null;
|
|
23006
23381
|
});
|
|
23007
23382
|
if (currentHash && currentHash !== installedMeta.sha256) {
|
|
23008
|
-
|
|
23383
|
+
error(`[lsp] ${spec.npm}@${version2}: TOFU sha256 mismatch \u2014 refusing to use ` + `tampered binary. Recorded ${installedMeta.sha256}, current ${currentHash}. ` + `Run \`aft doctor --clear\` to re-install from scratch.`);
|
|
23009
23384
|
return {
|
|
23010
23385
|
started: false,
|
|
23011
23386
|
reason: `TOFU sha256 mismatch on ${spec.npm}@${version2} \u2014 see plugin log`
|
|
@@ -23021,7 +23396,7 @@ async function ensureServerInstalled(spec, config2, fetchImpl, signal) {
|
|
|
23021
23396
|
}
|
|
23022
23397
|
}
|
|
23023
23398
|
const ok = await runInstall(spec, version2, cachedPackageDir(spec.npm), signal).catch((err) => {
|
|
23024
|
-
|
|
23399
|
+
error(`[lsp] background install ${spec.npm} crashed: ${err}`);
|
|
23025
23400
|
return false;
|
|
23026
23401
|
});
|
|
23027
23402
|
if (!ok) {
|
|
@@ -23077,6 +23452,7 @@ function runAutoInstall(projectRoot, config2, fetchImpl = fetch) {
|
|
|
23077
23452
|
const cachedBinDirs = [];
|
|
23078
23453
|
const skipped = [];
|
|
23079
23454
|
const installPromises = [];
|
|
23455
|
+
const installingBinaries = [];
|
|
23080
23456
|
let installsStarted = 0;
|
|
23081
23457
|
let projectExtensions = null;
|
|
23082
23458
|
const getProjectExtensions = () => {
|
|
@@ -23100,6 +23476,7 @@ function runAutoInstall(projectRoot, config2, fetchImpl = fetch) {
|
|
|
23100
23476
|
continue;
|
|
23101
23477
|
}
|
|
23102
23478
|
installsStarted += 1;
|
|
23479
|
+
installingBinaries.push(spec.binary);
|
|
23103
23480
|
const controller = new AbortController;
|
|
23104
23481
|
const promise2 = ensureServerInstalled(spec, config2, fetchImpl, controller.signal).then((outcome) => {
|
|
23105
23482
|
if (!outcome.started)
|
|
@@ -23111,12 +23488,13 @@ function runAutoInstall(projectRoot, config2, fetchImpl = fetch) {
|
|
|
23111
23488
|
installsStarted -= 1;
|
|
23112
23489
|
const reason = err instanceof Error ? err.message : String(err);
|
|
23113
23490
|
skipped.push({ id: spec.id, reason: `install error: ${reason}` });
|
|
23114
|
-
|
|
23491
|
+
error(`[lsp] background install ${spec.npm} promise rejected: ${reason}`);
|
|
23115
23492
|
});
|
|
23116
23493
|
installPromises.push(trackInFlightAutoInstall(controller, promise2));
|
|
23117
23494
|
}
|
|
23118
23495
|
return {
|
|
23119
23496
|
cachedBinDirs,
|
|
23497
|
+
installingBinaries,
|
|
23120
23498
|
get installsStarted() {
|
|
23121
23499
|
return installsStarted;
|
|
23122
23500
|
},
|
|
@@ -23138,10 +23516,10 @@ import {
|
|
|
23138
23516
|
readdirSync as readdirSync2,
|
|
23139
23517
|
readlinkSync,
|
|
23140
23518
|
realpathSync,
|
|
23141
|
-
renameSync,
|
|
23519
|
+
renameSync as renameSync2,
|
|
23142
23520
|
rmSync as rmSync2,
|
|
23143
23521
|
statSync as statSync4,
|
|
23144
|
-
unlinkSync as
|
|
23522
|
+
unlinkSync as unlinkSync4
|
|
23145
23523
|
} from "fs";
|
|
23146
23524
|
import { dirname as dirname3, join as join9, relative, resolve as resolve2 } from "path";
|
|
23147
23525
|
import { Readable } from "stream";
|
|
@@ -23456,7 +23834,7 @@ async function downloadFile(url2, destPath, fetchImpl, assetSize, signal) {
|
|
|
23456
23834
|
await pipeline(nodeStream, createWriteStream(destPath), { signal: timeout.signal });
|
|
23457
23835
|
} catch (err) {
|
|
23458
23836
|
try {
|
|
23459
|
-
|
|
23837
|
+
unlinkSync4(destPath);
|
|
23460
23838
|
} catch {}
|
|
23461
23839
|
throw err;
|
|
23462
23840
|
} finally {
|
|
@@ -23525,7 +23903,7 @@ function extractArchiveSafely(archivePath, destDir, archiveType) {
|
|
|
23525
23903
|
try {
|
|
23526
23904
|
rmSync2(destDir, { recursive: true, force: true });
|
|
23527
23905
|
} catch {}
|
|
23528
|
-
|
|
23906
|
+
renameSync2(stagingDir, destDir);
|
|
23529
23907
|
} catch (err) {
|
|
23530
23908
|
try {
|
|
23531
23909
|
rmSync2(stagingDir, { recursive: true, force: true });
|
|
@@ -23583,16 +23961,16 @@ async function downloadAndInstall(spec, tag, assets, platform2, arch, fetchImpl,
|
|
|
23583
23961
|
try {
|
|
23584
23962
|
await downloadFile(matchingAsset.url, archivePath, fetchImpl, matchingAsset.size, signal);
|
|
23585
23963
|
} catch (err) {
|
|
23586
|
-
|
|
23964
|
+
error(`[lsp] download ${spec.id} failed: ${err}`);
|
|
23587
23965
|
return null;
|
|
23588
23966
|
}
|
|
23589
23967
|
let archiveSha256;
|
|
23590
23968
|
try {
|
|
23591
23969
|
archiveSha256 = await sha256OfFile(archivePath);
|
|
23592
23970
|
} catch (err) {
|
|
23593
|
-
|
|
23971
|
+
error(`[lsp] hash ${spec.id} failed: ${err}`);
|
|
23594
23972
|
try {
|
|
23595
|
-
|
|
23973
|
+
unlinkSync4(archivePath);
|
|
23596
23974
|
} catch {}
|
|
23597
23975
|
return null;
|
|
23598
23976
|
}
|
|
@@ -23600,9 +23978,9 @@ async function downloadAndInstall(spec, tag, assets, platform2, arch, fetchImpl,
|
|
|
23600
23978
|
const previousMeta = readInstalledMetaIn(ghPackageDir(spec));
|
|
23601
23979
|
if (previousMeta && previousMeta.version === tag && previousMeta.sha256) {
|
|
23602
23980
|
if (previousMeta.sha256 !== archiveSha256) {
|
|
23603
|
-
|
|
23981
|
+
error(`[lsp] ${spec.id} ${tag}: TOFU sha256 mismatch \u2014 refusing install. ` + `Previously installed sha256=${previousMeta.sha256}, downloaded sha256=${archiveSha256}. ` + `This means the published release for tag ${tag} changed. Investigate before proceeding. ` + `Run \`aft doctor --clear\` to wipe the cache and force a fresh install if you've verified the change.`);
|
|
23604
23982
|
try {
|
|
23605
|
-
|
|
23983
|
+
unlinkSync4(archivePath);
|
|
23606
23984
|
} catch {}
|
|
23607
23985
|
return null;
|
|
23608
23986
|
}
|
|
@@ -23610,16 +23988,16 @@ async function downloadAndInstall(spec, tag, assets, platform2, arch, fetchImpl,
|
|
|
23610
23988
|
try {
|
|
23611
23989
|
extractArchiveSafely(archivePath, extractDir, expected.archive);
|
|
23612
23990
|
} catch (err) {
|
|
23613
|
-
|
|
23991
|
+
error(`[lsp] extract ${spec.id} failed: ${err}`);
|
|
23614
23992
|
return null;
|
|
23615
23993
|
} finally {
|
|
23616
23994
|
try {
|
|
23617
|
-
|
|
23995
|
+
unlinkSync4(archivePath);
|
|
23618
23996
|
} catch {}
|
|
23619
23997
|
}
|
|
23620
23998
|
const innerBinaryPath = join9(extractDir, spec.binaryPathInArchive(platform2, arch, version2));
|
|
23621
23999
|
if (!existsSync6(innerBinaryPath)) {
|
|
23622
|
-
|
|
24000
|
+
error(`[lsp] ${spec.id}: extracted binary not found at ${innerBinaryPath}`);
|
|
23623
24001
|
return null;
|
|
23624
24002
|
}
|
|
23625
24003
|
const targetBinary = ghBinaryPath(spec, platform2);
|
|
@@ -23631,7 +24009,7 @@ async function downloadAndInstall(spec, tag, assets, platform2, arch, fetchImpl,
|
|
|
23631
24009
|
chmodSync2(targetBinary, 493);
|
|
23632
24010
|
}
|
|
23633
24011
|
} catch (err) {
|
|
23634
|
-
|
|
24012
|
+
error(`[lsp] ${spec.id}: failed to place binary at ${targetBinary}: ${err}`);
|
|
23635
24013
|
return null;
|
|
23636
24014
|
}
|
|
23637
24015
|
log(`[lsp] installed ${spec.id} ${tag} at ${targetBinary}`);
|
|
@@ -23662,7 +24040,7 @@ async function ensureGithubInstalled(spec, config2, fetchImpl, platform2, arch,
|
|
|
23662
24040
|
}
|
|
23663
24041
|
}
|
|
23664
24042
|
const archiveSha256 = await downloadAndInstall(spec, tag, assets, platform2, arch, fetchImpl, signal).catch((err) => {
|
|
23665
|
-
|
|
24043
|
+
error(`[lsp] github install ${spec.id} crashed: ${err}`);
|
|
23666
24044
|
return null;
|
|
23667
24045
|
});
|
|
23668
24046
|
if (!archiveSha256) {
|
|
@@ -23694,6 +24072,7 @@ function runGithubAutoInstall(relevantServers, config2, fetchImpl = fetch) {
|
|
|
23694
24072
|
const cachedBinDirs = [];
|
|
23695
24073
|
const skipped = [];
|
|
23696
24074
|
const installPromises = [];
|
|
24075
|
+
const installingBinaries = [];
|
|
23697
24076
|
let installsStarted = 0;
|
|
23698
24077
|
const host = detectHostPlatform();
|
|
23699
24078
|
if (!host) {
|
|
@@ -23707,6 +24086,7 @@ function runGithubAutoInstall(relevantServers, config2, fetchImpl = fetch) {
|
|
|
23707
24086
|
return {
|
|
23708
24087
|
cachedBinDirs,
|
|
23709
24088
|
installsStarted: 0,
|
|
24089
|
+
installingBinaries: [],
|
|
23710
24090
|
skipped,
|
|
23711
24091
|
installsComplete: Promise.resolve()
|
|
23712
24092
|
};
|
|
@@ -23728,6 +24108,7 @@ function runGithubAutoInstall(relevantServers, config2, fetchImpl = fetch) {
|
|
|
23728
24108
|
continue;
|
|
23729
24109
|
}
|
|
23730
24110
|
installsStarted += 1;
|
|
24111
|
+
installingBinaries.push(spec.binary);
|
|
23731
24112
|
const controller = new AbortController;
|
|
23732
24113
|
const promise2 = ensureGithubInstalled(spec, config2, fetchImpl, host.platform, host.arch, controller.signal).then((outcome) => {
|
|
23733
24114
|
if (!outcome.started)
|
|
@@ -23739,12 +24120,13 @@ function runGithubAutoInstall(relevantServers, config2, fetchImpl = fetch) {
|
|
|
23739
24120
|
installsStarted -= 1;
|
|
23740
24121
|
const reason = err instanceof Error ? err.message : String(err);
|
|
23741
24122
|
skipped.push({ id: spec.id, reason: `install error: ${reason}` });
|
|
23742
|
-
|
|
24123
|
+
error(`[lsp] github install ${spec.id} promise rejected: ${reason}`);
|
|
23743
24124
|
});
|
|
23744
24125
|
installPromises.push(trackInFlightGithubInstall(controller, promise2));
|
|
23745
24126
|
}
|
|
23746
24127
|
return {
|
|
23747
24128
|
cachedBinDirs,
|
|
24129
|
+
installingBinaries,
|
|
23748
24130
|
get installsStarted() {
|
|
23749
24131
|
return installsStarted;
|
|
23750
24132
|
},
|
|
@@ -23859,7 +24241,7 @@ function normalizeToolMap(tools) {
|
|
|
23859
24241
|
}
|
|
23860
24242
|
|
|
23861
24243
|
// src/notifications.ts
|
|
23862
|
-
import { existsSync as existsSync7, mkdirSync as mkdirSync4, readFileSync as readFileSync5, writeFileSync as
|
|
24244
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync4, readFileSync as readFileSync5, writeFileSync as writeFileSync5 } from "fs";
|
|
23863
24245
|
import { homedir as homedir6, platform as platform2 } from "os";
|
|
23864
24246
|
import { join as join10 } from "path";
|
|
23865
24247
|
function isTuiMode() {
|
|
@@ -24021,7 +24403,7 @@ async function sendFeatureAnnouncement(opts, version2, features, storageDir) {
|
|
|
24021
24403
|
if (storageDir) {
|
|
24022
24404
|
try {
|
|
24023
24405
|
mkdirSync4(storageDir, { recursive: true });
|
|
24024
|
-
|
|
24406
|
+
writeFileSync5(join10(storageDir, "last_announced_version"), version2);
|
|
24025
24407
|
} catch {}
|
|
24026
24408
|
}
|
|
24027
24409
|
}
|
|
@@ -24048,13 +24430,14 @@ function writeWarnedTools(storageDir, warned) {
|
|
|
24048
24430
|
try {
|
|
24049
24431
|
mkdirSync4(storageDir, { recursive: true });
|
|
24050
24432
|
const warnedToolsPath = join10(storageDir, WARNED_TOOLS_FILE);
|
|
24051
|
-
|
|
24433
|
+
writeFileSync5(warnedToolsPath, `${JSON.stringify(warned, null, 2)}
|
|
24052
24434
|
`);
|
|
24053
24435
|
} catch {}
|
|
24054
24436
|
}
|
|
24055
24437
|
function warningKey(warning, projectRoot) {
|
|
24438
|
+
const scope = warning.kind === "lsp_binary_missing" ? "_" : projectRoot ?? "_";
|
|
24056
24439
|
return [
|
|
24057
|
-
|
|
24440
|
+
scope,
|
|
24058
24441
|
warning.kind,
|
|
24059
24442
|
warning.language ?? warning.server ?? "_",
|
|
24060
24443
|
warning.tool ?? warning.binary ?? "_",
|
|
@@ -24157,8 +24540,8 @@ import {
|
|
|
24157
24540
|
rmSync as rmSync3,
|
|
24158
24541
|
statSync as statSync5,
|
|
24159
24542
|
symlinkSync,
|
|
24160
|
-
unlinkSync as
|
|
24161
|
-
writeFileSync as
|
|
24543
|
+
unlinkSync as unlinkSync5,
|
|
24544
|
+
writeFileSync as writeFileSync6
|
|
24162
24545
|
} from "fs";
|
|
24163
24546
|
import { dirname as dirname4, join as join11, relative as relative2, resolve as resolve3 } from "path";
|
|
24164
24547
|
import { Readable as Readable2 } from "stream";
|
|
@@ -24231,7 +24614,7 @@ async function ensureOnnxRuntime(storageDir) {
|
|
|
24231
24614
|
try {
|
|
24232
24615
|
const currentHash = sha256File(libPath);
|
|
24233
24616
|
if (currentHash !== meta3.sha256) {
|
|
24234
|
-
|
|
24617
|
+
error(`ONNX Runtime at ${ortDir}: TOFU sha256 mismatch \u2014 refusing to use ` + `tampered binary. Recorded ${meta3.sha256}, current ${currentHash}. ` + `Run \`aft doctor --clear\` to re-download from scratch.`);
|
|
24235
24618
|
} else {
|
|
24236
24619
|
log(`ONNX Runtime found at ${ortDir} (TOFU verified)`);
|
|
24237
24620
|
return ortDir;
|
|
@@ -24316,7 +24699,7 @@ async function downloadFileWithCap(url2, destPath) {
|
|
|
24316
24699
|
await pipeline2(nodeStream, createWriteStream2(destPath), { signal: controller.signal });
|
|
24317
24700
|
} catch (err) {
|
|
24318
24701
|
try {
|
|
24319
|
-
|
|
24702
|
+
unlinkSync5(destPath);
|
|
24320
24703
|
} catch {}
|
|
24321
24704
|
throw err;
|
|
24322
24705
|
} finally {
|
|
@@ -24377,7 +24760,7 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
24377
24760
|
await extractZipArchive(archivePath, tmpDir);
|
|
24378
24761
|
}
|
|
24379
24762
|
try {
|
|
24380
|
-
|
|
24763
|
+
unlinkSync5(archivePath);
|
|
24381
24764
|
} catch {}
|
|
24382
24765
|
validateExtractedTree(tmpDir);
|
|
24383
24766
|
const extractedDir = join11(tmpDir, info.assetName, "lib");
|
|
@@ -24418,7 +24801,7 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
24418
24801
|
for (const link of symlinks) {
|
|
24419
24802
|
const dst = join11(targetDir, link.name);
|
|
24420
24803
|
try {
|
|
24421
|
-
|
|
24804
|
+
unlinkSync5(dst);
|
|
24422
24805
|
} catch {}
|
|
24423
24806
|
symlinkSync(link.target, dst);
|
|
24424
24807
|
}
|
|
@@ -24434,7 +24817,7 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
24434
24817
|
log(`ONNX Runtime v${ORT_VERSION} installed to ${targetDir}`);
|
|
24435
24818
|
return targetDir;
|
|
24436
24819
|
} catch (err) {
|
|
24437
|
-
|
|
24820
|
+
error(`Failed to download ONNX Runtime: ${err}`);
|
|
24438
24821
|
try {
|
|
24439
24822
|
rmSync3(tmpDir, { recursive: true, force: true });
|
|
24440
24823
|
} catch {}
|
|
@@ -24465,7 +24848,7 @@ function writeOnnxInstalledMeta(installDir, version2, sha256, archiveSha256) {
|
|
|
24465
24848
|
...sha256 ? { sha256 } : {},
|
|
24466
24849
|
archiveSha256
|
|
24467
24850
|
};
|
|
24468
|
-
|
|
24851
|
+
writeFileSync6(join11(installDir, ONNX_INSTALLED_META_FILE), JSON.stringify(meta3), "utf8");
|
|
24469
24852
|
} catch (err) {
|
|
24470
24853
|
log(`[onnx] failed to write installed-meta in ${installDir}: ${err}`);
|
|
24471
24854
|
}
|
|
@@ -24499,7 +24882,7 @@ function acquireLock(lockPath2) {
|
|
|
24499
24882
|
try {
|
|
24500
24883
|
const fd = openSync2(lockPath2, "wx");
|
|
24501
24884
|
try {
|
|
24502
|
-
|
|
24885
|
+
writeFileSync6(fd, `${process.pid}
|
|
24503
24886
|
${new Date().toISOString()}
|
|
24504
24887
|
`);
|
|
24505
24888
|
} finally {
|
|
@@ -24537,7 +24920,7 @@ ${new Date().toISOString()}
|
|
|
24537
24920
|
}
|
|
24538
24921
|
log(`[onnx] reclaiming install lock (owner_pid=${owningPid ?? "unknown"}, alive=${ownerAlive}, age_ms=${age})`);
|
|
24539
24922
|
try {
|
|
24540
|
-
|
|
24923
|
+
unlinkSync5(lockPath2);
|
|
24541
24924
|
} catch {}
|
|
24542
24925
|
return tryClaim();
|
|
24543
24926
|
}
|
|
@@ -24562,7 +24945,7 @@ function releaseLock(lockPath2) {
|
|
|
24562
24945
|
return;
|
|
24563
24946
|
}
|
|
24564
24947
|
try {
|
|
24565
|
-
|
|
24948
|
+
unlinkSync5(lockPath2);
|
|
24566
24949
|
} catch (unlinkErr) {
|
|
24567
24950
|
const code = unlinkErr.code;
|
|
24568
24951
|
if (code !== "ENOENT") {
|
|
@@ -24698,6 +25081,9 @@ class BinaryBridge {
|
|
|
24698
25081
|
if (this._shuttingDown) {
|
|
24699
25082
|
throw new Error(`[aft-plugin] Bridge is shutting down, cannot send "${command}"`);
|
|
24700
25083
|
}
|
|
25084
|
+
if (Object.hasOwn(params, "id")) {
|
|
25085
|
+
throw new Error("params cannot contain reserved key 'id'");
|
|
25086
|
+
}
|
|
24701
25087
|
this.ensureSpawned();
|
|
24702
25088
|
if (!this.configured) {
|
|
24703
25089
|
if (command !== "configure" && command !== "version") {
|
|
@@ -24726,18 +25112,37 @@ class BinaryBridge {
|
|
|
24726
25112
|
}
|
|
24727
25113
|
}
|
|
24728
25114
|
const id = String(this.nextId++);
|
|
24729
|
-
|
|
25115
|
+
let request;
|
|
25116
|
+
if (Object.hasOwn(params, "command") || Object.hasOwn(params, "method")) {
|
|
25117
|
+
const nested = { ...params };
|
|
25118
|
+
const reserved = {};
|
|
25119
|
+
for (const key of ["session_id", "lsp_hints"]) {
|
|
25120
|
+
if (Object.hasOwn(nested, key)) {
|
|
25121
|
+
reserved[key] = nested[key];
|
|
25122
|
+
delete nested[key];
|
|
25123
|
+
}
|
|
25124
|
+
}
|
|
25125
|
+
request = { id, command, ...reserved, params: nested };
|
|
25126
|
+
} else {
|
|
25127
|
+
request = { id, command, ...params };
|
|
25128
|
+
}
|
|
24730
25129
|
const line = `${JSON.stringify(request)}
|
|
24731
25130
|
`;
|
|
24732
|
-
const effectiveTimeoutMs = options?.timeoutMs ?? this.timeoutMs;
|
|
25131
|
+
const effectiveTimeoutMs = options?.transportTimeoutMs ?? options?.timeoutMs ?? this.timeoutMs;
|
|
25132
|
+
const requestSessionId = typeof params.session_id === "string" && params.session_id.length > 0 ? params.session_id : undefined;
|
|
24733
25133
|
return new Promise((resolve4, reject) => {
|
|
24734
25134
|
const timer = setTimeout(() => {
|
|
24735
25135
|
this.pending.delete(id);
|
|
24736
|
-
|
|
25136
|
+
const timeoutMsg = `Request "${command}" (id=${id}) timed out after ${effectiveTimeoutMs}ms \u2014 restarting bridge`;
|
|
25137
|
+
if (requestSessionId) {
|
|
25138
|
+
sessionWarn(requestSessionId, timeoutMsg);
|
|
25139
|
+
} else {
|
|
25140
|
+
warn(timeoutMsg);
|
|
25141
|
+
}
|
|
24737
25142
|
reject(new Error(`[aft-plugin] Request "${command}" (id=${id}) timed out after ${effectiveTimeoutMs}ms`));
|
|
24738
25143
|
this.handleTimeout();
|
|
24739
25144
|
}, effectiveTimeoutMs);
|
|
24740
|
-
this.pending.set(id, { resolve: resolve4, reject, timer });
|
|
25145
|
+
this.pending.set(id, { resolve: resolve4, reject, timer, onProgress: options?.onProgress });
|
|
24741
25146
|
if (!this.process?.stdin?.writable) {
|
|
24742
25147
|
this.pending.delete(id);
|
|
24743
25148
|
clearTimeout(timer);
|
|
@@ -24865,7 +25270,7 @@ class BinaryBridge {
|
|
|
24865
25270
|
child.on("error", (err) => {
|
|
24866
25271
|
if (this.process !== currentChild)
|
|
24867
25272
|
return;
|
|
24868
|
-
|
|
25273
|
+
error(`Process error: ${err.message}${this.formatStderrTail()}`);
|
|
24869
25274
|
this.handleCrash();
|
|
24870
25275
|
});
|
|
24871
25276
|
child.on("exit", (code, signal) => {
|
|
@@ -24917,6 +25322,29 @@ class BinaryBridge {
|
|
|
24917
25322
|
continue;
|
|
24918
25323
|
try {
|
|
24919
25324
|
const response = JSON.parse(line);
|
|
25325
|
+
if (response.type === "progress") {
|
|
25326
|
+
const requestId = response.request_id;
|
|
25327
|
+
const entry = requestId ? this.pending.get(requestId) : undefined;
|
|
25328
|
+
const kind = response.kind === "stderr" ? "stderr" : "stdout";
|
|
25329
|
+
const text = typeof response.chunk === "string" ? response.chunk : "";
|
|
25330
|
+
entry?.onProgress?.({ kind, text });
|
|
25331
|
+
continue;
|
|
25332
|
+
}
|
|
25333
|
+
if (response.type === "permission_ask") {
|
|
25334
|
+
const requestId = response.request_id;
|
|
25335
|
+
const entry = requestId ? this.pending.get(requestId) : undefined;
|
|
25336
|
+
if (requestId && entry) {
|
|
25337
|
+
this.pending.delete(requestId);
|
|
25338
|
+
clearTimeout(entry.timer);
|
|
25339
|
+
entry.resolve({
|
|
25340
|
+
success: false,
|
|
25341
|
+
code: "permission_required",
|
|
25342
|
+
message: "bash command requires permission",
|
|
25343
|
+
asks: response.asks
|
|
25344
|
+
});
|
|
25345
|
+
}
|
|
25346
|
+
continue;
|
|
25347
|
+
}
|
|
24920
25348
|
const id = response.id;
|
|
24921
25349
|
if (id && this.pending.has(id)) {
|
|
24922
25350
|
const entry = this.pending.get(id);
|
|
@@ -24941,7 +25369,11 @@ class BinaryBridge {
|
|
|
24941
25369
|
this.configured = false;
|
|
24942
25370
|
const tail = this.formatStderrTail();
|
|
24943
25371
|
this.stderrTail = [];
|
|
24944
|
-
|
|
25372
|
+
if (tail) {
|
|
25373
|
+
error(`Bridge killed after timeout.${tail}`);
|
|
25374
|
+
} else {
|
|
25375
|
+
warn(`Bridge killed after timeout (see ${getLogFilePath()})`);
|
|
25376
|
+
}
|
|
24945
25377
|
}
|
|
24946
25378
|
handleCrash(cause) {
|
|
24947
25379
|
const proc = this.process;
|
|
@@ -24952,7 +25384,10 @@ class BinaryBridge {
|
|
|
24952
25384
|
this.clearRestartResetTimer();
|
|
24953
25385
|
this.configured = false;
|
|
24954
25386
|
const tail = this.formatStderrTail();
|
|
24955
|
-
|
|
25387
|
+
if (tail) {
|
|
25388
|
+
error(`Binary crashed (restarts: ${this._restartCount})${cause ? `: ${cause.message}` : ""}.${tail}`);
|
|
25389
|
+
}
|
|
25390
|
+
this.rejectAllPending(new Error(`[aft-plugin] Binary crashed (restarts: ${this._restartCount})${cause ? `: ${cause.message}` : ""} (see ${getLogFilePath()})`));
|
|
24956
25391
|
if (this._restartCount < this.maxRestarts) {
|
|
24957
25392
|
const delay = 100 * 2 ** this._restartCount;
|
|
24958
25393
|
this._restartCount++;
|
|
@@ -24962,13 +25397,13 @@ class BinaryBridge {
|
|
|
24962
25397
|
try {
|
|
24963
25398
|
this.spawnProcess();
|
|
24964
25399
|
} catch (err) {
|
|
24965
|
-
|
|
25400
|
+
error(`Failed to restart: ${err.message}`);
|
|
24966
25401
|
}
|
|
24967
25402
|
}
|
|
24968
25403
|
}, delay);
|
|
24969
25404
|
this.scheduleRestartCountReset();
|
|
24970
25405
|
} else {
|
|
24971
|
-
|
|
25406
|
+
error(`Max restarts (${this.maxRestarts}) reached, giving up. Logs: ${getLogFilePath()}${tail}`);
|
|
24972
25407
|
this.scheduleRestartCountReset();
|
|
24973
25408
|
}
|
|
24974
25409
|
}
|
|
@@ -25057,7 +25492,7 @@ class BridgePool {
|
|
|
25057
25492
|
const now = Date.now();
|
|
25058
25493
|
for (const [dir, entry] of this.bridges) {
|
|
25059
25494
|
if (now - entry.lastUsed > this.idleTimeoutMs) {
|
|
25060
|
-
entry.bridge.shutdown().catch((err) =>
|
|
25495
|
+
entry.bridge.shutdown().catch((err) => error("cleanup shutdown failed:", err));
|
|
25061
25496
|
this.bridges.delete(dir);
|
|
25062
25497
|
}
|
|
25063
25498
|
}
|
|
@@ -25073,7 +25508,7 @@ class BridgePool {
|
|
|
25073
25508
|
}
|
|
25074
25509
|
if (oldestDir) {
|
|
25075
25510
|
const entry = this.bridges.get(oldestDir);
|
|
25076
|
-
entry?.bridge.shutdown().catch((err) =>
|
|
25511
|
+
entry?.bridge.shutdown().catch((err) => error("eviction shutdown failed:", err));
|
|
25077
25512
|
this.bridges.delete(oldestDir);
|
|
25078
25513
|
}
|
|
25079
25514
|
}
|
|
@@ -25103,7 +25538,7 @@ function normalizeKey(projectRoot) {
|
|
|
25103
25538
|
|
|
25104
25539
|
// src/resolver.ts
|
|
25105
25540
|
import { execSync, spawnSync } from "child_process";
|
|
25106
|
-
import { chmodSync as chmodSync3, copyFileSync as copyFileSync3, existsSync as existsSync9, mkdirSync as mkdirSync6, renameSync as
|
|
25541
|
+
import { chmodSync as chmodSync3, copyFileSync as copyFileSync3, existsSync as existsSync9, mkdirSync as mkdirSync6, renameSync as renameSync3 } from "fs";
|
|
25107
25542
|
import { createRequire } from "module";
|
|
25108
25543
|
import { homedir as homedir8 } from "os";
|
|
25109
25544
|
import { join as join13 } from "path";
|
|
@@ -25131,7 +25566,7 @@ function copyToVersionedCache(npmBinaryPath) {
|
|
|
25131
25566
|
if (process.platform !== "win32") {
|
|
25132
25567
|
chmodSync3(tmpPath, 493);
|
|
25133
25568
|
}
|
|
25134
|
-
|
|
25569
|
+
renameSync3(tmpPath, cachedPath);
|
|
25135
25570
|
log(`Copied npm binary to versioned cache: ${cachedPath}`);
|
|
25136
25571
|
return cachedPath;
|
|
25137
25572
|
} catch (err) {
|
|
@@ -25221,7 +25656,7 @@ async function findBinary() {
|
|
|
25221
25656
|
|
|
25222
25657
|
// src/shared/rpc-server.ts
|
|
25223
25658
|
import { randomBytes as randomBytes2 } from "crypto";
|
|
25224
|
-
import { mkdirSync as mkdirSync7, renameSync as
|
|
25659
|
+
import { mkdirSync as mkdirSync7, renameSync as renameSync4, unlinkSync as unlinkSync6, writeFileSync as writeFileSync7 } from "fs";
|
|
25225
25660
|
import { createServer } from "http";
|
|
25226
25661
|
import { dirname as dirname5 } from "path";
|
|
25227
25662
|
|
|
@@ -25270,8 +25705,8 @@ class AftRpcServer {
|
|
|
25270
25705
|
const dir = dirname5(this.portFilePath);
|
|
25271
25706
|
mkdirSync7(dir, { recursive: true });
|
|
25272
25707
|
const tmpPath = `${this.portFilePath}.tmp`;
|
|
25273
|
-
|
|
25274
|
-
|
|
25708
|
+
writeFileSync7(tmpPath, JSON.stringify({ port: this.port, token: this.token }), "utf-8");
|
|
25709
|
+
renameSync4(tmpPath, this.portFilePath);
|
|
25275
25710
|
log(`RPC server listening on 127.0.0.1:${this.port}`);
|
|
25276
25711
|
} catch (err) {
|
|
25277
25712
|
warn(`Failed to write RPC port file: ${err}`);
|
|
@@ -25288,7 +25723,7 @@ class AftRpcServer {
|
|
|
25288
25723
|
}
|
|
25289
25724
|
this.token = null;
|
|
25290
25725
|
try {
|
|
25291
|
-
|
|
25726
|
+
unlinkSync6(this.portFilePath);
|
|
25292
25727
|
} catch {}
|
|
25293
25728
|
}
|
|
25294
25729
|
dispatch(req, res) {
|
|
@@ -25418,8 +25853,8 @@ function coerceAftStatus(response) {
|
|
|
25418
25853
|
format_on_edit: readBoolean(features.format_on_edit),
|
|
25419
25854
|
validate_on_edit: readString(features.validate_on_edit, "off"),
|
|
25420
25855
|
restrict_to_project_root: readBoolean(features.restrict_to_project_root),
|
|
25421
|
-
|
|
25422
|
-
|
|
25856
|
+
search_index: readBoolean(features.search_index ?? features.experimental_search_index),
|
|
25857
|
+
semantic_search: readBoolean(features.semantic_search ?? features.experimental_semantic_search)
|
|
25423
25858
|
},
|
|
25424
25859
|
search_index: {
|
|
25425
25860
|
status: readString(searchIndex.status, "unknown"),
|
|
@@ -25466,8 +25901,8 @@ function formatStatusMarkdown(status) {
|
|
|
25466
25901
|
"",
|
|
25467
25902
|
"### Enabled features",
|
|
25468
25903
|
`- \`format_on_edit\`: ${formatFlag(status.features.format_on_edit)}`,
|
|
25469
|
-
`- \`
|
|
25470
|
-
`- \`
|
|
25904
|
+
`- \`search_index\`: ${formatFlag(status.features.search_index)}`,
|
|
25905
|
+
`- \`semantic_search\`: ${formatFlag(status.features.semantic_search)}`,
|
|
25471
25906
|
"",
|
|
25472
25907
|
"### Search index",
|
|
25473
25908
|
`- **Status:** \`${status.search_index.status}\``,
|
|
@@ -25510,7 +25945,7 @@ function formatStatusMarkdown(status) {
|
|
|
25510
25945
|
|
|
25511
25946
|
// src/shared/tui-config.ts
|
|
25512
25947
|
var import_comment_json4 = __toESM(require_src2(), 1);
|
|
25513
|
-
import { existsSync as existsSync10, mkdirSync as mkdirSync8, readFileSync as readFileSync7, writeFileSync as
|
|
25948
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync8, readFileSync as readFileSync7, writeFileSync as writeFileSync8 } from "fs";
|
|
25514
25949
|
import { dirname as dirname6, join as join16 } from "path";
|
|
25515
25950
|
|
|
25516
25951
|
// src/shared/opencode-config-dir.ts
|
|
@@ -25567,7 +26002,7 @@ function ensureTuiPluginEntry() {
|
|
|
25567
26002
|
plugins.push(PLUGIN_ENTRY);
|
|
25568
26003
|
config2.plugin = plugins;
|
|
25569
26004
|
mkdirSync8(dirname6(configPath), { recursive: true });
|
|
25570
|
-
|
|
26005
|
+
writeFileSync8(configPath, `${import_comment_json4.stringify(config2, null, 2)}
|
|
25571
26006
|
`);
|
|
25572
26007
|
log(`[aft-plugin] added TUI plugin entry to ${configPath}`);
|
|
25573
26008
|
return true;
|
|
@@ -25585,8 +26020,8 @@ import {
|
|
|
25585
26020
|
mkdirSync as mkdirSync9,
|
|
25586
26021
|
readdirSync as readdirSync4,
|
|
25587
26022
|
readFileSync as readFileSync8,
|
|
25588
|
-
unlinkSync as
|
|
25589
|
-
writeFileSync as
|
|
26023
|
+
unlinkSync as unlinkSync7,
|
|
26024
|
+
writeFileSync as writeFileSync9
|
|
25590
26025
|
} from "fs";
|
|
25591
26026
|
import { isIP } from "net";
|
|
25592
26027
|
import { join as join17 } from "path";
|
|
@@ -25816,9 +26251,9 @@ async function fetchUrlToTempFile(url2, storageDir, options = {}) {
|
|
|
25816
26251
|
const body = Buffer.concat(chunks);
|
|
25817
26252
|
const contentFile = contentPath(storageDir, hash2, extension);
|
|
25818
26253
|
const tmpContent = `${contentFile}.tmp-${process.pid}`;
|
|
25819
|
-
|
|
25820
|
-
const { renameSync:
|
|
25821
|
-
|
|
26254
|
+
writeFileSync9(tmpContent, body);
|
|
26255
|
+
const { renameSync: renameSync5 } = await import("fs");
|
|
26256
|
+
renameSync5(tmpContent, contentFile);
|
|
25822
26257
|
const meta3 = {
|
|
25823
26258
|
url: url2,
|
|
25824
26259
|
contentType,
|
|
@@ -25826,8 +26261,8 @@ async function fetchUrlToTempFile(url2, storageDir, options = {}) {
|
|
|
25826
26261
|
fetchedAt: Date.now()
|
|
25827
26262
|
};
|
|
25828
26263
|
const tmpMeta = `${metaFile}.tmp-${process.pid}`;
|
|
25829
|
-
|
|
25830
|
-
|
|
26264
|
+
writeFileSync9(tmpMeta, JSON.stringify(meta3));
|
|
26265
|
+
renameSync5(tmpMeta, metaFile);
|
|
25831
26266
|
log(`URL cached (${total} bytes): ${url2}`);
|
|
25832
26267
|
return contentFile;
|
|
25833
26268
|
}
|
|
@@ -25848,13 +26283,13 @@ function cleanupUrlCache(storageDir) {
|
|
|
25848
26283
|
const hash2 = entry.slice(0, -".meta.json".length);
|
|
25849
26284
|
const content = contentPath(storageDir, hash2, meta3.extension);
|
|
25850
26285
|
if (existsSync11(content))
|
|
25851
|
-
|
|
25852
|
-
|
|
26286
|
+
unlinkSync7(content);
|
|
26287
|
+
unlinkSync7(metaFile);
|
|
25853
26288
|
removed++;
|
|
25854
26289
|
}
|
|
25855
26290
|
} catch {
|
|
25856
26291
|
try {
|
|
25857
|
-
|
|
26292
|
+
unlinkSync7(metaFile);
|
|
25858
26293
|
removed++;
|
|
25859
26294
|
} catch {}
|
|
25860
26295
|
}
|
|
@@ -25950,7 +26385,7 @@ function projectRootFor(runtime) {
|
|
|
25950
26385
|
function bridgeFor(ctx, runtime) {
|
|
25951
26386
|
return ctx.pool.getBridge(projectRootFor(runtime));
|
|
25952
26387
|
}
|
|
25953
|
-
function callBridge(ctx, runtime, command, params = {}) {
|
|
26388
|
+
function callBridge(ctx, runtime, command, params = {}, options) {
|
|
25954
26389
|
const merged = { ...params };
|
|
25955
26390
|
if (runtime.sessionID) {
|
|
25956
26391
|
merged.session_id = runtime.sessionID;
|
|
@@ -25958,9 +26393,13 @@ function callBridge(ctx, runtime, command, params = {}) {
|
|
|
25958
26393
|
const timeoutMs = timeoutForCommand(command);
|
|
25959
26394
|
const sendOptions = {
|
|
25960
26395
|
...timeoutMs !== undefined ? { timeoutMs } : {},
|
|
25961
|
-
configureWarningClient: ctx.client
|
|
26396
|
+
configureWarningClient: ctx.client,
|
|
26397
|
+
...options
|
|
25962
26398
|
};
|
|
25963
|
-
return bridgeFor(ctx, runtime).send(command, merged, Object.keys(sendOptions).length > 0 ? sendOptions : undefined)
|
|
26399
|
+
return bridgeFor(ctx, runtime).send(command, merged, Object.keys(sendOptions).length > 0 ? sendOptions : undefined).then((response) => {
|
|
26400
|
+
ingestBgCompletions(runtime.sessionID, response.bg_completions);
|
|
26401
|
+
return response;
|
|
26402
|
+
});
|
|
25964
26403
|
}
|
|
25965
26404
|
|
|
25966
26405
|
// src/tools/permissions.ts
|
|
@@ -26139,7 +26578,7 @@ ${hint}`;
|
|
|
26139
26578
|
|
|
26140
26579
|
` + `**Warning: This tool modifies files directly.** Use dryRun=true to preview. Consider creating an aft_safety checkpoint before bulk replacements.
|
|
26141
26580
|
|
|
26142
|
-
` + "Returns: Text summary \u2014 'Replaced N match(es) across M file(s)' (or '[DRY RUN] Would replace...') followed by file
|
|
26581
|
+
` + "Returns: Text summary \u2014 'Replaced N match(es) across M file(s)' (or '[DRY RUN] Would replace...') followed by per-file output. In dry-run mode, each file is shown with its unified diff so you can verify the rewrite before applying (e.g. catch literal $$$ from anonymous-variadic typos). Diff preview is capped at 8KB total; remaining files are summarized.",
|
|
26143
26582
|
args: {
|
|
26144
26583
|
pattern: z2.string().describe("AST pattern with meta-variables ($VAR, $$$). Must be complete AST node."),
|
|
26145
26584
|
rewrite: z2.string().describe("Replacement pattern (can use $VAR from pattern)"),
|
|
@@ -26205,7 +26644,36 @@ ${data.scope_warnings.map((w) => ` ${w}`).join(`
|
|
|
26205
26644
|
` : `Replaced ${matchCount} match(es) in ${filesWithMatches} file(s) (${filesSearched} searched)
|
|
26206
26645
|
|
|
26207
26646
|
`;
|
|
26208
|
-
if (data.
|
|
26647
|
+
if (isDryRun && data.files && data.files.length > 0) {
|
|
26648
|
+
const MAX_DIFF_BYTES = 8 * 1024;
|
|
26649
|
+
let used = 0;
|
|
26650
|
+
let filesShown = 0;
|
|
26651
|
+
for (const f of data.files) {
|
|
26652
|
+
const relFile = f.file ?? "unknown";
|
|
26653
|
+
const reps = f.replacements ?? 0;
|
|
26654
|
+
const diff = f.diff ?? "";
|
|
26655
|
+
if (used + diff.length > MAX_DIFF_BYTES) {
|
|
26656
|
+
const remaining = data.files.length - filesShown;
|
|
26657
|
+
if (remaining > 0) {
|
|
26658
|
+
output += `
|
|
26659
|
+
... (${remaining} more file(s) omitted from preview to stay under ${MAX_DIFF_BYTES / 1024}KB; total ${matchCount} replacements across ${filesWithMatches} files)
|
|
26660
|
+
`;
|
|
26661
|
+
}
|
|
26662
|
+
break;
|
|
26663
|
+
}
|
|
26664
|
+
output += `${relFile} (${reps} replacement${reps === 1 ? "" : "s"}):
|
|
26665
|
+
`;
|
|
26666
|
+
output += diff;
|
|
26667
|
+
if (!diff.endsWith(`
|
|
26668
|
+
`))
|
|
26669
|
+
output += `
|
|
26670
|
+
`;
|
|
26671
|
+
output += `
|
|
26672
|
+
`;
|
|
26673
|
+
used += diff.length;
|
|
26674
|
+
filesShown += 1;
|
|
26675
|
+
}
|
|
26676
|
+
} else if (data.matches) {
|
|
26209
26677
|
for (const m of data.matches) {
|
|
26210
26678
|
const relFile = m.file ?? "unknown";
|
|
26211
26679
|
const line = m.line ?? 0;
|
|
@@ -26218,6 +26686,13 @@ ${data.scope_warnings.map((w) => ` ${w}`).join(`
|
|
|
26218
26686
|
`;
|
|
26219
26687
|
}
|
|
26220
26688
|
output += `
|
|
26689
|
+
`;
|
|
26690
|
+
}
|
|
26691
|
+
} else if (data.files && data.files.length > 0) {
|
|
26692
|
+
for (const f of data.files) {
|
|
26693
|
+
const relFile = f.file ?? "unknown";
|
|
26694
|
+
const reps = f.replacements ?? 0;
|
|
26695
|
+
output += ` ${relFile}: ${reps} replacement${reps === 1 ? "" : "s"}
|
|
26221
26696
|
`;
|
|
26222
26697
|
}
|
|
26223
26698
|
}
|
|
@@ -26253,7 +26728,7 @@ function conflictTools(ctx) {
|
|
|
26253
26728
|
// src/tools/hoisted.ts
|
|
26254
26729
|
import * as fs3 from "fs";
|
|
26255
26730
|
import * as path4 from "path";
|
|
26256
|
-
import { tool as
|
|
26731
|
+
import { tool as tool4 } from "@opencode-ai/plugin";
|
|
26257
26732
|
|
|
26258
26733
|
// src/patch-parser.ts
|
|
26259
26734
|
function stripHeredoc(input) {
|
|
@@ -26388,6 +26863,9 @@ function parsePatch(patchText) {
|
|
|
26388
26863
|
function normalizeUnicode(str) {
|
|
26389
26864
|
return str.replace(/[\u2018\u2019\u201A\u201B]/g, "'").replace(/[\u201C\u201D\u201E\u201F]/g, '"').replace(/[\u2010\u2011\u2012\u2013\u2014\u2015]/g, "-").replace(/\u2026/g, "...").replace(/\u00A0/g, " ");
|
|
26390
26865
|
}
|
|
26866
|
+
function normalizeIndent(str) {
|
|
26867
|
+
return str.replace(/^[\t ]+/, (m) => " ".repeat(m.length));
|
|
26868
|
+
}
|
|
26391
26869
|
function tryMatch(lines, pattern, startIndex, compare, eof) {
|
|
26392
26870
|
if (eof) {
|
|
26393
26871
|
const fromEnd = lines.length - pattern.length;
|
|
@@ -26416,19 +26894,58 @@ function tryMatch(lines, pattern, startIndex, compare, eof) {
|
|
|
26416
26894
|
}
|
|
26417
26895
|
return -1;
|
|
26418
26896
|
}
|
|
26419
|
-
function
|
|
26897
|
+
function seekSequenceTiered(lines, pattern, startIndex, eof = false) {
|
|
26420
26898
|
if (pattern.length === 0)
|
|
26421
|
-
return
|
|
26899
|
+
return null;
|
|
26422
26900
|
const exact = tryMatch(lines, pattern, startIndex, (a, b) => a === b, eof);
|
|
26423
26901
|
if (exact !== -1)
|
|
26424
|
-
return exact;
|
|
26902
|
+
return { found: exact, tier: "exact" };
|
|
26425
26903
|
const rstrip = tryMatch(lines, pattern, startIndex, (a, b) => a.trimEnd() === b.trimEnd(), eof);
|
|
26426
26904
|
if (rstrip !== -1)
|
|
26427
|
-
return rstrip;
|
|
26905
|
+
return { found: rstrip, tier: "rstrip" };
|
|
26428
26906
|
const trim = tryMatch(lines, pattern, startIndex, (a, b) => a.trim() === b.trim(), eof);
|
|
26429
26907
|
if (trim !== -1)
|
|
26430
|
-
return trim;
|
|
26431
|
-
|
|
26908
|
+
return { found: trim, tier: "trim" };
|
|
26909
|
+
const indent = tryMatch(lines, pattern, startIndex, (a, b) => normalizeIndent(a).trimEnd() === normalizeIndent(b).trimEnd(), eof);
|
|
26910
|
+
if (indent !== -1)
|
|
26911
|
+
return { found: indent, tier: "indent" };
|
|
26912
|
+
const unicode = tryMatch(lines, pattern, startIndex, (a, b) => normalizeUnicode(a.trim()) === normalizeUnicode(b.trim()), eof);
|
|
26913
|
+
if (unicode !== -1)
|
|
26914
|
+
return { found: unicode, tier: "unicode" };
|
|
26915
|
+
return null;
|
|
26916
|
+
}
|
|
26917
|
+
function seekSequence(lines, pattern, startIndex, eof = false) {
|
|
26918
|
+
const r = seekSequenceTiered(lines, pattern, startIndex, eof);
|
|
26919
|
+
return r ? r.found : -1;
|
|
26920
|
+
}
|
|
26921
|
+
function findClosestPartialMatch(lines, pattern) {
|
|
26922
|
+
if (pattern.length === 0 || lines.length === 0)
|
|
26923
|
+
return null;
|
|
26924
|
+
const compareAny = (a, b) => a === b || a.trimEnd() === b.trimEnd() || a.trim() === b.trim() || normalizeIndent(a).trimEnd() === normalizeIndent(b).trimEnd() || normalizeUnicode(a.trim()) === normalizeUnicode(b.trim());
|
|
26925
|
+
const candidates = [];
|
|
26926
|
+
for (let i = 0;i < lines.length && candidates.length < 16; i++) {
|
|
26927
|
+
if (compareAny(lines[i], pattern[0]))
|
|
26928
|
+
candidates.push(i);
|
|
26929
|
+
}
|
|
26930
|
+
if (candidates.length === 0)
|
|
26931
|
+
return null;
|
|
26932
|
+
let best = { lineNumber: -1, matchedLines: 0, firstDivergence: -1 };
|
|
26933
|
+
for (const start of candidates) {
|
|
26934
|
+
let matched = 0;
|
|
26935
|
+
for (let j = 0;j < pattern.length && start + j < lines.length; j++) {
|
|
26936
|
+
if (!compareAny(lines[start + j], pattern[j]))
|
|
26937
|
+
break;
|
|
26938
|
+
matched++;
|
|
26939
|
+
}
|
|
26940
|
+
if (matched > best.matchedLines) {
|
|
26941
|
+
best = {
|
|
26942
|
+
lineNumber: start + 1,
|
|
26943
|
+
matchedLines: matched,
|
|
26944
|
+
firstDivergence: matched
|
|
26945
|
+
};
|
|
26946
|
+
}
|
|
26947
|
+
}
|
|
26948
|
+
return best.lineNumber === -1 ? null : best;
|
|
26432
26949
|
}
|
|
26433
26950
|
function applyUpdateChunks(originalContent, filePath, chunks) {
|
|
26434
26951
|
const originalLines = originalContent.split(`
|
|
@@ -26465,9 +26982,30 @@ function applyUpdateChunks(originalContent, filePath, chunks) {
|
|
|
26465
26982
|
replacements.push([found, pattern.length, newSlice]);
|
|
26466
26983
|
lineIndex = found + pattern.length;
|
|
26467
26984
|
} else {
|
|
26985
|
+
const newSliceTrimmed = newSlice.filter((line) => line.trim().length > 0);
|
|
26986
|
+
const alreadyApplied = newSliceTrimmed.length > 0 && seekSequence(originalLines, newSliceTrimmed, 0, chunk.is_end_of_file) !== -1;
|
|
26987
|
+
const closest = findClosestPartialMatch(originalLines, pattern);
|
|
26988
|
+
let closestHint = "";
|
|
26989
|
+
if (closest && closest.matchedLines > 0) {
|
|
26990
|
+
const fileLineNo = closest.lineNumber + closest.firstDivergence;
|
|
26991
|
+
const expectedLine = pattern[closest.firstDivergence];
|
|
26992
|
+
const actualLine = fileLineNo - 1 < originalLines.length ? originalLines[fileLineNo - 1] : "<EOF>";
|
|
26993
|
+
closestHint = `
|
|
26994
|
+
|
|
26995
|
+
Closest match starts at line ${closest.lineNumber} ` + `(${closest.matchedLines} of ${pattern.length} lines matched).
|
|
26996
|
+
` + `First divergence at line ${fileLineNo}:
|
|
26997
|
+
` + ` expected: ${JSON.stringify(expectedLine)}
|
|
26998
|
+
` + ` actual: ${JSON.stringify(actualLine)}`;
|
|
26999
|
+
}
|
|
27000
|
+
const triedTiers = "exact, trimEnd, trim, indent (tab/space), unicode";
|
|
27001
|
+
const alreadyAppliedHint = alreadyApplied ? `
|
|
27002
|
+
|
|
27003
|
+
Hint: the replacement content for this hunk already appears in the file. ` + "The patch may have been partially applied in a prior turn \u2014 re-read the file " + "to confirm which hunks still need to apply." : "";
|
|
26468
27004
|
throw new Error(`Failed to find expected lines in ${filePath}:
|
|
26469
27005
|
${chunk.old_lines.join(`
|
|
26470
|
-
`)}
|
|
27006
|
+
`)}
|
|
27007
|
+
|
|
27008
|
+
` + `Tried match tiers: ${triedTiers}.${closestHint}${alreadyAppliedHint}`);
|
|
26471
27009
|
}
|
|
26472
27010
|
}
|
|
26473
27011
|
replacements.sort((a, b) => a[0] - b[0]);
|
|
@@ -26483,14 +27021,163 @@ ${chunk.old_lines.join(`
|
|
|
26483
27021
|
`);
|
|
26484
27022
|
}
|
|
26485
27023
|
|
|
26486
|
-
// src/tools/
|
|
27024
|
+
// src/tools/bash.ts
|
|
27025
|
+
import { tool as tool3 } from "@opencode-ai/plugin";
|
|
27026
|
+
var z3 = tool3.schema;
|
|
27027
|
+
var METADATA_PREVIEW_LIMIT = 30 * 1024;
|
|
27028
|
+
var DEFAULT_BASH_TIMEOUT_MS = 120000;
|
|
27029
|
+
var BASH_TRANSPORT_TIMEOUT_OVERHEAD_MS = 5000;
|
|
27030
|
+
var BASH_DESCRIPTION = `Hoisted bash tool with output compression, command rewriting to AFT tools, and optional background execution. By default, output is compressed; pass compressed: false for raw output. Pass background: true to spawn in the background and get a task_id for bash_status/bash_kill.`;
|
|
27031
|
+
async function withPermissionLoop(ctx, runtime, params, bridgeCall, options) {
|
|
27032
|
+
const first = await bridgeCall(ctx, runtime, "bash", params, options);
|
|
27033
|
+
if (first.success !== false || first.code !== "permission_required")
|
|
27034
|
+
return first;
|
|
27035
|
+
const asks = Array.isArray(first.asks) ? first.asks : [];
|
|
27036
|
+
const permissionsGranted = [];
|
|
27037
|
+
for (const ask of asks) {
|
|
27038
|
+
const permission = ask.kind === "external_directory" ? "external_directory" : "bash";
|
|
27039
|
+
await runtime.ask({
|
|
27040
|
+
permission,
|
|
27041
|
+
patterns: ask.patterns,
|
|
27042
|
+
always: ask.always,
|
|
27043
|
+
metadata: {}
|
|
27044
|
+
});
|
|
27045
|
+
permissionsGranted.push(...ask.always.length > 0 ? ask.always : ask.patterns);
|
|
27046
|
+
}
|
|
27047
|
+
const second = await bridgeCall(ctx, runtime, "bash", { ...params, permissions_granted: permissionsGranted }, options);
|
|
27048
|
+
if (second.success === false && second.code === "permission_required") {
|
|
27049
|
+
throw new Error("bash permission retry failed");
|
|
27050
|
+
}
|
|
27051
|
+
return second;
|
|
27052
|
+
}
|
|
27053
|
+
function createBashTool(ctx) {
|
|
27054
|
+
return {
|
|
27055
|
+
description: BASH_DESCRIPTION,
|
|
27056
|
+
args: {
|
|
27057
|
+
command: z3.string().describe("Shell command to execute through AFT's unified bash schema. Supports normal shell syntax, pipes, redirection, and command rewriting to dedicated AFT tools when available."),
|
|
27058
|
+
timeout: z3.number().optional().describe("Maximum execution time in milliseconds for foreground commands. Defaults to 120000 (2 minutes) when omitted."),
|
|
27059
|
+
workdir: z3.string().optional().describe("Working directory for command execution. Relative paths resolve through the bridge; defaults to the current tool context/project root when omitted."),
|
|
27060
|
+
description: z3.string().optional().describe("Short 5-10 word human-readable summary shown in OpenCode UI metadata instead of raw shell syntax."),
|
|
27061
|
+
background: z3.boolean().optional().describe("When true, spawn the command in the background and return a task_id for bash_status/bash_kill instead of waiting for completion. Defaults to false."),
|
|
27062
|
+
compressed: z3.boolean().optional().describe("When true or omitted, return compressed output with noisy terminal control sequences reduced. Set to false for raw output.")
|
|
27063
|
+
},
|
|
27064
|
+
execute: async (args, context) => {
|
|
27065
|
+
let accumulatedOutput = "";
|
|
27066
|
+
const description = args.description;
|
|
27067
|
+
const metadata = context.metadata;
|
|
27068
|
+
const command = args.command;
|
|
27069
|
+
const cwd = args.workdir ?? context.directory;
|
|
27070
|
+
const shellEnv = await ctx.plugin?.trigger?.("shell.env", { cwd, sessionID: context.sessionID, callID: getCallID(context) }, { env: {} });
|
|
27071
|
+
const data = await withPermissionLoop(ctx, context, {
|
|
27072
|
+
command,
|
|
27073
|
+
timeout: args.timeout,
|
|
27074
|
+
workdir: args.workdir,
|
|
27075
|
+
env: shellEnv?.env ?? {},
|
|
27076
|
+
description,
|
|
27077
|
+
background: args.background,
|
|
27078
|
+
compressed: args.compressed,
|
|
27079
|
+
permissions_requested: true
|
|
27080
|
+
}, callBridge, {
|
|
27081
|
+
transportTimeoutMs: bashTransportTimeoutMs(args.timeout),
|
|
27082
|
+
onProgress: ({ text }) => {
|
|
27083
|
+
accumulatedOutput = preview(accumulatedOutput + text);
|
|
27084
|
+
metadata?.({ output: accumulatedOutput, description });
|
|
27085
|
+
}
|
|
27086
|
+
});
|
|
27087
|
+
if (data.success === false) {
|
|
27088
|
+
throw new Error(data.message || "bash failed");
|
|
27089
|
+
}
|
|
27090
|
+
if (data.status === "running" && typeof data.task_id === "string") {
|
|
27091
|
+
const callID2 = getCallID(context);
|
|
27092
|
+
const taskId = data.task_id;
|
|
27093
|
+
trackBgTask(context.sessionID, taskId);
|
|
27094
|
+
const startedLine = `Background task started: ${taskId}`;
|
|
27095
|
+
const metadataPayload2 = { description, output: startedLine, status: "running", taskId };
|
|
27096
|
+
metadata?.(metadataPayload2);
|
|
27097
|
+
if (callID2) {
|
|
27098
|
+
storeToolMetadata(context.sessionID, callID2, {
|
|
27099
|
+
title: description ?? shortenCommand(command),
|
|
27100
|
+
metadata: metadataPayload2
|
|
27101
|
+
});
|
|
27102
|
+
}
|
|
27103
|
+
return startedLine;
|
|
27104
|
+
}
|
|
27105
|
+
const output = data.output ?? "";
|
|
27106
|
+
const metadataOutput = preview(output);
|
|
27107
|
+
const exit = data.exit_code;
|
|
27108
|
+
const truncated = data.truncated;
|
|
27109
|
+
const outputPath = data.output_path;
|
|
27110
|
+
const timedOut = data.timed_out === true;
|
|
27111
|
+
const callID = getCallID(context);
|
|
27112
|
+
const metadataPayload = {
|
|
27113
|
+
description,
|
|
27114
|
+
output: metadataOutput,
|
|
27115
|
+
exit,
|
|
27116
|
+
truncated,
|
|
27117
|
+
...outputPath ? { outputPath } : {}
|
|
27118
|
+
};
|
|
27119
|
+
metadata?.(metadataPayload);
|
|
27120
|
+
if (callID) {
|
|
27121
|
+
storeToolMetadata(context.sessionID, callID, {
|
|
27122
|
+
title: description ?? shortenCommand(command),
|
|
27123
|
+
metadata: metadataPayload
|
|
27124
|
+
});
|
|
27125
|
+
}
|
|
27126
|
+
let rendered = output;
|
|
27127
|
+
if (truncated && outputPath) {
|
|
27128
|
+
rendered += `
|
|
27129
|
+
[output truncated; full output at ${outputPath}]`;
|
|
27130
|
+
}
|
|
27131
|
+
if (timedOut) {
|
|
27132
|
+
rendered += `
|
|
27133
|
+
[command timed out]`;
|
|
27134
|
+
}
|
|
27135
|
+
if (typeof exit === "number" && exit !== 0) {
|
|
27136
|
+
rendered += `
|
|
27137
|
+
[exit code: ${exit}]`;
|
|
27138
|
+
}
|
|
27139
|
+
return rendered;
|
|
27140
|
+
}
|
|
27141
|
+
};
|
|
27142
|
+
}
|
|
27143
|
+
function bashTransportTimeoutMs(timeout) {
|
|
27144
|
+
const bashTimeout = timeout ?? DEFAULT_BASH_TIMEOUT_MS;
|
|
27145
|
+
return Math.max(30000, bashTimeout + BASH_TRANSPORT_TIMEOUT_OVERHEAD_MS);
|
|
27146
|
+
}
|
|
27147
|
+
function preview(output) {
|
|
27148
|
+
return output.length <= METADATA_PREVIEW_LIMIT ? output : output.slice(-METADATA_PREVIEW_LIMIT);
|
|
27149
|
+
}
|
|
26487
27150
|
function getCallID(ctx) {
|
|
26488
27151
|
const c = ctx;
|
|
26489
27152
|
return c.callID ?? c.callId ?? c.call_id;
|
|
26490
27153
|
}
|
|
27154
|
+
function shortenCommand(command) {
|
|
27155
|
+
const collapsed = command.replace(/\s+/g, " ").trim();
|
|
27156
|
+
return collapsed.length <= 80 ? collapsed : `${collapsed.slice(0, 77)}...`;
|
|
27157
|
+
}
|
|
27158
|
+
|
|
27159
|
+
// src/tools/hoisted.ts
|
|
27160
|
+
function getCallID2(ctx) {
|
|
27161
|
+
const c = ctx;
|
|
27162
|
+
return c.callID ?? c.callId ?? c.call_id;
|
|
27163
|
+
}
|
|
26491
27164
|
function relativeToWorktree(fp, worktree) {
|
|
26492
27165
|
return path4.relative(worktree, fp);
|
|
26493
27166
|
}
|
|
27167
|
+
function formatReadFooter(agentSpecifiedRange, data) {
|
|
27168
|
+
if (agentSpecifiedRange)
|
|
27169
|
+
return "";
|
|
27170
|
+
if (!data.truncated)
|
|
27171
|
+
return "";
|
|
27172
|
+
const startLine = data.start_line;
|
|
27173
|
+
const endLine = data.end_line;
|
|
27174
|
+
const totalLines = data.total_lines;
|
|
27175
|
+
if (startLine === undefined || endLine === undefined || totalLines === undefined) {
|
|
27176
|
+
return "";
|
|
27177
|
+
}
|
|
27178
|
+
return `
|
|
27179
|
+
(Showing lines ${startLine}-${endLine} of ${totalLines}. Use startLine/endLine to read other sections.)`;
|
|
27180
|
+
}
|
|
26494
27181
|
function buildUnifiedDiff(fp, before, after) {
|
|
26495
27182
|
const SIZE_CAP = 100 * 1024;
|
|
26496
27183
|
if (before.length > SIZE_CAP || after.length > SIZE_CAP) {
|
|
@@ -26677,7 +27364,7 @@ function inferBeforeStart(ops, from, beforeLen) {
|
|
|
26677
27364
|
}
|
|
26678
27365
|
return beforeLen;
|
|
26679
27366
|
}
|
|
26680
|
-
var
|
|
27367
|
+
var z4 = tool4.schema;
|
|
26681
27368
|
var READ_DESCRIPTION = `Read file contents or list directory entries.
|
|
26682
27369
|
|
|
26683
27370
|
Use either startLine/endLine OR offset/limit to read a section of a file.
|
|
@@ -26701,11 +27388,11 @@ function createReadTool(ctx) {
|
|
|
26701
27388
|
return {
|
|
26702
27389
|
description: READ_DESCRIPTION,
|
|
26703
27390
|
args: {
|
|
26704
|
-
filePath:
|
|
26705
|
-
startLine:
|
|
26706
|
-
endLine:
|
|
26707
|
-
limit:
|
|
26708
|
-
offset:
|
|
27391
|
+
filePath: z4.string().describe("Path to file or directory (absolute or relative to project root)"),
|
|
27392
|
+
startLine: z4.number().optional().describe("1-based line to start reading from"),
|
|
27393
|
+
endLine: z4.number().optional().describe("1-based line to stop reading at (inclusive)"),
|
|
27394
|
+
limit: z4.number().optional().describe("Max lines to return (default: 2000)"),
|
|
27395
|
+
offset: z4.number().optional().describe("1-based line number to start reading from (use with limit). Ignored if startLine is provided")
|
|
26709
27396
|
},
|
|
26710
27397
|
execute: async (args, context) => {
|
|
26711
27398
|
const file2 = args.filePath;
|
|
@@ -26743,7 +27430,7 @@ function createReadTool(ctx) {
|
|
|
26743
27430
|
} catch {}
|
|
26744
27431
|
const sizeStr = fileSize > 1048576 ? `${(fileSize / 1048576).toFixed(1)}MB` : fileSize > 1024 ? `${(fileSize / 1024).toFixed(0)}KB` : `${fileSize} bytes`;
|
|
26745
27432
|
const msg = `${label} read successfully`;
|
|
26746
|
-
const imgCallID =
|
|
27433
|
+
const imgCallID = getCallID2(context);
|
|
26747
27434
|
if (imgCallID) {
|
|
26748
27435
|
storeToolMetadata(context.sessionID, imgCallID, {
|
|
26749
27436
|
title: path4.relative(context.worktree, filePath),
|
|
@@ -26776,7 +27463,7 @@ function createReadTool(ctx) {
|
|
|
26776
27463
|
if (data.success === false) {
|
|
26777
27464
|
throw new Error(data.message || "read failed");
|
|
26778
27465
|
}
|
|
26779
|
-
const readCallID =
|
|
27466
|
+
const readCallID = getCallID2(context);
|
|
26780
27467
|
if (data.entries) {
|
|
26781
27468
|
if (readCallID) {
|
|
26782
27469
|
const dp = relativeToWorktree(filePath, context.worktree) || file2;
|
|
@@ -26797,10 +27484,10 @@ function createReadTool(ctx) {
|
|
|
26797
27484
|
storeToolMetadata(context.sessionID, readCallID, { title: dp, metadata: { title: dp } });
|
|
26798
27485
|
}
|
|
26799
27486
|
let output = data.content;
|
|
26800
|
-
|
|
26801
|
-
|
|
26802
|
-
(
|
|
26803
|
-
|
|
27487
|
+
const agentSpecifiedRange = args.startLine !== undefined || args.endLine !== undefined || args.offset !== undefined || args.limit !== undefined;
|
|
27488
|
+
const footer = formatReadFooter(agentSpecifiedRange, data);
|
|
27489
|
+
if (footer)
|
|
27490
|
+
output += footer;
|
|
26804
27491
|
return output;
|
|
26805
27492
|
}
|
|
26806
27493
|
};
|
|
@@ -26826,8 +27513,8 @@ function createWriteTool(ctx, editToolName = "edit") {
|
|
|
26826
27513
|
return {
|
|
26827
27514
|
description: getWriteDescription(editToolName),
|
|
26828
27515
|
args: {
|
|
26829
|
-
filePath:
|
|
26830
|
-
content:
|
|
27516
|
+
filePath: z4.string().describe("Path to the file to write (absolute or relative to project root)"),
|
|
27517
|
+
content: z4.string().describe("The full content to write to the file")
|
|
26831
27518
|
},
|
|
26832
27519
|
execute: async (args, context) => {
|
|
26833
27520
|
const file2 = args.filePath;
|
|
@@ -26880,7 +27567,7 @@ Note: LSP server(s) did not respond in time: ${pendingServers.join(", ")}. Diagn
|
|
|
26880
27567
|
Note: LSP server(s) exited during this edit: ${exitedServers.join(", ")}. Their diagnostics could not be collected.`;
|
|
26881
27568
|
}
|
|
26882
27569
|
const diff = data.diff;
|
|
26883
|
-
const callID =
|
|
27570
|
+
const callID = getCallID2(context);
|
|
26884
27571
|
if (callID) {
|
|
26885
27572
|
const dp = relativeToWorktree(filePath, context.worktree);
|
|
26886
27573
|
const beforeContent = diff?.before ?? "";
|
|
@@ -26909,7 +27596,7 @@ function getEditDescription(writeToolName) {
|
|
|
26909
27596
|
|
|
26910
27597
|
**Modes** (determined by which parameters you provide):
|
|
26911
27598
|
|
|
26912
|
-
Mode priority: operations > edits > symbol (without oldString) > oldString (find/replace). If none match, the call is rejected \u2014 there is no implicit "write" fallback.
|
|
27599
|
+
Mode priority: operations > appendContent > edits > symbol (without oldString) > oldString (find/replace). If none match, the call is rejected \u2014 there is no implicit "write" fallback.
|
|
26913
27600
|
|
|
26914
27601
|
1. **Multi-file transaction** \u2014 pass \`operations\` array
|
|
26915
27602
|
Edits across multiple files with checkpoint-based rollback on failure.
|
|
@@ -26917,33 +27604,37 @@ Mode priority: operations > edits > symbol (without oldString) > oldString (find
|
|
|
26917
27604
|
For \`edit_match\`: include \`match\`, \`replacement\`. For \`write\`: include \`content\`.
|
|
26918
27605
|
Example: \`{ "operations": [{ "file": "a.ts", "command": "edit_match", "match": "old", "replacement": "new" }, { "file": "b.ts", "command": "write", "content": "..." }] }\`
|
|
26919
27606
|
|
|
26920
|
-
2. **
|
|
27607
|
+
2. **Append** \u2014 pass \`filePath\` + \`appendContent\`
|
|
27608
|
+
Appends text to the end of a file, creating the file if it does not exist.
|
|
27609
|
+
Example: \`{ "filePath": "notes.txt", "appendContent": "new line\\n" }\`
|
|
27610
|
+
|
|
27611
|
+
3. **Batch edits** \u2014 pass \`filePath\` + \`edits\` array
|
|
26921
27612
|
Multiple edits in one file atomically. Each edit is either:
|
|
26922
27613
|
- \`{ "oldString": "old", "newString": "new" }\` \u2014 find/replace
|
|
26923
27614
|
- \`{ "startLine": 5, "endLine": 7, "content": "new lines" }\` \u2014 replace line range (1-based, both inclusive)
|
|
26924
27615
|
Set content to empty string to delete lines.
|
|
26925
27616
|
|
|
26926
|
-
|
|
27617
|
+
4. **Symbol replace** \u2014 pass \`filePath\` + \`symbol\` + \`content\`
|
|
26927
27618
|
Replaces an entire named symbol (function, class, type) with new content.
|
|
26928
27619
|
Includes decorators, attributes, and doc comments in the replacement range.
|
|
26929
27620
|
**Important:** You must NOT provide \`oldString\` when using symbol mode \u2014 if present, the tool silently falls back to find/replace mode.
|
|
26930
27621
|
Example: \`{ "filePath": "src/app.ts", "symbol": "handleRequest", "content": "function handleRequest() { ... }" }\`
|
|
26931
27622
|
|
|
26932
|
-
|
|
27623
|
+
5. **Find and replace** \u2014 pass \`filePath\` + \`oldString\` + \`newString\`
|
|
26933
27624
|
Finds the exact text in \`oldString\` and replaces it with \`newString\`.
|
|
26934
27625
|
Supports fuzzy matching (handles whitespace differences automatically).
|
|
26935
27626
|
If multiple matches exist, specify which one with \`occurrence\` or use \`replaceAll: true\`.
|
|
26936
27627
|
Example: \`{ "filePath": "src/app.ts", "oldString": "const x = 1", "newString": "const x = 2" }\`
|
|
26937
27628
|
|
|
26938
|
-
|
|
27629
|
+
6. **Replace all occurrences** \u2014 add \`replaceAll: true\`
|
|
26939
27630
|
Replaces every occurrence of \`oldString\` in the file.
|
|
26940
27631
|
Example: \`{ "filePath": "src/app.ts", "oldString": "oldName", "newString": "newName", "replaceAll": true }\`
|
|
26941
27632
|
|
|
26942
|
-
|
|
27633
|
+
7. **Select specific occurrence** \u2014 add \`occurrence: N\` (0-indexed)
|
|
26943
27634
|
When multiple matches exist, select the Nth one (0 = first, 1 = second, etc.).
|
|
26944
27635
|
Example: \`{ "filePath": "src/app.ts", "oldString": "TODO", "newString": "DONE", "occurrence": 0 }\`
|
|
26945
27636
|
|
|
26946
|
-
Note: Modes
|
|
27637
|
+
Note: Modes 6 and 7 are options on mode 5 (find/replace) \u2014 they require \`oldString\`.
|
|
26947
27638
|
|
|
26948
27639
|
**Behavior:**
|
|
26949
27640
|
- Backs up files before editing (recoverable via aft_safety undo)
|
|
@@ -26960,16 +27651,17 @@ function createEditTool(ctx, writeToolName = "write") {
|
|
|
26960
27651
|
return {
|
|
26961
27652
|
description: getEditDescription(writeToolName),
|
|
26962
27653
|
args: {
|
|
26963
|
-
filePath:
|
|
26964
|
-
oldString:
|
|
26965
|
-
newString:
|
|
26966
|
-
replaceAll:
|
|
26967
|
-
occurrence:
|
|
26968
|
-
symbol:
|
|
26969
|
-
content:
|
|
26970
|
-
|
|
26971
|
-
|
|
26972
|
-
|
|
27654
|
+
filePath: z4.string().optional().describe("Path to the file to edit (absolute or relative to project root). Required for all modes except 'operations' multi-file transactions"),
|
|
27655
|
+
oldString: z4.string().optional().describe("Text to find (exact match, with fuzzy fallback)"),
|
|
27656
|
+
newString: z4.string().optional().describe("Text to replace with (omit or set to empty string to delete the matched text)"),
|
|
27657
|
+
replaceAll: z4.boolean().optional().describe("Replace all occurrences"),
|
|
27658
|
+
occurrence: z4.number().optional().describe("0-indexed occurrence to replace when multiple matches exist"),
|
|
27659
|
+
symbol: z4.string().optional().describe("Named symbol to replace (function, class, type)"),
|
|
27660
|
+
content: z4.string().optional().describe("New content for symbol replace or file write"),
|
|
27661
|
+
appendContent: z4.string().optional().describe("Text to append to the end of filePath; creates the file if needed"),
|
|
27662
|
+
edits: z4.array(z4.record(z4.string(), z4.unknown())).optional().describe("Batch edits \u2014 array of { oldString: string, newString: string } or { startLine: number (1-based), endLine: number (1-based, inclusive), content: string }"),
|
|
27663
|
+
operations: z4.array(z4.record(z4.string(), z4.unknown())).optional().describe("Transaction \u2014 array of { file: string, command: 'edit_match' | 'write', match?: string, replacement?: string, content?: string } for multi-file edits with rollback. Note: uses 'file'/'match'/'replacement' (not filePath/oldString/newString)"),
|
|
27664
|
+
dryRun: z4.boolean().optional().describe("Preview changes without applying (returns diff, default: false)")
|
|
26973
27665
|
},
|
|
26974
27666
|
execute: async (args, context) => {
|
|
26975
27667
|
const argsRecord = args;
|
|
@@ -27007,7 +27699,12 @@ function createEditTool(ctx, writeToolName = "write") {
|
|
|
27007
27699
|
});
|
|
27008
27700
|
const params = { file: filePath };
|
|
27009
27701
|
let command;
|
|
27010
|
-
if (
|
|
27702
|
+
if (typeof args.appendContent === "string") {
|
|
27703
|
+
command = "edit_match";
|
|
27704
|
+
params.op = "append";
|
|
27705
|
+
params.append_content = args.appendContent;
|
|
27706
|
+
params.create_dirs = true;
|
|
27707
|
+
} else if (Array.isArray(args.edits)) {
|
|
27011
27708
|
command = "batch";
|
|
27012
27709
|
params.edits = args.edits.map((edit) => {
|
|
27013
27710
|
const translated = {};
|
|
@@ -27051,7 +27748,7 @@ function createEditTool(ctx, writeToolName = "write") {
|
|
|
27051
27748
|
const data = await callBridge(ctx, context, command, params);
|
|
27052
27749
|
if (!args.dryRun && data.success && data.diff) {
|
|
27053
27750
|
const diff = data.diff;
|
|
27054
|
-
const callID =
|
|
27751
|
+
const callID = getCallID2(context);
|
|
27055
27752
|
if (callID) {
|
|
27056
27753
|
const dp = relativeToWorktree(filePath, context.worktree);
|
|
27057
27754
|
const beforeContent = diff.before ?? "";
|
|
@@ -27150,7 +27847,7 @@ function createApplyPatchTool(ctx) {
|
|
|
27150
27847
|
return {
|
|
27151
27848
|
description: APPLY_PATCH_DESCRIPTION,
|
|
27152
27849
|
args: {
|
|
27153
|
-
patchText:
|
|
27850
|
+
patchText: z4.string().describe("The full patch text including Begin/End markers")
|
|
27154
27851
|
},
|
|
27155
27852
|
execute: async (args, context) => {
|
|
27156
27853
|
const patchText = args.patchText;
|
|
@@ -27182,6 +27879,7 @@ function createApplyPatchTool(ctx) {
|
|
|
27182
27879
|
}
|
|
27183
27880
|
}
|
|
27184
27881
|
const relPaths = Array.from(affectedAbs).map((abs) => path4.relative(context.worktree, abs));
|
|
27882
|
+
const multiFileWritePaths = Array.from(affectedAbs);
|
|
27185
27883
|
await context.ask({
|
|
27186
27884
|
permission: "edit",
|
|
27187
27885
|
patterns: relPaths,
|
|
@@ -27201,12 +27899,18 @@ function createApplyPatchTool(ctx) {
|
|
|
27201
27899
|
} catch {}
|
|
27202
27900
|
}
|
|
27203
27901
|
const results = [];
|
|
27902
|
+
const failures = [];
|
|
27204
27903
|
const perFileDiffs = [];
|
|
27205
|
-
let patchFailed = false;
|
|
27206
27904
|
for (const hunk of hunks) {
|
|
27207
27905
|
const filePath = path4.resolve(context.directory, hunk.path);
|
|
27208
27906
|
switch (hunk.type) {
|
|
27209
27907
|
case "add": {
|
|
27908
|
+
if (fs3.existsSync(filePath)) {
|
|
27909
|
+
const msg = `Failed to create ${hunk.path}: file already exists. Use *** Update File: to modify, or *** Delete File: first if you want to replace it entirely.`;
|
|
27910
|
+
results.push(msg);
|
|
27911
|
+
failures.push(hunk.path);
|
|
27912
|
+
break;
|
|
27913
|
+
}
|
|
27210
27914
|
try {
|
|
27211
27915
|
const content = hunk.contents.endsWith(`
|
|
27212
27916
|
`) ? hunk.contents : `${hunk.contents}
|
|
@@ -27216,7 +27920,8 @@ function createApplyPatchTool(ctx) {
|
|
|
27216
27920
|
content,
|
|
27217
27921
|
create_dirs: true,
|
|
27218
27922
|
diagnostics: true,
|
|
27219
|
-
include_diff: true
|
|
27923
|
+
include_diff: true,
|
|
27924
|
+
multi_file_write_paths: multiFileWritePaths
|
|
27220
27925
|
});
|
|
27221
27926
|
const wrDiff = writeResult.diff;
|
|
27222
27927
|
perFileDiffs.push({
|
|
@@ -27228,8 +27933,15 @@ function createApplyPatchTool(ctx) {
|
|
|
27228
27933
|
});
|
|
27229
27934
|
results.push(`Created ${hunk.path}`);
|
|
27230
27935
|
} catch (e) {
|
|
27231
|
-
|
|
27232
|
-
results.push(
|
|
27936
|
+
const msg = `Failed to create ${hunk.path}: ${e instanceof Error ? e.message : e}`;
|
|
27937
|
+
results.push(msg);
|
|
27938
|
+
failures.push(hunk.path);
|
|
27939
|
+
const filePath2 = path4.resolve(context.directory, hunk.path);
|
|
27940
|
+
if (fs3.existsSync(filePath2)) {
|
|
27941
|
+
try {
|
|
27942
|
+
await callBridge(ctx, context, "delete_file", { file: filePath2 });
|
|
27943
|
+
} catch {}
|
|
27944
|
+
}
|
|
27233
27945
|
}
|
|
27234
27946
|
break;
|
|
27235
27947
|
}
|
|
@@ -27246,8 +27958,8 @@ function createApplyPatchTool(ctx) {
|
|
|
27246
27958
|
});
|
|
27247
27959
|
results.push(`Deleted ${hunk.path}`);
|
|
27248
27960
|
} catch (e) {
|
|
27249
|
-
patchFailed = true;
|
|
27250
27961
|
results.push(`Failed to delete ${hunk.path}: ${e instanceof Error ? e.message : e}`);
|
|
27962
|
+
failures.push(hunk.path);
|
|
27251
27963
|
}
|
|
27252
27964
|
break;
|
|
27253
27965
|
}
|
|
@@ -27261,7 +27973,8 @@ function createApplyPatchTool(ctx) {
|
|
|
27261
27973
|
content: newContent,
|
|
27262
27974
|
create_dirs: true,
|
|
27263
27975
|
diagnostics: true,
|
|
27264
|
-
include_diff: true
|
|
27976
|
+
include_diff: true,
|
|
27977
|
+
multi_file_write_paths: multiFileWritePaths
|
|
27265
27978
|
});
|
|
27266
27979
|
const diags = writeResult.lsp_diagnostics;
|
|
27267
27980
|
if (diags && diags.length > 0) {
|
|
@@ -27289,51 +28002,60 @@ ${diagLines}`);
|
|
|
27289
28002
|
deletions
|
|
27290
28003
|
});
|
|
27291
28004
|
if (hunk.move_path) {
|
|
27292
|
-
|
|
28005
|
+
try {
|
|
28006
|
+
const deleteResult = await callBridge(ctx, context, "delete_file", {
|
|
28007
|
+
file: filePath
|
|
28008
|
+
});
|
|
28009
|
+
if (deleteResult.success === false) {
|
|
28010
|
+
throw new Error(deleteResult.message ?? "delete failed");
|
|
28011
|
+
}
|
|
28012
|
+
} catch (deleteError) {
|
|
28013
|
+
try {
|
|
28014
|
+
if (!checkpointCreated) {
|
|
28015
|
+
throw new Error("pre-patch checkpoint was not created");
|
|
28016
|
+
}
|
|
28017
|
+
const rollbackResult = await callBridge(ctx, context, "restore_checkpoint", {
|
|
28018
|
+
name: checkpointName
|
|
28019
|
+
});
|
|
28020
|
+
if (rollbackResult.success === false) {
|
|
28021
|
+
throw new Error(rollbackResult.message ?? "checkpoint restore failed");
|
|
28022
|
+
}
|
|
28023
|
+
if (newlyCreatedAbs.has(targetPath) && fs3.existsSync(targetPath)) {
|
|
28024
|
+
const cleanupResult = await callBridge(ctx, context, "delete_file", {
|
|
28025
|
+
file: targetPath
|
|
28026
|
+
});
|
|
28027
|
+
if (cleanupResult.success === false) {
|
|
28028
|
+
throw new Error(cleanupResult.message ?? "new destination cleanup failed");
|
|
28029
|
+
}
|
|
28030
|
+
}
|
|
28031
|
+
} catch (rollbackError) {
|
|
28032
|
+
throw new Error(`success: false; code: move_partial_failure; files: [${filePath}, ${targetPath}]; wrote destination ${targetPath}, but failed to delete source ${filePath} (${formatError2(deleteError)}) and failed to restore pre-patch checkpoint ${checkpointName} (${formatError2(rollbackError)}). Both copies may exist or destination content may be changed: ${filePath}, ${targetPath}`);
|
|
28033
|
+
}
|
|
28034
|
+
throw new Error(`source delete failed after writing move destination; restored pre-patch checkpoint ${checkpointName}: ${formatError2(deleteError)}`);
|
|
28035
|
+
}
|
|
27293
28036
|
results.push(`Updated and moved ${hunk.path} \u2192 ${hunk.move_path}`);
|
|
27294
28037
|
} else {
|
|
27295
28038
|
results.push(`Updated ${hunk.path}`);
|
|
27296
28039
|
}
|
|
27297
28040
|
} catch (e) {
|
|
27298
|
-
patchFailed = true;
|
|
27299
28041
|
results.push(`Failed to update ${hunk.path}: ${e instanceof Error ? e.message : e}`);
|
|
28042
|
+
failures.push(hunk.path);
|
|
27300
28043
|
break;
|
|
27301
28044
|
}
|
|
27302
28045
|
break;
|
|
27303
28046
|
}
|
|
27304
28047
|
}
|
|
27305
28048
|
}
|
|
27306
|
-
if (
|
|
27307
|
-
const
|
|
27308
|
-
if (
|
|
27309
|
-
|
|
27310
|
-
|
|
27311
|
-
|
|
27312
|
-
} catch {
|
|
27313
|
-
rollbackNotes.push("checkpoint restore FAILED, pre-existing files may be inconsistent");
|
|
27314
|
-
}
|
|
27315
|
-
} else if (checkpointPaths.length > 0) {
|
|
27316
|
-
rollbackNotes.push("no checkpoint was created, pre-existing files may be inconsistent");
|
|
27317
|
-
}
|
|
27318
|
-
let newlyDeleted = 0;
|
|
27319
|
-
for (const createdAbs of newlyCreatedAbs) {
|
|
27320
|
-
if (!fs3.existsSync(createdAbs))
|
|
27321
|
-
continue;
|
|
27322
|
-
try {
|
|
27323
|
-
await callBridge(ctx, context, "delete_file", { file: createdAbs });
|
|
27324
|
-
newlyDeleted++;
|
|
27325
|
-
} catch {
|
|
27326
|
-
rollbackNotes.push(`failed to delete newly-created ${path4.relative(context.worktree, createdAbs)}`);
|
|
27327
|
-
}
|
|
27328
|
-
}
|
|
27329
|
-
if (newlyDeleted > 0) {
|
|
27330
|
-
rollbackNotes.push(`removed ${newlyDeleted} newly-created file(s)`);
|
|
27331
|
-
}
|
|
27332
|
-
results.push(rollbackNotes.length > 0 ? `Patch failed \u2014 ${rollbackNotes.join("; ")}.` : "Patch failed \u2014 nothing to roll back.");
|
|
27333
|
-
return results.join(`
|
|
28049
|
+
if (failures.length > 0) {
|
|
28050
|
+
const partial2 = failures.length < hunks.length;
|
|
28051
|
+
const summary = partial2 ? `Patch partially applied \u2014 ${hunks.length - failures.length} of ${hunks.length} hunk(s) succeeded. Failed: ${failures.join(", ")}. Successful changes are kept; use \`aft_safety\` to revert if you want to abort.` : `Patch failed \u2014 none of the ${hunks.length} hunk(s) applied: ${failures.join(", ")}.`;
|
|
28052
|
+
results.push(summary);
|
|
28053
|
+
if (!partial2) {
|
|
28054
|
+
return results.join(`
|
|
27334
28055
|
`);
|
|
28056
|
+
}
|
|
27335
28057
|
}
|
|
27336
|
-
const callID =
|
|
28058
|
+
const callID = getCallID2(context);
|
|
27337
28059
|
if (callID) {
|
|
27338
28060
|
const diffByPath = new Map(perFileDiffs.map((d) => [d.filePath, d]));
|
|
27339
28061
|
const files = hunks.map((h) => {
|
|
@@ -27386,7 +28108,7 @@ function createDeleteTool(ctx) {
|
|
|
27386
28108
|
return {
|
|
27387
28109
|
description: DELETE_DESCRIPTION,
|
|
27388
28110
|
args: {
|
|
27389
|
-
filePath:
|
|
28111
|
+
filePath: z4.string().describe("Path to file to delete")
|
|
27390
28112
|
},
|
|
27391
28113
|
execute: async (args, context) => {
|
|
27392
28114
|
const filePath = path4.isAbsolute(args.filePath) ? args.filePath : path4.resolve(context.directory, args.filePath);
|
|
@@ -27410,8 +28132,8 @@ function createMoveTool(ctx) {
|
|
|
27410
28132
|
return {
|
|
27411
28133
|
description: MOVE_DESCRIPTION,
|
|
27412
28134
|
args: {
|
|
27413
|
-
filePath:
|
|
27414
|
-
destination:
|
|
28135
|
+
filePath: z4.string().describe("Source file path to move"),
|
|
28136
|
+
destination: z4.string().describe("Destination file path")
|
|
27415
28137
|
},
|
|
27416
28138
|
execute: async (args, context) => {
|
|
27417
28139
|
const filePath = path4.isAbsolute(args.filePath) ? args.filePath : path4.resolve(context.directory, args.filePath);
|
|
@@ -27435,6 +28157,7 @@ function createMoveTool(ctx) {
|
|
|
27435
28157
|
}
|
|
27436
28158
|
function hoistedTools(ctx) {
|
|
27437
28159
|
return {
|
|
28160
|
+
bash: createBashTool(ctx),
|
|
27438
28161
|
read: createReadTool(ctx),
|
|
27439
28162
|
write: createWriteTool(ctx, "edit"),
|
|
27440
28163
|
edit: createEditTool(ctx, "write"),
|
|
@@ -27443,6 +28166,9 @@ function hoistedTools(ctx) {
|
|
|
27443
28166
|
aft_move: createMoveTool(ctx)
|
|
27444
28167
|
};
|
|
27445
28168
|
}
|
|
28169
|
+
function formatError2(error49) {
|
|
28170
|
+
return error49 instanceof Error ? error49.message : String(error49);
|
|
28171
|
+
}
|
|
27446
28172
|
function aftPrefixedTools(ctx) {
|
|
27447
28173
|
const aftEditTool = createEditTool(ctx, "aft_write");
|
|
27448
28174
|
return {
|
|
@@ -27485,8 +28211,8 @@ function aftPrefixedTools(ctx) {
|
|
|
27485
28211
|
}
|
|
27486
28212
|
|
|
27487
28213
|
// src/tools/imports.ts
|
|
27488
|
-
import { tool as
|
|
27489
|
-
var
|
|
28214
|
+
import { tool as tool5 } from "@opencode-ai/plugin";
|
|
28215
|
+
var z5 = tool5.schema;
|
|
27490
28216
|
function importTools(ctx) {
|
|
27491
28217
|
return {
|
|
27492
28218
|
aft_import: {
|
|
@@ -27503,15 +28229,15 @@ function importTools(ctx) {
|
|
|
27503
28229
|
` + `- remove: { file, removed, module, name?, formatted, syntax_valid?, format_skipped_reason?, validation_errors?, validate_skipped_reason?, backup_id?, lsp_diagnostics? }
|
|
27504
28230
|
` + "- organize: { file, groups: [{ name, count }], removed_duplicates, formatted?, syntax_valid?, format_skipped_reason?, validation_errors?, validate_skipped_reason?, backup_id?, lsp_diagnostics? }",
|
|
27505
28231
|
args: {
|
|
27506
|
-
op:
|
|
27507
|
-
filePath:
|
|
27508
|
-
module:
|
|
27509
|
-
names:
|
|
27510
|
-
defaultImport:
|
|
27511
|
-
typeOnly:
|
|
27512
|
-
removeName:
|
|
27513
|
-
validate:
|
|
27514
|
-
dryRun:
|
|
28232
|
+
op: z5.enum(["add", "remove", "organize"]).describe("Import operation"),
|
|
28233
|
+
filePath: z5.string().describe("Path to the file (absolute or relative to project root)"),
|
|
28234
|
+
module: z5.string().optional().describe("Module path (required for add, remove \u2014 e.g. 'react', './utils', 'std::fmt')"),
|
|
28235
|
+
names: z5.array(z5.string()).optional().describe("Named imports to add (e.g. ['useState', 'useEffect'])"),
|
|
28236
|
+
defaultImport: z5.string().optional().describe("Default import name (e.g. 'React')"),
|
|
28237
|
+
typeOnly: z5.boolean().optional().describe("Type-only import (TS only, default: false)"),
|
|
28238
|
+
removeName: z5.string().optional().describe("Named import to remove for 'remove' op; omit to remove entire import"),
|
|
28239
|
+
validate: z5.enum(["syntax", "full"]).optional().describe("Validation level: 'syntax' (default) or 'full'. Syntax = tree-sitter parse check only. Full = also runs LSP type-checking (slower, catches more errors)"),
|
|
28240
|
+
dryRun: z5.boolean().optional().describe("Preview without modifying the file (default: false)")
|
|
27515
28241
|
},
|
|
27516
28242
|
execute: async (args, context) => {
|
|
27517
28243
|
const op = args.op;
|
|
@@ -27556,8 +28282,8 @@ function importTools(ctx) {
|
|
|
27556
28282
|
}
|
|
27557
28283
|
|
|
27558
28284
|
// src/tools/lsp.ts
|
|
27559
|
-
import { tool as
|
|
27560
|
-
var
|
|
28285
|
+
import { tool as tool6 } from "@opencode-ai/plugin";
|
|
28286
|
+
var z6 = tool6.schema;
|
|
27561
28287
|
function lspTools(ctx) {
|
|
27562
28288
|
const diagnosticsTool = {
|
|
27563
28289
|
description: "On-demand LSP file/scope check. Spawns the relevant language server (if " + "registered for the file's extension), opens the document, prefers LSP 3.17 " + "pull diagnostics when supported, and falls back to push + waitMs otherwise. " + "NOT a project-wide type checker \u2014 for full coverage run `tsc --noEmit`, " + "`cargo check`, `pyright`, etc.\n" + `
|
|
@@ -27579,10 +28305,10 @@ function lspTools(ctx) {
|
|
|
27579
28305
|
` + "- `total: 0, complete: true, lsp_servers_used: [{status: 'pull_ok'}]` \u2192 file is genuinely clean.\n" + "- `total: 0, lsp_servers_used: []` \u2192 **nothing was checked** (no server registered for this extension). Tell the user, don't claim 'no errors'.\n" + "- `lsp_servers_used: [{status: 'binary_not_installed: <name>'}]` \u2192 server matched the extension but its binary isn't on PATH. Tell the user to install it.\n" + "- `lsp_servers_used: [{status: 'no_root_marker (...)'}]` \u2192 server is registered but couldn't find a workspace root marker walking up from this file. The user's project layout doesn't match what the server expects.\n" + "- `complete: false` (directory mode) \u2192 some files in the directory weren't checked; see `unchecked_files`.\n" + `
|
|
27580
28306
|
` + "**When this tool gives an unhelpful answer**, run `bunx --bun @cortexkit/aft doctor lsp <filePath>` from a terminal to get a full per-server breakdown (registered servers, binary resolution, root-marker resolution, spawn outcome).",
|
|
27581
28307
|
args: {
|
|
27582
|
-
filePath:
|
|
27583
|
-
directory:
|
|
27584
|
-
severity:
|
|
27585
|
-
waitMs:
|
|
28308
|
+
filePath: z6.string().optional().describe("Path to a file to check. Mutually exclusive with 'directory'. Omit both to dump all cached diagnostics."),
|
|
28309
|
+
directory: z6.string().optional().describe("Path to a directory. Returns cached diagnostics + workspace pull from active servers; lists files we have no info for in 'unchecked_files'. Capped at 200 walked files."),
|
|
28310
|
+
severity: z6.enum(["error", "warning", "information", "hint", "all"]).optional().describe("Filter by severity (default: 'all')."),
|
|
28311
|
+
waitMs: z6.number().optional().describe("Wait up to N ms (max 10000, default 0) for push diagnostics to arrive. Only matters for servers that don't support LSP 3.17 pull (bash-language-server, yaml-language-server). Use after an edit to let the server re-analyze.")
|
|
27586
28312
|
},
|
|
27587
28313
|
execute: async (args, context) => {
|
|
27588
28314
|
const filePath = args.filePath || undefined;
|
|
@@ -27613,8 +28339,8 @@ function lspTools(ctx) {
|
|
|
27613
28339
|
}
|
|
27614
28340
|
|
|
27615
28341
|
// src/tools/navigation.ts
|
|
27616
|
-
import { tool as
|
|
27617
|
-
var
|
|
28342
|
+
import { tool as tool7 } from "@opencode-ai/plugin";
|
|
28343
|
+
var z7 = tool7.schema;
|
|
27618
28344
|
function navigationTools(ctx) {
|
|
27619
28345
|
return {
|
|
27620
28346
|
aft_navigate: {
|
|
@@ -27631,11 +28357,11 @@ function navigationTools(ctx) {
|
|
|
27631
28357
|
|
|
27632
28358
|
`,
|
|
27633
28359
|
args: {
|
|
27634
|
-
op:
|
|
27635
|
-
filePath:
|
|
27636
|
-
symbol:
|
|
27637
|
-
depth:
|
|
27638
|
-
expression:
|
|
28360
|
+
op: z7.enum(["call_tree", "callers", "trace_to", "impact", "trace_data"]).describe("Navigation operation"),
|
|
28361
|
+
filePath: z7.string().describe("Path to the source file containing the symbol (absolute or relative to project root)"),
|
|
28362
|
+
symbol: z7.string().describe("Name of the symbol to analyze"),
|
|
28363
|
+
depth: z7.number().optional().describe("Max traversal depth (default: call_tree=5, callers=1, trace_to=10, impact=5, trace_data=5)"),
|
|
28364
|
+
expression: z7.string().optional().describe("Expression to track through data flow (required for trace_data op)")
|
|
27639
28365
|
},
|
|
27640
28366
|
execute: async (args, context) => {
|
|
27641
28367
|
const params = {
|
|
@@ -27662,7 +28388,7 @@ function navigationTools(ctx) {
|
|
|
27662
28388
|
// src/tools/reading.ts
|
|
27663
28389
|
import { readdir } from "fs/promises";
|
|
27664
28390
|
import { extname as extname2, join as join18, resolve as resolve8 } from "path";
|
|
27665
|
-
import { tool as
|
|
28391
|
+
import { tool as tool8 } from "@opencode-ai/plugin";
|
|
27666
28392
|
var OUTLINE_EXTENSIONS = new Set([
|
|
27667
28393
|
".ts",
|
|
27668
28394
|
".tsx",
|
|
@@ -27699,7 +28425,7 @@ var OUTLINE_EXTENSIONS = new Set([
|
|
|
27699
28425
|
".sh",
|
|
27700
28426
|
".bash"
|
|
27701
28427
|
]);
|
|
27702
|
-
var
|
|
28428
|
+
var z8 = tool8.schema;
|
|
27703
28429
|
function readingTools(ctx) {
|
|
27704
28430
|
return {
|
|
27705
28431
|
aft_outline: {
|
|
@@ -27707,10 +28433,10 @@ function readingTools(ctx) {
|
|
|
27707
28433
|
|
|
27708
28434
|
` + "Provide exactly ONE of: 'filePath', 'files', 'directory', or 'url'.",
|
|
27709
28435
|
args: {
|
|
27710
|
-
filePath:
|
|
27711
|
-
files:
|
|
27712
|
-
directory:
|
|
27713
|
-
url:
|
|
28436
|
+
filePath: z8.string().optional().describe("Path to a single file to outline"),
|
|
28437
|
+
files: z8.array(z8.string()).optional().describe("Array of file paths to outline in one call"),
|
|
28438
|
+
directory: z8.string().optional().describe("Directory to outline recursively (200 file limit)"),
|
|
28439
|
+
url: z8.string().optional().describe("HTTP/HTTPS URL of an HTML or Markdown document to fetch and outline")
|
|
27714
28440
|
},
|
|
27715
28441
|
execute: async (args, context) => {
|
|
27716
28442
|
const filesArg = Array.isArray(args.files) ? args.files : undefined;
|
|
@@ -27780,11 +28506,11 @@ function readingTools(ctx) {
|
|
|
27780
28506
|
|
|
27781
28507
|
Provide exactly ONE of 'filePath' or 'url'. Pass either 'symbol' for a single lookup or 'symbols' for multiple in one call.`,
|
|
27782
28508
|
args: {
|
|
27783
|
-
filePath:
|
|
27784
|
-
url:
|
|
27785
|
-
symbol:
|
|
27786
|
-
symbols:
|
|
27787
|
-
contextLines:
|
|
28509
|
+
filePath: z8.string().optional().describe("Path to file (absolute or relative to project root)"),
|
|
28510
|
+
url: z8.string().optional().describe("HTTP/HTTPS URL of an HTML or Markdown document to fetch and zoom into"),
|
|
28511
|
+
symbol: z8.string().optional().describe("Symbol name for code, or heading text for Markdown/HTML"),
|
|
28512
|
+
symbols: z8.array(z8.string()).optional().describe("Array of symbol names or heading texts for a single batched call"),
|
|
28513
|
+
contextLines: z8.number().optional().describe("Lines of context before/after the symbol (default: 3)")
|
|
27788
28514
|
},
|
|
27789
28515
|
execute: async (args, context) => {
|
|
27790
28516
|
const hasFilePath = typeof args.filePath === "string" && args.filePath.length > 0;
|
|
@@ -27885,7 +28611,7 @@ ${lines}`;
|
|
|
27885
28611
|
}
|
|
27886
28612
|
|
|
27887
28613
|
// src/tools/refactoring.ts
|
|
27888
|
-
import { tool as
|
|
28614
|
+
import { tool as tool9 } from "@opencode-ai/plugin";
|
|
27889
28615
|
|
|
27890
28616
|
// src/lsp.ts
|
|
27891
28617
|
var LSP_SYMBOL_KIND_MAP = {
|
|
@@ -27944,7 +28670,7 @@ async function queryLspHints(client, symbolName, directory) {
|
|
|
27944
28670
|
}
|
|
27945
28671
|
|
|
27946
28672
|
// src/tools/refactoring.ts
|
|
27947
|
-
var
|
|
28673
|
+
var z9 = tool9.schema;
|
|
27948
28674
|
function refactoringTools(ctx) {
|
|
27949
28675
|
return {
|
|
27950
28676
|
aft_refactor: {
|
|
@@ -27962,16 +28688,16 @@ function refactoringTools(ctx) {
|
|
|
27962
28688
|
|
|
27963
28689
|
` + "Returns: move dry-run { ok, dry_run, diffs }; move apply { ok, files_modified, consumers_updated, checkpoint_name, results }. extract returns { file, name, parameters, return_type, syntax_valid, formatted, ... }. inline returns { file, symbol, call_context, substitutions, conflicts, syntax_valid, formatted, ... }.",
|
|
27964
28690
|
args: {
|
|
27965
|
-
op:
|
|
27966
|
-
filePath:
|
|
27967
|
-
symbol:
|
|
27968
|
-
destination:
|
|
27969
|
-
scope:
|
|
27970
|
-
name:
|
|
27971
|
-
startLine:
|
|
27972
|
-
endLine:
|
|
27973
|
-
callSiteLine:
|
|
27974
|
-
dryRun:
|
|
28691
|
+
op: z9.enum(["move", "extract", "inline"]).describe("Refactoring operation"),
|
|
28692
|
+
filePath: z9.string().describe("Path to the source file (absolute or relative to project root)"),
|
|
28693
|
+
symbol: z9.string().optional().describe("Symbol name \u2014 required for 'move' and 'inline' ops"),
|
|
28694
|
+
destination: z9.string().optional().describe("Target file path \u2014 required for 'move' op"),
|
|
28695
|
+
scope: z9.string().optional().describe("Disambiguation scope for 'move' op \u2014 when multiple top-level symbols share the same name, specify the containing scope to disambiguate (e.g. 'MyClass'). Does NOT enable access to nested symbols or class methods."),
|
|
28696
|
+
name: z9.string().optional().describe("New function name \u2014 required for 'extract' op"),
|
|
28697
|
+
startLine: z9.number().optional().describe("1-based start line \u2014 required for 'extract' op"),
|
|
28698
|
+
endLine: z9.number().optional().describe("1-based end line (inclusive) \u2014 required for 'extract' op"),
|
|
28699
|
+
callSiteLine: z9.number().optional().describe("1-based call site line \u2014 required for 'inline' op"),
|
|
28700
|
+
dryRun: z9.boolean().optional().describe("Preview changes as diff without modifying files (default: false)")
|
|
27975
28701
|
},
|
|
27976
28702
|
execute: async (args, context) => {
|
|
27977
28703
|
const op = args.op;
|
|
@@ -28041,8 +28767,8 @@ function refactoringTools(ctx) {
|
|
|
28041
28767
|
}
|
|
28042
28768
|
|
|
28043
28769
|
// src/tools/safety.ts
|
|
28044
|
-
import { tool as
|
|
28045
|
-
var
|
|
28770
|
+
import { tool as tool10 } from "@opencode-ai/plugin";
|
|
28771
|
+
var z10 = tool10.schema;
|
|
28046
28772
|
function safetyTools(ctx) {
|
|
28047
28773
|
return {
|
|
28048
28774
|
aft_safety: {
|
|
@@ -28063,10 +28789,10 @@ function safetyTools(ctx) {
|
|
|
28063
28789
|
|
|
28064
28790
|
` + "Returns: undo { path, backup_id }. history { file, entries }. checkpoint { ok, name }. restore { ok, name }. list { checkpoints }.",
|
|
28065
28791
|
args: {
|
|
28066
|
-
op:
|
|
28067
|
-
filePath:
|
|
28068
|
-
name:
|
|
28069
|
-
files:
|
|
28792
|
+
op: z10.enum(["undo", "history", "checkpoint", "restore", "list"]).describe("Safety operation"),
|
|
28793
|
+
filePath: z10.string().optional().describe("File path (required for undo, history). Absolute or relative to project root"),
|
|
28794
|
+
name: z10.string().optional().describe("Checkpoint name (required for checkpoint, restore)"),
|
|
28795
|
+
files: z10.array(z10.string()).optional().describe("Specific files to include in checkpoint (optional, defaults to all tracked files)")
|
|
28070
28796
|
},
|
|
28071
28797
|
execute: async (args, context) => {
|
|
28072
28798
|
const op = args.op;
|
|
@@ -28268,8 +28994,8 @@ function semanticTools(ctx) {
|
|
|
28268
28994
|
}
|
|
28269
28995
|
|
|
28270
28996
|
// src/tools/structure.ts
|
|
28271
|
-
import { tool as
|
|
28272
|
-
var
|
|
28997
|
+
import { tool as tool11 } from "@opencode-ai/plugin";
|
|
28998
|
+
var z11 = tool11.schema;
|
|
28273
28999
|
function structureTools(ctx) {
|
|
28274
29000
|
return {
|
|
28275
29001
|
aft_transform: {
|
|
@@ -28294,20 +29020,20 @@ function structureTools(ctx) {
|
|
|
28294
29020
|
` + `- add_decorator: { file, target, decorator, formatted, syntax_valid?, format_skipped_reason?, validation_errors?, validate_skipped_reason?, backup_id?, lsp_diagnostics? }
|
|
28295
29021
|
` + "- add_struct_tags: { file, target, field, tag_string, formatted, syntax_valid?, format_skipped_reason?, validation_errors?, validate_skipped_reason?, backup_id?, lsp_diagnostics? }",
|
|
28296
29022
|
args: {
|
|
28297
|
-
op:
|
|
28298
|
-
filePath:
|
|
28299
|
-
container:
|
|
28300
|
-
code:
|
|
28301
|
-
position:
|
|
28302
|
-
target:
|
|
28303
|
-
derives:
|
|
28304
|
-
catchBody:
|
|
28305
|
-
decorator:
|
|
28306
|
-
field:
|
|
28307
|
-
tag:
|
|
28308
|
-
value:
|
|
28309
|
-
validate:
|
|
28310
|
-
dryRun:
|
|
29023
|
+
op: z11.enum(["add_member", "add_derive", "wrap_try_catch", "add_decorator", "add_struct_tags"]).describe("Transformation operation"),
|
|
29024
|
+
filePath: z11.string().describe("Path to the source file (absolute or relative to project root)"),
|
|
29025
|
+
container: z11.string().optional().describe("Container name for add_member \u2014 the class, struct, or impl block to insert into. Appears as 'scope' in the response."),
|
|
29026
|
+
code: z11.string().optional().describe("Member code to insert (add_member)"),
|
|
29027
|
+
position: z11.string().optional().describe("For add_member: 'first', 'last' (default), 'before:name', 'after:name'. For add_decorator: 'first' (default) or 'last' only."),
|
|
29028
|
+
target: z11.string().optional().describe("Target symbol name (add_derive: struct/enum, wrap_try_catch: function, add_decorator: function/class, add_struct_tags: struct)"),
|
|
29029
|
+
derives: z11.array(z11.string()).optional().describe("Derive macro names (add_derive \u2014 e.g. ['Clone', 'Debug'])"),
|
|
29030
|
+
catchBody: z11.string().optional().describe("Catch block body (wrap_try_catch \u2014 default: 'throw error;')"),
|
|
29031
|
+
decorator: z11.string().optional().describe("Decorator text without @ (add_decorator \u2014 e.g. 'staticmethod')"),
|
|
29032
|
+
field: z11.string().optional().describe("Struct field name (add_struct_tags)"),
|
|
29033
|
+
tag: z11.string().optional().describe("Tag key (add_struct_tags \u2014 e.g. 'json')"),
|
|
29034
|
+
value: z11.string().optional().describe("Tag value (add_struct_tags \u2014 e.g. 'user_name,omitempty')"),
|
|
29035
|
+
validate: z11.enum(["syntax", "full"]).optional().describe("Validation level: 'syntax' (default) or 'full'. Syntax = tree-sitter parse check only. Full = also runs LSP type-checking (slower, catches more errors)"),
|
|
29036
|
+
dryRun: z11.boolean().optional().describe("Preview without modifying the file (default: false)")
|
|
28311
29037
|
},
|
|
28312
29038
|
execute: async (args, context) => {
|
|
28313
29039
|
const op = args.op;
|
|
@@ -28428,8 +29154,16 @@ var PLUGIN_VERSION = (() => {
|
|
|
28428
29154
|
return "0.0.0";
|
|
28429
29155
|
}
|
|
28430
29156
|
})();
|
|
28431
|
-
var ANNOUNCEMENT_VERSION = "";
|
|
28432
|
-
var ANNOUNCEMENT_FEATURES = [
|
|
29157
|
+
var ANNOUNCEMENT_VERSION = "0.18.0";
|
|
29158
|
+
var ANNOUNCEMENT_FEATURES = [
|
|
29159
|
+
`New experimental features \u2014 AFT now optionally hoists bash:
|
|
29160
|
+
- Run bash scripts in the background.
|
|
29161
|
+
- Initial output compression for git, cargo, npm, bun, pnpm, pytest, tsc (more in 0.19).
|
|
29162
|
+
- Rewrite cat/grep/find/sed/ls into AFT counterparts for faster, formatted output.
|
|
29163
|
+
Check GitHub for how to enable.`,
|
|
29164
|
+
"Trigram grep/glob and semantic search (aft_search) graduated out of experimental.",
|
|
29165
|
+
"Lots of bugfixes and new end-to-end test coverage."
|
|
29166
|
+
];
|
|
28433
29167
|
var plugin = async (input) => {
|
|
28434
29168
|
const binaryPath = await findBinary();
|
|
28435
29169
|
const aftConfig = loadAftConfig(input.directory);
|
|
@@ -28443,11 +29177,13 @@ var plugin = async (input) => {
|
|
|
28443
29177
|
configOverrides.formatter = aftConfig.formatter;
|
|
28444
29178
|
if (aftConfig.checker !== undefined)
|
|
28445
29179
|
configOverrides.checker = aftConfig.checker;
|
|
28446
|
-
configOverrides.restrict_to_project_root = aftConfig.restrict_to_project_root ??
|
|
28447
|
-
|
|
28448
|
-
|
|
28449
|
-
|
|
28450
|
-
|
|
29180
|
+
configOverrides.restrict_to_project_root = aftConfig.restrict_to_project_root ?? false;
|
|
29181
|
+
configOverrides.bash_permissions = true;
|
|
29182
|
+
if (aftConfig.search_index !== undefined)
|
|
29183
|
+
configOverrides.search_index = aftConfig.search_index;
|
|
29184
|
+
if (aftConfig.semantic_search !== undefined)
|
|
29185
|
+
configOverrides.semantic_search = aftConfig.semantic_search;
|
|
29186
|
+
Object.assign(configOverrides, resolveExperimentalConfigForConfigure(aftConfig));
|
|
28451
29187
|
Object.assign(configOverrides, resolveLspConfigForConfigure(aftConfig));
|
|
28452
29188
|
if (aftConfig.semantic !== undefined)
|
|
28453
29189
|
configOverrides.semantic = aftConfig.semantic;
|
|
@@ -28456,7 +29192,7 @@ var plugin = async (input) => {
|
|
|
28456
29192
|
const isFastembedSemanticBackend = (aftConfig.semantic?.backend ?? "fastembed") === "fastembed";
|
|
28457
29193
|
const dataHome = process.env.XDG_DATA_HOME || join19(homedir10(), ".local", "share");
|
|
28458
29194
|
configOverrides.storage_dir = join19(dataHome, "opencode", "storage", "plugin", "aft");
|
|
28459
|
-
if (aftConfig.
|
|
29195
|
+
if (aftConfig.semantic_search && isFastembedSemanticBackend) {
|
|
28460
29196
|
const storageDir2 = configOverrides.storage_dir;
|
|
28461
29197
|
const ortDylibDir = await ensureOnnxRuntime(storageDir2).catch((err) => {
|
|
28462
29198
|
warn(`ONNX Runtime setup failed: ${err instanceof Error ? err.message : String(err)}. Semantic search will be unavailable.`);
|
|
@@ -28473,6 +29209,9 @@ var plugin = async (input) => {
|
|
|
28473
29209
|
const lspGraceDays = aftConfig.lsp?.grace_days ?? 7;
|
|
28474
29210
|
const lspVersions = aftConfig.lsp?.versions ?? {};
|
|
28475
29211
|
const lspDisabled = new Set(aftConfig.lsp?.disabled ?? []);
|
|
29212
|
+
configOverrides.lsp_auto_install_binaries = [
|
|
29213
|
+
...new Set([...NPM_LSP_TABLE, ...GITHUB_LSP_TABLE].map((spec) => spec.binary))
|
|
29214
|
+
];
|
|
28476
29215
|
const npmResult = runAutoInstall(input.directory, {
|
|
28477
29216
|
autoInstall: lspAutoInstall,
|
|
28478
29217
|
graceDays: lspGraceDays,
|
|
@@ -28490,6 +29229,12 @@ var plugin = async (input) => {
|
|
|
28490
29229
|
if (mergedBinDirs.length > 0) {
|
|
28491
29230
|
configOverrides.lsp_paths_extra = mergedBinDirs;
|
|
28492
29231
|
}
|
|
29232
|
+
const lspInflightInstalls = [
|
|
29233
|
+
...new Set([...npmResult.installingBinaries, ...ghResult.installingBinaries])
|
|
29234
|
+
];
|
|
29235
|
+
if (lspInflightInstalls.length > 0) {
|
|
29236
|
+
configOverrides.lsp_inflight_installs = lspInflightInstalls;
|
|
29237
|
+
}
|
|
28493
29238
|
if (npmResult.installsStarted > 0 || ghResult.installsStarted > 0) {
|
|
28494
29239
|
log(`[lsp] auto-install: ${npmResult.installsStarted} npm + ${ghResult.installsStarted} github install(s) running in background`);
|
|
28495
29240
|
}
|
|
@@ -28540,12 +29285,12 @@ ${lines}
|
|
|
28540
29285
|
log(`Found/downloaded compatible binary at ${path5}. Replacing running bridges...`);
|
|
28541
29286
|
pool.replaceBinary(path5).then(() => {
|
|
28542
29287
|
log("Binary replaced successfully. New bridges will use the updated binary.");
|
|
28543
|
-
}, (err) =>
|
|
29288
|
+
}, (err) => error("Failed to replace binary:", err));
|
|
28544
29289
|
} else {
|
|
28545
29290
|
warn(`Could not find or download v${minVersion}. Continuing with v${binaryVersion}.`);
|
|
28546
29291
|
}
|
|
28547
29292
|
}, (err) => {
|
|
28548
|
-
|
|
29293
|
+
error(`Auto-download failed: ${err.message}. Install manually: cargo install agent-file-tools@${minVersion}`);
|
|
28549
29294
|
});
|
|
28550
29295
|
},
|
|
28551
29296
|
onConfigureWarnings: async ({ projectRoot, sessionId, client, warnings }) => {
|
|
@@ -28566,6 +29311,7 @@ ${lines}
|
|
|
28566
29311
|
const ctx = {
|
|
28567
29312
|
pool,
|
|
28568
29313
|
client: input.client,
|
|
29314
|
+
plugin: input.plugin,
|
|
28569
29315
|
config: aftConfig,
|
|
28570
29316
|
storageDir: configOverrides.storage_dir
|
|
28571
29317
|
};
|
|
@@ -28604,14 +29350,14 @@ ${lines}
|
|
|
28604
29350
|
if (storageDir && ANNOUNCEMENT_VERSION) {
|
|
28605
29351
|
try {
|
|
28606
29352
|
mkdirSync10(storageDir, { recursive: true });
|
|
28607
|
-
|
|
29353
|
+
writeFileSync10(join19(storageDir, "last_announced_version"), ANNOUNCEMENT_VERSION);
|
|
28608
29354
|
} catch {}
|
|
28609
29355
|
}
|
|
28610
29356
|
return { success: true };
|
|
28611
29357
|
});
|
|
28612
29358
|
rpcServer.handle("get-warnings", async () => {
|
|
28613
29359
|
const warnings = [];
|
|
28614
|
-
if (aftConfig.
|
|
29360
|
+
if (aftConfig.semantic_search && isFastembedSemanticBackend && !configOverrides._ort_dylib_dir) {
|
|
28615
29361
|
if (!isOrtAutoDownloadSupported()) {
|
|
28616
29362
|
warnings.push(`Semantic search requires ONNX Runtime.
|
|
28617
29363
|
Install: ${getManualInstallHint()}`);
|
|
@@ -28635,7 +29381,7 @@ Install: ${getManualInstallHint()}`);
|
|
|
28635
29381
|
sendFeatureAnnouncement(notifyOpts, ANNOUNCEMENT_VERSION, ANNOUNCEMENT_FEATURES, storageDir).catch(() => {});
|
|
28636
29382
|
}, 8000);
|
|
28637
29383
|
}
|
|
28638
|
-
if (aftConfig.
|
|
29384
|
+
if (aftConfig.semantic_search && isFastembedSemanticBackend && !configOverrides._ort_dylib_dir) {
|
|
28639
29385
|
setTimeout(() => {
|
|
28640
29386
|
if (!configOverrides._ort_dylib_dir && !isOrtAutoDownloadSupported()) {
|
|
28641
29387
|
sendWarning(notifyOpts, `Semantic search requires ONNX Runtime.
|
|
@@ -28661,8 +29407,8 @@ Install: ${getManualInstallHint()}`).catch(() => {});
|
|
|
28661
29407
|
...structureTools(ctx),
|
|
28662
29408
|
...navigationTools(ctx),
|
|
28663
29409
|
...surface !== "minimal" && astTools(ctx),
|
|
28664
|
-
...surface !== "minimal" && aftConfig.
|
|
28665
|
-
...surface !== "minimal" && aftConfig.
|
|
29410
|
+
...surface !== "minimal" && aftConfig.semantic_search === true && semanticTools(ctx),
|
|
29411
|
+
...surface !== "minimal" && aftConfig.search_index === true && searchTools(ctx),
|
|
28666
29412
|
...refactoringTools(ctx),
|
|
28667
29413
|
...surface !== "minimal" && lspTools(ctx),
|
|
28668
29414
|
...surface !== "minimal" && conflictTools(ctx)
|
|
@@ -28685,13 +29431,30 @@ Install: ${getManualInstallHint()}`).catch(() => {});
|
|
|
28685
29431
|
}
|
|
28686
29432
|
log(`Disabled ${disabled.size} tool(s): ${[...disabled].join(", ")}`);
|
|
28687
29433
|
}
|
|
29434
|
+
const autoUpdateEventHook = createAutoUpdateCheckerHook(input, {
|
|
29435
|
+
enabled: true,
|
|
29436
|
+
autoUpdate: aftConfig.auto_update ?? true,
|
|
29437
|
+
signal: autoUpdateAbort.signal
|
|
29438
|
+
});
|
|
28688
29439
|
return {
|
|
28689
29440
|
tool: allTools,
|
|
28690
|
-
event:
|
|
28691
|
-
|
|
28692
|
-
|
|
28693
|
-
|
|
28694
|
-
|
|
29441
|
+
event: async (eventInput) => {
|
|
29442
|
+
await autoUpdateEventHook(eventInput);
|
|
29443
|
+
if (eventInput.event.type !== "session.idle")
|
|
29444
|
+
return;
|
|
29445
|
+
const sessionID = extractSessionID(eventInput.event.properties);
|
|
29446
|
+
if (!sessionID)
|
|
29447
|
+
return;
|
|
29448
|
+
await handleIdleBgCompletions({
|
|
29449
|
+
ctx,
|
|
29450
|
+
directory: input.directory,
|
|
29451
|
+
sessionID,
|
|
29452
|
+
client: input.client
|
|
29453
|
+
});
|
|
29454
|
+
},
|
|
29455
|
+
"chat.message": async (messageInput) => {
|
|
29456
|
+
resetBgWake(messageInput.sessionID ?? messageInput.sessionId ?? messageInput.id);
|
|
29457
|
+
},
|
|
28695
29458
|
"command.execute.before": async (commandInput, _output) => {
|
|
28696
29459
|
if (isTuiMode2() || commandInput.command !== STATUS_COMMAND) {
|
|
28697
29460
|
return;
|
|
@@ -28705,22 +29468,22 @@ Install: ${getManualInstallHint()}`).catch(() => {});
|
|
|
28705
29468
|
await sendIgnoredMessage2(input.client, commandInput.sessionID, formatStatusMarkdown(status));
|
|
28706
29469
|
throwSentinel(commandInput.command);
|
|
28707
29470
|
},
|
|
28708
|
-
"tool.execute.after": async (
|
|
29471
|
+
"tool.execute.after": async (toolInput, output) => {
|
|
28709
29472
|
if (!output)
|
|
28710
29473
|
return;
|
|
28711
|
-
const stored = consumeToolMetadata(
|
|
29474
|
+
const stored = consumeToolMetadata(toolInput.sessionID, toolInput.callID);
|
|
28712
29475
|
if (stored) {
|
|
28713
29476
|
if (stored.title)
|
|
28714
29477
|
output.title = stored.title;
|
|
28715
29478
|
if (stored.metadata)
|
|
28716
29479
|
output.metadata = { ...output.metadata, ...stored.metadata };
|
|
28717
29480
|
}
|
|
28718
|
-
if (
|
|
29481
|
+
if (toolInput.tool === "bash" && output.output?.includes("Automatic merge failed; fix conflicts")) {
|
|
28719
29482
|
output.output += `
|
|
28720
29483
|
|
|
28721
29484
|
[Hint] Use aft_conflicts to see all conflict regions across files in a single call.`;
|
|
28722
29485
|
}
|
|
28723
|
-
if (
|
|
29486
|
+
if (toolInput.tool === "bash" && output.output) {
|
|
28724
29487
|
const firstLine = output.output.slice(0, 300).split(`
|
|
28725
29488
|
`)[0] ?? "";
|
|
28726
29489
|
if (/\b(rg|grep)\s/.test(firstLine)) {
|
|
@@ -28729,6 +29492,7 @@ Install: ${getManualInstallHint()}`).catch(() => {});
|
|
|
28729
29492
|
[Hint] Use the grep tool instead of bash for faster indexed search.`;
|
|
28730
29493
|
}
|
|
28731
29494
|
}
|
|
29495
|
+
await appendInTurnBgCompletions({ ctx, directory: input.directory, sessionID: toolInput.sessionID }, output);
|
|
28732
29496
|
},
|
|
28733
29497
|
config: async (config2) => {
|
|
28734
29498
|
config2.command = {
|