@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.
@@ -149,9 +149,10 @@ var PrintTerminal = class {
149
149
  import { render } from "ink";
150
150
 
151
151
  // src/ui/App.tsx
152
- import { useState as useState7, useRef as useRef6 } from "react";
153
- import { Box as Box9, Text as Text11, useApp, useInput as useInput5 } from "ink";
152
+ import { useState as useState10, useRef as useRef8 } from "react";
153
+ import { Box as Box11, Text as Text13, useApp, useInput as useInput7 } from "ink";
154
154
  import { getModelName } from "@robota-sdk/agent-core";
155
+ import { createSystemMessage as createSystemMessage3 } from "@robota-sdk/agent-core";
155
156
 
156
157
  // src/ui/hooks/useSession.ts
157
158
  import { useState, useCallback, useRef } from "react";
@@ -247,6 +248,7 @@ var NOOP_TERMINAL = {
247
248
  function useSession(props) {
248
249
  const [permissionRequest, setPermissionRequest] = useState(null);
249
250
  const [streamingText, setStreamingText] = useState("");
251
+ const streamingTextRef = useRef("");
250
252
  const [activeTools, setActiveTools] = useState([]);
251
253
  const permissionQueueRef = useRef([]);
252
254
  const processingRef = useRef(false);
@@ -278,8 +280,15 @@ function useSession(props) {
278
280
  processNextPermission();
279
281
  });
280
282
  };
283
+ let flushTimer = null;
281
284
  const onTextDelta = (delta) => {
282
- setStreamingText((prev) => prev + delta);
285
+ streamingTextRef.current += delta;
286
+ if (!flushTimer) {
287
+ flushTimer = setTimeout(() => {
288
+ setStreamingText(streamingTextRef.current);
289
+ flushTimer = null;
290
+ }, 16);
291
+ }
283
292
  };
284
293
  const onToolExecution = (event) => {
285
294
  if (event.type === "start") {
@@ -358,6 +367,7 @@ function useSession(props) {
358
367
  }
359
368
  const clearStreamingText = useCallback(() => {
360
369
  setStreamingText("");
370
+ streamingTextRef.current = "";
361
371
  setActiveTools([]);
362
372
  }, []);
363
373
  return {
@@ -372,16 +382,11 @@ function useSession(props) {
372
382
  // src/ui/hooks/useMessages.ts
373
383
  import { useState as useState2, useCallback as useCallback2 } from "react";
374
384
  var MAX_RENDERED_MESSAGES = 100;
375
- var msgIdCounter = 0;
376
- function nextId() {
377
- msgIdCounter += 1;
378
- return `msg_${msgIdCounter}`;
379
- }
380
385
  function useMessages() {
381
386
  const [messages, setMessages] = useState2([]);
382
387
  const addMessage = useCallback2((msg) => {
383
388
  setMessages((prev) => {
384
- const updated = [...prev, { ...msg, id: nextId(), timestamp: /* @__PURE__ */ new Date() }];
389
+ const updated = [...prev, msg];
385
390
  if (updated.length > MAX_RENDERED_MESSAGES) {
386
391
  return updated.slice(-MAX_RENDERED_MESSAGES);
387
392
  }
@@ -393,6 +398,7 @@ function useMessages() {
393
398
 
394
399
  // src/ui/hooks/useSlashCommands.ts
395
400
  import { useCallback as useCallback3 } from "react";
401
+ import { createSystemMessage } from "@robota-sdk/agent-core";
396
402
 
397
403
  // src/commands/slash-executor.ts
398
404
  var VALID_MODES2 = ["plan", "default", "acceptEdits", "bypassPermissions"];
@@ -503,18 +509,9 @@ async function handlePluginCommand(args, addMessage, callbacks) {
503
509
  try {
504
510
  switch (subcommand) {
505
511
  case "":
506
- case void 0: {
507
- const plugins = await callbacks.listInstalled();
508
- if (plugins.length === 0) {
509
- addMessage({ role: "system", content: "No plugins installed." });
510
- } else {
511
- const lines = plugins.map(
512
- (p) => ` ${p.name} \u2014 ${p.description} [${p.enabled ? "enabled" : "disabled"}]`
513
- );
514
- addMessage({ role: "system", content: `Installed plugins:
515
- ${lines.join("\n")}` });
516
- }
517
- return { handled: true };
512
+ case void 0:
513
+ case "manage": {
514
+ return { handled: true, triggerPluginTUI: true };
518
515
  }
519
516
  case "install": {
520
517
  if (!subArgs) {
@@ -661,18 +658,21 @@ async function executeSlashCommand(cmd, args, session, addMessage, clearMessages
661
658
 
662
659
  // src/ui/hooks/useSlashCommands.ts
663
660
  var EXIT_DELAY_MS = 500;
664
- function useSlashCommands(session, addMessage, setMessages, exit, registry, pendingModelChangeRef, setPendingModelId, pluginCallbacks) {
661
+ function useSlashCommands(session, addMessage, setMessages, exit, registry, pendingModelChangeRef, setPendingModelId, pluginCallbacks, setShowPluginTUI) {
665
662
  return useCallback3(
666
663
  async (input) => {
667
664
  const parts = input.slice(1).split(/\s+/);
668
665
  const cmd = parts[0]?.toLowerCase() ?? "";
669
666
  const args = parts.slice(1).join(" ");
670
667
  const clearMessages = () => setMessages([]);
668
+ const slashAddMessage = (msg) => {
669
+ addMessage(createSystemMessage(msg.content));
670
+ };
671
671
  const result = await executeSlashCommand(
672
672
  cmd,
673
673
  args,
674
674
  session,
675
- addMessage,
675
+ slashAddMessage,
676
676
  clearMessages,
677
677
  registry,
678
678
  pluginCallbacks
@@ -681,6 +681,9 @@ function useSlashCommands(session, addMessage, setMessages, exit, registry, pend
681
681
  pendingModelChangeRef.current = result.pendingModelId;
682
682
  setPendingModelId(result.pendingModelId);
683
683
  }
684
+ if (result.triggerPluginTUI) {
685
+ setShowPluginTUI?.(true);
686
+ }
684
687
  if (result.exitRequested) {
685
688
  setTimeout(() => exit(), EXIT_DELAY_MS);
686
689
  }
@@ -694,18 +697,26 @@ function useSlashCommands(session, addMessage, setMessages, exit, registry, pend
694
697
  registry,
695
698
  pendingModelChangeRef,
696
699
  setPendingModelId,
697
- pluginCallbacks
700
+ pluginCallbacks,
701
+ setShowPluginTUI
698
702
  ]
699
703
  );
700
704
  }
701
705
 
702
706
  // src/ui/hooks/useSubmitHandler.ts
703
707
  import { useCallback as useCallback4 } from "react";
708
+ import { randomUUID } from "crypto";
704
709
  import {
705
710
  createSubagentSession,
706
711
  getBuiltInAgent,
707
712
  retrieveAgentToolDeps
708
713
  } from "@robota-sdk/agent-sdk";
714
+ import {
715
+ createUserMessage,
716
+ createAssistantMessage,
717
+ createSystemMessage as createSystemMessage2,
718
+ createToolMessage
719
+ } from "@robota-sdk/agent-core";
709
720
 
710
721
  // src/utils/tool-call-extractor.ts
711
722
  var TOOL_ARG_MAX_LENGTH = 80;
@@ -862,21 +873,50 @@ async function runSessionPrompt(prompt, session, addMessage, clearStreamingText,
862
873
  historyBefore
863
874
  );
864
875
  if (toolSummaries.length > 0) {
865
- addMessage({
866
- role: "tool",
867
- content: JSON.stringify(toolSummaries),
868
- toolName: `${toolSummaries.length} tools`
869
- });
876
+ addMessage(
877
+ createToolMessage(JSON.stringify(toolSummaries), {
878
+ toolCallId: randomUUID(),
879
+ name: `${toolSummaries.length} tools`
880
+ })
881
+ );
870
882
  }
871
- addMessage({ role: "assistant", content: response || "(empty response)" });
883
+ addMessage(createAssistantMessage(response || "(empty response)"));
872
884
  syncContextState(session, setContextState);
873
885
  } catch (err) {
874
886
  clearStreamingText();
875
- if (err instanceof DOMException && err.name === "AbortError") {
876
- addMessage({ role: "system", content: "Cancelled." });
887
+ const isAbortError = err instanceof DOMException && err.name === "AbortError" || err instanceof Error && (err.message.includes("aborted") || err.message.includes("abort"));
888
+ if (isAbortError) {
889
+ const history = session.getHistory();
890
+ const toolSummaries = extractToolCallsWithDiff(
891
+ history,
892
+ historyBefore
893
+ );
894
+ if (toolSummaries.length > 0) {
895
+ addMessage(
896
+ createToolMessage(JSON.stringify(toolSummaries), {
897
+ toolCallId: randomUUID(),
898
+ name: `${toolSummaries.length} tools`
899
+ })
900
+ );
901
+ }
902
+ const assistantParts = [];
903
+ let lastAssistantState = "complete";
904
+ for (let i = historyBefore; i < history.length; i++) {
905
+ const msg = history[i];
906
+ if (msg && msg.role === "assistant" && msg.content) {
907
+ assistantParts.push(msg.content);
908
+ if (msg.state === "interrupted") lastAssistantState = "interrupted";
909
+ }
910
+ }
911
+ if (assistantParts.length > 0) {
912
+ addMessage(
913
+ createAssistantMessage(assistantParts.join("\n\n"), { state: lastAssistantState })
914
+ );
915
+ }
916
+ addMessage(createSystemMessage2("Interrupted by user."));
877
917
  } else {
878
918
  const errMsg = err instanceof Error ? err.message : String(err);
879
- addMessage({ role: "system", content: `Error: ${errMsg}` });
919
+ addMessage(createSystemMessage2(`Error: ${errMsg}`));
880
920
  }
881
921
  } finally {
882
922
  setIsThinking(false);
@@ -929,7 +969,7 @@ function useSubmitHandler(session, addMessage, handleSlashCommand, clearStreamin
929
969
  const runInFork = createForkRunner(session);
930
970
  const result = await executeSkill(skill, args, { runInFork });
931
971
  if (result.mode === "fork") {
932
- addMessage({ role: "assistant", content: result.result ?? "(empty response)" });
972
+ addMessage(createAssistantMessage(result.result ?? "(empty response)"));
933
973
  syncContextState(session, setContextState);
934
974
  return;
935
975
  }
@@ -964,7 +1004,7 @@ function useSubmitHandler(session, addMessage, handleSlashCommand, clearStreamin
964
1004
  hookInput
965
1005
  );
966
1006
  }
967
- addMessage({ role: "user", content: input });
1007
+ addMessage(createUserMessage(input));
968
1008
  return runSessionPrompt(
969
1009
  input,
970
1010
  session,
@@ -1082,22 +1122,7 @@ function createBuiltinCommands() {
1082
1122
  { name: "cost", description: "Show session info", source: "builtin" },
1083
1123
  { name: "context", description: "Context window info", source: "builtin" },
1084
1124
  { name: "permissions", description: "Permission rules", source: "builtin" },
1085
- {
1086
- name: "plugin",
1087
- description: "Manage plugins",
1088
- source: "builtin",
1089
- subcommands: [
1090
- { name: "install", description: "Install a plugin (name@marketplace)", source: "builtin" },
1091
- {
1092
- name: "uninstall",
1093
- description: "Uninstall a plugin (name@marketplace)",
1094
- source: "builtin"
1095
- },
1096
- { name: "enable", description: "Enable a plugin (name@marketplace)", source: "builtin" },
1097
- { name: "disable", description: "Disable a plugin (name@marketplace)", source: "builtin" },
1098
- { name: "marketplace", description: "Manage marketplace sources", source: "builtin" }
1099
- ]
1100
- },
1125
+ { name: "plugin", description: "Manage plugins", source: "builtin" },
1101
1126
  { name: "reload-plugins", description: "Reload all plugin resources", source: "builtin" },
1102
1127
  { name: "reset", description: "Delete settings and exit", source: "builtin" },
1103
1128
  { name: "exit", description: "Exit CLI", source: "builtin" }
@@ -1369,18 +1394,50 @@ function usePluginCallbacks(cwd) {
1369
1394
  return {
1370
1395
  listInstalled: async () => {
1371
1396
  const plugins = await loader.loadAll();
1372
- return plugins.map((p) => ({
1373
- name: p.manifest.name,
1374
- description: p.manifest.description,
1375
- enabled: true
1397
+ const enabledMap = settingsStore.getEnabledPlugins();
1398
+ return plugins.map((p) => {
1399
+ const parts = p.pluginDir.split("/");
1400
+ const cacheIdx = parts.indexOf("cache");
1401
+ const marketplaceName = cacheIdx >= 0 ? parts[cacheIdx + 1] : "";
1402
+ const fullId = marketplaceName ? `${p.manifest.name}@${marketplaceName}` : p.manifest.name;
1403
+ return {
1404
+ name: fullId,
1405
+ description: p.manifest.description,
1406
+ enabled: enabledMap[fullId] !== false && enabledMap[p.manifest.name] !== false
1407
+ };
1408
+ });
1409
+ },
1410
+ listAvailablePlugins: async (marketplaceName) => {
1411
+ let manifest;
1412
+ try {
1413
+ manifest = marketplace.fetchManifest(marketplaceName);
1414
+ } catch {
1415
+ return [];
1416
+ }
1417
+ const installed = installer.getInstalledPlugins();
1418
+ const installedNames = new Set(Object.values(installed).map((r) => r.pluginName));
1419
+ return manifest.plugins.map((p) => ({
1420
+ name: p.name,
1421
+ description: p.description,
1422
+ installed: installedNames.has(p.name)
1376
1423
  }));
1377
1424
  },
1378
- install: async (pluginId) => {
1425
+ install: async (pluginId, scope) => {
1379
1426
  const [name, marketplaceName] = pluginId.split("@");
1380
1427
  if (!name || !marketplaceName) {
1381
1428
  throw new Error("Plugin ID must be in format: name@marketplace");
1382
1429
  }
1383
- await installer.install(name, marketplaceName);
1430
+ if (scope === "project") {
1431
+ const projectPluginsDir = join4(cwd, ".robota", "plugins");
1432
+ const projectInstaller = new BundlePluginInstaller({
1433
+ pluginsDir: projectPluginsDir,
1434
+ settingsStore,
1435
+ marketplaceClient: marketplace
1436
+ });
1437
+ await projectInstaller.install(name, marketplaceName);
1438
+ } else {
1439
+ await installer.install(name, marketplaceName);
1440
+ }
1384
1441
  },
1385
1442
  uninstall: async (pluginId) => {
1386
1443
  await installer.uninstall(pluginId);
@@ -1423,6 +1480,7 @@ function usePluginCallbacks(cwd) {
1423
1480
  // src/ui/MessageList.tsx
1424
1481
  import React2 from "react";
1425
1482
  import { Box as Box2, Text as Text2 } from "ink";
1483
+ import { isToolMessage, isAssistantMessage } from "@robota-sdk/agent-core";
1426
1484
 
1427
1485
  // src/ui/render-markdown.ts
1428
1486
  import { marked } from "marked";
@@ -1482,7 +1540,7 @@ function DiffBlock({ file, lines }) {
1482
1540
  }
1483
1541
 
1484
1542
  // src/ui/MessageList.tsx
1485
- import { jsx, jsxs as jsxs2 } from "react/jsx-runtime";
1543
+ import { Fragment, jsx, jsxs as jsxs2 } from "react/jsx-runtime";
1486
1544
  function RoleLabel({ role }) {
1487
1545
  switch (role) {
1488
1546
  case "user":
@@ -1508,9 +1566,14 @@ function RoleLabel({ role }) {
1508
1566
  }
1509
1567
  }
1510
1568
  function ToolMessage({ message }) {
1569
+ if (!isToolMessage(message)) {
1570
+ return /* @__PURE__ */ jsx(Fragment, {});
1571
+ }
1572
+ const toolName = message.name;
1573
+ const content = message.content;
1511
1574
  let summaries = null;
1512
1575
  try {
1513
- const parsed = JSON.parse(message.content);
1576
+ const parsed = JSON.parse(content);
1514
1577
  if (Array.isArray(parsed) && parsed.length > 0 && typeof parsed[0].line === "string") {
1515
1578
  summaries = parsed;
1516
1579
  }
@@ -1523,9 +1586,9 @@ function ToolMessage({ message }) {
1523
1586
  "Tool:",
1524
1587
  " "
1525
1588
  ] }),
1526
- message.toolName && /* @__PURE__ */ jsxs2(Text2, { color: "white", dimColor: true, children: [
1589
+ toolName && /* @__PURE__ */ jsxs2(Text2, { color: "white", dimColor: true, children: [
1527
1590
  "[",
1528
- message.toolName,
1591
+ toolName,
1529
1592
  "]"
1530
1593
  ] })
1531
1594
  ] }),
@@ -1541,16 +1604,16 @@ function ToolMessage({ message }) {
1541
1604
  ] }, i))
1542
1605
  ] });
1543
1606
  }
1544
- const lines = message.content.split("\n").filter((l) => l.trim());
1607
+ const lines = content.split("\n").filter((l) => l.trim());
1545
1608
  return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", marginBottom: 1, children: [
1546
1609
  /* @__PURE__ */ jsxs2(Box2, { children: [
1547
1610
  /* @__PURE__ */ jsxs2(Text2, { color: "white", bold: true, children: [
1548
1611
  "Tool:",
1549
1612
  " "
1550
1613
  ] }),
1551
- message.toolName && /* @__PURE__ */ jsxs2(Text2, { color: "white", dimColor: true, children: [
1614
+ toolName && /* @__PURE__ */ jsxs2(Text2, { color: "white", dimColor: true, children: [
1552
1615
  "[",
1553
- message.toolName,
1616
+ toolName,
1554
1617
  "]"
1555
1618
  ] })
1556
1619
  ] }),
@@ -1566,21 +1629,15 @@ function ToolMessage({ message }) {
1566
1629
  var MessageItem = React2.memo(function MessageItem2({
1567
1630
  message
1568
1631
  }) {
1569
- if (message.role === "tool") {
1632
+ if (isToolMessage(message)) {
1570
1633
  return /* @__PURE__ */ jsx(ToolMessage, { message });
1571
1634
  }
1635
+ const content = message.content ?? "";
1636
+ const isInterrupted = message.state === "interrupted";
1572
1637
  return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", marginBottom: 1, children: [
1573
- /* @__PURE__ */ jsxs2(Box2, { children: [
1574
- /* @__PURE__ */ jsx(RoleLabel, { role: message.role }),
1575
- message.toolName && /* @__PURE__ */ jsxs2(Text2, { color: "magenta", dimColor: true, children: [
1576
- "[",
1577
- message.toolName,
1578
- "]",
1579
- " "
1580
- ] })
1581
- ] }),
1638
+ /* @__PURE__ */ jsx(Box2, { children: /* @__PURE__ */ jsx(RoleLabel, { role: message.role }) }),
1582
1639
  /* @__PURE__ */ jsx(Text2, { children: " " }),
1583
- /* @__PURE__ */ jsx(Box2, { marginLeft: 2, children: /* @__PURE__ */ jsx(Text2, { wrap: "wrap", children: message.role === "assistant" ? renderMarkdown(message.content) : message.content }) })
1640
+ /* @__PURE__ */ jsx(Box2, { marginLeft: 2, children: /* @__PURE__ */ jsx(Text2, { wrap: "wrap", children: isAssistantMessage(message) ? renderMarkdown(content + (isInterrupted ? "\n\n_(interrupted)_" : "")) : content }) })
1584
1641
  ] });
1585
1642
  });
1586
1643
  function MessageList({ messages }) {
@@ -1959,7 +2016,7 @@ function InputArea({ onSubmit, isDisabled, registry }) {
1959
2016
  isSubcommandMode
1960
2017
  }
1961
2018
  ),
1962
- /* @__PURE__ */ jsx6(Box5, { borderStyle: "single", borderColor: isDisabled ? "gray" : "green", paddingLeft: 1, children: isDisabled ? /* @__PURE__ */ jsx6(WaveText, { text: " Waiting for response..." }) : /* @__PURE__ */ jsxs5(Box5, { children: [
2019
+ /* @__PURE__ */ jsx6(Box5, { borderStyle: "single", borderColor: isDisabled ? "gray" : "green", paddingLeft: 1, children: isDisabled ? /* @__PURE__ */ jsx6(WaveText, { text: " Waiting for response... (ESC to interrupt)" }) : /* @__PURE__ */ jsxs5(Box5, { children: [
1963
2020
  /* @__PURE__ */ jsx6(Text7, { color: "green", bold: true, children: "> " }),
1964
2021
  /* @__PURE__ */ jsx6(
1965
2022
  CjkTextInput,
@@ -2084,7 +2141,7 @@ function PermissionPrompt({ request }) {
2084
2141
 
2085
2142
  // src/ui/StreamingIndicator.tsx
2086
2143
  import { Box as Box8, Text as Text10 } from "ink";
2087
- import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
2144
+ import { Fragment as Fragment2, jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
2088
2145
  function getToolStyle(t) {
2089
2146
  if (t.isRunning) return { color: "yellow", icon: "\u27F3", strikethrough: false };
2090
2147
  if (t.result === "error") return { color: "red", icon: "\u2717", strikethrough: true };
@@ -2095,7 +2152,7 @@ function StreamingIndicator({ text, activeTools }) {
2095
2152
  const hasTools = activeTools.length > 0;
2096
2153
  const hasText = text.length > 0;
2097
2154
  if (!hasTools && !hasText) {
2098
- return /* @__PURE__ */ jsx9(Text10, { color: "yellow", children: "Thinking..." });
2155
+ return /* @__PURE__ */ jsx9(Fragment2, {});
2099
2156
  }
2100
2157
  return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
2101
2158
  hasTools && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", marginBottom: 1, children: [
@@ -2125,8 +2182,459 @@ function StreamingIndicator({ text, activeTools }) {
2125
2182
  ] });
2126
2183
  }
2127
2184
 
2128
- // src/ui/App.tsx
2185
+ // src/ui/PluginTUI.tsx
2186
+ import { useState as useState9, useEffect as useEffect2, useCallback as useCallback9 } from "react";
2187
+
2188
+ // src/ui/MenuSelect.tsx
2189
+ import { useState as useState7, useCallback as useCallback7, useRef as useRef6 } from "react";
2190
+ import { Box as Box9, Text as Text11, useInput as useInput5 } from "ink";
2129
2191
  import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
2192
+ function MenuSelect({
2193
+ title,
2194
+ items,
2195
+ onSelect,
2196
+ onBack,
2197
+ loading,
2198
+ error
2199
+ }) {
2200
+ const [selected, setSelected] = useState7(0);
2201
+ const selectedRef = useRef6(0);
2202
+ const resolvedRef = useRef6(false);
2203
+ const doSelect = useCallback7(
2204
+ (index) => {
2205
+ if (resolvedRef.current || items.length === 0) return;
2206
+ resolvedRef.current = true;
2207
+ onSelect(items[index].value);
2208
+ },
2209
+ [items, onSelect]
2210
+ );
2211
+ useInput5((input, key) => {
2212
+ if (resolvedRef.current) return;
2213
+ if (key.escape) {
2214
+ resolvedRef.current = true;
2215
+ onBack();
2216
+ return;
2217
+ }
2218
+ if (loading || error || items.length === 0) return;
2219
+ if (key.upArrow) {
2220
+ const next = selectedRef.current > 0 ? selectedRef.current - 1 : selectedRef.current;
2221
+ selectedRef.current = next;
2222
+ setSelected(next);
2223
+ } else if (key.downArrow) {
2224
+ const next = selectedRef.current < items.length - 1 ? selectedRef.current + 1 : selectedRef.current;
2225
+ selectedRef.current = next;
2226
+ setSelected(next);
2227
+ } else if (key.return) {
2228
+ doSelect(selectedRef.current);
2229
+ }
2230
+ });
2231
+ return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
2232
+ /* @__PURE__ */ jsx10(Text11, { color: "yellow", bold: true, children: title }),
2233
+ loading && /* @__PURE__ */ jsx10(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx10(Text11, { dimColor: true, children: "Loading..." }) }),
2234
+ error && /* @__PURE__ */ jsxs9(Box9, { marginTop: 1, flexDirection: "column", children: [
2235
+ /* @__PURE__ */ jsx10(Text11, { color: "red", children: error }),
2236
+ /* @__PURE__ */ jsx10(Text11, { dimColor: true, children: "Press Esc to go back" })
2237
+ ] }),
2238
+ !loading && !error && /* @__PURE__ */ jsx10(Box9, { flexDirection: "column", marginTop: 1, children: items.map((item, i) => /* @__PURE__ */ jsxs9(Box9, { children: [
2239
+ /* @__PURE__ */ jsxs9(Text11, { color: i === selected ? "cyan" : void 0, bold: i === selected, children: [
2240
+ i === selected ? "> " : " ",
2241
+ item.label
2242
+ ] }),
2243
+ item.hint && /* @__PURE__ */ jsxs9(Text11, { dimColor: true, children: [
2244
+ " ",
2245
+ item.hint
2246
+ ] })
2247
+ ] }, item.value)) }),
2248
+ /* @__PURE__ */ jsx10(Text11, { dimColor: true, children: loading || error ? "" : " \u2191\u2193 Navigate Enter Select Esc Back" })
2249
+ ] });
2250
+ }
2251
+
2252
+ // src/ui/TextPrompt.tsx
2253
+ import { useState as useState8, useRef as useRef7, useCallback as useCallback8 } from "react";
2254
+ import { Box as Box10, Text as Text12, useInput as useInput6 } from "ink";
2255
+ import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
2256
+ function TextPrompt({
2257
+ title,
2258
+ placeholder,
2259
+ onSubmit,
2260
+ onCancel,
2261
+ validate
2262
+ }) {
2263
+ const [value, setValue] = useState8("");
2264
+ const [error, setError] = useState8();
2265
+ const resolvedRef = useRef7(false);
2266
+ const valueRef = useRef7("");
2267
+ const handleSubmit = useCallback8(() => {
2268
+ if (resolvedRef.current) return;
2269
+ const trimmed = valueRef.current.trim();
2270
+ if (!trimmed) return;
2271
+ if (validate) {
2272
+ const err = validate(trimmed);
2273
+ if (err) {
2274
+ setError(err);
2275
+ return;
2276
+ }
2277
+ }
2278
+ resolvedRef.current = true;
2279
+ onSubmit(trimmed);
2280
+ }, [validate, onSubmit]);
2281
+ useInput6((input, key) => {
2282
+ if (resolvedRef.current) return;
2283
+ if (key.escape) {
2284
+ resolvedRef.current = true;
2285
+ onCancel();
2286
+ return;
2287
+ }
2288
+ if (key.return) {
2289
+ handleSubmit();
2290
+ return;
2291
+ }
2292
+ if (key.backspace || key.delete) {
2293
+ valueRef.current = valueRef.current.slice(0, -1);
2294
+ setValue(valueRef.current);
2295
+ setError(void 0);
2296
+ return;
2297
+ }
2298
+ if (input && !key.ctrl && !key.meta) {
2299
+ valueRef.current = valueRef.current + input;
2300
+ setValue(valueRef.current);
2301
+ setError(void 0);
2302
+ }
2303
+ });
2304
+ return /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
2305
+ /* @__PURE__ */ jsx11(Text12, { color: "yellow", bold: true, children: title }),
2306
+ /* @__PURE__ */ jsxs10(Box10, { marginTop: 1, children: [
2307
+ /* @__PURE__ */ jsx11(Text12, { color: "cyan", children: "> " }),
2308
+ value ? /* @__PURE__ */ jsx11(Text12, { children: value }) : placeholder ? /* @__PURE__ */ jsx11(Text12, { dimColor: true, children: placeholder }) : null,
2309
+ /* @__PURE__ */ jsx11(Text12, { color: "cyan", children: "\u2588" })
2310
+ ] }),
2311
+ error && /* @__PURE__ */ jsx11(Text12, { color: "red", children: error }),
2312
+ /* @__PURE__ */ jsx11(Text12, { dimColor: true, children: " Enter Submit Esc Cancel" })
2313
+ ] });
2314
+ }
2315
+
2316
+ // src/ui/plugin-tui-handlers.ts
2317
+ function handleMainSelect(value, nav) {
2318
+ if (value === "marketplace") {
2319
+ nav.push({ screen: "marketplace-list" });
2320
+ } else if (value === "installed") {
2321
+ nav.push({ screen: "installed-list" });
2322
+ }
2323
+ }
2324
+ function handleMarketplaceListSelect(value, nav) {
2325
+ if (value === "__add__") {
2326
+ nav.push({ screen: "marketplace-add" });
2327
+ } else {
2328
+ nav.push({ screen: "marketplace-action", context: { marketplace: value } });
2329
+ }
2330
+ }
2331
+ function handleMarketplaceActionSelect(value, marketplace, callbacks, nav) {
2332
+ if (value === "browse") {
2333
+ nav.push({ screen: "marketplace-browse", context: { marketplace } });
2334
+ } else if (value === "update") {
2335
+ callbacks.marketplaceUpdate(marketplace).then(() => {
2336
+ nav.notify(`Updated marketplace "${marketplace}".`);
2337
+ nav.pop();
2338
+ }).catch((err) => {
2339
+ nav.notify(`Error: ${err instanceof Error ? err.message : String(err)}`);
2340
+ });
2341
+ } else if (value === "remove") {
2342
+ nav.setConfirm({
2343
+ message: `Remove marketplace "${marketplace}" and all its plugins?`,
2344
+ onConfirm: () => {
2345
+ nav.setConfirm(void 0);
2346
+ callbacks.marketplaceRemove(marketplace).then(() => {
2347
+ nav.notify(`Removed marketplace "${marketplace}".`);
2348
+ nav.popN(2);
2349
+ }).catch((err) => {
2350
+ nav.notify(`Error: ${err instanceof Error ? err.message : String(err)}`);
2351
+ });
2352
+ },
2353
+ onCancel: () => nav.setConfirm(void 0)
2354
+ });
2355
+ }
2356
+ }
2357
+ function handleMarketplaceBrowseSelect(value, marketplace, items, nav) {
2358
+ const fullId = `${value}@${marketplace}`;
2359
+ const item = items.find((i) => i.value === value);
2360
+ if (item?.hint === "installed") {
2361
+ nav.push({ screen: "installed-action", context: { pluginId: fullId } });
2362
+ } else {
2363
+ nav.push({ screen: "marketplace-install-scope", context: { marketplace, pluginId: fullId } });
2364
+ }
2365
+ }
2366
+ function handleInstallScopeSelect(value, pluginId, callbacks, nav) {
2367
+ const scope = value;
2368
+ callbacks.install(pluginId, scope).then(() => {
2369
+ nav.notify(`Installed plugin "${pluginId}" (${scope} scope).`);
2370
+ nav.popN(2);
2371
+ }).catch((err) => {
2372
+ nav.notify(`Error: ${err instanceof Error ? err.message : String(err)}`);
2373
+ });
2374
+ }
2375
+ function handleInstalledListSelect(value, callbacks, nav) {
2376
+ nav.setConfirm({
2377
+ message: `Uninstall plugin "${value}"?`,
2378
+ onConfirm: () => {
2379
+ nav.setConfirm(void 0);
2380
+ callbacks.uninstall(value).then(() => {
2381
+ nav.notify(`Uninstalled plugin "${value}".`);
2382
+ nav.refresh();
2383
+ }).catch((err) => {
2384
+ nav.notify(`Error: ${err instanceof Error ? err.message : String(err)}`);
2385
+ });
2386
+ },
2387
+ onCancel: () => nav.setConfirm(void 0)
2388
+ });
2389
+ }
2390
+ function handleInstalledActionSelect(value, pluginId, callbacks, nav) {
2391
+ if (value === "uninstall") {
2392
+ nav.setConfirm({
2393
+ message: `Uninstall plugin "${pluginId}"?`,
2394
+ onConfirm: () => {
2395
+ nav.setConfirm(void 0);
2396
+ callbacks.uninstall(pluginId).then(() => {
2397
+ nav.notify(`Uninstalled plugin "${pluginId}".`);
2398
+ nav.popN(2);
2399
+ }).catch((err) => {
2400
+ nav.notify(`Error: ${err instanceof Error ? err.message : String(err)}`);
2401
+ });
2402
+ },
2403
+ onCancel: () => nav.setConfirm(void 0)
2404
+ });
2405
+ }
2406
+ }
2407
+
2408
+ // src/ui/PluginTUI.tsx
2409
+ import { jsx as jsx12 } from "react/jsx-runtime";
2410
+ function PluginTUI({ callbacks, onClose, addMessage }) {
2411
+ const [stack, setStack] = useState9([{ screen: "main" }]);
2412
+ const [items, setItems] = useState9([]);
2413
+ const [loading, setLoading] = useState9(false);
2414
+ const [error, setError] = useState9();
2415
+ const [confirm, setConfirm] = useState9();
2416
+ const [refreshCounter, setRefreshCounter] = useState9(0);
2417
+ const current = stack[stack.length - 1] ?? { screen: "main" };
2418
+ const push = useCallback9((state) => {
2419
+ setStack((prev) => [...prev, state]);
2420
+ setItems([]);
2421
+ setError(void 0);
2422
+ }, []);
2423
+ const pop = useCallback9(() => {
2424
+ setStack((prev) => {
2425
+ if (prev.length <= 1) {
2426
+ onClose();
2427
+ return prev;
2428
+ }
2429
+ return prev.slice(0, -1);
2430
+ });
2431
+ setItems([]);
2432
+ setError(void 0);
2433
+ }, [onClose]);
2434
+ const popN = useCallback9(
2435
+ (n) => {
2436
+ setStack((prev) => {
2437
+ const next = prev.slice(0, Math.max(1, prev.length - n));
2438
+ if (next.length === 0) {
2439
+ onClose();
2440
+ return prev;
2441
+ }
2442
+ return next;
2443
+ });
2444
+ setItems([]);
2445
+ setError(void 0);
2446
+ },
2447
+ [onClose]
2448
+ );
2449
+ const notify = useCallback9(
2450
+ (content) => {
2451
+ addMessage?.({ role: "system", content });
2452
+ },
2453
+ [addMessage]
2454
+ );
2455
+ const refresh = useCallback9(() => {
2456
+ setItems([]);
2457
+ setRefreshCounter((c) => c + 1);
2458
+ }, []);
2459
+ const nav = { push, pop, popN, notify, setConfirm, refresh };
2460
+ useEffect2(() => {
2461
+ const screen2 = current.screen;
2462
+ if (screen2 === "marketplace-list") {
2463
+ setLoading(true);
2464
+ callbacks.marketplaceList().then((sources) => {
2465
+ const baseItems = [{ label: "Add Marketplace", value: "__add__" }];
2466
+ const sourceItems = sources.map((s) => ({
2467
+ label: s.name,
2468
+ value: s.name,
2469
+ hint: s.type
2470
+ }));
2471
+ setItems([...baseItems, ...sourceItems]);
2472
+ setLoading(false);
2473
+ }).catch((err) => {
2474
+ setError(err instanceof Error ? err.message : String(err));
2475
+ setLoading(false);
2476
+ });
2477
+ } else if (screen2 === "marketplace-browse") {
2478
+ const marketplace = current.context?.marketplace ?? "";
2479
+ setLoading(true);
2480
+ callbacks.listAvailablePlugins(marketplace).then((plugins) => {
2481
+ setItems(
2482
+ plugins.map((p) => ({
2483
+ label: p.name,
2484
+ value: p.name,
2485
+ hint: p.installed ? "installed" : p.description
2486
+ }))
2487
+ );
2488
+ setLoading(false);
2489
+ }).catch((err) => {
2490
+ setError(err instanceof Error ? err.message : String(err));
2491
+ setLoading(false);
2492
+ });
2493
+ } else if (screen2 === "installed-list") {
2494
+ setLoading(true);
2495
+ callbacks.listInstalled().then((plugins) => {
2496
+ setItems(
2497
+ plugins.map((p) => ({
2498
+ label: p.name,
2499
+ value: p.name,
2500
+ hint: p.description
2501
+ }))
2502
+ );
2503
+ setLoading(false);
2504
+ }).catch((err) => {
2505
+ setError(err instanceof Error ? err.message : String(err));
2506
+ setLoading(false);
2507
+ });
2508
+ }
2509
+ }, [stack.length, current.screen, current.context?.marketplace, callbacks, refreshCounter]);
2510
+ const handleSelect = useCallback9(
2511
+ (value) => {
2512
+ const screen2 = current.screen;
2513
+ const ctx = current.context;
2514
+ if (screen2 === "main") handleMainSelect(value, nav);
2515
+ else if (screen2 === "marketplace-list") handleMarketplaceListSelect(value, nav);
2516
+ else if (screen2 === "marketplace-action")
2517
+ handleMarketplaceActionSelect(value, ctx?.marketplace ?? "", callbacks, nav);
2518
+ else if (screen2 === "marketplace-browse")
2519
+ handleMarketplaceBrowseSelect(value, ctx?.marketplace ?? "", items, nav);
2520
+ else if (screen2 === "marketplace-install-scope")
2521
+ handleInstallScopeSelect(value, ctx?.pluginId ?? "", callbacks, nav);
2522
+ else if (screen2 === "installed-list") handleInstalledListSelect(value, callbacks, nav);
2523
+ else if (screen2 === "installed-action")
2524
+ handleInstalledActionSelect(value, ctx?.pluginId ?? "", callbacks, nav);
2525
+ },
2526
+ [current, items, callbacks, push, pop, popN, notify, setConfirm, refresh]
2527
+ );
2528
+ const handleTextSubmit = useCallback9(
2529
+ (value) => {
2530
+ if (current.screen === "marketplace-add") {
2531
+ callbacks.marketplaceAdd(value).then((name) => {
2532
+ notify(`Added marketplace "${name}" from ${value}.`);
2533
+ pop();
2534
+ }).catch((err) => {
2535
+ notify(`Error: ${err instanceof Error ? err.message : String(err)}`);
2536
+ pop();
2537
+ });
2538
+ }
2539
+ },
2540
+ [current.screen, callbacks, notify, pop]
2541
+ );
2542
+ if (confirm) {
2543
+ return /* @__PURE__ */ jsx12(
2544
+ ConfirmPrompt,
2545
+ {
2546
+ message: confirm.message,
2547
+ onSelect: (index) => {
2548
+ if (index === 0) confirm.onConfirm();
2549
+ else confirm.onCancel();
2550
+ }
2551
+ }
2552
+ );
2553
+ }
2554
+ const screen = current.screen;
2555
+ if (screen === "marketplace-add") {
2556
+ return /* @__PURE__ */ jsx12(
2557
+ TextPrompt,
2558
+ {
2559
+ title: "Add Marketplace Source",
2560
+ placeholder: "owner/repo or git URL",
2561
+ onSubmit: handleTextSubmit,
2562
+ onCancel: pop,
2563
+ validate: (v) => !v.includes("/") ? "Must be owner/repo or a git URL" : void 0
2564
+ }
2565
+ );
2566
+ }
2567
+ if (screen === "marketplace-action") {
2568
+ return /* @__PURE__ */ jsx12(
2569
+ MenuSelect,
2570
+ {
2571
+ title: `Marketplace: ${current.context?.marketplace ?? ""}`,
2572
+ items: [
2573
+ { label: "Browse plugins", value: "browse" },
2574
+ { label: "Update", value: "update" },
2575
+ { label: "Remove", value: "remove" }
2576
+ ],
2577
+ onSelect: handleSelect,
2578
+ onBack: pop
2579
+ },
2580
+ stack.length
2581
+ );
2582
+ }
2583
+ if (screen === "marketplace-install-scope") {
2584
+ return /* @__PURE__ */ jsx12(
2585
+ MenuSelect,
2586
+ {
2587
+ title: `Install scope for "${current.context?.pluginId ?? ""}"`,
2588
+ items: [
2589
+ { label: "User scope", value: "user" },
2590
+ { label: "Project scope", value: "project" }
2591
+ ],
2592
+ onSelect: handleSelect,
2593
+ onBack: pop
2594
+ },
2595
+ stack.length
2596
+ );
2597
+ }
2598
+ if (screen === "installed-action") {
2599
+ return /* @__PURE__ */ jsx12(
2600
+ MenuSelect,
2601
+ {
2602
+ title: `Plugin: ${current.context?.pluginId ?? ""}`,
2603
+ items: [{ label: "Uninstall", value: "uninstall" }],
2604
+ onSelect: handleSelect,
2605
+ onBack: pop
2606
+ },
2607
+ stack.length
2608
+ );
2609
+ }
2610
+ const titleMap = {
2611
+ main: "Plugin Management",
2612
+ "marketplace-list": "Marketplace",
2613
+ "marketplace-browse": `Browse: ${current.context?.marketplace ?? ""}`,
2614
+ "installed-list": "Installed Plugins"
2615
+ };
2616
+ const staticItemsMap = {
2617
+ main: [
2618
+ { label: "Marketplace", value: "marketplace" },
2619
+ { label: "Installed Plugins", value: "installed" }
2620
+ ]
2621
+ };
2622
+ return /* @__PURE__ */ jsx12(
2623
+ MenuSelect,
2624
+ {
2625
+ title: titleMap[screen] ?? "Plugin Management",
2626
+ items: staticItemsMap[screen] ?? items,
2627
+ onSelect: handleSelect,
2628
+ onBack: pop,
2629
+ loading,
2630
+ error
2631
+ },
2632
+ `${screen}-${stack.length}-${refreshCounter}`
2633
+ );
2634
+ }
2635
+
2636
+ // src/ui/App.tsx
2637
+ import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
2130
2638
  var EXIT_DELAY_MS2 = 500;
2131
2639
  function mergeHooksIntoConfig(configHooks, pluginHooks) {
2132
2640
  const pluginKeys = Object.keys(pluginHooks);
@@ -2158,15 +2666,16 @@ function App(props) {
2158
2666
  { ...props, config: configWithPluginHooks }
2159
2667
  );
2160
2668
  const { messages, setMessages, addMessage } = useMessages();
2161
- const [isThinking, setIsThinking] = useState7(false);
2669
+ const [isThinking, setIsThinking] = useState10(false);
2162
2670
  const initialCtx = session.getContextState();
2163
- const [contextState, setContextState] = useState7({
2671
+ const [contextState, setContextState] = useState10({
2164
2672
  percentage: initialCtx.usedPercentage,
2165
2673
  usedTokens: initialCtx.usedTokens,
2166
2674
  maxTokens: initialCtx.maxTokens
2167
2675
  });
2168
- const pendingModelChangeRef = useRef6(null);
2169
- const [pendingModelId, setPendingModelId] = useState7(null);
2676
+ const pendingModelChangeRef = useRef8(null);
2677
+ const [pendingModelId, setPendingModelId] = useState10(null);
2678
+ const [showPluginTUI, setShowPluginTUI] = useState10(false);
2170
2679
  const pluginCallbacks = usePluginCallbacks(props.cwd ?? process.cwd());
2171
2680
  const handleSlashCommand = useSlashCommands(
2172
2681
  session,
@@ -2176,7 +2685,8 @@ function App(props) {
2176
2685
  registry,
2177
2686
  pendingModelChangeRef,
2178
2687
  setPendingModelId,
2179
- pluginCallbacks
2688
+ pluginCallbacks,
2689
+ setShowPluginTUI
2180
2690
  );
2181
2691
  const handleSubmit = useSubmitHandler(
2182
2692
  session,
@@ -2187,33 +2697,33 @@ function App(props) {
2187
2697
  setContextState,
2188
2698
  registry
2189
2699
  );
2190
- useInput5(
2700
+ useInput7(
2191
2701
  (_input, key) => {
2192
2702
  if (key.ctrl && _input === "c") exit();
2193
2703
  if (key.escape && isThinking) session.abort();
2194
2704
  },
2195
- { isActive: !permissionRequest }
2705
+ { isActive: !permissionRequest && !showPluginTUI }
2196
2706
  );
2197
- return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
2198
- /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", paddingX: 1, marginBottom: 1, children: [
2199
- /* @__PURE__ */ jsx10(Text11, { color: "cyan", bold: true, children: `
2707
+ return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", children: [
2708
+ /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", paddingX: 1, marginBottom: 1, children: [
2709
+ /* @__PURE__ */ jsx13(Text13, { color: "cyan", bold: true, children: `
2200
2710
  ____ ___ ____ ___ _____ _
2201
2711
  | _ \\ / _ \\| __ ) / _ \\_ _|/ \\
2202
2712
  | |_) | | | | _ \\| | | || | / _ \\
2203
2713
  | _ <| |_| | |_) | |_| || |/ ___ \\
2204
2714
  |_| \\_\\\\___/|____/ \\___/ |_/_/ \\_\\
2205
2715
  ` }),
2206
- /* @__PURE__ */ jsxs9(Text11, { dimColor: true, children: [
2716
+ /* @__PURE__ */ jsxs11(Text13, { dimColor: true, children: [
2207
2717
  " v",
2208
2718
  props.version ?? "0.0.0"
2209
2719
  ] })
2210
2720
  ] }),
2211
- /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", paddingX: 1, flexGrow: 1, children: [
2212
- /* @__PURE__ */ jsx10(MessageList, { messages }),
2213
- isThinking && /* @__PURE__ */ jsx10(Box9, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ jsx10(StreamingIndicator, { text: streamingText, activeTools }) })
2721
+ /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", paddingX: 1, flexGrow: 1, children: [
2722
+ /* @__PURE__ */ jsx13(MessageList, { messages }),
2723
+ isThinking && /* @__PURE__ */ jsx13(Box11, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ jsx13(StreamingIndicator, { text: streamingText, activeTools }) })
2214
2724
  ] }),
2215
- permissionRequest && /* @__PURE__ */ jsx10(PermissionPrompt, { request: permissionRequest }),
2216
- pendingModelId && /* @__PURE__ */ jsx10(
2725
+ permissionRequest && /* @__PURE__ */ jsx13(PermissionPrompt, { request: permissionRequest }),
2726
+ pendingModelId && /* @__PURE__ */ jsx13(
2217
2727
  ConfirmPrompt,
2218
2728
  {
2219
2729
  message: `Change model to ${getModelName(pendingModelId)}? This will restart the session.`,
@@ -2224,24 +2734,34 @@ function App(props) {
2224
2734
  try {
2225
2735
  const settingsPath = getUserSettingsPath();
2226
2736
  updateModelInSettings(settingsPath, pendingModelId);
2227
- addMessage({
2228
- role: "system",
2229
- content: `Model changed to ${getModelName(pendingModelId)}. Restarting...`
2230
- });
2737
+ addMessage(
2738
+ createSystemMessage3(
2739
+ `Model changed to ${getModelName(pendingModelId)}. Restarting...`
2740
+ )
2741
+ );
2231
2742
  setTimeout(() => exit(), EXIT_DELAY_MS2);
2232
2743
  } catch (err) {
2233
- addMessage({
2234
- role: "system",
2235
- content: `Failed: ${err instanceof Error ? err.message : String(err)}`
2236
- });
2744
+ addMessage(
2745
+ createSystemMessage3(
2746
+ `Failed: ${err instanceof Error ? err.message : String(err)}`
2747
+ )
2748
+ );
2237
2749
  }
2238
2750
  } else {
2239
- addMessage({ role: "system", content: "Model change cancelled." });
2751
+ addMessage(createSystemMessage3("Model change cancelled."));
2240
2752
  }
2241
2753
  }
2242
2754
  }
2243
2755
  ),
2244
- /* @__PURE__ */ jsx10(
2756
+ showPluginTUI && /* @__PURE__ */ jsx13(
2757
+ PluginTUI,
2758
+ {
2759
+ callbacks: pluginCallbacks,
2760
+ onClose: () => setShowPluginTUI(false),
2761
+ addMessage: (msg) => addMessage(createSystemMessage3(msg.content))
2762
+ }
2763
+ ),
2764
+ /* @__PURE__ */ jsx13(
2245
2765
  StatusBar,
2246
2766
  {
2247
2767
  permissionMode: session.getPermissionMode(),
@@ -2254,20 +2774,20 @@ function App(props) {
2254
2774
  contextMaxTokens: contextState.maxTokens
2255
2775
  }
2256
2776
  ),
2257
- /* @__PURE__ */ jsx10(
2777
+ /* @__PURE__ */ jsx13(
2258
2778
  InputArea,
2259
2779
  {
2260
2780
  onSubmit: handleSubmit,
2261
- isDisabled: isThinking || !!permissionRequest,
2781
+ isDisabled: isThinking || !!permissionRequest || showPluginTUI,
2262
2782
  registry
2263
2783
  }
2264
2784
  ),
2265
- /* @__PURE__ */ jsx10(Text11, { children: " " })
2785
+ /* @__PURE__ */ jsx13(Text13, { children: " " })
2266
2786
  ] });
2267
2787
  }
2268
2788
 
2269
2789
  // src/ui/render.tsx
2270
- import { jsx as jsx11 } from "react/jsx-runtime";
2790
+ import { jsx as jsx14 } from "react/jsx-runtime";
2271
2791
  function renderApp(options) {
2272
2792
  process.on("unhandledRejection", (reason) => {
2273
2793
  process.stderr.write(`
@@ -2278,7 +2798,7 @@ function renderApp(options) {
2278
2798
  `);
2279
2799
  }
2280
2800
  });
2281
- const instance = render(/* @__PURE__ */ jsx11(App, { ...options }), {
2801
+ const instance = render(/* @__PURE__ */ jsx14(App, { ...options }), {
2282
2802
  exitOnCtrlC: true
2283
2803
  });
2284
2804
  instance.waitUntilExit().catch((err) => {