@robota-sdk/agent-cli 3.0.0-beta.33 → 3.0.0-beta.35

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.
@@ -40,7 +40,7 @@ module.exports = __toCommonJS(index_exports);
40
40
  var import_agent_sdk7 = require("@robota-sdk/agent-sdk");
41
41
 
42
42
  // src/cli.ts
43
- var import_node_fs3 = require("fs");
43
+ var import_node_fs4 = require("fs");
44
44
  var import_node_path5 = require("path");
45
45
  var import_node_url = require("url");
46
46
  var import_agent_sdk5 = require("@robota-sdk/agent-sdk");
@@ -179,11 +179,11 @@ var PrintTerminal = class {
179
179
  };
180
180
 
181
181
  // src/ui/render.tsx
182
- var import_ink12 = require("ink");
182
+ var import_ink14 = require("ink");
183
183
 
184
184
  // src/ui/App.tsx
185
- var import_react13 = require("react");
186
- var import_ink11 = require("ink");
185
+ var import_react16 = require("react");
186
+ var import_ink13 = require("ink");
187
187
  var import_agent_core3 = require("@robota-sdk/agent-core");
188
188
 
189
189
  // src/ui/hooks/useSession.ts
@@ -191,25 +191,69 @@ var import_react = require("react");
191
191
  var import_agent_sdk = require("@robota-sdk/agent-sdk");
192
192
 
193
193
  // src/utils/edit-diff.ts
