@cortexkit/aft-opencode 0.27.0 → 0.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bg-notifications.d.ts.map +1 -1
- package/dist/config.d.ts +67 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +371 -95
- package/dist/lsp-auto-install.d.ts +1 -1
- package/dist/lsp-auto-install.d.ts.map +1 -1
- package/dist/lsp-npm-table.d.ts +14 -0
- package/dist/lsp-npm-table.d.ts.map +1 -1
- package/dist/lsp-project-relevance.d.ts +13 -0
- package/dist/lsp-project-relevance.d.ts.map +1 -1
- package/dist/notifications.d.ts +1 -1
- package/dist/notifications.d.ts.map +1 -1
- package/dist/tools/hoisted.d.ts.map +1 -1
- package/dist/tui.js +103 -90
- package/dist/workflow-hints.d.ts +5 -1
- package/dist/workflow-hints.d.ts.map +1 -1
- package/package.json +9 -7
- package/src/tui/index.tsx +21 -6
- package/src/tui/sidebar.tsx +92 -66
package/dist/index.js
CHANGED
|
@@ -7803,7 +7803,7 @@ var require_src2 = __commonJS((exports, module) => {
|
|
|
7803
7803
|
});
|
|
7804
7804
|
|
|
7805
7805
|
// src/index.ts
|
|
7806
|
-
import { existsSync as existsSync15, mkdirSync as mkdirSync13, readFileSync as
|
|
7806
|
+
import { existsSync as existsSync15, mkdirSync as mkdirSync13, readFileSync as readFileSync13, writeFileSync as writeFileSync12 } from "fs";
|
|
7807
7807
|
import { createRequire as createRequire2 } from "module";
|
|
7808
7808
|
import { join as join22 } from "path";
|
|
7809
7809
|
|
|
@@ -8597,13 +8597,14 @@ import { pipeline } from "stream/promises";
|
|
|
8597
8597
|
var PLATFORM_ARCH_MAP = {
|
|
8598
8598
|
darwin: { arm64: "darwin-arm64", x64: "darwin-x64" },
|
|
8599
8599
|
linux: { arm64: "linux-arm64", x64: "linux-x64" },
|
|
8600
|
-
win32: { arm64: "win32-
|
|
8600
|
+
win32: { arm64: "win32-arm64", x64: "win32-x64" }
|
|
8601
8601
|
};
|
|
8602
8602
|
var PLATFORM_ASSET_MAP = {
|
|
8603
8603
|
"darwin-arm64": "aft-darwin-arm64",
|
|
8604
8604
|
"darwin-x64": "aft-darwin-x64",
|
|
8605
8605
|
"linux-arm64": "aft-linux-arm64",
|
|
8606
8606
|
"linux-x64": "aft-linux-x64",
|
|
8607
|
+
"win32-arm64": "aft-win32-arm64.exe",
|
|
8607
8608
|
"win32-x64": "aft-win32-x64.exe"
|
|
8608
8609
|
};
|
|
8609
8610
|
|
|
@@ -9664,6 +9665,7 @@ class BridgePool {
|
|
|
9664
9665
|
idleTimeoutMs;
|
|
9665
9666
|
bridgeOptions;
|
|
9666
9667
|
configOverrides;
|
|
9668
|
+
projectConfigLoader;
|
|
9667
9669
|
logger;
|
|
9668
9670
|
cleanupTimer = null;
|
|
9669
9671
|
constructor(binaryPath, options = {}, configOverrides = {}) {
|
|
@@ -9671,6 +9673,7 @@ class BridgePool {
|
|
|
9671
9673
|
this.maxPoolSize = options.maxPoolSize ?? DEFAULT_MAX_POOL_SIZE;
|
|
9672
9674
|
this.idleTimeoutMs = options.idleTimeoutMs ?? DEFAULT_IDLE_TIMEOUT_MS;
|
|
9673
9675
|
this.logger = options.logger;
|
|
9676
|
+
this.projectConfigLoader = options.projectConfigLoader;
|
|
9674
9677
|
this.bridgeOptions = {
|
|
9675
9678
|
timeoutMs: options.timeoutMs,
|
|
9676
9679
|
maxRestarts: options.maxRestarts,
|
|
@@ -9706,7 +9709,17 @@ class BridgePool {
|
|
|
9706
9709
|
if (this.bridges.size >= this.maxPoolSize) {
|
|
9707
9710
|
this.evictLRU();
|
|
9708
9711
|
}
|
|
9709
|
-
|
|
9712
|
+
let projectOverrides = {};
|
|
9713
|
+
if (this.projectConfigLoader) {
|
|
9714
|
+
try {
|
|
9715
|
+
projectOverrides = this.projectConfigLoader(key) ?? {};
|
|
9716
|
+
} catch (err) {
|
|
9717
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
9718
|
+
this.error(`projectConfigLoader failed; using global overrides only: ${message}`);
|
|
9719
|
+
}
|
|
9720
|
+
}
|
|
9721
|
+
const mergedOverrides = { ...this.configOverrides, ...projectOverrides };
|
|
9722
|
+
const bridge = new BinaryBridge(this.binaryPath, key, this.bridgeOptions, mergedOverrides);
|
|
9710
9723
|
this.bridges.set(key, { bridge, lastUsed: Date.now() });
|
|
9711
9724
|
return bridge;
|
|
9712
9725
|
}
|
|
@@ -10172,6 +10185,9 @@ function formatZoomText(targetLabel, response) {
|
|
|
10172
10185
|
return out.join(`
|
|
10173
10186
|
`);
|
|
10174
10187
|
}
|
|
10188
|
+
// src/bg-notifications.ts
|
|
10189
|
+
import { createHash as createHash4, randomUUID } from "crypto";
|
|
10190
|
+
|
|
10175
10191
|
// src/logger.ts
|
|
10176
10192
|
import * as fs from "fs";
|
|
10177
10193
|
import * as os from "os";
|
|
@@ -10348,6 +10364,9 @@ async function resolvePromptContext(client, sessionId) {
|
|
|
10348
10364
|
}
|
|
10349
10365
|
|
|
10350
10366
|
// src/bg-notifications.ts
|
|
10367
|
+
function hashReminder(text) {
|
|
10368
|
+
return createHash4("sha256").update(text).digest("hex").slice(0, 16);
|
|
10369
|
+
}
|
|
10351
10370
|
var sessionBgStates = new Map;
|
|
10352
10371
|
var SESSION_BG_STATE_IDLE_TTL_MS = 60 * 60 * 1000;
|
|
10353
10372
|
var DEBOUNCE_STEP_MS = 200;
|
|
@@ -10418,6 +10437,13 @@ async function appendInTurnBgCompletions(drainContext, output) {
|
|
|
10418
10437
|
const deliveredCompletions = [...state.pendingCompletions];
|
|
10419
10438
|
const reminder = formatCombinedSystemReminder(state.pendingCompletions, state.pendingLongRunning);
|
|
10420
10439
|
output.output = appendReminder(output.output ?? "", reminder);
|
|
10440
|
+
sessionLog(drainContext.sessionID, `${LOG_PREFIX} in-turn append`, {
|
|
10441
|
+
event: "bash_completion_in_turn_append",
|
|
10442
|
+
task_ids: deliveredCompletions.map((c) => c.task_id),
|
|
10443
|
+
long_running_task_ids: state.pendingLongRunning.map((r) => r.task_id),
|
|
10444
|
+
reminder_sha256: hashReminder(reminder),
|
|
10445
|
+
reminder_chars: reminder.length
|
|
10446
|
+
});
|
|
10421
10447
|
state.pendingCompletions = [];
|
|
10422
10448
|
state.pendingLongRunning = [];
|
|
10423
10449
|
state.wakeRetryAttempts = 0;
|
|
@@ -10461,14 +10487,53 @@ async function triggerWakeIfPending(drainContext, skipDrain) {
|
|
|
10461
10487
|
}
|
|
10462
10488
|
if (promptContext?.variant)
|
|
10463
10489
|
body.variant = promptContext.variant;
|
|
10464
|
-
|
|
10465
|
-
|
|
10466
|
-
|
|
10490
|
+
const deliveryID = `aftdel_${randomUUID()}`;
|
|
10491
|
+
const taskIDs = deliveredCompletions.map((c) => c.task_id);
|
|
10492
|
+
const wakeMeta = {
|
|
10493
|
+
delivery_id: deliveryID,
|
|
10494
|
+
attempt: state.wakeRetryAttempts + 1,
|
|
10495
|
+
task_ids: taskIDs,
|
|
10496
|
+
directory: drainContext.directory,
|
|
10497
|
+
reminder_sha256: hashReminder(reminder),
|
|
10498
|
+
reminder_chars: reminder.length,
|
|
10499
|
+
prompt_context: promptContext ? {
|
|
10500
|
+
agent: promptContext.agent,
|
|
10501
|
+
model: promptContext.model ? {
|
|
10502
|
+
providerID: promptContext.model.providerID,
|
|
10503
|
+
modelID: promptContext.model.modelID
|
|
10504
|
+
} : null,
|
|
10505
|
+
variant: promptContext.variant ?? null
|
|
10506
|
+
} : null
|
|
10507
|
+
};
|
|
10508
|
+
sessionLog(drainContext.sessionID, `${LOG_PREFIX} wake promptAsync start`, {
|
|
10509
|
+
event: "bash_completion_wake_prompt_async_start",
|
|
10510
|
+
...wakeMeta
|
|
10467
10511
|
});
|
|
10468
|
-
|
|
10512
|
+
try {
|
|
10513
|
+
await client.session.promptAsync({
|
|
10514
|
+
path: { id: drainContext.sessionID },
|
|
10515
|
+
body
|
|
10516
|
+
});
|
|
10517
|
+
} catch (err) {
|
|
10518
|
+
sessionWarn(drainContext.sessionID, `${LOG_PREFIX} wake promptAsync error`, {
|
|
10519
|
+
event: "bash_completion_wake_prompt_async_error",
|
|
10520
|
+
delivery_id: deliveryID,
|
|
10521
|
+
attempt: state.wakeRetryAttempts + 1,
|
|
10522
|
+
task_ids: taskIDs,
|
|
10523
|
+
error: err instanceof Error ? err.message : String(err)
|
|
10524
|
+
});
|
|
10525
|
+
throw err;
|
|
10526
|
+
}
|
|
10527
|
+
sessionLog(drainContext.sessionID, `${LOG_PREFIX} wake promptAsync ok`, {
|
|
10528
|
+
event: "bash_completion_wake_prompt_async_ok",
|
|
10529
|
+
delivery_id: deliveryID,
|
|
10530
|
+
attempt: state.wakeRetryAttempts + 1,
|
|
10531
|
+
task_ids: taskIDs
|
|
10532
|
+
});
|
|
10533
|
+
await ackCompletions(drainContext, deliveredCompletions, deliveryID);
|
|
10469
10534
|
}, (err, hardStopped) => {
|
|
10470
10535
|
sessionWarn(drainContext.sessionID, hardStopped ? `${LOG_PREFIX} wake send failed ${MAX_WAKE_SEND_ATTEMPTS} times; stopping retries: ${err instanceof Error ? err.message : String(err)}` : `${LOG_PREFIX} wake send failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
10471
|
-
});
|
|
10536
|
+
}, drainContext.sessionID);
|
|
10472
10537
|
}
|
|
10473
10538
|
function formatSystemReminder(completions) {
|
|
10474
10539
|
const bullets = completions.map((completion) => formatCompletion(completion)).join(`
|
|
@@ -10532,7 +10597,7 @@ async function drainCompletions({ ctx, directory, sessionID }) {
|
|
|
10532
10597
|
sessionWarn(sessionID, `${LOG_PREFIX} drain failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
10533
10598
|
}
|
|
10534
10599
|
}
|
|
10535
|
-
async function ackCompletions({ ctx, directory, sessionID }, completions) {
|
|
10600
|
+
async function ackCompletions({ ctx, directory, sessionID }, completions, deliveryID) {
|
|
10536
10601
|
const taskIds = [...new Set(completions.map((completion) => completion.task_id))];
|
|
10537
10602
|
if (taskIds.length === 0)
|
|
10538
10603
|
return;
|
|
@@ -10544,12 +10609,18 @@ async function ackCompletions({ ctx, directory, sessionID }, completions) {
|
|
|
10544
10609
|
});
|
|
10545
10610
|
if (response.success === false) {
|
|
10546
10611
|
sessionWarn(sessionID, `${LOG_PREFIX} ack failed: ${String(response.message ?? "unknown error")}`);
|
|
10612
|
+
return;
|
|
10547
10613
|
}
|
|
10614
|
+
sessionLog(sessionID, `${LOG_PREFIX} ack ok`, {
|
|
10615
|
+
event: "bash_completion_ack_ok",
|
|
10616
|
+
delivery_id: deliveryID ?? null,
|
|
10617
|
+
task_ids: taskIds
|
|
10618
|
+
});
|
|
10548
10619
|
} catch (err) {
|
|
10549
10620
|
sessionWarn(sessionID, `${LOG_PREFIX} ack failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
10550
10621
|
}
|
|
10551
10622
|
}
|
|
10552
|
-
function scheduleWake(state, sendWake, onSendFailure) {
|
|
10623
|
+
function scheduleWake(state, sendWake, onSendFailure, sessionID) {
|
|
10553
10624
|
if (state.wakeHardStopped)
|
|
10554
10625
|
return;
|
|
10555
10626
|
const now = Date.now();
|
|
@@ -10568,6 +10639,13 @@ function scheduleWake(state, sendWake, onSendFailure) {
|
|
|
10568
10639
|
if (state.debounceTimer)
|
|
10569
10640
|
clearTimeout(state.debounceTimer);
|
|
10570
10641
|
const delay = state.retryDelayMs ?? Math.max(0, (state.scheduledFireAt ?? now) - now);
|
|
10642
|
+
sessionLog(sessionID, `${LOG_PREFIX} wake scheduled`, {
|
|
10643
|
+
event: "bash_completion_wake_scheduled",
|
|
10644
|
+
delay_ms: delay,
|
|
10645
|
+
pending_completions: state.pendingCompletions.length,
|
|
10646
|
+
pending_long_running: state.pendingLongRunning.length,
|
|
10647
|
+
retry_attempt: state.wakeRetryAttempts
|
|
10648
|
+
});
|
|
10571
10649
|
state.debounceTimer = setTimeout(() => {
|
|
10572
10650
|
const pending = state.pendingCompletions;
|
|
10573
10651
|
const pendingLongRunning = state.pendingLongRunning;
|
|
@@ -10578,6 +10656,14 @@ function scheduleWake(state, sendWake, onSendFailure) {
|
|
|
10578
10656
|
if (pending.length === 0 && pendingLongRunning.length === 0)
|
|
10579
10657
|
return;
|
|
10580
10658
|
const reminder = formatCombinedSystemReminder(pending, pendingLongRunning);
|
|
10659
|
+
sessionLog(sessionID, `${LOG_PREFIX} wake fire`, {
|
|
10660
|
+
event: "bash_completion_wake_fire",
|
|
10661
|
+
task_ids: pending.map((c) => c.task_id),
|
|
10662
|
+
long_running_task_ids: pendingLongRunning.map((r) => r.task_id),
|
|
10663
|
+
reminder_sha256: hashReminder(reminder),
|
|
10664
|
+
reminder_chars: reminder.length,
|
|
10665
|
+
retry_attempt: state.wakeRetryAttempts
|
|
10666
|
+
});
|
|
10581
10667
|
state.pendingCompletions = [];
|
|
10582
10668
|
state.pendingLongRunning = [];
|
|
10583
10669
|
sendWake(reminder, pending).then(() => {
|
|
@@ -10596,7 +10682,7 @@ function scheduleWake(state, sendWake, onSendFailure) {
|
|
|
10596
10682
|
}
|
|
10597
10683
|
state.retryDelayMs = Math.min((delay || DEBOUNCE_STEP_MS) * 2, DEBOUNCE_CAP_MS);
|
|
10598
10684
|
onSendFailure(err, false);
|
|
10599
|
-
scheduleWake(state, sendWake, onSendFailure);
|
|
10685
|
+
scheduleWake(state, sendWake, onSendFailure, sessionID);
|
|
10600
10686
|
});
|
|
10601
10687
|
}, delay);
|
|
10602
10688
|
state.debounceTimer.unref?.();
|
|
@@ -24334,7 +24420,16 @@ var ExperimentalConfigSchema = exports_external.object({
|
|
|
24334
24420
|
}).optional(),
|
|
24335
24421
|
lsp_ty: exports_external.boolean().optional()
|
|
24336
24422
|
});
|
|
24423
|
+
var BashFeaturesSchema = exports_external.object({
|
|
24424
|
+
rewrite: exports_external.boolean().optional(),
|
|
24425
|
+
compress: exports_external.boolean().optional(),
|
|
24426
|
+
background: exports_external.boolean().optional(),
|
|
24427
|
+
long_running_reminder_enabled: exports_external.boolean().optional(),
|
|
24428
|
+
long_running_reminder_interval_ms: exports_external.number().int().positive().optional()
|
|
24429
|
+
});
|
|
24430
|
+
var BashConfigSchema = exports_external.union([exports_external.boolean(), BashFeaturesSchema]);
|
|
24337
24431
|
var AftConfigSchema = exports_external.object({
|
|
24432
|
+
$schema: exports_external.string().optional(),
|
|
24338
24433
|
format_on_edit: exports_external.boolean().optional(),
|
|
24339
24434
|
formatter_timeout_secs: exports_external.number().int().min(1).max(600).optional(),
|
|
24340
24435
|
validate_on_edit: exports_external.enum(["syntax", "full"]).optional(),
|
|
@@ -24346,6 +24441,7 @@ var AftConfigSchema = exports_external.object({
|
|
|
24346
24441
|
restrict_to_project_root: exports_external.boolean().optional(),
|
|
24347
24442
|
search_index: exports_external.boolean().optional(),
|
|
24348
24443
|
semantic_search: exports_external.boolean().optional(),
|
|
24444
|
+
bash: BashConfigSchema.optional(),
|
|
24349
24445
|
experimental: ExperimentalConfigSchema.optional(),
|
|
24350
24446
|
lsp: LspConfigSchema.optional(),
|
|
24351
24447
|
url_fetch_allow_private: exports_external.boolean().optional(),
|
|
@@ -24400,22 +24496,93 @@ function resolveLspConfigForConfigure(config2) {
|
|
|
24400
24496
|
}
|
|
24401
24497
|
return overrides;
|
|
24402
24498
|
}
|
|
24403
|
-
function
|
|
24499
|
+
function resolveProjectOverridesForConfigure(config2) {
|
|
24404
24500
|
const overrides = {};
|
|
24405
|
-
if (config2.
|
|
24406
|
-
overrides.
|
|
24407
|
-
|
|
24408
|
-
|
|
24409
|
-
|
|
24501
|
+
if (config2.format_on_edit !== undefined)
|
|
24502
|
+
overrides.format_on_edit = config2.format_on_edit;
|
|
24503
|
+
if (config2.formatter_timeout_secs !== undefined)
|
|
24504
|
+
overrides.formatter_timeout_secs = config2.formatter_timeout_secs;
|
|
24505
|
+
if (config2.validate_on_edit !== undefined)
|
|
24506
|
+
overrides.validate_on_edit = config2.validate_on_edit;
|
|
24507
|
+
if (config2.formatter !== undefined)
|
|
24508
|
+
overrides.formatter = config2.formatter;
|
|
24509
|
+
if (config2.checker !== undefined)
|
|
24510
|
+
overrides.checker = config2.checker;
|
|
24511
|
+
overrides.restrict_to_project_root = config2.restrict_to_project_root ?? false;
|
|
24512
|
+
if (config2.search_index !== undefined)
|
|
24513
|
+
overrides.search_index = config2.search_index;
|
|
24514
|
+
if (config2.semantic_search !== undefined)
|
|
24515
|
+
overrides.semantic_search = config2.semantic_search;
|
|
24516
|
+
Object.assign(overrides, resolveExperimentalConfigForConfigure(config2));
|
|
24517
|
+
Object.assign(overrides, resolveLspConfigForConfigure(config2));
|
|
24518
|
+
if (config2.semantic !== undefined)
|
|
24519
|
+
overrides.semantic = config2.semantic;
|
|
24520
|
+
if (config2.max_callgraph_files !== undefined)
|
|
24521
|
+
overrides.max_callgraph_files = config2.max_callgraph_files;
|
|
24522
|
+
return overrides;
|
|
24523
|
+
}
|
|
24524
|
+
function resolveBashConfig(config2) {
|
|
24525
|
+
const top = config2.bash;
|
|
24526
|
+
const legacy = config2.experimental?.bash;
|
|
24527
|
+
const surface = config2.tool_surface ?? "recommended";
|
|
24528
|
+
const surfaceDefaultEnabled = surface !== "minimal";
|
|
24529
|
+
const reminderEnabled = (typeof top === "object" && top !== null ? top.long_running_reminder_enabled : undefined) ?? legacy?.long_running_reminder_enabled;
|
|
24530
|
+
const reminderInterval = (typeof top === "object" && top !== null ? top.long_running_reminder_interval_ms : undefined) ?? legacy?.long_running_reminder_interval_ms;
|
|
24531
|
+
const base = {
|
|
24532
|
+
enabled: false,
|
|
24533
|
+
rewrite: false,
|
|
24534
|
+
compress: false,
|
|
24535
|
+
background: false,
|
|
24536
|
+
long_running_reminder_enabled: reminderEnabled,
|
|
24537
|
+
long_running_reminder_interval_ms: reminderInterval
|
|
24538
|
+
};
|
|
24539
|
+
if (top === false) {
|
|
24540
|
+
return base;
|
|
24541
|
+
}
|
|
24542
|
+
if (top === true) {
|
|
24543
|
+
return { ...base, enabled: true, rewrite: true, compress: true, background: true };
|
|
24544
|
+
}
|
|
24545
|
+
if (typeof top === "object" && top !== null) {
|
|
24546
|
+
return {
|
|
24547
|
+
...base,
|
|
24548
|
+
enabled: true,
|
|
24549
|
+
rewrite: top.rewrite ?? true,
|
|
24550
|
+
compress: top.compress ?? true,
|
|
24551
|
+
background: top.background ?? true
|
|
24552
|
+
};
|
|
24410
24553
|
}
|
|
24411
|
-
|
|
24412
|
-
|
|
24554
|
+
const hasLegacyFeatureFlag = legacy && (legacy.rewrite !== undefined || legacy.compress !== undefined || legacy.background !== undefined);
|
|
24555
|
+
if (hasLegacyFeatureFlag) {
|
|
24556
|
+
const rewrite = legacy.rewrite === true;
|
|
24557
|
+
const compress = legacy.compress === true;
|
|
24558
|
+
const background = legacy.background === true;
|
|
24559
|
+
return {
|
|
24560
|
+
...base,
|
|
24561
|
+
enabled: rewrite || compress || background,
|
|
24562
|
+
rewrite,
|
|
24563
|
+
compress,
|
|
24564
|
+
background
|
|
24565
|
+
};
|
|
24413
24566
|
}
|
|
24414
|
-
|
|
24415
|
-
|
|
24567
|
+
return {
|
|
24568
|
+
...base,
|
|
24569
|
+
enabled: surfaceDefaultEnabled,
|
|
24570
|
+
rewrite: surfaceDefaultEnabled,
|
|
24571
|
+
compress: surfaceDefaultEnabled,
|
|
24572
|
+
background: surfaceDefaultEnabled
|
|
24573
|
+
};
|
|
24574
|
+
}
|
|
24575
|
+
function resolveExperimentalConfigForConfigure(config2) {
|
|
24576
|
+
const overrides = {};
|
|
24577
|
+
const bash = resolveBashConfig(config2);
|
|
24578
|
+
overrides.experimental_bash_rewrite = bash.rewrite;
|
|
24579
|
+
overrides.experimental_bash_compress = bash.compress;
|
|
24580
|
+
overrides.experimental_bash_background = bash.background;
|
|
24581
|
+
if (bash.long_running_reminder_enabled !== undefined) {
|
|
24582
|
+
overrides.bash_long_running_reminder_enabled = bash.long_running_reminder_enabled;
|
|
24416
24583
|
}
|
|
24417
|
-
if (
|
|
24418
|
-
overrides.bash_long_running_reminder_interval_ms =
|
|
24584
|
+
if (bash.long_running_reminder_interval_ms !== undefined) {
|
|
24585
|
+
overrides.bash_long_running_reminder_interval_ms = bash.long_running_reminder_interval_ms;
|
|
24419
24586
|
}
|
|
24420
24587
|
if (config2.experimental?.lsp_ty !== undefined) {
|
|
24421
24588
|
overrides.experimental_lsp_ty = config2.experimental.lsp_ty;
|
|
@@ -24486,8 +24653,51 @@ function migrateRawConfig(rawConfig, configPath, logger) {
|
|
|
24486
24653
|
delete rawConfig[migration.oldKey];
|
|
24487
24654
|
oldKeys.push(migration.oldKey);
|
|
24488
24655
|
}
|
|
24656
|
+
oldKeys.push(...migrateExperimentalBashBlock(rawConfig, configPath, logger));
|
|
24489
24657
|
return oldKeys;
|
|
24490
24658
|
}
|
|
24659
|
+
function migrateExperimentalBashBlock(rawConfig, configPath, logger) {
|
|
24660
|
+
const experimental = rawConfig.experimental;
|
|
24661
|
+
if (typeof experimental !== "object" || experimental === null || Array.isArray(experimental)) {
|
|
24662
|
+
return [];
|
|
24663
|
+
}
|
|
24664
|
+
const expRecord = experimental;
|
|
24665
|
+
if (!Object.hasOwn(expRecord, "bash"))
|
|
24666
|
+
return [];
|
|
24667
|
+
const legacyBash = expRecord.bash;
|
|
24668
|
+
if (typeof legacyBash !== "object" || legacyBash === null || Array.isArray(legacyBash)) {
|
|
24669
|
+
delete expRecord.bash;
|
|
24670
|
+
if (Object.keys(expRecord).length === 0)
|
|
24671
|
+
delete rawConfig.experimental;
|
|
24672
|
+
return ["experimental.bash"];
|
|
24673
|
+
}
|
|
24674
|
+
const bashRecord = legacyBash;
|
|
24675
|
+
const hasFeatureFlag = "rewrite" in bashRecord || "compress" in bashRecord || "background" in bashRecord;
|
|
24676
|
+
if (!hasFeatureFlag)
|
|
24677
|
+
return [];
|
|
24678
|
+
const movedKeys = Object.keys(bashRecord).map((k) => `experimental.bash.${k}`);
|
|
24679
|
+
if (Object.hasOwn(rawConfig, "bash")) {
|
|
24680
|
+
logger?.warn(`Config migration conflict at ${configPath}: experimental.bash dropped because top-level "bash" is already set`);
|
|
24681
|
+
} else {
|
|
24682
|
+
const migrated = {
|
|
24683
|
+
rewrite: bashRecord.rewrite === true,
|
|
24684
|
+
compress: bashRecord.compress === true,
|
|
24685
|
+
background: bashRecord.background === true
|
|
24686
|
+
};
|
|
24687
|
+
if (bashRecord.long_running_reminder_enabled !== undefined) {
|
|
24688
|
+
migrated.long_running_reminder_enabled = bashRecord.long_running_reminder_enabled;
|
|
24689
|
+
}
|
|
24690
|
+
if (bashRecord.long_running_reminder_interval_ms !== undefined) {
|
|
24691
|
+
migrated.long_running_reminder_interval_ms = bashRecord.long_running_reminder_interval_ms;
|
|
24692
|
+
}
|
|
24693
|
+
rawConfig.bash = migrated;
|
|
24694
|
+
}
|
|
24695
|
+
delete expRecord.bash;
|
|
24696
|
+
if (Object.keys(expRecord).length === 0) {
|
|
24697
|
+
delete rawConfig.experimental;
|
|
24698
|
+
}
|
|
24699
|
+
return movedKeys;
|
|
24700
|
+
}
|
|
24491
24701
|
function migrateAftConfigFile(configPath, logger = { log: log2, warn: warn2 }) {
|
|
24492
24702
|
if (!existsSync6(configPath)) {
|
|
24493
24703
|
return { migrated: false, oldKeys: [] };
|
|
@@ -24623,6 +24833,22 @@ function mergeLspConfig(baseLsp, overrideLsp) {
|
|
|
24623
24833
|
}
|
|
24624
24834
|
return Object.fromEntries(Object.entries(lsp).filter(([, value]) => value !== undefined));
|
|
24625
24835
|
}
|
|
24836
|
+
function mergeBashConfig(baseBash, overrideBash) {
|
|
24837
|
+
if (baseBash === undefined && overrideBash === undefined)
|
|
24838
|
+
return;
|
|
24839
|
+
if (baseBash === undefined)
|
|
24840
|
+
return overrideBash;
|
|
24841
|
+
if (overrideBash === undefined)
|
|
24842
|
+
return baseBash;
|
|
24843
|
+
const expand = (value) => {
|
|
24844
|
+
if (value === true)
|
|
24845
|
+
return { rewrite: true, compress: true, background: true };
|
|
24846
|
+
if (value === false)
|
|
24847
|
+
return { rewrite: false, compress: false, background: false };
|
|
24848
|
+
return { ...value ?? {} };
|
|
24849
|
+
};
|
|
24850
|
+
return { ...expand(baseBash), ...expand(overrideBash) };
|
|
24851
|
+
}
|
|
24626
24852
|
function mergeExperimentalConfig(baseExperimental, overrideExperimental) {
|
|
24627
24853
|
const bash = {
|
|
24628
24854
|
...baseExperimental?.bash,
|
|
@@ -24666,7 +24892,8 @@ var PROJECT_SAFE_TOP_LEVEL_FIELDS = new Set([
|
|
|
24666
24892
|
"validate_on_edit",
|
|
24667
24893
|
"search_index",
|
|
24668
24894
|
"semantic_search",
|
|
24669
|
-
"experimental"
|
|
24895
|
+
"experimental",
|
|
24896
|
+
"bash"
|
|
24670
24897
|
]);
|
|
24671
24898
|
function pickProjectSafeFields(override) {
|
|
24672
24899
|
const safe = {};
|
|
@@ -24696,13 +24923,16 @@ function mergeConfigs(base, override) {
|
|
|
24696
24923
|
const semantic = mergeSemanticConfig(base.semantic, override.semantic);
|
|
24697
24924
|
const lsp = mergeLspConfig(base.lsp, override.lsp);
|
|
24698
24925
|
const experimental = mergeExperimentalConfig(base.experimental, override.experimental);
|
|
24926
|
+
const bash = mergeBashConfig(base.bash, override.bash);
|
|
24699
24927
|
const safeOverride = pickProjectSafeFields(override);
|
|
24928
|
+
delete safeOverride.bash;
|
|
24700
24929
|
return {
|
|
24701
24930
|
...base,
|
|
24702
24931
|
...safeOverride,
|
|
24703
24932
|
...Object.keys(formatter).length > 0 ? { formatter } : {},
|
|
24704
24933
|
...Object.keys(checker).length > 0 ? { checker } : {},
|
|
24705
24934
|
...lsp ? { lsp } : {},
|
|
24935
|
+
...bash !== undefined ? { bash } : {},
|
|
24706
24936
|
experimental,
|
|
24707
24937
|
semantic,
|
|
24708
24938
|
...disabledTools.length > 0 ? { disabled_tools: [...new Set(disabledTools)] } : {}
|
|
@@ -25360,8 +25590,8 @@ function showToast(ctx, title, message, variant = "info", duration3 = 3000) {
|
|
|
25360
25590
|
|
|
25361
25591
|
// src/lsp-auto-install.ts
|
|
25362
25592
|
import { spawn as spawn3 } from "child_process";
|
|
25363
|
-
import { createHash as
|
|
25364
|
-
import { createReadStream, mkdirSync as mkdirSync8, readFileSync as
|
|
25593
|
+
import { createHash as createHash5 } from "crypto";
|
|
25594
|
+
import { createReadStream, mkdirSync as mkdirSync8, readFileSync as readFileSync9, renameSync as renameSync5, rmSync as rmSync4, statSync as statSync5 } from "fs";
|
|
25365
25595
|
import { join as join15 } from "path";
|
|
25366
25596
|
|
|
25367
25597
|
// src/lsp-cache.ts
|
|
@@ -25695,19 +25925,33 @@ var NPM_LSP_TABLE = [
|
|
|
25695
25925
|
id: "vue",
|
|
25696
25926
|
npm: "@vue/language-server",
|
|
25697
25927
|
binary: "vue-language-server",
|
|
25698
|
-
extensions: ["vue"]
|
|
25928
|
+
extensions: ["vue"],
|
|
25929
|
+
rootMarkers: [
|
|
25930
|
+
"vue.config.js",
|
|
25931
|
+
"vue.config.mjs",
|
|
25932
|
+
"vue.config.ts",
|
|
25933
|
+
"nuxt.config.js",
|
|
25934
|
+
"nuxt.config.mjs",
|
|
25935
|
+
"nuxt.config.ts",
|
|
25936
|
+
"nuxt.config.cjs"
|
|
25937
|
+
],
|
|
25938
|
+
packageJsonDeps: ["vue", "@vue/runtime-core", "nuxt"]
|
|
25699
25939
|
},
|
|
25700
25940
|
{
|
|
25701
25941
|
id: "astro",
|
|
25702
25942
|
npm: "@astrojs/language-server",
|
|
25703
25943
|
binary: "astro-ls",
|
|
25704
|
-
extensions: ["astro"]
|
|
25944
|
+
extensions: ["astro"],
|
|
25945
|
+
rootMarkers: ["astro.config.js", "astro.config.mjs", "astro.config.ts", "astro.config.cjs"],
|
|
25946
|
+
packageJsonDeps: ["astro"]
|
|
25705
25947
|
},
|
|
25706
25948
|
{
|
|
25707
25949
|
id: "svelte",
|
|
25708
25950
|
npm: "svelte-language-server",
|
|
25709
25951
|
binary: "svelteserver",
|
|
25710
|
-
extensions: ["svelte"]
|
|
25952
|
+
extensions: ["svelte"],
|
|
25953
|
+
rootMarkers: ["svelte.config.js", "svelte.config.mjs", "svelte.config.ts", "svelte.config.cjs"],
|
|
25954
|
+
packageJsonDeps: ["svelte", "@sveltejs/kit"]
|
|
25711
25955
|
},
|
|
25712
25956
|
{
|
|
25713
25957
|
id: "php-intelephense",
|
|
@@ -25725,7 +25969,7 @@ var NPM_LSP_TABLE = [
|
|
|
25725
25969
|
];
|
|
25726
25970
|
|
|
25727
25971
|
// src/lsp-project-relevance.ts
|
|
25728
|
-
import { existsSync as existsSync10, readdirSync as readdirSync3 } from "fs";
|
|
25972
|
+
import { existsSync as existsSync10, readdirSync as readdirSync3, readFileSync as readFileSync8 } from "fs";
|
|
25729
25973
|
import { join as join14 } from "path";
|
|
25730
25974
|
var MAX_WALK_DIRS = 200;
|
|
25731
25975
|
var MAX_WALK_DEPTH = 4;
|
|
@@ -25748,6 +25992,34 @@ function hasRootMarker(projectRoot, rootMarkers) {
|
|
|
25748
25992
|
}
|
|
25749
25993
|
return false;
|
|
25750
25994
|
}
|
|
25995
|
+
function hasPackageJsonDep(projectRoot, depNames) {
|
|
25996
|
+
if (!depNames || depNames.length === 0)
|
|
25997
|
+
return false;
|
|
25998
|
+
const pkg = readPackageJson(projectRoot);
|
|
25999
|
+
if (!pkg)
|
|
26000
|
+
return false;
|
|
26001
|
+
const merged = {
|
|
26002
|
+
...typeof pkg.dependencies === "object" && pkg.dependencies ? pkg.dependencies : {},
|
|
26003
|
+
...typeof pkg.devDependencies === "object" && pkg.devDependencies ? pkg.devDependencies : {},
|
|
26004
|
+
...typeof pkg.peerDependencies === "object" && pkg.peerDependencies ? pkg.peerDependencies : {}
|
|
26005
|
+
};
|
|
26006
|
+
for (const name of depNames) {
|
|
26007
|
+
if (Object.hasOwn(merged, name))
|
|
26008
|
+
return true;
|
|
26009
|
+
}
|
|
26010
|
+
return false;
|
|
26011
|
+
}
|
|
26012
|
+
function readPackageJson(projectRoot) {
|
|
26013
|
+
try {
|
|
26014
|
+
const raw = readFileSync8(join14(projectRoot, "package.json"), "utf8");
|
|
26015
|
+
const parsed = JSON.parse(raw);
|
|
26016
|
+
if (typeof parsed !== "object" || parsed === null)
|
|
26017
|
+
return null;
|
|
26018
|
+
return parsed;
|
|
26019
|
+
} catch {
|
|
26020
|
+
return null;
|
|
26021
|
+
}
|
|
26022
|
+
}
|
|
25751
26023
|
function relevantExtensionsInProject(projectRoot, extToServer) {
|
|
25752
26024
|
const wanted = new Set(Object.keys(extToServer).map((ext) => ext.toLowerCase()));
|
|
25753
26025
|
const found = new Set;
|
|
@@ -25840,6 +26112,8 @@ async function probeRegistry(npmPackage, graceDays, fetchImpl = fetch) {
|
|
|
25840
26112
|
function isProjectRelevant(spec, projectRoot, projectExtensions) {
|
|
25841
26113
|
if (hasRootMarker(projectRoot, spec.rootMarkers))
|
|
25842
26114
|
return true;
|
|
26115
|
+
if (hasPackageJsonDep(projectRoot, spec.packageJsonDeps))
|
|
26116
|
+
return true;
|
|
25843
26117
|
const extensions = projectExtensions();
|
|
25844
26118
|
return spec.extensions.some((ext) => extensions.has(ext.toLowerCase()));
|
|
25845
26119
|
}
|
|
@@ -25901,8 +26175,9 @@ function runInstall(spec, version2, cwd, signal) {
|
|
|
25901
26175
|
resolve3(false);
|
|
25902
26176
|
return;
|
|
25903
26177
|
}
|
|
25904
|
-
const child = spawn3("
|
|
25905
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
26178
|
+
const child = spawn3("npm", ["install", "--no-save", "--ignore-scripts", "--silent", target], {
|
|
26179
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
26180
|
+
cwd
|
|
25906
26181
|
});
|
|
25907
26182
|
child.unref();
|
|
25908
26183
|
let stderrBuf = "";
|
|
@@ -26039,7 +26314,7 @@ function hashInstalledBinary(spec) {
|
|
|
26039
26314
|
reject(new Error(`installed binary not found at any of: ${candidates.join(", ")}`));
|
|
26040
26315
|
return;
|
|
26041
26316
|
}
|
|
26042
|
-
const hash2 =
|
|
26317
|
+
const hash2 = createHash5("sha256");
|
|
26043
26318
|
const stream = createReadStream(pathToHash);
|
|
26044
26319
|
stream.on("error", reject);
|
|
26045
26320
|
stream.on("data", (chunk) => hash2.update(chunk));
|
|
@@ -26062,7 +26337,7 @@ function installedBinaryPath(spec) {
|
|
|
26062
26337
|
return null;
|
|
26063
26338
|
}
|
|
26064
26339
|
function sha256OfFileSync(path2) {
|
|
26065
|
-
return
|
|
26340
|
+
return createHash5("sha256").update(readFileSync9(path2)).digest("hex");
|
|
26066
26341
|
}
|
|
26067
26342
|
function quarantineCachedNpmInstall(spec, reason) {
|
|
26068
26343
|
const packageDir = lspPackageDir(spec.npm);
|
|
@@ -26147,7 +26422,7 @@ function runAutoInstall(projectRoot, config2, fetchImpl = fetch) {
|
|
|
26147
26422
|
|
|
26148
26423
|
// src/lsp-github-install.ts
|
|
26149
26424
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
26150
|
-
import { createHash as
|
|
26425
|
+
import { createHash as createHash6, randomBytes } from "crypto";
|
|
26151
26426
|
import {
|
|
26152
26427
|
copyFileSync as copyFileSync3,
|
|
26153
26428
|
createReadStream as createReadStream2,
|
|
@@ -26156,7 +26431,7 @@ import {
|
|
|
26156
26431
|
lstatSync as lstatSync2,
|
|
26157
26432
|
mkdirSync as mkdirSync9,
|
|
26158
26433
|
readdirSync as readdirSync4,
|
|
26159
|
-
readFileSync as
|
|
26434
|
+
readFileSync as readFileSync10,
|
|
26160
26435
|
readlinkSync as readlinkSync2,
|
|
26161
26436
|
realpathSync as realpathSync3,
|
|
26162
26437
|
renameSync as renameSync6,
|
|
@@ -26290,7 +26565,7 @@ function readGithubInstalledMetaIn(installDir) {
|
|
|
26290
26565
|
const path2 = join16(installDir, INSTALLED_META_FILE2);
|
|
26291
26566
|
if (!statSync6(path2).isFile())
|
|
26292
26567
|
return null;
|
|
26293
|
-
const parsed = JSON.parse(
|
|
26568
|
+
const parsed = JSON.parse(readFileSync10(path2, "utf8"));
|
|
26294
26569
|
if (typeof parsed.version !== "string" || parsed.version.length === 0)
|
|
26295
26570
|
return null;
|
|
26296
26571
|
return {
|
|
@@ -26323,7 +26598,7 @@ var MAX_DOWNLOAD_BYTES3 = 256 * 1024 * 1024;
|
|
|
26323
26598
|
var MAX_EXTRACT_BYTES2 = 1024 * 1024 * 1024;
|
|
26324
26599
|
function sha256OfFile(path2) {
|
|
26325
26600
|
return new Promise((resolve4, reject) => {
|
|
26326
|
-
const hash2 =
|
|
26601
|
+
const hash2 = createHash6("sha256");
|
|
26327
26602
|
const stream = createReadStream2(path2);
|
|
26328
26603
|
stream.on("error", reject);
|
|
26329
26604
|
stream.on("data", (chunk) => hash2.update(chunk));
|
|
@@ -26331,7 +26606,7 @@ function sha256OfFile(path2) {
|
|
|
26331
26606
|
});
|
|
26332
26607
|
}
|
|
26333
26608
|
function sha256OfFileSync2(path2) {
|
|
26334
|
-
return
|
|
26609
|
+
return createHash6("sha256").update(readFileSync10(path2)).digest("hex");
|
|
26335
26610
|
}
|
|
26336
26611
|
async function fetchReleaseByTag(githubRepo, tag, fetchImpl, signal) {
|
|
26337
26612
|
const candidates = [];
|
|
@@ -27030,7 +27305,7 @@ function normalizeToolMap(tools) {
|
|
|
27030
27305
|
}
|
|
27031
27306
|
|
|
27032
27307
|
// src/notifications.ts
|
|
27033
|
-
import { existsSync as existsSync12, mkdirSync as mkdirSync10, readFileSync as
|
|
27308
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync10, readFileSync as readFileSync11, writeFileSync as writeFileSync9 } from "fs";
|
|
27034
27309
|
import { homedir as homedir9, platform as platform2 } from "os";
|
|
27035
27310
|
import { join as join17 } from "path";
|
|
27036
27311
|
function isTuiMode() {
|
|
@@ -27073,7 +27348,7 @@ function readDesktopState(directory) {
|
|
|
27073
27348
|
return { sessionId: null, serverUrl: null };
|
|
27074
27349
|
}
|
|
27075
27350
|
try {
|
|
27076
|
-
const raw =
|
|
27351
|
+
const raw = readFileSync11(statePath, "utf-8");
|
|
27077
27352
|
const state = JSON.parse(raw);
|
|
27078
27353
|
let serverUrl = null;
|
|
27079
27354
|
const serverStr = state.server;
|
|
@@ -27169,25 +27444,34 @@ async function sendWarning(opts, message) {
|
|
|
27169
27444
|
sessionLog(sessionId, `[aft-plugin] sending warning to session ${sessionId}`);
|
|
27170
27445
|
await sendIgnoredMessage(opts.client, sessionId, text);
|
|
27171
27446
|
}
|
|
27172
|
-
async function sendFeatureAnnouncement(opts, version2, features, storageDir) {
|
|
27447
|
+
async function sendFeatureAnnouncement(opts, version2, features, footer, storageDir) {
|
|
27173
27448
|
if (storageDir) {
|
|
27174
27449
|
const versionFile = join17(storageDir, "last_announced_version");
|
|
27175
27450
|
try {
|
|
27176
27451
|
if (existsSync12(versionFile)) {
|
|
27177
|
-
const lastVersion =
|
|
27452
|
+
const lastVersion = readFileSync11(versionFile, "utf-8").trim();
|
|
27178
27453
|
if (lastVersion === version2)
|
|
27179
27454
|
return;
|
|
27180
27455
|
}
|
|
27181
27456
|
} catch {}
|
|
27182
27457
|
}
|
|
27183
|
-
const
|
|
27458
|
+
const hasFooter = typeof footer === "string" && footer.trim().length > 0;
|
|
27459
|
+
const featureText = hasFooter ? [features.map((f) => `\u2022 ${f}`).join(`
|
|
27460
|
+
`), "", footer].join(`
|
|
27461
|
+
`) : features.map((f) => `\u2022 ${f}`).join(`
|
|
27184
27462
|
`);
|
|
27185
27463
|
const toastSent = await showTuiToast(opts.client, `AFT v${version2}`, featureText, "info", 12000);
|
|
27186
27464
|
if (!toastSent) {
|
|
27187
27465
|
const { sessionId } = readDesktopState(opts.directory);
|
|
27188
27466
|
if (!sessionId)
|
|
27189
27467
|
return;
|
|
27190
|
-
const
|
|
27468
|
+
const sections = [
|
|
27469
|
+
`${FEATURE_MARKER} v${version2}:`,
|
|
27470
|
+
...features.map((f) => ` \u2022 ${f}`)
|
|
27471
|
+
];
|
|
27472
|
+
if (hasFooter)
|
|
27473
|
+
sections.push("", footer);
|
|
27474
|
+
const text = sections.join(`
|
|
27191
27475
|
`);
|
|
27192
27476
|
sessionLog(sessionId, `[aft-plugin] sending feature announcement for v${version2}`);
|
|
27193
27477
|
await sendIgnoredMessage(opts.client, sessionId, text);
|
|
@@ -27317,11 +27601,11 @@ import { createServer } from "http";
|
|
|
27317
27601
|
import { dirname as dirname7 } from "path";
|
|
27318
27602
|
|
|
27319
27603
|
// src/shared/rpc-utils.ts
|
|
27320
|
-
import { createHash as
|
|
27604
|
+
import { createHash as createHash7 } from "crypto";
|
|
27321
27605
|
import { join as join18 } from "path";
|
|
27322
27606
|
function projectHash(directory) {
|
|
27323
27607
|
const normalized = directory.replace(/\/+$/, "");
|
|
27324
|
-
return
|
|
27608
|
+
return createHash7("sha256").update(normalized).digest("hex").slice(0, 16);
|
|
27325
27609
|
}
|
|
27326
27610
|
function rpcPortFilePath(storageDir, directory) {
|
|
27327
27611
|
const hash2 = projectHash(directory);
|
|
@@ -27674,7 +27958,7 @@ function formatStatusMarkdown(status) {
|
|
|
27674
27958
|
|
|
27675
27959
|
// src/shared/tui-config.ts
|
|
27676
27960
|
var import_comment_json4 = __toESM(require_src2(), 1);
|
|
27677
|
-
import { existsSync as existsSync13, mkdirSync as mkdirSync12, readFileSync as
|
|
27961
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync12, readFileSync as readFileSync12, writeFileSync as writeFileSync11 } from "fs";
|
|
27678
27962
|
import { dirname as dirname8, join as join20 } from "path";
|
|
27679
27963
|
|
|
27680
27964
|
// src/shared/opencode-config-dir.ts
|
|
@@ -27722,7 +28006,7 @@ function ensureTuiPluginEntry() {
|
|
|
27722
28006
|
const configPath = resolveTuiConfigPath();
|
|
27723
28007
|
let config2 = {};
|
|
27724
28008
|
if (existsSync13(configPath)) {
|
|
27725
|
-
config2 = import_comment_json4.parse(
|
|
28009
|
+
config2 = import_comment_json4.parse(readFileSync12(configPath, "utf-8")) ?? {};
|
|
27726
28010
|
}
|
|
27727
28011
|
const plugins = Array.isArray(config2.plugin) ? config2.plugin.filter((value) => typeof value === "string") : [];
|
|
27728
28012
|
if (plugins.some((plugin) => plugin === PLUGIN_NAME || plugin.startsWith(`${PLUGIN_NAME}@`) || plugin.includes("opencode-plugin") || plugin.includes("aft-opencode"))) {
|
|
@@ -29327,6 +29611,9 @@ function createWriteTool(ctx, editToolName = "edit") {
|
|
|
29327
29611
|
let output = data.created ? "Created new file." : "File updated.";
|
|
29328
29612
|
if (data.formatted)
|
|
29329
29613
|
output += " Auto-formatted.";
|
|
29614
|
+
if (data.no_op === true) {
|
|
29615
|
+
output += " No net change \u2014 the written content is byte-identical to what was already on disk.";
|
|
29616
|
+
}
|
|
29330
29617
|
const diags = data.lsp_diagnostics;
|
|
29331
29618
|
if (diags && diags.length > 0) {
|
|
29332
29619
|
const errors3 = diags.filter((d) => d.severity === "error");
|
|
@@ -29575,6 +29862,11 @@ function createEditTool(ctx, writeToolName = "write") {
|
|
|
29575
29862
|
result += `
|
|
29576
29863
|
|
|
29577
29864
|
${globSkipNote}`;
|
|
29865
|
+
if (data.no_op === true) {
|
|
29866
|
+
result += `
|
|
29867
|
+
|
|
29868
|
+
Note: no net file change \u2014 the match was found and applied, but the file content is byte-identical to before. Likely causes: oldString and newString are identical, or a formatter normalized the change away.`;
|
|
29869
|
+
}
|
|
29578
29870
|
const diags = data.lsp_diagnostics;
|
|
29579
29871
|
if (diags && diags.length > 0) {
|
|
29580
29872
|
const errors3 = diags.filter((d) => d.severity === "error");
|
|
@@ -30032,11 +30324,7 @@ function hoistedTools(ctx) {
|
|
|
30032
30324
|
aft_delete: createDeleteTool(ctx),
|
|
30033
30325
|
aft_move: createMoveTool(ctx)
|
|
30034
30326
|
};
|
|
30035
|
-
|
|
30036
|
-
const bashCompress = ctx.config.experimental?.bash?.compress === true;
|
|
30037
|
-
const bashBackground = ctx.config.experimental?.bash?.background === true;
|
|
30038
|
-
const anyBashExperimental = bashRewrite || bashCompress || bashBackground;
|
|
30039
|
-
if (anyBashExperimental) {
|
|
30327
|
+
if (resolveBashConfig(ctx.config).enabled) {
|
|
30040
30328
|
tools.bash = createBashTool(ctx);
|
|
30041
30329
|
tools.bash_status = createBashStatusTool(ctx);
|
|
30042
30330
|
tools.bash_kill = createBashKillTool(ctx);
|
|
@@ -30090,11 +30378,7 @@ function aftPrefixedTools(ctx) {
|
|
|
30090
30378
|
aft_delete: createDeleteTool(ctx),
|
|
30091
30379
|
aft_move: createMoveTool(ctx)
|
|
30092
30380
|
};
|
|
30093
|
-
|
|
30094
|
-
const bashCompress = ctx.config.experimental?.bash?.compress === true;
|
|
30095
|
-
const bashBackground = ctx.config.experimental?.bash?.background === true;
|
|
30096
|
-
const anyBashExperimental = bashRewrite || bashCompress || bashBackground;
|
|
30097
|
-
if (anyBashExperimental) {
|
|
30381
|
+
if (resolveBashConfig(ctx.config).enabled) {
|
|
30098
30382
|
tools.aft_bash = createBashTool(ctx);
|
|
30099
30383
|
tools.bash_status = createBashStatusTool(ctx);
|
|
30100
30384
|
tools.bash_kill = createBashKillTool(ctx);
|
|
@@ -31077,7 +31361,7 @@ function buildHintsFromConfig(config2, disabledTools) {
|
|
|
31077
31361
|
toolSurface: config2.tool_surface ?? "recommended",
|
|
31078
31362
|
hoistBuiltins: config2.hoist_builtin_tools !== false,
|
|
31079
31363
|
semanticEnabled: config2.semantic_search === true,
|
|
31080
|
-
bashBackgroundEnabled: config2.
|
|
31364
|
+
bashBackgroundEnabled: resolveBashConfig(config2).background,
|
|
31081
31365
|
disabledTools
|
|
31082
31366
|
});
|
|
31083
31367
|
}
|
|
@@ -31158,45 +31442,23 @@ var PLUGIN_VERSION = (() => {
|
|
|
31158
31442
|
return "0.0.0";
|
|
31159
31443
|
}
|
|
31160
31444
|
})();
|
|
31161
|
-
var ANNOUNCEMENT_VERSION = "0.
|
|
31445
|
+
var ANNOUNCEMENT_VERSION = "0.28.0";
|
|
31162
31446
|
var ANNOUNCEMENT_FEATURES = [
|
|
31163
|
-
`
|
|
31164
|
-
|
|
31165
|
-
|
|
31166
|
-
- Rewrite cat/grep/find/sed/ls into AFT counterparts for faster, formatted output.
|
|
31167
|
-
Check GitHub for how to enable.`,
|
|
31168
|
-
"Trigram grep/glob and semantic search (aft_search) graduated out of experimental.",
|
|
31169
|
-
"Lots of bugfixes and new end-to-end test coverage."
|
|
31447
|
+
"Bash hoisting is now default-on. Configure with top-level `bash: { rewrite, compress, background }` instead of `experimental.bash.*` \u2014 old config migrates automatically on first launch.",
|
|
31448
|
+
"Vue, Astro, and Svelte language servers now auto-install when the framework appears in your package.json (fixes #48).",
|
|
31449
|
+
"Native Windows ARM64 binary \u2014 ARM64 hosts no longer fall back to x64 under emulation."
|
|
31170
31450
|
];
|
|
31451
|
+
var ANNOUNCEMENT_FOOTER = "Join us on Discord: https://discord.gg/F2uWxjGnU";
|
|
31171
31452
|
var plugin = async (input) => initializePluginForDirectory(input);
|
|
31172
31453
|
async function initializePluginForDirectory(input) {
|
|
31173
31454
|
const binaryPath = await findBinary(PLUGIN_VERSION);
|
|
31174
31455
|
await ensureStorageMigrated({ harness: "opencode", binaryPath, logger: bridgeLogger });
|
|
31175
31456
|
const aftConfig = loadAftConfig(input.directory);
|
|
31176
31457
|
const autoUpdateAbort = new AbortController;
|
|
31177
|
-
const configOverrides = {
|
|
31178
|
-
|
|
31179
|
-
|
|
31180
|
-
|
|
31181
|
-
configOverrides.formatter_timeout_secs = aftConfig.formatter_timeout_secs;
|
|
31182
|
-
if (aftConfig.validate_on_edit !== undefined)
|
|
31183
|
-
configOverrides.validate_on_edit = aftConfig.validate_on_edit;
|
|
31184
|
-
if (aftConfig.formatter !== undefined)
|
|
31185
|
-
configOverrides.formatter = aftConfig.formatter;
|
|
31186
|
-
if (aftConfig.checker !== undefined)
|
|
31187
|
-
configOverrides.checker = aftConfig.checker;
|
|
31188
|
-
configOverrides.restrict_to_project_root = aftConfig.restrict_to_project_root ?? false;
|
|
31189
|
-
configOverrides.bash_permissions = true;
|
|
31190
|
-
if (aftConfig.search_index !== undefined)
|
|
31191
|
-
configOverrides.search_index = aftConfig.search_index;
|
|
31192
|
-
if (aftConfig.semantic_search !== undefined)
|
|
31193
|
-
configOverrides.semantic_search = aftConfig.semantic_search;
|
|
31194
|
-
Object.assign(configOverrides, resolveExperimentalConfigForConfigure(aftConfig));
|
|
31195
|
-
Object.assign(configOverrides, resolveLspConfigForConfigure(aftConfig));
|
|
31196
|
-
if (aftConfig.semantic !== undefined)
|
|
31197
|
-
configOverrides.semantic = aftConfig.semantic;
|
|
31198
|
-
if (aftConfig.max_callgraph_files !== undefined)
|
|
31199
|
-
configOverrides.max_callgraph_files = aftConfig.max_callgraph_files;
|
|
31458
|
+
const configOverrides = {
|
|
31459
|
+
...resolveProjectOverridesForConfigure(aftConfig),
|
|
31460
|
+
bash_permissions: true
|
|
31461
|
+
};
|
|
31200
31462
|
const isFastembedSemanticBackend = (aftConfig.semantic?.backend ?? "fastembed") === "fastembed";
|
|
31201
31463
|
configOverrides.storage_dir = resolveCortexKitStorageRoot();
|
|
31202
31464
|
let onnxRuntimePromise = null;
|
|
@@ -31277,6 +31539,15 @@ ${lines}
|
|
|
31277
31539
|
const poolOptions = {
|
|
31278
31540
|
errorPrefix: "[aft-plugin]",
|
|
31279
31541
|
minVersion: PLUGIN_VERSION,
|
|
31542
|
+
projectConfigLoader: (projectRoot) => {
|
|
31543
|
+
try {
|
|
31544
|
+
const projectConfig = loadAftConfig(projectRoot);
|
|
31545
|
+
return resolveProjectOverridesForConfigure(projectConfig);
|
|
31546
|
+
} catch (err) {
|
|
31547
|
+
warn2(`loadAftConfig(${projectRoot}) failed; falling back to plugin-init config: ${err instanceof Error ? err.message : String(err)}`);
|
|
31548
|
+
return {};
|
|
31549
|
+
}
|
|
31550
|
+
},
|
|
31280
31551
|
onVersionMismatch: async (binaryVersion, minVersion) => {
|
|
31281
31552
|
const existing = versionUpgradePromises.get(minVersion);
|
|
31282
31553
|
if (existing) {
|
|
@@ -31389,7 +31660,7 @@ ${lines}
|
|
|
31389
31660
|
return {
|
|
31390
31661
|
success: true,
|
|
31391
31662
|
status: "not_initialized",
|
|
31392
|
-
message: "
|
|
31663
|
+
message: "AFT bridge is now spawned lazily, information here will be populated after first tool call."
|
|
31393
31664
|
};
|
|
31394
31665
|
}
|
|
31395
31666
|
const cached2 = bridge.getCachedStatus();
|
|
@@ -31413,13 +31684,18 @@ ${lines}
|
|
|
31413
31684
|
const versionFile = join22(storageDir, "last_announced_version");
|
|
31414
31685
|
try {
|
|
31415
31686
|
if (existsSync15(versionFile)) {
|
|
31416
|
-
const lastVersion =
|
|
31687
|
+
const lastVersion = readFileSync13(versionFile, "utf-8").trim();
|
|
31417
31688
|
if (lastVersion === ANNOUNCEMENT_VERSION)
|
|
31418
31689
|
return { show: false };
|
|
31419
31690
|
}
|
|
31420
31691
|
} catch {}
|
|
31421
31692
|
}
|
|
31422
|
-
return {
|
|
31693
|
+
return {
|
|
31694
|
+
show: true,
|
|
31695
|
+
version: ANNOUNCEMENT_VERSION,
|
|
31696
|
+
features: ANNOUNCEMENT_FEATURES,
|
|
31697
|
+
footer: ANNOUNCEMENT_FOOTER
|
|
31698
|
+
};
|
|
31423
31699
|
});
|
|
31424
31700
|
rpcServer.handle("mark-announced", async () => {
|
|
31425
31701
|
if (storageDir && ANNOUNCEMENT_VERSION) {
|
|
@@ -31453,7 +31729,7 @@ Install: ${getManualInstallHint()}`);
|
|
|
31453
31729
|
};
|
|
31454
31730
|
if (ANNOUNCEMENT_VERSION && ANNOUNCEMENT_FEATURES.length > 0) {
|
|
31455
31731
|
setTimeout(() => {
|
|
31456
|
-
sendFeatureAnnouncement(notifyOpts, ANNOUNCEMENT_VERSION, ANNOUNCEMENT_FEATURES, storageDir).catch(() => {});
|
|
31732
|
+
sendFeatureAnnouncement(notifyOpts, ANNOUNCEMENT_VERSION, ANNOUNCEMENT_FEATURES, ANNOUNCEMENT_FOOTER, storageDir).catch(() => {});
|
|
31457
31733
|
}, 8000);
|
|
31458
31734
|
}
|
|
31459
31735
|
if (onnxRuntimePromise) {
|