@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/bin.cjs
CHANGED
|
@@ -163,11 +163,11 @@ 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
|
|
169
|
+
var import_react16 = require("react");
|
|
170
|
+
var import_ink13 = require("ink");
|
|
171
171
|
var import_agent_core3 = require("@robota-sdk/agent-core");
|
|
172
172
|
|
|
173
173
|
// src/ui/hooks/useSession.ts
|
|
@@ -520,18 +520,9 @@ async function handlePluginCommand(args, addMessage, callbacks) {
|
|
|
520
520
|
try {
|
|
521
521
|
switch (subcommand) {
|
|
522
522
|
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 };
|
|
523
|
+
case void 0:
|
|
524
|
+
case "manage": {
|
|
525
|
+
return { handled: true, triggerPluginTUI: true };
|
|
535
526
|
}
|
|
536
527
|
case "install": {
|
|
537
528
|
if (!subArgs) {
|
|
@@ -678,7 +669,7 @@ async function executeSlashCommand(cmd, args, session, addMessage, clearMessages
|
|
|
678
669
|
|
|
679
670
|
// src/ui/hooks/useSlashCommands.ts
|
|
680
671
|
var EXIT_DELAY_MS = 500;
|
|
681
|
-
function useSlashCommands(session, addMessage, setMessages, exit, registry, pendingModelChangeRef, setPendingModelId, pluginCallbacks) {
|
|
672
|
+
function useSlashCommands(session, addMessage, setMessages, exit, registry, pendingModelChangeRef, setPendingModelId, pluginCallbacks, setShowPluginTUI) {
|
|
682
673
|
return (0, import_react3.useCallback)(
|
|
683
674
|
async (input) => {
|
|
684
675
|
const parts = input.slice(1).split(/\s+/);
|
|
@@ -698,6 +689,9 @@ function useSlashCommands(session, addMessage, setMessages, exit, registry, pend
|
|
|
698
689
|
pendingModelChangeRef.current = result.pendingModelId;
|
|
699
690
|
setPendingModelId(result.pendingModelId);
|
|
700
691
|
}
|
|
692
|
+
if (result.triggerPluginTUI) {
|
|
693
|
+
setShowPluginTUI?.(true);
|
|
694
|
+
}
|
|
701
695
|
if (result.exitRequested) {
|
|
702
696
|
setTimeout(() => exit(), EXIT_DELAY_MS);
|
|
703
697
|
}
|
|
@@ -711,7 +705,8 @@ function useSlashCommands(session, addMessage, setMessages, exit, registry, pend
|
|
|
711
705
|
registry,
|
|
712
706
|
pendingModelChangeRef,
|
|
713
707
|
setPendingModelId,
|
|
714
|
-
pluginCallbacks
|
|
708
|
+
pluginCallbacks,
|
|
709
|
+
setShowPluginTUI
|
|
715
710
|
]
|
|
716
711
|
);
|
|
717
712
|
}
|
|
@@ -1095,22 +1090,7 @@ function createBuiltinCommands() {
|
|
|
1095
1090
|
{ name: "cost", description: "Show session info", source: "builtin" },
|
|
1096
1091
|
{ name: "context", description: "Context window info", source: "builtin" },
|
|
1097
1092
|
{ 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
|
-
},
|
|
1093
|
+
{ name: "plugin", description: "Manage plugins", source: "builtin" },
|
|
1114
1094
|
{ name: "reload-plugins", description: "Reload all plugin resources", source: "builtin" },
|
|
1115
1095
|
{ name: "reset", description: "Delete settings and exit", source: "builtin" },
|
|
1116
1096
|
{ name: "exit", description: "Exit CLI", source: "builtin" }
|
|
@@ -1377,18 +1357,50 @@ function usePluginCallbacks(cwd) {
|
|
|
1377
1357
|
return {
|
|
1378
1358
|
listInstalled: async () => {
|
|
1379
1359
|
const plugins = await loader.loadAll();
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1360
|
+
const enabledMap = settingsStore.getEnabledPlugins();
|
|
1361
|
+
return plugins.map((p) => {
|
|
1362
|
+
const parts = p.pluginDir.split("/");
|
|
1363
|
+
const cacheIdx = parts.indexOf("cache");
|
|
1364
|
+
const marketplaceName = cacheIdx >= 0 ? parts[cacheIdx + 1] : "";
|
|
1365
|
+
const fullId = marketplaceName ? `${p.manifest.name}@${marketplaceName}` : p.manifest.name;
|
|
1366
|
+
return {
|
|
1367
|
+
name: fullId,
|
|
1368
|
+
description: p.manifest.description,
|
|
1369
|
+
enabled: enabledMap[fullId] !== false && enabledMap[p.manifest.name] !== false
|
|
1370
|
+
};
|
|
1371
|
+
});
|
|
1372
|
+
},
|
|
1373
|
+
listAvailablePlugins: async (marketplaceName) => {
|
|
1374
|
+
let manifest;
|
|
1375
|
+
try {
|
|
1376
|
+
manifest = marketplace.fetchManifest(marketplaceName);
|
|
1377
|
+
} catch {
|
|
1378
|
+
return [];
|
|
1379
|
+
}
|
|
1380
|
+
const installed = installer.getInstalledPlugins();
|
|
1381
|
+
const installedNames = new Set(Object.values(installed).map((r) => r.pluginName));
|
|
1382
|
+
return manifest.plugins.map((p) => ({
|
|
1383
|
+
name: p.name,
|
|
1384
|
+
description: p.description,
|
|
1385
|
+
installed: installedNames.has(p.name)
|
|
1384
1386
|
}));
|
|
1385
1387
|
},
|
|
1386
|
-
install: async (pluginId) => {
|
|
1388
|
+
install: async (pluginId, scope) => {
|
|
1387
1389
|
const [name, marketplaceName] = pluginId.split("@");
|
|
1388
1390
|
if (!name || !marketplaceName) {
|
|
1389
1391
|
throw new Error("Plugin ID must be in format: name@marketplace");
|
|
1390
1392
|
}
|
|
1391
|
-
|
|
1393
|
+
if (scope === "project") {
|
|
1394
|
+
const projectPluginsDir = (0, import_node_path4.join)(cwd, ".robota", "plugins");
|
|
1395
|
+
const projectInstaller = new import_agent_sdk4.BundlePluginInstaller({
|
|
1396
|
+
pluginsDir: projectPluginsDir,
|
|
1397
|
+
settingsStore,
|
|
1398
|
+
marketplaceClient: marketplace
|
|
1399
|
+
});
|
|
1400
|
+
await projectInstaller.install(name, marketplaceName);
|
|
1401
|
+
} else {
|
|
1402
|
+
await installer.install(name, marketplaceName);
|
|
1403
|
+
}
|
|
1392
1404
|
},
|
|
1393
1405
|
uninstall: async (pluginId) => {
|
|
1394
1406
|
await installer.uninstall(pluginId);
|
|
@@ -2133,8 +2145,459 @@ function StreamingIndicator({ text, activeTools }) {
|
|
|
2133
2145
|
] });
|
|
2134
2146
|
}
|
|
2135
2147
|
|
|
2136
|
-
// src/ui/
|
|
2148
|
+
// src/ui/PluginTUI.tsx
|
|
2149
|
+
var import_react15 = require("react");
|
|
2150
|
+
|
|
2151
|
+
// src/ui/MenuSelect.tsx
|
|
2152
|
+
var import_react13 = require("react");
|
|
2153
|
+
var import_ink11 = require("ink");
|
|
2137
2154
|
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
2155
|
+
function MenuSelect({
|
|
2156
|
+
title,
|
|
2157
|
+
items,
|
|
2158
|
+
onSelect,
|
|
2159
|
+
onBack,
|
|
2160
|
+
loading,
|
|
2161
|
+
error
|
|
2162
|
+
}) {
|
|
2163
|
+
const [selected, setSelected] = (0, import_react13.useState)(0);
|
|
2164
|
+
const selectedRef = (0, import_react13.useRef)(0);
|
|
2165
|
+
const resolvedRef = (0, import_react13.useRef)(false);
|
|
2166
|
+
const doSelect = (0, import_react13.useCallback)(
|
|
2167
|
+
(index) => {
|
|
2168
|
+
if (resolvedRef.current || items.length === 0) return;
|
|
2169
|
+
resolvedRef.current = true;
|
|
2170
|
+
onSelect(items[index].value);
|
|
2171
|
+
},
|
|
2172
|
+
[items, onSelect]
|
|
2173
|
+
);
|
|
2174
|
+
(0, import_ink11.useInput)((input, key) => {
|
|
2175
|
+
if (resolvedRef.current) return;
|
|
2176
|
+
if (key.escape) {
|
|
2177
|
+
resolvedRef.current = true;
|
|
2178
|
+
onBack();
|
|
2179
|
+
return;
|
|
2180
|
+
}
|
|
2181
|
+
if (loading || error || items.length === 0) return;
|
|
2182
|
+
if (key.upArrow) {
|
|
2183
|
+
const next = selectedRef.current > 0 ? selectedRef.current - 1 : selectedRef.current;
|
|
2184
|
+
selectedRef.current = next;
|
|
2185
|
+
setSelected(next);
|
|
2186
|
+
} else if (key.downArrow) {
|
|
2187
|
+
const next = selectedRef.current < items.length - 1 ? selectedRef.current + 1 : selectedRef.current;
|
|
2188
|
+
selectedRef.current = next;
|
|
2189
|
+
setSelected(next);
|
|
2190
|
+
} else if (key.return) {
|
|
2191
|
+
doSelect(selectedRef.current);
|
|
2192
|
+
}
|
|
2193
|
+
});
|
|
2194
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_ink11.Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
|
|
2195
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_ink11.Text, { color: "yellow", bold: true, children: title }),
|
|
2196
|
+
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..." }) }),
|
|
2197
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_ink11.Box, { marginTop: 1, flexDirection: "column", children: [
|
|
2198
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_ink11.Text, { color: "red", children: error }),
|
|
2199
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_ink11.Text, { dimColor: true, children: "Press Esc to go back" })
|
|
2200
|
+
] }),
|
|
2201
|
+
!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: [
|
|
2202
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_ink11.Text, { color: i === selected ? "cyan" : void 0, bold: i === selected, children: [
|
|
2203
|
+
i === selected ? "> " : " ",
|
|
2204
|
+
item.label
|
|
2205
|
+
] }),
|
|
2206
|
+
item.hint && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_ink11.Text, { dimColor: true, children: [
|
|
2207
|
+
" ",
|
|
2208
|
+
item.hint
|
|
2209
|
+
] })
|
|
2210
|
+
] }, item.value)) }),
|
|
2211
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_ink11.Text, { dimColor: true, children: loading || error ? "" : " \u2191\u2193 Navigate Enter Select Esc Back" })
|
|
2212
|
+
] });
|
|
2213
|
+
}
|
|
2214
|
+
|
|
2215
|
+
// src/ui/TextPrompt.tsx
|
|
2216
|
+
var import_react14 = require("react");
|
|
2217
|
+
var import_ink12 = require("ink");
|
|
2218
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
2219
|
+
function TextPrompt({
|
|
2220
|
+
title,
|
|
2221
|
+
placeholder,
|
|
2222
|
+
onSubmit,
|
|
2223
|
+
onCancel,
|
|
2224
|
+
validate
|
|
2225
|
+
}) {
|
|
2226
|
+
const [value, setValue] = (0, import_react14.useState)("");
|
|
2227
|
+
const [error, setError] = (0, import_react14.useState)();
|
|
2228
|
+
const resolvedRef = (0, import_react14.useRef)(false);
|
|
2229
|
+
const valueRef = (0, import_react14.useRef)("");
|
|
2230
|
+
const handleSubmit = (0, import_react14.useCallback)(() => {
|
|
2231
|
+
if (resolvedRef.current) return;
|
|
2232
|
+
const trimmed = valueRef.current.trim();
|
|
2233
|
+
if (!trimmed) return;
|
|
2234
|
+
if (validate) {
|
|
2235
|
+
const err = validate(trimmed);
|
|
2236
|
+
if (err) {
|
|
2237
|
+
setError(err);
|
|
2238
|
+
return;
|
|
2239
|
+
}
|
|
2240
|
+
}
|
|
2241
|
+
resolvedRef.current = true;
|
|
2242
|
+
onSubmit(trimmed);
|
|
2243
|
+
}, [validate, onSubmit]);
|
|
2244
|
+
(0, import_ink12.useInput)((input, key) => {
|
|
2245
|
+
if (resolvedRef.current) return;
|
|
2246
|
+
if (key.escape) {
|
|
2247
|
+
resolvedRef.current = true;
|
|
2248
|
+
onCancel();
|
|
2249
|
+
return;
|
|
2250
|
+
}
|
|
2251
|
+
if (key.return) {
|
|
2252
|
+
handleSubmit();
|
|
2253
|
+
return;
|
|
2254
|
+
}
|
|
2255
|
+
if (key.backspace || key.delete) {
|
|
2256
|
+
valueRef.current = valueRef.current.slice(0, -1);
|
|
2257
|
+
setValue(valueRef.current);
|
|
2258
|
+
setError(void 0);
|
|
2259
|
+
return;
|
|
2260
|
+
}
|
|
2261
|
+
if (input && !key.ctrl && !key.meta) {
|
|
2262
|
+
valueRef.current = valueRef.current + input;
|
|
2263
|
+
setValue(valueRef.current);
|
|
2264
|
+
setError(void 0);
|
|
2265
|
+
}
|
|
2266
|
+
});
|
|
2267
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_ink12.Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
|
|
2268
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_ink12.Text, { color: "yellow", bold: true, children: title }),
|
|
2269
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_ink12.Box, { marginTop: 1, children: [
|
|
2270
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_ink12.Text, { color: "cyan", children: "> " }),
|
|
2271
|
+
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,
|
|
2272
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_ink12.Text, { color: "cyan", children: "\u2588" })
|
|
2273
|
+
] }),
|
|
2274
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_ink12.Text, { color: "red", children: error }),
|
|
2275
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_ink12.Text, { dimColor: true, children: " Enter Submit Esc Cancel" })
|
|
2276
|
+
] });
|
|
2277
|
+
}
|
|
2278
|
+
|
|
2279
|
+
// src/ui/plugin-tui-handlers.ts
|
|
2280
|
+
function handleMainSelect(value, nav) {
|
|
2281
|
+
if (value === "marketplace") {
|
|
2282
|
+
nav.push({ screen: "marketplace-list" });
|
|
2283
|
+
} else if (value === "installed") {
|
|
2284
|
+
nav.push({ screen: "installed-list" });
|
|
2285
|
+
}
|
|
2286
|
+
}
|
|
2287
|
+
function handleMarketplaceListSelect(value, nav) {
|
|
2288
|
+
if (value === "__add__") {
|
|
2289
|
+
nav.push({ screen: "marketplace-add" });
|
|
2290
|
+
} else {
|
|
2291
|
+
nav.push({ screen: "marketplace-action", context: { marketplace: value } });
|
|
2292
|
+
}
|
|
2293
|
+
}
|
|
2294
|
+
function handleMarketplaceActionSelect(value, marketplace, callbacks, nav) {
|
|
2295
|
+
if (value === "browse") {
|
|
2296
|
+
nav.push({ screen: "marketplace-browse", context: { marketplace } });
|
|
2297
|
+
} else if (value === "update") {
|
|
2298
|
+
callbacks.marketplaceUpdate(marketplace).then(() => {
|
|
2299
|
+
nav.notify(`Updated marketplace "${marketplace}".`);
|
|
2300
|
+
nav.pop();
|
|
2301
|
+
}).catch((err) => {
|
|
2302
|
+
nav.notify(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
2303
|
+
});
|
|
2304
|
+
} else if (value === "remove") {
|
|
2305
|
+
nav.setConfirm({
|
|
2306
|
+
message: `Remove marketplace "${marketplace}" and all its plugins?`,
|
|
2307
|
+
onConfirm: () => {
|
|
2308
|
+
nav.setConfirm(void 0);
|
|
2309
|
+
callbacks.marketplaceRemove(marketplace).then(() => {
|
|
2310
|
+
nav.notify(`Removed marketplace "${marketplace}".`);
|
|
2311
|
+
nav.popN(2);
|
|
2312
|
+
}).catch((err) => {
|
|
2313
|
+
nav.notify(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
2314
|
+
});
|
|
2315
|
+
},
|
|
2316
|
+
onCancel: () => nav.setConfirm(void 0)
|
|
2317
|
+
});
|
|
2318
|
+
}
|
|
2319
|
+
}
|
|
2320
|
+
function handleMarketplaceBrowseSelect(value, marketplace, items, nav) {
|
|
2321
|
+
const fullId = `${value}@${marketplace}`;
|
|
2322
|
+
const item = items.find((i) => i.value === value);
|
|
2323
|
+
if (item?.hint === "installed") {
|
|
2324
|
+
nav.push({ screen: "installed-action", context: { pluginId: fullId } });
|
|
2325
|
+
} else {
|
|
2326
|
+
nav.push({ screen: "marketplace-install-scope", context: { marketplace, pluginId: fullId } });
|
|
2327
|
+
}
|
|
2328
|
+
}
|
|
2329
|
+
function handleInstallScopeSelect(value, pluginId, callbacks, nav) {
|
|
2330
|
+
const scope = value;
|
|
2331
|
+
callbacks.install(pluginId, scope).then(() => {
|
|
2332
|
+
nav.notify(`Installed plugin "${pluginId}" (${scope} scope).`);
|
|
2333
|
+
nav.popN(2);
|
|
2334
|
+
}).catch((err) => {
|
|
2335
|
+
nav.notify(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
2336
|
+
});
|
|
2337
|
+
}
|
|
2338
|
+
function handleInstalledListSelect(value, callbacks, nav) {
|
|
2339
|
+
nav.setConfirm({
|
|
2340
|
+
message: `Uninstall plugin "${value}"?`,
|
|
2341
|
+
onConfirm: () => {
|
|
2342
|
+
nav.setConfirm(void 0);
|
|
2343
|
+
callbacks.uninstall(value).then(() => {
|
|
2344
|
+
nav.notify(`Uninstalled plugin "${value}".`);
|
|
2345
|
+
nav.refresh();
|
|
2346
|
+
}).catch((err) => {
|
|
2347
|
+
nav.notify(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
2348
|
+
});
|
|
2349
|
+
},
|
|
2350
|
+
onCancel: () => nav.setConfirm(void 0)
|
|
2351
|
+
});
|
|
2352
|
+
}
|
|
2353
|
+
function handleInstalledActionSelect(value, pluginId, callbacks, nav) {
|
|
2354
|
+
if (value === "uninstall") {
|
|
2355
|
+
nav.setConfirm({
|
|
2356
|
+
message: `Uninstall plugin "${pluginId}"?`,
|
|
2357
|
+
onConfirm: () => {
|
|
2358
|
+
nav.setConfirm(void 0);
|
|
2359
|
+
callbacks.uninstall(pluginId).then(() => {
|
|
2360
|
+
nav.notify(`Uninstalled plugin "${pluginId}".`);
|
|
2361
|
+
nav.popN(2);
|
|
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
|
+
}
|
|
2370
|
+
|
|
2371
|
+
// src/ui/PluginTUI.tsx
|
|
2372
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
2373
|
+
function PluginTUI({ callbacks, onClose, addMessage }) {
|
|
2374
|
+
const [stack, setStack] = (0, import_react15.useState)([{ screen: "main" }]);
|
|
2375
|
+
const [items, setItems] = (0, import_react15.useState)([]);
|
|
2376
|
+
const [loading, setLoading] = (0, import_react15.useState)(false);
|
|
2377
|
+
const [error, setError] = (0, import_react15.useState)();
|
|
2378
|
+
const [confirm, setConfirm] = (0, import_react15.useState)();
|
|
2379
|
+
const [refreshCounter, setRefreshCounter] = (0, import_react15.useState)(0);
|
|
2380
|
+
const current = stack[stack.length - 1] ?? { screen: "main" };
|
|
2381
|
+
const push = (0, import_react15.useCallback)((state) => {
|
|
2382
|
+
setStack((prev) => [...prev, state]);
|
|
2383
|
+
setItems([]);
|
|
2384
|
+
setError(void 0);
|
|
2385
|
+
}, []);
|
|
2386
|
+
const pop = (0, import_react15.useCallback)(() => {
|
|
2387
|
+
setStack((prev) => {
|
|
2388
|
+
if (prev.length <= 1) {
|
|
2389
|
+
onClose();
|
|
2390
|
+
return prev;
|
|
2391
|
+
}
|
|
2392
|
+
return prev.slice(0, -1);
|
|
2393
|
+
});
|
|
2394
|
+
setItems([]);
|
|
2395
|
+
setError(void 0);
|
|
2396
|
+
}, [onClose]);
|
|
2397
|
+
const popN = (0, import_react15.useCallback)(
|
|
2398
|
+
(n) => {
|
|
2399
|
+
setStack((prev) => {
|
|
2400
|
+
const next = prev.slice(0, Math.max(1, prev.length - n));
|
|
2401
|
+
if (next.length === 0) {
|
|
2402
|
+
onClose();
|
|
2403
|
+
return prev;
|
|
2404
|
+
}
|
|
2405
|
+
return next;
|
|
2406
|
+
});
|
|
2407
|
+
setItems([]);
|
|
2408
|
+
setError(void 0);
|
|
2409
|
+
},
|
|
2410
|
+
[onClose]
|
|
2411
|
+
);
|
|
2412
|
+
const notify = (0, import_react15.useCallback)(
|
|
2413
|
+
(content) => {
|
|
2414
|
+
addMessage?.({ role: "system", content });
|
|
2415
|
+
},
|
|
2416
|
+
[addMessage]
|
|
2417
|
+
);
|
|
2418
|
+
const refresh = (0, import_react15.useCallback)(() => {
|
|
2419
|
+
setItems([]);
|
|
2420
|
+
setRefreshCounter((c) => c + 1);
|
|
2421
|
+
}, []);
|
|
2422
|
+
const nav = { push, pop, popN, notify, setConfirm, refresh };
|
|
2423
|
+
(0, import_react15.useEffect)(() => {
|
|
2424
|
+
const screen2 = current.screen;
|
|
2425
|
+
if (screen2 === "marketplace-list") {
|
|
2426
|
+
setLoading(true);
|
|
2427
|
+
callbacks.marketplaceList().then((sources) => {
|
|
2428
|
+
const baseItems = [{ label: "Add Marketplace", value: "__add__" }];
|
|
2429
|
+
const sourceItems = sources.map((s) => ({
|
|
2430
|
+
label: s.name,
|
|
2431
|
+
value: s.name,
|
|
2432
|
+
hint: s.type
|
|
2433
|
+
}));
|
|
2434
|
+
setItems([...baseItems, ...sourceItems]);
|
|
2435
|
+
setLoading(false);
|
|
2436
|
+
}).catch((err) => {
|
|
2437
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
2438
|
+
setLoading(false);
|
|
2439
|
+
});
|
|
2440
|
+
} else if (screen2 === "marketplace-browse") {
|
|
2441
|
+
const marketplace = current.context?.marketplace ?? "";
|
|
2442
|
+
setLoading(true);
|
|
2443
|
+
callbacks.listAvailablePlugins(marketplace).then((plugins) => {
|
|
2444
|
+
setItems(
|
|
2445
|
+
plugins.map((p) => ({
|
|
2446
|
+
label: p.name,
|
|
2447
|
+
value: p.name,
|
|
2448
|
+
hint: p.installed ? "installed" : p.description
|
|
2449
|
+
}))
|
|
2450
|
+
);
|
|
2451
|
+
setLoading(false);
|
|
2452
|
+
}).catch((err) => {
|
|
2453
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
2454
|
+
setLoading(false);
|
|
2455
|
+
});
|
|
2456
|
+
} else if (screen2 === "installed-list") {
|
|
2457
|
+
setLoading(true);
|
|
2458
|
+
callbacks.listInstalled().then((plugins) => {
|
|
2459
|
+
setItems(
|
|
2460
|
+
plugins.map((p) => ({
|
|
2461
|
+
label: p.name,
|
|
2462
|
+
value: p.name,
|
|
2463
|
+
hint: p.description
|
|
2464
|
+
}))
|
|
2465
|
+
);
|
|
2466
|
+
setLoading(false);
|
|
2467
|
+
}).catch((err) => {
|
|
2468
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
2469
|
+
setLoading(false);
|
|
2470
|
+
});
|
|
2471
|
+
}
|
|
2472
|
+
}, [stack.length, current.screen, current.context?.marketplace, callbacks, refreshCounter]);
|
|
2473
|
+
const handleSelect = (0, import_react15.useCallback)(
|
|
2474
|
+
(value) => {
|
|
2475
|
+
const screen2 = current.screen;
|
|
2476
|
+
const ctx = current.context;
|
|
2477
|
+
if (screen2 === "main") handleMainSelect(value, nav);
|
|
2478
|
+
else if (screen2 === "marketplace-list") handleMarketplaceListSelect(value, nav);
|
|
2479
|
+
else if (screen2 === "marketplace-action")
|
|
2480
|
+
handleMarketplaceActionSelect(value, ctx?.marketplace ?? "", callbacks, nav);
|
|
2481
|
+
else if (screen2 === "marketplace-browse")
|
|
2482
|
+
handleMarketplaceBrowseSelect(value, ctx?.marketplace ?? "", items, nav);
|
|
2483
|
+
else if (screen2 === "marketplace-install-scope")
|
|
2484
|
+
handleInstallScopeSelect(value, ctx?.pluginId ?? "", callbacks, nav);
|
|
2485
|
+
else if (screen2 === "installed-list") handleInstalledListSelect(value, callbacks, nav);
|
|
2486
|
+
else if (screen2 === "installed-action")
|
|
2487
|
+
handleInstalledActionSelect(value, ctx?.pluginId ?? "", callbacks, nav);
|
|
2488
|
+
},
|
|
2489
|
+
[current, items, callbacks, push, pop, popN, notify, setConfirm, refresh]
|
|
2490
|
+
);
|
|
2491
|
+
const handleTextSubmit = (0, import_react15.useCallback)(
|
|
2492
|
+
(value) => {
|
|
2493
|
+
if (current.screen === "marketplace-add") {
|
|
2494
|
+
callbacks.marketplaceAdd(value).then((name) => {
|
|
2495
|
+
notify(`Added marketplace "${name}" from ${value}.`);
|
|
2496
|
+
pop();
|
|
2497
|
+
}).catch((err) => {
|
|
2498
|
+
notify(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
2499
|
+
pop();
|
|
2500
|
+
});
|
|
2501
|
+
}
|
|
2502
|
+
},
|
|
2503
|
+
[current.screen, callbacks, notify, pop]
|
|
2504
|
+
);
|
|
2505
|
+
if (confirm) {
|
|
2506
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2507
|
+
ConfirmPrompt,
|
|
2508
|
+
{
|
|
2509
|
+
message: confirm.message,
|
|
2510
|
+
onSelect: (index) => {
|
|
2511
|
+
if (index === 0) confirm.onConfirm();
|
|
2512
|
+
else confirm.onCancel();
|
|
2513
|
+
}
|
|
2514
|
+
}
|
|
2515
|
+
);
|
|
2516
|
+
}
|
|
2517
|
+
const screen = current.screen;
|
|
2518
|
+
if (screen === "marketplace-add") {
|
|
2519
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2520
|
+
TextPrompt,
|
|
2521
|
+
{
|
|
2522
|
+
title: "Add Marketplace Source",
|
|
2523
|
+
placeholder: "owner/repo or git URL",
|
|
2524
|
+
onSubmit: handleTextSubmit,
|
|
2525
|
+
onCancel: pop,
|
|
2526
|
+
validate: (v) => !v.includes("/") ? "Must be owner/repo or a git URL" : void 0
|
|
2527
|
+
}
|
|
2528
|
+
);
|
|
2529
|
+
}
|
|
2530
|
+
if (screen === "marketplace-action") {
|
|
2531
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2532
|
+
MenuSelect,
|
|
2533
|
+
{
|
|
2534
|
+
title: `Marketplace: ${current.context?.marketplace ?? ""}`,
|
|
2535
|
+
items: [
|
|
2536
|
+
{ label: "Browse plugins", value: "browse" },
|
|
2537
|
+
{ label: "Update", value: "update" },
|
|
2538
|
+
{ label: "Remove", value: "remove" }
|
|
2539
|
+
],
|
|
2540
|
+
onSelect: handleSelect,
|
|
2541
|
+
onBack: pop
|
|
2542
|
+
},
|
|
2543
|
+
stack.length
|
|
2544
|
+
);
|
|
2545
|
+
}
|
|
2546
|
+
if (screen === "marketplace-install-scope") {
|
|
2547
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2548
|
+
MenuSelect,
|
|
2549
|
+
{
|
|
2550
|
+
title: `Install scope for "${current.context?.pluginId ?? ""}"`,
|
|
2551
|
+
items: [
|
|
2552
|
+
{ label: "User scope", value: "user" },
|
|
2553
|
+
{ label: "Project scope", value: "project" }
|
|
2554
|
+
],
|
|
2555
|
+
onSelect: handleSelect,
|
|
2556
|
+
onBack: pop
|
|
2557
|
+
},
|
|
2558
|
+
stack.length
|
|
2559
|
+
);
|
|
2560
|
+
}
|
|
2561
|
+
if (screen === "installed-action") {
|
|
2562
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2563
|
+
MenuSelect,
|
|
2564
|
+
{
|
|
2565
|
+
title: `Plugin: ${current.context?.pluginId ?? ""}`,
|
|
2566
|
+
items: [{ label: "Uninstall", value: "uninstall" }],
|
|
2567
|
+
onSelect: handleSelect,
|
|
2568
|
+
onBack: pop
|
|
2569
|
+
},
|
|
2570
|
+
stack.length
|
|
2571
|
+
);
|
|
2572
|
+
}
|
|
2573
|
+
const titleMap = {
|
|
2574
|
+
main: "Plugin Management",
|
|
2575
|
+
"marketplace-list": "Marketplace",
|
|
2576
|
+
"marketplace-browse": `Browse: ${current.context?.marketplace ?? ""}`,
|
|
2577
|
+
"installed-list": "Installed Plugins"
|
|
2578
|
+
};
|
|
2579
|
+
const staticItemsMap = {
|
|
2580
|
+
main: [
|
|
2581
|
+
{ label: "Marketplace", value: "marketplace" },
|
|
2582
|
+
{ label: "Installed Plugins", value: "installed" }
|
|
2583
|
+
]
|
|
2584
|
+
};
|
|
2585
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2586
|
+
MenuSelect,
|
|
2587
|
+
{
|
|
2588
|
+
title: titleMap[screen] ?? "Plugin Management",
|
|
2589
|
+
items: staticItemsMap[screen] ?? items,
|
|
2590
|
+
onSelect: handleSelect,
|
|
2591
|
+
onBack: pop,
|
|
2592
|
+
loading,
|
|
2593
|
+
error
|
|
2594
|
+
},
|
|
2595
|
+
`${screen}-${stack.length}-${refreshCounter}`
|
|
2596
|
+
);
|
|
2597
|
+
}
|
|
2598
|
+
|
|
2599
|
+
// src/ui/App.tsx
|
|
2600
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
2138
2601
|
var EXIT_DELAY_MS2 = 500;
|
|
2139
2602
|
function mergeHooksIntoConfig(configHooks, pluginHooks) {
|
|
2140
2603
|
const pluginKeys = Object.keys(pluginHooks);
|
|
@@ -2153,7 +2616,7 @@ function mergeHooksIntoConfig(configHooks, pluginHooks) {
|
|
|
2153
2616
|
return merged;
|
|
2154
2617
|
}
|
|
2155
2618
|
function App(props) {
|
|
2156
|
-
const { exit } = (0,
|
|
2619
|
+
const { exit } = (0, import_ink13.useApp)();
|
|
2157
2620
|
const { registry, pluginHooks } = useCommandRegistry(props.cwd ?? process.cwd());
|
|
2158
2621
|
const configWithPluginHooks = {
|
|
2159
2622
|
...props.config,
|
|
@@ -2166,15 +2629,16 @@ function App(props) {
|
|
|
2166
2629
|
{ ...props, config: configWithPluginHooks }
|
|
2167
2630
|
);
|
|
2168
2631
|
const { messages, setMessages, addMessage } = useMessages();
|
|
2169
|
-
const [isThinking, setIsThinking] = (0,
|
|
2632
|
+
const [isThinking, setIsThinking] = (0, import_react16.useState)(false);
|
|
2170
2633
|
const initialCtx = session.getContextState();
|
|
2171
|
-
const [contextState, setContextState] = (0,
|
|
2634
|
+
const [contextState, setContextState] = (0, import_react16.useState)({
|
|
2172
2635
|
percentage: initialCtx.usedPercentage,
|
|
2173
2636
|
usedTokens: initialCtx.usedTokens,
|
|
2174
2637
|
maxTokens: initialCtx.maxTokens
|
|
2175
2638
|
});
|
|
2176
|
-
const pendingModelChangeRef = (0,
|
|
2177
|
-
const [pendingModelId, setPendingModelId] = (0,
|
|
2639
|
+
const pendingModelChangeRef = (0, import_react16.useRef)(null);
|
|
2640
|
+
const [pendingModelId, setPendingModelId] = (0, import_react16.useState)(null);
|
|
2641
|
+
const [showPluginTUI, setShowPluginTUI] = (0, import_react16.useState)(false);
|
|
2178
2642
|
const pluginCallbacks = usePluginCallbacks(props.cwd ?? process.cwd());
|
|
2179
2643
|
const handleSlashCommand = useSlashCommands(
|
|
2180
2644
|
session,
|
|
@@ -2184,7 +2648,8 @@ function App(props) {
|
|
|
2184
2648
|
registry,
|
|
2185
2649
|
pendingModelChangeRef,
|
|
2186
2650
|
setPendingModelId,
|
|
2187
|
-
pluginCallbacks
|
|
2651
|
+
pluginCallbacks,
|
|
2652
|
+
setShowPluginTUI
|
|
2188
2653
|
);
|
|
2189
2654
|
const handleSubmit = useSubmitHandler(
|
|
2190
2655
|
session,
|
|
@@ -2195,33 +2660,33 @@ function App(props) {
|
|
|
2195
2660
|
setContextState,
|
|
2196
2661
|
registry
|
|
2197
2662
|
);
|
|
2198
|
-
(0,
|
|
2663
|
+
(0, import_ink13.useInput)(
|
|
2199
2664
|
(_input, key) => {
|
|
2200
2665
|
if (key.ctrl && _input === "c") exit();
|
|
2201
2666
|
if (key.escape && isThinking) session.abort();
|
|
2202
2667
|
},
|
|
2203
|
-
{ isActive: !permissionRequest }
|
|
2668
|
+
{ isActive: !permissionRequest && !showPluginTUI }
|
|
2204
2669
|
);
|
|
2205
|
-
return /* @__PURE__ */ (0,
|
|
2206
|
-
/* @__PURE__ */ (0,
|
|
2207
|
-
/* @__PURE__ */ (0,
|
|
2670
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_ink13.Box, { flexDirection: "column", children: [
|
|
2671
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_ink13.Box, { flexDirection: "column", paddingX: 1, marginBottom: 1, children: [
|
|
2672
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_ink13.Text, { color: "cyan", bold: true, children: `
|
|
2208
2673
|
____ ___ ____ ___ _____ _
|
|
2209
2674
|
| _ \\ / _ \\| __ ) / _ \\_ _|/ \\
|
|
2210
2675
|
| |_) | | | | _ \\| | | || | / _ \\
|
|
2211
2676
|
| _ <| |_| | |_) | |_| || |/ ___ \\
|
|
2212
2677
|
|_| \\_\\\\___/|____/ \\___/ |_/_/ \\_\\
|
|
2213
2678
|
` }),
|
|
2214
|
-
/* @__PURE__ */ (0,
|
|
2679
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_ink13.Text, { dimColor: true, children: [
|
|
2215
2680
|
" v",
|
|
2216
2681
|
props.version ?? "0.0.0"
|
|
2217
2682
|
] })
|
|
2218
2683
|
] }),
|
|
2219
|
-
/* @__PURE__ */ (0,
|
|
2220
|
-
/* @__PURE__ */ (0,
|
|
2221
|
-
isThinking && /* @__PURE__ */ (0,
|
|
2684
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_ink13.Box, { flexDirection: "column", paddingX: 1, flexGrow: 1, children: [
|
|
2685
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(MessageList, { messages }),
|
|
2686
|
+
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
2687
|
] }),
|
|
2223
|
-
permissionRequest && /* @__PURE__ */ (0,
|
|
2224
|
-
pendingModelId && /* @__PURE__ */ (0,
|
|
2688
|
+
permissionRequest && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(PermissionPrompt, { request: permissionRequest }),
|
|
2689
|
+
pendingModelId && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
2225
2690
|
ConfirmPrompt,
|
|
2226
2691
|
{
|
|
2227
2692
|
message: `Change model to ${(0, import_agent_core3.getModelName)(pendingModelId)}? This will restart the session.`,
|
|
@@ -2249,7 +2714,15 @@ function App(props) {
|
|
|
2249
2714
|
}
|
|
2250
2715
|
}
|
|
2251
2716
|
),
|
|
2252
|
-
/* @__PURE__ */ (0,
|
|
2717
|
+
showPluginTUI && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
2718
|
+
PluginTUI,
|
|
2719
|
+
{
|
|
2720
|
+
callbacks: pluginCallbacks,
|
|
2721
|
+
onClose: () => setShowPluginTUI(false),
|
|
2722
|
+
addMessage: (msg) => addMessage(msg)
|
|
2723
|
+
}
|
|
2724
|
+
),
|
|
2725
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
2253
2726
|
StatusBar,
|
|
2254
2727
|
{
|
|
2255
2728
|
permissionMode: session.getPermissionMode(),
|
|
@@ -2262,20 +2735,20 @@ function App(props) {
|
|
|
2262
2735
|
contextMaxTokens: contextState.maxTokens
|
|
2263
2736
|
}
|
|
2264
2737
|
),
|
|
2265
|
-
/* @__PURE__ */ (0,
|
|
2738
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
2266
2739
|
InputArea,
|
|
2267
2740
|
{
|
|
2268
2741
|
onSubmit: handleSubmit,
|
|
2269
|
-
isDisabled: isThinking || !!permissionRequest,
|
|
2742
|
+
isDisabled: isThinking || !!permissionRequest || showPluginTUI,
|
|
2270
2743
|
registry
|
|
2271
2744
|
}
|
|
2272
2745
|
),
|
|
2273
|
-
/* @__PURE__ */ (0,
|
|
2746
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_ink13.Text, { children: " " })
|
|
2274
2747
|
] });
|
|
2275
2748
|
}
|
|
2276
2749
|
|
|
2277
2750
|
// src/ui/render.tsx
|
|
2278
|
-
var
|
|
2751
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
2279
2752
|
function renderApp(options) {
|
|
2280
2753
|
process.on("unhandledRejection", (reason) => {
|
|
2281
2754
|
process.stderr.write(`
|
|
@@ -2286,7 +2759,7 @@ function renderApp(options) {
|
|
|
2286
2759
|
`);
|
|
2287
2760
|
}
|
|
2288
2761
|
});
|
|
2289
|
-
const instance = (0,
|
|
2762
|
+
const instance = (0, import_ink14.render)(/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(App, { ...options }), {
|
|
2290
2763
|
exitOnCtrlC: true
|
|
2291
2764
|
});
|
|
2292
2765
|
instance.waitUntilExit().catch((err) => {
|