@robota-sdk/agent-cli 3.0.0-beta.34 → 3.0.0-beta.36
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 +634 -119
- package/dist/node/bin.js +1 -1
- package/dist/node/{chunk-RDPIMQOC.js → chunk-ERF646KY.js} +630 -110
- package/dist/node/index.cjs +634 -119
- package/dist/node/index.js +1 -1
- package/package.json +1 -1
package/dist/node/bin.cjs
CHANGED
|
@@ -163,12 +163,13 @@ var PrintTerminal = class {
|
|
|
163
163
|
};
|
|
164
164
|
|
|
165
165
|
// src/ui/render.tsx
|
|
166
|
-
var
|
|
166
|
+
var import_ink14 = require("ink");
|
|
167
167
|
|
|
168
168
|
// src/ui/App.tsx
|
|
169
|
-
var
|
|
170
|
-
var
|
|
171
|
-
var
|
|
169
|
+
var import_react16 = require("react");
|
|
170
|
+
var import_ink13 = require("ink");
|
|
171
|
+
var import_agent_core6 = require("@robota-sdk/agent-core");
|
|
172
|
+
var import_agent_core7 = require("@robota-sdk/agent-core");
|
|
172
173
|
|
|
173
174
|
// src/ui/hooks/useSession.ts
|
|
174
175
|
var import_react = require("react");
|
|
@@ -264,6 +265,7 @@ var NOOP_TERMINAL = {
|
|
|
264
265
|
function useSession(props) {
|
|
265
266
|
const [permissionRequest, setPermissionRequest] = (0, import_react.useState)(null);
|
|
266
267
|
const [streamingText, setStreamingText] = (0, import_react.useState)("");
|
|
268
|
+
const streamingTextRef = (0, import_react.useRef)("");
|
|
267
269
|
const [activeTools, setActiveTools] = (0, import_react.useState)([]);
|
|
268
270
|
const permissionQueueRef = (0, import_react.useRef)([]);
|
|
269
271
|
const processingRef = (0, import_react.useRef)(false);
|
|
@@ -295,8 +297,15 @@ function useSession(props) {
|
|
|
295
297
|
processNextPermission();
|
|
296
298
|
});
|
|
297
299
|
};
|
|
300
|
+
let flushTimer = null;
|
|
298
301
|
const onTextDelta = (delta) => {
|
|
299
|
-
|
|
302
|
+
streamingTextRef.current += delta;
|
|
303
|
+
if (!flushTimer) {
|
|
304
|
+
flushTimer = setTimeout(() => {
|
|
305
|
+
setStreamingText(streamingTextRef.current);
|
|
306
|
+
flushTimer = null;
|
|
307
|
+
}, 16);
|
|
308
|
+
}
|
|
300
309
|
};
|
|
301
310
|
const onToolExecution = (event) => {
|
|
302
311
|
if (event.type === "start") {
|
|
@@ -375,6 +384,7 @@ function useSession(props) {
|
|
|
375
384
|
}
|
|
376
385
|
const clearStreamingText = (0, import_react.useCallback)(() => {
|
|
377
386
|
setStreamingText("");
|
|
387
|
+
streamingTextRef.current = "";
|
|
378
388
|
setActiveTools([]);
|
|
379
389
|
}, []);
|
|
380
390
|
return {
|
|
@@ -389,16 +399,11 @@ function useSession(props) {
|
|
|
389
399
|
// src/ui/hooks/useMessages.ts
|
|
390
400
|
var import_react2 = require("react");
|
|
391
401
|
var MAX_RENDERED_MESSAGES = 100;
|
|
392
|
-
var msgIdCounter = 0;
|
|
393
|
-
function nextId() {
|
|
394
|
-
msgIdCounter += 1;
|
|
395
|
-
return `msg_${msgIdCounter}`;
|
|
396
|
-
}
|
|
397
402
|
function useMessages() {
|
|
398
403
|
const [messages, setMessages] = (0, import_react2.useState)([]);
|
|
399
404
|
const addMessage = (0, import_react2.useCallback)((msg) => {
|
|
400
405
|
setMessages((prev) => {
|
|
401
|
-
const updated = [...prev,
|
|
406
|
+
const updated = [...prev, msg];
|
|
402
407
|
if (updated.length > MAX_RENDERED_MESSAGES) {
|
|
403
408
|
return updated.slice(-MAX_RENDERED_MESSAGES);
|
|
404
409
|
}
|
|
@@ -410,6 +415,7 @@ function useMessages() {
|
|
|
410
415
|
|
|
411
416
|
// src/ui/hooks/useSlashCommands.ts
|
|
412
417
|
var import_react3 = require("react");
|
|
418
|
+
var import_agent_core = require("@robota-sdk/agent-core");
|
|
413
419
|
|
|
414
420
|
// src/commands/slash-executor.ts
|
|
415
421
|
var VALID_MODES2 = ["plan", "default", "acceptEdits", "bypassPermissions"];
|
|
@@ -520,18 +526,9 @@ async function handlePluginCommand(args, addMessage, callbacks) {
|
|
|
520
526
|
try {
|
|
521
527
|
switch (subcommand) {
|
|
522
528
|
case "":
|
|
523
|
-
case void 0:
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
addMessage({ role: "system", content: "No plugins installed." });
|
|
527
|
-
} else {
|
|
528
|
-
const lines = plugins.map(
|
|
529
|
-
(p) => ` ${p.name} \u2014 ${p.description} [${p.enabled ? "enabled" : "disabled"}]`
|
|
530
|
-
);
|
|
531
|
-
addMessage({ role: "system", content: `Installed plugins:
|
|
532
|
-
${lines.join("\n")}` });
|
|
533
|
-
}
|
|
534
|
-
return { handled: true };
|
|
529
|
+
case void 0:
|
|
530
|
+
case "manage": {
|
|
531
|
+
return { handled: true, triggerPluginTUI: true };
|
|
535
532
|
}
|
|
536
533
|
case "install": {
|
|
537
534
|
if (!subArgs) {
|
|
@@ -678,18 +675,21 @@ async function executeSlashCommand(cmd, args, session, addMessage, clearMessages
|
|
|
678
675
|
|
|
679
676
|
// src/ui/hooks/useSlashCommands.ts
|
|
680
677
|
var EXIT_DELAY_MS = 500;
|
|
681
|
-
function useSlashCommands(session, addMessage, setMessages, exit, registry, pendingModelChangeRef, setPendingModelId, pluginCallbacks) {
|
|
678
|
+
function useSlashCommands(session, addMessage, setMessages, exit, registry, pendingModelChangeRef, setPendingModelId, pluginCallbacks, setShowPluginTUI) {
|
|
682
679
|
return (0, import_react3.useCallback)(
|
|
683
680
|
async (input) => {
|
|
684
681
|
const parts = input.slice(1).split(/\s+/);
|
|
685
682
|
const cmd = parts[0]?.toLowerCase() ?? "";
|
|
686
683
|
const args = parts.slice(1).join(" ");
|
|
687
684
|
const clearMessages = () => setMessages([]);
|
|
685
|
+
const slashAddMessage = (msg) => {
|
|
686
|
+
addMessage((0, import_agent_core.createSystemMessage)(msg.content));
|
|
687
|
+
};
|
|
688
688
|
const result = await executeSlashCommand(
|
|
689
689
|
cmd,
|
|
690
690
|
args,
|
|
691
691
|
session,
|
|
692
|
-
|
|
692
|
+
slashAddMessage,
|
|
693
693
|
clearMessages,
|
|
694
694
|
registry,
|
|
695
695
|
pluginCallbacks
|
|
@@ -698,6 +698,9 @@ function useSlashCommands(session, addMessage, setMessages, exit, registry, pend
|
|
|
698
698
|
pendingModelChangeRef.current = result.pendingModelId;
|
|
699
699
|
setPendingModelId(result.pendingModelId);
|
|
700
700
|
}
|
|
701
|
+
if (result.triggerPluginTUI) {
|
|
702
|
+
setShowPluginTUI?.(true);
|
|
703
|
+
}
|
|
701
704
|
if (result.exitRequested) {
|
|
702
705
|
setTimeout(() => exit(), EXIT_DELAY_MS);
|
|
703
706
|
}
|
|
@@ -711,14 +714,17 @@ function useSlashCommands(session, addMessage, setMessages, exit, registry, pend
|
|
|
711
714
|
registry,
|
|
712
715
|
pendingModelChangeRef,
|
|
713
716
|
setPendingModelId,
|
|
714
|
-
pluginCallbacks
|
|
717
|
+
pluginCallbacks,
|
|
718
|
+
setShowPluginTUI
|
|
715
719
|
]
|
|
716
720
|
);
|
|
717
721
|
}
|
|
718
722
|
|
|
719
723
|
// src/ui/hooks/useSubmitHandler.ts
|
|
720
724
|
var import_react4 = require("react");
|
|
725
|
+
var import_node_crypto = require("crypto");
|
|
721
726
|
var import_agent_sdk2 = require("@robota-sdk/agent-sdk");
|
|
727
|
+
var import_agent_core2 = require("@robota-sdk/agent-core");
|
|
722
728
|
|
|
723
729
|
// src/utils/tool-call-extractor.ts
|
|
724
730
|
var TOOL_ARG_MAX_LENGTH = 80;
|
|
@@ -875,21 +881,50 @@ async function runSessionPrompt(prompt, session, addMessage, clearStreamingText,
|
|
|
875
881
|
historyBefore
|
|
876
882
|
);
|
|
877
883
|
if (toolSummaries.length > 0) {
|
|
878
|
-
addMessage(
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
884
|
+
addMessage(
|
|
885
|
+
(0, import_agent_core2.createToolMessage)(JSON.stringify(toolSummaries), {
|
|
886
|
+
toolCallId: (0, import_node_crypto.randomUUID)(),
|
|
887
|
+
name: `${toolSummaries.length} tools`
|
|
888
|
+
})
|
|
889
|
+
);
|
|
883
890
|
}
|
|
884
|
-
addMessage(
|
|
891
|
+
addMessage((0, import_agent_core2.createAssistantMessage)(response || "(empty response)"));
|
|
885
892
|
syncContextState(session, setContextState);
|
|
886
893
|
} catch (err) {
|
|
887
894
|
clearStreamingText();
|
|
888
|
-
|
|
889
|
-
|
|
895
|
+
const isAbortError = err instanceof DOMException && err.name === "AbortError" || err instanceof Error && (err.message.includes("aborted") || err.message.includes("abort"));
|
|
896
|
+
if (isAbortError) {
|
|
897
|
+
const history = session.getHistory();
|
|
898
|
+
const toolSummaries = extractToolCallsWithDiff(
|
|
899
|
+
history,
|
|
900
|
+
historyBefore
|
|
901
|
+
);
|
|
902
|
+
if (toolSummaries.length > 0) {
|
|
903
|
+
addMessage(
|
|
904
|
+
(0, import_agent_core2.createToolMessage)(JSON.stringify(toolSummaries), {
|
|
905
|
+
toolCallId: (0, import_node_crypto.randomUUID)(),
|
|
906
|
+
name: `${toolSummaries.length} tools`
|
|
907
|
+
})
|
|
908
|
+
);
|
|
909
|
+
}
|
|
910
|
+
const assistantParts = [];
|
|
911
|
+
let lastAssistantState = "complete";
|
|
912
|
+
for (let i = historyBefore; i < history.length; i++) {
|
|
913
|
+
const msg = history[i];
|
|
914
|
+
if (msg && msg.role === "assistant" && msg.content) {
|
|
915
|
+
assistantParts.push(msg.content);
|
|
916
|
+
if (msg.state === "interrupted") lastAssistantState = "interrupted";
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
if (assistantParts.length > 0) {
|
|
920
|
+
addMessage(
|
|
921
|
+
(0, import_agent_core2.createAssistantMessage)(assistantParts.join("\n\n"), { state: lastAssistantState })
|
|
922
|
+
);
|
|
923
|
+
}
|
|
924
|
+
addMessage((0, import_agent_core2.createSystemMessage)("Interrupted by user."));
|
|
890
925
|
} else {
|
|
891
926
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
892
|
-
addMessage(
|
|
927
|
+
addMessage((0, import_agent_core2.createSystemMessage)(`Error: ${errMsg}`));
|
|
893
928
|
}
|
|
894
929
|
} finally {
|
|
895
930
|
setIsThinking(false);
|
|
@@ -942,7 +977,7 @@ function useSubmitHandler(session, addMessage, handleSlashCommand, clearStreamin
|
|
|
942
977
|
const runInFork = createForkRunner(session);
|
|
943
978
|
const result = await executeSkill(skill, args, { runInFork });
|
|
944
979
|
if (result.mode === "fork") {
|
|
945
|
-
addMessage(
|
|
980
|
+
addMessage((0, import_agent_core2.createAssistantMessage)(result.result ?? "(empty response)"));
|
|
946
981
|
syncContextState(session, setContextState);
|
|
947
982
|
return;
|
|
948
983
|
}
|
|
@@ -977,7 +1012,7 @@ function useSubmitHandler(session, addMessage, handleSlashCommand, clearStreamin
|
|
|
977
1012
|
hookInput
|
|
978
1013
|
);
|
|
979
1014
|
}
|
|
980
|
-
addMessage(
|
|
1015
|
+
addMessage((0, import_agent_core2.createUserMessage)(input));
|
|
981
1016
|
return runSessionPrompt(
|
|
982
1017
|
input,
|
|
983
1018
|
session,
|
|
@@ -1044,16 +1079,16 @@ var CommandRegistry = class {
|
|
|
1044
1079
|
};
|
|
1045
1080
|
|
|
1046
1081
|
// src/commands/builtin-source.ts
|
|
1047
|
-
var
|
|
1082
|
+
var import_agent_core3 = require("@robota-sdk/agent-core");
|
|
1048
1083
|
function buildModelSubcommands() {
|
|
1049
1084
|
const seen = /* @__PURE__ */ new Set();
|
|
1050
1085
|
const commands = [];
|
|
1051
|
-
for (const model of Object.values(
|
|
1086
|
+
for (const model of Object.values(import_agent_core3.CLAUDE_MODELS)) {
|
|
1052
1087
|
if (seen.has(model.name)) continue;
|
|
1053
1088
|
seen.add(model.name);
|
|
1054
1089
|
commands.push({
|
|
1055
1090
|
name: model.id,
|
|
1056
|
-
description: `${model.name} (${(0,
|
|
1091
|
+
description: `${model.name} (${(0, import_agent_core3.formatTokenCount)(model.contextWindow).toUpperCase()})`,
|
|
1057
1092
|
source: "builtin"
|
|
1058
1093
|
});
|
|
1059
1094
|
}
|
|
@@ -1095,22 +1130,7 @@ function createBuiltinCommands() {
|
|
|
1095
1130
|
{ name: "cost", description: "Show session info", source: "builtin" },
|
|
1096
1131
|
{ name: "context", description: "Context window info", source: "builtin" },
|
|
1097
1132
|
{ name: "permissions", description: "Permission rules", source: "builtin" },
|
|
1098
|
-
{
|
|
1099
|
-
name: "plugin",
|
|
1100
|
-
description: "Manage plugins",
|
|
1101
|
-
source: "builtin",
|
|
1102
|
-
subcommands: [
|
|
1103
|
-
{ name: "install", description: "Install a plugin (name@marketplace)", source: "builtin" },
|
|
1104
|
-
{
|
|
1105
|
-
name: "uninstall",
|
|
1106
|
-
description: "Uninstall a plugin (name@marketplace)",
|
|
1107
|
-
source: "builtin"
|
|
1108
|
-
},
|
|
1109
|
-
{ name: "enable", description: "Enable a plugin (name@marketplace)", source: "builtin" },
|
|
1110
|
-
{ name: "disable", description: "Disable a plugin (name@marketplace)", source: "builtin" },
|
|
1111
|
-
{ name: "marketplace", description: "Manage marketplace sources", source: "builtin" }
|
|
1112
|
-
]
|
|
1113
|
-
},
|
|
1133
|
+
{ name: "plugin", description: "Manage plugins", source: "builtin" },
|
|
1114
1134
|
{ name: "reload-plugins", description: "Reload all plugin resources", source: "builtin" },
|
|
1115
1135
|
{ name: "reset", description: "Delete settings and exit", source: "builtin" },
|
|
1116
1136
|
{ name: "exit", description: "Exit CLI", source: "builtin" }
|
|
@@ -1377,18 +1397,50 @@ function usePluginCallbacks(cwd) {
|
|
|
1377
1397
|
return {
|
|
1378
1398
|
listInstalled: async () => {
|
|
1379
1399
|
const plugins = await loader.loadAll();
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1400
|
+
const enabledMap = settingsStore.getEnabledPlugins();
|
|
1401
|
+
return plugins.map((p) => {
|
|
1402
|
+
const parts = p.pluginDir.split("/");
|
|
1403
|
+
const cacheIdx = parts.indexOf("cache");
|
|
1404
|
+
const marketplaceName = cacheIdx >= 0 ? parts[cacheIdx + 1] : "";
|
|
1405
|
+
const fullId = marketplaceName ? `${p.manifest.name}@${marketplaceName}` : p.manifest.name;
|
|
1406
|
+
return {
|
|
1407
|
+
name: fullId,
|
|
1408
|
+
description: p.manifest.description,
|
|
1409
|
+
enabled: enabledMap[fullId] !== false && enabledMap[p.manifest.name] !== false
|
|
1410
|
+
};
|
|
1411
|
+
});
|
|
1412
|
+
},
|
|
1413
|
+
listAvailablePlugins: async (marketplaceName) => {
|
|
1414
|
+
let manifest;
|
|
1415
|
+
try {
|
|
1416
|
+
manifest = marketplace.fetchManifest(marketplaceName);
|
|
1417
|
+
} catch {
|
|
1418
|
+
return [];
|
|
1419
|
+
}
|
|
1420
|
+
const installed = installer.getInstalledPlugins();
|
|
1421
|
+
const installedNames = new Set(Object.values(installed).map((r) => r.pluginName));
|
|
1422
|
+
return manifest.plugins.map((p) => ({
|
|
1423
|
+
name: p.name,
|
|
1424
|
+
description: p.description,
|
|
1425
|
+
installed: installedNames.has(p.name)
|
|
1384
1426
|
}));
|
|
1385
1427
|
},
|
|
1386
|
-
install: async (pluginId) => {
|
|
1428
|
+
install: async (pluginId, scope) => {
|
|
1387
1429
|
const [name, marketplaceName] = pluginId.split("@");
|
|
1388
1430
|
if (!name || !marketplaceName) {
|
|
1389
1431
|
throw new Error("Plugin ID must be in format: name@marketplace");
|
|
1390
1432
|
}
|
|
1391
|
-
|
|
1433
|
+
if (scope === "project") {
|
|
1434
|
+
const projectPluginsDir = (0, import_node_path4.join)(cwd, ".robota", "plugins");
|
|
1435
|
+
const projectInstaller = new import_agent_sdk4.BundlePluginInstaller({
|
|
1436
|
+
pluginsDir: projectPluginsDir,
|
|
1437
|
+
settingsStore,
|
|
1438
|
+
marketplaceClient: marketplace
|
|
1439
|
+
});
|
|
1440
|
+
await projectInstaller.install(name, marketplaceName);
|
|
1441
|
+
} else {
|
|
1442
|
+
await installer.install(name, marketplaceName);
|
|
1443
|
+
}
|
|
1392
1444
|
},
|
|
1393
1445
|
uninstall: async (pluginId) => {
|
|
1394
1446
|
await installer.uninstall(pluginId);
|
|
@@ -1431,6 +1483,7 @@ function usePluginCallbacks(cwd) {
|
|
|
1431
1483
|
// src/ui/MessageList.tsx
|
|
1432
1484
|
var import_react7 = __toESM(require("react"), 1);
|
|
1433
1485
|
var import_ink2 = require("ink");
|
|
1486
|
+
var import_agent_core4 = require("@robota-sdk/agent-core");
|
|
1434
1487
|
|
|
1435
1488
|
// src/ui/render-markdown.ts
|
|
1436
1489
|
var import_marked = require("marked");
|
|
@@ -1516,9 +1569,14 @@ function RoleLabel({ role }) {
|
|
|
1516
1569
|
}
|
|
1517
1570
|
}
|
|
1518
1571
|
function ToolMessage({ message }) {
|
|
1572
|
+
if (!(0, import_agent_core4.isToolMessage)(message)) {
|
|
1573
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, {});
|
|
1574
|
+
}
|
|
1575
|
+
const toolName = message.name;
|
|
1576
|
+
const content = message.content;
|
|
1519
1577
|
let summaries = null;
|
|
1520
1578
|
try {
|
|
1521
|
-
const parsed = JSON.parse(
|
|
1579
|
+
const parsed = JSON.parse(content);
|
|
1522
1580
|
if (Array.isArray(parsed) && parsed.length > 0 && typeof parsed[0].line === "string") {
|
|
1523
1581
|
summaries = parsed;
|
|
1524
1582
|
}
|
|
@@ -1531,9 +1589,9 @@ function ToolMessage({ message }) {
|
|
|
1531
1589
|
"Tool:",
|
|
1532
1590
|
" "
|
|
1533
1591
|
] }),
|
|
1534
|
-
|
|
1592
|
+
toolName && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ink2.Text, { color: "white", dimColor: true, children: [
|
|
1535
1593
|
"[",
|
|
1536
|
-
|
|
1594
|
+
toolName,
|
|
1537
1595
|
"]"
|
|
1538
1596
|
] })
|
|
1539
1597
|
] }),
|
|
@@ -1549,16 +1607,16 @@ function ToolMessage({ message }) {
|
|
|
1549
1607
|
] }, i))
|
|
1550
1608
|
] });
|
|
1551
1609
|
}
|
|
1552
|
-
const lines =
|
|
1610
|
+
const lines = content.split("\n").filter((l) => l.trim());
|
|
1553
1611
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ink2.Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
1554
1612
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ink2.Box, { children: [
|
|
1555
1613
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ink2.Text, { color: "white", bold: true, children: [
|
|
1556
1614
|
"Tool:",
|
|
1557
1615
|
" "
|
|
1558
1616
|
] }),
|
|
1559
|
-
|
|
1617
|
+
toolName && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ink2.Text, { color: "white", dimColor: true, children: [
|
|
1560
1618
|
"[",
|
|
1561
|
-
|
|
1619
|
+
toolName,
|
|
1562
1620
|
"]"
|
|
1563
1621
|
] })
|
|
1564
1622
|
] }),
|
|
@@ -1574,21 +1632,15 @@ function ToolMessage({ message }) {
|
|
|
1574
1632
|
var MessageItem = import_react7.default.memo(function MessageItem2({
|
|
1575
1633
|
message
|
|
1576
1634
|
}) {
|
|
1577
|
-
if (
|
|
1635
|
+
if ((0, import_agent_core4.isToolMessage)(message)) {
|
|
1578
1636
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ToolMessage, { message });
|
|
1579
1637
|
}
|
|
1638
|
+
const content = message.content ?? "";
|
|
1639
|
+
const isInterrupted = message.state === "interrupted";
|
|
1580
1640
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ink2.Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
1581
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.
|
|
1582
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(RoleLabel, { role: message.role }),
|
|
1583
|
-
message.toolName && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ink2.Text, { color: "magenta", dimColor: true, children: [
|
|
1584
|
-
"[",
|
|
1585
|
-
message.toolName,
|
|
1586
|
-
"]",
|
|
1587
|
-
" "
|
|
1588
|
-
] })
|
|
1589
|
-
] }),
|
|
1641
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ink2.Box, { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(RoleLabel, { role: message.role }) }),
|
|
1590
1642
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ink2.Text, { children: " " }),
|
|
1591
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ink2.Box, { marginLeft: 2, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ink2.Text, { wrap: "wrap", children: message
|
|
1643
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ink2.Box, { marginLeft: 2, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ink2.Text, { wrap: "wrap", children: (0, import_agent_core4.isAssistantMessage)(message) ? renderMarkdown(content + (isInterrupted ? "\n\n_(interrupted)_" : "")) : content }) })
|
|
1592
1644
|
] });
|
|
1593
1645
|
});
|
|
1594
1646
|
function MessageList({ messages }) {
|
|
@@ -1597,7 +1649,7 @@ function MessageList({ messages }) {
|
|
|
1597
1649
|
|
|
1598
1650
|
// src/ui/StatusBar.tsx
|
|
1599
1651
|
var import_ink3 = require("ink");
|
|
1600
|
-
var
|
|
1652
|
+
var import_agent_core5 = require("@robota-sdk/agent-core");
|
|
1601
1653
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
1602
1654
|
var CONTEXT_YELLOW_THRESHOLD = 70;
|
|
1603
1655
|
var CONTEXT_RED_THRESHOLD = 90;
|
|
@@ -1637,9 +1689,9 @@ function StatusBar({
|
|
|
1637
1689
|
"Context: ",
|
|
1638
1690
|
Math.round(contextPercentage),
|
|
1639
1691
|
"% (",
|
|
1640
|
-
(0,
|
|
1692
|
+
(0, import_agent_core5.formatTokenCount)(contextUsedTokens),
|
|
1641
1693
|
"/",
|
|
1642
|
-
(0,
|
|
1694
|
+
(0, import_agent_core5.formatTokenCount)(contextMaxTokens),
|
|
1643
1695
|
")"
|
|
1644
1696
|
] })
|
|
1645
1697
|
] }),
|
|
@@ -1967,7 +2019,7 @@ function InputArea({ onSubmit, isDisabled, registry }) {
|
|
|
1967
2019
|
isSubcommandMode
|
|
1968
2020
|
}
|
|
1969
2021
|
),
|
|
1970
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_ink7.Box, { borderStyle: "single", borderColor: isDisabled ? "gray" : "green", paddingLeft: 1, children: isDisabled ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(WaveText, { text: " Waiting for response..." }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_ink7.Box, { children: [
|
|
2022
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_ink7.Box, { borderStyle: "single", borderColor: isDisabled ? "gray" : "green", paddingLeft: 1, children: isDisabled ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(WaveText, { text: " Waiting for response... (ESC to interrupt)" }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_ink7.Box, { children: [
|
|
1971
2023
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_ink7.Text, { color: "green", bold: true, children: "> " }),
|
|
1972
2024
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1973
2025
|
CjkTextInput,
|
|
@@ -2103,7 +2155,7 @@ function StreamingIndicator({ text, activeTools }) {
|
|
|
2103
2155
|
const hasTools = activeTools.length > 0;
|
|
2104
2156
|
const hasText = text.length > 0;
|
|
2105
2157
|
if (!hasTools && !hasText) {
|
|
2106
|
-
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2158
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_jsx_runtime10.Fragment, {});
|
|
2107
2159
|
}
|
|
2108
2160
|
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_ink10.Box, { flexDirection: "column", children: [
|
|
2109
2161
|
hasTools && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_ink10.Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
@@ -2133,8 +2185,459 @@ function StreamingIndicator({ text, activeTools }) {
|
|
|
2133
2185
|
] });
|
|
2134
2186
|
}
|
|
2135
2187
|
|
|
2136
|
-
// src/ui/
|
|
2188
|
+
// src/ui/PluginTUI.tsx
|
|
2189
|
+
var import_react15 = require("react");
|
|
2190
|
+
|
|
2191
|
+
// src/ui/MenuSelect.tsx
|
|
2192
|
+
var import_react13 = require("react");
|
|
2193
|
+
var import_ink11 = require("ink");
|
|
2137
2194
|
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
2195
|
+
function MenuSelect({
|
|
2196
|
+
title,
|
|
2197
|
+
items,
|
|
2198
|
+
onSelect,
|
|
2199
|
+
onBack,
|
|
2200
|
+
loading,
|
|
2201
|
+
error
|
|
2202
|
+
}) {
|
|
2203
|
+
const [selected, setSelected] = (0, import_react13.useState)(0);
|
|
2204
|
+
const selectedRef = (0, import_react13.useRef)(0);
|
|
2205
|
+
const resolvedRef = (0, import_react13.useRef)(false);
|
|
2206
|
+
const doSelect = (0, import_react13.useCallback)(
|
|
2207
|
+
(index) => {
|
|
2208
|
+
if (resolvedRef.current || items.length === 0) return;
|
|
2209
|
+
resolvedRef.current = true;
|
|
2210
|
+
onSelect(items[index].value);
|
|
2211
|
+
},
|
|
2212
|
+
[items, onSelect]
|
|
2213
|
+
);
|
|
2214
|
+
(0, import_ink11.useInput)((input, key) => {
|
|
2215
|
+
if (resolvedRef.current) return;
|
|
2216
|
+
if (key.escape) {
|
|
2217
|
+
resolvedRef.current = true;
|
|
2218
|
+
onBack();
|
|
2219
|
+
return;
|
|
2220
|
+
}
|
|
2221
|
+
if (loading || error || items.length === 0) return;
|
|
2222
|
+
if (key.upArrow) {
|
|
2223
|
+
const next = selectedRef.current > 0 ? selectedRef.current - 1 : selectedRef.current;
|
|
2224
|
+
selectedRef.current = next;
|
|
2225
|
+
setSelected(next);
|
|
2226
|
+
} else if (key.downArrow) {
|
|
2227
|
+
const next = selectedRef.current < items.length - 1 ? selectedRef.current + 1 : selectedRef.current;
|
|
2228
|
+
selectedRef.current = next;
|
|
2229
|
+
setSelected(next);
|
|
2230
|
+
} else if (key.return) {
|
|
2231
|
+
doSelect(selectedRef.current);
|
|
2232
|
+
}
|
|
2233
|
+
});
|
|
2234
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_ink11.Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
|
|
2235
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_ink11.Text, { color: "yellow", bold: true, children: title }),
|
|
2236
|
+
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..." }) }),
|
|
2237
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_ink11.Box, { marginTop: 1, flexDirection: "column", children: [
|
|
2238
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_ink11.Text, { color: "red", children: error }),
|
|
2239
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_ink11.Text, { dimColor: true, children: "Press Esc to go back" })
|
|
2240
|
+
] }),
|
|
2241
|
+
!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: [
|
|
2242
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_ink11.Text, { color: i === selected ? "cyan" : void 0, bold: i === selected, children: [
|
|
2243
|
+
i === selected ? "> " : " ",
|
|
2244
|
+
item.label
|
|
2245
|
+
] }),
|
|
2246
|
+
item.hint && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_ink11.Text, { dimColor: true, children: [
|
|
2247
|
+
" ",
|
|
2248
|
+
item.hint
|
|
2249
|
+
] })
|
|
2250
|
+
] }, item.value)) }),
|
|
2251
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_ink11.Text, { dimColor: true, children: loading || error ? "" : " \u2191\u2193 Navigate Enter Select Esc Back" })
|
|
2252
|
+
] });
|
|
2253
|
+
}
|
|
2254
|
+
|
|
2255
|
+
// src/ui/TextPrompt.tsx
|
|
2256
|
+
var import_react14 = require("react");
|
|
2257
|
+
var import_ink12 = require("ink");
|
|
2258
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
2259
|
+
function TextPrompt({
|
|
2260
|
+
title,
|
|
2261
|
+
placeholder,
|
|
2262
|
+
onSubmit,
|
|
2263
|
+
onCancel,
|
|
2264
|
+
validate
|
|
2265
|
+
}) {
|
|
2266
|
+
const [value, setValue] = (0, import_react14.useState)("");
|
|
2267
|
+
const [error, setError] = (0, import_react14.useState)();
|
|
2268
|
+
const resolvedRef = (0, import_react14.useRef)(false);
|
|
2269
|
+
const valueRef = (0, import_react14.useRef)("");
|
|
2270
|
+
const handleSubmit = (0, import_react14.useCallback)(() => {
|
|
2271
|
+
if (resolvedRef.current) return;
|
|
2272
|
+
const trimmed = valueRef.current.trim();
|
|
2273
|
+
if (!trimmed) return;
|
|
2274
|
+
if (validate) {
|
|
2275
|
+
const err = validate(trimmed);
|
|
2276
|
+
if (err) {
|
|
2277
|
+
setError(err);
|
|
2278
|
+
return;
|
|
2279
|
+
}
|
|
2280
|
+
}
|
|
2281
|
+
resolvedRef.current = true;
|
|
2282
|
+
onSubmit(trimmed);
|
|
2283
|
+
}, [validate, onSubmit]);
|
|
2284
|
+
(0, import_ink12.useInput)((input, key) => {
|
|
2285
|
+
if (resolvedRef.current) return;
|
|
2286
|
+
if (key.escape) {
|
|
2287
|
+
resolvedRef.current = true;
|
|
2288
|
+
onCancel();
|
|
2289
|
+
return;
|
|
2290
|
+
}
|
|
2291
|
+
if (key.return) {
|
|
2292
|
+
handleSubmit();
|
|
2293
|
+
return;
|
|
2294
|
+
}
|
|
2295
|
+
if (key.backspace || key.delete) {
|
|
2296
|
+
valueRef.current = valueRef.current.slice(0, -1);
|
|
2297
|
+
setValue(valueRef.current);
|
|
2298
|
+
setError(void 0);
|
|
2299
|
+
return;
|
|
2300
|
+
}
|
|
2301
|
+
if (input && !key.ctrl && !key.meta) {
|
|
2302
|
+
valueRef.current = valueRef.current + input;
|
|
2303
|
+
setValue(valueRef.current);
|
|
2304
|
+
setError(void 0);
|
|
2305
|
+
}
|
|
2306
|
+
});
|
|
2307
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_ink12.Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
|
|
2308
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_ink12.Text, { color: "yellow", bold: true, children: title }),
|
|
2309
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_ink12.Box, { marginTop: 1, children: [
|
|
2310
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_ink12.Text, { color: "cyan", children: "> " }),
|
|
2311
|
+
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,
|
|
2312
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_ink12.Text, { color: "cyan", children: "\u2588" })
|
|
2313
|
+
] }),
|
|
2314
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_ink12.Text, { color: "red", children: error }),
|
|
2315
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_ink12.Text, { dimColor: true, children: " Enter Submit Esc Cancel" })
|
|
2316
|
+
] });
|
|
2317
|
+
}
|
|
2318
|
+
|
|
2319
|
+
// src/ui/plugin-tui-handlers.ts
|
|
2320
|
+
function handleMainSelect(value, nav) {
|
|
2321
|
+
if (value === "marketplace") {
|
|
2322
|
+
nav.push({ screen: "marketplace-list" });
|
|
2323
|
+
} else if (value === "installed") {
|
|
2324
|
+
nav.push({ screen: "installed-list" });
|
|
2325
|
+
}
|
|
2326
|
+
}
|
|
2327
|
+
function handleMarketplaceListSelect(value, nav) {
|
|
2328
|
+
if (value === "__add__") {
|
|
2329
|
+
nav.push({ screen: "marketplace-add" });
|
|
2330
|
+
} else {
|
|
2331
|
+
nav.push({ screen: "marketplace-action", context: { marketplace: value } });
|
|
2332
|
+
}
|
|
2333
|
+
}
|
|
2334
|
+
function handleMarketplaceActionSelect(value, marketplace, callbacks, nav) {
|
|
2335
|
+
if (value === "browse") {
|
|
2336
|
+
nav.push({ screen: "marketplace-browse", context: { marketplace } });
|
|
2337
|
+
} else if (value === "update") {
|
|
2338
|
+
callbacks.marketplaceUpdate(marketplace).then(() => {
|
|
2339
|
+
nav.notify(`Updated marketplace "${marketplace}".`);
|
|
2340
|
+
nav.pop();
|
|
2341
|
+
}).catch((err) => {
|
|
2342
|
+
nav.notify(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
2343
|
+
});
|
|
2344
|
+
} else if (value === "remove") {
|
|
2345
|
+
nav.setConfirm({
|
|
2346
|
+
message: `Remove marketplace "${marketplace}" and all its plugins?`,
|
|
2347
|
+
onConfirm: () => {
|
|
2348
|
+
nav.setConfirm(void 0);
|
|
2349
|
+
callbacks.marketplaceRemove(marketplace).then(() => {
|
|
2350
|
+
nav.notify(`Removed marketplace "${marketplace}".`);
|
|
2351
|
+
nav.popN(2);
|
|
2352
|
+
}).catch((err) => {
|
|
2353
|
+
nav.notify(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
2354
|
+
});
|
|
2355
|
+
},
|
|
2356
|
+
onCancel: () => nav.setConfirm(void 0)
|
|
2357
|
+
});
|
|
2358
|
+
}
|
|
2359
|
+
}
|
|
2360
|
+
function handleMarketplaceBrowseSelect(value, marketplace, items, nav) {
|
|
2361
|
+
const fullId = `${value}@${marketplace}`;
|
|
2362
|
+
const item = items.find((i) => i.value === value);
|
|
2363
|
+
if (item?.hint === "installed") {
|
|
2364
|
+
nav.push({ screen: "installed-action", context: { pluginId: fullId } });
|
|
2365
|
+
} else {
|
|
2366
|
+
nav.push({ screen: "marketplace-install-scope", context: { marketplace, pluginId: fullId } });
|
|
2367
|
+
}
|
|
2368
|
+
}
|
|
2369
|
+
function handleInstallScopeSelect(value, pluginId, callbacks, nav) {
|
|
2370
|
+
const scope = value;
|
|
2371
|
+
callbacks.install(pluginId, scope).then(() => {
|
|
2372
|
+
nav.notify(`Installed plugin "${pluginId}" (${scope} scope).`);
|
|
2373
|
+
nav.popN(2);
|
|
2374
|
+
}).catch((err) => {
|
|
2375
|
+
nav.notify(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
2376
|
+
});
|
|
2377
|
+
}
|
|
2378
|
+
function handleInstalledListSelect(value, callbacks, nav) {
|
|
2379
|
+
nav.setConfirm({
|
|
2380
|
+
message: `Uninstall plugin "${value}"?`,
|
|
2381
|
+
onConfirm: () => {
|
|
2382
|
+
nav.setConfirm(void 0);
|
|
2383
|
+
callbacks.uninstall(value).then(() => {
|
|
2384
|
+
nav.notify(`Uninstalled plugin "${value}".`);
|
|
2385
|
+
nav.refresh();
|
|
2386
|
+
}).catch((err) => {
|
|
2387
|
+
nav.notify(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
2388
|
+
});
|
|
2389
|
+
},
|
|
2390
|
+
onCancel: () => nav.setConfirm(void 0)
|
|
2391
|
+
});
|
|
2392
|
+
}
|
|
2393
|
+
function handleInstalledActionSelect(value, pluginId, callbacks, nav) {
|
|
2394
|
+
if (value === "uninstall") {
|
|
2395
|
+
nav.setConfirm({
|
|
2396
|
+
message: `Uninstall plugin "${pluginId}"?`,
|
|
2397
|
+
onConfirm: () => {
|
|
2398
|
+
nav.setConfirm(void 0);
|
|
2399
|
+
callbacks.uninstall(pluginId).then(() => {
|
|
2400
|
+
nav.notify(`Uninstalled plugin "${pluginId}".`);
|
|
2401
|
+
nav.popN(2);
|
|
2402
|
+
}).catch((err) => {
|
|
2403
|
+
nav.notify(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
2404
|
+
});
|
|
2405
|
+
},
|
|
2406
|
+
onCancel: () => nav.setConfirm(void 0)
|
|
2407
|
+
});
|
|
2408
|
+
}
|
|
2409
|
+
}
|
|
2410
|
+
|
|
2411
|
+
// src/ui/PluginTUI.tsx
|
|
2412
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
2413
|
+
function PluginTUI({ callbacks, onClose, addMessage }) {
|
|
2414
|
+
const [stack, setStack] = (0, import_react15.useState)([{ screen: "main" }]);
|
|
2415
|
+
const [items, setItems] = (0, import_react15.useState)([]);
|
|
2416
|
+
const [loading, setLoading] = (0, import_react15.useState)(false);
|
|
2417
|
+
const [error, setError] = (0, import_react15.useState)();
|
|
2418
|
+
const [confirm, setConfirm] = (0, import_react15.useState)();
|
|
2419
|
+
const [refreshCounter, setRefreshCounter] = (0, import_react15.useState)(0);
|
|
2420
|
+
const current = stack[stack.length - 1] ?? { screen: "main" };
|
|
2421
|
+
const push = (0, import_react15.useCallback)((state) => {
|
|
2422
|
+
setStack((prev) => [...prev, state]);
|
|
2423
|
+
setItems([]);
|
|
2424
|
+
setError(void 0);
|
|
2425
|
+
}, []);
|
|
2426
|
+
const pop = (0, import_react15.useCallback)(() => {
|
|
2427
|
+
setStack((prev) => {
|
|
2428
|
+
if (prev.length <= 1) {
|
|
2429
|
+
onClose();
|
|
2430
|
+
return prev;
|
|
2431
|
+
}
|
|
2432
|
+
return prev.slice(0, -1);
|
|
2433
|
+
});
|
|
2434
|
+
setItems([]);
|
|
2435
|
+
setError(void 0);
|
|
2436
|
+
}, [onClose]);
|
|
2437
|
+
const popN = (0, import_react15.useCallback)(
|
|
2438
|
+
(n) => {
|
|
2439
|
+
setStack((prev) => {
|
|
2440
|
+
const next = prev.slice(0, Math.max(1, prev.length - n));
|
|
2441
|
+
if (next.length === 0) {
|
|
2442
|
+
onClose();
|
|
2443
|
+
return prev;
|
|
2444
|
+
}
|
|
2445
|
+
return next;
|
|
2446
|
+
});
|
|
2447
|
+
setItems([]);
|
|
2448
|
+
setError(void 0);
|
|
2449
|
+
},
|
|
2450
|
+
[onClose]
|
|
2451
|
+
);
|
|
2452
|
+
const notify = (0, import_react15.useCallback)(
|
|
2453
|
+
(content) => {
|
|
2454
|
+
addMessage?.({ role: "system", content });
|
|
2455
|
+
},
|
|
2456
|
+
[addMessage]
|
|
2457
|
+
);
|
|
2458
|
+
const refresh = (0, import_react15.useCallback)(() => {
|
|
2459
|
+
setItems([]);
|
|
2460
|
+
setRefreshCounter((c) => c + 1);
|
|
2461
|
+
}, []);
|
|
2462
|
+
const nav = { push, pop, popN, notify, setConfirm, refresh };
|
|
2463
|
+
(0, import_react15.useEffect)(() => {
|
|
2464
|
+
const screen2 = current.screen;
|
|
2465
|
+
if (screen2 === "marketplace-list") {
|
|
2466
|
+
setLoading(true);
|
|
2467
|
+
callbacks.marketplaceList().then((sources) => {
|
|
2468
|
+
const baseItems = [{ label: "Add Marketplace", value: "__add__" }];
|
|
2469
|
+
const sourceItems = sources.map((s) => ({
|
|
2470
|
+
label: s.name,
|
|
2471
|
+
value: s.name,
|
|
2472
|
+
hint: s.type
|
|
2473
|
+
}));
|
|
2474
|
+
setItems([...baseItems, ...sourceItems]);
|
|
2475
|
+
setLoading(false);
|
|
2476
|
+
}).catch((err) => {
|
|
2477
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
2478
|
+
setLoading(false);
|
|
2479
|
+
});
|
|
2480
|
+
} else if (screen2 === "marketplace-browse") {
|
|
2481
|
+
const marketplace = current.context?.marketplace ?? "";
|
|
2482
|
+
setLoading(true);
|
|
2483
|
+
callbacks.listAvailablePlugins(marketplace).then((plugins) => {
|
|
2484
|
+
setItems(
|
|
2485
|
+
plugins.map((p) => ({
|
|
2486
|
+
label: p.name,
|
|
2487
|
+
value: p.name,
|
|
2488
|
+
hint: p.installed ? "installed" : p.description
|
|
2489
|
+
}))
|
|
2490
|
+
);
|
|
2491
|
+
setLoading(false);
|
|
2492
|
+
}).catch((err) => {
|
|
2493
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
2494
|
+
setLoading(false);
|
|
2495
|
+
});
|
|
2496
|
+
} else if (screen2 === "installed-list") {
|
|
2497
|
+
setLoading(true);
|
|
2498
|
+
callbacks.listInstalled().then((plugins) => {
|
|
2499
|
+
setItems(
|
|
2500
|
+
plugins.map((p) => ({
|
|
2501
|
+
label: p.name,
|
|
2502
|
+
value: p.name,
|
|
2503
|
+
hint: p.description
|
|
2504
|
+
}))
|
|
2505
|
+
);
|
|
2506
|
+
setLoading(false);
|
|
2507
|
+
}).catch((err) => {
|
|
2508
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
2509
|
+
setLoading(false);
|
|
2510
|
+
});
|
|
2511
|
+
}
|
|
2512
|
+
}, [stack.length, current.screen, current.context?.marketplace, callbacks, refreshCounter]);
|
|
2513
|
+
const handleSelect = (0, import_react15.useCallback)(
|
|
2514
|
+
(value) => {
|
|
2515
|
+
const screen2 = current.screen;
|
|
2516
|
+
const ctx = current.context;
|
|
2517
|
+
if (screen2 === "main") handleMainSelect(value, nav);
|
|
2518
|
+
else if (screen2 === "marketplace-list") handleMarketplaceListSelect(value, nav);
|
|
2519
|
+
else if (screen2 === "marketplace-action")
|
|
2520
|
+
handleMarketplaceActionSelect(value, ctx?.marketplace ?? "", callbacks, nav);
|
|
2521
|
+
else if (screen2 === "marketplace-browse")
|
|
2522
|
+
handleMarketplaceBrowseSelect(value, ctx?.marketplace ?? "", items, nav);
|
|
2523
|
+
else if (screen2 === "marketplace-install-scope")
|
|
2524
|
+
handleInstallScopeSelect(value, ctx?.pluginId ?? "", callbacks, nav);
|
|
2525
|
+
else if (screen2 === "installed-list") handleInstalledListSelect(value, callbacks, nav);
|
|
2526
|
+
else if (screen2 === "installed-action")
|
|
2527
|
+
handleInstalledActionSelect(value, ctx?.pluginId ?? "", callbacks, nav);
|
|
2528
|
+
},
|
|
2529
|
+
[current, items, callbacks, push, pop, popN, notify, setConfirm, refresh]
|
|
2530
|
+
);
|
|
2531
|
+
const handleTextSubmit = (0, import_react15.useCallback)(
|
|
2532
|
+
(value) => {
|
|
2533
|
+
if (current.screen === "marketplace-add") {
|
|
2534
|
+
callbacks.marketplaceAdd(value).then((name) => {
|
|
2535
|
+
notify(`Added marketplace "${name}" from ${value}.`);
|
|
2536
|
+
pop();
|
|
2537
|
+
}).catch((err) => {
|
|
2538
|
+
notify(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
2539
|
+
pop();
|
|
2540
|
+
});
|
|
2541
|
+
}
|
|
2542
|
+
},
|
|
2543
|
+
[current.screen, callbacks, notify, pop]
|
|
2544
|
+
);
|
|
2545
|
+
if (confirm) {
|
|
2546
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2547
|
+
ConfirmPrompt,
|
|
2548
|
+
{
|
|
2549
|
+
message: confirm.message,
|
|
2550
|
+
onSelect: (index) => {
|
|
2551
|
+
if (index === 0) confirm.onConfirm();
|
|
2552
|
+
else confirm.onCancel();
|
|
2553
|
+
}
|
|
2554
|
+
}
|
|
2555
|
+
);
|
|
2556
|
+
}
|
|
2557
|
+
const screen = current.screen;
|
|
2558
|
+
if (screen === "marketplace-add") {
|
|
2559
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2560
|
+
TextPrompt,
|
|
2561
|
+
{
|
|
2562
|
+
title: "Add Marketplace Source",
|
|
2563
|
+
placeholder: "owner/repo or git URL",
|
|
2564
|
+
onSubmit: handleTextSubmit,
|
|
2565
|
+
onCancel: pop,
|
|
2566
|
+
validate: (v) => !v.includes("/") ? "Must be owner/repo or a git URL" : void 0
|
|
2567
|
+
}
|
|
2568
|
+
);
|
|
2569
|
+
}
|
|
2570
|
+
if (screen === "marketplace-action") {
|
|
2571
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2572
|
+
MenuSelect,
|
|
2573
|
+
{
|
|
2574
|
+
title: `Marketplace: ${current.context?.marketplace ?? ""}`,
|
|
2575
|
+
items: [
|
|
2576
|
+
{ label: "Browse plugins", value: "browse" },
|
|
2577
|
+
{ label: "Update", value: "update" },
|
|
2578
|
+
{ label: "Remove", value: "remove" }
|
|
2579
|
+
],
|
|
2580
|
+
onSelect: handleSelect,
|
|
2581
|
+
onBack: pop
|
|
2582
|
+
},
|
|
2583
|
+
stack.length
|
|
2584
|
+
);
|
|
2585
|
+
}
|
|
2586
|
+
if (screen === "marketplace-install-scope") {
|
|
2587
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2588
|
+
MenuSelect,
|
|
2589
|
+
{
|
|
2590
|
+
title: `Install scope for "${current.context?.pluginId ?? ""}"`,
|
|
2591
|
+
items: [
|
|
2592
|
+
{ label: "User scope", value: "user" },
|
|
2593
|
+
{ label: "Project scope", value: "project" }
|
|
2594
|
+
],
|
|
2595
|
+
onSelect: handleSelect,
|
|
2596
|
+
onBack: pop
|
|
2597
|
+
},
|
|
2598
|
+
stack.length
|
|
2599
|
+
);
|
|
2600
|
+
}
|
|
2601
|
+
if (screen === "installed-action") {
|
|
2602
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2603
|
+
MenuSelect,
|
|
2604
|
+
{
|
|
2605
|
+
title: `Plugin: ${current.context?.pluginId ?? ""}`,
|
|
2606
|
+
items: [{ label: "Uninstall", value: "uninstall" }],
|
|
2607
|
+
onSelect: handleSelect,
|
|
2608
|
+
onBack: pop
|
|
2609
|
+
},
|
|
2610
|
+
stack.length
|
|
2611
|
+
);
|
|
2612
|
+
}
|
|
2613
|
+
const titleMap = {
|
|
2614
|
+
main: "Plugin Management",
|
|
2615
|
+
"marketplace-list": "Marketplace",
|
|
2616
|
+
"marketplace-browse": `Browse: ${current.context?.marketplace ?? ""}`,
|
|
2617
|
+
"installed-list": "Installed Plugins"
|
|
2618
|
+
};
|
|
2619
|
+
const staticItemsMap = {
|
|
2620
|
+
main: [
|
|
2621
|
+
{ label: "Marketplace", value: "marketplace" },
|
|
2622
|
+
{ label: "Installed Plugins", value: "installed" }
|
|
2623
|
+
]
|
|
2624
|
+
};
|
|
2625
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2626
|
+
MenuSelect,
|
|
2627
|
+
{
|
|
2628
|
+
title: titleMap[screen] ?? "Plugin Management",
|
|
2629
|
+
items: staticItemsMap[screen] ?? items,
|
|
2630
|
+
onSelect: handleSelect,
|
|
2631
|
+
onBack: pop,
|
|
2632
|
+
loading,
|
|
2633
|
+
error
|
|
2634
|
+
},
|
|
2635
|
+
`${screen}-${stack.length}-${refreshCounter}`
|
|
2636
|
+
);
|
|
2637
|
+
}
|
|
2638
|
+
|
|
2639
|
+
// src/ui/App.tsx
|
|
2640
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
2138
2641
|
var EXIT_DELAY_MS2 = 500;
|
|
2139
2642
|
function mergeHooksIntoConfig(configHooks, pluginHooks) {
|
|
2140
2643
|
const pluginKeys = Object.keys(pluginHooks);
|
|
@@ -2153,7 +2656,7 @@ function mergeHooksIntoConfig(configHooks, pluginHooks) {
|
|
|
2153
2656
|
return merged;
|
|
2154
2657
|
}
|
|
2155
2658
|
function App(props) {
|
|
2156
|
-
const { exit } = (0,
|
|
2659
|
+
const { exit } = (0, import_ink13.useApp)();
|
|
2157
2660
|
const { registry, pluginHooks } = useCommandRegistry(props.cwd ?? process.cwd());
|
|
2158
2661
|
const configWithPluginHooks = {
|
|
2159
2662
|
...props.config,
|
|
@@ -2166,15 +2669,16 @@ function App(props) {
|
|
|
2166
2669
|
{ ...props, config: configWithPluginHooks }
|
|
2167
2670
|
);
|
|
2168
2671
|
const { messages, setMessages, addMessage } = useMessages();
|
|
2169
|
-
const [isThinking, setIsThinking] = (0,
|
|
2672
|
+
const [isThinking, setIsThinking] = (0, import_react16.useState)(false);
|
|
2170
2673
|
const initialCtx = session.getContextState();
|
|
2171
|
-
const [contextState, setContextState] = (0,
|
|
2674
|
+
const [contextState, setContextState] = (0, import_react16.useState)({
|
|
2172
2675
|
percentage: initialCtx.usedPercentage,
|
|
2173
2676
|
usedTokens: initialCtx.usedTokens,
|
|
2174
2677
|
maxTokens: initialCtx.maxTokens
|
|
2175
2678
|
});
|
|
2176
|
-
const pendingModelChangeRef = (0,
|
|
2177
|
-
const [pendingModelId, setPendingModelId] = (0,
|
|
2679
|
+
const pendingModelChangeRef = (0, import_react16.useRef)(null);
|
|
2680
|
+
const [pendingModelId, setPendingModelId] = (0, import_react16.useState)(null);
|
|
2681
|
+
const [showPluginTUI, setShowPluginTUI] = (0, import_react16.useState)(false);
|
|
2178
2682
|
const pluginCallbacks = usePluginCallbacks(props.cwd ?? process.cwd());
|
|
2179
2683
|
const handleSlashCommand = useSlashCommands(
|
|
2180
2684
|
session,
|
|
@@ -2184,7 +2688,8 @@ function App(props) {
|
|
|
2184
2688
|
registry,
|
|
2185
2689
|
pendingModelChangeRef,
|
|
2186
2690
|
setPendingModelId,
|
|
2187
|
-
pluginCallbacks
|
|
2691
|
+
pluginCallbacks,
|
|
2692
|
+
setShowPluginTUI
|
|
2188
2693
|
);
|
|
2189
2694
|
const handleSubmit = useSubmitHandler(
|
|
2190
2695
|
session,
|
|
@@ -2195,36 +2700,36 @@ function App(props) {
|
|
|
2195
2700
|
setContextState,
|
|
2196
2701
|
registry
|
|
2197
2702
|
);
|
|
2198
|
-
(0,
|
|
2703
|
+
(0, import_ink13.useInput)(
|
|
2199
2704
|
(_input, key) => {
|
|
2200
2705
|
if (key.ctrl && _input === "c") exit();
|
|
2201
2706
|
if (key.escape && isThinking) session.abort();
|
|
2202
2707
|
},
|
|
2203
|
-
{ isActive: !permissionRequest }
|
|
2708
|
+
{ isActive: !permissionRequest && !showPluginTUI }
|
|
2204
2709
|
);
|
|
2205
|
-
return /* @__PURE__ */ (0,
|
|
2206
|
-
/* @__PURE__ */ (0,
|
|
2207
|
-
/* @__PURE__ */ (0,
|
|
2710
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_ink13.Box, { flexDirection: "column", children: [
|
|
2711
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_ink13.Box, { flexDirection: "column", paddingX: 1, marginBottom: 1, children: [
|
|
2712
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_ink13.Text, { color: "cyan", bold: true, children: `
|
|
2208
2713
|
____ ___ ____ ___ _____ _
|
|
2209
2714
|
| _ \\ / _ \\| __ ) / _ \\_ _|/ \\
|
|
2210
2715
|
| |_) | | | | _ \\| | | || | / _ \\
|
|
2211
2716
|
| _ <| |_| | |_) | |_| || |/ ___ \\
|
|
2212
2717
|
|_| \\_\\\\___/|____/ \\___/ |_/_/ \\_\\
|
|
2213
2718
|
` }),
|
|
2214
|
-
/* @__PURE__ */ (0,
|
|
2719
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_ink13.Text, { dimColor: true, children: [
|
|
2215
2720
|
" v",
|
|
2216
2721
|
props.version ?? "0.0.0"
|
|
2217
2722
|
] })
|
|
2218
2723
|
] }),
|
|
2219
|
-
/* @__PURE__ */ (0,
|
|
2220
|
-
/* @__PURE__ */ (0,
|
|
2221
|
-
isThinking && /* @__PURE__ */ (0,
|
|
2724
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_ink13.Box, { flexDirection: "column", paddingX: 1, flexGrow: 1, children: [
|
|
2725
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(MessageList, { messages }),
|
|
2726
|
+
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 }) })
|
|
2222
2727
|
] }),
|
|
2223
|
-
permissionRequest && /* @__PURE__ */ (0,
|
|
2224
|
-
pendingModelId && /* @__PURE__ */ (0,
|
|
2728
|
+
permissionRequest && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(PermissionPrompt, { request: permissionRequest }),
|
|
2729
|
+
pendingModelId && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
2225
2730
|
ConfirmPrompt,
|
|
2226
2731
|
{
|
|
2227
|
-
message: `Change model to ${(0,
|
|
2732
|
+
message: `Change model to ${(0, import_agent_core6.getModelName)(pendingModelId)}? This will restart the session.`,
|
|
2228
2733
|
onSelect: (index) => {
|
|
2229
2734
|
setPendingModelId(null);
|
|
2230
2735
|
pendingModelChangeRef.current = null;
|
|
@@ -2232,28 +2737,38 @@ function App(props) {
|
|
|
2232
2737
|
try {
|
|
2233
2738
|
const settingsPath = getUserSettingsPath();
|
|
2234
2739
|
updateModelInSettings(settingsPath, pendingModelId);
|
|
2235
|
-
addMessage(
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2740
|
+
addMessage(
|
|
2741
|
+
(0, import_agent_core7.createSystemMessage)(
|
|
2742
|
+
`Model changed to ${(0, import_agent_core6.getModelName)(pendingModelId)}. Restarting...`
|
|
2743
|
+
)
|
|
2744
|
+
);
|
|
2239
2745
|
setTimeout(() => exit(), EXIT_DELAY_MS2);
|
|
2240
2746
|
} catch (err) {
|
|
2241
|
-
addMessage(
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2747
|
+
addMessage(
|
|
2748
|
+
(0, import_agent_core7.createSystemMessage)(
|
|
2749
|
+
`Failed: ${err instanceof Error ? err.message : String(err)}`
|
|
2750
|
+
)
|
|
2751
|
+
);
|
|
2245
2752
|
}
|
|
2246
2753
|
} else {
|
|
2247
|
-
addMessage(
|
|
2754
|
+
addMessage((0, import_agent_core7.createSystemMessage)("Model change cancelled."));
|
|
2248
2755
|
}
|
|
2249
2756
|
}
|
|
2250
2757
|
}
|
|
2251
2758
|
),
|
|
2252
|
-
/* @__PURE__ */ (0,
|
|
2759
|
+
showPluginTUI && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
2760
|
+
PluginTUI,
|
|
2761
|
+
{
|
|
2762
|
+
callbacks: pluginCallbacks,
|
|
2763
|
+
onClose: () => setShowPluginTUI(false),
|
|
2764
|
+
addMessage: (msg) => addMessage((0, import_agent_core7.createSystemMessage)(msg.content))
|
|
2765
|
+
}
|
|
2766
|
+
),
|
|
2767
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
2253
2768
|
StatusBar,
|
|
2254
2769
|
{
|
|
2255
2770
|
permissionMode: session.getPermissionMode(),
|
|
2256
|
-
modelName: (0,
|
|
2771
|
+
modelName: (0, import_agent_core6.getModelName)(props.config.provider.model),
|
|
2257
2772
|
sessionId: session.getSessionId(),
|
|
2258
2773
|
messageCount: messages.length,
|
|
2259
2774
|
isThinking,
|
|
@@ -2262,20 +2777,20 @@ function App(props) {
|
|
|
2262
2777
|
contextMaxTokens: contextState.maxTokens
|
|
2263
2778
|
}
|
|
2264
2779
|
),
|
|
2265
|
-
/* @__PURE__ */ (0,
|
|
2780
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
2266
2781
|
InputArea,
|
|
2267
2782
|
{
|
|
2268
2783
|
onSubmit: handleSubmit,
|
|
2269
|
-
isDisabled: isThinking || !!permissionRequest,
|
|
2784
|
+
isDisabled: isThinking || !!permissionRequest || showPluginTUI,
|
|
2270
2785
|
registry
|
|
2271
2786
|
}
|
|
2272
2787
|
),
|
|
2273
|
-
/* @__PURE__ */ (0,
|
|
2788
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_ink13.Text, { children: " " })
|
|
2274
2789
|
] });
|
|
2275
2790
|
}
|
|
2276
2791
|
|
|
2277
2792
|
// src/ui/render.tsx
|
|
2278
|
-
var
|
|
2793
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
2279
2794
|
function renderApp(options) {
|
|
2280
2795
|
process.on("unhandledRejection", (reason) => {
|
|
2281
2796
|
process.stderr.write(`
|
|
@@ -2286,7 +2801,7 @@ function renderApp(options) {
|
|
|
2286
2801
|
`);
|
|
2287
2802
|
}
|
|
2288
2803
|
});
|
|
2289
|
-
const instance = (0,
|
|
2804
|
+
const instance = (0, import_ink14.render)(/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(App, { ...options }), {
|
|
2290
2805
|
exitOnCtrlC: true
|
|
2291
2806
|
});
|
|
2292
2807
|
instance.waitUntilExit().catch((err) => {
|