194
- function generateDiffLines(oldStr, newStr) {
194
+ var import_node_fs2 = require("fs");
195
+ var CONTEXT_LINES = 2;
196
+ function generateDiffLines(oldStr, newStr, startLine = 1) {
195
197
  if (oldStr === newStr) return [];
196
198
  const lines = [];
197
- for (const line of oldStr.split("\n")) {
198
- lines.push({ type: "remove", text: line });
199
+ const oldLines = oldStr.split("\n");
200
+ const newLines = newStr.split("\n");
201
+ for (let i = 0; i < oldLines.length; i++) {
202
+ lines.push({ type: "remove", text: oldLines[i], lineNumber: startLine + i });
199
203
  }
200
- for (const line of newStr.split("\n")) {
201
- lines.push({ type: "add", text: line });
204
+ for (let i = 0; i < newLines.length; i++) {
205
+ lines.push({ type: "add", text: newLines[i], lineNumber: startLine + i });
202
206
  }
203
207
  return lines;
204
208
  }
205
- function extractEditDiff(toolName, toolArgs) {
209
+ function generateDiffLinesWithContext(oldStr, newStr, startLine, filePath) {
210
+ if (oldStr === newStr) return [];
211
+ const diffLines = generateDiffLines(oldStr, newStr, startLine);
212
+ let fileLines;
213
+ try {
214
+ fileLines = (0, import_node_fs2.readFileSync)(filePath, "utf-8").split("\n");
215
+ } catch {
216
+ return diffLines;
217
+ }
218
+ const result = [];
219
+ const contextStart = Math.max(0, startLine - 1 - CONTEXT_LINES);
220
+ for (let i = contextStart; i < startLine - 1; i++) {
221
+ if (i < fileLines.length) {
222
+ result.push({ type: "context", text: fileLines[i], lineNumber: i + 1 });
223
+ }
224
+ }
225
+ result.push(...diffLines);
226
+ const newLineCount = newStr.split("\n").length;
227
+ const afterStart = startLine - 1 + newLineCount;
228
+ for (let i = afterStart; i < afterStart + CONTEXT_LINES; i++) {
229
+ if (i < fileLines.length) {
230
+ result.push({ type: "context", text: fileLines[i], lineNumber: i + 1 });
231
+ }
232
+ }
233
+ return result;
234
+ }
235
+ function extractEditDiff(toolName, toolArgs, startLine) {
206
236
  if (toolName !== "Edit" || !toolArgs) return null;
207
237
  const filePath = toolArgs.file_path ?? toolArgs.filePath;
208
238
  const oldStr = toolArgs.old_string ?? toolArgs.oldString;
209
239
  const newStr = toolArgs.new_string ?? toolArgs.newString;
210
240
  if (typeof filePath !== "string") return null;
211
241
  if (typeof oldStr !== "string" || typeof newStr !== "string") return null;
212
- const lines = generateDiffLines(oldStr, newStr);
242
+ let sl = startLine ?? 0;
243
+ if (!sl) {
244
+ try {
245
+ const fileContent = (0, import_node_fs2.readFileSync)(filePath, "utf-8");
246
+ const idx = fileContent.indexOf(newStr);
247
+ if (idx >= 0) {
248
+ sl = fileContent.substring(0, idx).split("\n").length;
249
+ } else {
250
+ sl = 1;
251
+ }
252
+ } catch {
253
+ sl = 1;
254
+ }
255
+ }
256
+ const lines = generateDiffLinesWithContext(oldStr, newStr, sl, filePath);
213
257
  if (lines.length === 0) return null;
214
258
  return { file: filePath, lines };
215
259
  }
@@ -287,9 +331,20 @@ function useSession(props) {
287
331
  setActiveTools((prev) => {
288
332
  const updated = prev.map((t) => {
289
333
  if (!(t.toolName === event.toolName && t.isRunning)) return t;
334
+ let startLine;
335
+ if (event.toolResultData && event.toolName === "Edit") {
336
+ try {
337
+ const parsed = JSON.parse(event.toolResultData);
338
+ if (typeof parsed.startLine === "number") {
339
+ startLine = parsed.startLine;
340
+ }
341
+ } catch {
342
+ }
343
+ }
290
344
  const editDiff = extractEditDiff(
291
345
  event.toolName,
292
- t._toolArgs
346
+ t._toolArgs,
347
+ startLine
293
348
  );
294
349
  const finished = {
295
350
  ...t,
@@ -481,18 +536,9 @@ async function handlePluginCommand(args, addMessage, callbacks) {
481
536
  try {
482
537
  switch (subcommand) {
483
538
  case "":
484
- case void 0: {
485
- const plugins = await callbacks.listInstalled();
486
- if (plugins.length === 0) {
487
- addMessage({ role: "system", content: "No plugins installed." });
488
- } else {
489
- const lines = plugins.map(
490
- (p) => ` ${p.name} \u2014 ${p.description} [${p.enabled ? "enabled" : "disabled"}]`
491
- );
492
- addMessage({ role: "system", content: `Installed plugins:
493
- ${lines.join("\n")}` });
494
- }
495
- return { handled: true };
539
+ case void 0:
540
+ case "manage": {
541
+ return { handled: true, triggerPluginTUI: true };
496
542
  }
497
543
  case "install": {
498
544
  if (!subArgs) {
@@ -639,7 +685,7 @@ async function executeSlashCommand(cmd, args, session, addMessage, clearMessages
639
685
 
640
686
  // src/ui/hooks/useSlashCommands.ts
641
687
  var EXIT_DELAY_MS = 500;
642
- function useSlashCommands(session, addMessage, setMessages, exit, registry, pendingModelChangeRef, setPendingModelId, pluginCallbacks) {
688
+ function useSlashCommands(session, addMessage, setMessages, exit, registry, pendingModelChangeRef, setPendingModelId, pluginCallbacks, setShowPluginTUI) {
643
689
  return (0, import_react3.useCallback)(
644
690
  async (input) => {
645
691
  const parts = input.slice(1).split(/\s+/);
@@ -659,6 +705,9 @@ function useSlashCommands(session, addMessage, setMessages, exit, registry, pend
659
705
  pendingModelChangeRef.current = result.pendingModelId;
660
706
  setPendingModelId(result.pendingModelId);
661
707
  }
708
+ if (result.triggerPluginTUI) {
709
+ setShowPluginTUI?.(true);
710
+ }
662
711
  if (result.exitRequested) {
663
712
  setTimeout(() => exit(), EXIT_DELAY_MS);
664
713
  }
@@ -672,7 +721,8 @@ function useSlashCommands(session, addMessage, setMessages, exit, registry, pend
672
721
  registry,
673
722
  pendingModelChangeRef,
674
723
  setPendingModelId,
675
- pluginCallbacks
724
+ pluginCallbacks,
725
+ setShowPluginTUI
676
726
  ]
677
727
  );
678
728
  }
@@ -1056,22 +1106,7 @@ function createBuiltinCommands() {
1056
1106
  { name: "cost", description: "Show session info", source: "builtin" },
1057
1107
  { name: "context", description: "Context window info", source: "builtin" },
1058
1108
  { name: "permissions", description: "Permission rules", source: "builtin" },
1059
- {
1060
- name: "plugin",
1061
- description: "Manage plugins",
1062
- source: "builtin",
1063
- subcommands: [
1064
- { name: "install", description: "Install a plugin (name@marketplace)", source: "builtin" },
1065
- {
1066
- name: "uninstall",
1067
- description: "Uninstall a plugin (name@marketplace)",
1068
- source: "builtin"
1069
- },
1070
- { name: "enable", description: "Enable a plugin (name@marketplace)", source: "builtin" },
1071
- { name: "disable", description: "Disable a plugin (name@marketplace)", source: "builtin" },
1072
- { name: "marketplace", description: "Manage marketplace sources", source: "builtin" }
1073
- ]
1074
- },
1109
+ { name: "plugin", description: "Manage plugins", source: "builtin" },
1075
1110
  { name: "reload-plugins", description: "Reload all plugin resources", source: "builtin" },
1076
1111
  { name: "reset", description: "Delete settings and exit", source: "builtin" },
1077
1112
  { name: "exit", description: "Exit CLI", source: "builtin" }
@@ -1089,7 +1124,7 @@ var BuiltinCommandSource = class {
1089
1124
  };
1090
1125
 
1091
1126
  // src/commands/skill-source.ts
1092
- var import_node_fs2 = require("fs");
1127
+ var import_node_fs3 = require("fs");
1093
1128
  var import_node_path2 = require("path");
1094
1129
  var import_node_os = require("os");
1095
1130
  var BOOLEAN_KEYS = /* @__PURE__ */ new Set(["disable-model-invocation", "user-invocable"]);
@@ -1138,27 +1173,27 @@ function buildCommand(frontmatter, content, fallbackName) {
1138
1173
  return cmd;
1139
1174
  }
1140
1175
  function scanSkillsDir(skillsDir) {
1141
- if (!(0, import_node_fs2.existsSync)(skillsDir)) return [];
1176
+ if (!(0, import_node_fs3.existsSync)(skillsDir)) return [];
1142
1177
  const commands = [];
1143
- const entries = (0, import_node_fs2.readdirSync)(skillsDir, { withFileTypes: true });
1178
+ const entries = (0, import_node_fs3.readdirSync)(skillsDir, { withFileTypes: true });
1144
1179
  for (const entry of entries) {
1145
1180
  if (!entry.isDirectory()) continue;
1146
1181
  const skillFile = (0, import_node_path2.join)(skillsDir, entry.name, "SKILL.md");
1147
- if (!(0, import_node_fs2.existsSync)(skillFile)) continue;
1148
- const content = (0, import_node_fs2.readFileSync)(skillFile, "utf-8");
1182
+ if (!(0, import_node_fs3.existsSync)(skillFile)) continue;
1183
+ const content = (0, import_node_fs3.readFileSync)(skillFile, "utf-8");
1149
1184
  const frontmatter = parseFrontmatter(content);
1150
1185
  commands.push(buildCommand(frontmatter, content, entry.name));
1151
1186
  }
1152
1187
  return commands;
1153
1188
  }
1154
1189
  function scanCommandsDir(commandsDir) {
1155
- if (!(0, import_node_fs2.existsSync)(commandsDir)) return [];
1190
+ if (!(0, import_node_fs3.existsSync)(commandsDir)) return [];
1156
1191
  const commands = [];
1157
- const entries = (0, import_node_fs2.readdirSync)(commandsDir, { withFileTypes: true });
1192
+ const entries = (0, import_node_fs3.readdirSync)(commandsDir, { withFileTypes: true });
1158
1193
  for (const entry of entries) {
1159
1194
  if (!entry.isFile() || !entry.name.endsWith(".md")) continue;
1160
1195
  const filePath = (0, import_node_path2.join)(commandsDir, entry.name);
1161
- const content = (0, import_node_fs2.readFileSync)(filePath, "utf-8");
1196
+ const content = (0, import_node_fs3.readFileSync)(filePath, "utf-8");
1162
1197
  const frontmatter = parseFrontmatter(content);
1163
1198
  const fallbackName = (0, import_node_path2.basename)(entry.name, ".md");
1164
1199
  commands.push(buildCommand(frontmatter, content, fallbackName));
@@ -1338,18 +1373,50 @@ function usePluginCallbacks(cwd) {
1338
1373
  return {
1339
1374
  listInstalled: async () => {
1340
1375
  const plugins = await loader.loadAll();
1341
- return plugins.map((p) => ({
1342
- name: p.manifest.name,
1343
- description: p.manifest.description,
1344
- enabled: true
1376
+ const enabledMap = settingsStore.getEnabledPlugins();
1377
+ return plugins.map((p) => {
1378
+ const parts = p.pluginDir.split("/");
1379
+ const cacheIdx = parts.indexOf("cache");
1380
+ const marketplaceName = cacheIdx >= 0 ? parts[cacheIdx + 1] : "";
1381
+ const fullId = marketplaceName ? `${p.manifest.name}@${marketplaceName}` : p.manifest.name;
1382
+ return {
1383
+ name: fullId,
1384
+ description: p.manifest.description,
1385
+ enabled: enabledMap[fullId] !== false && enabledMap[p.manifest.name] !== false
1386
+ };
1387
+ });
1388
+ },
1389
+ listAvailablePlugins: async (marketplaceName) => {
1390
+ let manifest;
1391
+ try {
1392
+ manifest = marketplace.fetchManifest(marketplaceName);
1393
+ } catch {
1394
+ return [];
1395
+ }
1396
+ const installed = installer.getInstalledPlugins();
1397
+ const installedNames = new Set(Object.values(installed).map((r) => r.pluginName));
1398
+ return manifest.plugins.map((p) => ({
1399
+ name: p.name,
1400
+ description: p.description,
1401
+ installed: installedNames.has(p.name)
1345
1402
  }));
1346
1403
  },
1347
- install: async (pluginId) => {
1404
+ install: async (pluginId, scope) => {
1348
1405
  const [name, marketplaceName] = pluginId.split("@");
1349
1406
  if (!name || !marketplaceName) {
1350
1407
  throw new Error("Plugin ID must be in format: name@marketplace");
1351
1408
  }
1352
- await installer.install(name, marketplaceName);
1409
+ if (scope === "project") {
1410
+ const projectPluginsDir = (0, import_node_path4.join)(cwd, ".robota", "plugins");
1411
+ const projectInstaller = new import_agent_sdk4.BundlePluginInstaller({
1412
+ pluginsDir: projectPluginsDir,
1413
+ settingsStore,
1414
+ marketplaceClient: marketplace
1415
+ });
1416
+ await projectInstaller.install(name, marketplaceName);
1417
+ } else {
1418
+ await installer.install(name, marketplaceName);
1419
+ }
1353
1420
  },
1354
1421
  uninstall: async (pluginId) => {
1355
1422
  await installer.uninstall(pluginId);
@@ -1407,23 +1474,41 @@ function renderMarkdown(md) {
1407
1474
  // src/ui/DiffBlock.tsx
1408
1475
  var import_ink = require("ink");
1409
1476
  var import_jsx_runtime = require("react/jsx-runtime");
1410
- var MAX_DIFF_LINES = 10;
1411
- var TRUNCATED_SHOW = 8;
1477
+ var MAX_DIFF_LINES = 12;
1478
+ var TRUNCATED_SHOW = 10;
1412
1479
  function DiffBlock({ file, lines }) {
1413
1480
  const truncated = lines.length > MAX_DIFF_LINES;
1414
1481
  const visible = truncated ? lines.slice(0, TRUNCATED_SHOW) : lines;
1415
1482
  const remaining = lines.length - TRUNCATED_SHOW;
1483
+ const maxLineNum = Math.max(...visible.map((l) => l.lineNumber), 0);
1484
+ const numWidth = String(maxLineNum).length;
1416
1485
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink.Box, { flexDirection: "column", marginLeft: 4, children: [
1417
1486
  file && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink.Text, { color: "white", dimColor: true, children: [
1418
1487
  "\u2502 ",
1419
1488
  file
1420
1489
  ] }),
1421
- visible.map((line, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink.Text, { color: line.type === "remove" ? "red" : "greenBright", children: [
1422
- "\u2502 ",
1423
- line.type === "remove" ? "-" : "+",
1424
- " ",
1425
- line.text
1426
- ] }, i)),
1490
+ visible.map((line, i) => {
1491
+ const lineNum = String(line.lineNumber).padStart(numWidth, " ");
1492
+ if (line.type === "context") {
1493
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink.Text, { color: "white", dimColor: true, children: [
1494
+ "\u2502 ",
1495
+ lineNum,
1496
+ " ",
1497
+ line.text
1498
+ ] }, i);
1499
+ }
1500
+ const prefix = line.type === "remove" ? "-" : "+";
1501
+ const bgColor = line.type === "remove" ? "#5c1a1a" : "#1a3d1a";
1502
+ const fgColor = line.type === "remove" ? "#ff9999" : "#99ff99";
1503
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink.Text, { color: fgColor, backgroundColor: bgColor, children: [
1504
+ "\u2502 ",
1505
+ lineNum,
1506
+ " ",
1507
+ prefix,
1508
+ " ",
1509
+ line.text
1510
+ ] }, i);
1511
+ }),
1427
1512
  truncated && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink.Text, { color: "white", dimColor: true, children: [
1428
1513
  "\u2502 ... and ",
1429
1514
  remaining,
@@ -2076,8 +2161,459 @@ function StreamingIndicator({ text, activeTools }) {
2076
2161
  ] });
2077
2162
  }
2078
2163
 
2079
- // src/ui/App.tsx
2164
+ // src/ui/PluginTUI.tsx
2165
+ var import_react15 = require("react");
2166
+
2167
+ // src/ui/MenuSelect.tsx
2168
+ var import_react13 = require("react");
2169
+ var import_ink11 = require("ink");
2080
2170
  var import_jsx_runtime11 = require("react/jsx-runtime");
2171
+ function MenuSelect({
2172
+ title,
2173
+ items,
2174
+ onSelect,
2175
+ onBack,
2176
+ loading,
2177
+ error
2178
+ }) {
2179
+ const [selected, setSelected] = (0, import_react13.useState)(0);
2180
+ const selectedRef = (0, import_react13.useRef)(0);
2181
+ const resolvedRef = (0, import_react13.useRef)(false);
2182
+ const doSelect = (0, import_react13.useCallback)(
2183
+ (index) => {
2184
+ if (resolvedRef.current || items.length === 0) return;
2185
+ resolvedRef.current = true;
2186
+ onSelect(items[index].value);
2187
+ },
2188
+ [items, onSelect]
2189
+ );
2190
+ (0, import_ink11.useInput)((input, key) => {
2191
+ if (resolvedRef.current) return;
2192
+ if (key.escape) {
2193
+ resolvedRef.current = true;
2194
+ onBack();
2195
+ return;
2196
+ }
2197
+ if (loading || error || items.length === 0) return;
2198
+ if (key.upArrow) {
2199
+ const next = selectedRef.current > 0 ? selectedRef.current - 1 : selectedRef.current;
2200
+ selectedRef.current = next;
2201
+ setSelected(next);
2202
+ } else if (key.downArrow) {
2203
+ const next = selectedRef.current < items.length - 1 ? selectedRef.current + 1 : selectedRef.current;
2204
+ selectedRef.current = next;
2205
+ setSelected(next);
2206
+ } else if (key.return) {
2207
+ doSelect(selectedRef.current);
2208
+ }
2209
+ });
2210
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_ink11.Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
2211
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_ink11.Text, { color: "yellow", bold: true, children: title }),
2212
+ loading && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_ink11.Box, { marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_ink11.Text, { dimColor: true, children: "Loading..." }) }),
2213
+ error && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_ink11.Box, { marginTop: 1, flexDirection: "column", children: [
2214
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_ink11.Text, { color: "red", children: error }),
2215
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_ink11.Text, { dimColor: true, children: "Press Esc to go back" })
2216
+ ] }),
2217
+ !loading && !error && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_ink11.Box, { flexDirection: "column", marginTop: 1, children: items.map((item, i) => /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_ink11.Box, { children: [
2218
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_ink11.Text, { color: i === selected ? "cyan" : void 0, bold: i === selected, children: [
2219
+ i === selected ? "> " : " ",
2220
+ item.label
2221
+ ] }),
2222
+ item.hint && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_ink11.Text, { dimColor: true, children: [
2223
+ " ",
2224
+ item.hint
2225
+ ] })
2226
+ ] }, item.value)) }),
2227
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_ink11.Text, { dimColor: true, children: loading || error ? "" : " \u2191\u2193 Navigate Enter Select Esc Back" })
2228
+ ] });
2229
+ }
2230
+
2231
+ // src/ui/TextPrompt.tsx
2232
+ var import_react14 = require("react");
2233
+ var import_ink12 = require("ink");
2234
+ var import_jsx_runtime12 = require("react/jsx-runtime");
2235
+ function TextPrompt({
2236
+ title,
2237
+ placeholder,
2238
+ onSubmit,
2239
+ onCancel,
2240
+ validate
2241
+ }) {
2242
+ const [value, setValue] = (0, import_react14.useState)("");
2243
+ const [error, setError] = (0, import_react14.useState)();
2244
+ const resolvedRef = (0, import_react14.useRef)(false);
2245
+ const valueRef = (0, import_react14.useRef)("");
2246
+ const handleSubmit = (0, import_react14.useCallback)(() => {
2247
+ if (resolvedRef.current) return;
2248
+ const trimmed = valueRef.current.trim();
2249
+ if (!trimmed) return;
2250
+ if (validate) {
2251
+ const err = validate(trimmed);
2252
+ if (err) {
2253
+ setError(err);
2254
+ return;
2255
+ }
2256
+ }
2257
+ resolvedRef.current = true;
2258
+ onSubmit(trimmed);
2259
+ }, [validate, onSubmit]);
2260
+ (0, import_ink12.useInput)((input, key) => {
2261
+ if (resolvedRef.current) return;
2262
+ if (key.escape) {
2263
+ resolvedRef.current = true;
2264
+ onCancel();
2265
+ return;
2266
+ }
2267
+ if (key.return) {
2268
+ handleSubmit();
2269
+ return;
2270
+ }
2271
+ if (key.backspace || key.delete) {
2272
+ valueRef.current = valueRef.current.slice(0, -1);
2273
+ setValue(valueRef.current);
2274
+ setError(void 0);
2275
+ return;
2276
+ }
2277
+ if (input && !key.ctrl && !key.meta) {
2278
+ valueRef.current = valueRef.current + input;
2279
+ setValue(valueRef.current);
2280
+ setError(void 0);
2281
+ }
2282
+ });
2283
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_ink12.Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
2284
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_ink12.Text, { color: "yellow", bold: true, children: title }),
2285
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_ink12.Box, { marginTop: 1, children: [
2286
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_ink12.Text, { color: "cyan", children: "> " }),
2287
+ value ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_ink12.Text, { children: value }) : placeholder ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_ink12.Text, { dimColor: true, children: placeholder }) : null,
2288
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_ink12.Text, { color: "cyan", children: "\u2588" })
2289
+ ] }),
2290
+ error && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_ink12.Text, { color: "red", children: error }),
2291
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_ink12.Text, { dimColor: true, children: " Enter Submit Esc Cancel" })
2292
+ ] });
2293
+ }
2294
+
2295
+ // src/ui/plugin-tui-handlers.ts
2296
+ function handleMainSelect(value, nav) {
2297
+ if (value === "marketplace") {
2298
+ nav.push({ screen: "marketplace-list" });
2299
+ } else if (value === "installed") {
2300
+ nav.push({ screen: "installed-list" });
2301
+ }
2302
+ }
2303
+ function handleMarketplaceListSelect(value, nav) {
2304
+ if (value === "__add__") {
2305
+ nav.push({ screen: "marketplace-add" });
2306
+ } else {
2307
+ nav.push({ screen: "marketplace-action", context: { marketplace: value } });
2308
+ }
2309
+ }
2310
+ function handleMarketplaceActionSelect(value, marketplace, callbacks, nav) {
2311
+ if (value === "browse") {
2312
+ nav.push({ screen: "marketplace-browse", context: { marketplace } });
2313
+ } else if (value === "update") {
2314
+ callbacks.marketplaceUpdate(marketplace).then(() => {
2315
+ nav.notify(`Updated marketplace "${marketplace}".`);
2316
+ nav.pop();
2317
+ }).catch((err) => {
2318
+ nav.notify(`Error: ${err instanceof Error ? err.message : String(err)}`);
2319
+ });
2320
+ } else if (value === "remove") {
2321
+ nav.setConfirm({
2322
+ message: `Remove marketplace "${marketplace}" and all its plugins?`,
2323
+ onConfirm: () => {
2324
+ nav.setConfirm(void 0);
2325
+ callbacks.marketplaceRemove(marketplace).then(() => {
2326
+ nav.notify(`Removed marketplace "${marketplace}".`);
2327
+ nav.popN(2);
2328
+ }).catch((err) => {
2329
+ nav.notify(`Error: ${err instanceof Error ? err.message : String(err)}`);
2330
+ });
2331
+ },
2332
+ onCancel: () => nav.setConfirm(void 0)
2333
+ });
2334
+ }
2335
+ }
2336
+ function handleMarketplaceBrowseSelect(value, marketplace, items, nav) {
2337
+ const fullId = `${value}@${marketplace}`;
2338
+ const item = items.find((i) => i.value === value);
2339
+ if (item?.hint === "installed") {
2340
+ nav.push({ screen: "installed-action", context: { pluginId: fullId } });
2341
+ } else {
2342
+ nav.push({ screen: "marketplace-install-scope", context: { marketplace, pluginId: fullId } });
2343
+ }
2344
+ }
2345
+ function handleInstallScopeSelect(value, pluginId, callbacks, nav) {
2346
+ const scope = value;
2347
+ callbacks.install(pluginId, scope).then(() => {
2348
+ nav.notify(`Installed plugin "${pluginId}" (${scope} scope).`);
2349
+ nav.popN(2);
2350
+ }).catch((err) => {
2351
+ nav.notify(`Error: ${err instanceof Error ? err.message : String(err)}`);
2352
+ });
2353
+ }
2354
+ function handleInstalledListSelect(value, callbacks, nav) {
2355
+ nav.setConfirm({
2356
+ message: `Uninstall plugin "${value}"?`,
2357
+ onConfirm: () => {
2358
+ nav.setConfirm(void 0);
2359
+ callbacks.uninstall(value).then(() => {
2360
+ nav.notify(`Uninstalled plugin "${value}".`);
2361
+ nav.refresh();
2362
+ }).catch((err) => {
2363
+ nav.notify(`Error: ${err instanceof Error ? err.message : String(err)}`);
2364
+ });
2365
+ },
2366
+ onCancel: () => nav.setConfirm(void 0)
2367
+ });
2368
+ }
2369
+ function handleInstalledActionSelect(value, pluginId, callbacks, nav) {
2370
+ if (value === "uninstall") {
2371
+ nav.setConfirm({
2372
+ message: `Uninstall plugin "${pluginId}"?`,
2373
+ onConfirm: () => {
2374
+ nav.setConfirm(void 0);
2375
+ callbacks.uninstall(pluginId).then(() => {
2376
+ nav.notify(`Uninstalled plugin "${pluginId}".`);
2377
+ nav.popN(2);
2378
+ }).catch((err) => {
2379
+ nav.notify(`Error: ${err instanceof Error ? err.message : String(err)}`);
2380
+ });
2381
+ },
2382
+ onCancel: () => nav.setConfirm(void 0)
2383
+ });
2384
+ }
2385
+ }
2386
+
2387
+ // src/ui/PluginTUI.tsx
2388
+ var import_jsx_runtime13 = require("react/jsx-runtime");
2389
+ function PluginTUI({ callbacks, onClose, addMessage }) {
2390
+ const [stack, setStack] = (0, import_react15.useState)([{ screen: "main" }]);
2391
+ const [items, setItems] = (0, import_react15.useState)([]);
2392
+ const [loading, setLoading] = (0, import_react15.useState)(false);
2393
+ const [error, setError] = (0, import_react15.useState)();
2394
+ const [confirm, setConfirm] = (0, import_react15.useState)();
2395
+ const [refreshCounter, setRefreshCounter] = (0, import_react15.useState)(0);
2396
+ const current = stack[stack.length - 1] ?? { screen: "main" };
2397
+ const push = (0, import_react15.useCallback)((state) => {
2398
+ setStack((prev) => [...prev, state]);
2399
+ setItems([]);
2400
+ setError(void 0);
2401
+ }, []);
2402
+ const pop = (0, import_react15.useCallback)(() => {
2403
+ setStack((prev) => {
2404
+ if (prev.length <= 1) {
2405
+ onClose();
2406
+ return prev;
2407
+ }
2408
+ return prev.slice(0, -1);
2409
+ });
2410
+ setItems([]);
2411
+ setError(void 0);
2412
+ }, [onClose]);
2413
+ const popN = (0, import_react15.useCallback)(
2414
+ (n) => {
2415
+ setStack((prev) => {
2416
+ const next = prev.slice(0, Math.max(1, prev.length - n));
2417
+ if (next.length === 0) {
2418
+ onClose();
2419
+ return prev;
2420
+ }
2421
+ return next;
2422
+ });
2423
+ setItems([]);
2424
+ setError(void 0);
2425
+ },
2426
+ [onClose]
2427
+ );
2428
+ const notify = (0, import_react15.useCallback)(
2429
+ (content) => {
2430
+ addMessage?.({ role: "system", content });
2431
+ },
2432
+ [addMessage]
2433
+ );
2434
+ const refresh = (0, import_react15.useCallback)(() => {
2435
+ setItems([]);
2436
+ setRefreshCounter((c) => c + 1);
2437
+ }, []);
2438
+ const nav = { push, pop, popN, notify, setConfirm, refresh };
2439
+ (0, import_react15.useEffect)(() => {
2440
+ const screen2 = current.screen;
2441
+ if (screen2 === "marketplace-list") {
2442
+ setLoading(true);
2443
+ callbacks.marketplaceList().then((sources) => {
2444
+ const baseItems = [{ label: "Add Marketplace", value: "__add__" }];
2445
+ const sourceItems = sources.map((s) => ({
2446
+ label: s.name,
2447
+ value: s.name,
2448
+ hint: s.type
2449
+ }));
2450
+ setItems([...baseItems, ...sourceItems]);
2451
+ setLoading(false);
2452
+ }).catch((err) => {
2453
+ setError(err instanceof Error ? err.message : String(err));
2454
+ setLoading(false);
2455
+ });
2456
+ } else if (screen2 === "marketplace-browse") {
2457
+ const marketplace = current.context?.marketplace ?? "";
2458
+ setLoading(true);
2459
+ callbacks.listAvailablePlugins(marketplace).then((plugins) => {
2460
+ setItems(
2461
+ plugins.map((p) => ({
2462
+ label: p.name,
2463
+ value: p.name,
2464
+ hint: p.installed ? "installed" : p.description
2465
+ }))
2466
+ );
2467
+ setLoading(false);
2468
+ }).catch((err) => {
2469
+ setError(err instanceof Error ? err.message : String(err));
2470
+ setLoading(false);
2471
+ });
2472
+ } else if (screen2 === "installed-list") {
2473
+ setLoading(true);
2474
+ callbacks.listInstalled().then((plugins) => {
2475
+ setItems(
2476
+ plugins.map((p) => ({
2477
+ label: p.name,
2478
+ value: p.name,
2479
+ hint: p.description
2480
+ }))
2481
+ );
2482
+ setLoading(false);
2483
+ }).catch((err) => {
2484
+ setError(err instanceof Error ? err.message : String(err));
2485
+ setLoading(false);
2486
+ });
2487
+ }
2488
+ }, [stack.length, current.screen, current.context?.marketplace, callbacks, refreshCounter]);
2489
+ const handleSelect = (0, import_react15.useCallback)(
2490
+ (value) => {
2491
+ const screen2 = current.screen;
2492
+ const ctx = current.context;
2493
+ if (screen2 === "main") handleMainSelect(value, nav);
2494
+ else if (screen2 === "marketplace-list") handleMarketplaceListSelect(value, nav);
2495
+ else if (screen2 === "marketplace-action")
2496
+ handleMarketplaceActionSelect(value, ctx?.marketplace ?? "", callbacks, nav);
2497
+ else if (screen2 === "marketplace-browse")
2498
+ handleMarketplaceBrowseSelect(value, ctx?.marketplace ?? "", items, nav);
2499
+ else if (screen2 === "marketplace-install-scope")
2500
+ handleInstallScopeSelect(value, ctx?.pluginId ?? "", callbacks, nav);
2501
+ else if (screen2 === "installed-list") handleInstalledListSelect(value, callbacks, nav);
2502
+ else if (screen2 === "installed-action")
2503
+ handleInstalledActionSelect(value, ctx?.pluginId ?? "", callbacks, nav);
2504
+ },
2505
+ [current, items, callbacks, push, pop, popN, notify, setConfirm, refresh]
2506
+ );
2507
+ const handleTextSubmit = (0, import_react15.useCallback)(
2508
+ (value) => {
2509
+ if (current.screen === "marketplace-add") {
2510
+ callbacks.marketplaceAdd(value).then((name) => {
2511
+ notify(`Added marketplace "${name}" from ${value}.`);
2512
+ pop();
2513
+ }).catch((err) => {
2514
+ notify(`Error: ${err instanceof Error ? err.message : String(err)}`);
2515
+ pop();
2516
+ });
2517
+ }
2518
+ },
2519
+ [current.screen, callbacks, notify, pop]
2520
+ );
2521
+ if (confirm) {
2522
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2523
+ ConfirmPrompt,
2524
+ {
2525
+ message: confirm.message,
2526
+ onSelect: (index) => {
2527
+ if (index === 0) confirm.onConfirm();
2528
+ else confirm.onCancel();
2529
+ }
2530
+ }
2531
+ );
2532
+ }
2533
+ const screen = current.screen;
2534
+ if (screen === "marketplace-add") {
2535
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2536
+ TextPrompt,
2537
+ {
2538
+ title: "Add Marketplace Source",
2539
+ placeholder: "owner/repo or git URL",
2540
+ onSubmit: handleTextSubmit,
2541
+ onCancel: pop,
2542
+ validate: (v) => !v.includes("/") ? "Must be owner/repo or a git URL" : void 0
2543
+ }
2544
+ );
2545
+ }
2546
+ if (screen === "marketplace-action") {
2547
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2548
+ MenuSelect,
2549
+ {
2550
+ title: `Marketplace: ${current.context?.marketplace ?? ""}`,
2551
+ items: [
2552
+ { label: "Browse plugins", value: "browse" },
2553
+ { label: "Update", value: "update" },
2554
+ { label: "Remove", value: "remove" }
2555
+ ],
2556
+ onSelect: handleSelect,
2557
+ onBack: pop
2558
+ },
2559
+ stack.length
2560
+ );
2561
+ }
2562
+ if (screen === "marketplace-install-scope") {
2563
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2564
+ MenuSelect,
2565
+ {
2566
+ title: `Install scope for "${current.context?.pluginId ?? ""}"`,
2567
+ items: [
2568
+ { label: "User scope", value: "user" },
2569
+ { label: "Project scope", value: "project" }
2570
+ ],
2571
+ onSelect: handleSelect,
2572
+ onBack: pop
2573
+ },
2574
+ stack.length
2575
+ );
2576
+ }
2577
+ if (screen === "installed-action") {
2578
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2579
+ MenuSelect,
2580
+ {
2581
+ title: `Plugin: ${current.context?.pluginId ?? ""}`,
2582
+ items: [{ label: "Uninstall", value: "uninstall" }],
2583
+ onSelect: handleSelect,
2584
+ onBack: pop
2585
+ },
2586
+ stack.length
2587
+ );
2588
+ }
2589
+ const titleMap = {
2590
+ main: "Plugin Management",
2591
+ "marketplace-list": "Marketplace",
2592
+ "marketplace-browse": `Browse: ${current.context?.marketplace ?? ""}`,
2593
+ "installed-list": "Installed Plugins"
2594
+ };
2595
+ const staticItemsMap = {
2596
+ main: [
2597
+ { label: "Marketplace", value: "marketplace" },
2598
+ { label: "Installed Plugins", value: "installed" }
2599
+ ]
2600
+ };
2601
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2602
+ MenuSelect,
2603
+ {
2604
+ title: titleMap[screen] ?? "Plugin Management",
2605
+ items: staticItemsMap[screen] ?? items,
2606
+ onSelect: handleSelect,
2607
+ onBack: pop,
2608
+ loading,
2609
+ error
2610
+ },
2611
+ `${screen}-${stack.length}-${refreshCounter}`
2612
+ );
2613
+ }
2614
+
2615
+ // src/ui/App.tsx
2616
+ var import_jsx_runtime14 = require("react/jsx-runtime");
2081
2617
  var EXIT_DELAY_MS2 = 500;
