@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/index.cjs
CHANGED
|
@@ -179,12 +179,13 @@ var PrintTerminal = class {
|
|
|
179
179
|
};
|
|
180
180
|
|
|
181
181
|
// src/ui/render.tsx
|
|
182
|
-
var
|
|
182
|
+
var import_ink14 = require("ink");
|
|
183
183
|
|
|
184
184
|
// src/ui/App.tsx
|
|
185
|
-
var
|
|
186
|
-
var
|
|
187
|
-
var
|
|
185
|
+
var import_react16 = require("react");
|
|
186
|
+
var import_ink13 = require("ink");
|
|
187
|
+
var import_agent_core6 = require("@robota-sdk/agent-core");
|
|
188
|
+
var import_agent_core7 = require("@robota-sdk/agent-core");
|
|
188
189
|
|
|
189
190
|
// src/ui/hooks/useSession.ts
|
|
190
191
|
var import_react = require("react");
|
|
@@ -280,6 +281,7 @@ var NOOP_TERMINAL = {
|
|
|
280
281
|
function useSession(props) {
|
|
281
282
|
const [permissionRequest, setPermissionRequest] = (0, import_react.useState)(null);
|
|
282
283
|
const [streamingText, setStreamingText] = (0, import_react.useState)("");
|
|
284
|
+
const streamingTextRef = (0, import_react.useRef)("");
|
|
283
285
|
const [activeTools, setActiveTools] = (0, import_react.useState)([]);
|
|
284
286
|
const permissionQueueRef = (0, import_react.useRef)([]);
|
|
285
287
|
const processingRef = (0, import_react.useRef)(false);
|
|
@@ -311,8 +313,15 @@ function useSession(props) {
|
|
|
311
313
|
processNextPermission();
|
|
312
314
|
});
|
|
313
315
|
};
|
|
316
|
+
let flushTimer = null;
|
|
314
317
|
const onTextDelta = (delta) => {
|
|
315
|
-
|
|
318
|
+
streamingTextRef.current += delta;
|
|
319
|
+
if (!flushTimer) {
|
|
320
|
+
flushTimer = setTimeout(() => {
|
|
321
|
+
setStreamingText(streamingTextRef.current);
|
|
322
|
+
flushTimer = null;
|
|
323
|
+
}, 16);
|
|
324
|
+
}
|
|
316
325
|
};
|
|
317
326
|
const onToolExecution = (event) => {
|
|
318
327
|
if (event.type === "start") {
|
|
@@ -391,6 +400,7 @@ function useSession(props) {
|
|
|
391
400
|
}
|
|
392
401
|
const clearStreamingText = (0, import_react.useCallback)(() => {
|
|
393
402
|
setStreamingText("");
|
|
403
|
+
streamingTextRef.current = "";
|
|
394
404
|
setActiveTools([]);
|
|
395
405
|
}, []);
|
|
396
406
|
return {
|
|
@@ -405,16 +415,11 @@ function useSession(props) {
|
|
|
405
415
|
// src/ui/hooks/useMessages.ts
|
|
406
416
|
var import_react2 = require("react");
|
|
407
417
|
var MAX_RENDERED_MESSAGES = 100;
|
|
408
|
-
var msgIdCounter = 0;
|
|
409
|
-
function nextId() {
|
|
410
|
-
msgIdCounter += 1;
|
|
411
|
-
return `msg_${msgIdCounter}`;
|
|
412
|
-
}
|
|
413
418
|
function useMessages() {
|
|
414
419
|
const [messages, setMessages] = (0, import_react2.useState)([]);
|
|
415
420
|
const addMessage = (0, import_react2.useCallback)((msg) => {
|
|
416
421
|
setMessages((prev) => {
|
|
417
|
-
const updated = [...prev,
|
|
422
|
+
const updated = [...prev, msg];
|
|
418
423
|
if (updated.length > MAX_RENDERED_MESSAGES) {
|
|
419
424
|
return updated.slice(-MAX_RENDERED_MESSAGES);
|
|
420
425
|
}
|
|
@@ -426,6 +431,7 @@ function useMessages() {
|
|
|
426
431
|
|
|
427
432
|
// src/ui/hooks/useSlashCommands.ts
|
|
428
433
|
var import_react3 = require("react");
|
|
434
|
+
var import_agent_core = require("@robota-sdk/agent-core");
|
|
429
435
|
|
|
430
436
|
// src/commands/slash-executor.ts
|
|
431
437
|
var VALID_MODES2 = ["plan", "default", "acceptEdits", "bypassPermissions"];
|
|
@@ -536,18 +542,9 @@ async function handlePluginCommand(args, addMessage, callbacks) {
|
|
|
536
542
|
try {
|
|
537
543
|
switch (subcommand) {
|
|
538
544
|
case "":
|
|
539
|
-
case void 0:
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
addMessage({ role: "system", content: "No plugins installed." });
|
|
543
|
-
} else {
|
|
544
|
-
const lines = plugins.map(
|
|
545
|
-
(p) => ` ${p.name} \u2014 ${p.description} [${p.enabled ? "enabled" : "disabled"}]`
|
|
546
|
-
);
|
|
547
|
-
addMessage({ role: "system", content: `Installed plugins:
|
|
548
|
-
${lines.join("\n")}` });
|
|
549
|
-
}
|
|
550
|
-
return { handled: true };
|
|
545
|
+
case void 0:
|
|
546
|
+
case "manage": {
|
|
547
|
+
return { handled: true, triggerPluginTUI: true };
|
|
551
548
|
}
|
|
552
549
|
case "install": {
|
|
553
550
|
if (!subArgs) {
|
|
@@ -694,18 +691,21 @@ async function executeSlashCommand(cmd, args, session, addMessage, clearMessages
|
|
|
694
691
|
|
|
695
692
|
// src/ui/hooks/useSlashCommands.ts
|
|
696
693
|
var EXIT_DELAY_MS = 500;
|
|
697
|
-
function useSlashCommands(session, addMessage, setMessages, exit, registry, pendingModelChangeRef, setPendingModelId, pluginCallbacks) {
|
|
694
|
+
function useSlashCommands(session, addMessage, setMessages, exit, registry, pendingModelChangeRef, setPendingModelId, pluginCallbacks, setShowPluginTUI) {
|
|
698
695
|
return (0, import_react3.useCallback)(
|
|
699
696
|
async (input) => {
|
|
700
697
|
const parts = input.slice(1).split(/\s+/);
|
|
701
698
|
const cmd = parts[0]?.toLowerCase() ?? "";
|
|
702
699
|
const args = parts.slice(1).join(" ");
|
|
703
700
|
const clearMessages = () => setMessages([]);
|
|
701
|
+
const slashAddMessage = (msg) => {
|
|
702
|
+
addMessage((0, import_agent_core.createSystemMessage)(msg.content));
|
|
703
|
+
};
|
|
704
704
|
const result = await executeSlashCommand(
|
|
705
705
|
cmd,
|
|
706
706
|
args,
|
|
707
707
|
session,
|
|
708
|
-
|
|
708
|
+
slashAddMessage,
|
|
709
709
|
clearMessages,
|
|
710
710
|
registry,
|
|
711
711
|
pluginCallbacks
|
|
@@ -714,6 +714,9 @@ function useSlashCommands(session, addMessage, setMessages, exit, registry, pend
|
|
|
714
714
|
pendingModelChangeRef.current = result.pendingModelId;
|
|
715
715
|
setPendingModelId(result.pendingModelId);
|
|
716
716
|
}
|
|
717
|
+
if (result.triggerPluginTUI) {
|
|
718
|
+
setShowPluginTUI?.(true);
|
|
719
|
+
}
|
|
717
720
|
if (result.exitRequested) {
|
|
718
721
|
setTimeout(() => exit(), EXIT_DELAY_MS);
|
|
719
722
|
}
|
|
@@ -727,14 +730,17 @@ function useSlashCommands(session, addMessage, setMessages, exit, registry, pend
|
|
|
727
730
|
registry,
|
|
728
731
|
pendingModelChangeRef,
|
|
729
732
|
setPendingModelId,
|
|
730
|
-
pluginCallbacks
|
|
733
|
+
pluginCallbacks,
|
|
734
|
+
setShowPluginTUI
|
|
731
735
|
]
|
|
732
736
|
);
|
|
733
737
|
}
|
|
734
738
|
|
|
735
739
|
// src/ui/hooks/useSubmitHandler.ts
|
|
736
740
|
var import_react4 = require("react");
|
|
741
|
+
var import_node_crypto = require("crypto");
|
|
737
742
|
var import_agent_sdk2 = require("@robota-sdk/agent-sdk");
|
|
743
|
+
var import_agent_core2 = require("@robota-sdk/agent-core");
|
|
738
744
|
|
|
739
745
|
// src/utils/tool-call-extractor.ts
|
|
740
746
|
var TOOL_ARG_MAX_LENGTH = 80;
|
|
@@ -891,21 +897,50 @@ async function runSessionPrompt(prompt, session, addMessage, clearStreamingText,
|
|
|
891
897
|
historyBefore
|
|
892
898
|
);
|
|
893
899
|
if (toolSummaries.length > 0) {
|
|
894
|
-
addMessage(
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
900
|
+
addMessage(
|
|
901
|
+
(0, import_agent_core2.createToolMessage)(JSON.stringify(toolSummaries), {
|
|
902
|
+
toolCallId: (0, import_node_crypto.randomUUID)(),
|
|
903
|
+
name: `${toolSummaries.length} tools`
|
|
904
|
+
})
|
|
905
|
+
);
|
|
899
906
|
}
|
|
900
|
-
addMessage(
|
|
907
|
+
addMessage((0, import_agent_core2.createAssistantMessage)(response || "(empty response)"));
|
|
901
908
|
syncContextState(session, setContextState);
|
|
902
909
|
} catch (err) {
|
|
903
910
|
clearStreamingText();
|
|
904
|
-
|
|
905
|
-
|
|
911
|
+
const isAbortError = err instanceof DOMException && err.name === "AbortError" || err instanceof Error && (err.message.includes("aborted") || err.message.includes("abort"));
|
|
912
|
+
if (isAbortError) {
|
|
913
|
+
const history = session.getHistory();
|
|
914
|
+
const toolSummaries = extractToolCallsWithDiff(
|
|
915
|
+
history,
|
|
916
|
+
historyBefore
|
|
917
|
+
);
|
|
918
|
+
if (toolSummaries.length > 0) {
|
|
919
|
+
addMessage(
|
|
920
|
+
(0, import_agent_core2.createToolMessage)(JSON.stringify(toolSummaries), {
|
|
921
|
+
toolCallId: (0, import_node_crypto.randomUUID)(),
|
|
922
|
+
name: `${toolSummaries.length} tools`
|
|
923
|
+
})
|
|
924
|
+
);
|
|
925
|
+
}
|
|
926
|
+
const assistantParts = [];
|
|
927
|
+
let lastAssistantState = "complete";
|
|
928
|
+
for (let i = historyBefore; i < history.length; i++) {
|
|
929
|
+
const msg = history[i];
|
|
930
|
+
if (msg && msg.role === "assistant" && msg.content) {
|
|
931
|
+
assistantParts.push(msg.content);
|
|
932
|
+
if (msg.state === "interrupted") lastAssistantState = "interrupted";
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
if (assistantParts.length > 0) {
|
|
936
|
+
addMessage(
|
|
937
|
+
(0, import_agent_core2.createAssistantMessage)(assistantParts.join("\n\n"), { state: lastAssistantState })
|
|
938
|
+
);
|
|
939
|
+
}
|
|
940
|
+
addMessage((0, import_agent_core2.createSystemMessage)("Interrupted by user."));
|
|
906
941
|
} else {
|
|
907
942
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
908
|
-
addMessage(
|
|
943
|
+
addMessage((0, import_agent_core2.createSystemMessage)(`Error: ${errMsg}`));
|
|
909
944
|
}
|
|
910
945
|
} finally {
|
|
911
946
|
setIsThinking(false);
|
|
@@ -958,7 +993,7 @@ function useSubmitHandler(session, addMessage, handleSlashCommand, clearStreamin
|
|
|
958
993
|
const runInFork = createForkRunner(session);
|
|
959
994
|
const result = await executeSkill(skill, args, { runInFork });
|
|
960
995
|
if (result.mode === "fork") {
|
|
961
|
-
addMessage(
|
|
996
|
+
addMessage((0, import_agent_core2.createAssistantMessage)(result.result ?? "(empty response)"));
|
|
962
997
|
syncContextState(session, setContextState);
|
|
963
998
|
return;
|
|
964
999
|
}
|
|
@@ -993,7 +1028,7 @@ function useSubmitHandler(session, addMessage, handleSlashCommand, clearStreamin
|
|
|
993
1028
|
hookInput
|
|
994
1029
|
);
|
|
995
1030
|
}
|
|
996
|
-
addMessage(
|
|
1031
|
+
addMessage((0, import_agent_core2.createUserMessage)(input));
|
|
997
1032
|
return runSessionPrompt(
|
|
998
1033
|
input,
|
|
999
1034
|
session,
|
|
@@ -1060,16 +1095,16 @@ var CommandRegistry = class {
|
|
|
1060
1095
|
};
|
|
1061
1096
|
|
|
1062
1097
|
// src/commands/builtin-source.ts
|
|
1063
|
-
var
|
|
1098
|
+
var import_agent_core3 = require("@robota-sdk/agent-core");
|
|
1064
1099
|
function buildModelSubcommands() {
|
|
1065
1100
|
const seen = /* @__PURE__ */ new Set();
|
|
1066
1101
|
const commands = [];
|
|
1067
|
-
for (const model of Object.values(
|
|
1102
|
+
for (const model of Object.values(import_agent_core3.CLAUDE_MODELS)) {
|
|
1068
1103
|
if (seen.has(model.name)) continue;
|
|
1069
1104
|
seen.add(model.name);
|
|
1070
1105
|
commands.push({
|
|
1071
1106
|
name: model.id,
|
|
1072
|
-
description: `${model.name} (${(0,
|
|
1107
|
+
description: `${model.name} (${(0, import_agent_core3.formatTokenCount)(model.contextWindow).toUpperCase()})`,
|
|
1073
1108
|
source: "builtin"
|
|
1074
1109
|
});
|
|
1075
1110
|
}
|
|
@@ -1111,22 +1146,7 @@ function createBuiltinCommands() {
|
|
|
1111
1146
|
{ name: "cost", description: "Show session info", source: "builtin" },
|
|
1112
1147
|
{ name: "context", description: "Context window info", source: "builtin" },
|
|
1113
1148
|
{ name: "permissions", description: "Permission rules", source: "builtin" },
|
|
1114
|
-
{
|
|
1115
|
-
name: "plugin",
|
|
1116
|
-
description: "Manage plugins",
|
|
1117
|
-
source: "builtin",
|
|
1118
|
-
subcommands: [
|
|
1119
|
-
{ name: "install", description: "Install a plugin (name@marketplace)", source: "builtin" },
|
|
1120
|
-
{
|
|
1121
|
-
name: "uninstall",
|
|
1122
|
-
description: "Uninstall a plugin (name@marketplace)",
|
|
1123
|
-
source: "builtin"
|
|
1124
|
-
},
|
|
1125
|
-
{ name: "enable", description: "Enable a plugin (name@marketplace)", source: "builtin" },
|
|
1126
|
-
{ name: "disable", description: "Disable a plugin (name@marketplace)", source: "builtin" },
|
|
1127
|
-
{ name: "marketplace", description: "Manage marketplace sources", source: "builtin" }
|
|
1128
|
-
]
|
|
1129
|
-
},
|
|
1149
|
+
{ name: "plugin", description: "Manage plugins", source: "builtin" },
|
|
1130
1150
|
{ name: "reload-plugins", description: "Reload all plugin resources", source: "builtin" },
|
|
1131
1151
|
{ name: "reset", description: "Delete settings and exit", source: "builtin" },
|
|
1132
1152
|
{ name: "exit", description: "Exit CLI", source: "builtin" }
|
|
@@ -1393,18 +1413,50 @@ function usePluginCallbacks(cwd) {
|
|
|
1393
1413
|
return {
|
|
1394
1414
|
listInstalled: async () => {
|
|
1395
1415
|
const plugins = await loader.loadAll();
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1416
|
+
const enabledMap = settingsStore.getEnabledPlugins();
|
|
1417
|
+
return plugins.map((p) => {
|
|
1418
|
+
const parts = p.pluginDir.split("/");
|
|
1419
|
+
const cacheIdx = parts.indexOf("cache");
|
|
1420
|
+
const marketplaceName = cacheIdx >= 0 ? parts[cacheIdx + 1] : "";
|
|
1421
|
+
const fullId = marketplaceName ? `${p.manifest.name}@${marketplaceName}` : p.manifest.name;
|
|
1422
|
+
return {
|
|
1423
|
+
name: fullId,
|
|
1424
|
+
description: p.manifest.description,
|
|
1425
|
+
enabled: enabledMap[fullId] !== false && enabledMap[p.manifest.name] !== false
|
|
1426
|
+
};
|
|
1427
|
+
});
|
|
1428
|
+
},
|
|
1429
|
+
listAvailablePlugins: async (marketplaceName) => {
|
|
1430
|
+
let manifest;
|
|
1431
|
+
try {
|
|
1432
|
+
manifest = marketplace.fetchManifest(marketplaceName);
|
|
1433
|
+
} catch {
|
|
1434
|
+
return [];
|
|
1435
|
+
}
|
|
1436
|
+
const installed = installer.getInstalledPlugins();
|
|
1437
|
+
const installedNames = new Set(Object.values(installed).map((r) => r.pluginName));
|
|
1438
|
+
return manifest.plugins.map((p) => ({
|
|
1439
|
+
name: p.name,
|
|
1440
|
+
description: p.description,
|
|
1441
|
+
installed: installedNames.has(p.name)
|
|
1400
1442
|
}));
|
|
1401
1443
|
},
|
|
1402
|
-
install: async (pluginId) => {
|
|
1444
|
+
install: async (pluginId, scope) => {
|
|
1403
1445
|
const [name, marketplaceName] = pluginId.split("@");
|
|
1404
1446
|
if (!name || !marketplaceName) {
|
|
1405
1447
|
throw new Error("Plugin ID must be in format: name@marketplace");
|
|
1406
1448
|
}
|
|
1407
|
-
|
|
1449
|
+
if (scope === "project") {
|
|
1450
|
+
const projectPluginsDir = (0, import_node_path4.join)(cwd, ".robota", "plugins");
|
|
1451
|
+
const projectInstaller = new import_agent_sdk4.BundlePluginInstaller({
|
|
1452
|
+
pluginsDir: projectPluginsDir,
|
|
1453
|
+
settingsStore,
|
|
1454
|
+
marketplaceClient: marketplace
|
|
1455
|
+
});
|
|
1456
|
+
await projectInstaller.install(name, marketplaceName);
|
|
1457
|
+
} else {
|
|
1458
|
+
await installer.install(name, marketplaceName);
|
|
1459
|
+
}
|
|
1408
1460
|
},
|
|
1409
1461
|
uninstall: async (pluginId) => {
|
|
1410
1462
|
await installer.uninstall(pluginId);
|
|
@@ -1447,6 +1499,7 @@ function usePluginCallbacks(cwd) {
|
|
|
1447
1499
|
// src/ui/MessageList.tsx
|
|
1448
1500
|
var import_react7 = __toESM(require("react"), 1);
|
|
1449
1501
|
var import_ink2 = require("ink");
|
|
1502
|
+
var import_agent_core4 = require("@robota-sdk/agent-core");
|
|
1450
1503
|
|
|
1451
1504
|
// src/ui/render-markdown.ts
|
|
1452
1505
|
var import_marked = require("marked");
|
|
@@ -1532,9 +1585,14 @@ function RoleLabel({ role }) {
|
|
|
1532
1585
|
}
|
|
1533
1586
|
}
|
|
1534
1587
|
function ToolMessage({ message }) {
|
|
1588
|
+
if (!(0, import_agent_core4.isToolMessage)(message)) {
|
|
1589
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, {});
|
|
1590
|
+
}
|
|
1591
|
+
const toolName = message.name;
|
|
1592
|
+
const content = message.content;
|
|
1535
1593
|
let summaries = null;
|
|
1536
1594
|
try {
|
|
1537
|
-
const parsed = JSON.parse(
|
|
1595
|
+
const parsed = JSON.parse(content);
|
|
1538
1596
|
if (Array.isArray(parsed) && parsed.length > 0 && typeof parsed[0].line === "string") {
|
|
1539
1597
|
summaries = parsed;
|
|
1540
1598
|
}
|
|
@@ -1547,9 +1605,9 @@ function ToolMessage({ message }) {
|
|
|
1547
1605
|
"Tool:",
|
|
1548
1606
|
" "
|
|
1549
1607
|
] }),
|
|
1550
|
-
|
|
1608
|
+
toolName && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ink2.Text, { color: "white", dimColor: true, children: [
|
|
1551
1609
|
"[",
|
|
1552
|
-
|
|
1610
|
+
toolName,
|
|
1553
1611
|
"]"
|
|
1554
1612
|
] })
|
|
1555
1613
|
] }),
|
|
@@ -1565,16 +1623,16 @@ function ToolMessage({ message }) {
|
|
|
1565
1623
|
] }, i))
|
|
1566
1624
|
] });
|
|
1567
1625
|
}
|
|
1568
|
-
const lines =
|
|
1626
|
+
const lines = content.split("\n").filter((l) => l.trim());
|
|
1569
1627
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ink2.Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
1570
1628
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ink2.Box, { children: [
|
|
1571
1629
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ink2.Text, { color: "white", bold: true, children: [
|
|
1572
1630
|
"Tool:",
|
|
1573
1631
|
" "
|
|
1574
1632
|
] }),
|
|
1575
|
-
|
|
1633
|
+
toolName && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ink2.Text, { color: "white", dimColor: true, children: [
|
|
1576
1634
|
"[",
|
|
1577
|
-
|
|
1635
|
+
toolName,
|
|
1578
1636
|
"]"
|
|
1579
1637
|
] })
|
|
1580
1638
|
] }),
|
|
@@ -1590,21 +1648,15 @@ function ToolMessage({ message }) {
|
|
|
1590
1648
|
var MessageItem = import_react7.default.memo(function MessageItem2({
|
|
1591
1649
|
message
|
|
1592
1650
|
}) {
|
|
1593
|
-
if (
|
|
1651
|
+
if ((0, import_agent_core4.isToolMessage)(message)) {
|
|
1594
1652
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ToolMessage, { message });
|
|
1595
1653
|
}
|
|
1654
|
+
const content = message.content ?? "";
|
|
1655
|
+
const isInterrupted = message.state === "interrupted";
|
|
1596
1656
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ink2.Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
1597
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.
|
|
1598
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(RoleLabel, { role: message.role }),
|
|
1599
|
-
message.toolName && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ink2.Text, { color: "magenta", dimColor: true, children: [
|
|
1600
|
-
"[",
|
|
1601
|
-
message.toolName,
|
|
1602
|
-
"]",
|
|
1603
|
-
" "
|
|
1604
|
-
] })
|
|
1605
|
-
] }),
|
|
1657
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ink2.Box, { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(RoleLabel, { role: message.role }) }),
|
|
1606
1658
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ink2.Text, { children: " " }),
|
|
1607
|
-
/* @__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
|
|
1659
|
+
/* @__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 }) })
|
|
1608
1660
|
] });
|
|
1609
1661
|
});
|
|
1610
1662
|
function MessageList({ messages }) {
|
|
@@ -1613,7 +1665,7 @@ function MessageList({ messages }) {
|
|
|
1613
1665
|
|
|
1614
1666
|
// src/ui/StatusBar.tsx
|
|
1615
1667
|
var import_ink3 = require("ink");
|
|
1616
|
-
var
|
|
1668
|
+
var import_agent_core5 = require("@robota-sdk/agent-core");
|
|
1617
1669
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
1618
1670
|
var CONTEXT_YELLOW_THRESHOLD = 70;
|
|
1619
1671
|
var CONTEXT_RED_THRESHOLD = 90;
|
|
@@ -1653,9 +1705,9 @@ function StatusBar({
|
|
|
1653
1705
|
"Context: ",
|
|
1654
1706
|
Math.round(contextPercentage),
|
|
1655
1707
|
"% (",
|
|
1656
|
-
(0,
|
|
1708
|
+
(0, import_agent_core5.formatTokenCount)(contextUsedTokens),
|
|
1657
1709
|
"/",
|
|
1658
|
-
(0,
|
|
1710
|
+
(0, import_agent_core5.formatTokenCount)(contextMaxTokens),
|
|
1659
1711
|
")"
|
|
1660
1712
|
] })
|
|
1661
1713
|
] }),
|
|
@@ -1983,7 +2035,7 @@ function InputArea({ onSubmit, isDisabled, registry }) {
|
|
|
1983
2035
|
isSubcommandMode
|
|
1984
2036
|
}
|
|
1985
2037
|
),
|
|
1986
|
-
/* @__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: [
|
|
2038
|
+
/* @__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: [
|
|
1987
2039
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_ink7.Text, { color: "green", bold: true, children: "> " }),
|
|
1988
2040
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1989
2041
|
CjkTextInput,
|
|
@@ -2119,7 +2171,7 @@ function StreamingIndicator({ text, activeTools }) {
|
|
|
2119
2171
|
const hasTools = activeTools.length > 0;
|
|
2120
2172
|
const hasText = text.length > 0;
|
|
2121
2173
|
if (!hasTools && !hasText) {
|
|
2122
|
-
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2174
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_jsx_runtime10.Fragment, {});
|
|
2123
2175
|
}
|
|
2124
2176
|
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_ink10.Box, { flexDirection: "column", children: [
|
|
2125
2177
|
hasTools && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_ink10.Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
@@ -2149,8 +2201,459 @@ function StreamingIndicator({ text, activeTools }) {
|
|
|
2149
2201
|
] });
|
|
2150
2202
|
}
|
|
2151
2203
|
|
|
2152
|
-
// src/ui/
|
|
2204
|
+
// src/ui/PluginTUI.tsx
|
|
2205
|
+
var import_react15 = require("react");
|
|
2206
|
+
|
|
2207
|
+
// src/ui/MenuSelect.tsx
|
|
2208
|
+
var import_react13 = require("react");
|
|
2209
|
+
var import_ink11 = require("ink");
|
|
2153
2210
|
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
2211
|
+
function MenuSelect({
|
|
2212
|
+
title,
|
|
2213
|
+
items,
|
|
2214
|
+
onSelect,
|
|
2215
|
+
onBack,
|
|
2216
|
+
loading,
|
|
2217
|
+
error
|
|
2218
|
+
}) {
|
|
2219
|
+
const [selected, setSelected] = (0, import_react13.useState)(0);
|
|
2220
|
+
const selectedRef = (0, import_react13.useRef)(0);
|
|
2221
|
+
const resolvedRef = (0, import_react13.useRef)(false);
|
|
2222
|
+
const doSelect = (0, import_react13.useCallback)(
|
|
2223
|
+
(index) => {
|
|
2224
|
+
if (resolvedRef.current || items.length === 0) return;
|
|
2225
|
+
resolvedRef.current = true;
|
|
2226
|
+
onSelect(items[index].value);
|
|
2227
|
+
},
|
|
2228
|
+
[items, onSelect]
|
|
2229
|
+
);
|
|
2230
|
+
(0, import_ink11.useInput)((input, key) => {
|
|
2231
|
+
if (resolvedRef.current) return;
|
|
2232
|
+
if (key.escape) {
|
|
2233
|
+
resolvedRef.current = true;
|
|
2234
|
+
onBack();
|
|
2235
|
+
return;
|
|
2236
|
+
}
|
|
2237
|
+
if (loading || error || items.length === 0) return;
|
|
2238
|
+
if (key.upArrow) {
|
|
2239
|
+
const next = selectedRef.current > 0 ? selectedRef.current - 1 : selectedRef.current;
|
|
2240
|
+
selectedRef.current = next;
|
|
2241
|
+
setSelected(next);
|
|
2242
|
+
} else if (key.downArrow) {
|
|
2243
|
+
const next = selectedRef.current < items.length - 1 ? selectedRef.current + 1 : selectedRef.current;
|
|
2244
|
+
selectedRef.current = next;
|
|
2245
|
+
setSelected(next);
|
|
2246
|
+
} else if (key.return) {
|
|
2247
|
+
doSelect(selectedRef.current);
|
|
2248
|
+
}
|
|
2249
|
+
});
|
|
2250
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_ink11.Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
|
|
2251
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_ink11.Text, { color: "yellow", bold: true, children: title }),
|
|
2252
|
+
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..." }) }),
|
|
2253
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_ink11.Box, { marginTop: 1, flexDirection: "column", children: [
|
|
2254
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_ink11.Text, { color: "red", children: error }),
|
|
2255
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_ink11.Text, { dimColor: true, children: "Press Esc to go back" })
|
|
2256
|
+
] }),
|
|
2257
|
+
!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: [
|
|
2258
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_ink11.Text, { color: i === selected ? "cyan" : void 0, bold: i === selected, children: [
|
|
2259
|
+
i === selected ? "> " : " ",
|
|
2260
|
+
item.label
|
|
2261
|
+
] }),
|
|
2262
|
+
item.hint && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_ink11.Text, { dimColor: true, children: [
|
|
2263
|
+
" ",
|
|
2264
|
+
item.hint
|
|
2265
|
+
] })
|
|
2266
|
+
] }, item.value)) }),
|
|
2267
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_ink11.Text, { dimColor: true, children: loading || error ? "" : " \u2191\u2193 Navigate Enter Select Esc Back" })
|
|
2268
|
+
] });
|
|
2269
|
+
}
|
|
2270
|
+
|
|
2271
|
+
// src/ui/TextPrompt.tsx
|
|
2272
|
+
var import_react14 = require("react");
|
|
2273
|
+
var import_ink12 = require("ink");
|
|
2274
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
2275
|
+
function TextPrompt({
|
|
2276
|
+
title,
|
|
2277
|
+
placeholder,
|
|
2278
|
+
onSubmit,
|
|
2279
|
+
onCancel,
|
|
2280
|
+
validate
|
|
2281
|
+
}) {
|
|
2282
|
+
const [value, setValue] = (0, import_react14.useState)("");
|
|
2283
|
+
const [error, setError] = (0, import_react14.useState)();
|
|
2284
|
+
const resolvedRef = (0, import_react14.useRef)(false);
|
|
2285
|
+
const valueRef = (0, import_react14.useRef)("");
|
|
2286
|
+
const handleSubmit = (0, import_react14.useCallback)(() => {
|
|
2287
|
+
if (resolvedRef.current) return;
|
|
2288
|
+
const trimmed = valueRef.current.trim();
|
|
2289
|
+
if (!trimmed) return;
|
|
2290
|
+
if (validate) {
|
|
2291
|
+
const err = validate(trimmed);
|
|
2292
|
+
if (err) {
|
|
2293
|
+
setError(err);
|
|
2294
|
+
return;
|
|
2295
|
+
}
|
|
2296
|
+
}
|
|
2297
|
+
resolvedRef.current = true;
|
|
2298
|
+
onSubmit(trimmed);
|
|
2299
|
+
}, [validate, onSubmit]);
|
|
2300
|
+
(0, import_ink12.useInput)((input, key) => {
|
|
2301
|
+
if (resolvedRef.current) return;
|
|
2302
|
+
if (key.escape) {
|
|
2303
|
+
resolvedRef.current = true;
|
|
2304
|
+
onCancel();
|
|
2305
|
+
return;
|
|
2306
|
+
}
|
|
2307
|
+
if (key.return) {
|
|
2308
|
+
handleSubmit();
|
|
2309
|
+
return;
|
|
2310
|
+
}
|
|
2311
|
+
if (key.backspace || key.delete) {
|
|
2312
|
+
valueRef.current = valueRef.current.slice(0, -1);
|
|
2313
|
+
setValue(valueRef.current);
|
|
2314
|
+
setError(void 0);
|
|
2315
|
+
return;
|
|
2316
|
+
}
|
|
2317
|
+
if (input && !key.ctrl && !key.meta) {
|
|
2318
|
+
valueRef.current = valueRef.current + input;
|
|
2319
|
+
setValue(valueRef.current);
|
|
2320
|
+
setError(void 0);
|
|
2321
|
+
}
|
|
2322
|
+
});
|
|
2323
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_ink12.Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
|
|
2324
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_ink12.Text, { color: "yellow", bold: true, children: title }),
|
|
2325
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_ink12.Box, { marginTop: 1, children: [
|
|
2326
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_ink12.Text, { color: "cyan", children: "> " }),
|
|
2327
|
+
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,
|
|
2328
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_ink12.Text, { color: "cyan", children: "\u2588" })
|
|
2329
|
+
] }),
|
|
2330
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_ink12.Text, { color: "red", children: error }),
|
|
2331
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_ink12.Text, { dimColor: true, children: " Enter Submit Esc Cancel" })
|
|
2332
|
+
] });
|
|
2333
|
+
}
|
|
2334
|
+
|
|
2335
|
+
// src/ui/plugin-tui-handlers.ts
|
|
2336
|
+
function handleMainSelect(value, nav) {
|
|
2337
|
+
if (value === "marketplace") {
|
|
2338
|
+
nav.push({ screen: "marketplace-list" });
|
|
2339
|
+
} else if (value === "installed") {
|
|
2340
|
+
nav.push({ screen: "installed-list" });
|
|
2341
|
+
}
|
|
2342
|
+
}
|
|
2343
|
+
function handleMarketplaceListSelect(value, nav) {
|
|
2344
|
+
if (value === "__add__") {
|
|
2345
|
+
nav.push({ screen: "marketplace-add" });
|
|
2346
|
+
} else {
|
|
2347
|
+
nav.push({ screen: "marketplace-action", context: { marketplace: value } });
|
|
2348
|
+
}
|
|
2349
|
+
}
|
|
2350
|
+
function handleMarketplaceActionSelect(value, marketplace, callbacks, nav) {
|
|
2351
|
+
if (value === "browse") {
|
|
2352
|
+
nav.push({ screen: "marketplace-browse", context: { marketplace } });
|
|
2353
|
+
} else if (value === "update") {
|
|
2354
|
+
callbacks.marketplaceUpdate(marketplace).then(() => {
|
|
2355
|
+
nav.notify(`Updated marketplace "${marketplace}".`);
|
|
2356
|
+
nav.pop();
|
|
2357
|
+
}).catch((err) => {
|
|
2358
|
+
nav.notify(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
2359
|
+
});
|
|
2360
|
+
} else if (value === "remove") {
|
|
2361
|
+
nav.setConfirm({
|
|
2362
|
+
message: `Remove marketplace "${marketplace}" and all its plugins?`,
|
|
2363
|
+
onConfirm: () => {
|
|
2364
|
+
nav.setConfirm(void 0);
|
|
2365
|
+
callbacks.marketplaceRemove(marketplace).then(() => {
|
|
2366
|
+
nav.notify(`Removed marketplace "${marketplace}".`);
|
|
2367
|
+
nav.popN(2);
|
|
2368
|
+
}).catch((err) => {
|
|
2369
|
+
nav.notify(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
2370
|
+
});
|
|
2371
|
+
},
|
|
2372
|
+
onCancel: () => nav.setConfirm(void 0)
|
|
2373
|
+
});
|
|
2374
|
+
}
|
|
2375
|
+
}
|
|
2376
|
+
function handleMarketplaceBrowseSelect(value, marketplace, items, nav) {
|
|
2377
|
+
const fullId = `${value}@${marketplace}`;
|
|
2378
|
+
const item = items.find((i) => i.value === value);
|
|
2379
|
+
if (item?.hint === "installed") {
|
|
2380
|
+
nav.push({ screen: "installed-action", context: { pluginId: fullId } });
|
|
2381
|
+
} else {
|
|
2382
|
+
nav.push({ screen: "marketplace-install-scope", context: { marketplace, pluginId: fullId } });
|
|
2383
|
+
}
|
|
2384
|
+
}
|
|
2385
|
+
function handleInstallScopeSelect(value, pluginId, callbacks, nav) {
|
|
2386
|
+
const scope = value;
|
|
2387
|
+
callbacks.install(pluginId, scope).then(() => {
|
|
2388
|
+
nav.notify(`Installed plugin "${pluginId}" (${scope} scope).`);
|
|
2389
|
+
nav.popN(2);
|
|
2390
|
+
}).catch((err) => {
|
|
2391
|
+
nav.notify(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
2392
|
+
});
|
|
2393
|
+
}
|
|
2394
|
+
function handleInstalledListSelect(value, callbacks, nav) {
|
|
2395
|
+
nav.setConfirm({
|
|
2396
|
+
message: `Uninstall plugin "${value}"?`,
|
|
2397
|
+
onConfirm: () => {
|
|
2398
|
+
nav.setConfirm(void 0);
|
|
2399
|
+
callbacks.uninstall(value).then(() => {
|
|
2400
|
+
nav.notify(`Uninstalled plugin "${value}".`);
|
|
2401
|
+
nav.refresh();
|
|
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
|
+
function handleInstalledActionSelect(value, pluginId, callbacks, nav) {
|
|
2410
|
+
if (value === "uninstall") {
|
|
2411
|
+
nav.setConfirm({
|
|
2412
|
+
message: `Uninstall plugin "${pluginId}"?`,
|
|
2413
|
+
onConfirm: () => {
|
|
2414
|
+
nav.setConfirm(void 0);
|
|
2415
|
+
callbacks.uninstall(pluginId).then(() => {
|
|
2416
|
+
nav.notify(`Uninstalled plugin "${pluginId}".`);
|
|
2417
|
+
nav.popN(2);
|
|
2418
|
+
}).catch((err) => {
|
|
2419
|
+
nav.notify(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
2420
|
+
});
|
|
2421
|
+
},
|
|
2422
|
+
onCancel: () => nav.setConfirm(void 0)
|
|
2423
|
+
});
|
|
2424
|
+
}
|
|
2425
|
+
}
|
|
2426
|
+
|
|
2427
|
+
// src/ui/PluginTUI.tsx
|
|
2428
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
2429
|
+
function PluginTUI({ callbacks, onClose, addMessage }) {
|
|
2430
|
+
const [stack, setStack] = (0, import_react15.useState)([{ screen: "main" }]);
|
|
2431
|
+
const [items, setItems] = (0, import_react15.useState)([]);
|
|
2432
|
+
const [loading, setLoading] = (0, import_react15.useState)(false);
|
|
2433
|
+
const [error, setError] = (0, import_react15.useState)();
|
|
2434
|
+
const [confirm, setConfirm] = (0, import_react15.useState)();
|
|
2435
|
+
const [refreshCounter, setRefreshCounter] = (0, import_react15.useState)(0);
|
|
2436
|
+
const current = stack[stack.length - 1] ?? { screen: "main" };
|
|
2437
|
+
const push = (0, import_react15.useCallback)((state) => {
|
|
2438
|
+
setStack((prev) => [...prev, state]);
|
|
2439
|
+
setItems([]);
|
|
2440
|
+
setError(void 0);
|
|
2441
|
+
}, []);
|
|
2442
|
+
const pop = (0, import_react15.useCallback)(() => {
|
|
2443
|
+
setStack((prev) => {
|
|
2444
|
+
if (prev.length <= 1) {
|
|
2445
|
+
onClose();
|
|
2446
|
+
return prev;
|
|
2447
|
+
}
|
|
2448
|
+
return prev.slice(0, -1);
|
|
2449
|
+
});
|
|
2450
|
+
setItems([]);
|
|
2451
|
+
setError(void 0);
|
|
2452
|
+
}, [onClose]);
|
|
2453
|
+
const popN = (0, import_react15.useCallback)(
|
|
2454
|
+
(n) => {
|
|
2455
|
+
setStack((prev) => {
|
|
2456
|
+
const next = prev.slice(0, Math.max(1, prev.length - n));
|
|
2457
|
+
if (next.length === 0) {
|
|
2458
|
+
onClose();
|
|
2459
|
+
return prev;
|
|
2460
|
+
}
|
|
2461
|
+
return next;
|
|
2462
|
+
});
|
|
2463
|
+
setItems([]);
|
|
2464
|
+
setError(void 0);
|
|
2465
|
+
},
|
|
2466
|
+
[onClose]
|
|
2467
|
+
);
|
|
2468
|
+
const notify = (0, import_react15.useCallback)(
|
|
2469
|
+
(content) => {
|
|
2470
|
+
addMessage?.({ role: "system", content });
|
|
2471
|
+
},
|
|
2472
|
+
[addMessage]
|
|
2473
|
+
);
|
|
2474
|
+
const refresh = (0, import_react15.useCallback)(() => {
|
|
2475
|
+
setItems([]);
|
|
2476
|
+
setRefreshCounter((c) => c + 1);
|
|
2477
|
+
}, []);
|
|
2478
|
+
const nav = { push, pop, popN, notify, setConfirm, refresh };
|
|
2479
|
+
(0, import_react15.useEffect)(() => {
|
|
2480
|
+
const screen2 = current.screen;
|
|
2481
|
+
if (screen2 === "marketplace-list") {
|
|
2482
|
+
setLoading(true);
|
|
2483
|
+
callbacks.marketplaceList().then((sources) => {
|
|
2484
|
+
const baseItems = [{ label: "Add Marketplace", value: "__add__" }];
|
|
2485
|
+
const sourceItems = sources.map((s) => ({
|
|
2486
|
+
label: s.name,
|
|
2487
|
+
value: s.name,
|
|
2488
|
+
hint: s.type
|
|
2489
|
+
}));
|
|
2490
|
+
setItems([...baseItems, ...sourceItems]);
|
|
2491
|
+
setLoading(false);
|
|
2492
|
+
}).catch((err) => {
|
|
2493
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
2494
|
+
setLoading(false);
|
|
2495
|
+
});
|
|
2496
|
+
} else if (screen2 === "marketplace-browse") {
|
|
2497
|
+
const marketplace = current.context?.marketplace ?? "";
|
|
2498
|
+
setLoading(true);
|
|
2499
|
+
callbacks.listAvailablePlugins(marketplace).then((plugins) => {
|
|
2500
|
+
setItems(
|
|
2501
|
+
plugins.map((p) => ({
|
|
2502
|
+
label: p.name,
|
|
2503
|
+
value: p.name,
|
|
2504
|
+
hint: p.installed ? "installed" : p.description
|
|
2505
|
+
}))
|
|
2506
|
+
);
|
|
2507
|
+
setLoading(false);
|
|
2508
|
+
}).catch((err) => {
|
|
2509
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
2510
|
+
setLoading(false);
|
|
2511
|
+
});
|
|
2512
|
+
} else if (screen2 === "installed-list") {
|
|
2513
|
+
setLoading(true);
|
|
2514
|
+
callbacks.listInstalled().then((plugins) => {
|
|
2515
|
+
setItems(
|
|
2516
|
+
plugins.map((p) => ({
|
|
2517
|
+
label: p.name,
|
|
2518
|
+
value: p.name,
|
|
2519
|
+
hint: p.description
|
|
2520
|
+
}))
|
|
2521
|
+
);
|
|
2522
|
+
setLoading(false);
|
|
2523
|
+
}).catch((err) => {
|
|
2524
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
2525
|
+
setLoading(false);
|
|
2526
|
+
});
|
|
2527
|
+
}
|
|
2528
|
+
}, [stack.length, current.screen, current.context?.marketplace, callbacks, refreshCounter]);
|
|
2529
|
+
const handleSelect = (0, import_react15.useCallback)(
|
|
2530
|
+
(value) => {
|
|
2531
|
+
const screen2 = current.screen;
|
|
2532
|
+
const ctx = current.context;
|
|
2533
|
+
if (screen2 === "main") handleMainSelect(value, nav);
|
|
2534
|
+
else if (screen2 === "marketplace-list") handleMarketplaceListSelect(value, nav);
|
|
2535
|
+
else if (screen2 === "marketplace-action")
|
|
2536
|
+
handleMarketplaceActionSelect(value, ctx?.marketplace ?? "", callbacks, nav);
|
|
2537
|
+
else if (screen2 === "marketplace-browse")
|
|
2538
|
+
handleMarketplaceBrowseSelect(value, ctx?.marketplace ?? "", items, nav);
|
|
2539
|
+
else if (screen2 === "marketplace-install-scope")
|
|
2540
|
+
handleInstallScopeSelect(value, ctx?.pluginId ?? "", callbacks, nav);
|
|
2541
|
+
else if (screen2 === "installed-list") handleInstalledListSelect(value, callbacks, nav);
|
|
2542
|
+
else if (screen2 === "installed-action")
|
|
2543
|
+
handleInstalledActionSelect(value, ctx?.pluginId ?? "", callbacks, nav);
|
|
2544
|
+
},
|
|
2545
|
+
[current, items, callbacks, push, pop, popN, notify, setConfirm, refresh]
|
|
2546
|
+
);
|
|
2547
|
+
const handleTextSubmit = (0, import_react15.useCallback)(
|
|
2548
|
+
(value) => {
|
|
2549
|
+
if (current.screen === "marketplace-add") {
|
|
2550
|
+
callbacks.marketplaceAdd(value).then((name) => {
|
|
2551
|
+
notify(`Added marketplace "${name}" from ${value}.`);
|
|
2552
|
+
pop();
|
|
2553
|
+
}).catch((err) => {
|
|
2554
|
+
notify(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
2555
|
+
pop();
|
|
2556
|
+
});
|
|
2557
|
+
}
|
|
2558
|
+
},
|
|
2559
|
+
[current.screen, callbacks, notify, pop]
|
|
2560
|
+
);
|
|
2561
|
+
if (confirm) {
|
|
2562
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2563
|
+
ConfirmPrompt,
|
|
2564
|
+
{
|
|
2565
|
+
message: confirm.message,
|
|
2566
|
+
onSelect: (index) => {
|
|
2567
|
+
if (index === 0) confirm.onConfirm();
|
|
2568
|
+
else confirm.onCancel();
|
|
2569
|
+
}
|
|
2570
|
+
}
|
|
2571
|
+
);
|
|
2572
|
+
}
|
|
2573
|
+
const screen = current.screen;
|
|
2574
|
+
if (screen === "marketplace-add") {
|
|
2575
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2576
|
+
TextPrompt,
|
|
2577
|
+
{
|
|
2578
|
+
title: "Add Marketplace Source",
|
|
2579
|
+
placeholder: "owner/repo or git URL",
|
|
2580
|
+
onSubmit: handleTextSubmit,
|
|
2581
|
+
onCancel: pop,
|
|
2582
|
+
validate: (v) => !v.includes("/") ? "Must be owner/repo or a git URL" : void 0
|
|
2583
|
+
}
|
|
2584
|
+
);
|
|
2585
|
+
}
|
|
2586
|
+
if (screen === "marketplace-action") {
|
|
2587
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2588
|
+
MenuSelect,
|
|
2589
|
+
{
|
|
2590
|
+
title: `Marketplace: ${current.context?.marketplace ?? ""}`,
|
|
2591
|
+
items: [
|
|
2592
|
+
{ label: "Browse plugins", value: "browse" },
|
|
2593
|
+
{ label: "Update", value: "update" },
|
|
2594
|
+
{ label: "Remove", value: "remove" }
|
|
2595
|
+
],
|
|
2596
|
+
onSelect: handleSelect,
|
|
2597
|
+
onBack: pop
|
|
2598
|
+
},
|
|
2599
|
+
stack.length
|
|
2600
|
+
);
|
|
2601
|
+
}
|
|
2602
|
+
if (screen === "marketplace-install-scope") {
|
|
2603
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2604
|
+
MenuSelect,
|
|
2605
|
+
{
|
|
2606
|
+
title: `Install scope for "${current.context?.pluginId ?? ""}"`,
|
|
2607
|
+
items: [
|
|
2608
|
+
{ label: "User scope", value: "user" },
|
|
2609
|
+
{ label: "Project scope", value: "project" }
|
|
2610
|
+
],
|
|
2611
|
+
onSelect: handleSelect,
|
|
2612
|
+
onBack: pop
|
|
2613
|
+
},
|
|
2614
|
+
stack.length
|
|
2615
|
+
);
|
|
2616
|
+
}
|
|
2617
|
+
if (screen === "installed-action") {
|
|
2618
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2619
|
+
MenuSelect,
|
|
2620
|
+
{
|
|
2621
|
+
title: `Plugin: ${current.context?.pluginId ?? ""}`,
|
|
2622
|
+
items: [{ label: "Uninstall", value: "uninstall" }],
|
|
2623
|
+
onSelect: handleSelect,
|
|
2624
|
+
onBack: pop
|
|
2625
|
+
},
|
|
2626
|
+
stack.length
|
|
2627
|
+
);
|
|
2628
|
+
}
|
|
2629
|
+
const titleMap = {
|
|
2630
|
+
main: "Plugin Management",
|
|
2631
|
+
"marketplace-list": "Marketplace",
|
|
2632
|
+
"marketplace-browse": `Browse: ${current.context?.marketplace ?? ""}`,
|
|
2633
|
+
"installed-list": "Installed Plugins"
|
|
2634
|
+
};
|
|
2635
|
+
const staticItemsMap = {
|
|
2636
|
+
main: [
|
|
2637
|
+
{ label: "Marketplace", value: "marketplace" },
|
|
2638
|
+
{ label: "Installed Plugins", value: "installed" }
|
|
2639
|
+
]
|
|
2640
|
+
};
|
|
2641
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2642
|
+
MenuSelect,
|
|
2643
|
+
{
|
|
2644
|
+
title: titleMap[screen] ?? "Plugin Management",
|
|
2645
|
+
items: staticItemsMap[screen] ?? items,
|
|
2646
|
+
onSelect: handleSelect,
|
|
2647
|
+
onBack: pop,
|
|
2648
|
+
loading,
|
|
2649
|
+
error
|
|
2650
|
+
},
|
|
2651
|
+
`${screen}-${stack.length}-${refreshCounter}`
|
|
2652
|
+
);
|
|
2653
|
+
}
|
|
2654
|
+
|
|
2655
|
+
// src/ui/App.tsx
|
|
2656
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
2154
2657
|
var EXIT_DELAY_MS2 = 500;
|
|
2155
2658
|
function mergeHooksIntoConfig(configHooks, pluginHooks) {
|
|
2156
2659
|
const pluginKeys = Object.keys(pluginHooks);
|
|
@@ -2169,7 +2672,7 @@ function mergeHooksIntoConfig(configHooks, pluginHooks) {
|
|
|
2169
2672
|
return merged;
|
|
2170
2673
|
}
|
|
2171
2674
|
function App(props) {
|
|
2172
|
-
const { exit } = (0,
|
|
2675
|
+
const { exit } = (0, import_ink13.useApp)();
|
|
2173
2676
|
const { registry, pluginHooks } = useCommandRegistry(props.cwd ?? process.cwd());
|
|
2174
2677
|
const configWithPluginHooks = {
|
|
2175
2678
|
...props.config,
|
|
@@ -2182,15 +2685,16 @@ function App(props) {
|
|
|
2182
2685
|
{ ...props, config: configWithPluginHooks }
|
|
2183
2686
|
);
|
|
2184
2687
|
const { messages, setMessages, addMessage } = useMessages();
|
|
2185
|
-
const [isThinking, setIsThinking] = (0,
|
|
2688
|
+
const [isThinking, setIsThinking] = (0, import_react16.useState)(false);
|
|
2186
2689
|
const initialCtx = session.getContextState();
|
|
2187
|
-
const [contextState, setContextState] = (0,
|
|
2690
|
+
const [contextState, setContextState] = (0, import_react16.useState)({
|
|
2188
2691
|
percentage: initialCtx.usedPercentage,
|
|
2189
2692
|
usedTokens: initialCtx.usedTokens,
|
|
2190
2693
|
maxTokens: initialCtx.maxTokens
|
|
2191
2694
|
});
|
|
2192
|
-
const pendingModelChangeRef = (0,
|
|
2193
|
-
const [pendingModelId, setPendingModelId] = (0,
|
|
2695
|
+
const pendingModelChangeRef = (0, import_react16.useRef)(null);
|
|
2696
|
+
const [pendingModelId, setPendingModelId] = (0, import_react16.useState)(null);
|
|
2697
|
+
const [showPluginTUI, setShowPluginTUI] = (0, import_react16.useState)(false);
|
|
2194
2698
|
const pluginCallbacks = usePluginCallbacks(props.cwd ?? process.cwd());
|
|
2195
2699
|
const handleSlashCommand = useSlashCommands(
|
|
2196
2700
|
session,
|
|
@@ -2200,7 +2704,8 @@ function App(props) {
|
|
|
2200
2704
|
registry,
|
|
2201
2705
|
pendingModelChangeRef,
|
|
2202
2706
|
setPendingModelId,
|
|
2203
|
-
pluginCallbacks
|
|
2707
|
+
pluginCallbacks,
|
|
2708
|
+
setShowPluginTUI
|
|
2204
2709
|
);
|
|
2205
2710
|
const handleSubmit = useSubmitHandler(
|
|
2206
2711
|
session,
|
|
@@ -2211,36 +2716,36 @@ function App(props) {
|
|
|
2211
2716
|
setContextState,
|
|
2212
2717
|
registry
|
|
2213
2718
|
);
|
|
2214
|
-
(0,
|
|
2719
|
+
(0, import_ink13.useInput)(
|
|
2215
2720
|
(_input, key) => {
|
|
2216
2721
|
if (key.ctrl && _input === "c") exit();
|
|
2217
2722
|
if (key.escape && isThinking) session.abort();
|
|
2218
2723
|
},
|
|
2219
|
-
{ isActive: !permissionRequest }
|
|
2724
|
+
{ isActive: !permissionRequest && !showPluginTUI }
|
|
2220
2725
|
);
|
|
2221
|
-
return /* @__PURE__ */ (0,
|
|
2222
|
-
/* @__PURE__ */ (0,
|
|
2223
|
-
/* @__PURE__ */ (0,
|
|
2726
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_ink13.Box, { flexDirection: "column", children: [
|
|
2727
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_ink13.Box, { flexDirection: "column", paddingX: 1, marginBottom: 1, children: [
|
|
2728
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_ink13.Text, { color: "cyan", bold: true, children: `
|
|
2224
2729
|
____ ___ ____ ___ _____ _
|
|
2225
2730
|
| _ \\ / _ \\| __ ) / _ \\_ _|/ \\
|
|
2226
2731
|
| |_) | | | | _ \\| | | || | / _ \\
|
|
2227
2732
|
| _ <| |_| | |_) | |_| || |/ ___ \\
|
|
2228
2733
|
|_| \\_\\\\___/|____/ \\___/ |_/_/ \\_\\
|
|
2229
2734
|
` }),
|
|
2230
|
-
/* @__PURE__ */ (0,
|
|
2735
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_ink13.Text, { dimColor: true, children: [
|
|
2231
2736
|
" v",
|
|
2232
2737
|
props.version ?? "0.0.0"
|
|
2233
2738
|
] })
|
|
2234
2739
|
] }),
|
|
2235
|
-
/* @__PURE__ */ (0,
|
|
2236
|
-
/* @__PURE__ */ (0,
|
|
2237
|
-
isThinking && /* @__PURE__ */ (0,
|
|
2740
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_ink13.Box, { flexDirection: "column", paddingX: 1, flexGrow: 1, children: [
|
|
2741
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(MessageList, { messages }),
|
|
2742
|
+
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 }) })
|
|
2238
2743
|
] }),
|
|
2239
|
-
permissionRequest && /* @__PURE__ */ (0,
|
|
2240
|
-
pendingModelId && /* @__PURE__ */ (0,
|
|
2744
|
+
permissionRequest && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(PermissionPrompt, { request: permissionRequest }),
|
|
2745
|
+
pendingModelId && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
2241
2746
|
ConfirmPrompt,
|
|
2242
2747
|
{
|
|
2243
|
-
message: `Change model to ${(0,
|
|
2748
|
+
message: `Change model to ${(0, import_agent_core6.getModelName)(pendingModelId)}? This will restart the session.`,
|
|
2244
2749
|
onSelect: (index) => {
|
|
2245
2750
|
setPendingModelId(null);
|
|
2246
2751
|
pendingModelChangeRef.current = null;
|
|
@@ -2248,28 +2753,38 @@ function App(props) {
|
|
|
2248
2753
|
try {
|
|
2249
2754
|
const settingsPath = getUserSettingsPath();
|
|
2250
2755
|
updateModelInSettings(settingsPath, pendingModelId);
|
|
2251
|
-
addMessage(
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2756
|
+
addMessage(
|
|
2757
|
+
(0, import_agent_core7.createSystemMessage)(
|
|
2758
|
+
`Model changed to ${(0, import_agent_core6.getModelName)(pendingModelId)}. Restarting...`
|
|
2759
|
+
)
|
|
2760
|
+
);
|
|
2255
2761
|
setTimeout(() => exit(), EXIT_DELAY_MS2);
|
|
2256
2762
|
} catch (err) {
|
|
2257
|
-
addMessage(
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2763
|
+
addMessage(
|
|
2764
|
+
(0, import_agent_core7.createSystemMessage)(
|
|
2765
|
+
`Failed: ${err instanceof Error ? err.message : String(err)}`
|
|
2766
|
+
)
|
|
2767
|
+
);
|
|
2261
2768
|
}
|
|
2262
2769
|
} else {
|
|
2263
|
-
addMessage(
|
|
2770
|
+
addMessage((0, import_agent_core7.createSystemMessage)("Model change cancelled."));
|
|
2264
2771
|
}
|
|
2265
2772
|
}
|
|
2266
2773
|
}
|
|
2267
2774
|
),
|
|
2268
|
-
/* @__PURE__ */ (0,
|
|
2775
|
+
showPluginTUI && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
2776
|
+
PluginTUI,
|
|
2777
|
+
{
|
|
2778
|
+
callbacks: pluginCallbacks,
|
|
2779
|
+
onClose: () => setShowPluginTUI(false),
|
|
2780
|
+
addMessage: (msg) => addMessage((0, import_agent_core7.createSystemMessage)(msg.content))
|
|
2781
|
+
}
|
|
2782
|
+
),
|
|
2783
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
2269
2784
|
StatusBar,
|
|
2270
2785
|
{
|
|
2271
2786
|
permissionMode: session.getPermissionMode(),
|
|
2272
|
-
modelName: (0,
|
|
2787
|
+
modelName: (0, import_agent_core6.getModelName)(props.config.provider.model),
|
|
2273
2788
|
sessionId: session.getSessionId(),
|
|
2274
2789
|
messageCount: messages.length,
|
|
2275
2790
|
isThinking,
|
|
@@ -2278,20 +2793,20 @@ function App(props) {
|
|
|
2278
2793
|
contextMaxTokens: contextState.maxTokens
|
|
2279
2794
|
}
|
|
2280
2795
|
),
|
|
2281
|
-
/* @__PURE__ */ (0,
|
|
2796
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
2282
2797
|
InputArea,
|
|
2283
2798
|
{
|
|
2284
2799
|
onSubmit: handleSubmit,
|
|
2285
|
-
isDisabled: isThinking || !!permissionRequest,
|
|
2800
|
+
isDisabled: isThinking || !!permissionRequest || showPluginTUI,
|
|
2286
2801
|
registry
|
|
2287
2802
|
}
|
|
2288
2803
|
),
|
|
2289
|
-
/* @__PURE__ */ (0,
|
|
2804
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_ink13.Text, { children: " " })
|
|
2290
2805
|
] });
|
|
2291
2806
|
}
|
|
2292
2807
|
|
|
2293
2808
|
// src/ui/render.tsx
|
|
2294
|
-
var
|
|
2809
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
2295
2810
|
function renderApp(options) {
|
|
2296
2811
|
process.on("unhandledRejection", (reason) => {
|
|
2297
2812
|
process.stderr.write(`
|
|
@@ -2302,7 +2817,7 @@ function renderApp(options) {
|
|
|
2302
2817
|
`);
|
|
2303
2818
|
}
|
|
2304
2819
|
});
|
|
2305
|
-
const instance = (0,
|
|
2820
|
+
const instance = (0, import_ink14.render)(/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(App, { ...options }), {
|
|
2306
2821
|
exitOnCtrlC: true
|
|
2307
2822
|
});
|
|
2308
2823
|
instance.waitUntilExit().catch((err) => {
|