@tonyclaw/agent-inspector 2.0.38 → 2.0.39
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/.output/cli.js +528 -24
- package/.output/nitro.json +1 -1
- package/.output/public/assets/{CompareDrawer-hc5OoAls.js → CompareDrawer-Jfe6M6DQ.js} +1 -1
- package/.output/public/assets/{ProxyViewerContainer-BMKBs8Qz.js → ProxyViewerContainer-CQKV0Bqq.js} +8 -8
- package/.output/public/assets/{ReplayDialog-CN-KM2nu.js → ReplayDialog-B58TbTtY.js} +1 -1
- package/.output/public/assets/{RequestAnatomy-B1kTlAUk.js → RequestAnatomy-d4P6JNiP.js} +1 -1
- package/.output/public/assets/{ResponseView-BchUjKjt.js → ResponseView-Bum1a3tG.js} +1 -1
- package/.output/public/assets/{StreamingChunkSequence-BQOxI9Hi.js → StreamingChunkSequence-CjBDp5E9.js} +1 -1
- package/.output/public/assets/_sessionId-BupV2gtf.js +1 -0
- package/.output/public/assets/index-DHSww5em.js +1 -0
- package/.output/public/assets/{main-Blykwzsn.js → main-DK9PoBjx.js} +2 -2
- package/.output/server/{_sessionId-BUNZz2zZ.mjs → _sessionId-DjarbXpT.mjs} +2 -2
- package/.output/server/_ssr/{CompareDrawer-VaDYPM5G.mjs → CompareDrawer-C5Z6AlUk.mjs} +2 -2
- package/.output/server/_ssr/{ProxyViewerContainer-CpdWs7Pk.mjs → ProxyViewerContainer-4pXsBywn.mjs} +34 -6
- package/.output/server/_ssr/{ReplayDialog-DbfIjJhb.mjs → ReplayDialog-w1vc1p5e.mjs} +3 -3
- package/.output/server/_ssr/{RequestAnatomy-CrD8h6As.mjs → RequestAnatomy-2HaBhsNV.mjs} +2 -2
- package/.output/server/_ssr/{ResponseView-BalvDwtU.mjs → ResponseView-SO_Y_W85.mjs} +2 -2
- package/.output/server/_ssr/{StreamingChunkSequence-RxatDbPV.mjs → StreamingChunkSequence-CXEa2DkO.mjs} +2 -2
- package/.output/server/_ssr/{index-11qAtV9d.mjs → index-DuCGt4a2.mjs} +2 -2
- package/.output/server/_ssr/index.mjs +2 -2
- package/.output/server/_ssr/{router-C4OdRnqX.mjs → router-D0BaSzkZ.mjs} +3 -3
- package/.output/server/{_tanstack-start-manifest_v-F6bwcl33.mjs → _tanstack-start-manifest_v-6N4SODyd.mjs} +1 -1
- package/.output/server/index.mjs +57 -57
- package/README.md +7 -0
- package/package.json +1 -1
- package/src/cli/onboard.ts +629 -21
- package/src/components/providers/SettingsDialog.tsx +30 -0
- package/.output/public/assets/_sessionId-CVw5e8TK.js +0 -1
- package/.output/public/assets/index-BdUTMQL6.js +0 -1
package/.output/cli.js
CHANGED
|
@@ -938,6 +938,11 @@ function parseFlags(argv) {
|
|
|
938
938
|
skipToolWire: false,
|
|
939
939
|
codexOnly: false,
|
|
940
940
|
skipCodexSkill: false,
|
|
941
|
+
opencode: false,
|
|
942
|
+
opencodeOnly: false,
|
|
943
|
+
opencodeConfig: null,
|
|
944
|
+
opencodeTransport: "local",
|
|
945
|
+
opencodeMcpUrl: DEFAULT_MCP_URL,
|
|
941
946
|
uninstall: false,
|
|
942
947
|
status: false,
|
|
943
948
|
json: false,
|
|
@@ -967,6 +972,58 @@ function parseFlags(argv) {
|
|
|
967
972
|
case "--skip-codex-skill":
|
|
968
973
|
flags.skipCodexSkill = true;
|
|
969
974
|
break;
|
|
975
|
+
case "--opencode":
|
|
976
|
+
flags.opencode = true;
|
|
977
|
+
break;
|
|
978
|
+
case "--opencode-only":
|
|
979
|
+
flags.opencode = true;
|
|
980
|
+
flags.opencodeOnly = true;
|
|
981
|
+
break;
|
|
982
|
+
case "--opencode-config": {
|
|
983
|
+
const next = argv[i + 1];
|
|
984
|
+
if (next === void 0) {
|
|
985
|
+
process.stderr.write(
|
|
986
|
+
"agent-inspector onboard: --opencode-config requires a path argument\n"
|
|
987
|
+
);
|
|
988
|
+
process.exit(2);
|
|
989
|
+
}
|
|
990
|
+
flags.opencodeConfig = next;
|
|
991
|
+
i++;
|
|
992
|
+
break;
|
|
993
|
+
}
|
|
994
|
+
case "--opencode-transport": {
|
|
995
|
+
const next = argv[i + 1];
|
|
996
|
+
if (next === void 0) {
|
|
997
|
+
process.stderr.write(
|
|
998
|
+
"agent-inspector onboard: --opencode-transport requires local or remote\n"
|
|
999
|
+
);
|
|
1000
|
+
process.exit(2);
|
|
1001
|
+
}
|
|
1002
|
+
switch (next) {
|
|
1003
|
+
case "local":
|
|
1004
|
+
case "remote":
|
|
1005
|
+
flags.opencodeTransport = next;
|
|
1006
|
+
break;
|
|
1007
|
+
default:
|
|
1008
|
+
process.stderr.write(
|
|
1009
|
+
`agent-inspector onboard: invalid --opencode-transport: ${next}
|
|
1010
|
+
`
|
|
1011
|
+
);
|
|
1012
|
+
process.exit(2);
|
|
1013
|
+
}
|
|
1014
|
+
i++;
|
|
1015
|
+
break;
|
|
1016
|
+
}
|
|
1017
|
+
case "--opencode-mcp-url": {
|
|
1018
|
+
const next = argv[i + 1];
|
|
1019
|
+
if (next === void 0) {
|
|
1020
|
+
process.stderr.write("agent-inspector onboard: --opencode-mcp-url requires a URL\n");
|
|
1021
|
+
process.exit(2);
|
|
1022
|
+
}
|
|
1023
|
+
flags.opencodeMcpUrl = next;
|
|
1024
|
+
i++;
|
|
1025
|
+
break;
|
|
1026
|
+
}
|
|
970
1027
|
case "--uninstall":
|
|
971
1028
|
flags.uninstall = true;
|
|
972
1029
|
break;
|
|
@@ -1024,6 +1081,12 @@ Options:
|
|
|
1024
1081
|
--skip-tool-wire Skip the wire-tool phase in the Claude skill body
|
|
1025
1082
|
--skip-codex-skill Install only the Claude Code skill and slash command
|
|
1026
1083
|
--codex-only Install only the Codex skill
|
|
1084
|
+
--opencode Also configure OpenCode MCP in opencode.json/jsonc
|
|
1085
|
+
--opencode-only Configure only OpenCode MCP
|
|
1086
|
+
--opencode-config <path> Override OpenCode config path (default: ~/.config/opencode/opencode.json)
|
|
1087
|
+
--opencode-transport <local|remote>
|
|
1088
|
+
OpenCode MCP transport to write (default: local)
|
|
1089
|
+
--opencode-mcp-url <url> Agent Inspector MCP endpoint for OpenCode
|
|
1027
1090
|
--uninstall Remove generated files whose version matches this package
|
|
1028
1091
|
--status Show installed onboarding file versions and suggested action
|
|
1029
1092
|
--json Emit machine-readable JSON with --status
|
|
@@ -1052,6 +1115,356 @@ function resolveTargets(flags) {
|
|
|
1052
1115
|
function isObject(value) {
|
|
1053
1116
|
return typeof value === "object" && value !== null;
|
|
1054
1117
|
}
|
|
1118
|
+
function isOpenCodeEnabled(flags) {
|
|
1119
|
+
return flags.opencode || flags.opencodeOnly;
|
|
1120
|
+
}
|
|
1121
|
+
function resolveOpenCodeConfigPath(flags) {
|
|
1122
|
+
if (flags.opencodeConfig !== null) {
|
|
1123
|
+
return flags.opencodeConfig;
|
|
1124
|
+
}
|
|
1125
|
+
const configDir = join2(homedir2(), ".config", "opencode");
|
|
1126
|
+
const jsoncPath = join2(configDir, "opencode.jsonc");
|
|
1127
|
+
if (existsSync2(jsoncPath)) {
|
|
1128
|
+
return jsoncPath;
|
|
1129
|
+
}
|
|
1130
|
+
return join2(configDir, "opencode.json");
|
|
1131
|
+
}
|
|
1132
|
+
function stripJsoncComments(raw) {
|
|
1133
|
+
let result = "";
|
|
1134
|
+
let index = 0;
|
|
1135
|
+
let inString = false;
|
|
1136
|
+
let stringChar = "";
|
|
1137
|
+
while (index < raw.length) {
|
|
1138
|
+
const ch = raw[index];
|
|
1139
|
+
const next = raw[index + 1];
|
|
1140
|
+
if (inString) {
|
|
1141
|
+
if (ch === "\\" && next !== void 0) {
|
|
1142
|
+
result += ch + next;
|
|
1143
|
+
index += 2;
|
|
1144
|
+
continue;
|
|
1145
|
+
}
|
|
1146
|
+
if (ch === stringChar) {
|
|
1147
|
+
inString = false;
|
|
1148
|
+
stringChar = "";
|
|
1149
|
+
}
|
|
1150
|
+
result += ch;
|
|
1151
|
+
index += 1;
|
|
1152
|
+
continue;
|
|
1153
|
+
}
|
|
1154
|
+
if (ch === '"' || ch === "'") {
|
|
1155
|
+
inString = true;
|
|
1156
|
+
stringChar = ch;
|
|
1157
|
+
result += ch;
|
|
1158
|
+
index += 1;
|
|
1159
|
+
continue;
|
|
1160
|
+
}
|
|
1161
|
+
if (ch === "/" && next === "/") {
|
|
1162
|
+
while (index < raw.length && raw[index] !== "\n") {
|
|
1163
|
+
index += 1;
|
|
1164
|
+
}
|
|
1165
|
+
continue;
|
|
1166
|
+
}
|
|
1167
|
+
if (ch === "/" && next === "*") {
|
|
1168
|
+
index += 2;
|
|
1169
|
+
while (index < raw.length - 1 && !(raw[index] === "*" && raw[index + 1] === "/")) {
|
|
1170
|
+
index += 1;
|
|
1171
|
+
}
|
|
1172
|
+
index += 2;
|
|
1173
|
+
continue;
|
|
1174
|
+
}
|
|
1175
|
+
result += ch;
|
|
1176
|
+
index += 1;
|
|
1177
|
+
}
|
|
1178
|
+
return result;
|
|
1179
|
+
}
|
|
1180
|
+
function readOpenCodeConfig(path) {
|
|
1181
|
+
if (!existsSync2(path)) {
|
|
1182
|
+
return { ok: true, exists: false, config: {} };
|
|
1183
|
+
}
|
|
1184
|
+
try {
|
|
1185
|
+
const raw = readFileSync(path, "utf8");
|
|
1186
|
+
if (raw.trim().length === 0) {
|
|
1187
|
+
return { ok: true, exists: true, config: {} };
|
|
1188
|
+
}
|
|
1189
|
+
const parsed = JSON.parse(stripJsoncComments(raw));
|
|
1190
|
+
if (isObject(parsed)) {
|
|
1191
|
+
return { ok: true, exists: true, config: parsed };
|
|
1192
|
+
}
|
|
1193
|
+
return {
|
|
1194
|
+
ok: false,
|
|
1195
|
+
exists: true,
|
|
1196
|
+
message: "OpenCode config root must be a JSON object"
|
|
1197
|
+
};
|
|
1198
|
+
} catch (err) {
|
|
1199
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
1200
|
+
return {
|
|
1201
|
+
ok: false,
|
|
1202
|
+
exists: true,
|
|
1203
|
+
message
|
|
1204
|
+
};
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
function buildOpenCodeMcpEntry(transport, endpoint) {
|
|
1208
|
+
switch (transport) {
|
|
1209
|
+
case "local":
|
|
1210
|
+
return {
|
|
1211
|
+
type: "local",
|
|
1212
|
+
command: ["agent-inspector-mcp", "stdio", "--url", endpoint],
|
|
1213
|
+
enabled: true
|
|
1214
|
+
};
|
|
1215
|
+
case "remote":
|
|
1216
|
+
return {
|
|
1217
|
+
type: "remote",
|
|
1218
|
+
url: endpoint,
|
|
1219
|
+
enabled: true
|
|
1220
|
+
};
|
|
1221
|
+
default:
|
|
1222
|
+
return {
|
|
1223
|
+
type: "local",
|
|
1224
|
+
command: ["agent-inspector-mcp", "stdio", "--url", endpoint],
|
|
1225
|
+
enabled: true
|
|
1226
|
+
};
|
|
1227
|
+
}
|
|
1228
|
+
}
|
|
1229
|
+
function stringArrayEquals(value, expected) {
|
|
1230
|
+
if (!Array.isArray(value) || value.length !== expected.length) {
|
|
1231
|
+
return false;
|
|
1232
|
+
}
|
|
1233
|
+
return value.every((item, index) => item === expected[index]);
|
|
1234
|
+
}
|
|
1235
|
+
function isOpenCodeLocalEntry(value, endpoint, ignoreEnabled) {
|
|
1236
|
+
if (!isObject(value)) {
|
|
1237
|
+
return false;
|
|
1238
|
+
}
|
|
1239
|
+
const enabled = value["enabled"];
|
|
1240
|
+
if (!ignoreEnabled && enabled === false) {
|
|
1241
|
+
return false;
|
|
1242
|
+
}
|
|
1243
|
+
const env = value["environment"];
|
|
1244
|
+
const usesUrlArg = stringArrayEquals(value["command"], [
|
|
1245
|
+
"agent-inspector-mcp",
|
|
1246
|
+
"stdio",
|
|
1247
|
+
"--url",
|
|
1248
|
+
endpoint
|
|
1249
|
+
]);
|
|
1250
|
+
const usesEnv = stringArrayEquals(value["command"], ["agent-inspector-mcp", "stdio"]) && isObject(env) && env["AGENT_INSPECTOR_MCP_URL"] === endpoint;
|
|
1251
|
+
return value["type"] === "local" && (usesUrlArg || usesEnv);
|
|
1252
|
+
}
|
|
1253
|
+
function isOpenCodeRemoteEntry(value, endpoint, ignoreEnabled) {
|
|
1254
|
+
if (!isObject(value)) {
|
|
1255
|
+
return false;
|
|
1256
|
+
}
|
|
1257
|
+
const enabled = value["enabled"];
|
|
1258
|
+
if (!ignoreEnabled && enabled === false) {
|
|
1259
|
+
return false;
|
|
1260
|
+
}
|
|
1261
|
+
return value["type"] === "remote" && value["url"] === endpoint;
|
|
1262
|
+
}
|
|
1263
|
+
function isKnownOpenCodeEntry(value, endpoint, ignoreEnabled) {
|
|
1264
|
+
return isOpenCodeLocalEntry(value, endpoint, ignoreEnabled) || isOpenCodeRemoteEntry(value, endpoint, ignoreEnabled);
|
|
1265
|
+
}
|
|
1266
|
+
function detectOpenCodeTransport(value) {
|
|
1267
|
+
if (!isObject(value)) {
|
|
1268
|
+
return "unknown";
|
|
1269
|
+
}
|
|
1270
|
+
switch (value["type"]) {
|
|
1271
|
+
case "local":
|
|
1272
|
+
return "local";
|
|
1273
|
+
case "remote":
|
|
1274
|
+
return "remote";
|
|
1275
|
+
default:
|
|
1276
|
+
return "unknown";
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
function openCodeActionForStatus(status) {
|
|
1280
|
+
switch (status.state) {
|
|
1281
|
+
case "missing":
|
|
1282
|
+
return "agent-inspector onboard --opencode-only";
|
|
1283
|
+
case "configured":
|
|
1284
|
+
return "opencode mcp list";
|
|
1285
|
+
case "disabled":
|
|
1286
|
+
case "custom":
|
|
1287
|
+
return "agent-inspector onboard --opencode-only --force";
|
|
1288
|
+
case "invalid":
|
|
1289
|
+
return "fix OpenCode JSON/JSONC, then rerun agent-inspector onboard --opencode-only";
|
|
1290
|
+
default:
|
|
1291
|
+
return "agent-inspector onboard --opencode-only";
|
|
1292
|
+
}
|
|
1293
|
+
}
|
|
1294
|
+
function makeOpenCodeStatus(path, state, transport, endpoint, detail) {
|
|
1295
|
+
const status = {
|
|
1296
|
+
label: "OpenCode MCP config",
|
|
1297
|
+
path,
|
|
1298
|
+
state,
|
|
1299
|
+
transport,
|
|
1300
|
+
endpoint,
|
|
1301
|
+
action: "agent-inspector onboard --opencode-only",
|
|
1302
|
+
detail
|
|
1303
|
+
};
|
|
1304
|
+
return {
|
|
1305
|
+
...status,
|
|
1306
|
+
action: openCodeActionForStatus(status)
|
|
1307
|
+
};
|
|
1308
|
+
}
|
|
1309
|
+
function getOpenCodeEntry(config) {
|
|
1310
|
+
const mcp = config["mcp"];
|
|
1311
|
+
if (!isObject(mcp)) {
|
|
1312
|
+
return void 0;
|
|
1313
|
+
}
|
|
1314
|
+
return mcp["agent-inspector"];
|
|
1315
|
+
}
|
|
1316
|
+
function buildOpenCodeConfig(config, transport, endpoint) {
|
|
1317
|
+
const schema = typeof config["$schema"] === "string" ? config["$schema"] : "https://opencode.ai/config.json";
|
|
1318
|
+
const nextConfig = {
|
|
1319
|
+
$schema: schema
|
|
1320
|
+
};
|
|
1321
|
+
for (const [key, value] of Object.entries(config)) {
|
|
1322
|
+
if (key !== "$schema" && key !== "mcp") {
|
|
1323
|
+
nextConfig[key] = value;
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
const currentMcp = config["mcp"];
|
|
1327
|
+
const nextMcp = isObject(currentMcp) ? { ...currentMcp } : {};
|
|
1328
|
+
nextMcp["agent-inspector"] = buildOpenCodeMcpEntry(transport, endpoint);
|
|
1329
|
+
nextConfig["mcp"] = nextMcp;
|
|
1330
|
+
return nextConfig;
|
|
1331
|
+
}
|
|
1332
|
+
function formatOpenCodeConfig(config) {
|
|
1333
|
+
return `${JSON.stringify(config, null, 2)}
|
|
1334
|
+
`;
|
|
1335
|
+
}
|
|
1336
|
+
function removeOpenCodeEntry(config) {
|
|
1337
|
+
const nextConfig = {};
|
|
1338
|
+
for (const [key, value] of Object.entries(config)) {
|
|
1339
|
+
if (key !== "mcp") {
|
|
1340
|
+
nextConfig[key] = value;
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
const currentMcp = config["mcp"];
|
|
1344
|
+
if (!isObject(currentMcp)) {
|
|
1345
|
+
return nextConfig;
|
|
1346
|
+
}
|
|
1347
|
+
const nextMcp = {};
|
|
1348
|
+
for (const [key, value] of Object.entries(currentMcp)) {
|
|
1349
|
+
if (key !== "agent-inspector") {
|
|
1350
|
+
nextMcp[key] = value;
|
|
1351
|
+
}
|
|
1352
|
+
}
|
|
1353
|
+
if (Object.keys(nextMcp).length > 0) {
|
|
1354
|
+
nextConfig["mcp"] = nextMcp;
|
|
1355
|
+
}
|
|
1356
|
+
return nextConfig;
|
|
1357
|
+
}
|
|
1358
|
+
function readOpenCodeStatus(flags) {
|
|
1359
|
+
const path = resolveOpenCodeConfigPath(flags);
|
|
1360
|
+
const read = readOpenCodeConfig(path);
|
|
1361
|
+
if (!read.ok) {
|
|
1362
|
+
return makeOpenCodeStatus(path, "invalid", "unknown", flags.opencodeMcpUrl, read.message);
|
|
1363
|
+
}
|
|
1364
|
+
const entry = getOpenCodeEntry(read.config);
|
|
1365
|
+
if (entry === void 0) {
|
|
1366
|
+
const detail = read.exists ? "OpenCode config has no mcp.agent-inspector entry" : "Missing file";
|
|
1367
|
+
return makeOpenCodeStatus(path, "missing", "unknown", flags.opencodeMcpUrl, detail);
|
|
1368
|
+
}
|
|
1369
|
+
const transport = detectOpenCodeTransport(entry);
|
|
1370
|
+
if (isObject(entry) && entry["enabled"] === false) {
|
|
1371
|
+
return makeOpenCodeStatus(
|
|
1372
|
+
path,
|
|
1373
|
+
"disabled",
|
|
1374
|
+
transport,
|
|
1375
|
+
flags.opencodeMcpUrl,
|
|
1376
|
+
"mcp.agent-inspector is present but disabled"
|
|
1377
|
+
);
|
|
1378
|
+
}
|
|
1379
|
+
if (isKnownOpenCodeEntry(entry, flags.opencodeMcpUrl, false)) {
|
|
1380
|
+
return makeOpenCodeStatus(
|
|
1381
|
+
path,
|
|
1382
|
+
"configured",
|
|
1383
|
+
transport,
|
|
1384
|
+
flags.opencodeMcpUrl,
|
|
1385
|
+
"mcp.agent-inspector points at Agent Inspector MCP"
|
|
1386
|
+
);
|
|
1387
|
+
}
|
|
1388
|
+
return makeOpenCodeStatus(
|
|
1389
|
+
path,
|
|
1390
|
+
"custom",
|
|
1391
|
+
transport,
|
|
1392
|
+
flags.opencodeMcpUrl,
|
|
1393
|
+
"mcp.agent-inspector exists but does not match Agent Inspector defaults"
|
|
1394
|
+
);
|
|
1395
|
+
}
|
|
1396
|
+
function buildOpenCodePlan(flags) {
|
|
1397
|
+
const path = resolveOpenCodeConfigPath(flags);
|
|
1398
|
+
const read = readOpenCodeConfig(path);
|
|
1399
|
+
if (!read.ok) {
|
|
1400
|
+
return {
|
|
1401
|
+
status: makeOpenCodeStatus(path, "invalid", "unknown", flags.opencodeMcpUrl, read.message),
|
|
1402
|
+
body: null,
|
|
1403
|
+
shouldWrite: false,
|
|
1404
|
+
shouldRemove: false,
|
|
1405
|
+
blockedMessage: `OpenCode config is invalid: ${read.message}`
|
|
1406
|
+
};
|
|
1407
|
+
}
|
|
1408
|
+
const status = readOpenCodeStatus(flags);
|
|
1409
|
+
const entry = getOpenCodeEntry(read.config);
|
|
1410
|
+
const nextBody = formatOpenCodeConfig(
|
|
1411
|
+
buildOpenCodeConfig(read.config, flags.opencodeTransport, flags.opencodeMcpUrl)
|
|
1412
|
+
);
|
|
1413
|
+
if (flags.uninstall) {
|
|
1414
|
+
const shouldRemove = entry !== void 0 && isKnownOpenCodeEntry(entry, flags.opencodeMcpUrl, true);
|
|
1415
|
+
const removeBody = shouldRemove ? formatOpenCodeConfig(removeOpenCodeEntry(read.config)) : null;
|
|
1416
|
+
return {
|
|
1417
|
+
status,
|
|
1418
|
+
body: removeBody,
|
|
1419
|
+
shouldWrite: false,
|
|
1420
|
+
shouldRemove,
|
|
1421
|
+
blockedMessage: shouldRemove ? null : "OpenCode mcp.agent-inspector is missing or custom; preserved"
|
|
1422
|
+
};
|
|
1423
|
+
}
|
|
1424
|
+
switch (status.state) {
|
|
1425
|
+
case "configured":
|
|
1426
|
+
return {
|
|
1427
|
+
status,
|
|
1428
|
+
body: nextBody,
|
|
1429
|
+
shouldWrite: flags.force,
|
|
1430
|
+
shouldRemove: false,
|
|
1431
|
+
blockedMessage: null
|
|
1432
|
+
};
|
|
1433
|
+
case "missing":
|
|
1434
|
+
return {
|
|
1435
|
+
status,
|
|
1436
|
+
body: nextBody,
|
|
1437
|
+
shouldWrite: true,
|
|
1438
|
+
shouldRemove: false,
|
|
1439
|
+
blockedMessage: null
|
|
1440
|
+
};
|
|
1441
|
+
case "custom":
|
|
1442
|
+
case "disabled":
|
|
1443
|
+
return {
|
|
1444
|
+
status,
|
|
1445
|
+
body: nextBody,
|
|
1446
|
+
shouldWrite: flags.force,
|
|
1447
|
+
shouldRemove: false,
|
|
1448
|
+
blockedMessage: flags.force ? null : "OpenCode mcp.agent-inspector is custom or disabled; use --force to replace"
|
|
1449
|
+
};
|
|
1450
|
+
case "invalid":
|
|
1451
|
+
return {
|
|
1452
|
+
status,
|
|
1453
|
+
body: null,
|
|
1454
|
+
shouldWrite: false,
|
|
1455
|
+
shouldRemove: false,
|
|
1456
|
+
blockedMessage: "OpenCode config is invalid"
|
|
1457
|
+
};
|
|
1458
|
+
default:
|
|
1459
|
+
return {
|
|
1460
|
+
status,
|
|
1461
|
+
body: null,
|
|
1462
|
+
shouldWrite: false,
|
|
1463
|
+
shouldRemove: false,
|
|
1464
|
+
blockedMessage: "OpenCode config state is unknown"
|
|
1465
|
+
};
|
|
1466
|
+
}
|
|
1467
|
+
}
|
|
1055
1468
|
function buildDetectedSummary() {
|
|
1056
1469
|
const entries = detectAll();
|
|
1057
1470
|
const present = entries.filter((e) => e.result.found);
|
|
@@ -1230,8 +1643,8 @@ function readGeneratedFileStatus(file, currentVersion) {
|
|
|
1230
1643
|
}
|
|
1231
1644
|
}
|
|
1232
1645
|
function buildPlannedFiles(flags, targets, version) {
|
|
1233
|
-
const installClaude = !flags.codexOnly;
|
|
1234
|
-
const installCodex = !flags.skipCodexSkill;
|
|
1646
|
+
const installClaude = !flags.codexOnly && !flags.opencodeOnly;
|
|
1647
|
+
const installCodex = !flags.skipCodexSkill && !flags.opencodeOnly;
|
|
1235
1648
|
const detectedSummary = installClaude ? buildDetectedSummary() : "";
|
|
1236
1649
|
const claudeSkillBody = installClaude ? renderSkillOnboard({
|
|
1237
1650
|
version,
|
|
@@ -1289,7 +1702,7 @@ function removeEmptyDirectory(path) {
|
|
|
1289
1702
|
} catch {
|
|
1290
1703
|
}
|
|
1291
1704
|
}
|
|
1292
|
-
function runUninstall(plannedFiles, currentVersion, dryRun) {
|
|
1705
|
+
function runUninstall(plannedFiles, currentVersion, dryRun, openCodePlan) {
|
|
1293
1706
|
const enabledFiles = plannedFiles.filter((file) => file.enabled);
|
|
1294
1707
|
const filesToRemove = enabledFiles.filter((file) => shouldUninstall(file, currentVersion));
|
|
1295
1708
|
if (dryRun) {
|
|
@@ -1301,15 +1714,31 @@ function runUninstall(plannedFiles, currentVersion, dryRun) {
|
|
|
1301
1714
|
process.stdout.write(`${file.label}: ${file.path} (${status})
|
|
1302
1715
|
`);
|
|
1303
1716
|
}
|
|
1717
|
+
if (openCodePlan !== null) {
|
|
1718
|
+
const status = openCodePlan.shouldRemove ? "matching" : "skipped";
|
|
1719
|
+
process.stdout.write(
|
|
1720
|
+
`${openCodePlan.status.label}: ${openCodePlan.status.path} (${status})
|
|
1721
|
+
`
|
|
1722
|
+
);
|
|
1723
|
+
if (openCodePlan.blockedMessage !== null) {
|
|
1724
|
+
process.stdout.write(` ${openCodePlan.blockedMessage}
|
|
1725
|
+
`);
|
|
1726
|
+
}
|
|
1727
|
+
}
|
|
1304
1728
|
process.stdout.write(`
|
|
1305
1729
|
No files were removed.
|
|
1306
1730
|
`);
|
|
1307
1731
|
return 0;
|
|
1308
1732
|
}
|
|
1309
|
-
|
|
1733
|
+
const removeOpenCode = openCodePlan !== null && openCodePlan.shouldRemove;
|
|
1734
|
+
if (filesToRemove.length === 0 && !removeOpenCode) {
|
|
1310
1735
|
process.stdout.write(
|
|
1311
1736
|
"agent-inspector onboard: no generated onboarding files match this package version\n"
|
|
1312
1737
|
);
|
|
1738
|
+
if (openCodePlan !== null && openCodePlan.blockedMessage !== null) {
|
|
1739
|
+
process.stdout.write(`${openCodePlan.blockedMessage}
|
|
1740
|
+
`);
|
|
1741
|
+
}
|
|
1313
1742
|
return 0;
|
|
1314
1743
|
}
|
|
1315
1744
|
try {
|
|
@@ -1317,6 +1746,12 @@ No files were removed.
|
|
|
1317
1746
|
unlinkSync(file.path);
|
|
1318
1747
|
removeEmptyDirectory(dirname(file.path));
|
|
1319
1748
|
process.stdout.write(`Removed ${file.label}: ${file.path}
|
|
1749
|
+
`);
|
|
1750
|
+
}
|
|
1751
|
+
if (openCodePlan !== null && openCodePlan.shouldRemove && openCodePlan.body !== null) {
|
|
1752
|
+
mkdirSync(dirname(openCodePlan.status.path), { recursive: true });
|
|
1753
|
+
writeFileSync(openCodePlan.status.path, openCodePlan.body, "utf8");
|
|
1754
|
+
process.stdout.write(`Removed OpenCode MCP entry from: ${openCodePlan.status.path}
|
|
1320
1755
|
`);
|
|
1321
1756
|
}
|
|
1322
1757
|
} catch (err) {
|
|
@@ -1330,13 +1765,20 @@ No files were removed.
|
|
|
1330
1765
|
function formatStatusVersion(status) {
|
|
1331
1766
|
return status.version ?? "-";
|
|
1332
1767
|
}
|
|
1333
|
-
function summarizeStatusAction(statuses) {
|
|
1768
|
+
function summarizeStatusAction(statuses, openCodeStatus) {
|
|
1334
1769
|
const actionable = statuses.filter(
|
|
1335
1770
|
(status) => status.state === "missing" || status.state === "outdated"
|
|
1336
1771
|
);
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1772
|
+
const actions = actionable.map((status) => status.action);
|
|
1773
|
+
if (openCodeStatus !== null && openCodeStatus.state === "missing") {
|
|
1774
|
+
actions.push(openCodeStatus.action);
|
|
1775
|
+
}
|
|
1776
|
+
if (actions.length > 0) {
|
|
1777
|
+
const uniqueActions = Array.from(new Set(actions));
|
|
1778
|
+
return `Run: ${uniqueActions.join(" && ")}`;
|
|
1779
|
+
}
|
|
1780
|
+
if (openCodeStatus !== null && (openCodeStatus.state === "custom" || openCodeStatus.state === "disabled" || openCodeStatus.state === "invalid")) {
|
|
1781
|
+
return `OpenCode config needs review: ${openCodeStatus.action}`;
|
|
1340
1782
|
}
|
|
1341
1783
|
if (statuses.some((status) => status.state === "custom")) {
|
|
1342
1784
|
return "Custom files are preserved. Use --force only if you want to replace them.";
|
|
@@ -1346,16 +1788,17 @@ function summarizeStatusAction(statuses) {
|
|
|
1346
1788
|
}
|
|
1347
1789
|
return "All selected onboarding files are current.";
|
|
1348
1790
|
}
|
|
1349
|
-
function runStatus(plannedFiles, currentVersion, json) {
|
|
1791
|
+
function runStatus(plannedFiles, currentVersion, json, openCodeStatus) {
|
|
1350
1792
|
const enabledFiles = plannedFiles.filter((file) => file.enabled);
|
|
1351
1793
|
const statuses = enabledFiles.map((file) => readGeneratedFileStatus(file, currentVersion));
|
|
1352
|
-
const summary = summarizeStatusAction(statuses);
|
|
1794
|
+
const summary = summarizeStatusAction(statuses, openCodeStatus);
|
|
1353
1795
|
if (json) {
|
|
1354
1796
|
process.stdout.write(
|
|
1355
1797
|
`${JSON.stringify(
|
|
1356
1798
|
{
|
|
1357
1799
|
packageVersion: currentVersion,
|
|
1358
1800
|
files: statuses,
|
|
1801
|
+
opencodeConfig: openCodeStatus,
|
|
1359
1802
|
suggestedAction: summary
|
|
1360
1803
|
},
|
|
1361
1804
|
null,
|
|
@@ -1377,6 +1820,19 @@ function runStatus(plannedFiles, currentVersion, json) {
|
|
|
1377
1820
|
process.stdout.write(` ${status.path}
|
|
1378
1821
|
`);
|
|
1379
1822
|
process.stdout.write(` Action: ${status.action}
|
|
1823
|
+
`);
|
|
1824
|
+
}
|
|
1825
|
+
if (openCodeStatus !== null) {
|
|
1826
|
+
process.stdout.write(`${openCodeStatus.label}: ${openCodeStatus.state}`);
|
|
1827
|
+
process.stdout.write(`, transport ${openCodeStatus.transport}
|
|
1828
|
+
`);
|
|
1829
|
+
process.stdout.write(` ${openCodeStatus.path}
|
|
1830
|
+
`);
|
|
1831
|
+
process.stdout.write(` Endpoint: ${openCodeStatus.endpoint}
|
|
1832
|
+
`);
|
|
1833
|
+
process.stdout.write(` Detail: ${openCodeStatus.detail}
|
|
1834
|
+
`);
|
|
1835
|
+
process.stdout.write(` Action: ${openCodeStatus.action}
|
|
1380
1836
|
`);
|
|
1381
1837
|
}
|
|
1382
1838
|
process.stdout.write(`
|
|
@@ -1401,19 +1857,21 @@ function runOnboardSync(argv) {
|
|
|
1401
1857
|
const version = readPackageVersion();
|
|
1402
1858
|
const plannedFiles = buildPlannedFiles(flags, targets, version);
|
|
1403
1859
|
const enabledFiles = plannedFiles.filter((file) => file.enabled);
|
|
1860
|
+
const openCodePlan = isOpenCodeEnabled(flags) ? buildOpenCodePlan(flags) : null;
|
|
1861
|
+
const openCodeStatus = openCodePlan === null ? null : openCodePlan.status;
|
|
1404
1862
|
if (flags.json && !flags.status) {
|
|
1405
1863
|
process.stderr.write("agent-inspector onboard: --json is only supported with --status\n");
|
|
1406
1864
|
return 2;
|
|
1407
1865
|
}
|
|
1408
|
-
if (enabledFiles.length === 0) {
|
|
1866
|
+
if (enabledFiles.length === 0 && openCodePlan === null) {
|
|
1409
1867
|
process.stderr.write("agent-inspector onboard: no onboarding target selected\n");
|
|
1410
1868
|
return 2;
|
|
1411
1869
|
}
|
|
1412
1870
|
if (flags.status) {
|
|
1413
|
-
return runStatus(plannedFiles, version, flags.json);
|
|
1871
|
+
return runStatus(plannedFiles, version, flags.json, openCodeStatus);
|
|
1414
1872
|
}
|
|
1415
1873
|
if (flags.uninstall) {
|
|
1416
|
-
return runUninstall(plannedFiles, version, flags.dryRun);
|
|
1874
|
+
return runUninstall(plannedFiles, version, flags.dryRun, openCodePlan);
|
|
1417
1875
|
}
|
|
1418
1876
|
if (flags.dryRun) {
|
|
1419
1877
|
process.stdout.write(`agent-inspector onboard --dry-run
|
|
@@ -1424,31 +1882,47 @@ function runOnboardSync(argv) {
|
|
|
1424
1882
|
process.stdout.write(`${file.label}: ${file.path} (${status})
|
|
1425
1883
|
`);
|
|
1426
1884
|
}
|
|
1885
|
+
if (openCodePlan !== null) {
|
|
1886
|
+
process.stdout.write(
|
|
1887
|
+
`${openCodePlan.status.label}: ${openCodePlan.status.path} (${openCodePlan.status.state})
|
|
1888
|
+
`
|
|
1889
|
+
);
|
|
1890
|
+
process.stdout.write(` Transport: ${flags.opencodeTransport}
|
|
1891
|
+
`);
|
|
1892
|
+
process.stdout.write(` Endpoint: ${openCodePlan.status.endpoint}
|
|
1893
|
+
`);
|
|
1894
|
+
process.stdout.write(` Action: ${openCodePlan.status.action}
|
|
1895
|
+
`);
|
|
1896
|
+
if (openCodePlan.blockedMessage !== null) {
|
|
1897
|
+
process.stdout.write(` ${openCodePlan.blockedMessage}
|
|
1898
|
+
`);
|
|
1899
|
+
}
|
|
1900
|
+
}
|
|
1427
1901
|
process.stdout.write(`
|
|
1428
1902
|
Claude skill headings:
|
|
1429
1903
|
`);
|
|
1430
|
-
if (!flags.codexOnly) {
|
|
1904
|
+
if (!flags.codexOnly && !flags.opencodeOnly) {
|
|
1431
1905
|
for (const heading of REQUIRED_PHASE_HEADINGS) {
|
|
1432
1906
|
process.stdout.write(` - ${heading}
|
|
1433
1907
|
`);
|
|
1434
1908
|
}
|
|
1435
1909
|
} else {
|
|
1436
|
-
process.stdout.write(` (disabled by
|
|
1910
|
+
process.stdout.write(` (disabled by selected targets)
|
|
1437
1911
|
`);
|
|
1438
1912
|
}
|
|
1439
1913
|
process.stdout.write(`
|
|
1440
1914
|
Codex skill headings:
|
|
1441
1915
|
`);
|
|
1442
|
-
if (!flags.skipCodexSkill) {
|
|
1916
|
+
if (!flags.skipCodexSkill && !flags.opencodeOnly) {
|
|
1443
1917
|
for (const heading of REQUIRED_CODEX_PHASE_HEADINGS) {
|
|
1444
1918
|
process.stdout.write(` - ${heading}
|
|
1445
1919
|
`);
|
|
1446
1920
|
}
|
|
1447
1921
|
} else {
|
|
1448
|
-
process.stdout.write(` (disabled by
|
|
1922
|
+
process.stdout.write(` (disabled by selected targets)
|
|
1449
1923
|
`);
|
|
1450
1924
|
}
|
|
1451
|
-
if (!flags.codexOnly) {
|
|
1925
|
+
if (!flags.codexOnly && !flags.opencodeOnly) {
|
|
1452
1926
|
process.stdout.write(`
|
|
1453
1927
|
Detected tools:
|
|
1454
1928
|
${buildDetectedSummary()}
|
|
@@ -1460,10 +1934,20 @@ No files were written.
|
|
|
1460
1934
|
return 0;
|
|
1461
1935
|
}
|
|
1462
1936
|
const filesToWrite = plannedFiles.filter((file) => shouldWrite(file, flags.force, version));
|
|
1463
|
-
|
|
1937
|
+
const shouldWriteOpenCode = openCodePlan !== null && openCodePlan.shouldWrite && openCodePlan.body !== null;
|
|
1938
|
+
if (openCodePlan !== null && openCodePlan.status.state === "invalid") {
|
|
1939
|
+
process.stderr.write(`agent-inspector onboard: ${openCodePlan.blockedMessage ?? "invalid"}
|
|
1940
|
+
`);
|
|
1941
|
+
return 1;
|
|
1942
|
+
}
|
|
1943
|
+
if (filesToWrite.length === 0 && !shouldWriteOpenCode) {
|
|
1464
1944
|
process.stdout.write(
|
|
1465
1945
|
"agent-inspector onboard: all selected onboarding files are already up to date\n"
|
|
1466
1946
|
);
|
|
1947
|
+
if (openCodePlan !== null && openCodePlan.blockedMessage !== null) {
|
|
1948
|
+
process.stdout.write(`${openCodePlan.blockedMessage}
|
|
1949
|
+
`);
|
|
1950
|
+
}
|
|
1467
1951
|
process.stdout.write("Re-run with --force to refresh.\n");
|
|
1468
1952
|
return 0;
|
|
1469
1953
|
}
|
|
@@ -1472,6 +1956,10 @@ No files were written.
|
|
|
1472
1956
|
mkdirSync(dirname(file.path), { recursive: true });
|
|
1473
1957
|
writeFileSync(file.path, file.body, "utf8");
|
|
1474
1958
|
}
|
|
1959
|
+
if (shouldWriteOpenCode && openCodePlan !== null && openCodePlan.body !== null) {
|
|
1960
|
+
mkdirSync(dirname(openCodePlan.status.path), { recursive: true });
|
|
1961
|
+
writeFileSync(openCodePlan.status.path, openCodePlan.body, "utf8");
|
|
1962
|
+
}
|
|
1475
1963
|
} catch (err) {
|
|
1476
1964
|
const msg = err instanceof Error ? err.message : String(err);
|
|
1477
1965
|
process.stderr.write(`agent-inspector onboard: failed to write files: ${msg}
|
|
@@ -1482,26 +1970,41 @@ No files were written.
|
|
|
1482
1970
|
const toolHint = firstTool !== null ? firstTool.displayName : "no known tool detected";
|
|
1483
1971
|
for (const file of filesToWrite) {
|
|
1484
1972
|
process.stdout.write(`Installed/updated ${file.label} to: ${file.path}
|
|
1973
|
+
`);
|
|
1974
|
+
}
|
|
1975
|
+
if (shouldWriteOpenCode && openCodePlan !== null) {
|
|
1976
|
+
process.stdout.write(`Installed/updated OpenCode MCP config: ${openCodePlan.status.path}
|
|
1485
1977
|
`);
|
|
1486
1978
|
}
|
|
1487
1979
|
process.stdout.write(`
|
|
1488
1980
|
Next steps:
|
|
1489
1981
|
`);
|
|
1490
|
-
if (!flags.codexOnly) {
|
|
1982
|
+
if (!flags.codexOnly && !flags.opencodeOnly) {
|
|
1491
1983
|
process.stdout.write(` - Open Claude Code and run: /agent-inspector:onboard
|
|
1492
1984
|
`);
|
|
1493
1985
|
}
|
|
1494
|
-
if (!flags.skipCodexSkill) {
|
|
1986
|
+
if (!flags.skipCodexSkill && !flags.opencodeOnly) {
|
|
1495
1987
|
process.stdout.write(` - Open Codex and ask to use the agent-inspector-onboard skill
|
|
1496
1988
|
`);
|
|
1497
1989
|
}
|
|
1498
|
-
|
|
1990
|
+
if (openCodePlan !== null) {
|
|
1991
|
+
process.stdout.write(` - Verify OpenCode MCP: opencode mcp list
|
|
1992
|
+
`);
|
|
1993
|
+
}
|
|
1994
|
+
if (flags.opencodeOnly) {
|
|
1995
|
+
process.stdout.write(
|
|
1996
|
+
` - Refresh OpenCode later: agent-inspector onboard --opencode-only --force
|
|
1997
|
+
`
|
|
1998
|
+
);
|
|
1999
|
+
} else {
|
|
2000
|
+
process.stdout.write(` - Refresh later: agent-inspector onboard --force
|
|
1499
2001
|
`);
|
|
1500
|
-
|
|
2002
|
+
process.stdout.write(` - Detected primary tool: ${toolHint}
|
|
1501
2003
|
`);
|
|
2004
|
+
}
|
|
1502
2005
|
return 0;
|
|
1503
2006
|
}
|
|
1504
|
-
var __filename, __dirname, DEFAULT_PORT, SKILL_DIR_NAME, SKILL_FILE_NAME, COMMAND_FILE_NAME, GENERATED_VERSION_PATTERN, FRONTMATTER_PATTERN, SEMVER_PATTERN;
|
|
2007
|
+
var __filename, __dirname, DEFAULT_PORT, DEFAULT_MCP_URL, SKILL_DIR_NAME, SKILL_FILE_NAME, COMMAND_FILE_NAME, GENERATED_VERSION_PATTERN, FRONTMATTER_PATTERN, SEMVER_PATTERN;
|
|
1505
2008
|
var init_onboard = __esm({
|
|
1506
2009
|
"src/cli/onboard.ts"() {
|
|
1507
2010
|
"use strict";
|
|
@@ -1512,6 +2015,7 @@ var init_onboard = __esm({
|
|
|
1512
2015
|
__filename = fileURLToPath(import.meta.url);
|
|
1513
2016
|
__dirname = dirname(__filename);
|
|
1514
2017
|
DEFAULT_PORT = 25947;
|
|
2018
|
+
DEFAULT_MCP_URL = `http://localhost:${DEFAULT_PORT}/api/mcp`;
|
|
1515
2019
|
SKILL_DIR_NAME = "agent-inspector-onboard";
|
|
1516
2020
|
SKILL_FILE_NAME = "SKILL.md";
|
|
1517
2021
|
COMMAND_FILE_NAME = process.platform === "win32" ? "agent-inspector-onboard.md" : "agent-inspector:onboard.md";
|