@cortexkit/aft-opencode 0.17.3 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bg-notifications.d.ts +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 +1240 -493
- package/dist/logger.d.ts +9 -0
- package/dist/logger.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) {
|
|
@@ -23111,7 +23486,7 @@ function runAutoInstall(projectRoot, config2, fetchImpl = fetch) {
|
|
|
23111
23486
|
installsStarted -= 1;
|
|
23112
23487
|
const reason = err instanceof Error ? err.message : String(err);
|
|
23113
23488
|
skipped.push({ id: spec.id, reason: `install error: ${reason}` });
|
|
23114
|
-
|
|
23489
|
+
error(`[lsp] background install ${spec.npm} promise rejected: ${reason}`);
|
|
23115
23490
|
});
|
|
23116
23491
|
installPromises.push(trackInFlightAutoInstall(controller, promise2));
|
|
23117
23492
|
}
|
|
@@ -23138,10 +23513,10 @@ import {
|
|
|
23138
23513
|
readdirSync as readdirSync2,
|
|
23139
23514
|
readlinkSync,
|
|
23140
23515
|
realpathSync,
|
|
23141
|
-
renameSync,
|
|
23516
|
+
renameSync as renameSync2,
|
|
23142
23517
|
rmSync as rmSync2,
|
|
23143
23518
|
statSync as statSync4,
|
|
23144
|
-
unlinkSync as
|
|
23519
|
+
unlinkSync as unlinkSync4
|
|
23145
23520
|
} from "fs";
|
|
23146
23521
|
import { dirname as dirname3, join as join9, relative, resolve as resolve2 } from "path";
|
|
23147
23522
|
import { Readable } from "stream";
|
|
@@ -23456,7 +23831,7 @@ async function downloadFile(url2, destPath, fetchImpl, assetSize, signal) {
|
|
|
23456
23831
|
await pipeline(nodeStream, createWriteStream(destPath), { signal: timeout.signal });
|
|
23457
23832
|
} catch (err) {
|
|
23458
23833
|
try {
|
|
23459
|
-
|
|
23834
|
+
unlinkSync4(destPath);
|
|
23460
23835
|
} catch {}
|
|
23461
23836
|
throw err;
|
|
23462
23837
|
} finally {
|
|
@@ -23525,7 +23900,7 @@ function extractArchiveSafely(archivePath, destDir, archiveType) {
|
|
|
23525
23900
|
try {
|
|
23526
23901
|
rmSync2(destDir, { recursive: true, force: true });
|
|
23527
23902
|
} catch {}
|
|
23528
|
-
|
|
23903
|
+
renameSync2(stagingDir, destDir);
|
|
23529
23904
|
} catch (err) {
|
|
23530
23905
|
try {
|
|
23531
23906
|
rmSync2(stagingDir, { recursive: true, force: true });
|
|
@@ -23583,16 +23958,16 @@ async function downloadAndInstall(spec, tag, assets, platform2, arch, fetchImpl,
|
|
|
23583
23958
|
try {
|
|
23584
23959
|
await downloadFile(matchingAsset.url, archivePath, fetchImpl, matchingAsset.size, signal);
|
|
23585
23960
|
} catch (err) {
|
|
23586
|
-
|
|
23961
|
+
error(`[lsp] download ${spec.id} failed: ${err}`);
|
|
23587
23962
|
return null;
|
|
23588
23963
|
}
|
|
23589
23964
|
let archiveSha256;
|
|
23590
23965
|
try {
|
|
23591
23966
|
archiveSha256 = await sha256OfFile(archivePath);
|
|
23592
23967
|
} catch (err) {
|
|
23593
|
-
|
|
23968
|
+
error(`[lsp] hash ${spec.id} failed: ${err}`);
|
|
23594
23969
|
try {
|
|
23595
|
-
|
|
23970
|
+
unlinkSync4(archivePath);
|
|
23596
23971
|
} catch {}
|
|
23597
23972
|
return null;
|
|
23598
23973
|
}
|
|
@@ -23600,9 +23975,9 @@ async function downloadAndInstall(spec, tag, assets, platform2, arch, fetchImpl,
|
|
|
23600
23975
|
const previousMeta = readInstalledMetaIn(ghPackageDir(spec));
|
|
23601
23976
|
if (previousMeta && previousMeta.version === tag && previousMeta.sha256) {
|
|
23602
23977
|
if (previousMeta.sha256 !== archiveSha256) {
|
|
23603
|
-
|
|
23978
|
+
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
23979
|
try {
|
|
23605
|
-
|
|
23980
|
+
unlinkSync4(archivePath);
|
|
23606
23981
|
} catch {}
|
|
23607
23982
|
return null;
|
|
23608
23983
|
}
|
|
@@ -23610,16 +23985,16 @@ async function downloadAndInstall(spec, tag, assets, platform2, arch, fetchImpl,
|
|
|
23610
23985
|
try {
|
|
23611
23986
|
extractArchiveSafely(archivePath, extractDir, expected.archive);
|
|
23612
23987
|
} catch (err) {
|
|
23613
|
-
|
|
23988
|
+
error(`[lsp] extract ${spec.id} failed: ${err}`);
|
|
23614
23989
|
return null;
|
|
23615
23990
|
} finally {
|
|
23616
23991
|
try {
|
|
23617
|
-
|
|
23992
|
+
unlinkSync4(archivePath);
|
|
23618
23993
|
} catch {}
|
|
23619
23994
|
}
|
|
23620
23995
|
const innerBinaryPath = join9(extractDir, spec.binaryPathInArchive(platform2, arch, version2));
|
|
23621
23996
|
if (!existsSync6(innerBinaryPath)) {
|
|
23622
|
-
|
|
23997
|
+
error(`[lsp] ${spec.id}: extracted binary not found at ${innerBinaryPath}`);
|
|
23623
23998
|
return null;
|
|
23624
23999
|
}
|
|
23625
24000
|
const targetBinary = ghBinaryPath(spec, platform2);
|
|
@@ -23631,7 +24006,7 @@ async function downloadAndInstall(spec, tag, assets, platform2, arch, fetchImpl,
|
|
|
23631
24006
|
chmodSync2(targetBinary, 493);
|
|
23632
24007
|
}
|
|
23633
24008
|
} catch (err) {
|
|
23634
|
-
|
|
24009
|
+
error(`[lsp] ${spec.id}: failed to place binary at ${targetBinary}: ${err}`);
|
|
23635
24010
|
return null;
|
|
23636
24011
|
}
|
|
23637
24012
|
log(`[lsp] installed ${spec.id} ${tag} at ${targetBinary}`);
|
|
@@ -23662,7 +24037,7 @@ async function ensureGithubInstalled(spec, config2, fetchImpl, platform2, arch,
|
|
|
23662
24037
|
}
|
|
23663
24038
|
}
|
|
23664
24039
|
const archiveSha256 = await downloadAndInstall(spec, tag, assets, platform2, arch, fetchImpl, signal).catch((err) => {
|
|
23665
|
-
|
|
24040
|
+
error(`[lsp] github install ${spec.id} crashed: ${err}`);
|
|
23666
24041
|
return null;
|
|
23667
24042
|
});
|
|
23668
24043
|
if (!archiveSha256) {
|
|
@@ -23739,7 +24114,7 @@ function runGithubAutoInstall(relevantServers, config2, fetchImpl = fetch) {
|
|
|
23739
24114
|
installsStarted -= 1;
|
|
23740
24115
|
const reason = err instanceof Error ? err.message : String(err);
|
|
23741
24116
|
skipped.push({ id: spec.id, reason: `install error: ${reason}` });
|
|
23742
|
-
|
|
24117
|
+
error(`[lsp] github install ${spec.id} promise rejected: ${reason}`);
|
|
23743
24118
|
});
|
|
23744
24119
|
installPromises.push(trackInFlightGithubInstall(controller, promise2));
|
|
23745
24120
|
}
|
|
@@ -23859,7 +24234,7 @@ function normalizeToolMap(tools) {
|
|
|
23859
24234
|
}
|
|
23860
24235
|
|
|
23861
24236
|
// src/notifications.ts
|
|
23862
|
-
import { existsSync as existsSync7, mkdirSync as mkdirSync4, readFileSync as readFileSync5, writeFileSync as
|
|
24237
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync4, readFileSync as readFileSync5, writeFileSync as writeFileSync5 } from "fs";
|
|
23863
24238
|
import { homedir as homedir6, platform as platform2 } from "os";
|
|
23864
24239
|
import { join as join10 } from "path";
|
|
23865
24240
|
function isTuiMode() {
|
|
@@ -24021,7 +24396,7 @@ async function sendFeatureAnnouncement(opts, version2, features, storageDir) {
|
|
|
24021
24396
|
if (storageDir) {
|
|
24022
24397
|
try {
|
|
24023
24398
|
mkdirSync4(storageDir, { recursive: true });
|
|
24024
|
-
|
|
24399
|
+
writeFileSync5(join10(storageDir, "last_announced_version"), version2);
|
|
24025
24400
|
} catch {}
|
|
24026
24401
|
}
|
|
24027
24402
|
}
|
|
@@ -24048,7 +24423,7 @@ function writeWarnedTools(storageDir, warned) {
|
|
|
24048
24423
|
try {
|
|
24049
24424
|
mkdirSync4(storageDir, { recursive: true });
|
|
24050
24425
|
const warnedToolsPath = join10(storageDir, WARNED_TOOLS_FILE);
|
|
24051
|
-
|
|
24426
|
+
writeFileSync5(warnedToolsPath, `${JSON.stringify(warned, null, 2)}
|
|
24052
24427
|
`);
|
|
24053
24428
|
} catch {}
|
|
24054
24429
|
}
|
|
@@ -24157,8 +24532,8 @@ import {
|
|
|
24157
24532
|
rmSync as rmSync3,
|
|
24158
24533
|
statSync as statSync5,
|
|
24159
24534
|
symlinkSync,
|
|
24160
|
-
unlinkSync as
|
|
24161
|
-
writeFileSync as
|
|
24535
|
+
unlinkSync as unlinkSync5,
|
|
24536
|
+
writeFileSync as writeFileSync6
|
|
24162
24537
|
} from "fs";
|
|
24163
24538
|
import { dirname as dirname4, join as join11, relative as relative2, resolve as resolve3 } from "path";
|
|
24164
24539
|
import { Readable as Readable2 } from "stream";
|
|
@@ -24231,7 +24606,7 @@ async function ensureOnnxRuntime(storageDir) {
|
|
|
24231
24606
|
try {
|
|
24232
24607
|
const currentHash = sha256File(libPath);
|
|
24233
24608
|
if (currentHash !== meta3.sha256) {
|
|
24234
|
-
|
|
24609
|
+
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
24610
|
} else {
|
|
24236
24611
|
log(`ONNX Runtime found at ${ortDir} (TOFU verified)`);
|
|
24237
24612
|
return ortDir;
|
|
@@ -24316,7 +24691,7 @@ async function downloadFileWithCap(url2, destPath) {
|
|
|
24316
24691
|
await pipeline2(nodeStream, createWriteStream2(destPath), { signal: controller.signal });
|
|
24317
24692
|
} catch (err) {
|
|
24318
24693
|
try {
|
|
24319
|
-
|
|
24694
|
+
unlinkSync5(destPath);
|
|
24320
24695
|
} catch {}
|
|
24321
24696
|
throw err;
|
|
24322
24697
|
} finally {
|
|
@@ -24377,7 +24752,7 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
24377
24752
|
await extractZipArchive(archivePath, tmpDir);
|
|
24378
24753
|
}
|
|
24379
24754
|
try {
|
|
24380
|
-
|
|
24755
|
+
unlinkSync5(archivePath);
|
|
24381
24756
|
} catch {}
|
|
24382
24757
|
validateExtractedTree(tmpDir);
|
|
24383
24758
|
const extractedDir = join11(tmpDir, info.assetName, "lib");
|
|
@@ -24418,7 +24793,7 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
24418
24793
|
for (const link of symlinks) {
|
|
24419
24794
|
const dst = join11(targetDir, link.name);
|
|
24420
24795
|
try {
|
|
24421
|
-
|
|
24796
|
+
unlinkSync5(dst);
|
|
24422
24797
|
} catch {}
|
|
24423
24798
|
symlinkSync(link.target, dst);
|
|
24424
24799
|
}
|
|
@@ -24434,7 +24809,7 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
24434
24809
|
log(`ONNX Runtime v${ORT_VERSION} installed to ${targetDir}`);
|
|
24435
24810
|
return targetDir;
|
|
24436
24811
|
} catch (err) {
|
|
24437
|
-
|
|
24812
|
+
error(`Failed to download ONNX Runtime: ${err}`);
|
|
24438
24813
|
try {
|
|
24439
24814
|
rmSync3(tmpDir, { recursive: true, force: true });
|
|
24440
24815
|
} catch {}
|
|
@@ -24465,7 +24840,7 @@ function writeOnnxInstalledMeta(installDir, version2, sha256, archiveSha256) {
|
|
|
24465
24840
|
...sha256 ? { sha256 } : {},
|
|
24466
24841
|
archiveSha256
|
|
24467
24842
|
};
|
|
24468
|
-
|
|
24843
|
+
writeFileSync6(join11(installDir, ONNX_INSTALLED_META_FILE), JSON.stringify(meta3), "utf8");
|
|
24469
24844
|
} catch (err) {
|
|
24470
24845
|
log(`[onnx] failed to write installed-meta in ${installDir}: ${err}`);
|
|
24471
24846
|
}
|
|
@@ -24499,7 +24874,7 @@ function acquireLock(lockPath2) {
|
|
|
24499
24874
|
try {
|
|
24500
24875
|
const fd = openSync2(lockPath2, "wx");
|
|
24501
24876
|
try {
|
|
24502
|
-
|
|
24877
|
+
writeFileSync6(fd, `${process.pid}
|
|
24503
24878
|
${new Date().toISOString()}
|
|
24504
24879
|
`);
|
|
24505
24880
|
} finally {
|
|
@@ -24537,7 +24912,7 @@ ${new Date().toISOString()}
|
|
|
24537
24912
|
}
|
|
24538
24913
|
log(`[onnx] reclaiming install lock (owner_pid=${owningPid ?? "unknown"}, alive=${ownerAlive}, age_ms=${age})`);
|
|
24539
24914
|
try {
|
|
24540
|
-
|
|
24915
|
+
unlinkSync5(lockPath2);
|
|
24541
24916
|
} catch {}
|
|
24542
24917
|
return tryClaim();
|
|
24543
24918
|
}
|
|
@@ -24562,7 +24937,7 @@ function releaseLock(lockPath2) {
|
|
|
24562
24937
|
return;
|
|
24563
24938
|
}
|
|
24564
24939
|
try {
|
|
24565
|
-
|
|
24940
|
+
unlinkSync5(lockPath2);
|
|
24566
24941
|
} catch (unlinkErr) {
|
|
24567
24942
|
const code = unlinkErr.code;
|
|
24568
24943
|
if (code !== "ENOENT") {
|
|
@@ -24698,6 +25073,9 @@ class BinaryBridge {
|
|
|
24698
25073
|
if (this._shuttingDown) {
|
|
24699
25074
|
throw new Error(`[aft-plugin] Bridge is shutting down, cannot send "${command}"`);
|
|
24700
25075
|
}
|
|
25076
|
+
if (Object.hasOwn(params, "id")) {
|
|
25077
|
+
throw new Error("params cannot contain reserved key 'id'");
|
|
25078
|
+
}
|
|
24701
25079
|
this.ensureSpawned();
|
|
24702
25080
|
if (!this.configured) {
|
|
24703
25081
|
if (command !== "configure" && command !== "version") {
|
|
@@ -24726,18 +25104,37 @@ class BinaryBridge {
|
|
|
24726
25104
|
}
|
|
24727
25105
|
}
|
|
24728
25106
|
const id = String(this.nextId++);
|
|
24729
|
-
|
|
25107
|
+
let request;
|
|
25108
|
+
if (Object.hasOwn(params, "command") || Object.hasOwn(params, "method")) {
|
|
25109
|
+
const nested = { ...params };
|
|
25110
|
+
const reserved = {};
|
|
25111
|
+
for (const key of ["session_id", "lsp_hints"]) {
|
|
25112
|
+
if (Object.hasOwn(nested, key)) {
|
|
25113
|
+
reserved[key] = nested[key];
|
|
25114
|
+
delete nested[key];
|
|
25115
|
+
}
|
|
25116
|
+
}
|
|
25117
|
+
request = { id, command, ...reserved, params: nested };
|
|
25118
|
+
} else {
|
|
25119
|
+
request = { id, command, ...params };
|
|
25120
|
+
}
|
|
24730
25121
|
const line = `${JSON.stringify(request)}
|
|
24731
25122
|
`;
|
|
24732
|
-
const effectiveTimeoutMs = options?.timeoutMs ?? this.timeoutMs;
|
|
25123
|
+
const effectiveTimeoutMs = options?.transportTimeoutMs ?? options?.timeoutMs ?? this.timeoutMs;
|
|
25124
|
+
const requestSessionId = typeof params.session_id === "string" && params.session_id.length > 0 ? params.session_id : undefined;
|
|
24733
25125
|
return new Promise((resolve4, reject) => {
|
|
24734
25126
|
const timer = setTimeout(() => {
|
|
24735
25127
|
this.pending.delete(id);
|
|
24736
|
-
|
|
25128
|
+
const timeoutMsg = `Request "${command}" (id=${id}) timed out after ${effectiveTimeoutMs}ms \u2014 restarting bridge`;
|
|
25129
|
+
if (requestSessionId) {
|
|
25130
|
+
sessionWarn(requestSessionId, timeoutMsg);
|
|
25131
|
+
} else {
|
|
25132
|
+
warn(timeoutMsg);
|
|
25133
|
+
}
|
|
24737
25134
|
reject(new Error(`[aft-plugin] Request "${command}" (id=${id}) timed out after ${effectiveTimeoutMs}ms`));
|
|
24738
25135
|
this.handleTimeout();
|
|
24739
25136
|
}, effectiveTimeoutMs);
|
|
24740
|
-
this.pending.set(id, { resolve: resolve4, reject, timer });
|
|
25137
|
+
this.pending.set(id, { resolve: resolve4, reject, timer, onProgress: options?.onProgress });
|
|
24741
25138
|
if (!this.process?.stdin?.writable) {
|
|
24742
25139
|
this.pending.delete(id);
|
|
24743
25140
|
clearTimeout(timer);
|
|
@@ -24865,7 +25262,7 @@ class BinaryBridge {
|
|
|
24865
25262
|
child.on("error", (err) => {
|
|
24866
25263
|
if (this.process !== currentChild)
|
|
24867
25264
|
return;
|
|
24868
|
-
|
|
25265
|
+
error(`Process error: ${err.message}${this.formatStderrTail()}`);
|
|
24869
25266
|
this.handleCrash();
|
|
24870
25267
|
});
|
|
24871
25268
|
child.on("exit", (code, signal) => {
|
|
@@ -24917,6 +25314,29 @@ class BinaryBridge {
|
|
|
24917
25314
|
continue;
|
|
24918
25315
|
try {
|
|
24919
25316
|
const response = JSON.parse(line);
|
|
25317
|
+
if (response.type === "progress") {
|
|
25318
|
+
const requestId = response.request_id;
|
|
25319
|
+
const entry = requestId ? this.pending.get(requestId) : undefined;
|
|
25320
|
+
const kind = response.kind === "stderr" ? "stderr" : "stdout";
|
|
25321
|
+
const text = typeof response.chunk === "string" ? response.chunk : "";
|
|
25322
|
+
entry?.onProgress?.({ kind, text });
|
|
25323
|
+
continue;
|
|
25324
|
+
}
|
|
25325
|
+
if (response.type === "permission_ask") {
|
|
25326
|
+
const requestId = response.request_id;
|
|
25327
|
+
const entry = requestId ? this.pending.get(requestId) : undefined;
|
|
25328
|
+
if (requestId && entry) {
|
|
25329
|
+
this.pending.delete(requestId);
|
|
25330
|
+
clearTimeout(entry.timer);
|
|
25331
|
+
entry.resolve({
|
|
25332
|
+
success: false,
|
|
25333
|
+
code: "permission_required",
|
|
25334
|
+
message: "bash command requires permission",
|
|
25335
|
+
asks: response.asks
|
|
25336
|
+
});
|
|
25337
|
+
}
|
|
25338
|
+
continue;
|
|
25339
|
+
}
|
|
24920
25340
|
const id = response.id;
|
|
24921
25341
|
if (id && this.pending.has(id)) {
|
|
24922
25342
|
const entry = this.pending.get(id);
|
|
@@ -24941,7 +25361,11 @@ class BinaryBridge {
|
|
|
24941
25361
|
this.configured = false;
|
|
24942
25362
|
const tail = this.formatStderrTail();
|
|
24943
25363
|
this.stderrTail = [];
|
|
24944
|
-
|
|
25364
|
+
if (tail) {
|
|
25365
|
+
error(`Bridge killed after timeout.${tail}`);
|
|
25366
|
+
} else {
|
|
25367
|
+
warn(`Bridge killed after timeout (see ${getLogFilePath()})`);
|
|
25368
|
+
}
|
|
24945
25369
|
}
|
|
24946
25370
|
handleCrash(cause) {
|
|
24947
25371
|
const proc = this.process;
|
|
@@ -24952,7 +25376,10 @@ class BinaryBridge {
|
|
|
24952
25376
|
this.clearRestartResetTimer();
|
|
24953
25377
|
this.configured = false;
|
|
24954
25378
|
const tail = this.formatStderrTail();
|
|
24955
|
-
|
|
25379
|
+
if (tail) {
|
|
25380
|
+
error(`Binary crashed (restarts: ${this._restartCount})${cause ? `: ${cause.message}` : ""}.${tail}`);
|
|
25381
|
+
}
|
|
25382
|
+
this.rejectAllPending(new Error(`[aft-plugin] Binary crashed (restarts: ${this._restartCount})${cause ? `: ${cause.message}` : ""} (see ${getLogFilePath()})`));
|
|
24956
25383
|
if (this._restartCount < this.maxRestarts) {
|
|
24957
25384
|
const delay = 100 * 2 ** this._restartCount;
|
|
24958
25385
|
this._restartCount++;
|
|
@@ -24962,13 +25389,13 @@ class BinaryBridge {
|
|
|
24962
25389
|
try {
|
|
24963
25390
|
this.spawnProcess();
|
|
24964
25391
|
} catch (err) {
|
|
24965
|
-
|
|
25392
|
+
error(`Failed to restart: ${err.message}`);
|
|
24966
25393
|
}
|
|
24967
25394
|
}
|
|
24968
25395
|
}, delay);
|
|
24969
25396
|
this.scheduleRestartCountReset();
|
|
24970
25397
|
} else {
|
|
24971
|
-
|
|
25398
|
+
error(`Max restarts (${this.maxRestarts}) reached, giving up. Logs: ${getLogFilePath()}${tail}`);
|
|
24972
25399
|
this.scheduleRestartCountReset();
|
|
24973
25400
|
}
|
|
24974
25401
|
}
|
|
@@ -25057,7 +25484,7 @@ class BridgePool {
|
|
|
25057
25484
|
const now = Date.now();
|
|
25058
25485
|
for (const [dir, entry] of this.bridges) {
|
|
25059
25486
|
if (now - entry.lastUsed > this.idleTimeoutMs) {
|
|
25060
|
-
entry.bridge.shutdown().catch((err) =>
|
|
25487
|
+
entry.bridge.shutdown().catch((err) => error("cleanup shutdown failed:", err));
|
|
25061
25488
|
this.bridges.delete(dir);
|
|
25062
25489
|
}
|
|
25063
25490
|
}
|
|
@@ -25073,7 +25500,7 @@ class BridgePool {
|
|
|
25073
25500
|
}
|
|
25074
25501
|
if (oldestDir) {
|
|
25075
25502
|
const entry = this.bridges.get(oldestDir);
|
|
25076
|
-
entry?.bridge.shutdown().catch((err) =>
|
|
25503
|
+
entry?.bridge.shutdown().catch((err) => error("eviction shutdown failed:", err));
|
|
25077
25504
|
this.bridges.delete(oldestDir);
|
|
25078
25505
|
}
|
|
25079
25506
|
}
|
|
@@ -25103,7 +25530,7 @@ function normalizeKey(projectRoot) {
|
|
|
25103
25530
|
|
|
25104
25531
|
// src/resolver.ts
|
|
25105
25532
|
import { execSync, spawnSync } from "child_process";
|
|
25106
|
-
import { chmodSync as chmodSync3, copyFileSync as copyFileSync3, existsSync as existsSync9, mkdirSync as mkdirSync6, renameSync as
|
|
25533
|
+
import { chmodSync as chmodSync3, copyFileSync as copyFileSync3, existsSync as existsSync9, mkdirSync as mkdirSync6, renameSync as renameSync3 } from "fs";
|
|
25107
25534
|
import { createRequire } from "module";
|
|
25108
25535
|
import { homedir as homedir8 } from "os";
|
|
25109
25536
|
import { join as join13 } from "path";
|
|
@@ -25131,7 +25558,7 @@ function copyToVersionedCache(npmBinaryPath) {
|
|
|
25131
25558
|
if (process.platform !== "win32") {
|
|
25132
25559
|
chmodSync3(tmpPath, 493);
|
|
25133
25560
|
}
|
|
25134
|
-
|
|
25561
|
+
renameSync3(tmpPath, cachedPath);
|
|
25135
25562
|
log(`Copied npm binary to versioned cache: ${cachedPath}`);
|
|
25136
25563
|
return cachedPath;
|
|
25137
25564
|
} catch (err) {
|
|
@@ -25221,7 +25648,7 @@ async function findBinary() {
|
|
|
25221
25648
|
|
|
25222
25649
|
// src/shared/rpc-server.ts
|
|
25223
25650
|
import { randomBytes as randomBytes2 } from "crypto";
|
|
25224
|
-
import { mkdirSync as mkdirSync7, renameSync as
|
|
25651
|
+
import { mkdirSync as mkdirSync7, renameSync as renameSync4, unlinkSync as unlinkSync6, writeFileSync as writeFileSync7 } from "fs";
|
|
25225
25652
|
import { createServer } from "http";
|
|
25226
25653
|
import { dirname as dirname5 } from "path";
|
|
25227
25654
|
|
|
@@ -25270,8 +25697,8 @@ class AftRpcServer {
|
|
|
25270
25697
|
const dir = dirname5(this.portFilePath);
|
|
25271
25698
|
mkdirSync7(dir, { recursive: true });
|
|
25272
25699
|
const tmpPath = `${this.portFilePath}.tmp`;
|
|
25273
|
-
|
|
25274
|
-
|
|
25700
|
+
writeFileSync7(tmpPath, JSON.stringify({ port: this.port, token: this.token }), "utf-8");
|
|
25701
|
+
renameSync4(tmpPath, this.portFilePath);
|
|
25275
25702
|
log(`RPC server listening on 127.0.0.1:${this.port}`);
|
|
25276
25703
|
} catch (err) {
|
|
25277
25704
|
warn(`Failed to write RPC port file: ${err}`);
|
|
@@ -25288,7 +25715,7 @@ class AftRpcServer {
|
|
|
25288
25715
|
}
|
|
25289
25716
|
this.token = null;
|
|
25290
25717
|
try {
|
|
25291
|
-
|
|
25718
|
+
unlinkSync6(this.portFilePath);
|
|
25292
25719
|
} catch {}
|
|
25293
25720
|
}
|
|
25294
25721
|
dispatch(req, res) {
|
|
@@ -25418,8 +25845,8 @@ function coerceAftStatus(response) {
|
|
|
25418
25845
|
format_on_edit: readBoolean(features.format_on_edit),
|
|
25419
25846
|
validate_on_edit: readString(features.validate_on_edit, "off"),
|
|
25420
25847
|
restrict_to_project_root: readBoolean(features.restrict_to_project_root),
|
|
25421
|
-
|
|
25422
|
-
|
|
25848
|
+
search_index: readBoolean(features.search_index ?? features.experimental_search_index),
|
|
25849
|
+
semantic_search: readBoolean(features.semantic_search ?? features.experimental_semantic_search)
|
|
25423
25850
|
},
|
|
25424
25851
|
search_index: {
|
|
25425
25852
|
status: readString(searchIndex.status, "unknown"),
|
|
@@ -25466,8 +25893,8 @@ function formatStatusMarkdown(status) {
|
|
|
25466
25893
|
"",
|
|
25467
25894
|
"### Enabled features",
|
|
25468
25895
|
`- \`format_on_edit\`: ${formatFlag(status.features.format_on_edit)}`,
|
|
25469
|
-
`- \`
|
|
25470
|
-
`- \`
|
|
25896
|
+
`- \`search_index\`: ${formatFlag(status.features.search_index)}`,
|
|
25897
|
+
`- \`semantic_search\`: ${formatFlag(status.features.semantic_search)}`,
|
|
25471
25898
|
"",
|
|
25472
25899
|
"### Search index",
|
|
25473
25900
|
`- **Status:** \`${status.search_index.status}\``,
|
|
@@ -25510,7 +25937,7 @@ function formatStatusMarkdown(status) {
|
|
|
25510
25937
|
|
|
25511
25938
|
// src/shared/tui-config.ts
|
|
25512
25939
|
var import_comment_json4 = __toESM(require_src2(), 1);
|
|
25513
|
-
import { existsSync as existsSync10, mkdirSync as mkdirSync8, readFileSync as readFileSync7, writeFileSync as
|
|
25940
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync8, readFileSync as readFileSync7, writeFileSync as writeFileSync8 } from "fs";
|
|
25514
25941
|
import { dirname as dirname6, join as join16 } from "path";
|
|
25515
25942
|
|
|
25516
25943
|
// src/shared/opencode-config-dir.ts
|
|
@@ -25567,7 +25994,7 @@ function ensureTuiPluginEntry() {
|
|
|
25567
25994
|
plugins.push(PLUGIN_ENTRY);
|
|
25568
25995
|
config2.plugin = plugins;
|
|
25569
25996
|
mkdirSync8(dirname6(configPath), { recursive: true });
|
|
25570
|
-
|
|
25997
|
+
writeFileSync8(configPath, `${import_comment_json4.stringify(config2, null, 2)}
|
|
25571
25998
|
`);
|
|
25572
25999
|
log(`[aft-plugin] added TUI plugin entry to ${configPath}`);
|
|
25573
26000
|
return true;
|
|
@@ -25585,8 +26012,8 @@ import {
|
|
|
25585
26012
|
mkdirSync as mkdirSync9,
|
|
25586
26013
|
readdirSync as readdirSync4,
|
|
25587
26014
|
readFileSync as readFileSync8,
|
|
25588
|
-
unlinkSync as
|
|
25589
|
-
writeFileSync as
|
|
26015
|
+
unlinkSync as unlinkSync7,
|
|
26016
|
+
writeFileSync as writeFileSync9
|
|
25590
26017
|
} from "fs";
|
|
25591
26018
|
import { isIP } from "net";
|
|
25592
26019
|
import { join as join17 } from "path";
|
|
@@ -25816,9 +26243,9 @@ async function fetchUrlToTempFile(url2, storageDir, options = {}) {
|
|
|
25816
26243
|
const body = Buffer.concat(chunks);
|
|
25817
26244
|
const contentFile = contentPath(storageDir, hash2, extension);
|
|
25818
26245
|
const tmpContent = `${contentFile}.tmp-${process.pid}`;
|
|
25819
|
-
|
|
25820
|
-
const { renameSync:
|
|
25821
|
-
|
|
26246
|
+
writeFileSync9(tmpContent, body);
|
|
26247
|
+
const { renameSync: renameSync5 } = await import("fs");
|
|
26248
|
+
renameSync5(tmpContent, contentFile);
|
|
25822
26249
|
const meta3 = {
|
|
25823
26250
|
url: url2,
|
|
25824
26251
|
contentType,
|
|
@@ -25826,8 +26253,8 @@ async function fetchUrlToTempFile(url2, storageDir, options = {}) {
|
|
|
25826
26253
|
fetchedAt: Date.now()
|
|
25827
26254
|
};
|
|
25828
26255
|
const tmpMeta = `${metaFile}.tmp-${process.pid}`;
|
|
25829
|
-
|
|
25830
|
-
|
|
26256
|
+
writeFileSync9(tmpMeta, JSON.stringify(meta3));
|
|
26257
|
+
renameSync5(tmpMeta, metaFile);
|
|
25831
26258
|
log(`URL cached (${total} bytes): ${url2}`);
|
|
25832
26259
|
return contentFile;
|
|
25833
26260
|
}
|
|
@@ -25848,13 +26275,13 @@ function cleanupUrlCache(storageDir) {
|
|
|
25848
26275
|
const hash2 = entry.slice(0, -".meta.json".length);
|
|
25849
26276
|
const content = contentPath(storageDir, hash2, meta3.extension);
|
|
25850
26277
|
if (existsSync11(content))
|
|
25851
|
-
|
|
25852
|
-
|
|
26278
|
+
unlinkSync7(content);
|
|
26279
|
+
unlinkSync7(metaFile);
|
|
25853
26280
|
removed++;
|
|
25854
26281
|
}
|
|
25855
26282
|
} catch {
|
|
25856
26283
|
try {
|
|
25857
|
-
|
|
26284
|
+
unlinkSync7(metaFile);
|
|
25858
26285
|
removed++;
|
|
25859
26286
|
} catch {}
|
|
25860
26287
|
}
|
|
@@ -25950,7 +26377,7 @@ function projectRootFor(runtime) {
|
|
|
25950
26377
|
function bridgeFor(ctx, runtime) {
|
|
25951
26378
|
return ctx.pool.getBridge(projectRootFor(runtime));
|
|
25952
26379
|
}
|
|
25953
|
-
function callBridge(ctx, runtime, command, params = {}) {
|
|
26380
|
+
function callBridge(ctx, runtime, command, params = {}, options) {
|
|
25954
26381
|
const merged = { ...params };
|
|
25955
26382
|
if (runtime.sessionID) {
|
|
25956
26383
|
merged.session_id = runtime.sessionID;
|
|
@@ -25958,9 +26385,13 @@ function callBridge(ctx, runtime, command, params = {}) {
|
|
|
25958
26385
|
const timeoutMs = timeoutForCommand(command);
|
|
25959
26386
|
const sendOptions = {
|
|
25960
26387
|
...timeoutMs !== undefined ? { timeoutMs } : {},
|
|
25961
|
-
configureWarningClient: ctx.client
|
|
26388
|
+
configureWarningClient: ctx.client,
|
|
26389
|
+
...options
|
|
25962
26390
|
};
|
|
25963
|
-
return bridgeFor(ctx, runtime).send(command, merged, Object.keys(sendOptions).length > 0 ? sendOptions : undefined)
|
|
26391
|
+
return bridgeFor(ctx, runtime).send(command, merged, Object.keys(sendOptions).length > 0 ? sendOptions : undefined).then((response) => {
|
|
26392
|
+
ingestBgCompletions(runtime.sessionID, response.bg_completions);
|
|
26393
|
+
return response;
|
|
26394
|
+
});
|
|
25964
26395
|
}
|
|
25965
26396
|
|
|
25966
26397
|
// src/tools/permissions.ts
|
|
@@ -26139,7 +26570,7 @@ ${hint}`;
|
|
|
26139
26570
|
|
|
26140
26571
|
` + `**Warning: This tool modifies files directly.** Use dryRun=true to preview. Consider creating an aft_safety checkpoint before bulk replacements.
|
|
26141
26572
|
|
|
26142
|
-
` + "Returns: Text summary \u2014 'Replaced N match(es) across M file(s)' (or '[DRY RUN] Would replace...') followed by file
|
|
26573
|
+
` + "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
26574
|
args: {
|
|
26144
26575
|
pattern: z2.string().describe("AST pattern with meta-variables ($VAR, $$$). Must be complete AST node."),
|
|
26145
26576
|
rewrite: z2.string().describe("Replacement pattern (can use $VAR from pattern)"),
|
|
@@ -26205,7 +26636,36 @@ ${data.scope_warnings.map((w) => ` ${w}`).join(`
|
|
|
26205
26636
|
` : `Replaced ${matchCount} match(es) in ${filesWithMatches} file(s) (${filesSearched} searched)
|
|
26206
26637
|
|
|
26207
26638
|
`;
|
|
26208
|
-
if (data.
|
|
26639
|
+
if (isDryRun && data.files && data.files.length > 0) {
|
|
26640
|
+
const MAX_DIFF_BYTES = 8 * 1024;
|
|
26641
|
+
let used = 0;
|
|
26642
|
+
let filesShown = 0;
|
|
26643
|
+
for (const f of data.files) {
|
|
26644
|
+
const relFile = f.file ?? "unknown";
|
|
26645
|
+
const reps = f.replacements ?? 0;
|
|
26646
|
+
const diff = f.diff ?? "";
|
|
26647
|
+
if (used + diff.length > MAX_DIFF_BYTES) {
|
|
26648
|
+
const remaining = data.files.length - filesShown;
|
|
26649
|
+
if (remaining > 0) {
|
|
26650
|
+
output += `
|
|
26651
|
+
... (${remaining} more file(s) omitted from preview to stay under ${MAX_DIFF_BYTES / 1024}KB; total ${matchCount} replacements across ${filesWithMatches} files)
|
|
26652
|
+
`;
|
|
26653
|
+
}
|
|
26654
|
+
break;
|
|
26655
|
+
}
|
|
26656
|
+
output += `${relFile} (${reps} replacement${reps === 1 ? "" : "s"}):
|
|
26657
|
+
`;
|
|
26658
|
+
output += diff;
|
|
26659
|
+
if (!diff.endsWith(`
|
|
26660
|
+
`))
|
|
26661
|
+
output += `
|
|
26662
|
+
`;
|
|
26663
|
+
output += `
|
|
26664
|
+
`;
|
|
26665
|
+
used += diff.length;
|
|
26666
|
+
filesShown += 1;
|
|
26667
|
+
}
|
|
26668
|
+
} else if (data.matches) {
|
|
26209
26669
|
for (const m of data.matches) {
|
|
26210
26670
|
const relFile = m.file ?? "unknown";
|
|
26211
26671
|
const line = m.line ?? 0;
|
|
@@ -26218,6 +26678,13 @@ ${data.scope_warnings.map((w) => ` ${w}`).join(`
|
|
|
26218
26678
|
`;
|
|
26219
26679
|
}
|
|
26220
26680
|
output += `
|
|
26681
|
+
`;
|
|
26682
|
+
}
|
|
26683
|
+
} else if (data.files && data.files.length > 0) {
|
|
26684
|
+
for (const f of data.files) {
|
|
26685
|
+
const relFile = f.file ?? "unknown";
|
|
26686
|
+
const reps = f.replacements ?? 0;
|
|
26687
|
+
output += ` ${relFile}: ${reps} replacement${reps === 1 ? "" : "s"}
|
|
26221
26688
|
`;
|
|
26222
26689
|
}
|
|
26223
26690
|
}
|
|
@@ -26253,7 +26720,7 @@ function conflictTools(ctx) {
|
|
|
26253
26720
|
// src/tools/hoisted.ts
|
|
26254
26721
|
import * as fs3 from "fs";
|
|
26255
26722
|
import * as path4 from "path";
|
|
26256
|
-
import { tool as
|
|
26723
|
+
import { tool as tool4 } from "@opencode-ai/plugin";
|
|
26257
26724
|
|
|
26258
26725
|
// src/patch-parser.ts
|
|
26259
26726
|
function stripHeredoc(input) {
|
|
@@ -26388,6 +26855,9 @@ function parsePatch(patchText) {
|
|
|
26388
26855
|
function normalizeUnicode(str) {
|
|
26389
26856
|
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
26857
|
}
|
|
26858
|
+
function normalizeIndent(str) {
|
|
26859
|
+
return str.replace(/^[\t ]+/, (m) => " ".repeat(m.length));
|
|
26860
|
+
}
|
|
26391
26861
|
function tryMatch(lines, pattern, startIndex, compare, eof) {
|
|
26392
26862
|
if (eof) {
|
|
26393
26863
|
const fromEnd = lines.length - pattern.length;
|
|
@@ -26416,19 +26886,58 @@ function tryMatch(lines, pattern, startIndex, compare, eof) {
|
|
|
26416
26886
|
}
|
|
26417
26887
|
return -1;
|
|
26418
26888
|
}
|
|
26419
|
-
function
|
|
26889
|
+
function seekSequenceTiered(lines, pattern, startIndex, eof = false) {
|
|
26420
26890
|
if (pattern.length === 0)
|
|
26421
|
-
return
|
|
26891
|
+
return null;
|
|
26422
26892
|
const exact = tryMatch(lines, pattern, startIndex, (a, b) => a === b, eof);
|
|
26423
26893
|
if (exact !== -1)
|
|
26424
|
-
return exact;
|
|
26894
|
+
return { found: exact, tier: "exact" };
|
|
26425
26895
|
const rstrip = tryMatch(lines, pattern, startIndex, (a, b) => a.trimEnd() === b.trimEnd(), eof);
|
|
26426
26896
|
if (rstrip !== -1)
|
|
26427
|
-
return rstrip;
|
|
26897
|
+
return { found: rstrip, tier: "rstrip" };
|
|
26428
26898
|
const trim = tryMatch(lines, pattern, startIndex, (a, b) => a.trim() === b.trim(), eof);
|
|
26429
26899
|
if (trim !== -1)
|
|
26430
|
-
return trim;
|
|
26431
|
-
|
|
26900
|
+
return { found: trim, tier: "trim" };
|
|
26901
|
+
const indent = tryMatch(lines, pattern, startIndex, (a, b) => normalizeIndent(a).trimEnd() === normalizeIndent(b).trimEnd(), eof);
|
|
26902
|
+
if (indent !== -1)
|
|
26903
|
+
return { found: indent, tier: "indent" };
|
|
26904
|
+
const unicode = tryMatch(lines, pattern, startIndex, (a, b) => normalizeUnicode(a.trim()) === normalizeUnicode(b.trim()), eof);
|
|
26905
|
+
if (unicode !== -1)
|
|
26906
|
+
return { found: unicode, tier: "unicode" };
|
|
26907
|
+
return null;
|
|
26908
|
+
}
|
|
26909
|
+
function seekSequence(lines, pattern, startIndex, eof = false) {
|
|
26910
|
+
const r = seekSequenceTiered(lines, pattern, startIndex, eof);
|
|
26911
|
+
return r ? r.found : -1;
|
|
26912
|
+
}
|
|
26913
|
+
function findClosestPartialMatch(lines, pattern) {
|
|
26914
|
+
if (pattern.length === 0 || lines.length === 0)
|
|
26915
|
+
return null;
|
|
26916
|
+
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());
|
|
26917
|
+
const candidates = [];
|
|
26918
|
+
for (let i = 0;i < lines.length && candidates.length < 16; i++) {
|
|
26919
|
+
if (compareAny(lines[i], pattern[0]))
|
|
26920
|
+
candidates.push(i);
|
|
26921
|
+
}
|
|
26922
|
+
if (candidates.length === 0)
|
|
26923
|
+
return null;
|
|
26924
|
+
let best = { lineNumber: -1, matchedLines: 0, firstDivergence: -1 };
|
|
26925
|
+
for (const start of candidates) {
|
|
26926
|
+
let matched = 0;
|
|
26927
|
+
for (let j = 0;j < pattern.length && start + j < lines.length; j++) {
|
|
26928
|
+
if (!compareAny(lines[start + j], pattern[j]))
|
|
26929
|
+
break;
|
|
26930
|
+
matched++;
|
|
26931
|
+
}
|
|
26932
|
+
if (matched > best.matchedLines) {
|
|
26933
|
+
best = {
|
|
26934
|
+
lineNumber: start + 1,
|
|
26935
|
+
matchedLines: matched,
|
|
26936
|
+
firstDivergence: matched
|
|
26937
|
+
};
|
|
26938
|
+
}
|
|
26939
|
+
}
|
|
26940
|
+
return best.lineNumber === -1 ? null : best;
|
|
26432
26941
|
}
|
|
26433
26942
|
function applyUpdateChunks(originalContent, filePath, chunks) {
|
|
26434
26943
|
const originalLines = originalContent.split(`
|
|
@@ -26465,9 +26974,30 @@ function applyUpdateChunks(originalContent, filePath, chunks) {
|
|
|
26465
26974
|
replacements.push([found, pattern.length, newSlice]);
|
|
26466
26975
|
lineIndex = found + pattern.length;
|
|
26467
26976
|
} else {
|
|
26977
|
+
const newSliceTrimmed = newSlice.filter((line) => line.trim().length > 0);
|
|
26978
|
+
const alreadyApplied = newSliceTrimmed.length > 0 && seekSequence(originalLines, newSliceTrimmed, 0, chunk.is_end_of_file) !== -1;
|
|
26979
|
+
const closest = findClosestPartialMatch(originalLines, pattern);
|
|
26980
|
+
let closestHint = "";
|
|
26981
|
+
if (closest && closest.matchedLines > 0) {
|
|
26982
|
+
const fileLineNo = closest.lineNumber + closest.firstDivergence;
|
|
26983
|
+
const expectedLine = pattern[closest.firstDivergence];
|
|
26984
|
+
const actualLine = fileLineNo - 1 < originalLines.length ? originalLines[fileLineNo - 1] : "<EOF>";
|
|
26985
|
+
closestHint = `
|
|
26986
|
+
|
|
26987
|
+
Closest match starts at line ${closest.lineNumber} ` + `(${closest.matchedLines} of ${pattern.length} lines matched).
|
|
26988
|
+
` + `First divergence at line ${fileLineNo}:
|
|
26989
|
+
` + ` expected: ${JSON.stringify(expectedLine)}
|
|
26990
|
+
` + ` actual: ${JSON.stringify(actualLine)}`;
|
|
26991
|
+
}
|
|
26992
|
+
const triedTiers = "exact, trimEnd, trim, indent (tab/space), unicode";
|
|
26993
|
+
const alreadyAppliedHint = alreadyApplied ? `
|
|
26994
|
+
|
|
26995
|
+
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
26996
|
throw new Error(`Failed to find expected lines in ${filePath}:
|
|
26469
26997
|
${chunk.old_lines.join(`
|
|
26470
|
-
`)}
|
|
26998
|
+
`)}
|
|
26999
|
+
|
|
27000
|
+
` + `Tried match tiers: ${triedTiers}.${closestHint}${alreadyAppliedHint}`);
|
|
26471
27001
|
}
|
|
26472
27002
|
}
|
|
26473
27003
|
replacements.sort((a, b) => a[0] - b[0]);
|
|
@@ -26483,14 +27013,163 @@ ${chunk.old_lines.join(`
|
|
|
26483
27013
|
`);
|
|
26484
27014
|
}
|
|
26485
27015
|
|
|
26486
|
-
// src/tools/
|
|
27016
|
+
// src/tools/bash.ts
|
|
27017
|
+
import { tool as tool3 } from "@opencode-ai/plugin";
|
|
27018
|
+
var z3 = tool3.schema;
|
|
27019
|
+
var METADATA_PREVIEW_LIMIT = 30 * 1024;
|
|
27020
|
+
var DEFAULT_BASH_TIMEOUT_MS = 120000;
|
|
27021
|
+
var BASH_TRANSPORT_TIMEOUT_OVERHEAD_MS = 5000;
|
|
27022
|
+
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.`;
|
|
27023
|
+
async function withPermissionLoop(ctx, runtime, params, bridgeCall, options) {
|
|
27024
|
+
const first = await bridgeCall(ctx, runtime, "bash", params, options);
|
|
27025
|
+
if (first.success !== false || first.code !== "permission_required")
|
|
27026
|
+
return first;
|
|
27027
|
+
const asks = Array.isArray(first.asks) ? first.asks : [];
|
|
27028
|
+
const permissionsGranted = [];
|
|
27029
|
+
for (const ask of asks) {
|
|
27030
|
+
const permission = ask.kind === "external_directory" ? "external_directory" : "bash";
|
|
27031
|
+
await runtime.ask({
|
|
27032
|
+
permission,
|
|
27033
|
+
patterns: ask.patterns,
|
|
27034
|
+
always: ask.always,
|
|
27035
|
+
metadata: {}
|
|
27036
|
+
});
|
|
27037
|
+
permissionsGranted.push(...ask.always.length > 0 ? ask.always : ask.patterns);
|
|
27038
|
+
}
|
|
27039
|
+
const second = await bridgeCall(ctx, runtime, "bash", { ...params, permissions_granted: permissionsGranted }, options);
|
|
27040
|
+
if (second.success === false && second.code === "permission_required") {
|
|
27041
|
+
throw new Error("bash permission retry failed");
|
|
27042
|
+
}
|
|
27043
|
+
return second;
|
|
27044
|
+
}
|
|
27045
|
+
function createBashTool(ctx) {
|
|
27046
|
+
return {
|
|
27047
|
+
description: BASH_DESCRIPTION,
|
|
27048
|
+
args: {
|
|
27049
|
+
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."),
|
|
27050
|
+
timeout: z3.number().optional().describe("Maximum execution time in milliseconds for foreground commands. Defaults to 120000 (2 minutes) when omitted."),
|
|
27051
|
+
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."),
|
|
27052
|
+
description: z3.string().optional().describe("Short 5-10 word human-readable summary shown in OpenCode UI metadata instead of raw shell syntax."),
|
|
27053
|
+
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."),
|
|
27054
|
+
compressed: z3.boolean().optional().describe("When true or omitted, return compressed output with noisy terminal control sequences reduced. Set to false for raw output.")
|
|
27055
|
+
},
|
|
27056
|
+
execute: async (args, context) => {
|
|
27057
|
+
let accumulatedOutput = "";
|
|
27058
|
+
const description = args.description;
|
|
27059
|
+
const metadata = context.metadata;
|
|
27060
|
+
const command = args.command;
|
|
27061
|
+
const cwd = args.workdir ?? context.directory;
|
|
27062
|
+
const shellEnv = await ctx.plugin?.trigger?.("shell.env", { cwd, sessionID: context.sessionID, callID: getCallID(context) }, { env: {} });
|
|
27063
|
+
const data = await withPermissionLoop(ctx, context, {
|
|
27064
|
+
command,
|
|
27065
|
+
timeout: args.timeout,
|
|
27066
|
+
workdir: args.workdir,
|
|
27067
|
+
env: shellEnv?.env ?? {},
|
|
27068
|
+
description,
|
|
27069
|
+
background: args.background,
|
|
27070
|
+
compressed: args.compressed,
|
|
27071
|
+
permissions_requested: true
|
|
27072
|
+
}, callBridge, {
|
|
27073
|
+
transportTimeoutMs: bashTransportTimeoutMs(args.timeout),
|
|
27074
|
+
onProgress: ({ text }) => {
|
|
27075
|
+
accumulatedOutput = preview(accumulatedOutput + text);
|
|
27076
|
+
metadata?.({ output: accumulatedOutput, description });
|
|
27077
|
+
}
|
|
27078
|
+
});
|
|
27079
|
+
if (data.success === false) {
|
|
27080
|
+
throw new Error(data.message || "bash failed");
|
|
27081
|
+
}
|
|
27082
|
+
if (data.status === "running" && typeof data.task_id === "string") {
|
|
27083
|
+
const callID2 = getCallID(context);
|
|
27084
|
+
const taskId = data.task_id;
|
|
27085
|
+
trackBgTask(context.sessionID, taskId);
|
|
27086
|
+
const startedLine = `Background task started: ${taskId}`;
|
|
27087
|
+
const metadataPayload2 = { description, output: startedLine, status: "running", taskId };
|
|
27088
|
+
metadata?.(metadataPayload2);
|
|
27089
|
+
if (callID2) {
|
|
27090
|
+
storeToolMetadata(context.sessionID, callID2, {
|
|
27091
|
+
title: description ?? shortenCommand(command),
|
|
27092
|
+
metadata: metadataPayload2
|
|
27093
|
+
});
|
|
27094
|
+
}
|
|
27095
|
+
return startedLine;
|
|
27096
|
+
}
|
|
27097
|
+
const output = data.output ?? "";
|
|
27098
|
+
const metadataOutput = preview(output);
|
|
27099
|
+
const exit = data.exit_code;
|
|
27100
|
+
const truncated = data.truncated;
|
|
27101
|
+
const outputPath = data.output_path;
|
|
27102
|
+
const timedOut = data.timed_out === true;
|
|
27103
|
+
const callID = getCallID(context);
|
|
27104
|
+
const metadataPayload = {
|
|
27105
|
+
description,
|
|
27106
|
+
output: metadataOutput,
|
|
27107
|
+
exit,
|
|
27108
|
+
truncated,
|
|
27109
|
+
...outputPath ? { outputPath } : {}
|
|
27110
|
+
};
|
|
27111
|
+
metadata?.(metadataPayload);
|
|
27112
|
+
if (callID) {
|
|
27113
|
+
storeToolMetadata(context.sessionID, callID, {
|
|
27114
|
+
title: description ?? shortenCommand(command),
|
|
27115
|
+
metadata: metadataPayload
|
|
27116
|
+
});
|
|
27117
|
+
}
|
|
27118
|
+
let rendered = output;
|
|
27119
|
+
if (truncated && outputPath) {
|
|
27120
|
+
rendered += `
|
|
27121
|
+
[output truncated; full output at ${outputPath}]`;
|
|
27122
|
+
}
|
|
27123
|
+
if (timedOut) {
|
|
27124
|
+
rendered += `
|
|
27125
|
+
[command timed out]`;
|
|
27126
|
+
}
|
|
27127
|
+
if (typeof exit === "number" && exit !== 0) {
|
|
27128
|
+
rendered += `
|
|
27129
|
+
[exit code: ${exit}]`;
|
|
27130
|
+
}
|
|
27131
|
+
return rendered;
|
|
27132
|
+
}
|
|
27133
|
+
};
|
|
27134
|
+
}
|
|
27135
|
+
function bashTransportTimeoutMs(timeout) {
|
|
27136
|
+
const bashTimeout = timeout ?? DEFAULT_BASH_TIMEOUT_MS;
|
|
27137
|
+
return Math.max(30000, bashTimeout + BASH_TRANSPORT_TIMEOUT_OVERHEAD_MS);
|
|
27138
|
+
}
|
|
27139
|
+
function preview(output) {
|
|
27140
|
+
return output.length <= METADATA_PREVIEW_LIMIT ? output : output.slice(-METADATA_PREVIEW_LIMIT);
|
|
27141
|
+
}
|
|
26487
27142
|
function getCallID(ctx) {
|
|
26488
27143
|
const c = ctx;
|
|
26489
27144
|
return c.callID ?? c.callId ?? c.call_id;
|
|
26490
27145
|
}
|
|
27146
|
+
function shortenCommand(command) {
|
|
27147
|
+
const collapsed = command.replace(/\s+/g, " ").trim();
|
|
27148
|
+
return collapsed.length <= 80 ? collapsed : `${collapsed.slice(0, 77)}...`;
|
|
27149
|
+
}
|
|
27150
|
+
|
|
27151
|
+
// src/tools/hoisted.ts
|
|
27152
|
+
function getCallID2(ctx) {
|
|
27153
|
+
const c = ctx;
|
|
27154
|
+
return c.callID ?? c.callId ?? c.call_id;
|
|
27155
|
+
}
|
|
26491
27156
|
function relativeToWorktree(fp, worktree) {
|
|
26492
27157
|
return path4.relative(worktree, fp);
|
|
26493
27158
|
}
|
|
27159
|
+
function formatReadFooter(agentSpecifiedRange, data) {
|
|
27160
|
+
if (agentSpecifiedRange)
|
|
27161
|
+
return "";
|
|
27162
|
+
if (!data.truncated)
|
|
27163
|
+
return "";
|
|
27164
|
+
const startLine = data.start_line;
|
|
27165
|
+
const endLine = data.end_line;
|
|
27166
|
+
const totalLines = data.total_lines;
|
|
27167
|
+
if (startLine === undefined || endLine === undefined || totalLines === undefined) {
|
|
27168
|
+
return "";
|
|
27169
|
+
}
|
|
27170
|
+
return `
|
|
27171
|
+
(Showing lines ${startLine}-${endLine} of ${totalLines}. Use startLine/endLine to read other sections.)`;
|
|
27172
|
+
}
|
|
26494
27173
|
function buildUnifiedDiff(fp, before, after) {
|
|
26495
27174
|
const SIZE_CAP = 100 * 1024;
|
|
26496
27175
|
if (before.length > SIZE_CAP || after.length > SIZE_CAP) {
|
|
@@ -26677,7 +27356,7 @@ function inferBeforeStart(ops, from, beforeLen) {
|
|
|
26677
27356
|
}
|
|
26678
27357
|
return beforeLen;
|
|
26679
27358
|
}
|
|
26680
|
-
var
|
|
27359
|
+
var z4 = tool4.schema;
|
|
26681
27360
|
var READ_DESCRIPTION = `Read file contents or list directory entries.
|
|
26682
27361
|
|
|
26683
27362
|
Use either startLine/endLine OR offset/limit to read a section of a file.
|
|
@@ -26701,11 +27380,11 @@ function createReadTool(ctx) {
|
|
|
26701
27380
|
return {
|
|
26702
27381
|
description: READ_DESCRIPTION,
|
|
26703
27382
|
args: {
|
|
26704
|
-
filePath:
|
|
26705
|
-
startLine:
|
|
26706
|
-
endLine:
|
|
26707
|
-
limit:
|
|
26708
|
-
offset:
|
|
27383
|
+
filePath: z4.string().describe("Path to file or directory (absolute or relative to project root)"),
|
|
27384
|
+
startLine: z4.number().optional().describe("1-based line to start reading from"),
|
|
27385
|
+
endLine: z4.number().optional().describe("1-based line to stop reading at (inclusive)"),
|
|
27386
|
+
limit: z4.number().optional().describe("Max lines to return (default: 2000)"),
|
|
27387
|
+
offset: z4.number().optional().describe("1-based line number to start reading from (use with limit). Ignored if startLine is provided")
|
|
26709
27388
|
},
|
|
26710
27389
|
execute: async (args, context) => {
|
|
26711
27390
|
const file2 = args.filePath;
|
|
@@ -26743,7 +27422,7 @@ function createReadTool(ctx) {
|
|
|
26743
27422
|
} catch {}
|
|
26744
27423
|
const sizeStr = fileSize > 1048576 ? `${(fileSize / 1048576).toFixed(1)}MB` : fileSize > 1024 ? `${(fileSize / 1024).toFixed(0)}KB` : `${fileSize} bytes`;
|
|
26745
27424
|
const msg = `${label} read successfully`;
|
|
26746
|
-
const imgCallID =
|
|
27425
|
+
const imgCallID = getCallID2(context);
|
|
26747
27426
|
if (imgCallID) {
|
|
26748
27427
|
storeToolMetadata(context.sessionID, imgCallID, {
|
|
26749
27428
|
title: path4.relative(context.worktree, filePath),
|
|
@@ -26776,7 +27455,7 @@ function createReadTool(ctx) {
|
|
|
26776
27455
|
if (data.success === false) {
|
|
26777
27456
|
throw new Error(data.message || "read failed");
|
|
26778
27457
|
}
|
|
26779
|
-
const readCallID =
|
|
27458
|
+
const readCallID = getCallID2(context);
|
|
26780
27459
|
if (data.entries) {
|
|
26781
27460
|
if (readCallID) {
|
|
26782
27461
|
const dp = relativeToWorktree(filePath, context.worktree) || file2;
|
|
@@ -26797,10 +27476,10 @@ function createReadTool(ctx) {
|
|
|
26797
27476
|
storeToolMetadata(context.sessionID, readCallID, { title: dp, metadata: { title: dp } });
|
|
26798
27477
|
}
|
|
26799
27478
|
let output = data.content;
|
|
26800
|
-
|
|
26801
|
-
|
|
26802
|
-
(
|
|
26803
|
-
|
|
27479
|
+
const agentSpecifiedRange = args.startLine !== undefined || args.endLine !== undefined || args.offset !== undefined || args.limit !== undefined;
|
|
27480
|
+
const footer = formatReadFooter(agentSpecifiedRange, data);
|
|
27481
|
+
if (footer)
|
|
27482
|
+
output += footer;
|
|
26804
27483
|
return output;
|
|
26805
27484
|
}
|
|
26806
27485
|
};
|
|
@@ -26826,8 +27505,8 @@ function createWriteTool(ctx, editToolName = "edit") {
|
|
|
26826
27505
|
return {
|
|
26827
27506
|
description: getWriteDescription(editToolName),
|
|
26828
27507
|
args: {
|
|
26829
|
-
filePath:
|
|
26830
|
-
content:
|
|
27508
|
+
filePath: z4.string().describe("Path to the file to write (absolute or relative to project root)"),
|
|
27509
|
+
content: z4.string().describe("The full content to write to the file")
|
|
26831
27510
|
},
|
|
26832
27511
|
execute: async (args, context) => {
|
|
26833
27512
|
const file2 = args.filePath;
|
|
@@ -26880,7 +27559,7 @@ Note: LSP server(s) did not respond in time: ${pendingServers.join(", ")}. Diagn
|
|
|
26880
27559
|
Note: LSP server(s) exited during this edit: ${exitedServers.join(", ")}. Their diagnostics could not be collected.`;
|
|
26881
27560
|
}
|
|
26882
27561
|
const diff = data.diff;
|
|
26883
|
-
const callID =
|
|
27562
|
+
const callID = getCallID2(context);
|
|
26884
27563
|
if (callID) {
|
|
26885
27564
|
const dp = relativeToWorktree(filePath, context.worktree);
|
|
26886
27565
|
const beforeContent = diff?.before ?? "";
|
|
@@ -26909,7 +27588,7 @@ function getEditDescription(writeToolName) {
|
|
|
26909
27588
|
|
|
26910
27589
|
**Modes** (determined by which parameters you provide):
|
|
26911
27590
|
|
|
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.
|
|
27591
|
+
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
27592
|
|
|
26914
27593
|
1. **Multi-file transaction** \u2014 pass \`operations\` array
|
|
26915
27594
|
Edits across multiple files with checkpoint-based rollback on failure.
|
|
@@ -26917,33 +27596,37 @@ Mode priority: operations > edits > symbol (without oldString) > oldString (find
|
|
|
26917
27596
|
For \`edit_match\`: include \`match\`, \`replacement\`. For \`write\`: include \`content\`.
|
|
26918
27597
|
Example: \`{ "operations": [{ "file": "a.ts", "command": "edit_match", "match": "old", "replacement": "new" }, { "file": "b.ts", "command": "write", "content": "..." }] }\`
|
|
26919
27598
|
|
|
26920
|
-
2. **
|
|
27599
|
+
2. **Append** \u2014 pass \`filePath\` + \`appendContent\`
|
|
27600
|
+
Appends text to the end of a file, creating the file if it does not exist.
|
|
27601
|
+
Example: \`{ "filePath": "notes.txt", "appendContent": "new line\\n" }\`
|
|
27602
|
+
|
|
27603
|
+
3. **Batch edits** \u2014 pass \`filePath\` + \`edits\` array
|
|
26921
27604
|
Multiple edits in one file atomically. Each edit is either:
|
|
26922
27605
|
- \`{ "oldString": "old", "newString": "new" }\` \u2014 find/replace
|
|
26923
27606
|
- \`{ "startLine": 5, "endLine": 7, "content": "new lines" }\` \u2014 replace line range (1-based, both inclusive)
|
|
26924
27607
|
Set content to empty string to delete lines.
|
|
26925
27608
|
|
|
26926
|
-
|
|
27609
|
+
4. **Symbol replace** \u2014 pass \`filePath\` + \`symbol\` + \`content\`
|
|
26927
27610
|
Replaces an entire named symbol (function, class, type) with new content.
|
|
26928
27611
|
Includes decorators, attributes, and doc comments in the replacement range.
|
|
26929
27612
|
**Important:** You must NOT provide \`oldString\` when using symbol mode \u2014 if present, the tool silently falls back to find/replace mode.
|
|
26930
27613
|
Example: \`{ "filePath": "src/app.ts", "symbol": "handleRequest", "content": "function handleRequest() { ... }" }\`
|
|
26931
27614
|
|
|
26932
|
-
|
|
27615
|
+
5. **Find and replace** \u2014 pass \`filePath\` + \`oldString\` + \`newString\`
|
|
26933
27616
|
Finds the exact text in \`oldString\` and replaces it with \`newString\`.
|
|
26934
27617
|
Supports fuzzy matching (handles whitespace differences automatically).
|
|
26935
27618
|
If multiple matches exist, specify which one with \`occurrence\` or use \`replaceAll: true\`.
|
|
26936
27619
|
Example: \`{ "filePath": "src/app.ts", "oldString": "const x = 1", "newString": "const x = 2" }\`
|
|
26937
27620
|
|
|
26938
|
-
|
|
27621
|
+
6. **Replace all occurrences** \u2014 add \`replaceAll: true\`
|
|
26939
27622
|
Replaces every occurrence of \`oldString\` in the file.
|
|
26940
27623
|
Example: \`{ "filePath": "src/app.ts", "oldString": "oldName", "newString": "newName", "replaceAll": true }\`
|
|
26941
27624
|
|
|
26942
|
-
|
|
27625
|
+
7. **Select specific occurrence** \u2014 add \`occurrence: N\` (0-indexed)
|
|
26943
27626
|
When multiple matches exist, select the Nth one (0 = first, 1 = second, etc.).
|
|
26944
27627
|
Example: \`{ "filePath": "src/app.ts", "oldString": "TODO", "newString": "DONE", "occurrence": 0 }\`
|
|
26945
27628
|
|
|
26946
|
-
Note: Modes
|
|
27629
|
+
Note: Modes 6 and 7 are options on mode 5 (find/replace) \u2014 they require \`oldString\`.
|
|
26947
27630
|
|
|
26948
27631
|
**Behavior:**
|
|
26949
27632
|
- Backs up files before editing (recoverable via aft_safety undo)
|
|
@@ -26960,16 +27643,17 @@ function createEditTool(ctx, writeToolName = "write") {
|
|
|
26960
27643
|
return {
|
|
26961
27644
|
description: getEditDescription(writeToolName),
|
|
26962
27645
|
args: {
|
|
26963
|
-
filePath:
|
|
26964
|
-
oldString:
|
|
26965
|
-
newString:
|
|
26966
|
-
replaceAll:
|
|
26967
|
-
occurrence:
|
|
26968
|
-
symbol:
|
|
26969
|
-
content:
|
|
26970
|
-
|
|
26971
|
-
|
|
26972
|
-
|
|
27646
|
+
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"),
|
|
27647
|
+
oldString: z4.string().optional().describe("Text to find (exact match, with fuzzy fallback)"),
|
|
27648
|
+
newString: z4.string().optional().describe("Text to replace with (omit or set to empty string to delete the matched text)"),
|
|
27649
|
+
replaceAll: z4.boolean().optional().describe("Replace all occurrences"),
|
|
27650
|
+
occurrence: z4.number().optional().describe("0-indexed occurrence to replace when multiple matches exist"),
|
|
27651
|
+
symbol: z4.string().optional().describe("Named symbol to replace (function, class, type)"),
|
|
27652
|
+
content: z4.string().optional().describe("New content for symbol replace or file write"),
|
|
27653
|
+
appendContent: z4.string().optional().describe("Text to append to the end of filePath; creates the file if needed"),
|
|
27654
|
+
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 }"),
|
|
27655
|
+
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)"),
|
|
27656
|
+
dryRun: z4.boolean().optional().describe("Preview changes without applying (returns diff, default: false)")
|
|
26973
27657
|
},
|
|
26974
27658
|
execute: async (args, context) => {
|
|
26975
27659
|
const argsRecord = args;
|
|
@@ -27007,7 +27691,12 @@ function createEditTool(ctx, writeToolName = "write") {
|
|
|
27007
27691
|
});
|
|
27008
27692
|
const params = { file: filePath };
|
|
27009
27693
|
let command;
|
|
27010
|
-
if (
|
|
27694
|
+
if (typeof args.appendContent === "string") {
|
|
27695
|
+
command = "edit_match";
|
|
27696
|
+
params.op = "append";
|
|
27697
|
+
params.append_content = args.appendContent;
|
|
27698
|
+
params.create_dirs = true;
|
|
27699
|
+
} else if (Array.isArray(args.edits)) {
|
|
27011
27700
|
command = "batch";
|
|
27012
27701
|
params.edits = args.edits.map((edit) => {
|
|
27013
27702
|
const translated = {};
|
|
@@ -27051,7 +27740,7 @@ function createEditTool(ctx, writeToolName = "write") {
|
|
|
27051
27740
|
const data = await callBridge(ctx, context, command, params);
|
|
27052
27741
|
if (!args.dryRun && data.success && data.diff) {
|
|
27053
27742
|
const diff = data.diff;
|
|
27054
|
-
const callID =
|
|
27743
|
+
const callID = getCallID2(context);
|
|
27055
27744
|
if (callID) {
|
|
27056
27745
|
const dp = relativeToWorktree(filePath, context.worktree);
|
|
27057
27746
|
const beforeContent = diff.before ?? "";
|
|
@@ -27150,7 +27839,7 @@ function createApplyPatchTool(ctx) {
|
|
|
27150
27839
|
return {
|
|
27151
27840
|
description: APPLY_PATCH_DESCRIPTION,
|
|
27152
27841
|
args: {
|
|
27153
|
-
patchText:
|
|
27842
|
+
patchText: z4.string().describe("The full patch text including Begin/End markers")
|
|
27154
27843
|
},
|
|
27155
27844
|
execute: async (args, context) => {
|
|
27156
27845
|
const patchText = args.patchText;
|
|
@@ -27182,6 +27871,7 @@ function createApplyPatchTool(ctx) {
|
|
|
27182
27871
|
}
|
|
27183
27872
|
}
|
|
27184
27873
|
const relPaths = Array.from(affectedAbs).map((abs) => path4.relative(context.worktree, abs));
|
|
27874
|
+
const multiFileWritePaths = Array.from(affectedAbs);
|
|
27185
27875
|
await context.ask({
|
|
27186
27876
|
permission: "edit",
|
|
27187
27877
|
patterns: relPaths,
|
|
@@ -27201,12 +27891,18 @@ function createApplyPatchTool(ctx) {
|
|
|
27201
27891
|
} catch {}
|
|
27202
27892
|
}
|
|
27203
27893
|
const results = [];
|
|
27894
|
+
const failures = [];
|
|
27204
27895
|
const perFileDiffs = [];
|
|
27205
|
-
let patchFailed = false;
|
|
27206
27896
|
for (const hunk of hunks) {
|
|
27207
27897
|
const filePath = path4.resolve(context.directory, hunk.path);
|
|
27208
27898
|
switch (hunk.type) {
|
|
27209
27899
|
case "add": {
|
|
27900
|
+
if (fs3.existsSync(filePath)) {
|
|
27901
|
+
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.`;
|
|
27902
|
+
results.push(msg);
|
|
27903
|
+
failures.push(hunk.path);
|
|
27904
|
+
break;
|
|
27905
|
+
}
|
|
27210
27906
|
try {
|
|
27211
27907
|
const content = hunk.contents.endsWith(`
|
|
27212
27908
|
`) ? hunk.contents : `${hunk.contents}
|
|
@@ -27216,7 +27912,8 @@ function createApplyPatchTool(ctx) {
|
|
|
27216
27912
|
content,
|
|
27217
27913
|
create_dirs: true,
|
|
27218
27914
|
diagnostics: true,
|
|
27219
|
-
include_diff: true
|
|
27915
|
+
include_diff: true,
|
|
27916
|
+
multi_file_write_paths: multiFileWritePaths
|
|
27220
27917
|
});
|
|
27221
27918
|
const wrDiff = writeResult.diff;
|
|
27222
27919
|
perFileDiffs.push({
|
|
@@ -27228,8 +27925,15 @@ function createApplyPatchTool(ctx) {
|
|
|
27228
27925
|
});
|
|
27229
27926
|
results.push(`Created ${hunk.path}`);
|
|
27230
27927
|
} catch (e) {
|
|
27231
|
-
|
|
27232
|
-
results.push(
|
|
27928
|
+
const msg = `Failed to create ${hunk.path}: ${e instanceof Error ? e.message : e}`;
|
|
27929
|
+
results.push(msg);
|
|
27930
|
+
failures.push(hunk.path);
|
|
27931
|
+
const filePath2 = path4.resolve(context.directory, hunk.path);
|
|
27932
|
+
if (fs3.existsSync(filePath2)) {
|
|
27933
|
+
try {
|
|
27934
|
+
await callBridge(ctx, context, "delete_file", { file: filePath2 });
|
|
27935
|
+
} catch {}
|
|
27936
|
+
}
|
|
27233
27937
|
}
|
|
27234
27938
|
break;
|
|
27235
27939
|
}
|
|
@@ -27246,8 +27950,8 @@ function createApplyPatchTool(ctx) {
|
|
|
27246
27950
|
});
|
|
27247
27951
|
results.push(`Deleted ${hunk.path}`);
|
|
27248
27952
|
} catch (e) {
|
|
27249
|
-
patchFailed = true;
|
|
27250
27953
|
results.push(`Failed to delete ${hunk.path}: ${e instanceof Error ? e.message : e}`);
|
|
27954
|
+
failures.push(hunk.path);
|
|
27251
27955
|
}
|
|
27252
27956
|
break;
|
|
27253
27957
|
}
|
|
@@ -27261,7 +27965,8 @@ function createApplyPatchTool(ctx) {
|
|
|
27261
27965
|
content: newContent,
|
|
27262
27966
|
create_dirs: true,
|
|
27263
27967
|
diagnostics: true,
|
|
27264
|
-
include_diff: true
|
|
27968
|
+
include_diff: true,
|
|
27969
|
+
multi_file_write_paths: multiFileWritePaths
|
|
27265
27970
|
});
|
|
27266
27971
|
const diags = writeResult.lsp_diagnostics;
|
|
27267
27972
|
if (diags && diags.length > 0) {
|
|
@@ -27289,51 +27994,60 @@ ${diagLines}`);
|
|
|
27289
27994
|
deletions
|
|
27290
27995
|
});
|
|
27291
27996
|
if (hunk.move_path) {
|
|
27292
|
-
|
|
27997
|
+
try {
|
|
27998
|
+
const deleteResult = await callBridge(ctx, context, "delete_file", {
|
|
27999
|
+
file: filePath
|
|
28000
|
+
});
|
|
28001
|
+
if (deleteResult.success === false) {
|
|
28002
|
+
throw new Error(deleteResult.message ?? "delete failed");
|
|
28003
|
+
}
|
|
28004
|
+
} catch (deleteError) {
|
|
28005
|
+
try {
|
|
28006
|
+
if (!checkpointCreated) {
|
|
28007
|
+
throw new Error("pre-patch checkpoint was not created");
|
|
28008
|
+
}
|
|
28009
|
+
const rollbackResult = await callBridge(ctx, context, "restore_checkpoint", {
|
|
28010
|
+
name: checkpointName
|
|
28011
|
+
});
|
|
28012
|
+
if (rollbackResult.success === false) {
|
|
28013
|
+
throw new Error(rollbackResult.message ?? "checkpoint restore failed");
|
|
28014
|
+
}
|
|
28015
|
+
if (newlyCreatedAbs.has(targetPath) && fs3.existsSync(targetPath)) {
|
|
28016
|
+
const cleanupResult = await callBridge(ctx, context, "delete_file", {
|
|
28017
|
+
file: targetPath
|
|
28018
|
+
});
|
|
28019
|
+
if (cleanupResult.success === false) {
|
|
28020
|
+
throw new Error(cleanupResult.message ?? "new destination cleanup failed");
|
|
28021
|
+
}
|
|
28022
|
+
}
|
|
28023
|
+
} catch (rollbackError) {
|
|
28024
|
+
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}`);
|
|
28025
|
+
}
|
|
28026
|
+
throw new Error(`source delete failed after writing move destination; restored pre-patch checkpoint ${checkpointName}: ${formatError2(deleteError)}`);
|
|
28027
|
+
}
|
|
27293
28028
|
results.push(`Updated and moved ${hunk.path} \u2192 ${hunk.move_path}`);
|
|
27294
28029
|
} else {
|
|
27295
28030
|
results.push(`Updated ${hunk.path}`);
|
|
27296
28031
|
}
|
|
27297
28032
|
} catch (e) {
|
|
27298
|
-
patchFailed = true;
|
|
27299
28033
|
results.push(`Failed to update ${hunk.path}: ${e instanceof Error ? e.message : e}`);
|
|
28034
|
+
failures.push(hunk.path);
|
|
27300
28035
|
break;
|
|
27301
28036
|
}
|
|
27302
28037
|
break;
|
|
27303
28038
|
}
|
|
27304
28039
|
}
|
|
27305
28040
|
}
|
|
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(`
|
|
28041
|
+
if (failures.length > 0) {
|
|
28042
|
+
const partial2 = failures.length < hunks.length;
|
|
28043
|
+
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(", ")}.`;
|
|
28044
|
+
results.push(summary);
|
|
28045
|
+
if (!partial2) {
|
|
28046
|
+
return results.join(`
|
|
27334
28047
|
`);
|
|
28048
|
+
}
|
|
27335
28049
|
}
|
|
27336
|
-
const callID =
|
|
28050
|
+
const callID = getCallID2(context);
|
|
27337
28051
|
if (callID) {
|
|
27338
28052
|
const diffByPath = new Map(perFileDiffs.map((d) => [d.filePath, d]));
|
|
27339
28053
|
const files = hunks.map((h) => {
|
|
@@ -27386,7 +28100,7 @@ function createDeleteTool(ctx) {
|
|
|
27386
28100
|
return {
|
|
27387
28101
|
description: DELETE_DESCRIPTION,
|
|
27388
28102
|
args: {
|
|
27389
|
-
filePath:
|
|
28103
|
+
filePath: z4.string().describe("Path to file to delete")
|
|
27390
28104
|
},
|
|
27391
28105
|
execute: async (args, context) => {
|
|
27392
28106
|
const filePath = path4.isAbsolute(args.filePath) ? args.filePath : path4.resolve(context.directory, args.filePath);
|
|
@@ -27410,8 +28124,8 @@ function createMoveTool(ctx) {
|
|
|
27410
28124
|
return {
|
|
27411
28125
|
description: MOVE_DESCRIPTION,
|
|
27412
28126
|
args: {
|
|
27413
|
-
filePath:
|
|
27414
|
-
destination:
|
|
28127
|
+
filePath: z4.string().describe("Source file path to move"),
|
|
28128
|
+
destination: z4.string().describe("Destination file path")
|
|
27415
28129
|
},
|
|
27416
28130
|
execute: async (args, context) => {
|
|
27417
28131
|
const filePath = path4.isAbsolute(args.filePath) ? args.filePath : path4.resolve(context.directory, args.filePath);
|
|
@@ -27435,6 +28149,7 @@ function createMoveTool(ctx) {
|
|
|
27435
28149
|
}
|
|
27436
28150
|
function hoistedTools(ctx) {
|
|
27437
28151
|
return {
|
|
28152
|
+
bash: createBashTool(ctx),
|
|
27438
28153
|
read: createReadTool(ctx),
|
|
27439
28154
|
write: createWriteTool(ctx, "edit"),
|
|
27440
28155
|
edit: createEditTool(ctx, "write"),
|
|
@@ -27443,6 +28158,9 @@ function hoistedTools(ctx) {
|
|
|
27443
28158
|
aft_move: createMoveTool(ctx)
|
|
27444
28159
|
};
|
|
27445
28160
|
}
|
|
28161
|
+
function formatError2(error49) {
|
|
28162
|
+
return error49 instanceof Error ? error49.message : String(error49);
|
|
28163
|
+
}
|
|
27446
28164
|
function aftPrefixedTools(ctx) {
|
|
27447
28165
|
const aftEditTool = createEditTool(ctx, "aft_write");
|
|
27448
28166
|
return {
|
|
@@ -27485,8 +28203,8 @@ function aftPrefixedTools(ctx) {
|
|
|
27485
28203
|
}
|
|
27486
28204
|
|
|
27487
28205
|
// src/tools/imports.ts
|
|
27488
|
-
import { tool as
|
|
27489
|
-
var
|
|
28206
|
+
import { tool as tool5 } from "@opencode-ai/plugin";
|
|
28207
|
+
var z5 = tool5.schema;
|
|
27490
28208
|
function importTools(ctx) {
|
|
27491
28209
|
return {
|
|
27492
28210
|
aft_import: {
|
|
@@ -27503,15 +28221,15 @@ function importTools(ctx) {
|
|
|
27503
28221
|
` + `- remove: { file, removed, module, name?, formatted, syntax_valid?, format_skipped_reason?, validation_errors?, validate_skipped_reason?, backup_id?, lsp_diagnostics? }
|
|
27504
28222
|
` + "- organize: { file, groups: [{ name, count }], removed_duplicates, formatted?, syntax_valid?, format_skipped_reason?, validation_errors?, validate_skipped_reason?, backup_id?, lsp_diagnostics? }",
|
|
27505
28223
|
args: {
|
|
27506
|
-
op:
|
|
27507
|
-
filePath:
|
|
27508
|
-
module:
|
|
27509
|
-
names:
|
|
27510
|
-
defaultImport:
|
|
27511
|
-
typeOnly:
|
|
27512
|
-
removeName:
|
|
27513
|
-
validate:
|
|
27514
|
-
dryRun:
|
|
28224
|
+
op: z5.enum(["add", "remove", "organize"]).describe("Import operation"),
|
|
28225
|
+
filePath: z5.string().describe("Path to the file (absolute or relative to project root)"),
|
|
28226
|
+
module: z5.string().optional().describe("Module path (required for add, remove \u2014 e.g. 'react', './utils', 'std::fmt')"),
|
|
28227
|
+
names: z5.array(z5.string()).optional().describe("Named imports to add (e.g. ['useState', 'useEffect'])"),
|
|
28228
|
+
defaultImport: z5.string().optional().describe("Default import name (e.g. 'React')"),
|
|
28229
|
+
typeOnly: z5.boolean().optional().describe("Type-only import (TS only, default: false)"),
|
|
28230
|
+
removeName: z5.string().optional().describe("Named import to remove for 'remove' op; omit to remove entire import"),
|
|
28231
|
+
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)"),
|
|
28232
|
+
dryRun: z5.boolean().optional().describe("Preview without modifying the file (default: false)")
|
|
27515
28233
|
},
|
|
27516
28234
|
execute: async (args, context) => {
|
|
27517
28235
|
const op = args.op;
|
|
@@ -27556,8 +28274,8 @@ function importTools(ctx) {
|
|
|
27556
28274
|
}
|
|
27557
28275
|
|
|
27558
28276
|
// src/tools/lsp.ts
|
|
27559
|
-
import { tool as
|
|
27560
|
-
var
|
|
28277
|
+
import { tool as tool6 } from "@opencode-ai/plugin";
|
|
28278
|
+
var z6 = tool6.schema;
|
|
27561
28279
|
function lspTools(ctx) {
|
|
27562
28280
|
const diagnosticsTool = {
|
|
27563
28281
|
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 +28297,10 @@ function lspTools(ctx) {
|
|
|
27579
28297
|
` + "- `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
28298
|
` + "**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
28299
|
args: {
|
|
27582
|
-
filePath:
|
|
27583
|
-
directory:
|
|
27584
|
-
severity:
|
|
27585
|
-
waitMs:
|
|
28300
|
+
filePath: z6.string().optional().describe("Path to a file to check. Mutually exclusive with 'directory'. Omit both to dump all cached diagnostics."),
|
|
28301
|
+
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."),
|
|
28302
|
+
severity: z6.enum(["error", "warning", "information", "hint", "all"]).optional().describe("Filter by severity (default: 'all')."),
|
|
28303
|
+
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
28304
|
},
|
|
27587
28305
|
execute: async (args, context) => {
|
|
27588
28306
|
const filePath = args.filePath || undefined;
|
|
@@ -27613,8 +28331,8 @@ function lspTools(ctx) {
|
|
|
27613
28331
|
}
|
|
27614
28332
|
|
|
27615
28333
|
// src/tools/navigation.ts
|
|
27616
|
-
import { tool as
|
|
27617
|
-
var
|
|
28334
|
+
import { tool as tool7 } from "@opencode-ai/plugin";
|
|
28335
|
+
var z7 = tool7.schema;
|
|
27618
28336
|
function navigationTools(ctx) {
|
|
27619
28337
|
return {
|
|
27620
28338
|
aft_navigate: {
|
|
@@ -27631,11 +28349,11 @@ function navigationTools(ctx) {
|
|
|
27631
28349
|
|
|
27632
28350
|
`,
|
|
27633
28351
|
args: {
|
|
27634
|
-
op:
|
|
27635
|
-
filePath:
|
|
27636
|
-
symbol:
|
|
27637
|
-
depth:
|
|
27638
|
-
expression:
|
|
28352
|
+
op: z7.enum(["call_tree", "callers", "trace_to", "impact", "trace_data"]).describe("Navigation operation"),
|
|
28353
|
+
filePath: z7.string().describe("Path to the source file containing the symbol (absolute or relative to project root)"),
|
|
28354
|
+
symbol: z7.string().describe("Name of the symbol to analyze"),
|
|
28355
|
+
depth: z7.number().optional().describe("Max traversal depth (default: call_tree=5, callers=1, trace_to=10, impact=5, trace_data=5)"),
|
|
28356
|
+
expression: z7.string().optional().describe("Expression to track through data flow (required for trace_data op)")
|
|
27639
28357
|
},
|
|
27640
28358
|
execute: async (args, context) => {
|
|
27641
28359
|
const params = {
|
|
@@ -27662,7 +28380,7 @@ function navigationTools(ctx) {
|
|
|
27662
28380
|
// src/tools/reading.ts
|
|
27663
28381
|
import { readdir } from "fs/promises";
|
|
27664
28382
|
import { extname as extname2, join as join18, resolve as resolve8 } from "path";
|
|
27665
|
-
import { tool as
|
|
28383
|
+
import { tool as tool8 } from "@opencode-ai/plugin";
|
|
27666
28384
|
var OUTLINE_EXTENSIONS = new Set([
|
|
27667
28385
|
".ts",
|
|
27668
28386
|
".tsx",
|
|
@@ -27699,7 +28417,7 @@ var OUTLINE_EXTENSIONS = new Set([
|
|
|
27699
28417
|
".sh",
|
|
27700
28418
|
".bash"
|
|
27701
28419
|
]);
|
|
27702
|
-
var
|
|
28420
|
+
var z8 = tool8.schema;
|
|
27703
28421
|
function readingTools(ctx) {
|
|
27704
28422
|
return {
|
|
27705
28423
|
aft_outline: {
|
|
@@ -27707,10 +28425,10 @@ function readingTools(ctx) {
|
|
|
27707
28425
|
|
|
27708
28426
|
` + "Provide exactly ONE of: 'filePath', 'files', 'directory', or 'url'.",
|
|
27709
28427
|
args: {
|
|
27710
|
-
filePath:
|
|
27711
|
-
files:
|
|
27712
|
-
directory:
|
|
27713
|
-
url:
|
|
28428
|
+
filePath: z8.string().optional().describe("Path to a single file to outline"),
|
|
28429
|
+
files: z8.array(z8.string()).optional().describe("Array of file paths to outline in one call"),
|
|
28430
|
+
directory: z8.string().optional().describe("Directory to outline recursively (200 file limit)"),
|
|
28431
|
+
url: z8.string().optional().describe("HTTP/HTTPS URL of an HTML or Markdown document to fetch and outline")
|
|
27714
28432
|
},
|
|
27715
28433
|
execute: async (args, context) => {
|
|
27716
28434
|
const filesArg = Array.isArray(args.files) ? args.files : undefined;
|
|
@@ -27780,11 +28498,11 @@ function readingTools(ctx) {
|
|
|
27780
28498
|
|
|
27781
28499
|
Provide exactly ONE of 'filePath' or 'url'. Pass either 'symbol' for a single lookup or 'symbols' for multiple in one call.`,
|
|
27782
28500
|
args: {
|
|
27783
|
-
filePath:
|
|
27784
|
-
url:
|
|
27785
|
-
symbol:
|
|
27786
|
-
symbols:
|
|
27787
|
-
contextLines:
|
|
28501
|
+
filePath: z8.string().optional().describe("Path to file (absolute or relative to project root)"),
|
|
28502
|
+
url: z8.string().optional().describe("HTTP/HTTPS URL of an HTML or Markdown document to fetch and zoom into"),
|
|
28503
|
+
symbol: z8.string().optional().describe("Symbol name for code, or heading text for Markdown/HTML"),
|
|
28504
|
+
symbols: z8.array(z8.string()).optional().describe("Array of symbol names or heading texts for a single batched call"),
|
|
28505
|
+
contextLines: z8.number().optional().describe("Lines of context before/after the symbol (default: 3)")
|
|
27788
28506
|
},
|
|
27789
28507
|
execute: async (args, context) => {
|
|
27790
28508
|
const hasFilePath = typeof args.filePath === "string" && args.filePath.length > 0;
|
|
@@ -27885,7 +28603,7 @@ ${lines}`;
|
|
|
27885
28603
|
}
|
|
27886
28604
|
|
|
27887
28605
|
// src/tools/refactoring.ts
|
|
27888
|
-
import { tool as
|
|
28606
|
+
import { tool as tool9 } from "@opencode-ai/plugin";
|
|
27889
28607
|
|
|
27890
28608
|
// src/lsp.ts
|
|
27891
28609
|
var LSP_SYMBOL_KIND_MAP = {
|
|
@@ -27944,7 +28662,7 @@ async function queryLspHints(client, symbolName, directory) {
|
|
|
27944
28662
|
}
|
|
27945
28663
|
|
|
27946
28664
|
// src/tools/refactoring.ts
|
|
27947
|
-
var
|
|
28665
|
+
var z9 = tool9.schema;
|
|
27948
28666
|
function refactoringTools(ctx) {
|
|
27949
28667
|
return {
|
|
27950
28668
|
aft_refactor: {
|
|
@@ -27962,16 +28680,16 @@ function refactoringTools(ctx) {
|
|
|
27962
28680
|
|
|
27963
28681
|
` + "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
28682
|
args: {
|
|
27965
|
-
op:
|
|
27966
|
-
filePath:
|
|
27967
|
-
symbol:
|
|
27968
|
-
destination:
|
|
27969
|
-
scope:
|
|
27970
|
-
name:
|
|
27971
|
-
startLine:
|
|
27972
|
-
endLine:
|
|
27973
|
-
callSiteLine:
|
|
27974
|
-
dryRun:
|
|
28683
|
+
op: z9.enum(["move", "extract", "inline"]).describe("Refactoring operation"),
|
|
28684
|
+
filePath: z9.string().describe("Path to the source file (absolute or relative to project root)"),
|
|
28685
|
+
symbol: z9.string().optional().describe("Symbol name \u2014 required for 'move' and 'inline' ops"),
|
|
28686
|
+
destination: z9.string().optional().describe("Target file path \u2014 required for 'move' op"),
|
|
28687
|
+
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."),
|
|
28688
|
+
name: z9.string().optional().describe("New function name \u2014 required for 'extract' op"),
|
|
28689
|
+
startLine: z9.number().optional().describe("1-based start line \u2014 required for 'extract' op"),
|
|
28690
|
+
endLine: z9.number().optional().describe("1-based end line (inclusive) \u2014 required for 'extract' op"),
|
|
28691
|
+
callSiteLine: z9.number().optional().describe("1-based call site line \u2014 required for 'inline' op"),
|
|
28692
|
+
dryRun: z9.boolean().optional().describe("Preview changes as diff without modifying files (default: false)")
|
|
27975
28693
|
},
|
|
27976
28694
|
execute: async (args, context) => {
|
|
27977
28695
|
const op = args.op;
|
|
@@ -28041,8 +28759,8 @@ function refactoringTools(ctx) {
|
|
|
28041
28759
|
}
|
|
28042
28760
|
|
|
28043
28761
|
// src/tools/safety.ts
|
|
28044
|
-
import { tool as
|
|
28045
|
-
var
|
|
28762
|
+
import { tool as tool10 } from "@opencode-ai/plugin";
|
|
28763
|
+
var z10 = tool10.schema;
|
|
28046
28764
|
function safetyTools(ctx) {
|
|
28047
28765
|
return {
|
|
28048
28766
|
aft_safety: {
|
|
@@ -28063,10 +28781,10 @@ function safetyTools(ctx) {
|
|
|
28063
28781
|
|
|
28064
28782
|
` + "Returns: undo { path, backup_id }. history { file, entries }. checkpoint { ok, name }. restore { ok, name }. list { checkpoints }.",
|
|
28065
28783
|
args: {
|
|
28066
|
-
op:
|
|
28067
|
-
filePath:
|
|
28068
|
-
name:
|
|
28069
|
-
files:
|
|
28784
|
+
op: z10.enum(["undo", "history", "checkpoint", "restore", "list"]).describe("Safety operation"),
|
|
28785
|
+
filePath: z10.string().optional().describe("File path (required for undo, history). Absolute or relative to project root"),
|
|
28786
|
+
name: z10.string().optional().describe("Checkpoint name (required for checkpoint, restore)"),
|
|
28787
|
+
files: z10.array(z10.string()).optional().describe("Specific files to include in checkpoint (optional, defaults to all tracked files)")
|
|
28070
28788
|
},
|
|
28071
28789
|
execute: async (args, context) => {
|
|
28072
28790
|
const op = args.op;
|
|
@@ -28268,8 +28986,8 @@ function semanticTools(ctx) {
|
|
|
28268
28986
|
}
|
|
28269
28987
|
|
|
28270
28988
|
// src/tools/structure.ts
|
|
28271
|
-
import { tool as
|
|
28272
|
-
var
|
|
28989
|
+
import { tool as tool11 } from "@opencode-ai/plugin";
|
|
28990
|
+
var z11 = tool11.schema;
|
|
28273
28991
|
function structureTools(ctx) {
|
|
28274
28992
|
return {
|
|
28275
28993
|
aft_transform: {
|
|
@@ -28294,20 +29012,20 @@ function structureTools(ctx) {
|
|
|
28294
29012
|
` + `- add_decorator: { file, target, decorator, formatted, syntax_valid?, format_skipped_reason?, validation_errors?, validate_skipped_reason?, backup_id?, lsp_diagnostics? }
|
|
28295
29013
|
` + "- add_struct_tags: { file, target, field, tag_string, formatted, syntax_valid?, format_skipped_reason?, validation_errors?, validate_skipped_reason?, backup_id?, lsp_diagnostics? }",
|
|
28296
29014
|
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:
|
|
29015
|
+
op: z11.enum(["add_member", "add_derive", "wrap_try_catch", "add_decorator", "add_struct_tags"]).describe("Transformation operation"),
|
|
29016
|
+
filePath: z11.string().describe("Path to the source file (absolute or relative to project root)"),
|
|
29017
|
+
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."),
|
|
29018
|
+
code: z11.string().optional().describe("Member code to insert (add_member)"),
|
|
29019
|
+
position: z11.string().optional().describe("For add_member: 'first', 'last' (default), 'before:name', 'after:name'. For add_decorator: 'first' (default) or 'last' only."),
|
|
29020
|
+
target: z11.string().optional().describe("Target symbol name (add_derive: struct/enum, wrap_try_catch: function, add_decorator: function/class, add_struct_tags: struct)"),
|
|
29021
|
+
derives: z11.array(z11.string()).optional().describe("Derive macro names (add_derive \u2014 e.g. ['Clone', 'Debug'])"),
|
|
29022
|
+
catchBody: z11.string().optional().describe("Catch block body (wrap_try_catch \u2014 default: 'throw error;')"),
|
|
29023
|
+
decorator: z11.string().optional().describe("Decorator text without @ (add_decorator \u2014 e.g. 'staticmethod')"),
|
|
29024
|
+
field: z11.string().optional().describe("Struct field name (add_struct_tags)"),
|
|
29025
|
+
tag: z11.string().optional().describe("Tag key (add_struct_tags \u2014 e.g. 'json')"),
|
|
29026
|
+
value: z11.string().optional().describe("Tag value (add_struct_tags \u2014 e.g. 'user_name,omitempty')"),
|
|
29027
|
+
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)"),
|
|
29028
|
+
dryRun: z11.boolean().optional().describe("Preview without modifying the file (default: false)")
|
|
28311
29029
|
},
|
|
28312
29030
|
execute: async (args, context) => {
|
|
28313
29031
|
const op = args.op;
|
|
@@ -28428,8 +29146,16 @@ var PLUGIN_VERSION = (() => {
|
|
|
28428
29146
|
return "0.0.0";
|
|
28429
29147
|
}
|
|
28430
29148
|
})();
|
|
28431
|
-
var ANNOUNCEMENT_VERSION = "";
|
|
28432
|
-
var ANNOUNCEMENT_FEATURES = [
|
|
29149
|
+
var ANNOUNCEMENT_VERSION = "0.18.0";
|
|
29150
|
+
var ANNOUNCEMENT_FEATURES = [
|
|
29151
|
+
`New experimental features \u2014 AFT now optionally hoists bash:
|
|
29152
|
+
- Run bash scripts in the background.
|
|
29153
|
+
- Initial output compression for git, cargo, npm, bun, pnpm, pytest, tsc (more in 0.19).
|
|
29154
|
+
- Rewrite cat/grep/find/sed/ls into AFT counterparts for faster, formatted output.
|
|
29155
|
+
Check GitHub for how to enable.`,
|
|
29156
|
+
"Trigram grep/glob and semantic search (aft_search) graduated out of experimental.",
|
|
29157
|
+
"Lots of bugfixes and new end-to-end test coverage."
|
|
29158
|
+
];
|
|
28433
29159
|
var plugin = async (input) => {
|
|
28434
29160
|
const binaryPath = await findBinary();
|
|
28435
29161
|
const aftConfig = loadAftConfig(input.directory);
|
|
@@ -28444,10 +29170,12 @@ var plugin = async (input) => {
|
|
|
28444
29170
|
if (aftConfig.checker !== undefined)
|
|
28445
29171
|
configOverrides.checker = aftConfig.checker;
|
|
28446
29172
|
configOverrides.restrict_to_project_root = aftConfig.restrict_to_project_root ?? true;
|
|
28447
|
-
|
|
28448
|
-
|
|
28449
|
-
|
|
28450
|
-
|
|
29173
|
+
configOverrides.bash_permissions = true;
|
|
29174
|
+
if (aftConfig.search_index !== undefined)
|
|
29175
|
+
configOverrides.search_index = aftConfig.search_index;
|
|
29176
|
+
if (aftConfig.semantic_search !== undefined)
|
|
29177
|
+
configOverrides.semantic_search = aftConfig.semantic_search;
|
|
29178
|
+
Object.assign(configOverrides, resolveExperimentalConfigForConfigure(aftConfig));
|
|
28451
29179
|
Object.assign(configOverrides, resolveLspConfigForConfigure(aftConfig));
|
|
28452
29180
|
if (aftConfig.semantic !== undefined)
|
|
28453
29181
|
configOverrides.semantic = aftConfig.semantic;
|
|
@@ -28456,7 +29184,7 @@ var plugin = async (input) => {
|
|
|
28456
29184
|
const isFastembedSemanticBackend = (aftConfig.semantic?.backend ?? "fastembed") === "fastembed";
|
|
28457
29185
|
const dataHome = process.env.XDG_DATA_HOME || join19(homedir10(), ".local", "share");
|
|
28458
29186
|
configOverrides.storage_dir = join19(dataHome, "opencode", "storage", "plugin", "aft");
|
|
28459
|
-
if (aftConfig.
|
|
29187
|
+
if (aftConfig.semantic_search && isFastembedSemanticBackend) {
|
|
28460
29188
|
const storageDir2 = configOverrides.storage_dir;
|
|
28461
29189
|
const ortDylibDir = await ensureOnnxRuntime(storageDir2).catch((err) => {
|
|
28462
29190
|
warn(`ONNX Runtime setup failed: ${err instanceof Error ? err.message : String(err)}. Semantic search will be unavailable.`);
|
|
@@ -28540,12 +29268,12 @@ ${lines}
|
|
|
28540
29268
|
log(`Found/downloaded compatible binary at ${path5}. Replacing running bridges...`);
|
|
28541
29269
|
pool.replaceBinary(path5).then(() => {
|
|
28542
29270
|
log("Binary replaced successfully. New bridges will use the updated binary.");
|
|
28543
|
-
}, (err) =>
|
|
29271
|
+
}, (err) => error("Failed to replace binary:", err));
|
|
28544
29272
|
} else {
|
|
28545
29273
|
warn(`Could not find or download v${minVersion}. Continuing with v${binaryVersion}.`);
|
|
28546
29274
|
}
|
|
28547
29275
|
}, (err) => {
|
|
28548
|
-
|
|
29276
|
+
error(`Auto-download failed: ${err.message}. Install manually: cargo install agent-file-tools@${minVersion}`);
|
|
28549
29277
|
});
|
|
28550
29278
|
},
|
|
28551
29279
|
onConfigureWarnings: async ({ projectRoot, sessionId, client, warnings }) => {
|
|
@@ -28566,6 +29294,7 @@ ${lines}
|
|
|
28566
29294
|
const ctx = {
|
|
28567
29295
|
pool,
|
|
28568
29296
|
client: input.client,
|
|
29297
|
+
plugin: input.plugin,
|
|
28569
29298
|
config: aftConfig,
|
|
28570
29299
|
storageDir: configOverrides.storage_dir
|
|
28571
29300
|
};
|
|
@@ -28604,14 +29333,14 @@ ${lines}
|
|
|
28604
29333
|
if (storageDir && ANNOUNCEMENT_VERSION) {
|
|
28605
29334
|
try {
|
|
28606
29335
|
mkdirSync10(storageDir, { recursive: true });
|
|
28607
|
-
|
|
29336
|
+
writeFileSync10(join19(storageDir, "last_announced_version"), ANNOUNCEMENT_VERSION);
|
|
28608
29337
|
} catch {}
|
|
28609
29338
|
}
|
|
28610
29339
|
return { success: true };
|
|
28611
29340
|
});
|
|
28612
29341
|
rpcServer.handle("get-warnings", async () => {
|
|
28613
29342
|
const warnings = [];
|
|
28614
|
-
if (aftConfig.
|
|
29343
|
+
if (aftConfig.semantic_search && isFastembedSemanticBackend && !configOverrides._ort_dylib_dir) {
|
|
28615
29344
|
if (!isOrtAutoDownloadSupported()) {
|
|
28616
29345
|
warnings.push(`Semantic search requires ONNX Runtime.
|
|
28617
29346
|
Install: ${getManualInstallHint()}`);
|
|
@@ -28635,7 +29364,7 @@ Install: ${getManualInstallHint()}`);
|
|
|
28635
29364
|
sendFeatureAnnouncement(notifyOpts, ANNOUNCEMENT_VERSION, ANNOUNCEMENT_FEATURES, storageDir).catch(() => {});
|
|
28636
29365
|
}, 8000);
|
|
28637
29366
|
}
|
|
28638
|
-
if (aftConfig.
|
|
29367
|
+
if (aftConfig.semantic_search && isFastembedSemanticBackend && !configOverrides._ort_dylib_dir) {
|
|
28639
29368
|
setTimeout(() => {
|
|
28640
29369
|
if (!configOverrides._ort_dylib_dir && !isOrtAutoDownloadSupported()) {
|
|
28641
29370
|
sendWarning(notifyOpts, `Semantic search requires ONNX Runtime.
|
|
@@ -28661,8 +29390,8 @@ Install: ${getManualInstallHint()}`).catch(() => {});
|
|
|
28661
29390
|
...structureTools(ctx),
|
|
28662
29391
|
...navigationTools(ctx),
|
|
28663
29392
|
...surface !== "minimal" && astTools(ctx),
|
|
28664
|
-
...surface !== "minimal" && aftConfig.
|
|
28665
|
-
...surface !== "minimal" && aftConfig.
|
|
29393
|
+
...surface !== "minimal" && aftConfig.semantic_search === true && semanticTools(ctx),
|
|
29394
|
+
...surface !== "minimal" && aftConfig.search_index === true && searchTools(ctx),
|
|
28666
29395
|
...refactoringTools(ctx),
|
|
28667
29396
|
...surface !== "minimal" && lspTools(ctx),
|
|
28668
29397
|
...surface !== "minimal" && conflictTools(ctx)
|
|
@@ -28685,13 +29414,30 @@ Install: ${getManualInstallHint()}`).catch(() => {});
|
|
|
28685
29414
|
}
|
|
28686
29415
|
log(`Disabled ${disabled.size} tool(s): ${[...disabled].join(", ")}`);
|
|
28687
29416
|
}
|
|
29417
|
+
const autoUpdateEventHook = createAutoUpdateCheckerHook(input, {
|
|
29418
|
+
enabled: true,
|
|
29419
|
+
autoUpdate: aftConfig.auto_update ?? true,
|
|
29420
|
+
signal: autoUpdateAbort.signal
|
|
29421
|
+
});
|
|
28688
29422
|
return {
|
|
28689
29423
|
tool: allTools,
|
|
28690
|
-
event:
|
|
28691
|
-
|
|
28692
|
-
|
|
28693
|
-
|
|
28694
|
-
|
|
29424
|
+
event: async (eventInput) => {
|
|
29425
|
+
await autoUpdateEventHook(eventInput);
|
|
29426
|
+
if (eventInput.event.type !== "session.idle")
|
|
29427
|
+
return;
|
|
29428
|
+
const sessionID = extractSessionID(eventInput.event.properties);
|
|
29429
|
+
if (!sessionID)
|
|
29430
|
+
return;
|
|
29431
|
+
await handleIdleBgCompletions({
|
|
29432
|
+
ctx,
|
|
29433
|
+
directory: input.directory,
|
|
29434
|
+
sessionID,
|
|
29435
|
+
client: input.client
|
|
29436
|
+
});
|
|
29437
|
+
},
|
|
29438
|
+
"chat.message": async (messageInput) => {
|
|
29439
|
+
resetBgWake(messageInput.sessionID ?? messageInput.sessionId ?? messageInput.id);
|
|
29440
|
+
},
|
|
28695
29441
|
"command.execute.before": async (commandInput, _output) => {
|
|
28696
29442
|
if (isTuiMode2() || commandInput.command !== STATUS_COMMAND) {
|
|
28697
29443
|
return;
|
|
@@ -28705,22 +29451,22 @@ Install: ${getManualInstallHint()}`).catch(() => {});
|
|
|
28705
29451
|
await sendIgnoredMessage2(input.client, commandInput.sessionID, formatStatusMarkdown(status));
|
|
28706
29452
|
throwSentinel(commandInput.command);
|
|
28707
29453
|
},
|
|
28708
|
-
"tool.execute.after": async (
|
|
29454
|
+
"tool.execute.after": async (toolInput, output) => {
|
|
28709
29455
|
if (!output)
|
|
28710
29456
|
return;
|
|
28711
|
-
const stored = consumeToolMetadata(
|
|
29457
|
+
const stored = consumeToolMetadata(toolInput.sessionID, toolInput.callID);
|
|
28712
29458
|
if (stored) {
|
|
28713
29459
|
if (stored.title)
|
|
28714
29460
|
output.title = stored.title;
|
|
28715
29461
|
if (stored.metadata)
|
|
28716
29462
|
output.metadata = { ...output.metadata, ...stored.metadata };
|
|
28717
29463
|
}
|
|
28718
|
-
if (
|
|
29464
|
+
if (toolInput.tool === "bash" && output.output?.includes("Automatic merge failed; fix conflicts")) {
|
|
28719
29465
|
output.output += `
|
|
28720
29466
|
|
|
28721
29467
|
[Hint] Use aft_conflicts to see all conflict regions across files in a single call.`;
|
|
28722
29468
|
}
|
|
28723
|
-
if (
|
|
29469
|
+
if (toolInput.tool === "bash" && output.output) {
|
|
28724
29470
|
const firstLine = output.output.slice(0, 300).split(`
|
|
28725
29471
|
`)[0] ?? "";
|
|
28726
29472
|
if (/\b(rg|grep)\s/.test(firstLine)) {
|
|
@@ -28729,6 +29475,7 @@ Install: ${getManualInstallHint()}`).catch(() => {});
|
|
|
28729
29475
|
[Hint] Use the grep tool instead of bash for faster indexed search.`;
|
|
28730
29476
|
}
|
|
28731
29477
|
}
|
|
29478
|
+
await appendInTurnBgCompletions({ ctx, directory: input.directory, sessionID: toolInput.sessionID }, output);
|
|
28732
29479
|
},
|
|
28733
29480
|
config: async (config2) => {
|
|
28734
29481
|
config2.command = {
|