@cortexkit/aft-opencode 0.9.1 → 0.10.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/bridge.d.ts.map +1 -1
- package/dist/bridge.js +18 -4
- package/dist/bridge.js.map +1 -1
- package/dist/config.d.ts +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +2 -0
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +182 -1
- package/dist/index.js.map +1 -1
- package/dist/notifications.d.ts +48 -0
- package/dist/notifications.d.ts.map +1 -0
- package/dist/notifications.js +307 -0
- package/dist/notifications.js.map +1 -0
- package/dist/onnx-runtime.d.ts +35 -0
- package/dist/onnx-runtime.d.ts.map +1 -0
- package/dist/onnx-runtime.js +203 -0
- package/dist/onnx-runtime.js.map +1 -0
- package/dist/pool.d.ts +2 -0
- package/dist/pool.d.ts.map +1 -1
- package/dist/pool.js +25 -6
- package/dist/pool.js.map +1 -1
- package/dist/resolver.d.ts.map +1 -1
- package/dist/resolver.js +15 -4
- package/dist/resolver.js.map +1 -1
- package/dist/shared/opencode-config-dir.d.ts +16 -0
- package/dist/shared/opencode-config-dir.d.ts.map +1 -0
- package/dist/shared/opencode-config-dir.js +26 -0
- package/dist/shared/opencode-config-dir.js.map +1 -0
- package/dist/shared/rpc-client.d.ts +16 -0
- package/dist/shared/rpc-client.d.ts.map +1 -0
- package/dist/shared/rpc-client.js +108 -0
- package/dist/shared/rpc-client.js.map +1 -0
- package/dist/shared/rpc-server.d.ts +17 -0
- package/dist/shared/rpc-server.d.ts.map +1 -0
- package/dist/shared/rpc-server.js +120 -0
- package/dist/shared/rpc-server.js.map +1 -0
- package/dist/shared/rpc-utils.d.ts +11 -0
- package/dist/shared/rpc-utils.d.ts.map +1 -0
- package/dist/shared/rpc-utils.js +20 -0
- package/dist/shared/rpc-utils.js.map +1 -0
- package/dist/shared/runtime.d.ts +10 -0
- package/dist/shared/runtime.d.ts.map +1 -0
- package/dist/shared/runtime.js +14 -0
- package/dist/shared/runtime.js.map +1 -0
- package/dist/shared/status.d.ts +37 -0
- package/dist/shared/status.d.ts.map +1 -0
- package/dist/shared/status.js +135 -0
- package/dist/shared/status.js.map +1 -0
- package/dist/shared/tui-config.d.ts +2 -0
- package/dist/shared/tui-config.d.ts.map +1 -0
- package/dist/shared/tui-config.js +134 -0
- package/dist/shared/tui-config.js.map +1 -0
- package/dist/tools/search.d.ts.map +1 -1
- package/dist/tools/search.js +23 -3
- package/dist/tools/search.js.map +1 -1
- package/dist/tools/semantic.d.ts +4 -0
- package/dist/tools/semantic.d.ts.map +1 -0
- package/dist/tools/semantic.js +35 -0
- package/dist/tools/semantic.js.map +1 -0
- package/package.json +26 -6
- package/src/shared/opencode-config-dir.ts +46 -0
- package/src/shared/rpc-client.ts +123 -0
- package/src/shared/rpc-server.ts +135 -0
- package/src/shared/rpc-utils.ts +21 -0
- package/src/shared/runtime.ts +26 -0
- package/src/shared/status.ts +206 -0
- package/src/shared/tui-config.ts +155 -0
- package/src/tui/index.tsx +209 -0
- package/src/tui/types/opencode-plugin-tui.d.ts +232 -0
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
function asRecord(value) {
|
|
2
|
+
return typeof value === "object" && value !== null ? value : {};
|
|
3
|
+
}
|
|
4
|
+
function readString(value, fallback = "") {
|
|
5
|
+
return typeof value === "string" ? value : fallback;
|
|
6
|
+
}
|
|
7
|
+
function readNullableString(value) {
|
|
8
|
+
return typeof value === "string" ? value : null;
|
|
9
|
+
}
|
|
10
|
+
function readBoolean(value, fallback = false) {
|
|
11
|
+
return typeof value === "boolean" ? value : fallback;
|
|
12
|
+
}
|
|
13
|
+
function readNumber(value, fallback = 0) {
|
|
14
|
+
return typeof value === "number" && Number.isFinite(value) ? value : fallback;
|
|
15
|
+
}
|
|
16
|
+
function readOptionalNumber(value) {
|
|
17
|
+
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
18
|
+
}
|
|
19
|
+
function formatFlag(enabled) {
|
|
20
|
+
return enabled ? "enabled" : "disabled";
|
|
21
|
+
}
|
|
22
|
+
function formatCount(value) {
|
|
23
|
+
return value == null ? "—" : value.toLocaleString("en-US");
|
|
24
|
+
}
|
|
25
|
+
export function formatBytes(bytes) {
|
|
26
|
+
if (!Number.isFinite(bytes) || bytes <= 0)
|
|
27
|
+
return "0 B";
|
|
28
|
+
const units = ["B", "KB", "MB", "GB", "TB"];
|
|
29
|
+
let value = bytes;
|
|
30
|
+
let unitIndex = 0;
|
|
31
|
+
while (value >= 1024 && unitIndex < units.length - 1) {
|
|
32
|
+
value /= 1024;
|
|
33
|
+
unitIndex++;
|
|
34
|
+
}
|
|
35
|
+
const decimals = value >= 10 || unitIndex === 0 ? 0 : 1;
|
|
36
|
+
return `${value.toFixed(decimals)} ${units[unitIndex]}`;
|
|
37
|
+
}
|
|
38
|
+
export function coerceAftStatus(response) {
|
|
39
|
+
const features = asRecord(response.features);
|
|
40
|
+
const searchIndex = asRecord(response.search_index);
|
|
41
|
+
const semanticIndex = asRecord(response.semantic_index);
|
|
42
|
+
const disk = asRecord(response.disk);
|
|
43
|
+
const symbolCache = asRecord(response.symbol_cache);
|
|
44
|
+
return {
|
|
45
|
+
version: readString(response.version, "unknown"),
|
|
46
|
+
project_root: readNullableString(response.project_root),
|
|
47
|
+
features: {
|
|
48
|
+
format_on_edit: readBoolean(features.format_on_edit),
|
|
49
|
+
validate_on_edit: readString(features.validate_on_edit, "off"),
|
|
50
|
+
restrict_to_project_root: readBoolean(features.restrict_to_project_root),
|
|
51
|
+
experimental_search_index: readBoolean(features.experimental_search_index),
|
|
52
|
+
experimental_semantic_search: readBoolean(features.experimental_semantic_search),
|
|
53
|
+
},
|
|
54
|
+
search_index: {
|
|
55
|
+
status: readString(searchIndex.status, "unknown"),
|
|
56
|
+
files: readOptionalNumber(searchIndex.files),
|
|
57
|
+
trigrams: readOptionalNumber(searchIndex.trigrams),
|
|
58
|
+
},
|
|
59
|
+
semantic_index: {
|
|
60
|
+
status: readString(semanticIndex.status, "unknown"),
|
|
61
|
+
entries: readOptionalNumber(semanticIndex.entries),
|
|
62
|
+
dimension: readOptionalNumber(semanticIndex.dimension),
|
|
63
|
+
},
|
|
64
|
+
disk: {
|
|
65
|
+
storage_dir: readNullableString(disk.storage_dir),
|
|
66
|
+
trigram_disk_bytes: readNumber(disk.trigram_disk_bytes),
|
|
67
|
+
semantic_disk_bytes: readNumber(disk.semantic_disk_bytes),
|
|
68
|
+
},
|
|
69
|
+
lsp_servers: readNumber(response.lsp_servers),
|
|
70
|
+
symbol_cache: {
|
|
71
|
+
local_entries: readNumber(symbolCache.local_entries),
|
|
72
|
+
warm_entries: readNumber(symbolCache.warm_entries),
|
|
73
|
+
},
|
|
74
|
+
storage_dir: readNullableString(response.storage_dir),
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
export function formatStatusDialogMessage(status) {
|
|
78
|
+
const lines = [
|
|
79
|
+
`AFT version: ${status.version}`,
|
|
80
|
+
`Project root: ${status.project_root ?? "(not configured)"}`,
|
|
81
|
+
"",
|
|
82
|
+
"Enabled features",
|
|
83
|
+
`- format_on_edit: ${formatFlag(status.features.format_on_edit)}`,
|
|
84
|
+
`- experimental_search_index: ${formatFlag(status.features.experimental_search_index)}`,
|
|
85
|
+
`- experimental_semantic_search: ${formatFlag(status.features.experimental_semantic_search)}`,
|
|
86
|
+
"",
|
|
87
|
+
"Search index",
|
|
88
|
+
`- status: ${status.search_index.status}`,
|
|
89
|
+
`- files: ${formatCount(status.search_index.files)}`,
|
|
90
|
+
`- trigrams: ${formatCount(status.search_index.trigrams)}`,
|
|
91
|
+
"",
|
|
92
|
+
"Semantic index",
|
|
93
|
+
`- status: ${status.semantic_index.status}`,
|
|
94
|
+
`- entries: ${formatCount(status.semantic_index.entries)}`,
|
|
95
|
+
];
|
|
96
|
+
if (status.semantic_index.dimension != null) {
|
|
97
|
+
lines.push(`- dimension: ${formatCount(status.semantic_index.dimension)}`);
|
|
98
|
+
}
|
|
99
|
+
lines.push("", "Disk usage", `- trigram index: ${formatBytes(status.disk.trigram_disk_bytes)}`, `- semantic index: ${formatBytes(status.disk.semantic_disk_bytes)}`, "", "Runtime", `- LSP servers: ${formatCount(status.lsp_servers)}`, `- symbol cache: ${formatCount(status.symbol_cache.local_entries)} local / ${formatCount(status.symbol_cache.warm_entries)} warm`);
|
|
100
|
+
if (status.storage_dir ?? status.disk.storage_dir) {
|
|
101
|
+
lines.push(`- storage dir: ${status.storage_dir ?? status.disk.storage_dir}`);
|
|
102
|
+
}
|
|
103
|
+
return lines.join("\n");
|
|
104
|
+
}
|
|
105
|
+
export function formatStatusMarkdown(status) {
|
|
106
|
+
const lines = [
|
|
107
|
+
"## AFT Status",
|
|
108
|
+
"",
|
|
109
|
+
`- **Version:** \`${status.version}\``,
|
|
110
|
+
`- **Project root:** \`${status.project_root ?? "(not configured)"}\``,
|
|
111
|
+
"",
|
|
112
|
+
"### Enabled features",
|
|
113
|
+
`- \`format_on_edit\`: ${formatFlag(status.features.format_on_edit)}`,
|
|
114
|
+
`- \`experimental_search_index\`: ${formatFlag(status.features.experimental_search_index)}`,
|
|
115
|
+
`- \`experimental_semantic_search\`: ${formatFlag(status.features.experimental_semantic_search)}`,
|
|
116
|
+
"",
|
|
117
|
+
"### Search index",
|
|
118
|
+
`- **Status:** \`${status.search_index.status}\``,
|
|
119
|
+
`- **Files:** ${formatCount(status.search_index.files)}`,
|
|
120
|
+
`- **Trigrams:** ${formatCount(status.search_index.trigrams)}`,
|
|
121
|
+
"",
|
|
122
|
+
"### Semantic index",
|
|
123
|
+
`- **Status:** \`${status.semantic_index.status}\``,
|
|
124
|
+
`- **Entries:** ${formatCount(status.semantic_index.entries)}`,
|
|
125
|
+
];
|
|
126
|
+
if (status.semantic_index.dimension != null) {
|
|
127
|
+
lines.push(`- **Dimension:** ${formatCount(status.semantic_index.dimension)}`);
|
|
128
|
+
}
|
|
129
|
+
lines.push("", "### Disk usage", `- **Trigram index:** ${formatBytes(status.disk.trigram_disk_bytes)}`, `- **Semantic index:** ${formatBytes(status.disk.semantic_disk_bytes)}`, "", "### Runtime", `- **LSP servers:** ${formatCount(status.lsp_servers)}`, `- **Symbol cache:** ${formatCount(status.symbol_cache.local_entries)} local / ${formatCount(status.symbol_cache.warm_entries)} warm`);
|
|
130
|
+
if (status.storage_dir ?? status.disk.storage_dir) {
|
|
131
|
+
lines.push(`- **Storage dir:** \`${status.storage_dir ?? status.disk.storage_dir}\``);
|
|
132
|
+
}
|
|
133
|
+
return lines.join("\n");
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/shared/status.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tui-config.d.ts","sourceRoot":"","sources":["../../src/shared/tui-config.ts"],"names":[],"mappings":"AAoHA,wBAAgB,oBAAoB,IAAI,OAAO,CAsC9C"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
import { log } from "../logger.js";
|
|
4
|
+
import { getOpenCodeConfigPaths } from "./opencode-config-dir.js";
|
|
5
|
+
const PLUGIN_NAME = "@cortexkit/aft-opencode";
|
|
6
|
+
const PLUGIN_ENTRY = `${PLUGIN_NAME}@latest`;
|
|
7
|
+
function stripJsoncComments(text) {
|
|
8
|
+
let result = "";
|
|
9
|
+
let i = 0;
|
|
10
|
+
let inString = false;
|
|
11
|
+
let escaped = false;
|
|
12
|
+
while (i < text.length) {
|
|
13
|
+
const ch = text[i];
|
|
14
|
+
if (inString) {
|
|
15
|
+
result += ch;
|
|
16
|
+
if (escaped) {
|
|
17
|
+
escaped = false;
|
|
18
|
+
}
|
|
19
|
+
else if (ch === "\\") {
|
|
20
|
+
escaped = true;
|
|
21
|
+
}
|
|
22
|
+
else if (ch === '"') {
|
|
23
|
+
inString = false;
|
|
24
|
+
}
|
|
25
|
+
i++;
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
if (ch === '"') {
|
|
29
|
+
inString = true;
|
|
30
|
+
result += ch;
|
|
31
|
+
i++;
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
if (ch === "/" && text[i + 1] === "/") {
|
|
35
|
+
i += 2;
|
|
36
|
+
while (i < text.length && text[i] !== "\n")
|
|
37
|
+
i++;
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
if (ch === "/" && text[i + 1] === "*") {
|
|
41
|
+
i += 2;
|
|
42
|
+
while (i < text.length && !(text[i] === "*" && text[i + 1] === "/"))
|
|
43
|
+
i++;
|
|
44
|
+
i += 2;
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
result += ch;
|
|
48
|
+
i++;
|
|
49
|
+
}
|
|
50
|
+
return result;
|
|
51
|
+
}
|
|
52
|
+
function stripTrailingCommas(text) {
|
|
53
|
+
let result = "";
|
|
54
|
+
let i = 0;
|
|
55
|
+
let inString = false;
|
|
56
|
+
let escaped = false;
|
|
57
|
+
while (i < text.length) {
|
|
58
|
+
const ch = text[i];
|
|
59
|
+
if (inString) {
|
|
60
|
+
result += ch;
|
|
61
|
+
if (escaped) {
|
|
62
|
+
escaped = false;
|
|
63
|
+
}
|
|
64
|
+
else if (ch === "\\") {
|
|
65
|
+
escaped = true;
|
|
66
|
+
}
|
|
67
|
+
else if (ch === '"') {
|
|
68
|
+
inString = false;
|
|
69
|
+
}
|
|
70
|
+
i++;
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
if (ch === '"') {
|
|
74
|
+
inString = true;
|
|
75
|
+
result += ch;
|
|
76
|
+
i++;
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
if (ch === ",") {
|
|
80
|
+
let j = i + 1;
|
|
81
|
+
while (j < text.length && /\s/.test(text[j]))
|
|
82
|
+
j++;
|
|
83
|
+
if (text[j] === "}" || text[j] === "]") {
|
|
84
|
+
i++;
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
result += ch;
|
|
89
|
+
i++;
|
|
90
|
+
}
|
|
91
|
+
return result;
|
|
92
|
+
}
|
|
93
|
+
function parseJsonc(content) {
|
|
94
|
+
return JSON.parse(stripTrailingCommas(stripJsoncComments(content)));
|
|
95
|
+
}
|
|
96
|
+
function resolveTuiConfigPath() {
|
|
97
|
+
const configDir = getOpenCodeConfigPaths({ binary: "opencode" }).configDir;
|
|
98
|
+
const jsoncPath = join(configDir, "tui.jsonc");
|
|
99
|
+
const jsonPath = join(configDir, "tui.json");
|
|
100
|
+
if (existsSync(jsoncPath))
|
|
101
|
+
return jsoncPath;
|
|
102
|
+
if (existsSync(jsonPath))
|
|
103
|
+
return jsonPath;
|
|
104
|
+
return jsonPath;
|
|
105
|
+
}
|
|
106
|
+
export function ensureTuiPluginEntry() {
|
|
107
|
+
try {
|
|
108
|
+
const configPath = resolveTuiConfigPath();
|
|
109
|
+
let config = {};
|
|
110
|
+
if (existsSync(configPath)) {
|
|
111
|
+
config = parseJsonc(readFileSync(configPath, "utf-8")) ?? {};
|
|
112
|
+
}
|
|
113
|
+
const plugins = Array.isArray(config.plugin)
|
|
114
|
+
? config.plugin.filter((value) => typeof value === "string")
|
|
115
|
+
: [];
|
|
116
|
+
if (plugins.some((plugin) => plugin === PLUGIN_NAME ||
|
|
117
|
+
plugin.startsWith(`${PLUGIN_NAME}@`) ||
|
|
118
|
+
plugin.includes("opencode-plugin") ||
|
|
119
|
+
plugin.includes("aft-opencode"))) {
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
plugins.push(PLUGIN_ENTRY);
|
|
123
|
+
config.plugin = plugins;
|
|
124
|
+
mkdirSync(dirname(configPath), { recursive: true });
|
|
125
|
+
writeFileSync(configPath, `${JSON.stringify(config, null, 2)}\n`);
|
|
126
|
+
log(`[aft-plugin] added TUI plugin entry to ${configPath}`);
|
|
127
|
+
return true;
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
log(`[aft-plugin] failed to update tui.json: ${error instanceof Error ? error.message : String(error)}`);
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=tui-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tui-config.js","sourceRoot":"","sources":["../../src/shared/tui-config.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/tools/search.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAuDjD;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/tools/search.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAuDjD;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAyF9E"}
|
package/dist/tools/search.js
CHANGED
|
@@ -45,7 +45,12 @@ export function searchTools(ctx) {
|
|
|
45
45
|
const response = await bridge.send("grep", {
|
|
46
46
|
pattern: args.pattern,
|
|
47
47
|
case_sensitive: true,
|
|
48
|
-
include: args.include
|
|
48
|
+
include: args.include
|
|
49
|
+
? String(args.include)
|
|
50
|
+
.split(",")
|
|
51
|
+
.map((s) => normalizeGlob(s.trim()))
|
|
52
|
+
.filter(Boolean)
|
|
53
|
+
: undefined,
|
|
49
54
|
path: args.path,
|
|
50
55
|
max_results: 100,
|
|
51
56
|
});
|
|
@@ -63,9 +68,24 @@ export function searchTools(ctx) {
|
|
|
63
68
|
},
|
|
64
69
|
execute: async (args, context) => {
|
|
65
70
|
const bridge = ctx.pool.getBridge(context.directory, context.sessionID);
|
|
71
|
+
// Handle absolute paths embedded in the pattern (e.g. "/abs/path/src/**/*.ts")
|
|
72
|
+
// Split into path (directory prefix) and pattern (glob suffix)
|
|
73
|
+
let globPattern = String(args.pattern);
|
|
74
|
+
let globPath = args.path ? String(args.path) : undefined;
|
|
75
|
+
if (!globPath && globPattern.startsWith("/")) {
|
|
76
|
+
// Find the last directory component before any glob metacharacters
|
|
77
|
+
const metaIdx = globPattern.search(/[*?{}[\]]/);
|
|
78
|
+
if (metaIdx > 0) {
|
|
79
|
+
const lastSlash = globPattern.lastIndexOf("/", metaIdx);
|
|
80
|
+
if (lastSlash > 0) {
|
|
81
|
+
globPath = globPattern.slice(0, lastSlash);
|
|
82
|
+
globPattern = `**/${globPattern.slice(lastSlash + 1)}`;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
66
86
|
const response = await bridge.send("glob", {
|
|
67
|
-
pattern:
|
|
68
|
-
path:
|
|
87
|
+
pattern: globPattern,
|
|
88
|
+
path: globPath,
|
|
69
89
|
});
|
|
70
90
|
if (response.success === false) {
|
|
71
91
|
throw new Error(response.message || "glob failed");
|
package/dist/tools/search.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/tools/search.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAmBxB,SAAS,GAAG,CAAC,MAAe;IAC1B,OAAO,MAAiB,CAAC;AAC3B,CAAC;AAED,SAAS,gBAAgB,CAAC,QAAsB;IAC9C,IAAI,OAAO,QAAQ,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QACtC,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAED,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IACxE,MAAM,YAAY,GAAG,QAAQ,CAAC,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC;IAC9D,MAAM,gBAAgB,GAAG,QAAQ,CAAC,kBAAkB,IAAI,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IAEjG,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,SAAS,YAAY,iBAAiB,gBAAgB,WAAW,CAAC;IAC3E,CAAC;IAED,MAAM,IAAI,GAAG,OAAO;SACjB,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QACb,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,IAAI,SAAS,CAAC;QACrC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC;QAC7B,MAAM,IAAI,GAAG,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC;QACjD,OAAO,GAAG,IAAI,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;IACpC,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,OAAO,GAAG,IAAI,aAAa,YAAY,iBAAiB,gBAAgB,WAAW,CAAC;AACtF,CAAC;AAED,kGAAkG;AAClG,SAAS,aAAa,CAAC,OAAe;IACpC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QACzD,OAAO,MAAM,OAAO,EAAE,CAAC;IACzB,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,GAAkB;IAC5C,MAAM,QAAQ,GAAmB;QAC/B,WAAW,EACT,oHAAoH;QACtH,IAAI,EAAE;YACJ,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,0CAA0C,CAAC,CAAC;YAC7E,OAAO,EAAE,GAAG,CACV,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,qDAAqD,CAAC,CACtF;YACD,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,kDAAkD,CAAC,CAAC;SAC9F;QACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAmB,EAAE;YAChD,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;YACxE,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE;gBACzC,OAAO,EAAE,IAAI,CAAC,OAAO;gBACrB,cAAc,EAAE,IAAI;gBACpB,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/tools/search.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAmBxB,SAAS,GAAG,CAAC,MAAe;IAC1B,OAAO,MAAiB,CAAC;AAC3B,CAAC;AAED,SAAS,gBAAgB,CAAC,QAAsB;IAC9C,IAAI,OAAO,QAAQ,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QACtC,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAED,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IACxE,MAAM,YAAY,GAAG,QAAQ,CAAC,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC;IAC9D,MAAM,gBAAgB,GAAG,QAAQ,CAAC,kBAAkB,IAAI,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IAEjG,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,SAAS,YAAY,iBAAiB,gBAAgB,WAAW,CAAC;IAC3E,CAAC;IAED,MAAM,IAAI,GAAG,OAAO;SACjB,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QACb,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,IAAI,SAAS,CAAC;QACrC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC;QAC7B,MAAM,IAAI,GAAG,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC;QACjD,OAAO,GAAG,IAAI,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;IACpC,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,OAAO,GAAG,IAAI,aAAa,YAAY,iBAAiB,gBAAgB,WAAW,CAAC;AACtF,CAAC;AAED,kGAAkG;AAClG,SAAS,aAAa,CAAC,OAAe;IACpC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QACzD,OAAO,MAAM,OAAO,EAAE,CAAC;IACzB,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,GAAkB;IAC5C,MAAM,QAAQ,GAAmB;QAC/B,WAAW,EACT,oHAAoH;QACtH,IAAI,EAAE;YACJ,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,0CAA0C,CAAC,CAAC;YAC7E,OAAO,EAAE,GAAG,CACV,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,qDAAqD,CAAC,CACtF;YACD,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,kDAAkD,CAAC,CAAC;SAC9F;QACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAmB,EAAE;YAChD,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;YACxE,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE;gBACzC,OAAO,EAAE,IAAI,CAAC,OAAO;gBACrB,cAAc,EAAE,IAAI;gBACpB,OAAO,EAAE,IAAI,CAAC,OAAO;oBACnB,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC;yBACjB,KAAK,CAAC,GAAG,CAAC;yBACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;yBACnC,MAAM,CAAC,OAAO,CAAC;oBACpB,CAAC,CAAC,SAAS;gBACb,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,WAAW,EAAE,GAAG;aACjB,CAAC,CAAC;YAEH,IAAI,QAAQ,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC;gBAC/B,MAAM,IAAI,KAAK,CAAE,QAAQ,CAAC,OAAkB,IAAI,aAAa,CAAC,CAAC;YACjE,CAAC;YAED,OAAO,gBAAgB,CAAC,QAAwB,CAAC,CAAC;QACpD,CAAC;KACF,CAAC;IAEF,MAAM,QAAQ,GAAmB;QAC/B,WAAW,EACT,8FAA8F;QAChG,IAAI,EAAE;YACJ,OAAO,EAAE,GAAG,CACV,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,2DAA2D,CAAC,CACjF;YACD,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,kDAAkD,CAAC,CAAC;SAC9F;QACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAmB,EAAE;YAChD,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;YAExE,+EAA+E;YAC/E,+DAA+D;YAC/D,IAAI,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACvC,IAAI,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YAEzD,IAAI,CAAC,QAAQ,IAAI,WAAW,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC7C,mEAAmE;gBACnE,MAAM,OAAO,GAAG,WAAW,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;gBAChD,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;oBAChB,MAAM,SAAS,GAAG,WAAW,CAAC,WAAW,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;oBACxD,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;wBAClB,QAAQ,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;wBAC3C,WAAW,GAAG,MAAM,WAAW,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,EAAE,CAAC;oBACzD,CAAC;gBACH,CAAC;YACH,CAAC;YAED,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE;gBACzC,OAAO,EAAE,WAAW;gBACpB,IAAI,EAAE,QAAQ;aACf,CAAC,CAAC;YAEH,IAAI,QAAQ,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC;gBAC/B,MAAM,IAAI,KAAK,CAAE,QAAQ,CAAC,OAAkB,IAAI,aAAa,CAAC,CAAC;YACjE,CAAC;YAED,IAAI,OAAO,QAAQ,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACtC,OAAO,QAAQ,CAAC,IAAI,CAAC;YACvB,CAAC;YAED,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;gBAClC,OAAO,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACnC,CAAC;YAED,OAAQ,QAAQ,CAAC,IAAe,IAAI,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QAC/D,CAAC;KACF,CAAC;IAEF,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC,mBAAmB,KAAK,KAAK,CAAC;IAC1D,OAAO;QACL,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE,QAAQ;QAC1C,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE,QAAQ;KAC3C,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"semantic.d.ts","sourceRoot":"","sources":["../../src/tools/semantic.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAQjD,wBAAgB,aAAa,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAqChF"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
function arg(schema) {
|
|
3
|
+
return schema;
|
|
4
|
+
}
|
|
5
|
+
export function semanticTools(ctx) {
|
|
6
|
+
const searchTool = {
|
|
7
|
+
description: "Search code by meaning using semantic similarity. Use when you don't know the exact name or text — describe what you're looking for in natural language and get the most relevant symbols, functions, and types.",
|
|
8
|
+
args: {
|
|
9
|
+
query: arg(z.string().describe("Natural language search query")),
|
|
10
|
+
topK: arg(z.number().optional().describe("Number of results (default: 10)")),
|
|
11
|
+
},
|
|
12
|
+
execute: async (args, context) => {
|
|
13
|
+
const bridge = ctx.pool.getBridge(context.directory, context.sessionID);
|
|
14
|
+
const response = await bridge.send("semantic_search", {
|
|
15
|
+
query: args.query,
|
|
16
|
+
top_k: args.topK ?? 10,
|
|
17
|
+
});
|
|
18
|
+
if (response.success === false) {
|
|
19
|
+
if (response.code === "semantic_search_unavailable" &&
|
|
20
|
+
typeof response.message === "string") {
|
|
21
|
+
return response.message;
|
|
22
|
+
}
|
|
23
|
+
throw new Error(response.message || "semantic_search failed");
|
|
24
|
+
}
|
|
25
|
+
if (typeof response.text === "string") {
|
|
26
|
+
return response.text;
|
|
27
|
+
}
|
|
28
|
+
return JSON.stringify(response);
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
return {
|
|
32
|
+
aft_search: searchTool,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=semantic.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"semantic.js","sourceRoot":"","sources":["../../src/tools/semantic.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,SAAS,GAAG,CAAC,MAAe;IAC1B,OAAO,MAAiB,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,GAAkB;IAC9C,MAAM,UAAU,GAAmB;QACjC,WAAW,EACT,kNAAkN;QACpN,IAAI,EAAE;YACJ,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,+BAA+B,CAAC,CAAC;YAChE,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,iCAAiC,CAAC,CAAC;SAC7E;QACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAmB,EAAE;YAChD,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;YACxE,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,iBAAiB,EAAE;gBACpD,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,KAAK,EAAE,IAAI,CAAC,IAAI,IAAI,EAAE;aACvB,CAAC,CAAC;YAEH,IAAI,QAAQ,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC;gBAC/B,IACE,QAAQ,CAAC,IAAI,KAAK,6BAA6B;oBAC/C,OAAO,QAAQ,CAAC,OAAO,KAAK,QAAQ,EACpC,CAAC;oBACD,OAAO,QAAQ,CAAC,OAAO,CAAC;gBAC1B,CAAC;gBAED,MAAM,IAAI,KAAK,CAAE,QAAQ,CAAC,OAAkB,IAAI,wBAAwB,CAAC,CAAC;YAC5E,CAAC;YAED,IAAI,OAAO,QAAQ,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACtC,OAAO,QAAQ,CAAC,IAAI,CAAC;YACvB,CAAC;YAED,OAAO,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QAClC,CAAC;KACF,CAAC;IAEF,OAAO;QACL,UAAU,EAAE,UAAU;KACvB,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cortexkit/aft-opencode",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.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",
|
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
},
|
|
13
13
|
"files": [
|
|
14
14
|
"dist",
|
|
15
|
+
"src/tui",
|
|
16
|
+
"src/shared",
|
|
15
17
|
"README.md"
|
|
16
18
|
],
|
|
17
19
|
"scripts": {
|
|
@@ -24,18 +26,36 @@
|
|
|
24
26
|
},
|
|
25
27
|
"dependencies": {
|
|
26
28
|
"@opencode-ai/plugin": "^1.2.26",
|
|
29
|
+
"@opencode-ai/sdk": "^1.2.26",
|
|
27
30
|
"jsonc-parser": "^3.3.1",
|
|
28
31
|
"zod": "^4.1.8"
|
|
29
32
|
},
|
|
30
33
|
"optionalDependencies": {
|
|
31
|
-
"@cortexkit/aft-darwin-arm64": "0.
|
|
32
|
-
"@cortexkit/aft-darwin-x64": "0.
|
|
33
|
-
"@cortexkit/aft-linux-arm64": "0.
|
|
34
|
-
"@cortexkit/aft-linux-x64": "0.
|
|
35
|
-
"@cortexkit/aft-win32-x64": "0.
|
|
34
|
+
"@cortexkit/aft-darwin-arm64": "0.10.1",
|
|
35
|
+
"@cortexkit/aft-darwin-x64": "0.10.1",
|
|
36
|
+
"@cortexkit/aft-linux-arm64": "0.10.1",
|
|
37
|
+
"@cortexkit/aft-linux-x64": "0.10.1",
|
|
38
|
+
"@cortexkit/aft-win32-x64": "0.10.1"
|
|
36
39
|
},
|
|
37
40
|
"devDependencies": {
|
|
38
41
|
"@types/node": "^22.0.0",
|
|
39
42
|
"typescript": "^5.8.0"
|
|
43
|
+
},
|
|
44
|
+
"exports": {
|
|
45
|
+
".": {
|
|
46
|
+
"types": "./dist/index.d.ts",
|
|
47
|
+
"import": "./dist/index.js"
|
|
48
|
+
},
|
|
49
|
+
"./tui": {
|
|
50
|
+
"types": "./src/tui/index.tsx",
|
|
51
|
+
"import": "./src/tui/index.tsx"
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
"oc-plugin": [
|
|
55
|
+
"server",
|
|
56
|
+
"tui"
|
|
57
|
+
],
|
|
58
|
+
"peerDependencies": {
|
|
59
|
+
"@opencode-ai/plugin": ">=1.2.0"
|
|
40
60
|
}
|
|
41
61
|
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { homedir } from "node:os";
|
|
2
|
+
import { join, resolve } from "node:path";
|
|
3
|
+
|
|
4
|
+
export type OpenCodeBinaryType = "opencode" | "opencode-desktop";
|
|
5
|
+
|
|
6
|
+
export interface OpenCodeConfigDirOptions {
|
|
7
|
+
binary: OpenCodeBinaryType;
|
|
8
|
+
version?: string | null;
|
|
9
|
+
checkExisting?: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface OpenCodeConfigPaths {
|
|
13
|
+
configDir: string;
|
|
14
|
+
configJson: string;
|
|
15
|
+
configJsonc: string;
|
|
16
|
+
packageJson: string;
|
|
17
|
+
omoConfig: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function getCliConfigDir(): string {
|
|
21
|
+
const envConfigDir = process.env.OPENCODE_CONFIG_DIR?.trim();
|
|
22
|
+
if (envConfigDir) {
|
|
23
|
+
return resolve(envConfigDir);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (process.platform === "win32") {
|
|
27
|
+
return join(homedir(), ".config", "opencode");
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return join(process.env.XDG_CONFIG_HOME || join(homedir(), ".config"), "opencode");
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function getOpenCodeConfigDir(_options: OpenCodeConfigDirOptions): string {
|
|
34
|
+
return getCliConfigDir();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function getOpenCodeConfigPaths(options: OpenCodeConfigDirOptions): OpenCodeConfigPaths {
|
|
38
|
+
const configDir = getOpenCodeConfigDir(options);
|
|
39
|
+
return {
|
|
40
|
+
configDir,
|
|
41
|
+
configJson: join(configDir, "opencode.json"),
|
|
42
|
+
configJsonc: join(configDir, "opencode.jsonc"),
|
|
43
|
+
packageJson: join(configDir, "package.json"),
|
|
44
|
+
omoConfig: join(configDir, "magic-context.jsonc"),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { rpcPortFilePath } from "./rpc-utils.js";
|
|
3
|
+
|
|
4
|
+
const MAX_RETRIES = 10;
|
|
5
|
+
const RETRY_DELAY_MS = 500;
|
|
6
|
+
const REQUEST_TIMEOUT_MS = 5000;
|
|
7
|
+
|
|
8
|
+
export class AftRpcClient {
|
|
9
|
+
private port: number | null = null;
|
|
10
|
+
private portFilePath: string;
|
|
11
|
+
private healthChecked = false;
|
|
12
|
+
|
|
13
|
+
constructor(storageDir: string, directory: string) {
|
|
14
|
+
this.portFilePath = rpcPortFilePath(storageDir, directory);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** Call an RPC method. Retries port resolution if the server isn't ready yet. */
|
|
18
|
+
async call<T = Record<string, unknown>>(
|
|
19
|
+
method: string,
|
|
20
|
+
params: Record<string, unknown> = {},
|
|
21
|
+
): Promise<T> {
|
|
22
|
+
const port = await this.resolvePort();
|
|
23
|
+
if (!port) {
|
|
24
|
+
throw new Error("AFT RPC server not available");
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const response = await this.fetchWithTimeout(`http://127.0.0.1:${port}/rpc/${method}`, {
|
|
28
|
+
method: "POST",
|
|
29
|
+
headers: { "Content-Type": "application/json" },
|
|
30
|
+
body: JSON.stringify(params),
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
if (!response.ok) {
|
|
34
|
+
const text = await response.text();
|
|
35
|
+
throw new Error(`RPC ${method} failed (${response.status}): ${text}`);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return (await response.json()) as T;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Check if the RPC server is reachable. */
|
|
42
|
+
async isAvailable(): Promise<boolean> {
|
|
43
|
+
try {
|
|
44
|
+
const port = await this.resolvePort();
|
|
45
|
+
return port !== null;
|
|
46
|
+
} catch {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
private async resolvePort(): Promise<number | null> {
|
|
52
|
+
if (this.port && this.healthChecked) {
|
|
53
|
+
return this.port;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (this.port) {
|
|
57
|
+
const alive = await this.healthCheck(this.port);
|
|
58
|
+
if (alive) {
|
|
59
|
+
this.healthChecked = true;
|
|
60
|
+
return this.port;
|
|
61
|
+
}
|
|
62
|
+
this.port = null;
|
|
63
|
+
this.healthChecked = false;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {
|
|
67
|
+
const port = this.readPortFile();
|
|
68
|
+
if (port) {
|
|
69
|
+
const alive = await this.healthCheck(port);
|
|
70
|
+
if (alive) {
|
|
71
|
+
this.port = port;
|
|
72
|
+
this.healthChecked = true;
|
|
73
|
+
return port;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (attempt < MAX_RETRIES - 1) {
|
|
78
|
+
await new Promise((r) => setTimeout(r, RETRY_DELAY_MS));
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
private readPortFile(): number | null {
|
|
86
|
+
try {
|
|
87
|
+
const content = readFileSync(this.portFilePath, "utf-8").trim();
|
|
88
|
+
const port = Number.parseInt(content, 10);
|
|
89
|
+
if (Number.isNaN(port) || port <= 0 || port > 65535) {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
return port;
|
|
93
|
+
} catch {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
private async healthCheck(port: number): Promise<boolean> {
|
|
99
|
+
try {
|
|
100
|
+
const response = await this.fetchWithTimeout(`http://127.0.0.1:${port}/health`, {
|
|
101
|
+
method: "GET",
|
|
102
|
+
});
|
|
103
|
+
return response.ok;
|
|
104
|
+
} catch {
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
private async fetchWithTimeout(url: string, options: RequestInit): Promise<Response> {
|
|
110
|
+
const controller = new AbortController();
|
|
111
|
+
const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
|
|
112
|
+
try {
|
|
113
|
+
return await fetch(url, { ...options, signal: controller.signal });
|
|
114
|
+
} finally {
|
|
115
|
+
clearTimeout(timeout);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
reset(): void {
|
|
120
|
+
this.port = null;
|
|
121
|
+
this.healthChecked = false;
|
|
122
|
+
}
|
|
123
|
+
}
|