@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.
- package/dist/node/bin.cjs +639 -93
- package/dist/node/bin.js +1 -1
- package/dist/node/{chunk-EPCRZIQ6.js → chunk-27OPEZHA.js} +629 -83
- package/dist/node/index.cjs +639 -93
- package/dist/node/index.js +1 -1
- package/package.json +3 -3
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/cli.ts
|
|
2
|
-
import { readFileSync as
|
|
2
|
+
import { readFileSync as readFileSync4, existsSync as existsSync3, mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
3
3
|
import { join as join5, dirname as dirname3 } from "path";
|
|
4
4
|
import { fileURLToPath } from "url";
|
|
5
5
|
import {
|
|
@@ -149,8 +149,8 @@ var PrintTerminal = class {
|
|
|
149
149
|
import { render } from "ink";
|
|
150
150
|
|
|
151
151
|
// src/ui/App.tsx
|
|
152
|
-
import { useState as
|
|
153
|
-
import { Box as
|
|
152
|
+
import { useState as useState10, useRef as useRef8 } from "react";
|
|
153
|
+
import { Box as Box11, Text as Text13, useApp, useInput as useInput7 } from "ink";
|
|
154
154
|
import { getModelName } from "@robota-sdk/agent-core";
|
|
155
155
|
|
|
156
156
|
// src/ui/hooks/useSession.ts
|
|
@@ -158,25 +158,69 @@ import { useState, useCallback, useRef } from "react";
|
|
|
158
158
|
import { createSession, FileSessionLogger, projectPaths } from "@robota-sdk/agent-sdk";
|
|
159
159
|
|
|
160
160
|
// src/utils/edit-diff.ts
|
|
161
|
-
|
|
161
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
162
|
+
var CONTEXT_LINES = 2;
|
|
163
|
+
function generateDiffLines(oldStr, newStr, startLine = 1) {
|
|
162
164
|
if (oldStr === newStr) return [];
|
|
163
165
|
const lines = [];
|
|
164
|
-
|
|
165
|
-
|
|
166
|
+
const oldLines = oldStr.split("\n");
|
|
167
|
+
const newLines = newStr.split("\n");
|
|
168
|
+
for (let i = 0; i < oldLines.length; i++) {
|
|
169
|
+
lines.push({ type: "remove", text: oldLines[i], lineNumber: startLine + i });
|
|
166
170
|
}
|
|
167
|
-
for (
|
|
168
|
-
lines.push({ type: "add", text:
|
|
171
|
+
for (let i = 0; i < newLines.length; i++) {
|
|
172
|
+
lines.push({ type: "add", text: newLines[i], lineNumber: startLine + i });
|
|
169
173
|
}
|
|
170
174
|
return lines;
|
|
171
175
|
}
|
|
172
|
-
function
|
|
176
|
+
function generateDiffLinesWithContext(oldStr, newStr, startLine, filePath) {
|
|
177
|
+
if (oldStr === newStr) return [];
|
|
178
|
+
const diffLines = generateDiffLines(oldStr, newStr, startLine);
|
|
179
|
+
let fileLines;
|
|
180
|
+
try {
|
|
181
|
+
fileLines = readFileSync2(filePath, "utf-8").split("\n");
|
|
182
|
+
} catch {
|
|
183
|
+
return diffLines;
|
|
184
|
+
}
|
|
185
|
+
const result = [];
|
|
186
|
+
const contextStart = Math.max(0, startLine - 1 - CONTEXT_LINES);
|
|
187
|
+
for (let i = contextStart; i < startLine - 1; i++) {
|
|
188
|
+
if (i < fileLines.length) {
|
|
189
|
+
result.push({ type: "context", text: fileLines[i], lineNumber: i + 1 });
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
result.push(...diffLines);
|
|
193
|
+
const newLineCount = newStr.split("\n").length;
|
|
194
|
+
const afterStart = startLine - 1 + newLineCount;
|
|
195
|
+
for (let i = afterStart; i < afterStart + CONTEXT_LINES; i++) {
|
|
196
|
+
if (i < fileLines.length) {
|
|
197
|
+
result.push({ type: "context", text: fileLines[i], lineNumber: i + 1 });
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return result;
|
|
201
|
+
}
|
|
202
|
+
function extractEditDiff(toolName, toolArgs, startLine) {
|
|
173
203
|
if (toolName !== "Edit" || !toolArgs) return null;
|
|
174
204
|
const filePath = toolArgs.file_path ?? toolArgs.filePath;
|
|
175
205
|
const oldStr = toolArgs.old_string ?? toolArgs.oldString;
|
|
176
206
|
const newStr = toolArgs.new_string ?? toolArgs.newString;
|
|
177
207
|
if (typeof filePath !== "string") return null;
|
|
178
208
|
if (typeof oldStr !== "string" || typeof newStr !== "string") return null;
|
|
179
|
-
|
|
209
|
+
let sl = startLine ?? 0;
|
|
210
|
+
if (!sl) {
|
|
211
|
+
try {
|
|
212
|
+
const fileContent = readFileSync2(filePath, "utf-8");
|
|
213
|
+
const idx = fileContent.indexOf(newStr);
|
|
214
|
+
if (idx >= 0) {
|
|
215
|
+
sl = fileContent.substring(0, idx).split("\n").length;
|
|
216
|
+
} else {
|
|
217
|
+
sl = 1;
|
|
218
|
+
}
|
|
219
|
+
} catch {
|
|
220
|
+
sl = 1;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
const lines = generateDiffLinesWithContext(oldStr, newStr, sl, filePath);
|
|
180
224
|
if (lines.length === 0) return null;
|
|
181
225
|
return { file: filePath, lines };
|
|
182
226
|
}
|
|
@@ -254,9 +298,20 @@ function useSession(props) {
|
|
|
254
298
|
setActiveTools((prev) => {
|
|
255
299
|
const updated = prev.map((t) => {
|
|
256
300
|
if (!(t.toolName === event.toolName && t.isRunning)) return t;
|
|
301
|
+
let startLine;
|
|
302
|
+
if (event.toolResultData && event.toolName === "Edit") {
|
|
303
|
+
try {
|
|
304
|
+
const parsed = JSON.parse(event.toolResultData);
|
|
305
|
+
if (typeof parsed.startLine === "number") {
|
|
306
|
+
startLine = parsed.startLine;
|
|
307
|
+
}
|
|
308
|
+
} catch {
|
|
309
|
+
}
|
|
310
|
+
}
|
|
257
311
|
const editDiff = extractEditDiff(
|
|
258
312
|
event.toolName,
|
|
259
|
-
t._toolArgs
|
|
313
|
+
t._toolArgs,
|
|
314
|
+
startLine
|
|
260
315
|
);
|
|
261
316
|
const finished = {
|
|
262
317
|
...t,
|
|
@@ -448,18 +503,9 @@ async function handlePluginCommand(args, addMessage, callbacks) {
|
|
|
448
503
|
try {
|
|
449
504
|
switch (subcommand) {
|
|
450
505
|
case "":
|
|
451
|
-
case void 0:
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
addMessage({ role: "system", content: "No plugins installed." });
|
|
455
|
-
} else {
|
|
456
|
-
const lines = plugins.map(
|
|
457
|
-
(p) => ` ${p.name} \u2014 ${p.description} [${p.enabled ? "enabled" : "disabled"}]`
|
|
458
|
-
);
|
|
459
|
-
addMessage({ role: "system", content: `Installed plugins:
|
|
460
|
-
${lines.join("\n")}` });
|
|
461
|
-
}
|
|
462
|
-
return { handled: true };
|
|
506
|
+
case void 0:
|
|
507
|
+
case "manage": {
|
|
508
|
+
return { handled: true, triggerPluginTUI: true };
|
|
463
509
|
}
|
|
464
510
|
case "install": {
|
|
465
511
|
if (!subArgs) {
|
|
@@ -606,7 +652,7 @@ async function executeSlashCommand(cmd, args, session, addMessage, clearMessages
|
|
|
606
652
|
|
|
607
653
|
// src/ui/hooks/useSlashCommands.ts
|
|
608
654
|
var EXIT_DELAY_MS = 500;
|
|
609
|
-
function useSlashCommands(session, addMessage, setMessages, exit, registry, pendingModelChangeRef, setPendingModelId, pluginCallbacks) {
|
|
655
|
+
function useSlashCommands(session, addMessage, setMessages, exit, registry, pendingModelChangeRef, setPendingModelId, pluginCallbacks, setShowPluginTUI) {
|
|
610
656
|
return useCallback3(
|
|
611
657
|
async (input) => {
|
|
612
658
|
const parts = input.slice(1).split(/\s+/);
|
|
@@ -626,6 +672,9 @@ function useSlashCommands(session, addMessage, setMessages, exit, registry, pend
|
|
|
626
672
|
pendingModelChangeRef.current = result.pendingModelId;
|
|
627
673
|
setPendingModelId(result.pendingModelId);
|
|
628
674
|
}
|
|
675
|
+
if (result.triggerPluginTUI) {
|
|
676
|
+
setShowPluginTUI?.(true);
|
|
677
|
+
}
|
|
629
678
|
if (result.exitRequested) {
|
|
630
679
|
setTimeout(() => exit(), EXIT_DELAY_MS);
|
|
631
680
|
}
|
|
@@ -639,7 +688,8 @@ function useSlashCommands(session, addMessage, setMessages, exit, registry, pend
|
|
|
639
688
|
registry,
|
|
640
689
|
pendingModelChangeRef,
|
|
641
690
|
setPendingModelId,
|
|
642
|
-
pluginCallbacks
|
|
691
|
+
pluginCallbacks,
|
|
692
|
+
setShowPluginTUI
|
|
643
693
|
]
|
|
644
694
|
);
|
|
645
695
|
}
|
|
@@ -1027,22 +1077,7 @@ function createBuiltinCommands() {
|
|
|
1027
1077
|
{ name: "cost", description: "Show session info", source: "builtin" },
|
|
1028
1078
|
{ name: "context", description: "Context window info", source: "builtin" },
|
|
1029
1079
|
{ name: "permissions", description: "Permission rules", source: "builtin" },
|
|
1030
|
-
{
|
|
1031
|
-
name: "plugin",
|
|
1032
|
-
description: "Manage plugins",
|
|
1033
|
-
source: "builtin",
|
|
1034
|
-
subcommands: [
|
|
1035
|
-
{ name: "install", description: "Install a plugin (name@marketplace)", source: "builtin" },
|
|
1036
|
-
{
|
|
1037
|
-
name: "uninstall",
|
|
1038
|
-
description: "Uninstall a plugin (name@marketplace)",
|
|
1039
|
-
source: "builtin"
|
|
1040
|
-
},
|
|
1041
|
-
{ name: "enable", description: "Enable a plugin (name@marketplace)", source: "builtin" },
|
|
1042
|
-
{ name: "disable", description: "Disable a plugin (name@marketplace)", source: "builtin" },
|
|
1043
|
-
{ name: "marketplace", description: "Manage marketplace sources", source: "builtin" }
|
|
1044
|
-
]
|
|
1045
|
-
},
|
|
1080
|
+
{ name: "plugin", description: "Manage plugins", source: "builtin" },
|
|
1046
1081
|
{ name: "reload-plugins", description: "Reload all plugin resources", source: "builtin" },
|
|
1047
1082
|
{ name: "reset", description: "Delete settings and exit", source: "builtin" },
|
|
1048
1083
|
{ name: "exit", description: "Exit CLI", source: "builtin" }
|
|
@@ -1060,7 +1095,7 @@ var BuiltinCommandSource = class {
|
|
|
1060
1095
|
};
|
|
1061
1096
|
|
|
1062
1097
|
// src/commands/skill-source.ts
|
|
1063
|
-
import { readdirSync, readFileSync as
|
|
1098
|
+
import { readdirSync, readFileSync as readFileSync3, existsSync as existsSync2 } from "fs";
|
|
1064
1099
|
import { join as join2, basename } from "path";
|
|
1065
1100
|
import { homedir } from "os";
|
|
1066
1101
|
var BOOLEAN_KEYS = /* @__PURE__ */ new Set(["disable-model-invocation", "user-invocable"]);
|
|
@@ -1116,7 +1151,7 @@ function scanSkillsDir(skillsDir) {
|
|
|
1116
1151
|
if (!entry.isDirectory()) continue;
|
|
1117
1152
|
const skillFile = join2(skillsDir, entry.name, "SKILL.md");
|
|
1118
1153
|
if (!existsSync2(skillFile)) continue;
|
|
1119
|
-
const content =
|
|
1154
|
+
const content = readFileSync3(skillFile, "utf-8");
|
|
1120
1155
|
const frontmatter = parseFrontmatter(content);
|
|
1121
1156
|
commands.push(buildCommand(frontmatter, content, entry.name));
|
|
1122
1157
|
}
|
|
@@ -1129,7 +1164,7 @@ function scanCommandsDir(commandsDir) {
|
|
|
1129
1164
|
for (const entry of entries) {
|
|
1130
1165
|
if (!entry.isFile() || !entry.name.endsWith(".md")) continue;
|
|
1131
1166
|
const filePath = join2(commandsDir, entry.name);
|
|
1132
|
-
const content =
|
|
1167
|
+
const content = readFileSync3(filePath, "utf-8");
|
|
1133
1168
|
const frontmatter = parseFrontmatter(content);
|
|
1134
1169
|
const fallbackName = basename(entry.name, ".md");
|
|
1135
1170
|
commands.push(buildCommand(frontmatter, content, fallbackName));
|
|
@@ -1314,18 +1349,50 @@ function usePluginCallbacks(cwd) {
|
|
|
1314
1349
|
return {
|
|
1315
1350
|
listInstalled: async () => {
|
|
1316
1351
|
const plugins = await loader.loadAll();
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1352
|
+
const enabledMap = settingsStore.getEnabledPlugins();
|
|
1353
|
+
return plugins.map((p) => {
|
|
1354
|
+
const parts = p.pluginDir.split("/");
|
|
1355
|
+
const cacheIdx = parts.indexOf("cache");
|
|
1356
|
+
const marketplaceName = cacheIdx >= 0 ? parts[cacheIdx + 1] : "";
|
|
1357
|
+
const fullId = marketplaceName ? `${p.manifest.name}@${marketplaceName}` : p.manifest.name;
|
|
1358
|
+
return {
|
|
1359
|
+
name: fullId,
|
|
1360
|
+
description: p.manifest.description,
|
|
1361
|
+
enabled: enabledMap[fullId] !== false && enabledMap[p.manifest.name] !== false
|
|
1362
|
+
};
|
|
1363
|
+
});
|
|
1364
|
+
},
|
|
1365
|
+
listAvailablePlugins: async (marketplaceName) => {
|
|
1366
|
+
let manifest;
|
|
1367
|
+
try {
|
|
1368
|
+
manifest = marketplace.fetchManifest(marketplaceName);
|
|
1369
|
+
} catch {
|
|
1370
|
+
return [];
|
|
1371
|
+
}
|
|
1372
|
+
const installed = installer.getInstalledPlugins();
|
|
1373
|
+
const installedNames = new Set(Object.values(installed).map((r) => r.pluginName));
|
|
1374
|
+
return manifest.plugins.map((p) => ({
|
|
1375
|
+
name: p.name,
|
|
1376
|
+
description: p.description,
|
|
1377
|
+
installed: installedNames.has(p.name)
|
|
1321
1378
|
}));
|
|
1322
1379
|
},
|
|
1323
|
-
install: async (pluginId) => {
|
|
1380
|
+
install: async (pluginId, scope) => {
|
|
1324
1381
|
const [name, marketplaceName] = pluginId.split("@");
|
|
1325
1382
|
if (!name || !marketplaceName) {
|
|
1326
1383
|
throw new Error("Plugin ID must be in format: name@marketplace");
|
|
1327
1384
|
}
|
|
1328
|
-
|
|
1385
|
+
if (scope === "project") {
|
|
1386
|
+
const projectPluginsDir = join4(cwd, ".robota", "plugins");
|
|
1387
|
+
const projectInstaller = new BundlePluginInstaller({
|
|
1388
|
+
pluginsDir: projectPluginsDir,
|
|
1389
|
+
settingsStore,
|
|
1390
|
+
marketplaceClient: marketplace
|
|
1391
|
+
});
|
|
1392
|
+
await projectInstaller.install(name, marketplaceName);
|
|
1393
|
+
} else {
|
|
1394
|
+
await installer.install(name, marketplaceName);
|
|
1395
|
+
}
|
|
1329
1396
|
},
|
|
1330
1397
|
uninstall: async (pluginId) => {
|
|
1331
1398
|
await installer.uninstall(pluginId);
|
|
@@ -1383,23 +1450,41 @@ function renderMarkdown(md) {
|
|
|
1383
1450
|
// src/ui/DiffBlock.tsx
|
|
1384
1451
|
import { Box, Text } from "ink";
|
|
1385
1452
|
import { jsxs } from "react/jsx-runtime";
|
|
1386
|
-
var MAX_DIFF_LINES =
|
|
1387
|
-
var TRUNCATED_SHOW =
|
|
1453
|
+
var MAX_DIFF_LINES = 12;
|
|
1454
|
+
var TRUNCATED_SHOW = 10;
|
|
1388
1455
|
function DiffBlock({ file, lines }) {
|
|
1389
1456
|
const truncated = lines.length > MAX_DIFF_LINES;
|
|
1390
1457
|
const visible = truncated ? lines.slice(0, TRUNCATED_SHOW) : lines;
|
|
1391
1458
|
const remaining = lines.length - TRUNCATED_SHOW;
|
|
1459
|
+
const maxLineNum = Math.max(...visible.map((l) => l.lineNumber), 0);
|
|
1460
|
+
const numWidth = String(maxLineNum).length;
|
|
1392
1461
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginLeft: 4, children: [
|
|
1393
1462
|
file && /* @__PURE__ */ jsxs(Text, { color: "white", dimColor: true, children: [
|
|
1394
1463
|
"\u2502 ",
|
|
1395
1464
|
file
|
|
1396
1465
|
] }),
|
|
1397
|
-
visible.map((line, i) =>
|
|
1398
|
-
"
|
|
1399
|
-
line.type === "
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1466
|
+
visible.map((line, i) => {
|
|
1467
|
+
const lineNum = String(line.lineNumber).padStart(numWidth, " ");
|
|
1468
|
+
if (line.type === "context") {
|
|
1469
|
+
return /* @__PURE__ */ jsxs(Text, { color: "white", dimColor: true, children: [
|
|
1470
|
+
"\u2502 ",
|
|
1471
|
+
lineNum,
|
|
1472
|
+
" ",
|
|
1473
|
+
line.text
|
|
1474
|
+
] }, i);
|
|
1475
|
+
}
|
|
1476
|
+
const prefix = line.type === "remove" ? "-" : "+";
|
|
1477
|
+
const bgColor = line.type === "remove" ? "#5c1a1a" : "#1a3d1a";
|
|
1478
|
+
const fgColor = line.type === "remove" ? "#ff9999" : "#99ff99";
|
|
1479
|
+
return /* @__PURE__ */ jsxs(Text, { color: fgColor, backgroundColor: bgColor, children: [
|
|
1480
|
+
"\u2502 ",
|
|
1481
|
+
lineNum,
|
|
1482
|
+
" ",
|
|
1483
|
+
prefix,
|
|
1484
|
+
" ",
|
|
1485
|
+
line.text
|
|
1486
|
+
] }, i);
|
|
1487
|
+
}),
|
|
1403
1488
|
truncated && /* @__PURE__ */ jsxs(Text, { color: "white", dimColor: true, children: [
|
|
1404
1489
|
"\u2502 ... and ",
|
|
1405
1490
|
remaining,
|
|
@@ -2052,8 +2137,459 @@ function StreamingIndicator({ text, activeTools }) {
|
|
|
2052
2137
|
] });
|
|
2053
2138
|
}
|
|
2054
2139
|
|
|
2055
|
-
// src/ui/
|
|
2140
|
+
// src/ui/PluginTUI.tsx
|
|
2141
|
+
import { useState as useState9, useEffect as useEffect2, useCallback as useCallback9 } from "react";
|
|
2142
|
+
|
|
2143
|
+
// src/ui/MenuSelect.tsx
|
|
2144
|
+
import { useState as useState7, useCallback as useCallback7, useRef as useRef6 } from "react";
|
|
2145
|
+
import { Box as Box9, Text as Text11, useInput as useInput5 } from "ink";
|
|
2056
2146
|
import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
2147
|
+
function MenuSelect({
|
|
2148
|
+
title,
|
|
2149
|
+
items,
|
|
2150
|
+
onSelect,
|
|
2151
|
+
onBack,
|
|
2152
|
+
loading,
|
|
2153
|
+
error
|
|
2154
|
+
}) {
|
|
2155
|
+
const [selected, setSelected] = useState7(0);
|
|
2156
|
+
const selectedRef = useRef6(0);
|
|
2157
|
+
const resolvedRef = useRef6(false);
|
|
2158
|
+
const doSelect = useCallback7(
|
|
2159
|
+
(index) => {
|
|
2160
|
+
if (resolvedRef.current || items.length === 0) return;
|
|
2161
|
+
resolvedRef.current = true;
|
|
2162
|
+
onSelect(items[index].value);
|
|
2163
|
+
},
|
|
2164
|
+
[items, onSelect]
|
|
2165
|
+
);
|
|
2166
|
+
useInput5((input, key) => {
|
|
2167
|
+
if (resolvedRef.current) return;
|
|
2168
|
+
if (key.escape) {
|
|
2169
|
+
resolvedRef.current = true;
|
|
2170
|
+
onBack();
|
|
2171
|
+
return;
|
|
2172
|
+
}
|
|
2173
|
+
if (loading || error || items.length === 0) return;
|
|
2174
|
+
if (key.upArrow) {
|
|
2175
|
+
const next = selectedRef.current > 0 ? selectedRef.current - 1 : selectedRef.current;
|
|
2176
|
+
selectedRef.current = next;
|
|
2177
|
+
setSelected(next);
|
|
2178
|
+
} else if (key.downArrow) {
|
|
2179
|
+
const next = selectedRef.current < items.length - 1 ? selectedRef.current + 1 : selectedRef.current;
|
|
2180
|
+
selectedRef.current = next;
|
|
2181
|
+
setSelected(next);
|
|
2182
|
+
} else if (key.return) {
|
|
2183
|
+
doSelect(selectedRef.current);
|
|
2184
|
+
}
|
|
2185
|
+
});
|
|
2186
|
+
return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
|
|
2187
|
+
/* @__PURE__ */ jsx10(Text11, { color: "yellow", bold: true, children: title }),
|
|
2188
|
+
loading && /* @__PURE__ */ jsx10(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx10(Text11, { dimColor: true, children: "Loading..." }) }),
|
|
2189
|
+
error && /* @__PURE__ */ jsxs9(Box9, { marginTop: 1, flexDirection: "column", children: [
|
|
2190
|
+
/* @__PURE__ */ jsx10(Text11, { color: "red", children: error }),
|
|
2191
|
+
/* @__PURE__ */ jsx10(Text11, { dimColor: true, children: "Press Esc to go back" })
|
|
2192
|
+
] }),
|
|
2193
|
+
!loading && !error && /* @__PURE__ */ jsx10(Box9, { flexDirection: "column", marginTop: 1, children: items.map((item, i) => /* @__PURE__ */ jsxs9(Box9, { children: [
|
|
2194
|
+
/* @__PURE__ */ jsxs9(Text11, { color: i === selected ? "cyan" : void 0, bold: i === selected, children: [
|
|
2195
|
+
i === selected ? "> " : " ",
|
|
2196
|
+
item.label
|
|
2197
|
+
] }),
|
|
2198
|
+
item.hint && /* @__PURE__ */ jsxs9(Text11, { dimColor: true, children: [
|
|
2199
|
+
" ",
|
|
2200
|
+
item.hint
|
|
2201
|
+
] })
|
|
2202
|
+
] }, item.value)) }),
|
|
2203
|
+
/* @__PURE__ */ jsx10(Text11, { dimColor: true, children: loading || error ? "" : " \u2191\u2193 Navigate Enter Select Esc Back" })
|
|
2204
|
+
] });
|
|
2205
|
+
}
|
|
2206
|
+
|
|
2207
|
+
// src/ui/TextPrompt.tsx
|
|
2208
|
+
import { useState as useState8, useRef as useRef7, useCallback as useCallback8 } from "react";
|
|
2209
|
+
import { Box as Box10, Text as Text12, useInput as useInput6 } from "ink";
|
|
2210
|
+
import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
2211
|
+
function TextPrompt({
|
|
2212
|
+
title,
|
|
2213
|
+
placeholder,
|
|
2214
|
+
onSubmit,
|
|
2215
|
+
onCancel,
|
|
2216
|
+
validate
|
|
2217
|
+
}) {
|
|
2218
|
+
const [value, setValue] = useState8("");
|
|
2219
|
+
const [error, setError] = useState8();
|
|
2220
|
+
const resolvedRef = useRef7(false);
|
|
2221
|
+
const valueRef = useRef7("");
|
|
2222
|
+
const handleSubmit = useCallback8(() => {
|
|
2223
|
+
if (resolvedRef.current) return;
|
|
2224
|
+
const trimmed = valueRef.current.trim();
|
|
2225
|
+
if (!trimmed) return;
|
|
2226
|
+
if (validate) {
|
|
2227
|
+
const err = validate(trimmed);
|
|
2228
|
+
if (err) {
|
|
2229
|
+
setError(err);
|
|
2230
|
+
return;
|
|
2231
|
+
}
|
|
2232
|
+
}
|
|
2233
|
+
resolvedRef.current = true;
|
|
2234
|
+
onSubmit(trimmed);
|
|
2235
|
+
}, [validate, onSubmit]);
|
|
2236
|
+
useInput6((input, key) => {
|
|
2237
|
+
if (resolvedRef.current) return;
|
|
2238
|
+
if (key.escape) {
|
|
2239
|
+
resolvedRef.current = true;
|
|
2240
|
+
onCancel();
|
|
2241
|
+
return;
|
|
2242
|
+
}
|
|
2243
|
+
if (key.return) {
|
|
2244
|
+
handleSubmit();
|
|
2245
|
+
return;
|
|
2246
|
+
}
|
|
2247
|
+
if (key.backspace || key.delete) {
|
|
2248
|
+
valueRef.current = valueRef.current.slice(0, -1);
|
|
2249
|
+
setValue(valueRef.current);
|
|
2250
|
+
setError(void 0);
|
|
2251
|
+
return;
|
|
2252
|
+
}
|
|
2253
|
+
if (input && !key.ctrl && !key.meta) {
|
|
2254
|
+
valueRef.current = valueRef.current + input;
|
|
2255
|
+
setValue(valueRef.current);
|
|
2256
|
+
setError(void 0);
|
|
2257
|
+
}
|
|
2258
|
+
});
|
|
2259
|
+
return /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
|
|
2260
|
+
/* @__PURE__ */ jsx11(Text12, { color: "yellow", bold: true, children: title }),
|
|
2261
|
+
/* @__PURE__ */ jsxs10(Box10, { marginTop: 1, children: [
|
|
2262
|
+
/* @__PURE__ */ jsx11(Text12, { color: "cyan", children: "> " }),
|
|
2263
|
+
value ? /* @__PURE__ */ jsx11(Text12, { children: value }) : placeholder ? /* @__PURE__ */ jsx11(Text12, { dimColor: true, children: placeholder }) : null,
|
|
2264
|
+
/* @__PURE__ */ jsx11(Text12, { color: "cyan", children: "\u2588" })
|
|
2265
|
+
] }),
|
|
2266
|
+
error && /* @__PURE__ */ jsx11(Text12, { color: "red", children: error }),
|
|
2267
|
+
/* @__PURE__ */ jsx11(Text12, { dimColor: true, children: " Enter Submit Esc Cancel" })
|
|
2268
|
+
] });
|
|
2269
|
+
}
|
|
2270
|
+
|
|
2271
|
+
// src/ui/plugin-tui-handlers.ts
|
|
2272
|
+
function handleMainSelect(value, nav) {
|
|
2273
|
+
if (value === "marketplace") {
|
|
2274
|
+
nav.push({ screen: "marketplace-list" });
|
|
2275
|
+
} else if (value === "installed") {
|
|
2276
|
+
nav.push({ screen: "installed-list" });
|
|
2277
|
+
}
|
|
2278
|
+
}
|
|
2279
|
+
function handleMarketplaceListSelect(value, nav) {
|
|
2280
|
+
if (value === "__add__") {
|
|
2281
|
+
nav.push({ screen: "marketplace-add" });
|
|
2282
|
+
} else {
|
|
2283
|
+
nav.push({ screen: "marketplace-action", context: { marketplace: value } });
|
|
2284
|
+
}
|
|
2285
|
+
}
|
|
2286
|
+
function handleMarketplaceActionSelect(value, marketplace, callbacks, nav) {
|
|
2287
|
+
if (value === "browse") {
|
|
2288
|
+
nav.push({ screen: "marketplace-browse", context: { marketplace } });
|
|
2289
|
+
} else if (value === "update") {
|
|
2290
|
+
callbacks.marketplaceUpdate(marketplace).then(() => {
|
|
2291
|
+
nav.notify(`Updated marketplace "${marketplace}".`);
|
|
2292
|
+
nav.pop();
|
|
2293
|
+
}).catch((err) => {
|
|
2294
|
+
nav.notify(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
2295
|
+
});
|
|
2296
|
+
} else if (value === "remove") {
|
|
2297
|
+
nav.setConfirm({
|
|
2298
|
+
message: `Remove marketplace "${marketplace}" and all its plugins?`,
|
|
2299
|
+
onConfirm: () => {
|
|
2300
|
+
nav.setConfirm(void 0);
|
|
2301
|
+
callbacks.marketplaceRemove(marketplace).then(() => {
|
|
2302
|
+
nav.notify(`Removed marketplace "${marketplace}".`);
|
|
2303
|
+
nav.popN(2);
|
|
2304
|
+
}).catch((err) => {
|
|
2305
|
+
nav.notify(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
2306
|
+
});
|
|
2307
|
+
},
|
|
2308
|
+
onCancel: () => nav.setConfirm(void 0)
|
|
2309
|
+
});
|
|
2310
|
+
}
|
|
2311
|
+
}
|
|
2312
|
+
function handleMarketplaceBrowseSelect(value, marketplace, items, nav) {
|
|
2313
|
+
const fullId = `${value}@${marketplace}`;
|
|
2314
|
+
const item = items.find((i) => i.value === value);
|
|
2315
|
+
if (item?.hint === "installed") {
|
|
2316
|
+
nav.push({ screen: "installed-action", context: { pluginId: fullId } });
|
|
2317
|
+
} else {
|
|
2318
|
+
nav.push({ screen: "marketplace-install-scope", context: { marketplace, pluginId: fullId } });
|
|
2319
|
+
}
|
|
2320
|
+
}
|
|
2321
|
+
function handleInstallScopeSelect(value, pluginId, callbacks, nav) {
|
|
2322
|
+
const scope = value;
|
|
2323
|
+
callbacks.install(pluginId, scope).then(() => {
|
|
2324
|
+
nav.notify(`Installed plugin "${pluginId}" (${scope} scope).`);
|
|
2325
|
+
nav.popN(2);
|
|
2326
|
+
}).catch((err) => {
|
|
2327
|
+
nav.notify(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
2328
|
+
});
|
|
2329
|
+
}
|
|
2330
|
+
function handleInstalledListSelect(value, callbacks, nav) {
|
|
2331
|
+
nav.setConfirm({
|
|
2332
|
+
message: `Uninstall plugin "${value}"?`,
|
|
2333
|
+
onConfirm: () => {
|
|
2334
|
+
nav.setConfirm(void 0);
|
|
2335
|
+
callbacks.uninstall(value).then(() => {
|
|
2336
|
+
nav.notify(`Uninstalled plugin "${value}".`);
|
|
2337
|
+
nav.refresh();
|
|
2338
|
+
}).catch((err) => {
|
|
2339
|
+
nav.notify(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
2340
|
+
});
|
|
2341
|
+
},
|
|
2342
|
+
onCancel: () => nav.setConfirm(void 0)
|
|
2343
|
+
});
|
|
2344
|
+
}
|
|
2345
|
+
function handleInstalledActionSelect(value, pluginId, callbacks, nav) {
|
|
2346
|
+
if (value === "uninstall") {
|
|
2347
|
+
nav.setConfirm({
|
|
2348
|
+
message: `Uninstall plugin "${pluginId}"?`,
|
|
2349
|
+
onConfirm: () => {
|
|
2350
|
+
nav.setConfirm(void 0);
|
|
2351
|
+
callbacks.uninstall(pluginId).then(() => {
|
|
2352
|
+
nav.notify(`Uninstalled plugin "${pluginId}".`);
|
|
2353
|
+
nav.popN(2);
|
|
2354
|
+
}).catch((err) => {
|
|
2355
|
+
nav.notify(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
2356
|
+
});
|
|
2357
|
+
},
|
|
2358
|
+
onCancel: () => nav.setConfirm(void 0)
|
|
2359
|
+
});
|
|
2360
|
+
}
|
|
2361
|
+
}
|
|
2362
|
+
|
|
2363
|
+
// src/ui/PluginTUI.tsx
|
|
2364
|
+
import { jsx as jsx12 } from "react/jsx-runtime";
|
|
2365
|
+
function PluginTUI({ callbacks, onClose, addMessage }) {
|
|
2366
|
+
const [stack, setStack] = useState9([{ screen: "main" }]);
|
|
2367
|
+
const [items, setItems] = useState9([]);
|
|
2368
|
+
const [loading, setLoading] = useState9(false);
|
|
2369
|
+
const [error, setError] = useState9();
|
|
2370
|
+
const [confirm, setConfirm] = useState9();
|
|
2371
|
+
const [refreshCounter, setRefreshCounter] = useState9(0);
|
|
2372
|
+
const current = stack[stack.length - 1] ?? { screen: "main" };
|
|
2373
|
+
const push = useCallback9((state) => {
|
|
2374
|
+
setStack((prev) => [...prev, state]);
|
|
2375
|
+
setItems([]);
|
|
2376
|
+
setError(void 0);
|
|
2377
|
+
}, []);
|
|
2378
|
+
const pop = useCallback9(() => {
|
|
2379
|
+
setStack((prev) => {
|
|
2380
|
+
if (prev.length <= 1) {
|
|
2381
|
+
onClose();
|
|
2382
|
+
return prev;
|
|
2383
|
+
}
|
|
2384
|
+
return prev.slice(0, -1);
|
|
2385
|
+
});
|
|
2386
|
+
setItems([]);
|
|
2387
|
+
setError(void 0);
|
|
2388
|
+
}, [onClose]);
|
|
2389
|
+
const popN = useCallback9(
|
|
2390
|
+
(n) => {
|
|
2391
|
+
setStack((prev) => {
|
|
2392
|
+
const next = prev.slice(0, Math.max(1, prev.length - n));
|
|
2393
|
+
if (next.length === 0) {
|
|
2394
|
+
onClose();
|
|
2395
|
+
return prev;
|
|
2396
|
+
}
|
|
2397
|
+
return next;
|
|
2398
|
+
});
|
|
2399
|
+
setItems([]);
|
|
2400
|
+
setError(void 0);
|
|
2401
|
+
},
|
|
2402
|
+
[onClose]
|
|
2403
|
+
);
|
|
2404
|
+
const notify = useCallback9(
|
|
2405
|
+
(content) => {
|
|
2406
|
+
addMessage?.({ role: "system", content });
|
|
2407
|
+
},
|
|
2408
|
+
[addMessage]
|
|
2409
|
+
);
|
|
2410
|
+
const refresh = useCallback9(() => {
|
|
2411
|
+
setItems([]);
|
|
2412
|
+
setRefreshCounter((c) => c + 1);
|
|
2413
|
+
}, []);
|
|
2414
|
+
const nav = { push, pop, popN, notify, setConfirm, refresh };
|
|
2415
|
+
useEffect2(() => {
|
|
2416
|
+
const screen2 = current.screen;
|
|
2417
|
+
if (screen2 === "marketplace-list") {
|
|
2418
|
+
setLoading(true);
|
|
2419
|
+
callbacks.marketplaceList().then((sources) => {
|
|
2420
|
+
const baseItems = [{ label: "Add Marketplace", value: "__add__" }];
|
|
2421
|
+
const sourceItems = sources.map((s) => ({
|
|
2422
|
+
label: s.name,
|
|
2423
|
+
value: s.name,
|
|
2424
|
+
hint: s.type
|
|
2425
|
+
}));
|
|
2426
|
+
setItems([...baseItems, ...sourceItems]);
|
|
2427
|
+
setLoading(false);
|
|
2428
|
+
}).catch((err) => {
|
|
2429
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
2430
|
+
setLoading(false);
|
|
2431
|
+
});
|
|
2432
|
+
} else if (screen2 === "marketplace-browse") {
|
|
2433
|
+
const marketplace = current.context?.marketplace ?? "";
|
|
2434
|
+
setLoading(true);
|
|
2435
|
+
callbacks.listAvailablePlugins(marketplace).then((plugins) => {
|
|
2436
|
+
setItems(
|
|
2437
|
+
plugins.map((p) => ({
|
|
2438
|
+
label: p.name,
|
|
2439
|
+
value: p.name,
|
|
2440
|
+
hint: p.installed ? "installed" : p.description
|
|
2441
|
+
}))
|
|
2442
|
+
);
|
|
2443
|
+
setLoading(false);
|
|
2444
|
+
}).catch((err) => {
|
|
2445
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
2446
|
+
setLoading(false);
|
|
2447
|
+
});
|
|
2448
|
+
} else if (screen2 === "installed-list") {
|
|
2449
|
+
setLoading(true);
|
|
2450
|
+
callbacks.listInstalled().then((plugins) => {
|
|
2451
|
+
setItems(
|
|
2452
|
+
plugins.map((p) => ({
|
|
2453
|
+
label: p.name,
|
|
2454
|
+
value: p.name,
|
|
2455
|
+
hint: p.description
|
|
2456
|
+
}))
|
|
2457
|
+
);
|
|
2458
|
+
setLoading(false);
|
|
2459
|
+
}).catch((err) => {
|
|
2460
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
2461
|
+
setLoading(false);
|
|
2462
|
+
});
|
|
2463
|
+
}
|
|
2464
|
+
}, [stack.length, current.screen, current.context?.marketplace, callbacks, refreshCounter]);
|
|
2465
|
+
const handleSelect = useCallback9(
|
|
2466
|
+
(value) => {
|
|
2467
|
+
const screen2 = current.screen;
|
|
2468
|
+
const ctx = current.context;
|
|
2469
|
+
if (screen2 === "main") handleMainSelect(value, nav);
|
|
2470
|
+
else if (screen2 === "marketplace-list") handleMarketplaceListSelect(value, nav);
|
|
2471
|
+
else if (screen2 === "marketplace-action")
|
|
2472
|
+
handleMarketplaceActionSelect(value, ctx?.marketplace ?? "", callbacks, nav);
|
|
2473
|
+
else if (screen2 === "marketplace-browse")
|
|
2474
|
+
handleMarketplaceBrowseSelect(value, ctx?.marketplace ?? "", items, nav);
|
|
2475
|
+
else if (screen2 === "marketplace-install-scope")
|
|
2476
|
+
handleInstallScopeSelect(value, ctx?.pluginId ?? "", callbacks, nav);
|
|
2477
|
+
else if (screen2 === "installed-list") handleInstalledListSelect(value, callbacks, nav);
|
|
2478
|
+
else if (screen2 === "installed-action")
|
|
2479
|
+
handleInstalledActionSelect(value, ctx?.pluginId ?? "", callbacks, nav);
|
|
2480
|
+
},
|
|
2481
|
+
[current, items, callbacks, push, pop, popN, notify, setConfirm, refresh]
|
|
2482
|
+
);
|
|
2483
|
+
const handleTextSubmit = useCallback9(
|
|
2484
|
+
(value) => {
|
|
2485
|
+
if (current.screen === "marketplace-add") {
|
|
2486
|
+
callbacks.marketplaceAdd(value).then((name) => {
|
|
2487
|
+
notify(`Added marketplace "${name}" from ${value}.`);
|
|
2488
|
+
pop();
|
|
2489
|
+
}).catch((err) => {
|
|
2490
|
+
notify(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
2491
|
+
pop();
|
|
2492
|
+
});
|
|
2493
|
+
}
|
|
2494
|
+
},
|
|
2495
|
+
[current.screen, callbacks, notify, pop]
|
|
2496
|
+
);
|
|
2497
|
+
if (confirm) {
|
|
2498
|
+
return /* @__PURE__ */ jsx12(
|
|
2499
|
+
ConfirmPrompt,
|
|
2500
|
+
{
|
|
2501
|
+
message: confirm.message,
|
|
2502
|
+
onSelect: (index) => {
|
|
2503
|
+
if (index === 0) confirm.onConfirm();
|
|
2504
|
+
else confirm.onCancel();
|
|
2505
|
+
}
|
|
2506
|
+
}
|
|
2507
|
+
);
|
|
2508
|
+
}
|
|
2509
|
+
const screen = current.screen;
|
|
2510
|
+
if (screen === "marketplace-add") {
|
|
2511
|
+
return /* @__PURE__ */ jsx12(
|
|
2512
|
+
TextPrompt,
|
|
2513
|
+
{
|
|
2514
|
+
title: "Add Marketplace Source",
|
|
2515
|
+
placeholder: "owner/repo or git URL",
|
|
2516
|
+
onSubmit: handleTextSubmit,
|
|
2517
|
+
onCancel: pop,
|
|
2518
|
+
validate: (v) => !v.includes("/") ? "Must be owner/repo or a git URL" : void 0
|
|
2519
|
+
}
|
|
2520
|
+
);
|
|
2521
|
+
}
|
|
2522
|
+
if (screen === "marketplace-action") {
|
|
2523
|
+
return /* @__PURE__ */ jsx12(
|
|
2524
|
+
MenuSelect,
|
|
2525
|
+
{
|
|
2526
|
+
title: `Marketplace: ${current.context?.marketplace ?? ""}`,
|
|
2527
|
+
items: [
|
|
2528
|
+
{ label: "Browse plugins", value: "browse" },
|
|
2529
|
+
{ label: "Update", value: "update" },
|
|
2530
|
+
{ label: "Remove", value: "remove" }
|
|
2531
|
+
],
|
|
2532
|
+
onSelect: handleSelect,
|
|
2533
|
+
onBack: pop
|
|
2534
|
+
},
|
|
2535
|
+
stack.length
|
|
2536
|
+
);
|
|
2537
|
+
}
|
|
2538
|
+
if (screen === "marketplace-install-scope") {
|
|
2539
|
+
return /* @__PURE__ */ jsx12(
|
|
2540
|
+
MenuSelect,
|
|
2541
|
+
{
|
|
2542
|
+
title: `Install scope for "${current.context?.pluginId ?? ""}"`,
|
|
2543
|
+
items: [
|
|
2544
|
+
{ label: "User scope", value: "user" },
|
|
2545
|
+
{ label: "Project scope", value: "project" }
|
|
2546
|
+
],
|
|
2547
|
+
onSelect: handleSelect,
|
|
2548
|
+
onBack: pop
|
|
2549
|
+
},
|
|
2550
|
+
stack.length
|
|
2551
|
+
);
|
|
2552
|
+
}
|
|
2553
|
+
if (screen === "installed-action") {
|
|
2554
|
+
return /* @__PURE__ */ jsx12(
|
|
2555
|
+
MenuSelect,
|
|
2556
|
+
{
|
|
2557
|
+
title: `Plugin: ${current.context?.pluginId ?? ""}`,
|
|
2558
|
+
items: [{ label: "Uninstall", value: "uninstall" }],
|
|
2559
|
+
onSelect: handleSelect,
|
|
2560
|
+
onBack: pop
|
|
2561
|
+
},
|
|
2562
|
+
stack.length
|
|
2563
|
+
);
|
|
2564
|
+
}
|
|
2565
|
+
const titleMap = {
|
|
2566
|
+
main: "Plugin Management",
|
|
2567
|
+
"marketplace-list": "Marketplace",
|
|
2568
|
+
"marketplace-browse": `Browse: ${current.context?.marketplace ?? ""}`,
|
|
2569
|
+
"installed-list": "Installed Plugins"
|
|
2570
|
+
};
|
|
2571
|
+
const staticItemsMap = {
|
|
2572
|
+
main: [
|
|
2573
|
+
{ label: "Marketplace", value: "marketplace" },
|
|
2574
|
+
{ label: "Installed Plugins", value: "installed" }
|
|
2575
|
+
]
|
|
2576
|
+
};
|
|
2577
|
+
return /* @__PURE__ */ jsx12(
|
|
2578
|
+
MenuSelect,
|
|
2579
|
+
{
|
|
2580
|
+
title: titleMap[screen] ?? "Plugin Management",
|
|
2581
|
+
items: staticItemsMap[screen] ?? items,
|
|
2582
|
+
onSelect: handleSelect,
|
|
2583
|
+
onBack: pop,
|
|
2584
|
+
loading,
|
|
2585
|
+
error
|
|
2586
|
+
},
|
|
2587
|
+
`${screen}-${stack.length}-${refreshCounter}`
|
|
2588
|
+
);
|
|
2589
|
+
}
|
|
2590
|
+
|
|
2591
|
+
// src/ui/App.tsx
|
|
2592
|
+
import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
2057
2593
|
var EXIT_DELAY_MS2 = 500;
|
|
2058
2594
|
function mergeHooksIntoConfig(configHooks, pluginHooks) {
|
|
2059
2595
|
const pluginKeys = Object.keys(pluginHooks);
|
|
@@ -2085,15 +2621,16 @@ function App(props) {
|
|
|
2085
2621
|
{ ...props, config: configWithPluginHooks }
|
|
2086
2622
|
);
|
|
2087
2623
|
const { messages, setMessages, addMessage } = useMessages();
|
|
2088
|
-
const [isThinking, setIsThinking] =
|
|
2624
|
+
const [isThinking, setIsThinking] = useState10(false);
|
|
2089
2625
|
const initialCtx = session.getContextState();
|
|
2090
|
-
const [contextState, setContextState] =
|
|
2626
|
+
const [contextState, setContextState] = useState10({
|
|
2091
2627
|
percentage: initialCtx.usedPercentage,
|
|
2092
2628
|
usedTokens: initialCtx.usedTokens,
|
|
2093
2629
|
maxTokens: initialCtx.maxTokens
|
|
2094
2630
|
});
|
|
2095
|
-
const pendingModelChangeRef =
|
|
2096
|
-
const [pendingModelId, setPendingModelId] =
|
|
2631
|
+
const pendingModelChangeRef = useRef8(null);
|
|
2632
|
+
const [pendingModelId, setPendingModelId] = useState10(null);
|
|
2633
|
+
const [showPluginTUI, setShowPluginTUI] = useState10(false);
|
|
2097
2634
|
const pluginCallbacks = usePluginCallbacks(props.cwd ?? process.cwd());
|
|
2098
2635
|
const handleSlashCommand = useSlashCommands(
|
|
2099
2636
|
session,
|
|
@@ -2103,7 +2640,8 @@ function App(props) {
|
|
|
2103
2640
|
registry,
|
|
2104
2641
|
pendingModelChangeRef,
|
|
2105
2642
|
setPendingModelId,
|
|
2106
|
-
pluginCallbacks
|
|
2643
|
+
pluginCallbacks,
|
|
2644
|
+
setShowPluginTUI
|
|
2107
2645
|
);
|
|
2108
2646
|
const handleSubmit = useSubmitHandler(
|
|
2109
2647
|
session,
|
|
@@ -2114,33 +2652,33 @@ function App(props) {
|
|
|
2114
2652
|
setContextState,
|
|
2115
2653
|
registry
|
|
2116
2654
|
);
|
|
2117
|
-
|
|
2655
|
+
useInput7(
|
|
2118
2656
|
(_input, key) => {
|
|
2119
2657
|
if (key.ctrl && _input === "c") exit();
|
|
2120
2658
|
if (key.escape && isThinking) session.abort();
|
|
2121
2659
|
},
|
|
2122
|
-
{ isActive: !permissionRequest }
|
|
2660
|
+
{ isActive: !permissionRequest && !showPluginTUI }
|
|
2123
2661
|
);
|
|
2124
|
-
return /* @__PURE__ */
|
|
2125
|
-
/* @__PURE__ */
|
|
2126
|
-
/* @__PURE__ */
|
|
2662
|
+
return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", children: [
|
|
2663
|
+
/* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", paddingX: 1, marginBottom: 1, children: [
|
|
2664
|
+
/* @__PURE__ */ jsx13(Text13, { color: "cyan", bold: true, children: `
|
|
2127
2665
|
____ ___ ____ ___ _____ _
|
|
2128
2666
|
| _ \\ / _ \\| __ ) / _ \\_ _|/ \\
|
|
2129
2667
|
| |_) | | | | _ \\| | | || | / _ \\
|
|
2130
2668
|
| _ <| |_| | |_) | |_| || |/ ___ \\
|
|
2131
2669
|
|_| \\_\\\\___/|____/ \\___/ |_/_/ \\_\\
|
|
2132
2670
|
` }),
|
|
2133
|
-
/* @__PURE__ */
|
|
2671
|
+
/* @__PURE__ */ jsxs11(Text13, { dimColor: true, children: [
|
|
2134
2672
|
" v",
|
|
2135
2673
|
props.version ?? "0.0.0"
|
|
2136
2674
|
] })
|
|
2137
2675
|
] }),
|
|
2138
|
-
/* @__PURE__ */
|
|
2139
|
-
/* @__PURE__ */
|
|
2140
|
-
isThinking && /* @__PURE__ */
|
|
2676
|
+
/* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", paddingX: 1, flexGrow: 1, children: [
|
|
2677
|
+
/* @__PURE__ */ jsx13(MessageList, { messages }),
|
|
2678
|
+
isThinking && /* @__PURE__ */ jsx13(Box11, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ jsx13(StreamingIndicator, { text: streamingText, activeTools }) })
|
|
2141
2679
|
] }),
|
|
2142
|
-
permissionRequest && /* @__PURE__ */
|
|
2143
|
-
pendingModelId && /* @__PURE__ */
|
|
2680
|
+
permissionRequest && /* @__PURE__ */ jsx13(PermissionPrompt, { request: permissionRequest }),
|
|
2681
|
+
pendingModelId && /* @__PURE__ */ jsx13(
|
|
2144
2682
|
ConfirmPrompt,
|
|
2145
2683
|
{
|
|
2146
2684
|
message: `Change model to ${getModelName(pendingModelId)}? This will restart the session.`,
|
|
@@ -2168,7 +2706,15 @@ function App(props) {
|
|
|
2168
2706
|
}
|
|
2169
2707
|
}
|
|
2170
2708
|
),
|
|
2171
|
-
/* @__PURE__ */
|
|
2709
|
+
showPluginTUI && /* @__PURE__ */ jsx13(
|
|
2710
|
+
PluginTUI,
|
|
2711
|
+
{
|
|
2712
|
+
callbacks: pluginCallbacks,
|
|
2713
|
+
onClose: () => setShowPluginTUI(false),
|
|
2714
|
+
addMessage: (msg) => addMessage(msg)
|
|
2715
|
+
}
|
|
2716
|
+
),
|
|
2717
|
+
/* @__PURE__ */ jsx13(
|
|
2172
2718
|
StatusBar,
|
|
2173
2719
|
{
|
|
2174
2720
|
permissionMode: session.getPermissionMode(),
|
|
@@ -2181,20 +2727,20 @@ function App(props) {
|
|
|
2181
2727
|
contextMaxTokens: contextState.maxTokens
|
|
2182
2728
|
}
|
|
2183
2729
|
),
|
|
2184
|
-
/* @__PURE__ */
|
|
2730
|
+
/* @__PURE__ */ jsx13(
|
|
2185
2731
|
InputArea,
|
|
2186
2732
|
{
|
|
2187
2733
|
onSubmit: handleSubmit,
|
|
2188
|
-
isDisabled: isThinking || !!permissionRequest,
|
|
2734
|
+
isDisabled: isThinking || !!permissionRequest || showPluginTUI,
|
|
2189
2735
|
registry
|
|
2190
2736
|
}
|
|
2191
2737
|
),
|
|
2192
|
-
/* @__PURE__ */
|
|
2738
|
+
/* @__PURE__ */ jsx13(Text13, { children: " " })
|
|
2193
2739
|
] });
|
|
2194
2740
|
}
|
|
2195
2741
|
|
|
2196
2742
|
// src/ui/render.tsx
|
|
2197
|
-
import { jsx as
|
|
2743
|
+
import { jsx as jsx14 } from "react/jsx-runtime";
|
|
2198
2744
|
function renderApp(options) {
|
|
2199
2745
|
process.on("unhandledRejection", (reason) => {
|
|
2200
2746
|
process.stderr.write(`
|
|
@@ -2205,7 +2751,7 @@ function renderApp(options) {
|
|
|
2205
2751
|
`);
|
|
2206
2752
|
}
|
|
2207
2753
|
});
|
|
2208
|
-
const instance = render(/* @__PURE__ */
|
|
2754
|
+
const instance = render(/* @__PURE__ */ jsx14(App, { ...options }), {
|
|
2209
2755
|
exitOnCtrlC: true
|
|
2210
2756
|
});
|
|
2211
2757
|
instance.waitUntilExit().catch((err) => {
|
|
@@ -2221,7 +2767,7 @@ function renderApp(options) {
|
|
|
2221
2767
|
function checkSettingsFile(filePath) {
|
|
2222
2768
|
if (!existsSync3(filePath)) return "missing";
|
|
2223
2769
|
try {
|
|
2224
|
-
const raw =
|
|
2770
|
+
const raw = readFileSync4(filePath, "utf8").trim();
|
|
2225
2771
|
if (raw.length === 0) return "incomplete";
|
|
2226
2772
|
const parsed = JSON.parse(raw);
|
|
2227
2773
|
const provider = parsed.provider;
|
|
@@ -2238,7 +2784,7 @@ function readVersion() {
|
|
|
2238
2784
|
const candidates = [join5(dir, "..", "..", "package.json"), join5(dir, "..", "package.json")];
|
|
2239
2785
|
for (const pkgPath of candidates) {
|
|
2240
2786
|
try {
|
|
2241
|
-
const raw =
|
|
2787
|
+
const raw = readFileSync4(pkgPath, "utf-8");
|
|
2242
2788
|
const pkg = JSON.parse(raw);
|
|
2243
2789
|
if (pkg.version !== void 0 && pkg.name !== void 0) {
|
|
2244
2790
|
return pkg.version;
|