2082
2618
  function mergeHooksIntoConfig(configHooks, pluginHooks) {
2083
2619
  const pluginKeys = Object.keys(pluginHooks);
@@ -2096,7 +2632,7 @@ function mergeHooksIntoConfig(configHooks, pluginHooks) {
2096
2632
  return merged;
2097
2633
  }
2098
2634
  function App(props) {
2099
- const { exit } = (0, import_ink11.useApp)();
2635
+ const { exit } = (0, import_ink13.useApp)();
2100
2636
  const { registry, pluginHooks } = useCommandRegistry(props.cwd ?? process.cwd());
2101
2637
  const configWithPluginHooks = {
2102
2638
  ...props.config,
@@ -2109,15 +2645,16 @@ function App(props) {
2109
2645
  { ...props, config: configWithPluginHooks }
2110
2646
  );
2111
2647
  const { messages, setMessages, addMessage } = useMessages();
2112
- const [isThinking, setIsThinking] = (0, import_react13.useState)(false);
2648
+ const [isThinking, setIsThinking] = (0, import_react16.useState)(false);
2113
2649
  const initialCtx = session.getContextState();
2114
- const [contextState, setContextState] = (0, import_react13.useState)({
2650
+ const [contextState, setContextState] = (0, import_react16.useState)({
2115
2651
  percentage: initialCtx.usedPercentage,
2116
2652
  usedTokens: initialCtx.usedTokens,
2117
2653
  maxTokens: initialCtx.maxTokens
2118
2654
  });
2119
- const pendingModelChangeRef = (0, import_react13.useRef)(null);
2120
- const [pendingModelId, setPendingModelId] = (0, import_react13.useState)(null);
2655
+ const pendingModelChangeRef = (0, import_react16.useRef)(null);
2656
+ const [pendingModelId, setPendingModelId] = (0, import_react16.useState)(null);
2657
+ const [showPluginTUI, setShowPluginTUI] = (0, import_react16.useState)(false);
2121
2658
  const pluginCallbacks = usePluginCallbacks(props.cwd ?? process.cwd());
2122
2659
  const handleSlashCommand = useSlashCommands(
2123
2660
  session,
@@ -2127,7 +2664,8 @@ function App(props) {
2127
2664
  registry,
2128
2665
  pendingModelChangeRef,
2129
2666
  setPendingModelId,
2130
- pluginCallbacks
2667
+ pluginCallbacks,
2668
+ setShowPluginTUI
2131
2669
  );
2132
2670
  const handleSubmit = useSubmitHandler(
2133
2671
  session,
@@ -2138,33 +2676,33 @@ function App(props) {
2138
2676
  setContextState,
2139
2677
  registry
2140
2678
  );
2141
- (0, import_ink11.useInput)(
2679
+ (0, import_ink13.useInput)(
2142
2680
  (_input, key) => {
2143
2681
  if (key.ctrl && _input === "c") exit();
2144
2682
  if (key.escape && isThinking) session.abort();
2145
2683
  },
2146
- { isActive: !permissionRequest }
2684
+ { isActive: !permissionRequest && !showPluginTUI }
2147
2685
  );
2148
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_ink11.Box, { flexDirection: "column", children: [
2149
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_ink11.Box, { flexDirection: "column", paddingX: 1, marginBottom: 1, children: [
2150
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_ink11.Text, { color: "cyan", bold: true, children: `
2686
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_ink13.Box, { flexDirection: "column", children: [
2687
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_ink13.Box, { flexDirection: "column", paddingX: 1, marginBottom: 1, children: [
2688
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_ink13.Text, { color: "cyan", bold: true, children: `
2151
2689
  ____ ___ ____ ___ _____ _
2152
2690
  | _ \\ / _ \\| __ ) / _ \\_ _|/ \\
2153
2691
  | |_) | | | | _ \\| | | || | / _ \\
2154
2692
  | _ <| |_| | |_) | |_| || |/ ___ \\
2155
2693
  |_| \\_\\\\___/|____/ \\___/ |_/_/ \\_\\
2156
2694
  ` }),
2157
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_ink11.Text, { dimColor: true, children: [
2695
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_ink13.Text, { dimColor: true, children: [
2158
2696
  " v",
2159
2697
  props.version ?? "0.0.0"
2160
2698
  ] })
2161
2699
  ] }),
2162
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_ink11.Box, { flexDirection: "column", paddingX: 1, flexGrow: 1, children: [
2163
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(MessageList, { messages }),
2164
- isThinking && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_ink11.Box, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(StreamingIndicator, { text: streamingText, activeTools }) })
2700
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_ink13.Box, { flexDirection: "column", paddingX: 1, flexGrow: 1, children: [
2701
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(MessageList, { messages }),
2702
+ isThinking && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_ink13.Box, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(StreamingIndicator, { text: streamingText, activeTools }) })
2165
2703
  ] }),
2166
- permissionRequest && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(PermissionPrompt, { request: permissionRequest }),
2167
- pendingModelId && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2704
+ permissionRequest && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(PermissionPrompt, { request: permissionRequest }),
2705
+ pendingModelId && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2168
2706
  ConfirmPrompt,
2169
2707
  {
2170
2708
  message: `Change model to ${(0, import_agent_core3.getModelName)(pendingModelId)}? This will restart the session.`,
@@ -2192,7 +2730,15 @@ function App(props) {
2192
2730
  }
2193
2731
  }
2194
2732
  ),
2195
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2733
+ showPluginTUI && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2734
+ PluginTUI,
2735
+ {
2736
+ callbacks: pluginCallbacks,
2737
+ onClose: () => setShowPluginTUI(false),
2738
+ addMessage: (msg) => addMessage(msg)
2739
+ }
2740
+ ),
2741
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2196
2742
  StatusBar,
2197
2743
  {
2198
2744
  permissionMode: session.getPermissionMode(),
@@ -2205,20 +2751,20 @@ function App(props) {
2205
2751
  contextMaxTokens: contextState.maxTokens
2206
2752
  }
2207
2753
  ),
2208
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2754
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2209
2755
  InputArea,
2210
2756
  {
2211
2757
  onSubmit: handleSubmit,
2212
- isDisabled: isThinking || !!permissionRequest,
2758
+ isDisabled: isThinking || !!permissionRequest || showPluginTUI,
2213
2759
  registry
2214
2760
  }
2215
2761
  ),
2216
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_ink11.Text, { children: " " })
2762
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_ink13.Text, { children: " " })
2217
2763
  ] });
2218
2764
  }
2219
2765
 
2220
2766
  // src/ui/render.tsx
2221
- var import_jsx_runtime12 = require("react/jsx-runtime");
2767
+ var import_jsx_runtime15 = require("react/jsx-runtime");
2222
2768
  function renderApp(options) {
2223
2769
  process.on("unhandledRejection", (reason) => {
2224
2770
  process.stderr.write(`
@@ -2229,7 +2775,7 @@ function renderApp(options) {
2229
2775
  `);
2230
2776
  }
2231
2777
  });
2232
- const instance = (0, import_ink12.render)(/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(App, { ...options }), {
2778
+ const instance = (0, import_ink14.render)(/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(App, { ...options }), {
2233
2779
  exitOnCtrlC: true
2234
2780
  });
2235
2781
  instance.waitUntilExit().catch((err) => {
@@ -2244,9 +2790,9 @@ function renderApp(options) {
2244
2790
  // src/cli.ts
2245
2791
  var import_meta = {};
2246
2792
  function checkSettingsFile(filePath) {
2247
- if (!(0, import_node_fs3.existsSync)(filePath)) return "missing";
2793
+ if (!(0, import_node_fs4.existsSync)(filePath)) return "missing";
2248
2794
  try {
2249
- const raw = (0, import_node_fs3.readFileSync)(filePath, "utf8").trim();
2795
+ const raw = (0, import_node_fs4.readFileSync)(filePath, "utf8").trim();
2250
2796
  if (raw.length === 0) return "incomplete";
2251
2797
  const parsed = JSON.parse(raw);
2252
2798
  const provider = parsed.provider;
@@ -2263,7 +2809,7 @@ function readVersion() {
2263
2809
  const candidates = [(0, import_node_path5.join)(dir, "..", "..", "package.json"), (0, import_node_path5.join)(dir, "..", "package.json")];
2264
2810
  for (const pkgPath of candidates) {
2265
2811
  try {
2266
- const raw = (0, import_node_fs3.readFileSync)(pkgPath, "utf-8");
2812
+ const raw = (0, import_node_fs4.readFileSync)(pkgPath, "utf-8");
2267
2813
  const pkg = JSON.parse(raw);
2268
2814
  if (pkg.version !== void 0 && pkg.name !== void 0) {
2269
2815
  return pkg.version;
@@ -2351,7 +2897,7 @@ async function ensureConfig(cwd) {
2351
2897
  }
2352
2898
  const language = await promptInput(" Response language (ko/en/ja/zh, default: en): ");
2353
2899
  const settingsDir = (0, import_node_path5.dirname)(userPath);
2354
- (0, import_node_fs3.mkdirSync)(settingsDir, { recursive: true });
2900
+ (0, import_node_fs4.mkdirSync)(settingsDir, { recursive: true });
2355
2901
  const settings = {
2356
2902
  provider: {
2357
2903
  name: "anthropic",
@@ -2362,7 +2908,7 @@ async function ensureConfig(cwd) {
2362
2908
  if (language) {
2363
2909
  settings.language = language;
2364
2910
  }
2365
- (0, import_node_fs3.writeFileSync)(userPath, JSON.stringify(settings, null, 2) + "\n", "utf8");
2911
+ (0, import_node_fs4.writeFileSync)(userPath, JSON.stringify(settings, null, 2) + "\n", "utf8");
2366
2912
  process.stdout.write(`
2367
2913
  Config saved to ${userPath}
2368
2914