@robota-sdk/agent-cli 3.0.0-beta.34 → 3.0.0-beta.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/node/bin.cjs +536 -63
- package/dist/node/bin.js +1 -1
- package/dist/node/{chunk-RDPIMQOC.js → chunk-27OPEZHA.js} +534 -61
- package/dist/node/index.cjs +536 -63
- package/dist/node/index.js +1 -1
- package/package.json +3 -3
package/dist/node/index.cjs
CHANGED
|
@@ -179,11 +179,11 @@ 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
|
|
185
|
+
var import_react16 = require("react");
|
|
186
|
+
var import_ink13 = require("ink");
|
|
187
187
|
var import_agent_core3 = require("@robota-sdk/agent-core");
|
|
188
188
|
|
|
189
189
|
// src/ui/hooks/useSession.ts
|
|
@@ -536,18 +536,9 @@ async function handlePluginCommand(args, addMessage, callbacks) {
|
|
|
536
536
|
try {
|
|
537
537
|
switch (subcommand) {
|
|
538
538
|
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 };
|
|
539
|
+
case void 0:
|
|
540
|
+
case "manage": {
|
|
541
|
+
return { handled: true, triggerPluginTUI: true };
|
|
551
542
|
}
|
|
552
543
|
case "install": {
|
|
553
544
|
if (!subArgs) {
|
|
@@ -694,7 +685,7 @@ async function executeSlashCommand(cmd, args, session, addMessage, clearMessages
|
|
|
694
685
|
|
|
695
686
|
// src/ui/hooks/useSlashCommands.ts
|
|
696
687
|
var EXIT_DELAY_MS = 500;
|
|
697
|
-
function useSlashCommands(session, addMessage, setMessages, exit, registry, pendingModelChangeRef, setPendingModelId, pluginCallbacks) {
|
|
688
|
+
function useSlashCommands(session, addMessage, setMessages, exit, registry, pendingModelChangeRef, setPendingModelId, pluginCallbacks, setShowPluginTUI) {
|
|
698
689
|
return (0, import_react3.useCallback)(
|
|
699
690
|
async (input) => {
|
|
700
691
|
const parts = input.slice(1).split(/\s+/);
|
|
@@ -714,6 +705,9 @@ function useSlashCommands(session, addMessage, setMessages, exit, registry, pend
|
|
|
714
705
|
pendingModelChangeRef.current = result.pendingModelId;
|
|
715
706
|
setPendingModelId(result.pendingModelId);
|
|
716
707
|
}
|
|
708
|
+
if (result.triggerPluginTUI) {
|
|
709
|
+
setShowPluginTUI?.(true);
|
|
710
|
+
}
|
|
717
711
|
if (result.exitRequested) {
|
|
718
712
|
setTimeout(() => exit(), EXIT_DELAY_MS);
|
|
719
713
|
}
|
|
@@ -727,7 +721,8 @@ function useSlashCommands(session, addMessage, setMessages, exit, registry, pend
|
|
|
727
721
|
registry,
|
|
728
722
|
pendingModelChangeRef,
|
|
729
723
|
setPendingModelId,
|
|
730
|
-
pluginCallbacks
|
|
724
|
+
pluginCallbacks,
|
|
725
|
+
setShowPluginTUI
|
|
731
726
|
]
|
|
732
727
|
);
|
|
733
728
|
}
|
|
@@ -1111,22 +1106,7 @@ function createBuiltinCommands() {
|
|
|
1111
1106
|
{ name: "cost", description: "Show session info", source: "builtin" },
|
|
1112
1107
|
{ name: "context", description: "Context window info", source: "builtin" },
|
|
1113
1108
|
{ 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
|
-
},
|
|
1109
|
+
{ name: "plugin", description: "Manage plugins", source: "builtin" },
|
|
1130
1110
|
{ name: "reload-plugins", description: "Reload all plugin resources", source: "builtin" },
|
|
1131
1111
|
{ name: "reset", description: "Delete settings and exit", source: "builtin" },
|
|
1132
1112
|
{ name: "exit", description: "Exit CLI", source: "builtin" }
|
|
@@ -1393,18 +1373,50 @@ function usePluginCallbacks(cwd) {
|
|
|
1393
1373
|
return {
|
|
1394
1374
|
listInstalled: async () => {
|
|
1395
1375
|
const plugins = await loader.loadAll();
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1376
|
+
const enabledMap = settingsStore.getEnabledPlugins();
|
|
1377
|
+
return plugins.map((p) => {
|
|
1378
|
+
const parts = p.pluginDir.split("/");
|
|
1379
|
+
const cacheIdx = parts.indexOf("cache");
|
|
1380
|
+
const marketplaceName = cacheIdx >= 0 ? parts[cacheIdx + 1] : "";
|
|
1381
|
+
const fullId = marketplaceName ? `${p.manifest.name}@${marketplaceName}` : p.manifest.name;
|
|
1382
|
+
return {
|
|
1383
|
+
name: fullId,
|
|
1384
|
+
description: p.manifest.description,
|
|
1385
|
+
enabled: enabledMap[fullId] !== false && enabledMap[p.manifest.name] !== false
|
|
1386
|
+
};
|
|
1387
|
+
});
|
|
1388
|
+
},
|
|
1389
|
+
listAvailablePlugins: async (marketplaceName) => {
|
|
1390
|
+
let manifest;
|
|
1391
|
+
try {
|
|
1392
|
+
manifest = marketplace.fetchManifest(marketplaceName);
|
|
1393
|
+
} catch {
|
|
1394
|
+
return [];
|
|
1395
|
+
}
|
|
1396
|
+
const installed = installer.getInstalledPlugins();
|
|
1397
|
+
const installedNames = new Set(Object.values(installed).map((r) => r.pluginName));
|
|
1398
|
+
return manifest.plugins.map((p) => ({
|
|
1399
|
+
name: p.name,
|
|
1400
|
+
description: p.description,
|
|
1401
|
+
installed: installedNames.has(p.name)
|
|
1400
1402
|
}));
|
|
1401
1403
|
},
|
|
1402
|
-
install: async (pluginId) => {
|
|
1404
|
+
install: async (pluginId, scope) => {
|
|
1403
1405
|
const [name, marketplaceName] = pluginId.split("@");
|
|
1404
1406
|
if (!name || !marketplaceName) {
|
|
1405
1407
|
throw new Error("Plugin ID must be in format: name@marketplace");
|
|
1406
1408
|
}
|
|
1407
|
-
|
|
1409
|
+
if (scope === "project") {
|
|
1410
|
+
const projectPluginsDir = (0, import_node_path4.join)(cwd, ".robota", "plugins");
|
|
1411
|
+
const projectInstaller = new import_agent_sdk4.BundlePluginInstaller({
|
|
1412
|
+
pluginsDir: projectPluginsDir,
|
|
1413
|
+
settingsStore,
|
|
1414
|
+
marketplaceClient: marketplace
|
|
1415
|
+
});
|
|
1416
|
+
await projectInstaller.install(name, marketplaceName);
|
|
1417
|
+
} else {
|
|
1418
|
+
await installer.install(name, marketplaceName);
|
|
1419
|
+
}
|
|
1408
1420
|
},
|
|
1409
1421
|
uninstall: async (pluginId) => {
|
|
1410
1422
|
await installer.uninstall(pluginId);
|
|
@@ -2149,8 +2161,459 @@ function StreamingIndicator({ text, activeTools }) {
|
|
|
2149
2161
|
] });
|
|
2150
2162
|
}
|
|
2151
2163
|
|
|
2152
|
-
// src/ui/
|
|
2164
|
+
// src/ui/PluginTUI.tsx
|
|
2165
|
+
var import_react15 = require("react");
|
|
2166
|
+
|
|
2167
|
+
// src/ui/MenuSelect.tsx
|
|
2168
|
+
var import_react13 = require("react");
|
|
2169
|
+
var import_ink11 = require("ink");
|
|
2153
2170
|
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
2171
|
+
function MenuSelect({
|
|
2172
|
+
title,
|
|
2173
|
+
items,
|
|
2174
|
+
onSelect,
|
|
2175
|
+
onBack,
|
|
2176
|
+
loading,
|
|
2177
|
+
error
|
|
2178
|
+
}) {
|
|
2179
|
+
const [selected, setSelected] = (0, import_react13.useState)(0);
|
|
2180
|
+
const selectedRef = (0, import_react13.useRef)(0);
|
|
2181
|
+
const resolvedRef = (0, import_react13.useRef)(false);
|
|
2182
|
+
const doSelect = (0, import_react13.useCallback)(
|
|
2183
|
+
(index) => {
|
|
2184
|
+
if (resolvedRef.current || items.length === 0) return;
|
|
2185
|
+
resolvedRef.current = true;
|
|
2186
|
+
onSelect(items[index].value);
|
|
2187
|
+
},
|
|
2188
|
+
[items, onSelect]
|
|
2189
|
+
);
|
|
2190
|
+
(0, import_ink11.useInput)((input, key) => {
|
|
2191
|
+
if (resolvedRef.current) return;
|
|
2192
|
+
if (key.escape) {
|
|
2193
|
+
resolvedRef.current = true;
|
|
2194
|
+
onBack();
|
|
2195
|
+
return;
|
|
2196
|
+
}
|
|
2197
|
+
if (loading || error || items.length === 0) return;
|
|
2198
|
+
if (key.upArrow) {
|
|
2199
|
+
const next = selectedRef.current > 0 ? selectedRef.current - 1 : selectedRef.current;
|
|
2200
|
+
selectedRef.current = next;
|
|
2201
|
+
setSelected(next);
|
|
2202
|
+
} else if (key.downArrow) {
|
|
2203
|
+
const next = selectedRef.current < items.length - 1 ? selectedRef.current + 1 : selectedRef.current;
|
|
2204
|
+
selectedRef.current = next;
|
|
2205
|
+
setSelected(next);
|
|
2206
|
+
} else if (key.return) {
|
|
2207
|
+
doSelect(selectedRef.current);
|
|
2208
|
+
}
|
|
2209
|
+
});
|
|
2210
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_ink11.Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
|
|
2211
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_ink11.Text, { color: "yellow", bold: true, children: title }),
|
|
2212
|
+
loading && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_ink11.Box, { marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_ink11.Text, { dimColor: true, children: "Loading..." }) }),
|
|
2213
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_ink11.Box, { marginTop: 1, flexDirection: "column", children: [
|
|
2214
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_ink11.Text, { color: "red", children: error }),
|
|
2215
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_ink11.Text, { dimColor: true, children: "Press Esc to go back" })
|
|
2216
|
+
] }),
|
|
2217
|
+
!loading && !error && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_ink11.Box, { flexDirection: "column", marginTop: 1, children: items.map((item, i) => /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_ink11.Box, { children: [
|
|
2218
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_ink11.Text, { color: i === selected ? "cyan" : void 0, bold: i === selected, children: [
|
|
2219
|
+
i === selected ? "> " : " ",
|
|
2220
|
+
item.label
|
|
2221
|
+
] }),
|
|
2222
|
+
item.hint && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_ink11.Text, { dimColor: true, children: [
|
|
2223
|
+
" ",
|
|
2224
|
+
item.hint
|
|
2225
|
+
] })
|
|
2226
|
+
] }, item.value)) }),
|
|
2227
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_ink11.Text, { dimColor: true, children: loading || error ? "" : " \u2191\u2193 Navigate Enter Select Esc Back" })
|
|
2228
|
+
] });
|
|
2229
|
+
}
|
|
2230
|
+
|
|
2231
|
+
// src/ui/TextPrompt.tsx
|
|
2232
|
+
var import_react14 = require("react");
|
|
2233
|
+
var import_ink12 = require("ink");
|
|
2234
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
2235
|
+
function TextPrompt({
|
|
2236
|
+
title,
|
|
2237
|
+
placeholder,
|
|
2238
|
+
onSubmit,
|
|
2239
|
+
onCancel,
|
|
2240
|
+
validate
|
|
2241
|
+
}) {
|
|
2242
|
+
const [value, setValue] = (0, import_react14.useState)("");
|
|
2243
|
+
const [error, setError] = (0, import_react14.useState)();
|
|
2244
|
+
const resolvedRef = (0, import_react14.useRef)(false);
|
|
2245
|
+
const valueRef = (0, import_react14.useRef)("");
|
|
2246
|
+
const handleSubmit = (0, import_react14.useCallback)(() => {
|
|
2247
|
+
if (resolvedRef.current) return;
|
|
2248
|
+
const trimmed = valueRef.current.trim();
|
|
2249
|
+
if (!trimmed) return;
|
|
2250
|
+
if (validate) {
|
|
2251
|
+
const err = validate(trimmed);
|
|
2252
|
+
if (err) {
|
|
2253
|
+
setError(err);
|
|
2254
|
+
return;
|
|
2255
|
+
}
|
|
2256
|
+
}
|
|
2257
|
+
resolvedRef.current = true;
|
|
2258
|
+
onSubmit(trimmed);
|
|
2259
|
+
}, [validate, onSubmit]);
|
|
2260
|
+
(0, import_ink12.useInput)((input, key) => {
|
|
2261
|
+
if (resolvedRef.current) return;
|
|
2262
|
+
if (key.escape) {
|
|
2263
|
+
resolvedRef.current = true;
|
|
2264
|
+
onCancel();
|
|
2265
|
+
return;
|
|
2266
|
+
}
|
|
2267
|
+
if (key.return) {
|
|
2268
|
+
handleSubmit();
|
|
2269
|
+
return;
|
|
2270
|
+
}
|
|
2271
|
+
if (key.backspace || key.delete) {
|
|
2272
|
+
valueRef.current = valueRef.current.slice(0, -1);
|
|
2273
|
+
setValue(valueRef.current);
|
|
2274
|
+
setError(void 0);
|
|
2275
|
+
return;
|
|
2276
|
+
}
|
|
2277
|
+
if (input && !key.ctrl && !key.meta) {
|
|
2278
|
+
valueRef.current = valueRef.current + input;
|
|
2279
|
+
setValue(valueRef.current);
|
|
2280
|
+
setError(void 0);
|
|
2281
|
+
}
|
|
2282
|
+
});
|
|
2283
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_ink12.Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
|
|
2284
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_ink12.Text, { color: "yellow", bold: true, children: title }),
|
|
2285
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_ink12.Box, { marginTop: 1, children: [
|
|
2286
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_ink12.Text, { color: "cyan", children: "> " }),
|
|
2287
|
+
value ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_ink12.Text, { children: value }) : placeholder ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_ink12.Text, { dimColor: true, children: placeholder }) : null,
|
|
2288
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_ink12.Text, { color: "cyan", children: "\u2588" })
|
|
2289
|
+
] }),
|
|
2290
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_ink12.Text, { color: "red", children: error }),
|
|
2291
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_ink12.Text, { dimColor: true, children: " Enter Submit Esc Cancel" })
|
|
2292
|
+
] });
|
|
2293
|
+
}
|
|
2294
|
+
|
|
2295
|
+
// src/ui/plugin-tui-handlers.ts
|
|
2296
|
+
function handleMainSelect(value, nav) {
|
|
2297
|
+
if (value === "marketplace") {
|
|
2298
|
+
nav.push({ screen: "marketplace-list" });
|
|
2299
|
+
} else if (value === "installed") {
|
|
2300
|
+
nav.push({ screen: "installed-list" });
|
|
2301
|
+
}
|
|
2302
|
+
}
|
|
2303
|
+
function handleMarketplaceListSelect(value, nav) {
|
|
2304
|
+
if (value === "__add__") {
|
|
2305
|
+
nav.push({ screen: "marketplace-add" });
|
|
2306
|
+
} else {
|
|
2307
|
+
nav.push({ screen: "marketplace-action", context: { marketplace: value } });
|
|
2308
|
+
}
|
|
2309
|
+
}
|
|
2310
|
+
function handleMarketplaceActionSelect(value, marketplace, callbacks, nav) {
|
|
2311
|
+
if (value === "browse") {
|
|
2312
|
+
nav.push({ screen: "marketplace-browse", context: { marketplace } });
|
|
2313
|
+
} else if (value === "update") {
|
|
2314
|
+
callbacks.marketplaceUpdate(marketplace).then(() => {
|
|
2315
|
+
nav.notify(`Updated marketplace "${marketplace}".`);
|
|
2316
|
+
nav.pop();
|
|
2317
|
+
}).catch((err) => {
|
|
2318
|
+
nav.notify(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
2319
|
+
});
|
|
2320
|
+
} else if (value === "remove") {
|
|
2321
|
+
nav.setConfirm({
|
|
2322
|
+
message: `Remove marketplace "${marketplace}" and all its plugins?`,
|
|
2323
|
+
onConfirm: () => {
|
|
2324
|
+
nav.setConfirm(void 0);
|
|
2325
|
+
callbacks.marketplaceRemove(marketplace).then(() => {
|
|
2326
|
+
nav.notify(`Removed marketplace "${marketplace}".`);
|
|
2327
|
+
nav.popN(2);
|
|
2328
|
+
}).catch((err) => {
|
|
2329
|
+
nav.notify(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
2330
|
+
});
|
|
2331
|
+
},
|
|
2332
|
+
onCancel: () => nav.setConfirm(void 0)
|
|
2333
|
+
});
|
|
2334
|
+
}
|
|
2335
|
+
}
|
|
2336
|
+
function handleMarketplaceBrowseSelect(value, marketplace, items, nav) {
|
|
2337
|
+
const fullId = `${value}@${marketplace}`;
|
|
2338
|
+
const item = items.find((i) => i.value === value);
|
|
2339
|
+
if (item?.hint === "installed") {
|
|
2340
|
+
nav.push({ screen: "installed-action", context: { pluginId: fullId } });
|
|
2341
|
+
} else {
|
|
2342
|
+
nav.push({ screen: "marketplace-install-scope", context: { marketplace, pluginId: fullId } });
|
|
2343
|
+
}
|
|
2344
|
+
}
|
|
2345
|
+
function handleInstallScopeSelect(value, pluginId, callbacks, nav) {
|
|
2346
|
+
const scope = value;
|
|
2347
|
+
callbacks.install(pluginId, scope).then(() => {
|
|
2348
|
+
nav.notify(`Installed plugin "${pluginId}" (${scope} scope).`);
|
|
2349
|
+
nav.popN(2);
|
|
2350
|
+
}).catch((err) => {
|
|
2351
|
+
nav.notify(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
2352
|
+
});
|
|
2353
|
+
}
|
|
2354
|
+
function handleInstalledListSelect(value, callbacks, nav) {
|
|
2355
|
+
nav.setConfirm({
|
|
2356
|
+
message: `Uninstall plugin "${value}"?`,
|
|
2357
|
+
onConfirm: () => {
|
|
2358
|
+
nav.setConfirm(void 0);
|
|
2359
|
+
callbacks.uninstall(value).then(() => {
|
|
2360
|
+
nav.notify(`Uninstalled plugin "${value}".`);
|
|
2361
|
+
nav.refresh();
|
|
2362
|
+
}).catch((err) => {
|
|
2363
|
+
nav.notify(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
2364
|
+
});
|
|
2365
|
+
},
|
|
2366
|
+
onCancel: () => nav.setConfirm(void 0)
|
|
2367
|
+
});
|
|
2368
|
+
}
|
|
2369
|
+
function handleInstalledActionSelect(value, pluginId, callbacks, nav) {
|
|
2370
|
+
if (value === "uninstall") {
|
|
2371
|
+
nav.setConfirm({
|
|
2372
|
+
message: `Uninstall plugin "${pluginId}"?`,
|
|
2373
|
+
onConfirm: () => {
|
|
2374
|
+
nav.setConfirm(void 0);
|
|
2375
|
+
callbacks.uninstall(pluginId).then(() => {
|
|
2376
|
+
nav.notify(`Uninstalled plugin "${pluginId}".`);
|
|
2377
|
+
nav.popN(2);
|
|
2378
|
+
}).catch((err) => {
|
|
2379
|
+
nav.notify(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
2380
|
+
});
|
|
2381
|
+
},
|
|
2382
|
+
onCancel: () => nav.setConfirm(void 0)
|
|
2383
|
+
});
|
|
2384
|
+
}
|
|
2385
|
+
}
|
|
2386
|
+
|
|
2387
|
+
// src/ui/PluginTUI.tsx
|
|
2388
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
2389
|
+
function PluginTUI({ callbacks, onClose, addMessage }) {
|
|
2390
|
+
const [stack, setStack] = (0, import_react15.useState)([{ screen: "main" }]);
|
|
2391
|
+
const [items, setItems] = (0, import_react15.useState)([]);
|
|
2392
|
+
const [loading, setLoading] = (0, import_react15.useState)(false);
|
|
2393
|
+
const [error, setError] = (0, import_react15.useState)();
|
|
2394
|
+
const [confirm, setConfirm] = (0, import_react15.useState)();
|
|
2395
|
+
const [refreshCounter, setRefreshCounter] = (0, import_react15.useState)(0);
|
|
2396
|
+
const current = stack[stack.length - 1] ?? { screen: "main" };
|
|
2397
|
+
const push = (0, import_react15.useCallback)((state) => {
|
|
2398
|
+
setStack((prev) => [...prev, state]);
|
|
2399
|
+
setItems([]);
|
|
2400
|
+
setError(void 0);
|
|
2401
|
+
}, []);
|
|
2402
|
+
const pop = (0, import_react15.useCallback)(() => {
|
|
2403
|
+
setStack((prev) => {
|
|
2404
|
+
if (prev.length <= 1) {
|
|
2405
|
+
onClose();
|
|
2406
|
+
return prev;
|
|
2407
|
+
}
|
|
2408
|
+
return prev.slice(0, -1);
|
|
2409
|
+
});
|
|
2410
|
+
setItems([]);
|
|
2411
|
+
setError(void 0);
|
|
2412
|
+
}, [onClose]);
|
|
2413
|
+
const popN = (0, import_react15.useCallback)(
|
|
2414
|
+
(n) => {
|
|
2415
|
+
setStack((prev) => {
|
|
2416
|
+
const next = prev.slice(0, Math.max(1, prev.length - n));
|
|
2417
|
+
if (next.length === 0) {
|
|
2418
|
+
onClose();
|
|
2419
|
+
return prev;
|
|
2420
|
+
}
|
|
2421
|
+
return next;
|
|
2422
|
+
});
|
|
2423
|
+
setItems([]);
|
|
2424
|
+
setError(void 0);
|
|
2425
|
+
},
|
|
2426
|
+
[onClose]
|
|
2427
|
+
);
|
|
2428
|
+
const notify = (0, import_react15.useCallback)(
|
|
2429
|
+
(content) => {
|
|
2430
|
+
addMessage?.({ role: "system", content });
|
|
2431
|
+
},
|
|
2432
|
+
[addMessage]
|
|
2433
|
+
);
|
|
2434
|
+
const refresh = (0, import_react15.useCallback)(() => {
|
|
2435
|
+
setItems([]);
|
|
2436
|
+
setRefreshCounter((c) => c + 1);
|
|
2437
|
+
}, []);
|
|
2438
|
+
const nav = { push, pop, popN, notify, setConfirm, refresh };
|
|
2439
|
+
(0, import_react15.useEffect)(() => {
|
|
2440
|
+
const screen2 = current.screen;
|
|
2441
|
+
if (screen2 === "marketplace-list") {
|
|
2442
|
+
setLoading(true);
|
|
2443
|
+
callbacks.marketplaceList().then((sources) => {
|
|
2444
|
+
const baseItems = [{ label: "Add Marketplace", value: "__add__" }];
|
|
2445
|
+
const sourceItems = sources.map((s) => ({
|
|
2446
|
+
label: s.name,
|
|
2447
|
+
value: s.name,
|
|
2448
|
+
hint: s.type
|
|
2449
|
+
}));
|
|
2450
|
+
setItems([...baseItems, ...sourceItems]);
|
|
2451
|
+
setLoading(false);
|
|
2452
|
+
}).catch((err) => {
|
|
2453
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
2454
|
+
setLoading(false);
|
|
2455
|
+
});
|
|
2456
|
+
} else if (screen2 === "marketplace-browse") {
|
|
2457
|
+
const marketplace = current.context?.marketplace ?? "";
|
|
2458
|
+
setLoading(true);
|
|
2459
|
+
callbacks.listAvailablePlugins(marketplace).then((plugins) => {
|
|
2460
|
+
setItems(
|
|
2461
|
+
plugins.map((p) => ({
|
|
2462
|
+
label: p.name,
|
|
2463
|
+
value: p.name,
|
|
2464
|
+
hint: p.installed ? "installed" : p.description
|
|
2465
|
+
}))
|
|
2466
|
+
);
|
|
2467
|
+
setLoading(false);
|
|
2468
|
+
}).catch((err) => {
|
|
2469
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
2470
|
+
setLoading(false);
|
|
2471
|
+
});
|
|
2472
|
+
} else if (screen2 === "installed-list") {
|
|
2473
|
+
setLoading(true);
|
|
2474
|
+
callbacks.listInstalled().then((plugins) => {
|
|
2475
|
+
setItems(
|
|
2476
|
+
plugins.map((p) => ({
|
|
2477
|
+
label: p.name,
|
|
2478
|
+
value: p.name,
|
|
2479
|
+
hint: p.description
|
|
2480
|
+
}))
|
|
2481
|
+
);
|
|
2482
|
+
setLoading(false);
|
|
2483
|
+
}).catch((err) => {
|
|
2484
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
2485
|
+
setLoading(false);
|
|
2486
|
+
});
|
|
2487
|
+
}
|
|
2488
|
+
}, [stack.length, current.screen, current.context?.marketplace, callbacks, refreshCounter]);
|
|
2489
|
+
const handleSelect = (0, import_react15.useCallback)(
|
|
2490
|
+
(value) => {
|
|
2491
|
+
const screen2 = current.screen;
|
|
2492
|
+
const ctx = current.context;
|
|
2493
|
+
if (screen2 === "main") handleMainSelect(value, nav);
|
|
2494
|
+
else if (screen2 === "marketplace-list") handleMarketplaceListSelect(value, nav);
|
|
2495
|
+
else if (screen2 === "marketplace-action")
|
|
2496
|
+
handleMarketplaceActionSelect(value, ctx?.marketplace ?? "", callbacks, nav);
|
|
2497
|
+
else if (screen2 === "marketplace-browse")
|
|
2498
|
+
handleMarketplaceBrowseSelect(value, ctx?.marketplace ?? "", items, nav);
|
|
2499
|
+
else if (screen2 === "marketplace-install-scope")
|
|
2500
|
+
handleInstallScopeSelect(value, ctx?.pluginId ?? "", callbacks, nav);
|
|
2501
|
+
else if (screen2 === "installed-list") handleInstalledListSelect(value, callbacks, nav);
|
|
2502
|
+
else if (screen2 === "installed-action")
|
|
2503
|
+
handleInstalledActionSelect(value, ctx?.pluginId ?? "", callbacks, nav);
|
|
2504
|
+
},
|
|
2505
|
+
[current, items, callbacks, push, pop, popN, notify, setConfirm, refresh]
|
|
2506
|
+
);
|
|
2507
|
+
const handleTextSubmit = (0, import_react15.useCallback)(
|
|
2508
|
+
(value) => {
|
|
2509
|
+
if (current.screen === "marketplace-add") {
|
|
2510
|
+
callbacks.marketplaceAdd(value).then((name) => {
|
|
2511
|
+
notify(`Added marketplace "${name}" from ${value}.`);
|
|
2512
|
+
pop();
|
|
2513
|
+
}).catch((err) => {
|
|
2514
|
+
notify(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
2515
|
+
pop();
|
|
2516
|
+
});
|
|
2517
|
+
}
|
|
2518
|
+
},
|
|
2519
|
+
[current.screen, callbacks, notify, pop]
|
|
2520
|
+
);
|
|
2521
|
+
if (confirm) {
|
|
2522
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2523
|
+
ConfirmPrompt,
|
|
2524
|
+
{
|
|
2525
|
+
message: confirm.message,
|
|
2526
|
+
onSelect: (index) => {
|
|
2527
|
+
if (index === 0) confirm.onConfirm();
|
|
2528
|
+
else confirm.onCancel();
|
|
2529
|
+
}
|
|
2530
|
+
}
|
|
2531
|
+
);
|
|
2532
|
+
}
|
|
2533
|
+
const screen = current.screen;
|
|
2534
|
+
if (screen === "marketplace-add") {
|
|
2535
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2536
|
+
TextPrompt,
|
|
2537
|
+
{
|
|
2538
|
+
title: "Add Marketplace Source",
|
|
2539
|
+
placeholder: "owner/repo or git URL",
|
|
2540
|
+
onSubmit: handleTextSubmit,
|
|
2541
|
+
onCancel: pop,
|
|
2542
|
+
validate: (v) => !v.includes("/") ? "Must be owner/repo or a git URL" : void 0
|
|
2543
|
+
}
|
|
2544
|
+
);
|
|
2545
|
+
}
|
|
2546
|
+
if (screen === "marketplace-action") {
|
|
2547
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2548
|
+
MenuSelect,
|
|
2549
|
+
{
|
|
2550
|
+
title: `Marketplace: ${current.context?.marketplace ?? ""}`,
|
|
2551
|
+
items: [
|
|
2552
|
+
{ label: "Browse plugins", value: "browse" },
|
|
2553
|
+
{ label: "Update", value: "update" },
|
|
2554
|
+
{ label: "Remove", value: "remove" }
|
|
2555
|
+
],
|
|
2556
|
+
onSelect: handleSelect,
|
|
2557
|
+
onBack: pop
|
|
2558
|
+
},
|
|
2559
|
+
stack.length
|
|
2560
|
+
);
|
|
2561
|
+
}
|
|
2562
|
+
if (screen === "marketplace-install-scope") {
|
|
2563
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2564
|
+
MenuSelect,
|
|
2565
|
+
{
|
|
2566
|
+
title: `Install scope for "${current.context?.pluginId ?? ""}"`,
|
|
2567
|
+
items: [
|
|
2568
|
+
{ label: "User scope", value: "user" },
|
|
2569
|
+
{ label: "Project scope", value: "project" }
|
|
2570
|
+
],
|
|
2571
|
+
onSelect: handleSelect,
|
|
2572
|
+
onBack: pop
|
|
2573
|
+
},
|
|
2574
|
+
stack.length
|
|
2575
|
+
);
|
|
2576
|
+
}
|
|
2577
|
+
if (screen === "installed-action") {
|
|
2578
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2579
|
+
MenuSelect,
|
|
2580
|
+
{
|
|
2581
|
+
title: `Plugin: ${current.context?.pluginId ?? ""}`,
|
|
2582
|
+
items: [{ label: "Uninstall", value: "uninstall" }],
|
|
2583
|
+
onSelect: handleSelect,
|
|
2584
|
+
onBack: pop
|
|
2585
|
+
},
|
|
2586
|
+
stack.length
|
|
2587
|
+
);
|
|
2588
|
+
}
|
|
2589
|
+
const titleMap = {
|
|
2590
|
+
main: "Plugin Management",
|
|
2591
|
+
"marketplace-list": "Marketplace",
|
|
2592
|
+
"marketplace-browse": `Browse: ${current.context?.marketplace ?? ""}`,
|
|
2593
|
+
"installed-list": "Installed Plugins"
|
|
2594
|
+
};
|
|
2595
|
+
const staticItemsMap = {
|
|
2596
|
+
main: [
|
|
2597
|
+
{ label: "Marketplace", value: "marketplace" },
|
|
2598
|
+
{ label: "Installed Plugins", value: "installed" }
|
|
2599
|
+
]
|
|
2600
|
+
};
|
|
2601
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2602
|
+
MenuSelect,
|
|
2603
|
+
{
|
|
2604
|
+
title: titleMap[screen] ?? "Plugin Management",
|
|
2605
|
+
items: staticItemsMap[screen] ?? items,
|
|
2606
|
+
onSelect: handleSelect,
|
|
2607
|
+
onBack: pop,
|
|
2608
|
+
loading,
|
|
2609
|
+
error
|
|
2610
|
+
},
|
|
2611
|
+
`${screen}-${stack.length}-${refreshCounter}`
|
|
2612
|
+
);
|
|
2613
|
+
}
|
|
2614
|
+
|
|
2615
|
+
// src/ui/App.tsx
|
|
2616
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
2154
2617
|
var EXIT_DELAY_MS2 = 500;
|
|
2155
2618
|
function mergeHooksIntoConfig(configHooks, pluginHooks) {
|
|
2156
2619
|
const pluginKeys = Object.keys(pluginHooks);
|
|
@@ -2169,7 +2632,7 @@ function mergeHooksIntoConfig(configHooks, pluginHooks) {
|
|
|
2169
2632
|
return merged;
|
|
2170
2633
|
}
|
|
2171
2634
|
function App(props) {
|
|
2172
|
-
const { exit } = (0,
|
|
2635
|
+
const { exit } = (0, import_ink13.useApp)();
|
|
2173
2636
|
const { registry, pluginHooks } = useCommandRegistry(props.cwd ?? process.cwd());
|
|
2174
2637
|
const configWithPluginHooks = {
|
|
2175
2638
|
...props.config,
|
|
@@ -2182,15 +2645,16 @@ function App(props) {
|
|
|
2182
2645
|
{ ...props, config: configWithPluginHooks }
|
|
2183
2646
|
);
|
|
2184
2647
|
const { messages, setMessages, addMessage } = useMessages();
|
|
2185
|
-
const [isThinking, setIsThinking] = (0,
|
|
2648
|
+
const [isThinking, setIsThinking] = (0, import_react16.useState)(false);
|
|
2186
2649
|
const initialCtx = session.getContextState();
|
|
2187
|
-
const [contextState, setContextState] = (0,
|
|
2650
|
+
const [contextState, setContextState] = (0, import_react16.useState)({
|
|
2188
2651
|
percentage: initialCtx.usedPercentage,
|
|
2189
2652
|
usedTokens: initialCtx.usedTokens,
|
|
2190
2653
|
maxTokens: initialCtx.maxTokens
|
|
2191
2654
|
});
|
|
2192
|
-
const pendingModelChangeRef = (0,
|
|
2193
|
-
const [pendingModelId, setPendingModelId] = (0,
|
|
2655
|
+
const pendingModelChangeRef = (0, import_react16.useRef)(null);
|
|
2656
|
+
const [pendingModelId, setPendingModelId] = (0, import_react16.useState)(null);
|
|
2657
|
+
const [showPluginTUI, setShowPluginTUI] = (0, import_react16.useState)(false);
|
|
2194
2658
|
const pluginCallbacks = usePluginCallbacks(props.cwd ?? process.cwd());
|
|
2195
2659
|
const handleSlashCommand = useSlashCommands(
|
|
2196
2660
|
session,
|
|
@@ -2200,7 +2664,8 @@ function App(props) {
|
|
|
2200
2664
|
registry,
|
|
2201
2665
|
pendingModelChangeRef,
|
|
2202
2666
|
setPendingModelId,
|
|
2203
|
-
pluginCallbacks
|
|
2667
|
+
pluginCallbacks,
|
|
2668
|
+
setShowPluginTUI
|
|
2204
2669
|
);
|
|
2205
2670
|
const handleSubmit = useSubmitHandler(
|
|
2206
2671
|
session,
|
|
@@ -2211,33 +2676,33 @@ function App(props) {
|
|
|
2211
2676
|
setContextState,
|
|
2212
2677
|
registry
|
|
2213
2678
|
);
|
|
2214
|
-
(0,
|
|
2679
|
+
(0, import_ink13.useInput)(
|
|
2215
2680
|
(_input, key) => {
|
|
2216
2681
|
if (key.ctrl && _input === "c") exit();
|
|
2217
2682
|
if (key.escape && isThinking) session.abort();
|
|
2218
2683
|
},
|
|
2219
|
-
{ isActive: !permissionRequest }
|
|
2684
|
+
{ isActive: !permissionRequest && !showPluginTUI }
|
|
2220
2685
|
);
|
|
2221
|
-
return /* @__PURE__ */ (0,
|
|
2222
|
-
/* @__PURE__ */ (0,
|
|
2223
|
-
/* @__PURE__ */ (0,
|
|
2686
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_ink13.Box, { flexDirection: "column", children: [
|
|
2687
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_ink13.Box, { flexDirection: "column", paddingX: 1, marginBottom: 1, children: [
|
|
2688
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_ink13.Text, { color: "cyan", bold: true, children: `
|
|
2224
2689
|
____ ___ ____ ___ _____ _
|
|
2225
2690
|
| _ \\ / _ \\| __ ) / _ \\_ _|/ \\
|
|
2226
2691
|
| |_) | | | | _ \\| | | || | / _ \\
|
|
2227
2692
|
| _ <| |_| | |_) | |_| || |/ ___ \\
|
|
2228
2693
|
|_| \\_\\\\___/|____/ \\___/ |_/_/ \\_\\
|
|
2229
2694
|
` }),
|
|
2230
|
-
/* @__PURE__ */ (0,
|
|
2695
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_ink13.Text, { dimColor: true, children: [
|
|
2231
2696
|
" v",
|
|
2232
2697
|
props.version ?? "0.0.0"
|
|
2233
2698
|
] })
|
|
2234
2699
|
] }),
|
|
2235
|
-
/* @__PURE__ */ (0,
|
|
2236
|
-
/* @__PURE__ */ (0,
|
|
2237
|
-
isThinking && /* @__PURE__ */ (0,
|
|
2700
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_ink13.Box, { flexDirection: "column", paddingX: 1, flexGrow: 1, children: [
|
|
2701
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(MessageList, { messages }),
|
|
2702
|
+
isThinking && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_ink13.Box, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(StreamingIndicator, { text: streamingText, activeTools }) })
|
|
2238
2703
|
] }),
|
|
2239
|
-
permissionRequest && /* @__PURE__ */ (0,
|
|
2240
|
-
pendingModelId && /* @__PURE__ */ (0,
|
|
2704
|
+
permissionRequest && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(PermissionPrompt, { request: permissionRequest }),
|
|
2705
|
+
pendingModelId && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
2241
2706
|
ConfirmPrompt,
|
|
2242
2707
|
{
|
|
2243
2708
|
message: `Change model to ${(0, import_agent_core3.getModelName)(pendingModelId)}? This will restart the session.`,
|
|
@@ -2265,7 +2730,15 @@ function App(props) {
|
|
|
2265
2730
|
}
|
|
2266
2731
|
}
|
|
2267
2732
|
),
|
|
2268
|
-
/* @__PURE__ */ (0,
|
|
2733
|
+
showPluginTUI && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
2734
|
+
PluginTUI,
|
|
2735
|
+
{
|
|
2736
|
+
callbacks: pluginCallbacks,
|
|
2737
|
+
onClose: () => setShowPluginTUI(false),
|
|
2738
|
+
addMessage: (msg) => addMessage(msg)
|
|
2739
|
+
}
|
|
2740
|
+
),
|
|
2741
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
2269
2742
|
StatusBar,
|
|
2270
2743
|
{
|
|
2271
2744
|
permissionMode: session.getPermissionMode(),
|
|
@@ -2278,20 +2751,20 @@ function App(props) {
|
|
|
2278
2751
|
contextMaxTokens: contextState.maxTokens
|
|
2279
2752
|
}
|
|
2280
2753
|
),
|
|
2281
|
-
/* @__PURE__ */ (0,
|
|
2754
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
2282
2755
|
InputArea,
|
|
2283
2756
|
{
|
|
2284
2757
|
onSubmit: handleSubmit,
|
|
2285
|
-
isDisabled: isThinking || !!permissionRequest,
|
|
2758
|
+
isDisabled: isThinking || !!permissionRequest || showPluginTUI,
|
|
2286
2759
|
registry
|
|
2287
2760
|
}
|
|
2288
2761
|
),
|
|
2289
|
-
/* @__PURE__ */ (0,
|
|
2762
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_ink13.Text, { children: " " })
|
|
2290
2763
|
] });
|
|
2291
2764
|
}
|
|
2292
2765
|
|
|
2293
2766
|
// src/ui/render.tsx
|
|
2294
|
-
var
|
|
2767
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
2295
2768
|
function renderApp(options) {
|
|
2296
2769
|
process.on("unhandledRejection", (reason) => {
|
|
2297
2770
|
process.stderr.write(`
|
|
@@ -2302,7 +2775,7 @@ function renderApp(options) {
|
|
|
2302
2775
|
`);
|
|
2303
2776
|
}
|
|
2304
2777
|
});
|
|
2305
|
-
const instance = (0,
|
|
2778
|
+
const instance = (0, import_ink14.render)(/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(App, { ...options }), {
|
|
2306
2779
|
exitOnCtrlC: true
|
|
2307
2780
|
});
|
|
2308
2781
|
instance.waitUntilExit().catch((err) => {
|