@cortexkit/aft-opencode 0.27.1 → 0.28.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bg-notifications.d.ts +10 -0
- package/dist/bg-notifications.d.ts.map +1 -1
- package/dist/config.d.ts +47 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +24680 -2053
- 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/shared/live-server-client.d.ts +60 -0
- package/dist/shared/live-server-client.d.ts.map +1 -0
- package/dist/shared/rpc-client.d.ts +18 -8
- package/dist/shared/rpc-client.d.ts.map +1 -1
- package/dist/shared/rpc-server.d.ts +3 -0
- package/dist/shared/rpc-server.d.ts.map +1 -1
- package/dist/shared/rpc-utils.d.ts +19 -1
- package/dist/shared/rpc-utils.d.ts.map +1 -1
- package/dist/tools/hoisted.d.ts.map +1 -1
- package/dist/tui.js +194 -168
- package/dist/workflow-hints.d.ts +5 -1
- package/dist/workflow-hints.d.ts.map +1 -1
- package/package.json +9 -8
- package/src/shared/live-server-client.ts +132 -0
- package/src/shared/rpc-client.ts +97 -76
- package/src/shared/rpc-server.ts +8 -3
- package/src/shared/rpc-utils.ts +23 -1
- package/src/tui/index.tsx +21 -6
- package/src/tui/sidebar.tsx +92 -66
package/dist/tui.js
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
// @bun
|
|
2
1
|
// src/tui/index.tsx
|
|
3
2
|
import { createMemo as createMemo2, createSignal as createSignal2, onCleanup as onCleanup2 } from "solid-js";
|
|
4
3
|
// package.json
|
|
5
4
|
var package_default = {
|
|
6
5
|
name: "@cortexkit/aft-opencode",
|
|
7
|
-
version: "0.
|
|
6
|
+
version: "0.28.1",
|
|
8
7
|
type: "module",
|
|
9
|
-
description: "OpenCode plugin for Agent File Tools (AFT)
|
|
8
|
+
description: "OpenCode plugin for Agent File Tools (AFT) — tree-sitter and lsp powered code analysis",
|
|
10
9
|
main: "dist/index.js",
|
|
11
10
|
types: "dist/index.d.ts",
|
|
12
11
|
license: "MIT",
|
|
@@ -22,7 +21,7 @@ var package_default = {
|
|
|
22
21
|
"README.md"
|
|
23
22
|
],
|
|
24
23
|
scripts: {
|
|
25
|
-
build: "bun build src/index.ts --outdir dist --target
|
|
24
|
+
build: "bun build src/index.ts --outdir dist --target node --format esm --external @opencode-ai/plugin --external @opencode-ai/sdk && bun build src/tui/index.tsx --outfile dist/tui.js --target node --format esm --external @opencode-ai/plugin --external @opencode-ai/plugin/tui --external @opencode-ai/sdk --external @opentui/solid --external solid-js && tsc --emitDeclarationOnly",
|
|
26
25
|
typecheck: "tsc --noEmit",
|
|
27
26
|
pretest: "cd ../.. && cargo build",
|
|
28
27
|
test: "bun test",
|
|
@@ -33,7 +32,7 @@ var package_default = {
|
|
|
33
32
|
},
|
|
34
33
|
dependencies: {
|
|
35
34
|
"@clack/prompts": "^1.2.0",
|
|
36
|
-
"@cortexkit/aft-bridge": "0.
|
|
35
|
+
"@cortexkit/aft-bridge": "0.28.1",
|
|
37
36
|
"@opencode-ai/plugin": "^1.15.5",
|
|
38
37
|
"@opencode-ai/sdk": "^1.15.5",
|
|
39
38
|
"comment-json": "^4.6.2",
|
|
@@ -41,11 +40,12 @@ var package_default = {
|
|
|
41
40
|
zod: "^4.1.8"
|
|
42
41
|
},
|
|
43
42
|
optionalDependencies: {
|
|
44
|
-
"@cortexkit/aft-darwin-arm64": "0.
|
|
45
|
-
"@cortexkit/aft-darwin-x64": "0.
|
|
46
|
-
"@cortexkit/aft-linux-arm64": "0.
|
|
47
|
-
"@cortexkit/aft-linux-x64": "0.
|
|
48
|
-
"@cortexkit/aft-win32-
|
|
43
|
+
"@cortexkit/aft-darwin-arm64": "0.28.1",
|
|
44
|
+
"@cortexkit/aft-darwin-x64": "0.28.1",
|
|
45
|
+
"@cortexkit/aft-linux-arm64": "0.28.1",
|
|
46
|
+
"@cortexkit/aft-linux-x64": "0.28.1",
|
|
47
|
+
"@cortexkit/aft-win32-arm64": "0.28.1",
|
|
48
|
+
"@cortexkit/aft-win32-x64": "0.28.1"
|
|
49
49
|
},
|
|
50
50
|
devDependencies: {
|
|
51
51
|
"@types/node": "^22.0.0",
|
|
@@ -71,12 +71,13 @@ var package_default = {
|
|
|
71
71
|
};
|
|
72
72
|
|
|
73
73
|
// src/shared/rpc-client.ts
|
|
74
|
-
import { readFileSync } from "fs";
|
|
74
|
+
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
75
|
+
import { join as join3 } from "node:path";
|
|
75
76
|
|
|
76
77
|
// src/logger.ts
|
|
77
|
-
import * as fs from "fs";
|
|
78
|
-
import * as os from "os";
|
|
79
|
-
import * as path from "path";
|
|
78
|
+
import * as fs from "node:fs";
|
|
79
|
+
import * as os from "node:os";
|
|
80
|
+
import * as path from "node:path";
|
|
80
81
|
var TAG = "[aft-plugin]";
|
|
81
82
|
var isTestEnv = process.env.BUN_TEST === "1" || false;
|
|
82
83
|
var logFile = path.join(os.tmpdir(), isTestEnv ? "aft-plugin-test.log" : "aft-plugin.log");
|
|
@@ -133,8 +134,8 @@ function warn(message, data) {
|
|
|
133
134
|
}
|
|
134
135
|
|
|
135
136
|
// src/shared/rpc-utils.ts
|
|
136
|
-
import { createHash } from "crypto";
|
|
137
|
-
import { join as join2 } from "path";
|
|
137
|
+
import { createHash } from "node:crypto";
|
|
138
|
+
import { join as join2 } from "node:path";
|
|
138
139
|
function projectHash(directory) {
|
|
139
140
|
const normalized = directory.replace(/\/+$/, "");
|
|
140
141
|
return createHash("sha256").update(normalized).digest("hex").slice(0, 16);
|
|
@@ -143,6 +144,10 @@ function rpcPortFilePath(storageDir, directory) {
|
|
|
143
144
|
const hash = projectHash(directory);
|
|
144
145
|
return join2(storageDir, "rpc", hash, "port");
|
|
145
146
|
}
|
|
147
|
+
function rpcPortFileDir(storageDir, directory) {
|
|
148
|
+
const hash = projectHash(directory);
|
|
149
|
+
return join2(storageDir, "rpc", hash, "ports");
|
|
150
|
+
}
|
|
146
151
|
|
|
147
152
|
// src/shared/rpc-client.ts
|
|
148
153
|
var MAX_RETRIES = 10;
|
|
@@ -152,95 +157,106 @@ var REQUEST_TIMEOUT_MS = 5000;
|
|
|
152
157
|
class AftRpcClient {
|
|
153
158
|
port = null;
|
|
154
159
|
token = null;
|
|
155
|
-
|
|
156
|
-
|
|
160
|
+
portsDir;
|
|
161
|
+
legacyPortFile;
|
|
157
162
|
constructor(storageDir, directory) {
|
|
158
|
-
this.
|
|
163
|
+
this.portsDir = rpcPortFileDir(storageDir, directory);
|
|
164
|
+
this.legacyPortFile = rpcPortFilePath(storageDir, directory);
|
|
159
165
|
}
|
|
160
166
|
async call(method, params = {}) {
|
|
161
|
-
const
|
|
162
|
-
if (
|
|
167
|
+
const infos = await this.resolvePortInfos();
|
|
168
|
+
if (infos.length === 0) {
|
|
163
169
|
throw new Error("AFT RPC server not available");
|
|
164
170
|
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
171
|
+
let placeholder = null;
|
|
172
|
+
let lastError = null;
|
|
173
|
+
for (const info of infos) {
|
|
174
|
+
try {
|
|
175
|
+
const result = await this.callOne(method, params, info);
|
|
176
|
+
if (this.looksLikePlaceholder(result)) {
|
|
177
|
+
placeholder = result;
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
this.port = info.port;
|
|
181
|
+
this.token = info.token;
|
|
182
|
+
return result;
|
|
183
|
+
} catch (err) {
|
|
184
|
+
lastError = err;
|
|
185
|
+
}
|
|
179
186
|
}
|
|
187
|
+
if (placeholder !== null)
|
|
188
|
+
return placeholder;
|
|
189
|
+
throw lastError instanceof Error ? lastError : new Error(String(lastError));
|
|
190
|
+
}
|
|
191
|
+
async callOne(method, params, info) {
|
|
192
|
+
const response = await this.fetchWithTimeout(`http://127.0.0.1:${info.port}/rpc/${method}`, {
|
|
193
|
+
method: "POST",
|
|
194
|
+
headers: { "Content-Type": "application/json" },
|
|
195
|
+
body: JSON.stringify({ ...params, token: info.token })
|
|
196
|
+
});
|
|
180
197
|
if (!response.ok) {
|
|
181
198
|
const text = await response.text();
|
|
182
|
-
if (response.status >= 500 && retryOnConnectionFailure) {
|
|
183
|
-
return this.retryAfterReset(method, params, `HTTP ${response.status}: ${text}`);
|
|
184
|
-
}
|
|
185
199
|
throw new Error(`RPC ${method} failed (${response.status}): ${text}`);
|
|
186
200
|
}
|
|
187
201
|
return await response.json();
|
|
188
202
|
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
if (!refreshed) {
|
|
195
|
-
throw new Error("AFT RPC server not available after port refresh");
|
|
196
|
-
}
|
|
197
|
-
return this.callResolved(method, params, refreshed, false);
|
|
203
|
+
looksLikePlaceholder(result) {
|
|
204
|
+
if (!result || typeof result !== "object")
|
|
205
|
+
return false;
|
|
206
|
+
const status = result.status;
|
|
207
|
+
return status === "not_initialized";
|
|
198
208
|
}
|
|
199
209
|
async isAvailable() {
|
|
200
210
|
try {
|
|
201
|
-
const
|
|
202
|
-
return
|
|
211
|
+
const infos = await this.resolvePortInfos();
|
|
212
|
+
return infos.length > 0;
|
|
203
213
|
} catch {
|
|
204
214
|
return false;
|
|
205
215
|
}
|
|
206
216
|
}
|
|
207
|
-
async
|
|
208
|
-
return (await this.resolvePortInfo())?.port ?? null;
|
|
209
|
-
}
|
|
210
|
-
async resolvePortInfo() {
|
|
211
|
-
if (this.port && this.healthChecked) {
|
|
212
|
-
return { port: this.port, token: this.token };
|
|
213
|
-
}
|
|
214
|
-
if (this.port) {
|
|
215
|
-
const alive = await this.healthCheck(this.port);
|
|
216
|
-
if (alive) {
|
|
217
|
-
this.healthChecked = true;
|
|
218
|
-
return { port: this.port, token: this.token };
|
|
219
|
-
}
|
|
220
|
-
this.port = null;
|
|
221
|
-
this.token = null;
|
|
222
|
-
this.healthChecked = false;
|
|
223
|
-
}
|
|
217
|
+
async resolvePortInfos() {
|
|
224
218
|
for (let attempt = 0;attempt < MAX_RETRIES; attempt++) {
|
|
225
|
-
const
|
|
226
|
-
if (
|
|
227
|
-
const alive =
|
|
228
|
-
|
|
229
|
-
this.
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
return info;
|
|
219
|
+
const infos = this.readAllPortFiles();
|
|
220
|
+
if (infos.length > 0) {
|
|
221
|
+
const alive = [];
|
|
222
|
+
for (const info of infos) {
|
|
223
|
+
if (await this.healthCheck(info.port)) {
|
|
224
|
+
alive.push(info);
|
|
225
|
+
}
|
|
233
226
|
}
|
|
227
|
+
if (alive.length > 0)
|
|
228
|
+
return alive;
|
|
234
229
|
}
|
|
235
230
|
if (attempt < MAX_RETRIES - 1) {
|
|
236
231
|
await new Promise((r) => setTimeout(r, RETRY_DELAY_MS));
|
|
237
232
|
}
|
|
238
233
|
}
|
|
239
|
-
return
|
|
234
|
+
return [];
|
|
240
235
|
}
|
|
241
|
-
|
|
236
|
+
readAllPortFiles() {
|
|
237
|
+
const collected = [];
|
|
238
|
+
if (existsSync(this.portsDir)) {
|
|
239
|
+
try {
|
|
240
|
+
const entries = readdirSync(this.portsDir);
|
|
241
|
+
for (const entry of entries) {
|
|
242
|
+
if (!entry.endsWith(".json"))
|
|
243
|
+
continue;
|
|
244
|
+
const info = this.parsePortFile(join3(this.portsDir, entry));
|
|
245
|
+
if (info)
|
|
246
|
+
collected.push(info);
|
|
247
|
+
}
|
|
248
|
+
} catch {}
|
|
249
|
+
}
|
|
250
|
+
if (collected.length === 0) {
|
|
251
|
+
const info = this.parsePortFile(this.legacyPortFile);
|
|
252
|
+
if (info)
|
|
253
|
+
collected.push(info);
|
|
254
|
+
}
|
|
255
|
+
return collected;
|
|
256
|
+
}
|
|
257
|
+
parsePortFile(path2) {
|
|
242
258
|
try {
|
|
243
|
-
const content = readFileSync(
|
|
259
|
+
const content = readFileSync(path2, "utf-8").trim();
|
|
244
260
|
let port;
|
|
245
261
|
let token;
|
|
246
262
|
if (content.startsWith("{")) {
|
|
@@ -282,7 +298,6 @@ class AftRpcClient {
|
|
|
282
298
|
reset() {
|
|
283
299
|
this.port = null;
|
|
284
300
|
this.token = null;
|
|
285
|
-
this.healthChecked = false;
|
|
286
301
|
}
|
|
287
302
|
}
|
|
288
303
|
|
|
@@ -408,7 +423,7 @@ var REFRESH_DEBOUNCE_MS = 200;
|
|
|
408
423
|
var POLL_INTERVAL_MS = 1500;
|
|
409
424
|
function formatBytes2(n) {
|
|
410
425
|
if (!Number.isFinite(n) || n <= 0)
|
|
411
|
-
return "
|
|
426
|
+
return "—";
|
|
412
427
|
if (n >= 1073741824)
|
|
413
428
|
return `${(n / 1073741824).toFixed(1)} GB`;
|
|
414
429
|
if (n >= 1048576)
|
|
@@ -419,7 +434,7 @@ function formatBytes2(n) {
|
|
|
419
434
|
}
|
|
420
435
|
function formatCount(n) {
|
|
421
436
|
if (n == null || !Number.isFinite(n))
|
|
422
|
-
return "
|
|
437
|
+
return "—";
|
|
423
438
|
if (n >= 1e6)
|
|
424
439
|
return `${(n / 1e6).toFixed(1)}M`;
|
|
425
440
|
if (n >= 1000)
|
|
@@ -595,6 +610,7 @@ var SidebarContent = (props) => {
|
|
|
595
610
|
});
|
|
596
611
|
}, { defer: false }));
|
|
597
612
|
const s = createMemo(() => status());
|
|
613
|
+
const notInitialized = () => s()?.cache_role === "not_initialized";
|
|
598
614
|
const searchStatus = () => statusDisplay(s()?.search_index?.status ?? "disabled");
|
|
599
615
|
const semanticStatus = () => statusDisplay(s()?.semantic_index?.status ?? "disabled");
|
|
600
616
|
const trigramBytes = () => s()?.disk?.trigram_disk_bytes ?? 0;
|
|
@@ -663,7 +679,7 @@ var SidebarContent = (props) => {
|
|
|
663
679
|
}, undefined, false, undefined, this)
|
|
664
680
|
]
|
|
665
681
|
}, undefined, true, undefined, this),
|
|
666
|
-
/* @__PURE__ */ jsxDEV("text", {
|
|
682
|
+
!notInitialized() && /* @__PURE__ */ jsxDEV("text", {
|
|
667
683
|
fg: props.theme.textMuted,
|
|
668
684
|
children: [
|
|
669
685
|
"v",
|
|
@@ -678,100 +694,104 @@ var SidebarContent = (props) => {
|
|
|
678
694
|
children: /* @__PURE__ */ jsxDEV("text", {
|
|
679
695
|
fg: props.theme.warning,
|
|
680
696
|
children: [
|
|
681
|
-
"
|
|
697
|
+
"⚠ ",
|
|
682
698
|
degradedSummary()
|
|
683
699
|
]
|
|
684
700
|
}, undefined, true, undefined, this)
|
|
685
701
|
}, undefined, false, undefined, this),
|
|
686
|
-
|
|
702
|
+
notInitialized() && /* @__PURE__ */ jsxDEV("box", {
|
|
687
703
|
marginTop: 1,
|
|
688
704
|
width: "100%",
|
|
689
705
|
children: /* @__PURE__ */ jsxDEV("text", {
|
|
690
706
|
fg: props.theme.textMuted,
|
|
691
|
-
children: s().message || "
|
|
707
|
+
children: s().message || "AFT bridge is now spawned lazily, information here will be populated after first tool call."
|
|
692
708
|
}, undefined, false, undefined, this)
|
|
693
709
|
}, undefined, false, undefined, this),
|
|
694
|
-
/* @__PURE__ */ jsxDEV(
|
|
695
|
-
theme: props.theme,
|
|
696
|
-
title: "Search Index"
|
|
697
|
-
}, undefined, false, undefined, this),
|
|
698
|
-
/* @__PURE__ */ jsxDEV(StatRow, {
|
|
699
|
-
theme: props.theme,
|
|
700
|
-
label: "Status",
|
|
701
|
-
value: searchStatus().label,
|
|
702
|
-
tone: searchStatus().tone
|
|
703
|
-
}, undefined, false, undefined, this),
|
|
704
|
-
(s()?.search_index?.files ?? null) != null && /* @__PURE__ */ jsxDEV(StatRow, {
|
|
705
|
-
theme: props.theme,
|
|
706
|
-
label: "Files",
|
|
707
|
-
value: formatCount(s().search_index.files),
|
|
708
|
-
tone: "muted"
|
|
709
|
-
}, undefined, false, undefined, this),
|
|
710
|
-
/* @__PURE__ */ jsxDEV(StatRow, {
|
|
711
|
-
theme: props.theme,
|
|
712
|
-
label: "Disk",
|
|
713
|
-
value: formatBytes2(trigramBytes()),
|
|
714
|
-
tone: "muted"
|
|
715
|
-
}, undefined, false, undefined, this),
|
|
716
|
-
/* @__PURE__ */ jsxDEV(SectionHeader, {
|
|
717
|
-
theme: props.theme,
|
|
718
|
-
title: "Semantic Index"
|
|
719
|
-
}, undefined, false, undefined, this),
|
|
720
|
-
/* @__PURE__ */ jsxDEV(StatRow, {
|
|
721
|
-
theme: props.theme,
|
|
722
|
-
label: "Status",
|
|
723
|
-
value: semanticStatus().label,
|
|
724
|
-
tone: semanticStatus().tone
|
|
725
|
-
}, undefined, false, undefined, this),
|
|
726
|
-
s()?.semantic_index?.status === "loading" && s()?.semantic_index?.entries_total != null && s().semantic_index.entries_total > 0 && /* @__PURE__ */ jsxDEV(StatRow, {
|
|
727
|
-
theme: props.theme,
|
|
728
|
-
label: "Progress",
|
|
729
|
-
value: `${formatCount(s().semantic_index.entries_done)} / ${formatCount(s().semantic_index.entries_total)}`,
|
|
730
|
-
tone: "warn"
|
|
731
|
-
}, undefined, false, undefined, this),
|
|
732
|
-
(s()?.semantic_index?.entries ?? null) != null && /* @__PURE__ */ jsxDEV(StatRow, {
|
|
733
|
-
theme: props.theme,
|
|
734
|
-
label: "Entries",
|
|
735
|
-
value: formatCount(s().semantic_index.entries),
|
|
736
|
-
tone: "muted"
|
|
737
|
-
}, undefined, false, undefined, this),
|
|
738
|
-
/* @__PURE__ */ jsxDEV(StatRow, {
|
|
739
|
-
theme: props.theme,
|
|
740
|
-
label: "Disk",
|
|
741
|
-
value: formatBytes2(semanticBytes()),
|
|
742
|
-
tone: "muted"
|
|
743
|
-
}, undefined, false, undefined, this),
|
|
744
|
-
compressionRows().length > 0 && /* @__PURE__ */ jsxDEV(Fragment, {
|
|
710
|
+
!notInitialized() && /* @__PURE__ */ jsxDEV(Fragment, {
|
|
745
711
|
children: [
|
|
746
712
|
/* @__PURE__ */ jsxDEV(SectionHeader, {
|
|
747
713
|
theme: props.theme,
|
|
748
|
-
title: "
|
|
714
|
+
title: "Search Index"
|
|
749
715
|
}, undefined, false, undefined, this),
|
|
750
|
-
|
|
751
|
-
width: "100%",
|
|
752
|
-
children: /* @__PURE__ */ jsxDEV("text", {
|
|
753
|
-
fg: props.theme.text,
|
|
754
|
-
children: row.label
|
|
755
|
-
}, undefined, false, undefined, this)
|
|
756
|
-
}, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV(StatRow, {
|
|
716
|
+
/* @__PURE__ */ jsxDEV(StatRow, {
|
|
757
717
|
theme: props.theme,
|
|
758
|
-
label:
|
|
759
|
-
value:
|
|
718
|
+
label: "Status",
|
|
719
|
+
value: searchStatus().label,
|
|
720
|
+
tone: searchStatus().tone
|
|
721
|
+
}, undefined, false, undefined, this),
|
|
722
|
+
(s()?.search_index?.files ?? null) != null && /* @__PURE__ */ jsxDEV(StatRow, {
|
|
723
|
+
theme: props.theme,
|
|
724
|
+
label: "Files",
|
|
725
|
+
value: formatCount(s().search_index.files),
|
|
760
726
|
tone: "muted"
|
|
761
|
-
}, undefined, false, undefined, this)
|
|
727
|
+
}, undefined, false, undefined, this),
|
|
728
|
+
/* @__PURE__ */ jsxDEV(StatRow, {
|
|
729
|
+
theme: props.theme,
|
|
730
|
+
label: "Disk",
|
|
731
|
+
value: formatBytes2(trigramBytes()),
|
|
732
|
+
tone: "muted"
|
|
733
|
+
}, undefined, false, undefined, this),
|
|
734
|
+
/* @__PURE__ */ jsxDEV(SectionHeader, {
|
|
735
|
+
theme: props.theme,
|
|
736
|
+
title: "Semantic Index"
|
|
737
|
+
}, undefined, false, undefined, this),
|
|
738
|
+
/* @__PURE__ */ jsxDEV(StatRow, {
|
|
739
|
+
theme: props.theme,
|
|
740
|
+
label: "Status",
|
|
741
|
+
value: semanticStatus().label,
|
|
742
|
+
tone: semanticStatus().tone
|
|
743
|
+
}, undefined, false, undefined, this),
|
|
744
|
+
s()?.semantic_index?.status === "loading" && s()?.semantic_index?.entries_total != null && s().semantic_index.entries_total > 0 && /* @__PURE__ */ jsxDEV(StatRow, {
|
|
745
|
+
theme: props.theme,
|
|
746
|
+
label: "Progress",
|
|
747
|
+
value: `${formatCount(s().semantic_index.entries_done)} / ${formatCount(s().semantic_index.entries_total)}`,
|
|
748
|
+
tone: "warn"
|
|
749
|
+
}, undefined, false, undefined, this),
|
|
750
|
+
(s()?.semantic_index?.entries ?? null) != null && /* @__PURE__ */ jsxDEV(StatRow, {
|
|
751
|
+
theme: props.theme,
|
|
752
|
+
label: "Entries",
|
|
753
|
+
value: formatCount(s().semantic_index.entries),
|
|
754
|
+
tone: "muted"
|
|
755
|
+
}, undefined, false, undefined, this),
|
|
756
|
+
/* @__PURE__ */ jsxDEV(StatRow, {
|
|
757
|
+
theme: props.theme,
|
|
758
|
+
label: "Disk",
|
|
759
|
+
value: formatBytes2(semanticBytes()),
|
|
760
|
+
tone: "muted"
|
|
761
|
+
}, undefined, false, undefined, this),
|
|
762
|
+
compressionRows().length > 0 && /* @__PURE__ */ jsxDEV(Fragment, {
|
|
763
|
+
children: [
|
|
764
|
+
/* @__PURE__ */ jsxDEV(SectionHeader, {
|
|
765
|
+
theme: props.theme,
|
|
766
|
+
title: "Compression"
|
|
767
|
+
}, undefined, false, undefined, this),
|
|
768
|
+
compressionRows().map((row) => row.kind === "scope" ? /* @__PURE__ */ jsxDEV("box", {
|
|
769
|
+
width: "100%",
|
|
770
|
+
children: /* @__PURE__ */ jsxDEV("text", {
|
|
771
|
+
fg: props.theme.text,
|
|
772
|
+
children: row.label
|
|
773
|
+
}, undefined, false, undefined, this)
|
|
774
|
+
}, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV(StatRow, {
|
|
775
|
+
theme: props.theme,
|
|
776
|
+
label: row.label,
|
|
777
|
+
value: row.value,
|
|
778
|
+
tone: "muted"
|
|
779
|
+
}, undefined, false, undefined, this))
|
|
780
|
+
]
|
|
781
|
+
}, undefined, true, undefined, this),
|
|
782
|
+
s()?.semantic_index?.status === "failed" && s()?.semantic_index?.error && /* @__PURE__ */ jsxDEV("box", {
|
|
783
|
+
marginTop: 1,
|
|
784
|
+
width: "100%",
|
|
785
|
+
children: /* @__PURE__ */ jsxDEV("text", {
|
|
786
|
+
fg: props.theme.error,
|
|
787
|
+
children: [
|
|
788
|
+
"⚠ ",
|
|
789
|
+
s().semantic_index.error
|
|
790
|
+
]
|
|
791
|
+
}, undefined, true, undefined, this)
|
|
792
|
+
}, undefined, false, undefined, this)
|
|
762
793
|
]
|
|
763
|
-
}, undefined, true, undefined, this)
|
|
764
|
-
s()?.semantic_index?.status === "failed" && s()?.semantic_index?.error && /* @__PURE__ */ jsxDEV("box", {
|
|
765
|
-
marginTop: 1,
|
|
766
|
-
width: "100%",
|
|
767
|
-
children: /* @__PURE__ */ jsxDEV("text", {
|
|
768
|
-
fg: props.theme.error,
|
|
769
|
-
children: [
|
|
770
|
-
"\u26A0 ",
|
|
771
|
-
s().semantic_index.error
|
|
772
|
-
]
|
|
773
|
-
}, undefined, true, undefined, this)
|
|
774
|
-
}, undefined, false, undefined, this)
|
|
794
|
+
}, undefined, true, undefined, this)
|
|
775
795
|
]
|
|
776
796
|
}, undefined, true, undefined, this);
|
|
777
797
|
};
|
|
@@ -819,7 +839,7 @@ function getSessionId(api) {
|
|
|
819
839
|
var POLL_INTERVAL_MS2 = 1500;
|
|
820
840
|
function formatCountShort(value) {
|
|
821
841
|
if (value == null || !Number.isFinite(value))
|
|
822
|
-
return "
|
|
842
|
+
return "—";
|
|
823
843
|
if (value >= 1e6)
|
|
824
844
|
return `${(value / 1e6).toFixed(1)}M`;
|
|
825
845
|
if (value >= 1000)
|
|
@@ -911,10 +931,10 @@ var StatusDialog = (props) => {
|
|
|
911
931
|
/* @__PURE__ */ jsxDEV2("text", {
|
|
912
932
|
fg: t().accent,
|
|
913
933
|
children: /* @__PURE__ */ jsxDEV2("b", {
|
|
914
|
-
children: "
|
|
934
|
+
children: "⚡ AFT Status"
|
|
915
935
|
}, undefined, false, undefined, this)
|
|
916
936
|
}, undefined, false, undefined, this),
|
|
917
|
-
/* @__PURE__ */ jsxDEV2("text", {
|
|
937
|
+
status()?.cache_role !== "not_initialized" && /* @__PURE__ */ jsxDEV2("text", {
|
|
918
938
|
fg: t().textMuted,
|
|
919
939
|
children: [
|
|
920
940
|
"v",
|
|
@@ -937,7 +957,7 @@ var StatusDialog = (props) => {
|
|
|
937
957
|
justifyContent: "center",
|
|
938
958
|
children: /* @__PURE__ */ jsxDEV2("text", {
|
|
939
959
|
fg: t().textMuted,
|
|
940
|
-
children: status().message || "
|
|
960
|
+
children: status().message || "AFT bridge is now spawned lazily, information here will be populated after first tool call."
|
|
941
961
|
}, undefined, false, undefined, this)
|
|
942
962
|
}, undefined, false, undefined, this) : null,
|
|
943
963
|
status() && status().cache_role !== "not_initialized" ? /* @__PURE__ */ jsxDEV2("box", {
|
|
@@ -963,7 +983,7 @@ var StatusDialog = (props) => {
|
|
|
963
983
|
}, undefined, false, undefined, this)
|
|
964
984
|
]
|
|
965
985
|
}, undefined, true, undefined, this) : null,
|
|
966
|
-
status() ? /* @__PURE__ */ jsxDEV2("box", {
|
|
986
|
+
status() && status().cache_role !== "not_initialized" ? /* @__PURE__ */ jsxDEV2("box", {
|
|
967
987
|
flexDirection: "row",
|
|
968
988
|
width: "100%",
|
|
969
989
|
gap: 4,
|
|
@@ -1164,7 +1184,7 @@ var StatusDialog = (props) => {
|
|
|
1164
1184
|
children: /* @__PURE__ */ jsxDEV2("text", {
|
|
1165
1185
|
fg: t().error,
|
|
1166
1186
|
children: [
|
|
1167
|
-
"
|
|
1187
|
+
"⚠ ",
|
|
1168
1188
|
status().semantic_index.error
|
|
1169
1189
|
]
|
|
1170
1190
|
}, undefined, true, undefined, this)
|
|
@@ -1287,13 +1307,19 @@ async function showStartupNotifications(api) {
|
|
|
1287
1307
|
try {
|
|
1288
1308
|
const announcement = await client.call("get-announcement", {});
|
|
1289
1309
|
if (announcement.show && announcement.version && announcement.features?.length) {
|
|
1290
|
-
const featureText = announcement.features.map((f) => `
|
|
1310
|
+
const featureText = announcement.features.map((f) => ` • ${f}`).join(`
|
|
1291
1311
|
`);
|
|
1312
|
+
const hasFooter = typeof announcement.footer === "string" && announcement.footer.trim().length > 0;
|
|
1313
|
+
const message = hasFooter ? `What's new:
|
|
1314
|
+
|
|
1315
|
+
${featureText}
|
|
1316
|
+
|
|
1317
|
+
${announcement.footer}` : `What's new:
|
|
1318
|
+
|
|
1319
|
+
${featureText}`;
|
|
1292
1320
|
api.ui.dialog.replace(() => /* @__PURE__ */ jsxDEV2(api.ui.DialogAlert, {
|
|
1293
1321
|
title: `AFT v${announcement.version}`,
|
|
1294
|
-
message
|
|
1295
|
-
|
|
1296
|
-
${featureText}`,
|
|
1322
|
+
message,
|
|
1297
1323
|
onConfirm: () => {
|
|
1298
1324
|
client.call("mark-announced", {});
|
|
1299
1325
|
}
|
package/dist/workflow-hints.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type AftConfig } from "./config.js";
|
|
2
2
|
export interface WorkflowHintsOpts {
|
|
3
3
|
/** `tool_surface` setting — controls which tools are registered. */
|
|
4
4
|
toolSurface: "minimal" | "recommended" | "all";
|
|
@@ -20,6 +20,10 @@ export declare function buildWorkflowHints(opts: WorkflowHintsOpts): string | nu
|
|
|
20
20
|
/**
|
|
21
21
|
* Resolve workflow-hints opts from a loaded AftConfig and the active
|
|
22
22
|
* disabled-tools set computed at registration time.
|
|
23
|
+
*
|
|
24
|
+
* Background-bash gating reads the resolved bash config so the new
|
|
25
|
+
* graduated `bash: true` / `bash: { background: true }` shapes enable the
|
|
26
|
+
* hint, not just the legacy `experimental.bash.background: true` path.
|
|
23
27
|
*/
|
|
24
28
|
export declare function buildHintsFromConfig(config: AftConfig, disabledTools: Set<string>): string | null;
|
|
25
29
|
//# sourceMappingURL=workflow-hints.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workflow-hints.d.ts","sourceRoot":"","sources":["../src/workflow-hints.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"workflow-hints.d.ts","sourceRoot":"","sources":["../src/workflow-hints.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,KAAK,SAAS,EAAqB,MAAM,aAAa,CAAC;AAEhE,MAAM,WAAW,iBAAiB;IAChC,oEAAoE;IACpE,WAAW,EAAE,SAAS,GAAG,aAAa,GAAG,KAAK,CAAC;IAC/C,4EAA4E;IAC5E,aAAa,EAAE,OAAO,CAAC;IACvB,mEAAmE;IACnE,eAAe,EAAE,OAAO,CAAC;IACzB,wEAAwE;IACxE,qBAAqB,EAAE,OAAO,CAAC;IAC/B,4DAA4D;IAC5D,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAC5B;AAID;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM,GAAG,IAAI,CAmEzE;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,MAAM,GAAG,IAAI,CAQjG"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cortexkit/aft-opencode",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.28.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "OpenCode plugin for Agent File Tools (AFT) — tree-sitter and lsp powered code analysis",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"README.md"
|
|
19
19
|
],
|
|
20
20
|
"scripts": {
|
|
21
|
-
"build": "bun build src/index.ts --outdir dist --target
|
|
21
|
+
"build": "bun build src/index.ts --outdir dist --target node --format esm --external @opencode-ai/plugin --external @opencode-ai/sdk && bun build src/tui/index.tsx --outfile dist/tui.js --target node --format esm --external @opencode-ai/plugin --external @opencode-ai/plugin/tui --external @opencode-ai/sdk --external @opentui/solid --external solid-js && tsc --emitDeclarationOnly",
|
|
22
22
|
"typecheck": "tsc --noEmit",
|
|
23
23
|
"pretest": "cd ../.. && cargo build",
|
|
24
24
|
"test": "bun test",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"@clack/prompts": "^1.2.0",
|
|
32
|
-
"@cortexkit/aft-bridge": "0.
|
|
32
|
+
"@cortexkit/aft-bridge": "0.28.1",
|
|
33
33
|
"@opencode-ai/plugin": "^1.15.5",
|
|
34
34
|
"@opencode-ai/sdk": "^1.15.5",
|
|
35
35
|
"comment-json": "^4.6.2",
|
|
@@ -37,11 +37,12 @@
|
|
|
37
37
|
"zod": "^4.1.8"
|
|
38
38
|
},
|
|
39
39
|
"optionalDependencies": {
|
|
40
|
-
"@cortexkit/aft-darwin-arm64": "0.
|
|
41
|
-
"@cortexkit/aft-darwin-x64": "0.
|
|
42
|
-
"@cortexkit/aft-linux-arm64": "0.
|
|
43
|
-
"@cortexkit/aft-linux-x64": "0.
|
|
44
|
-
"@cortexkit/aft-win32-
|
|
40
|
+
"@cortexkit/aft-darwin-arm64": "0.28.1",
|
|
41
|
+
"@cortexkit/aft-darwin-x64": "0.28.1",
|
|
42
|
+
"@cortexkit/aft-linux-arm64": "0.28.1",
|
|
43
|
+
"@cortexkit/aft-linux-x64": "0.28.1",
|
|
44
|
+
"@cortexkit/aft-win32-arm64": "0.28.1",
|
|
45
|
+
"@cortexkit/aft-win32-x64": "0.28.1"
|
|
45
46
|
},
|
|
46
47
|
"devDependencies": {
|
|
47
48
|
"@types/node": "^22.0.0",
|