@robota-sdk/agent-cli 3.0.0-beta.51 → 3.0.0-beta.53
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.js +1 -1
- package/dist/node/{chunk-7EBJI2DW.js → chunk-CXBD4JNS.js} +458 -366
- package/dist/node/index.cjs +621 -528
- package/dist/node/index.js +1 -1
- package/package.json +6 -6
package/dist/node/index.cjs
CHANGED
|
@@ -38,7 +38,7 @@ module.exports = __toCommonJS(index_exports);
|
|
|
38
38
|
var import_node_fs3 = require("fs");
|
|
39
39
|
var import_node_path5 = require("path");
|
|
40
40
|
var import_node_url = require("url");
|
|
41
|
-
var
|
|
41
|
+
var import_agent_sdk4 = require("@robota-sdk/agent-sdk");
|
|
42
42
|
var import_agent_sessions = require("@robota-sdk/agent-sessions");
|
|
43
43
|
|
|
44
44
|
// src/utils/cli-args.ts
|
|
@@ -111,7 +111,14 @@ function getUserSettingsPath() {
|
|
|
111
111
|
}
|
|
112
112
|
function readSettings(path) {
|
|
113
113
|
if (!(0, import_node_fs.existsSync)(path)) return {};
|
|
114
|
-
|
|
114
|
+
const raw = (0, import_node_fs.readFileSync)(path, "utf8");
|
|
115
|
+
try {
|
|
116
|
+
return JSON.parse(raw);
|
|
117
|
+
} catch {
|
|
118
|
+
process.stderr.write(`Warning: corrupt settings file at ${path}, resetting to defaults
|
|
119
|
+
`);
|
|
120
|
+
return {};
|
|
121
|
+
}
|
|
115
122
|
}
|
|
116
123
|
function writeSettings(path, settings) {
|
|
117
124
|
(0, import_node_fs.mkdirSync)((0, import_node_path.dirname)(path), { recursive: true });
|
|
@@ -180,20 +187,18 @@ function createProviderFromSettings(cwd, modelOverride) {
|
|
|
180
187
|
var import_agent_transport_headless = require("@robota-sdk/agent-transport-headless");
|
|
181
188
|
|
|
182
189
|
// src/ui/render.tsx
|
|
183
|
-
var
|
|
190
|
+
var import_ink17 = require("ink");
|
|
184
191
|
|
|
185
192
|
// src/ui/App.tsx
|
|
186
|
-
var
|
|
187
|
-
var
|
|
188
|
-
var
|
|
193
|
+
var import_react17 = require("react");
|
|
194
|
+
var import_ink16 = require("ink");
|
|
195
|
+
var import_agent_core5 = require("@robota-sdk/agent-core");
|
|
189
196
|
|
|
190
197
|
// src/ui/hooks/useInteractiveSession.ts
|
|
191
|
-
var
|
|
198
|
+
var import_react2 = require("react");
|
|
192
199
|
var import_node_os2 = require("os");
|
|
193
200
|
var import_node_path3 = require("path");
|
|
194
|
-
var
|
|
195
|
-
var import_agent_core = require("@robota-sdk/agent-core");
|
|
196
|
-
var import_node_crypto = require("crypto");
|
|
201
|
+
var import_agent_sdk2 = require("@robota-sdk/agent-sdk");
|
|
197
202
|
|
|
198
203
|
// src/ui/tui-state-manager.ts
|
|
199
204
|
var MAX_RENDERED_MESSAGES = 100;
|
|
@@ -321,9 +326,97 @@ var TuiStateManager = class {
|
|
|
321
326
|
}
|
|
322
327
|
};
|
|
323
328
|
|
|
329
|
+
// src/ui/hooks/useSlashRouting.ts
|
|
330
|
+
var import_react = require("react");
|
|
331
|
+
var import_node_crypto = require("crypto");
|
|
332
|
+
var import_agent_sdk = require("@robota-sdk/agent-sdk");
|
|
333
|
+
var import_agent_core = require("@robota-sdk/agent-core");
|
|
334
|
+
function useSlashRouting(interactiveSession, registry, manager) {
|
|
335
|
+
return (0, import_react.useCallback)(
|
|
336
|
+
async (input) => {
|
|
337
|
+
if (!input.startsWith("/")) {
|
|
338
|
+
await interactiveSession.submit(input);
|
|
339
|
+
manager.setPendingPrompt(interactiveSession.getPendingPrompt());
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
const parts = input.slice(1).split(/\s+/);
|
|
343
|
+
const cmd = parts[0]?.toLowerCase() ?? "";
|
|
344
|
+
const args = parts.slice(1).join(" ");
|
|
345
|
+
const result = await interactiveSession.executeCommand(cmd, args);
|
|
346
|
+
if (result) {
|
|
347
|
+
manager.addEntry((0, import_agent_core.messageToHistoryEntry)((0, import_agent_core.createSystemMessage)(result.message)));
|
|
348
|
+
const effects = interactiveSession;
|
|
349
|
+
if (result.data?.modelId) {
|
|
350
|
+
effects._pendingModelId = result.data.modelId;
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
if (result.data?.language) {
|
|
354
|
+
effects._pendingLanguage = result.data.language;
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
if (result.data?.resetRequested) {
|
|
358
|
+
effects._resetRequested = true;
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
if (result.data?.triggerResumePicker) {
|
|
362
|
+
effects._triggerResumePicker = true;
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
if (result.data?.name) {
|
|
366
|
+
effects._sessionName = result.data.name;
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
const ctx = interactiveSession.getContextState();
|
|
370
|
+
manager.setContextState({
|
|
371
|
+
percentage: ctx.usedPercentage,
|
|
372
|
+
usedTokens: ctx.usedTokens,
|
|
373
|
+
maxTokens: ctx.maxTokens
|
|
374
|
+
});
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
const skillCmd = registry.getCommands().find((c) => c.name === cmd && (c.source === "skill" || c.source === "plugin"));
|
|
378
|
+
if (skillCmd) {
|
|
379
|
+
manager.addEntry({
|
|
380
|
+
id: (0, import_node_crypto.randomUUID)(),
|
|
381
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
382
|
+
category: "event",
|
|
383
|
+
type: "skill-invocation",
|
|
384
|
+
data: {
|
|
385
|
+
skillName: cmd,
|
|
386
|
+
source: skillCmd.source,
|
|
387
|
+
message: `Invoking ${skillCmd.source}: ${cmd}`
|
|
388
|
+
}
|
|
389
|
+
});
|
|
390
|
+
const prompt = await (0, import_agent_sdk.buildSkillPrompt)(input, registry);
|
|
391
|
+
if (prompt) {
|
|
392
|
+
const qualifiedName = registry.resolveQualifiedName(cmd);
|
|
393
|
+
const hookInput = qualifiedName ? `/${qualifiedName}${input.slice(1 + cmd.length)}` : input;
|
|
394
|
+
await interactiveSession.submit(prompt, input, hookInput);
|
|
395
|
+
manager.setPendingPrompt(interactiveSession.getPendingPrompt());
|
|
396
|
+
return;
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
if (cmd === "exit") {
|
|
400
|
+
interactiveSession._exitRequested = true;
|
|
401
|
+
return;
|
|
402
|
+
}
|
|
403
|
+
if (cmd === "plugin") {
|
|
404
|
+
interactiveSession._triggerPluginTUI = true;
|
|
405
|
+
return;
|
|
406
|
+
}
|
|
407
|
+
manager.addEntry(
|
|
408
|
+
(0, import_agent_core.messageToHistoryEntry)(
|
|
409
|
+
(0, import_agent_core.createSystemMessage)(`Unknown command "/${cmd}". Type /help for help.`)
|
|
410
|
+
)
|
|
411
|
+
);
|
|
412
|
+
},
|
|
413
|
+
[interactiveSession, registry, manager]
|
|
414
|
+
);
|
|
415
|
+
}
|
|
416
|
+
|
|
324
417
|
// src/ui/hooks/useInteractiveSession.ts
|
|
325
418
|
function initializeSession(props, permissionHandler) {
|
|
326
|
-
const interactiveSession = new
|
|
419
|
+
const interactiveSession = new import_agent_sdk2.InteractiveSession({
|
|
327
420
|
cwd: props.cwd,
|
|
328
421
|
provider: props.provider,
|
|
329
422
|
permissionMode: props.permissionMode,
|
|
@@ -334,15 +427,15 @@ function initializeSession(props, permissionHandler) {
|
|
|
334
427
|
forkSession: props.forkSession,
|
|
335
428
|
sessionName: props.sessionName
|
|
336
429
|
});
|
|
337
|
-
const registry = new
|
|
338
|
-
registry.addSource(new
|
|
339
|
-
registry.addSource(new
|
|
430
|
+
const registry = new import_agent_sdk2.CommandRegistry();
|
|
431
|
+
registry.addSource(new import_agent_sdk2.BuiltinCommandSource());
|
|
432
|
+
registry.addSource(new import_agent_sdk2.SkillCommandSource(props.cwd));
|
|
340
433
|
const pluginsDir = (0, import_node_path3.join)((0, import_node_os2.homedir)(), ".robota", "plugins");
|
|
341
|
-
const loader = new
|
|
434
|
+
const loader = new import_agent_sdk2.BundlePluginLoader(pluginsDir);
|
|
342
435
|
try {
|
|
343
436
|
const plugins = loader.loadPluginsSync();
|
|
344
437
|
if (plugins.length > 0) {
|
|
345
|
-
registry.addSource(new
|
|
438
|
+
registry.addSource(new import_agent_sdk2.PluginCommandSource(plugins));
|
|
346
439
|
}
|
|
347
440
|
} catch {
|
|
348
441
|
}
|
|
@@ -350,11 +443,11 @@ function initializeSession(props, permissionHandler) {
|
|
|
350
443
|
return { interactiveSession, registry, manager };
|
|
351
444
|
}
|
|
352
445
|
function useInteractiveSession(props) {
|
|
353
|
-
const [, forceRender] = (0,
|
|
354
|
-
const [permissionRequest, setPermissionRequest] = (0,
|
|
355
|
-
const permissionQueueRef = (0,
|
|
356
|
-
const processingRef = (0,
|
|
357
|
-
const processNextPermission = (0,
|
|
446
|
+
const [, forceRender] = (0, import_react2.useState)(0);
|
|
447
|
+
const [permissionRequest, setPermissionRequest] = (0, import_react2.useState)(null);
|
|
448
|
+
const permissionQueueRef = (0, import_react2.useRef)([]);
|
|
449
|
+
const processingRef = (0, import_react2.useRef)(false);
|
|
450
|
+
const processNextPermission = (0, import_react2.useCallback)(() => {
|
|
358
451
|
if (processingRef.current) return;
|
|
359
452
|
const next = permissionQueueRef.current[0];
|
|
360
453
|
if (!next) {
|
|
@@ -374,14 +467,14 @@ function useInteractiveSession(props) {
|
|
|
374
467
|
}
|
|
375
468
|
});
|
|
376
469
|
}, []);
|
|
377
|
-
const permissionHandler = (0,
|
|
470
|
+
const permissionHandler = (0, import_react2.useCallback)(
|
|
378
471
|
(toolName, toolArgs) => new Promise((resolve) => {
|
|
379
472
|
permissionQueueRef.current.push({ toolName, toolArgs, resolve });
|
|
380
473
|
processNextPermission();
|
|
381
474
|
}),
|
|
382
475
|
[processNextPermission]
|
|
383
476
|
);
|
|
384
|
-
const stateRef = (0,
|
|
477
|
+
const stateRef = (0, import_react2.useRef)(null);
|
|
385
478
|
if (stateRef.current === null) {
|
|
386
479
|
stateRef.current = initializeSession(props, permissionHandler);
|
|
387
480
|
}
|
|
@@ -393,7 +486,7 @@ function useInteractiveSession(props) {
|
|
|
393
486
|
manager.syncHistory(restored);
|
|
394
487
|
}
|
|
395
488
|
}
|
|
396
|
-
(0,
|
|
489
|
+
(0, import_react2.useEffect)(() => {
|
|
397
490
|
interactiveSession.on("text_delta", manager.onTextDelta);
|
|
398
491
|
interactiveSession.on("tool_start", manager.onToolStart);
|
|
399
492
|
interactiveSession.on("tool_end", manager.onToolEnd);
|
|
@@ -428,97 +521,18 @@ function useInteractiveSession(props) {
|
|
|
428
521
|
interactiveSession.off("error", manager.onError);
|
|
429
522
|
};
|
|
430
523
|
}, [interactiveSession, manager]);
|
|
431
|
-
(0,
|
|
524
|
+
(0, import_react2.useEffect)(() => {
|
|
432
525
|
manager.syncHistory(interactiveSession.getFullHistory());
|
|
433
526
|
if (!manager.isThinking) {
|
|
434
527
|
manager.setPendingPrompt(interactiveSession.getPendingPrompt());
|
|
435
528
|
}
|
|
436
529
|
}, [manager.isThinking, interactiveSession, manager]);
|
|
437
|
-
const handleSubmit = (
|
|
438
|
-
|
|
439
|
-
if (input.startsWith("/")) {
|
|
440
|
-
const parts = input.slice(1).split(/\s+/);
|
|
441
|
-
const cmd = parts[0]?.toLowerCase() ?? "";
|
|
442
|
-
const args = parts.slice(1).join(" ");
|
|
443
|
-
const result = await interactiveSession.executeCommand(cmd, args);
|
|
444
|
-
if (result) {
|
|
445
|
-
manager.addEntry((0, import_agent_core.messageToHistoryEntry)((0, import_agent_core.createSystemMessage)(result.message)));
|
|
446
|
-
const effects = interactiveSession;
|
|
447
|
-
if (result.data?.modelId) {
|
|
448
|
-
effects._pendingModelId = result.data.modelId;
|
|
449
|
-
return;
|
|
450
|
-
}
|
|
451
|
-
if (result.data?.language) {
|
|
452
|
-
effects._pendingLanguage = result.data.language;
|
|
453
|
-
return;
|
|
454
|
-
}
|
|
455
|
-
if (result.data?.resetRequested) {
|
|
456
|
-
effects._resetRequested = true;
|
|
457
|
-
return;
|
|
458
|
-
}
|
|
459
|
-
if (result.data?.triggerResumePicker) {
|
|
460
|
-
effects._triggerResumePicker = true;
|
|
461
|
-
return;
|
|
462
|
-
}
|
|
463
|
-
if (result.data?.name) {
|
|
464
|
-
effects._sessionName = result.data.name;
|
|
465
|
-
return;
|
|
466
|
-
}
|
|
467
|
-
const ctx = interactiveSession.getContextState();
|
|
468
|
-
manager.setContextState({
|
|
469
|
-
percentage: ctx.usedPercentage,
|
|
470
|
-
usedTokens: ctx.usedTokens,
|
|
471
|
-
maxTokens: ctx.maxTokens
|
|
472
|
-
});
|
|
473
|
-
return;
|
|
474
|
-
}
|
|
475
|
-
const skillCmd = registry.getCommands().find((c) => c.name === cmd && (c.source === "skill" || c.source === "plugin"));
|
|
476
|
-
if (skillCmd) {
|
|
477
|
-
manager.addEntry({
|
|
478
|
-
id: (0, import_node_crypto.randomUUID)(),
|
|
479
|
-
timestamp: /* @__PURE__ */ new Date(),
|
|
480
|
-
category: "event",
|
|
481
|
-
type: "skill-invocation",
|
|
482
|
-
data: {
|
|
483
|
-
skillName: cmd,
|
|
484
|
-
source: skillCmd.source,
|
|
485
|
-
message: `Invoking ${skillCmd.source}: ${cmd}`
|
|
486
|
-
}
|
|
487
|
-
});
|
|
488
|
-
const prompt = await (0, import_agent_sdk.buildSkillPrompt)(input, registry);
|
|
489
|
-
if (prompt) {
|
|
490
|
-
const qualifiedName = registry.resolveQualifiedName(cmd);
|
|
491
|
-
const hookInput = qualifiedName ? `/${qualifiedName}${input.slice(1 + cmd.length)}` : input;
|
|
492
|
-
await interactiveSession.submit(prompt, input, hookInput);
|
|
493
|
-
manager.setPendingPrompt(interactiveSession.getPendingPrompt());
|
|
494
|
-
return;
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
if (cmd === "exit") {
|
|
498
|
-
interactiveSession._exitRequested = true;
|
|
499
|
-
return;
|
|
500
|
-
}
|
|
501
|
-
if (cmd === "plugin") {
|
|
502
|
-
interactiveSession._triggerPluginTUI = true;
|
|
503
|
-
return;
|
|
504
|
-
}
|
|
505
|
-
manager.addEntry(
|
|
506
|
-
(0, import_agent_core.messageToHistoryEntry)(
|
|
507
|
-
(0, import_agent_core.createSystemMessage)(`Unknown command "/${cmd}". Type /help for help.`)
|
|
508
|
-
)
|
|
509
|
-
);
|
|
510
|
-
return;
|
|
511
|
-
}
|
|
512
|
-
await interactiveSession.submit(input);
|
|
513
|
-
manager.setPendingPrompt(interactiveSession.getPendingPrompt());
|
|
514
|
-
},
|
|
515
|
-
[interactiveSession, registry, manager]
|
|
516
|
-
);
|
|
517
|
-
const handleAbort = (0, import_react.useCallback)(() => {
|
|
530
|
+
const handleSubmit = useSlashRouting(interactiveSession, registry, manager);
|
|
531
|
+
const handleAbort = (0, import_react2.useCallback)(() => {
|
|
518
532
|
manager.setAborting(true);
|
|
519
533
|
interactiveSession.abort();
|
|
520
534
|
}, [interactiveSession, manager]);
|
|
521
|
-
const handleCancelQueue = (0,
|
|
535
|
+
const handleCancelQueue = (0, import_react2.useCallback)(() => {
|
|
522
536
|
interactiveSession.cancelQueue();
|
|
523
537
|
manager.setPendingPrompt(null);
|
|
524
538
|
}, [interactiveSession, manager]);
|
|
@@ -541,23 +555,23 @@ function useInteractiveSession(props) {
|
|
|
541
555
|
}
|
|
542
556
|
|
|
543
557
|
// src/ui/hooks/usePluginCallbacks.ts
|
|
544
|
-
var
|
|
558
|
+
var import_react3 = require("react");
|
|
545
559
|
var import_node_os3 = require("os");
|
|
546
560
|
var import_node_path4 = require("path");
|
|
547
|
-
var
|
|
561
|
+
var import_agent_sdk3 = require("@robota-sdk/agent-sdk");
|
|
548
562
|
function usePluginCallbacks(cwd) {
|
|
549
|
-
return (0,
|
|
563
|
+
return (0, import_react3.useMemo)(() => {
|
|
550
564
|
const home = (0, import_node_os3.homedir)();
|
|
551
565
|
const pluginsDir = (0, import_node_path4.join)(home, ".robota", "plugins");
|
|
552
566
|
const userSettingsPath = (0, import_node_path4.join)(home, ".robota", "settings.json");
|
|
553
|
-
const settingsStore = new
|
|
554
|
-
const marketplace = new
|
|
555
|
-
const installer = new
|
|
567
|
+
const settingsStore = new import_agent_sdk3.PluginSettingsStore(userSettingsPath);
|
|
568
|
+
const marketplace = new import_agent_sdk3.MarketplaceClient({ pluginsDir });
|
|
569
|
+
const installer = new import_agent_sdk3.BundlePluginInstaller({
|
|
556
570
|
pluginsDir,
|
|
557
571
|
settingsStore,
|
|
558
572
|
marketplaceClient: marketplace
|
|
559
573
|
});
|
|
560
|
-
const loader = new
|
|
574
|
+
const loader = new import_agent_sdk3.BundlePluginLoader(pluginsDir);
|
|
561
575
|
return {
|
|
562
576
|
listInstalled: async () => {
|
|
563
577
|
const plugins = await loader.loadAll();
|
|
@@ -596,7 +610,7 @@ function usePluginCallbacks(cwd) {
|
|
|
596
610
|
}
|
|
597
611
|
if (scope === "project") {
|
|
598
612
|
const projectPluginsDir = (0, import_node_path4.join)(cwd, ".robota", "plugins");
|
|
599
|
-
const projectInstaller = new
|
|
613
|
+
const projectInstaller = new import_agent_sdk3.BundlePluginInstaller({
|
|
600
614
|
pluginsDir: projectPluginsDir,
|
|
601
615
|
settingsStore,
|
|
602
616
|
marketplaceClient: marketplace
|
|
@@ -644,10 +658,128 @@ function usePluginCallbacks(cwd) {
|
|
|
644
658
|
}, [cwd]);
|
|
645
659
|
}
|
|
646
660
|
|
|
647
|
-
// src/ui/
|
|
648
|
-
var
|
|
649
|
-
var
|
|
661
|
+
// src/ui/hooks/useSideEffects.ts
|
|
662
|
+
var import_react4 = require("react");
|
|
663
|
+
var import_ink = require("ink");
|
|
650
664
|
var import_agent_core2 = require("@robota-sdk/agent-core");
|
|
665
|
+
var EXIT_DELAY_MS = 500;
|
|
666
|
+
function useSideEffects({
|
|
667
|
+
interactiveSession,
|
|
668
|
+
addEntry,
|
|
669
|
+
baseHandleSubmit,
|
|
670
|
+
setSessionName
|
|
671
|
+
}) {
|
|
672
|
+
const { exit } = (0, import_ink.useApp)();
|
|
673
|
+
const [pendingModelId, setPendingModelId] = (0, import_react4.useState)(null);
|
|
674
|
+
const pendingModelChangeRef = (0, import_react4.useRef)(null);
|
|
675
|
+
const [showPluginTUI, setShowPluginTUI] = (0, import_react4.useState)(false);
|
|
676
|
+
const [showSessionPicker, setShowSessionPicker] = (0, import_react4.useState)(false);
|
|
677
|
+
const handleSubmit = (0, import_react4.useCallback)(
|
|
678
|
+
async (input) => {
|
|
679
|
+
await baseHandleSubmit(input);
|
|
680
|
+
const sideEffects = interactiveSession;
|
|
681
|
+
if (sideEffects._pendingModelId) {
|
|
682
|
+
const modelId = sideEffects._pendingModelId;
|
|
683
|
+
delete sideEffects._pendingModelId;
|
|
684
|
+
pendingModelChangeRef.current = modelId;
|
|
685
|
+
setPendingModelId(modelId);
|
|
686
|
+
return;
|
|
687
|
+
}
|
|
688
|
+
if (sideEffects._pendingLanguage) {
|
|
689
|
+
const lang = sideEffects._pendingLanguage;
|
|
690
|
+
delete sideEffects._pendingLanguage;
|
|
691
|
+
const settingsPath = getUserSettingsPath();
|
|
692
|
+
const settings = readSettings(settingsPath);
|
|
693
|
+
settings.language = lang;
|
|
694
|
+
writeSettings(settingsPath, settings);
|
|
695
|
+
addEntry(
|
|
696
|
+
(0, import_agent_core2.messageToHistoryEntry)((0, import_agent_core2.createSystemMessage)(`Language set to "${lang}". Restarting...`))
|
|
697
|
+
);
|
|
698
|
+
setTimeout(() => exit(), EXIT_DELAY_MS);
|
|
699
|
+
return;
|
|
700
|
+
}
|
|
701
|
+
if (sideEffects._resetRequested) {
|
|
702
|
+
delete sideEffects._resetRequested;
|
|
703
|
+
const settingsPath = getUserSettingsPath();
|
|
704
|
+
if (deleteSettings(settingsPath)) {
|
|
705
|
+
addEntry(
|
|
706
|
+
(0, import_agent_core2.messageToHistoryEntry)((0, import_agent_core2.createSystemMessage)(`Deleted ${settingsPath}. Exiting...`))
|
|
707
|
+
);
|
|
708
|
+
} else {
|
|
709
|
+
addEntry((0, import_agent_core2.messageToHistoryEntry)((0, import_agent_core2.createSystemMessage)("No user settings found.")));
|
|
710
|
+
}
|
|
711
|
+
setTimeout(() => exit(), EXIT_DELAY_MS);
|
|
712
|
+
return;
|
|
713
|
+
}
|
|
714
|
+
if (sideEffects._exitRequested) {
|
|
715
|
+
delete sideEffects._exitRequested;
|
|
716
|
+
setTimeout(() => exit(), EXIT_DELAY_MS);
|
|
717
|
+
return;
|
|
718
|
+
}
|
|
719
|
+
if (sideEffects._triggerPluginTUI) {
|
|
720
|
+
delete sideEffects._triggerPluginTUI;
|
|
721
|
+
setShowPluginTUI(true);
|
|
722
|
+
return;
|
|
723
|
+
}
|
|
724
|
+
if (sideEffects._triggerResumePicker) {
|
|
725
|
+
delete sideEffects._triggerResumePicker;
|
|
726
|
+
setShowSessionPicker(true);
|
|
727
|
+
return;
|
|
728
|
+
}
|
|
729
|
+
if (sideEffects._sessionName) {
|
|
730
|
+
const name = sideEffects._sessionName;
|
|
731
|
+
delete sideEffects._sessionName;
|
|
732
|
+
interactiveSession.setName(name);
|
|
733
|
+
setSessionName(name);
|
|
734
|
+
return;
|
|
735
|
+
}
|
|
736
|
+
},
|
|
737
|
+
[interactiveSession, baseHandleSubmit, addEntry, exit, setSessionName]
|
|
738
|
+
);
|
|
739
|
+
const handleModelConfirm = (0, import_react4.useCallback)(
|
|
740
|
+
(index) => {
|
|
741
|
+
const modelId = pendingModelChangeRef.current;
|
|
742
|
+
setPendingModelId(null);
|
|
743
|
+
pendingModelChangeRef.current = null;
|
|
744
|
+
if (index === 0 && modelId) {
|
|
745
|
+
try {
|
|
746
|
+
const settingsPath = getUserSettingsPath();
|
|
747
|
+
updateModelInSettings(settingsPath, modelId);
|
|
748
|
+
addEntry(
|
|
749
|
+
(0, import_agent_core2.messageToHistoryEntry)(
|
|
750
|
+
(0, import_agent_core2.createSystemMessage)(`Model changed to ${(0, import_agent_core2.getModelName)(modelId)}. Restarting...`)
|
|
751
|
+
)
|
|
752
|
+
);
|
|
753
|
+
setTimeout(() => exit(), EXIT_DELAY_MS);
|
|
754
|
+
} catch (err) {
|
|
755
|
+
addEntry(
|
|
756
|
+
(0, import_agent_core2.messageToHistoryEntry)(
|
|
757
|
+
(0, import_agent_core2.createSystemMessage)(`Failed: ${err instanceof Error ? err.message : String(err)}`)
|
|
758
|
+
)
|
|
759
|
+
);
|
|
760
|
+
}
|
|
761
|
+
} else {
|
|
762
|
+
addEntry((0, import_agent_core2.messageToHistoryEntry)((0, import_agent_core2.createSystemMessage)("Model change cancelled.")));
|
|
763
|
+
}
|
|
764
|
+
},
|
|
765
|
+
[addEntry, exit]
|
|
766
|
+
);
|
|
767
|
+
return {
|
|
768
|
+
handleSubmit,
|
|
769
|
+
pendingModelId,
|
|
770
|
+
showPluginTUI,
|
|
771
|
+
showSessionPicker,
|
|
772
|
+
setPendingModelId,
|
|
773
|
+
setShowPluginTUI,
|
|
774
|
+
setShowSessionPicker,
|
|
775
|
+
handleModelConfirm
|
|
776
|
+
};
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
// src/ui/MessageList.tsx
|
|
780
|
+
var import_react5 = __toESM(require("react"), 1);
|
|
781
|
+
var import_ink3 = require("ink");
|
|
782
|
+
var import_agent_core3 = require("@robota-sdk/agent-core");
|
|
651
783
|
|
|
652
784
|
// src/ui/render-markdown.ts
|
|
653
785
|
var import_marked = require("marked");
|
|
@@ -661,7 +793,7 @@ function renderMarkdown(md) {
|
|
|
661
793
|
}
|
|
662
794
|
|
|
663
795
|
// src/ui/DiffBlock.tsx
|
|
664
|
-
var
|
|
796
|
+
var import_ink2 = require("ink");
|
|
665
797
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
666
798
|
var MAX_DIFF_LINES = 12;
|
|
667
799
|
var TRUNCATED_SHOW = 10;
|
|
@@ -671,15 +803,15 @@ function DiffBlock({ file, lines }) {
|
|
|
671
803
|
const remaining = lines.length - TRUNCATED_SHOW;
|
|
672
804
|
const maxLineNum = Math.max(...visible.map((l) => l.lineNumber), 0);
|
|
673
805
|
const numWidth = String(maxLineNum).length;
|
|
674
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
675
|
-
file && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
806
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink2.Box, { flexDirection: "column", marginLeft: 4, children: [
|
|
807
|
+
file && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink2.Text, { color: "white", dimColor: true, children: [
|
|
676
808
|
"\u2502 ",
|
|
677
809
|
file
|
|
678
810
|
] }),
|
|
679
811
|
visible.map((line, i) => {
|
|
680
812
|
const lineNum = String(line.lineNumber).padStart(numWidth, " ");
|
|
681
813
|
if (line.type === "context") {
|
|
682
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
814
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink2.Text, { color: "white", dimColor: true, children: [
|
|
683
815
|
"\u2502 ",
|
|
684
816
|
lineNum,
|
|
685
817
|
" ",
|
|
@@ -689,7 +821,7 @@ function DiffBlock({ file, lines }) {
|
|
|
689
821
|
const prefix = line.type === "remove" ? "-" : "+";
|
|
690
822
|
const bgColor = line.type === "remove" ? "#5c1a1a" : "#1a3d1a";
|
|
691
823
|
const fgColor = line.type === "remove" ? "#ff9999" : "#99ff99";
|
|
692
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
824
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink2.Text, { color: fgColor, backgroundColor: bgColor, children: [
|
|
693
825
|
"\u2502 ",
|
|
694
826
|
lineNum,
|
|
695
827
|
" ",
|
|
@@ -698,7 +830,7 @@ function DiffBlock({ file, lines }) {
|
|
|
698
830
|
line.text
|
|
699
831
|
] }, i);
|
|
700
832
|
}),
|
|
701
|
-
truncated && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
833
|
+
truncated && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink2.Text, { color: "white", dimColor: true, children: [
|
|
702
834
|
"\u2502 ... and ",
|
|
703
835
|
remaining,
|
|
704
836
|
" more lines"
|
|
@@ -711,29 +843,29 @@ var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
|
711
843
|
function RoleLabel({ role }) {
|
|
712
844
|
switch (role) {
|
|
713
845
|
case "user":
|
|
714
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
846
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ink3.Text, { color: "green", bold: true, children: [
|
|
715
847
|
"You:",
|
|
716
848
|
" "
|
|
717
849
|
] });
|
|
718
850
|
case "assistant":
|
|
719
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
851
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ink3.Text, { color: "cyan", bold: true, children: [
|
|
720
852
|
"Robota:",
|
|
721
853
|
" "
|
|
722
854
|
] });
|
|
723
855
|
case "system":
|
|
724
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
856
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ink3.Text, { color: "yellow", bold: true, children: [
|
|
725
857
|
"System:",
|
|
726
858
|
" "
|
|
727
859
|
] });
|
|
728
860
|
case "tool":
|
|
729
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
861
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ink3.Text, { color: "white", bold: true, children: [
|
|
730
862
|
"Tool:",
|
|
731
863
|
" "
|
|
732
864
|
] });
|
|
733
865
|
}
|
|
734
866
|
}
|
|
735
867
|
function ToolMessage({ message }) {
|
|
736
|
-
if (!(0,
|
|
868
|
+
if (!(0, import_agent_core3.isToolMessage)(message)) {
|
|
737
869
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, {});
|
|
738
870
|
}
|
|
739
871
|
const toolName = message.name;
|
|
@@ -747,21 +879,21 @@ function ToolMessage({ message }) {
|
|
|
747
879
|
} catch {
|
|
748
880
|
}
|
|
749
881
|
if (summaries) {
|
|
750
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
751
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
752
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
882
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ink3.Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
883
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ink3.Box, { children: [
|
|
884
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ink3.Text, { color: "white", bold: true, children: [
|
|
753
885
|
"Tool:",
|
|
754
886
|
" "
|
|
755
887
|
] }),
|
|
756
|
-
toolName && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
888
|
+
toolName && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ink3.Text, { color: "white", dimColor: true, children: [
|
|
757
889
|
"[",
|
|
758
890
|
toolName,
|
|
759
891
|
"]"
|
|
760
892
|
] })
|
|
761
893
|
] }),
|
|
762
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
763
|
-
summaries.map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
764
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
894
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ink3.Text, { children: " " }),
|
|
895
|
+
summaries.map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ink3.Box, { flexDirection: "column", children: [
|
|
896
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ink3.Text, { color: "green", children: [
|
|
765
897
|
" ",
|
|
766
898
|
"\u2713",
|
|
767
899
|
" ",
|
|
@@ -772,20 +904,20 @@ function ToolMessage({ message }) {
|
|
|
772
904
|
] });
|
|
773
905
|
}
|
|
774
906
|
const lines = content.split("\n").filter((l) => l.trim());
|
|
775
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
776
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
777
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
907
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ink3.Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
908
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ink3.Box, { children: [
|
|
909
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ink3.Text, { color: "white", bold: true, children: [
|
|
778
910
|
"Tool:",
|
|
779
911
|
" "
|
|
780
912
|
] }),
|
|
781
|
-
toolName && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
913
|
+
toolName && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ink3.Text, { color: "white", dimColor: true, children: [
|
|
782
914
|
"[",
|
|
783
915
|
toolName,
|
|
784
916
|
"]"
|
|
785
917
|
] })
|
|
786
918
|
] }),
|
|
787
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
788
|
-
lines.map((line, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
919
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ink3.Text, { children: " " }),
|
|
920
|
+
lines.map((line, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ink3.Text, { color: "green", children: [
|
|
789
921
|
" ",
|
|
790
922
|
"\u2713",
|
|
791
923
|
" ",
|
|
@@ -793,30 +925,30 @@ function ToolMessage({ message }) {
|
|
|
793
925
|
] }, i))
|
|
794
926
|
] });
|
|
795
927
|
}
|
|
796
|
-
var MessageItem =
|
|
928
|
+
var MessageItem = import_react5.default.memo(function MessageItem2({
|
|
797
929
|
message
|
|
798
930
|
}) {
|
|
799
|
-
if ((0,
|
|
931
|
+
if ((0, import_agent_core3.isToolMessage)(message)) {
|
|
800
932
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ToolMessage, { message });
|
|
801
933
|
}
|
|
802
934
|
const content = message.content ?? "";
|
|
803
935
|
const isInterrupted = message.state === "interrupted";
|
|
804
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
805
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
806
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
807
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
936
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ink3.Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
937
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ink3.Box, { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(RoleLabel, { role: message.role }) }),
|
|
938
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ink3.Text, { children: " " }),
|
|
939
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ink3.Box, { marginLeft: 2, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ink3.Text, { wrap: "wrap", children: (0, import_agent_core3.isAssistantMessage)(message) ? renderMarkdown(content + (isInterrupted ? "\n\n_(interrupted)_" : "")) : content }) })
|
|
808
940
|
] });
|
|
809
941
|
});
|
|
810
942
|
function ToolSummaryEntry({ entry }) {
|
|
811
943
|
const data = entry.data;
|
|
812
944
|
const lines = data?.summary?.split("\n") ?? [];
|
|
813
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
814
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
945
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ink3.Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
946
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ink3.Box, { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ink3.Text, { color: "white", bold: true, children: [
|
|
815
947
|
"Tool:",
|
|
816
948
|
" "
|
|
817
949
|
] }) }),
|
|
818
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
819
|
-
lines.map((line, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
950
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ink3.Text, { children: " " }),
|
|
951
|
+
lines.map((line, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ink3.Text, { color: "green", children: [
|
|
820
952
|
" ",
|
|
821
953
|
line
|
|
822
954
|
] }, i))
|
|
@@ -825,13 +957,13 @@ function ToolSummaryEntry({ entry }) {
|
|
|
825
957
|
function EventEntry({ entry }) {
|
|
826
958
|
const eventData = entry.data;
|
|
827
959
|
const eventMessage = typeof eventData?.message === "string" ? eventData.message : typeof eventData?.content === "string" ? eventData.content : entry.type;
|
|
828
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
829
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
960
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ink3.Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
961
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ink3.Box, { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ink3.Text, { color: "yellow", bold: true, children: [
|
|
830
962
|
"System:",
|
|
831
963
|
" "
|
|
832
964
|
] }) }),
|
|
833
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
834
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
965
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ink3.Text, { children: " " }),
|
|
966
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ink3.Box, { marginLeft: 2, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ink3.Text, { wrap: "wrap", children: eventMessage }) })
|
|
835
967
|
] });
|
|
836
968
|
}
|
|
837
969
|
function EntryItem({ entry }) {
|
|
@@ -848,12 +980,12 @@ function EntryItem({ entry }) {
|
|
|
848
980
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(EventEntry, { entry });
|
|
849
981
|
}
|
|
850
982
|
function MessageList({ history }) {
|
|
851
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
983
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ink3.Box, { flexDirection: "column", children: history.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(EntryItem, { entry }, entry.id)) });
|
|
852
984
|
}
|
|
853
985
|
|
|
854
986
|
// src/ui/StatusBar.tsx
|
|
855
|
-
var
|
|
856
|
-
var
|
|
987
|
+
var import_ink4 = require("ink");
|
|
988
|
+
var import_agent_core4 = require("@robota-sdk/agent-core");
|
|
857
989
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
858
990
|
var CONTEXT_YELLOW_THRESHOLD = 70;
|
|
859
991
|
var CONTEXT_RED_THRESHOLD = 90;
|
|
@@ -875,7 +1007,7 @@ function StatusBar({
|
|
|
875
1007
|
}) {
|
|
876
1008
|
const contextColor = getContextColor(contextPercentage);
|
|
877
1009
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
878
|
-
|
|
1010
|
+
import_ink4.Box,
|
|
879
1011
|
{
|
|
880
1012
|
borderStyle: "single",
|
|
881
1013
|
borderColor: "gray",
|
|
@@ -883,30 +1015,30 @@ function StatusBar({
|
|
|
883
1015
|
paddingRight: 1,
|
|
884
1016
|
justifyContent: "space-between",
|
|
885
1017
|
children: [
|
|
886
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
887
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1018
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ink4.Text, { children: [
|
|
1019
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ink4.Text, { color: "cyan", bold: true, children: "Mode:" }),
|
|
888
1020
|
" ",
|
|
889
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1021
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ink4.Text, { children: permissionMode }),
|
|
890
1022
|
sessionName && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
891
1023
|
" | ",
|
|
892
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1024
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ink4.Text, { color: "magenta", children: sessionName })
|
|
893
1025
|
] }),
|
|
894
1026
|
" | ",
|
|
895
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1027
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ink4.Text, { dimColor: true, children: modelName }),
|
|
896
1028
|
" | ",
|
|
897
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
1029
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ink4.Text, { color: contextColor, children: [
|
|
898
1030
|
"Context: ",
|
|
899
1031
|
Math.round(contextPercentage),
|
|
900
1032
|
"% (",
|
|
901
|
-
(0,
|
|
1033
|
+
(0, import_agent_core4.formatTokenCount)(contextUsedTokens),
|
|
902
1034
|
"/",
|
|
903
|
-
(0,
|
|
1035
|
+
(0, import_agent_core4.formatTokenCount)(contextMaxTokens),
|
|
904
1036
|
")"
|
|
905
1037
|
] })
|
|
906
1038
|
] }),
|
|
907
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
908
|
-
isThinking && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
909
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
1039
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ink4.Text, { children: [
|
|
1040
|
+
isThinking && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ink4.Text, { color: "yellow", children: "Thinking... " }),
|
|
1041
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_ink4.Text, { dimColor: true, children: [
|
|
910
1042
|
"msgs: ",
|
|
911
1043
|
messageCount
|
|
912
1044
|
] })
|
|
@@ -917,12 +1049,12 @@ function StatusBar({
|
|
|
917
1049
|
}
|
|
918
1050
|
|
|
919
1051
|
// src/ui/InputArea.tsx
|
|
920
|
-
var
|
|
921
|
-
var
|
|
1052
|
+
var import_react9 = require("react");
|
|
1053
|
+
var import_ink8 = require("ink");
|
|
922
1054
|
|
|
923
1055
|
// src/ui/CjkTextInput.tsx
|
|
924
|
-
var
|
|
925
|
-
var
|
|
1056
|
+
var import_react6 = require("react");
|
|
1057
|
+
var import_ink5 = require("ink");
|
|
926
1058
|
var import_chalk = __toESM(require("chalk"), 1);
|
|
927
1059
|
var import_string_width = __toESM(require("string-width"), 1);
|
|
928
1060
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
@@ -965,18 +1097,19 @@ function CjkTextInput({
|
|
|
965
1097
|
placeholder = "",
|
|
966
1098
|
focus = true,
|
|
967
1099
|
showCursor = true,
|
|
968
|
-
availableWidth
|
|
1100
|
+
availableWidth,
|
|
1101
|
+
cursorHint = null
|
|
969
1102
|
}) {
|
|
970
|
-
const valueRef = (0,
|
|
971
|
-
const cursorRef = (0,
|
|
972
|
-
const [, forceRender] = (0,
|
|
973
|
-
const isPastingRef = (0,
|
|
974
|
-
const pasteBufferRef = (0,
|
|
1103
|
+
const valueRef = (0, import_react6.useRef)(value);
|
|
1104
|
+
const cursorRef = (0, import_react6.useRef)(value.length);
|
|
1105
|
+
const [, forceRender] = (0, import_react6.useState)(0);
|
|
1106
|
+
const isPastingRef = (0, import_react6.useRef)(false);
|
|
1107
|
+
const pasteBufferRef = (0, import_react6.useRef)("");
|
|
975
1108
|
if (value !== valueRef.current) {
|
|
976
1109
|
valueRef.current = value;
|
|
977
|
-
cursorRef.current = value.length;
|
|
1110
|
+
cursorRef.current = cursorHint != null ? Math.min(cursorHint, value.length) : value.length;
|
|
978
1111
|
}
|
|
979
|
-
(0,
|
|
1112
|
+
(0, import_ink5.useInput)(
|
|
980
1113
|
(input, key) => {
|
|
981
1114
|
try {
|
|
982
1115
|
if (input === PASTE_START || input.startsWith(PASTE_START)) {
|
|
@@ -996,7 +1129,7 @@ function CjkTextInput({
|
|
|
996
1129
|
isPastingRef.current = false;
|
|
997
1130
|
if (text.length > 0) {
|
|
998
1131
|
if (text.includes("\n") && onPaste) {
|
|
999
|
-
onPaste(text);
|
|
1132
|
+
onPaste(text, cursorRef.current);
|
|
1000
1133
|
} else {
|
|
1001
1134
|
const printable2 = filterPrintable(text);
|
|
1002
1135
|
if (printable2.length > 0) {
|
|
@@ -1035,7 +1168,7 @@ function CjkTextInput({
|
|
|
1035
1168
|
return;
|
|
1036
1169
|
}
|
|
1037
1170
|
if (input.length > 1 && (input.includes("\n") || input.includes("\r")) && onPaste) {
|
|
1038
|
-
onPaste(input.replace(/\r\n?/g, "\n"));
|
|
1171
|
+
onPaste(input.replace(/\r\n?/g, "\n"), cursorRef.current);
|
|
1039
1172
|
return;
|
|
1040
1173
|
}
|
|
1041
1174
|
if (key.leftArrow) {
|
|
@@ -1073,7 +1206,7 @@ function CjkTextInput({
|
|
|
1073
1206
|
},
|
|
1074
1207
|
{ isActive: focus }
|
|
1075
1208
|
);
|
|
1076
|
-
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1209
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ink5.Text, { children: renderWithCursor(valueRef.current, cursorRef.current, placeholder, showCursor && focus) });
|
|
1077
1210
|
}
|
|
1078
1211
|
function renderWithCursor(value, cursorOffset, placeholder, showCursor) {
|
|
1079
1212
|
if (!showCursor) {
|
|
@@ -1098,30 +1231,30 @@ function renderWithCursor(value, cursorOffset, placeholder, showCursor) {
|
|
|
1098
1231
|
}
|
|
1099
1232
|
|
|
1100
1233
|
// src/ui/WaveText.tsx
|
|
1101
|
-
var
|
|
1102
|
-
var
|
|
1234
|
+
var import_react7 = require("react");
|
|
1235
|
+
var import_ink6 = require("ink");
|
|
1103
1236
|
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
1104
1237
|
var WAVE_COLORS = ["#666666", "#888888", "#aaaaaa", "#888888"];
|
|
1105
1238
|
var INTERVAL_MS = 400;
|
|
1106
1239
|
var CHARS_PER_GROUP = 4;
|
|
1107
1240
|
function WaveText({ text }) {
|
|
1108
|
-
const [tick, setTick] = (0,
|
|
1109
|
-
(0,
|
|
1241
|
+
const [tick, setTick] = (0, import_react7.useState)(0);
|
|
1242
|
+
(0, import_react7.useEffect)(() => {
|
|
1110
1243
|
const timer = setInterval(() => {
|
|
1111
1244
|
setTick((prev) => prev + 1);
|
|
1112
1245
|
}, INTERVAL_MS);
|
|
1113
1246
|
return () => clearInterval(timer);
|
|
1114
1247
|
}, []);
|
|
1115
1248
|
const chars = [...text];
|
|
1116
|
-
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1249
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_ink6.Text, { children: chars.map((char, i) => {
|
|
1117
1250
|
const group = Math.floor(i / CHARS_PER_GROUP);
|
|
1118
1251
|
const colorIndex = (tick + group) % WAVE_COLORS.length;
|
|
1119
|
-
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1252
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_ink6.Text, { color: WAVE_COLORS[colorIndex], children: char }, i);
|
|
1120
1253
|
}) });
|
|
1121
1254
|
}
|
|
1122
1255
|
|
|
1123
1256
|
// src/ui/SlashAutocomplete.tsx
|
|
1124
|
-
var
|
|
1257
|
+
var import_ink7 = require("ink");
|
|
1125
1258
|
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
1126
1259
|
var MAX_VISIBLE = 8;
|
|
1127
1260
|
function CommandRow(props) {
|
|
@@ -1129,7 +1262,7 @@ function CommandRow(props) {
|
|
|
1129
1262
|
const indicator = isSelected ? "\u25B8 " : " ";
|
|
1130
1263
|
const nameColor = isSelected ? "cyan" : void 0;
|
|
1131
1264
|
const dimmed = !isSelected;
|
|
1132
|
-
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1265
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_ink7.Box, { children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_ink7.Text, { color: nameColor, dimColor: dimmed, children: [
|
|
1133
1266
|
indicator,
|
|
1134
1267
|
showSlash ? `/${cmd.name} ${cmd.description}` : cmd.description
|
|
1135
1268
|
] }) });
|
|
@@ -1143,7 +1276,7 @@ function SlashAutocomplete({
|
|
|
1143
1276
|
if (!visible || commands.length === 0) return null;
|
|
1144
1277
|
const scrollOffset = computeScrollOffset(selectedIndex, commands.length);
|
|
1145
1278
|
const visibleCommands = commands.slice(scrollOffset, scrollOffset + MAX_VISIBLE);
|
|
1146
|
-
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1279
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_ink7.Box, { flexDirection: "column", borderStyle: "round", borderColor: "gray", paddingX: 1, children: visibleCommands.map((cmd, i) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1147
1280
|
CommandRow,
|
|
1148
1281
|
{
|
|
1149
1282
|
cmd,
|
|
@@ -1166,8 +1299,8 @@ function expandPasteLabels(text, store) {
|
|
|
1166
1299
|
return text.replace(PASTE_LABEL_RE, (_, id) => store.get(Number(id)) ?? "");
|
|
1167
1300
|
}
|
|
1168
1301
|
|
|
1169
|
-
// src/ui/
|
|
1170
|
-
var
|
|
1302
|
+
// src/ui/hooks/useAutocomplete.ts
|
|
1303
|
+
var import_react8 = __toESM(require("react"), 1);
|
|
1171
1304
|
function parseSlashInput(value) {
|
|
1172
1305
|
if (!value.startsWith("/")) return { isSlash: false, parentCommand: "", filter: "" };
|
|
1173
1306
|
const afterSlash = value.slice(1);
|
|
@@ -1178,16 +1311,16 @@ function parseSlashInput(value) {
|
|
|
1178
1311
|
return { isSlash: true, parentCommand: parent, filter: rest };
|
|
1179
1312
|
}
|
|
1180
1313
|
function useAutocomplete(value, registry) {
|
|
1181
|
-
const [selectedIndex, setSelectedIndex] = (0,
|
|
1182
|
-
const [dismissed, setDismissed] = (0,
|
|
1183
|
-
const prevValueRef =
|
|
1314
|
+
const [selectedIndex, setSelectedIndex] = (0, import_react8.useState)(0);
|
|
1315
|
+
const [dismissed, setDismissed] = (0, import_react8.useState)(false);
|
|
1316
|
+
const prevValueRef = import_react8.default.useRef(value);
|
|
1184
1317
|
if (prevValueRef.current !== value) {
|
|
1185
1318
|
prevValueRef.current = value;
|
|
1186
1319
|
if (dismissed) setDismissed(false);
|
|
1187
1320
|
}
|
|
1188
1321
|
const parsed = parseSlashInput(value);
|
|
1189
1322
|
const isSubcommandMode = parsed.isSlash && parsed.parentCommand.length > 0;
|
|
1190
|
-
const filteredCommands = (0,
|
|
1323
|
+
const filteredCommands = (0, import_react8.useMemo)(() => {
|
|
1191
1324
|
if (!registry || !parsed.isSlash || dismissed) return [];
|
|
1192
1325
|
if (isSubcommandMode) {
|
|
1193
1326
|
const subs = registry.getSubcommands(parsed.parentCommand);
|
|
@@ -1220,6 +1353,9 @@ function useAutocomplete(value, registry) {
|
|
|
1220
1353
|
}
|
|
1221
1354
|
};
|
|
1222
1355
|
}
|
|
1356
|
+
|
|
1357
|
+
// src/ui/InputArea.tsx
|
|
1358
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
1223
1359
|
var BORDER_HORIZONTAL = 2;
|
|
1224
1360
|
var PADDING_LEFT = 1;
|
|
1225
1361
|
var PROMPT_WIDTH = 2;
|
|
@@ -1233,12 +1369,13 @@ function InputArea({
|
|
|
1233
1369
|
registry,
|
|
1234
1370
|
sessionName
|
|
1235
1371
|
}) {
|
|
1236
|
-
const [value, setValue] = (0,
|
|
1237
|
-
const
|
|
1238
|
-
const
|
|
1372
|
+
const [value, setValue] = (0, import_react9.useState)("");
|
|
1373
|
+
const [cursorHint, setCursorHint] = (0, import_react9.useState)(null);
|
|
1374
|
+
const pasteStore = (0, import_react9.useRef)(/* @__PURE__ */ new Map());
|
|
1375
|
+
const { stdout } = (0, import_ink8.useStdout)();
|
|
1239
1376
|
const terminalColumns = stdout?.columns ?? 80;
|
|
1240
1377
|
const availableWidth = Math.max(1, terminalColumns - INPUT_AREA_OVERHEAD);
|
|
1241
|
-
const pasteIdRef = (0,
|
|
1378
|
+
const pasteIdRef = (0, import_react9.useRef)(0);
|
|
1242
1379
|
const {
|
|
1243
1380
|
showPopup,
|
|
1244
1381
|
filteredCommands,
|
|
@@ -1247,15 +1384,17 @@ function InputArea({
|
|
|
1247
1384
|
isSubcommandMode,
|
|
1248
1385
|
setShowPopup
|
|
1249
1386
|
} = useAutocomplete(value, registry);
|
|
1250
|
-
const handlePaste = (0,
|
|
1387
|
+
const handlePaste = (0, import_react9.useCallback)((text, cursorPosition) => {
|
|
1251
1388
|
pasteIdRef.current += 1;
|
|
1252
1389
|
const id = pasteIdRef.current;
|
|
1253
1390
|
pasteStore.current.set(id, text);
|
|
1254
1391
|
const lineCount = text.split("\n").length;
|
|
1255
1392
|
const label = `[Pasted text #${id} +${lineCount} lines]`;
|
|
1256
|
-
|
|
1393
|
+
const newCursorPos = cursorPosition + label.length;
|
|
1394
|
+
setCursorHint(newCursorPos);
|
|
1395
|
+
setValue((prev) => prev.slice(0, cursorPosition) + label + prev.slice(cursorPosition));
|
|
1257
1396
|
}, []);
|
|
1258
|
-
const tabCompleteCommand = (0,
|
|
1397
|
+
const tabCompleteCommand = (0, import_react9.useCallback)(
|
|
1259
1398
|
(cmd) => {
|
|
1260
1399
|
const parsed = parseSlashInput(value);
|
|
1261
1400
|
if (parsed.parentCommand) {
|
|
@@ -1271,7 +1410,7 @@ function InputArea({
|
|
|
1271
1410
|
},
|
|
1272
1411
|
[value, setSelectedIndex]
|
|
1273
1412
|
);
|
|
1274
|
-
const enterSelectCommand = (0,
|
|
1413
|
+
const enterSelectCommand = (0, import_react9.useCallback)(
|
|
1275
1414
|
(cmd) => {
|
|
1276
1415
|
const parsed = parseSlashInput(value);
|
|
1277
1416
|
if (parsed.parentCommand) {
|
|
@@ -1290,7 +1429,7 @@ function InputArea({
|
|
|
1290
1429
|
},
|
|
1291
1430
|
[value, onSubmit, setSelectedIndex]
|
|
1292
1431
|
);
|
|
1293
|
-
const handleSubmit = (0,
|
|
1432
|
+
const handleSubmit = (0, import_react9.useCallback)(
|
|
1294
1433
|
(text) => {
|
|
1295
1434
|
const trimmed = text.trim();
|
|
1296
1435
|
if (trimmed.length === 0) return;
|
|
@@ -1306,7 +1445,7 @@ function InputArea({
|
|
|
1306
1445
|
},
|
|
1307
1446
|
[showPopup, filteredCommands, selectedIndex, onSubmit, enterSelectCommand]
|
|
1308
1447
|
);
|
|
1309
|
-
(0,
|
|
1448
|
+
(0, import_ink8.useInput)(
|
|
1310
1449
|
(_input, key) => {
|
|
1311
1450
|
if (!showPopup) return;
|
|
1312
1451
|
if (key.upArrow) {
|
|
@@ -1322,7 +1461,7 @@ function InputArea({
|
|
|
1322
1461
|
},
|
|
1323
1462
|
{ isActive: showPopup && !isDisabled }
|
|
1324
1463
|
);
|
|
1325
|
-
(0,
|
|
1464
|
+
(0, import_ink8.useInput)(
|
|
1326
1465
|
(_input, key) => {
|
|
1327
1466
|
if ((key.backspace || key.delete) && pendingPrompt) {
|
|
1328
1467
|
onCancelQueue?.();
|
|
@@ -1341,7 +1480,7 @@ function InputArea({
|
|
|
1341
1480
|
}
|
|
1342
1481
|
return { left: "\u250C" + "\u2500".repeat(innerWidth), label: "", right: "\u2510" };
|
|
1343
1482
|
})();
|
|
1344
|
-
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
1483
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_ink8.Box, { flexDirection: "column", children: [
|
|
1345
1484
|
showPopup && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1346
1485
|
SlashAutocomplete,
|
|
1347
1486
|
{
|
|
@@ -1351,28 +1490,32 @@ function InputArea({
|
|
|
1351
1490
|
isSubcommandMode
|
|
1352
1491
|
}
|
|
1353
1492
|
),
|
|
1354
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
1493
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_ink8.Text, { color: borderColor, children: [
|
|
1355
1494
|
topBorder.left,
|
|
1356
|
-
topBorder.label ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1495
|
+
topBorder.label ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_ink8.Text, { backgroundColor: borderColor, color: "black", bold: true, children: topBorder.label }) : null,
|
|
1357
1496
|
topBorder.right
|
|
1358
1497
|
] }),
|
|
1359
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1498
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_ink8.Box, { borderStyle: "single", borderTop: false, borderColor, paddingLeft: 1, children: isAborting ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_ink8.Text, { color: "yellow", children: " Interrupting..." }) : pendingPrompt ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_ink8.Text, { color: "cyan", children: [
|
|
1360
1499
|
" ",
|
|
1361
1500
|
"Queued: ",
|
|
1362
1501
|
pendingPrompt.length > 50 ? pendingPrompt.slice(0, 47) + "..." : pendingPrompt,
|
|
1363
1502
|
" ",
|
|
1364
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1365
|
-
] }) : isDisabled ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(WaveText, { text: " Waiting for response... (ESC to interrupt)" }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
1366
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1503
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_ink8.Text, { dimColor: true, children: "(Backspace to cancel)" })
|
|
1504
|
+
] }) : isDisabled ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(WaveText, { text: " Waiting for response... (ESC to interrupt)" }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_ink8.Box, { children: [
|
|
1505
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_ink8.Text, { color: "green", bold: true, children: "> " }),
|
|
1367
1506
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1368
1507
|
CjkTextInput,
|
|
1369
1508
|
{
|
|
1370
1509
|
value,
|
|
1371
|
-
onChange:
|
|
1510
|
+
onChange: (v) => {
|
|
1511
|
+
setValue(v);
|
|
1512
|
+
setCursorHint(null);
|
|
1513
|
+
},
|
|
1372
1514
|
onSubmit: handleSubmit,
|
|
1373
1515
|
onPaste: handlePaste,
|
|
1374
1516
|
placeholder: "Type a message or /help",
|
|
1375
|
-
availableWidth
|
|
1517
|
+
availableWidth,
|
|
1518
|
+
cursorHint
|
|
1376
1519
|
}
|
|
1377
1520
|
)
|
|
1378
1521
|
] }) })
|
|
@@ -1380,17 +1523,17 @@ function InputArea({
|
|
|
1380
1523
|
}
|
|
1381
1524
|
|
|
1382
1525
|
// src/ui/ConfirmPrompt.tsx
|
|
1383
|
-
var
|
|
1384
|
-
var
|
|
1526
|
+
var import_react10 = require("react");
|
|
1527
|
+
var import_ink9 = require("ink");
|
|
1385
1528
|
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
1386
1529
|
function ConfirmPrompt({
|
|
1387
1530
|
message,
|
|
1388
1531
|
options = ["Yes", "No"],
|
|
1389
1532
|
onSelect
|
|
1390
1533
|
}) {
|
|
1391
|
-
const [selected, setSelected] = (0,
|
|
1392
|
-
const resolvedRef = (0,
|
|
1393
|
-
const doSelect = (0,
|
|
1534
|
+
const [selected, setSelected] = (0, import_react10.useState)(0);
|
|
1535
|
+
const resolvedRef = (0, import_react10.useRef)(false);
|
|
1536
|
+
const doSelect = (0, import_react10.useCallback)(
|
|
1394
1537
|
(index) => {
|
|
1395
1538
|
if (resolvedRef.current) return;
|
|
1396
1539
|
resolvedRef.current = true;
|
|
@@ -1398,7 +1541,7 @@ function ConfirmPrompt({
|
|
|
1398
1541
|
},
|
|
1399
1542
|
[onSelect]
|
|
1400
1543
|
);
|
|
1401
|
-
(0,
|
|
1544
|
+
(0, import_ink9.useInput)((input, key) => {
|
|
1402
1545
|
if (resolvedRef.current) return;
|
|
1403
1546
|
if (key.leftArrow || key.upArrow) {
|
|
1404
1547
|
setSelected((prev) => prev > 0 ? prev - 1 : prev);
|
|
@@ -1412,19 +1555,19 @@ function ConfirmPrompt({
|
|
|
1412
1555
|
doSelect(1);
|
|
1413
1556
|
}
|
|
1414
1557
|
});
|
|
1415
|
-
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
1416
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1417
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1558
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_ink9.Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
|
|
1559
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_ink9.Text, { color: "yellow", children: message }),
|
|
1560
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_ink9.Box, { marginTop: 1, children: options.map((opt, i) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_ink9.Box, { marginRight: 2, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_ink9.Text, { color: i === selected ? "cyan" : void 0, bold: i === selected, children: [
|
|
1418
1561
|
i === selected ? "> " : " ",
|
|
1419
1562
|
opt
|
|
1420
1563
|
] }) }, opt)) }),
|
|
1421
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1564
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_ink9.Text, { dimColor: true, children: " arrow keys to select, Enter to confirm" })
|
|
1422
1565
|
] });
|
|
1423
1566
|
}
|
|
1424
1567
|
|
|
1425
1568
|
// src/ui/PermissionPrompt.tsx
|
|
1426
|
-
var
|
|
1427
|
-
var
|
|
1569
|
+
var import_react11 = __toESM(require("react"), 1);
|
|
1570
|
+
var import_ink10 = require("ink");
|
|
1428
1571
|
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
1429
1572
|
var OPTIONS = ["Allow", "Allow always (this session)", "Deny"];
|
|
1430
1573
|
function formatArgs(args) {
|
|
@@ -1433,15 +1576,15 @@ function formatArgs(args) {
|
|
|
1433
1576
|
return entries.map(([k, v]) => `${k}: ${typeof v === "string" ? v : JSON.stringify(v)}`).join(", ");
|
|
1434
1577
|
}
|
|
1435
1578
|
function PermissionPrompt({ request }) {
|
|
1436
|
-
const [selected, setSelected] =
|
|
1437
|
-
const resolvedRef =
|
|
1438
|
-
const prevRequestRef =
|
|
1579
|
+
const [selected, setSelected] = import_react11.default.useState(0);
|
|
1580
|
+
const resolvedRef = import_react11.default.useRef(false);
|
|
1581
|
+
const prevRequestRef = import_react11.default.useRef(request);
|
|
1439
1582
|
if (prevRequestRef.current !== request) {
|
|
1440
1583
|
prevRequestRef.current = request;
|
|
1441
1584
|
resolvedRef.current = false;
|
|
1442
1585
|
setSelected(0);
|
|
1443
1586
|
}
|
|
1444
|
-
const doResolve =
|
|
1587
|
+
const doResolve = import_react11.default.useCallback(
|
|
1445
1588
|
(index) => {
|
|
1446
1589
|
if (resolvedRef.current) return;
|
|
1447
1590
|
resolvedRef.current = true;
|
|
@@ -1451,7 +1594,7 @@ function PermissionPrompt({ request }) {
|
|
|
1451
1594
|
},
|
|
1452
1595
|
[request]
|
|
1453
1596
|
);
|
|
1454
|
-
(0,
|
|
1597
|
+
(0, import_ink10.useInput)((input, key) => {
|
|
1455
1598
|
if (resolvedRef.current) return;
|
|
1456
1599
|
if (key.upArrow || key.leftArrow) {
|
|
1457
1600
|
setSelected((prev) => prev > 0 ? prev - 1 : prev);
|
|
@@ -1467,27 +1610,27 @@ function PermissionPrompt({ request }) {
|
|
|
1467
1610
|
doResolve(2);
|
|
1468
1611
|
}
|
|
1469
1612
|
});
|
|
1470
|
-
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
1471
|
-
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1472
|
-
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
1613
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_ink10.Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
|
|
1614
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_ink10.Text, { color: "yellow", bold: true, children: "[Permission Required]" }),
|
|
1615
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_ink10.Text, { children: [
|
|
1473
1616
|
"Tool:",
|
|
1474
1617
|
" ",
|
|
1475
|
-
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1618
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_ink10.Text, { color: "cyan", bold: true, children: request.toolName })
|
|
1476
1619
|
] }),
|
|
1477
|
-
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
1620
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_ink10.Text, { dimColor: true, children: [
|
|
1478
1621
|
" ",
|
|
1479
1622
|
formatArgs(request.toolArgs)
|
|
1480
1623
|
] }),
|
|
1481
|
-
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1624
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_ink10.Box, { marginTop: 1, children: OPTIONS.map((opt, i) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_ink10.Box, { marginRight: 2, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_ink10.Text, { color: i === selected ? "cyan" : void 0, bold: i === selected, children: [
|
|
1482
1625
|
i === selected ? "> " : " ",
|
|
1483
1626
|
opt
|
|
1484
1627
|
] }) }, opt)) }),
|
|
1485
|
-
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1628
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_ink10.Text, { dimColor: true, children: " left/right to select, Enter to confirm" })
|
|
1486
1629
|
] });
|
|
1487
1630
|
}
|
|
1488
1631
|
|
|
1489
1632
|
// src/ui/StreamingIndicator.tsx
|
|
1490
|
-
var
|
|
1633
|
+
var import_ink11 = require("ink");
|
|
1491
1634
|
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
1492
1635
|
function getToolStyle(t) {
|
|
1493
1636
|
if (t.isRunning) return { color: "yellow", icon: "\u27F3", strikethrough: false };
|
|
@@ -1501,14 +1644,14 @@ function StreamingIndicator({ text, activeTools }) {
|
|
|
1501
1644
|
if (!hasTools && !hasText) {
|
|
1502
1645
|
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_jsx_runtime10.Fragment, {});
|
|
1503
1646
|
}
|
|
1504
|
-
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
1505
|
-
hasTools && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
1506
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1507
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1647
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_ink11.Box, { flexDirection: "column", children: [
|
|
1648
|
+
hasTools && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_ink11.Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
1649
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_ink11.Text, { color: "white", bold: true, children: "Tools:" }),
|
|
1650
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_ink11.Text, { children: " " }),
|
|
1508
1651
|
activeTools.map((t, i) => {
|
|
1509
1652
|
const { color, icon, strikethrough } = getToolStyle(t);
|
|
1510
|
-
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
1511
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
1653
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_ink11.Box, { flexDirection: "column", children: [
|
|
1654
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_ink11.Text, { color, strikethrough, children: [
|
|
1512
1655
|
" ",
|
|
1513
1656
|
icon,
|
|
1514
1657
|
" ",
|
|
@@ -1521,20 +1664,20 @@ function StreamingIndicator({ text, activeTools }) {
|
|
|
1521
1664
|
] }, `${t.toolName}-${i}`);
|
|
1522
1665
|
})
|
|
1523
1666
|
] }),
|
|
1524
|
-
hasText && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
1525
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1526
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1527
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1667
|
+
hasText && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_ink11.Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
1668
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_ink11.Text, { color: "cyan", bold: true, children: "Robota:" }),
|
|
1669
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_ink11.Text, { children: " " }),
|
|
1670
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_ink11.Box, { marginLeft: 2, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_ink11.Text, { wrap: "wrap", children: renderMarkdown(text) }) })
|
|
1528
1671
|
] })
|
|
1529
1672
|
] });
|
|
1530
1673
|
}
|
|
1531
1674
|
|
|
1532
1675
|
// src/ui/PluginTUI.tsx
|
|
1533
|
-
var
|
|
1676
|
+
var import_react15 = require("react");
|
|
1534
1677
|
|
|
1535
1678
|
// src/ui/MenuSelect.tsx
|
|
1536
|
-
var
|
|
1537
|
-
var
|
|
1679
|
+
var import_react12 = require("react");
|
|
1680
|
+
var import_ink12 = require("ink");
|
|
1538
1681
|
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
1539
1682
|
function MenuSelect({
|
|
1540
1683
|
title,
|
|
@@ -1544,10 +1687,10 @@ function MenuSelect({
|
|
|
1544
1687
|
loading,
|
|
1545
1688
|
error
|
|
1546
1689
|
}) {
|
|
1547
|
-
const [selected, setSelected] = (0,
|
|
1548
|
-
const selectedRef = (0,
|
|
1549
|
-
const resolvedRef = (0,
|
|
1550
|
-
const doSelect = (0,
|
|
1690
|
+
const [selected, setSelected] = (0, import_react12.useState)(0);
|
|
1691
|
+
const selectedRef = (0, import_react12.useRef)(0);
|
|
1692
|
+
const resolvedRef = (0, import_react12.useRef)(false);
|
|
1693
|
+
const doSelect = (0, import_react12.useCallback)(
|
|
1551
1694
|
(index) => {
|
|
1552
1695
|
if (resolvedRef.current || items.length === 0) return;
|
|
1553
1696
|
resolvedRef.current = true;
|
|
@@ -1555,7 +1698,7 @@ function MenuSelect({
|
|
|
1555
1698
|
},
|
|
1556
1699
|
[items, onSelect]
|
|
1557
1700
|
);
|
|
1558
|
-
(0,
|
|
1701
|
+
(0, import_ink12.useInput)((input, key) => {
|
|
1559
1702
|
if (resolvedRef.current) return;
|
|
1560
1703
|
if (key.escape) {
|
|
1561
1704
|
resolvedRef.current = true;
|
|
@@ -1575,30 +1718,30 @@ function MenuSelect({
|
|
|
1575
1718
|
doSelect(selectedRef.current);
|
|
1576
1719
|
}
|
|
1577
1720
|
});
|
|
1578
|
-
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
1579
|
-
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1580
|
-
loading && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1581
|
-
error && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
1582
|
-
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1583
|
-
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1721
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_ink12.Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
|
|
1722
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_ink12.Text, { color: "yellow", bold: true, children: title }),
|
|
1723
|
+
loading && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_ink12.Box, { marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_ink12.Text, { dimColor: true, children: "Loading..." }) }),
|
|
1724
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_ink12.Box, { marginTop: 1, flexDirection: "column", children: [
|
|
1725
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_ink12.Text, { color: "red", children: error }),
|
|
1726
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_ink12.Text, { dimColor: true, children: "Press Esc to go back" })
|
|
1584
1727
|
] }),
|
|
1585
|
-
!loading && !error && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1586
|
-
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
1728
|
+
!loading && !error && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_ink12.Box, { flexDirection: "column", marginTop: 1, children: items.map((item, i) => /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_ink12.Box, { children: [
|
|
1729
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_ink12.Text, { color: i === selected ? "cyan" : void 0, bold: i === selected, children: [
|
|
1587
1730
|
i === selected ? "> " : " ",
|
|
1588
1731
|
item.label
|
|
1589
1732
|
] }),
|
|
1590
|
-
item.hint && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
1733
|
+
item.hint && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_ink12.Text, { dimColor: true, children: [
|
|
1591
1734
|
" ",
|
|
1592
1735
|
item.hint
|
|
1593
1736
|
] })
|
|
1594
1737
|
] }, item.value)) }),
|
|
1595
|
-
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1738
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_ink12.Text, { dimColor: true, children: loading || error ? "" : " \u2191\u2193 Navigate Enter Select Esc Back" })
|
|
1596
1739
|
] });
|
|
1597
1740
|
}
|
|
1598
1741
|
|
|
1599
1742
|
// src/ui/TextPrompt.tsx
|
|
1600
|
-
var
|
|
1601
|
-
var
|
|
1743
|
+
var import_react13 = require("react");
|
|
1744
|
+
var import_ink13 = require("ink");
|
|
1602
1745
|
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
1603
1746
|
function TextPrompt({
|
|
1604
1747
|
title,
|
|
@@ -1607,11 +1750,11 @@ function TextPrompt({
|
|
|
1607
1750
|
onCancel,
|
|
1608
1751
|
validate
|
|
1609
1752
|
}) {
|
|
1610
|
-
const [value, setValue] = (0,
|
|
1611
|
-
const [error, setError] = (0,
|
|
1612
|
-
const resolvedRef = (0,
|
|
1613
|
-
const valueRef = (0,
|
|
1614
|
-
const handleSubmit = (0,
|
|
1753
|
+
const [value, setValue] = (0, import_react13.useState)("");
|
|
1754
|
+
const [error, setError] = (0, import_react13.useState)();
|
|
1755
|
+
const resolvedRef = (0, import_react13.useRef)(false);
|
|
1756
|
+
const valueRef = (0, import_react13.useRef)("");
|
|
1757
|
+
const handleSubmit = (0, import_react13.useCallback)(() => {
|
|
1615
1758
|
if (resolvedRef.current) return;
|
|
1616
1759
|
const trimmed = valueRef.current.trim();
|
|
1617
1760
|
if (!trimmed) return;
|
|
@@ -1625,7 +1768,7 @@ function TextPrompt({
|
|
|
1625
1768
|
resolvedRef.current = true;
|
|
1626
1769
|
onSubmit(trimmed);
|
|
1627
1770
|
}, [validate, onSubmit]);
|
|
1628
|
-
(0,
|
|
1771
|
+
(0, import_ink13.useInput)((input, key) => {
|
|
1629
1772
|
if (resolvedRef.current) return;
|
|
1630
1773
|
if (key.escape) {
|
|
1631
1774
|
resolvedRef.current = true;
|
|
@@ -1648,15 +1791,15 @@ function TextPrompt({
|
|
|
1648
1791
|
setError(void 0);
|
|
1649
1792
|
}
|
|
1650
1793
|
});
|
|
1651
|
-
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
1652
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1653
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
1654
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1655
|
-
value ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1656
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1794
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_ink13.Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
|
|
1795
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_ink13.Text, { color: "yellow", bold: true, children: title }),
|
|
1796
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_ink13.Box, { marginTop: 1, children: [
|
|
1797
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_ink13.Text, { color: "cyan", children: "> " }),
|
|
1798
|
+
value ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_ink13.Text, { children: value }) : placeholder ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_ink13.Text, { dimColor: true, children: placeholder }) : null,
|
|
1799
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_ink13.Text, { color: "cyan", children: "\u2588" })
|
|
1657
1800
|
] }),
|
|
1658
|
-
error && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1659
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1801
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_ink13.Text, { color: "red", children: error }),
|
|
1802
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_ink13.Text, { dimColor: true, children: " Enter Submit Esc Cancel" })
|
|
1660
1803
|
] });
|
|
1661
1804
|
}
|
|
1662
1805
|
|
|
@@ -1752,61 +1895,16 @@ function handleInstalledActionSelect(value, pluginId, callbacks, nav) {
|
|
|
1752
1895
|
}
|
|
1753
1896
|
}
|
|
1754
1897
|
|
|
1755
|
-
// src/ui/
|
|
1756
|
-
var
|
|
1757
|
-
function
|
|
1758
|
-
const [
|
|
1759
|
-
const [
|
|
1760
|
-
const [
|
|
1761
|
-
|
|
1762
|
-
const [confirm, setConfirm] = (0, import_react11.useState)();
|
|
1763
|
-
const [refreshCounter, setRefreshCounter] = (0, import_react11.useState)(0);
|
|
1764
|
-
const current = stack[stack.length - 1] ?? { screen: "main" };
|
|
1765
|
-
const push = (0, import_react11.useCallback)((state) => {
|
|
1766
|
-
setStack((prev) => [...prev, state]);
|
|
1898
|
+
// src/ui/hooks/usePluginScreenData.ts
|
|
1899
|
+
var import_react14 = require("react");
|
|
1900
|
+
function usePluginScreenData(screen, marketplace, callbacks, refreshCounter, stackLength) {
|
|
1901
|
+
const [items, setItems] = (0, import_react14.useState)([]);
|
|
1902
|
+
const [loading, setLoading] = (0, import_react14.useState)(false);
|
|
1903
|
+
const [error, setError] = (0, import_react14.useState)();
|
|
1904
|
+
(0, import_react14.useEffect)(() => {
|
|
1767
1905
|
setItems([]);
|
|
1768
1906
|
setError(void 0);
|
|
1769
|
-
|
|
1770
|
-
const pop = (0, import_react11.useCallback)(() => {
|
|
1771
|
-
setStack((prev) => {
|
|
1772
|
-
if (prev.length <= 1) {
|
|
1773
|
-
onClose();
|
|
1774
|
-
return prev;
|
|
1775
|
-
}
|
|
1776
|
-
return prev.slice(0, -1);
|
|
1777
|
-
});
|
|
1778
|
-
setItems([]);
|
|
1779
|
-
setError(void 0);
|
|
1780
|
-
}, [onClose]);
|
|
1781
|
-
const popN = (0, import_react11.useCallback)(
|
|
1782
|
-
(n) => {
|
|
1783
|
-
setStack((prev) => {
|
|
1784
|
-
const next = prev.slice(0, Math.max(1, prev.length - n));
|
|
1785
|
-
if (next.length === 0) {
|
|
1786
|
-
onClose();
|
|
1787
|
-
return prev;
|
|
1788
|
-
}
|
|
1789
|
-
return next;
|
|
1790
|
-
});
|
|
1791
|
-
setItems([]);
|
|
1792
|
-
setError(void 0);
|
|
1793
|
-
},
|
|
1794
|
-
[onClose]
|
|
1795
|
-
);
|
|
1796
|
-
const notify = (0, import_react11.useCallback)(
|
|
1797
|
-
(content) => {
|
|
1798
|
-
addMessage?.({ role: "system", content });
|
|
1799
|
-
},
|
|
1800
|
-
[addMessage]
|
|
1801
|
-
);
|
|
1802
|
-
const refresh = (0, import_react11.useCallback)(() => {
|
|
1803
|
-
setItems([]);
|
|
1804
|
-
setRefreshCounter((c) => c + 1);
|
|
1805
|
-
}, []);
|
|
1806
|
-
const nav = { push, pop, popN, notify, setConfirm, refresh };
|
|
1807
|
-
(0, import_react11.useEffect)(() => {
|
|
1808
|
-
const screen2 = current.screen;
|
|
1809
|
-
if (screen2 === "marketplace-list") {
|
|
1907
|
+
if (screen === "marketplace-list") {
|
|
1810
1908
|
setLoading(true);
|
|
1811
1909
|
callbacks.marketplaceList().then((sources) => {
|
|
1812
1910
|
const baseItems = [{ label: "Add Marketplace", value: "__add__" }];
|
|
@@ -1821,10 +1919,10 @@ function PluginTUI({ callbacks, onClose, addMessage }) {
|
|
|
1821
1919
|
setError(err instanceof Error ? err.message : String(err));
|
|
1822
1920
|
setLoading(false);
|
|
1823
1921
|
});
|
|
1824
|
-
} else if (
|
|
1825
|
-
const
|
|
1922
|
+
} else if (screen === "marketplace-browse") {
|
|
1923
|
+
const mp = marketplace ?? "";
|
|
1826
1924
|
setLoading(true);
|
|
1827
|
-
callbacks.listAvailablePlugins(
|
|
1925
|
+
callbacks.listAvailablePlugins(mp).then((plugins) => {
|
|
1828
1926
|
setItems(
|
|
1829
1927
|
plugins.map((p) => ({
|
|
1830
1928
|
label: p.name,
|
|
@@ -1837,7 +1935,7 @@ function PluginTUI({ callbacks, onClose, addMessage }) {
|
|
|
1837
1935
|
setError(err instanceof Error ? err.message : String(err));
|
|
1838
1936
|
setLoading(false);
|
|
1839
1937
|
});
|
|
1840
|
-
} else if (
|
|
1938
|
+
} else if (screen === "installed-list") {
|
|
1841
1939
|
setLoading(true);
|
|
1842
1940
|
callbacks.listInstalled().then((plugins) => {
|
|
1843
1941
|
setItems(
|
|
@@ -1853,8 +1951,60 @@ function PluginTUI({ callbacks, onClose, addMessage }) {
|
|
|
1853
1951
|
setLoading(false);
|
|
1854
1952
|
});
|
|
1855
1953
|
}
|
|
1856
|
-
}, [
|
|
1857
|
-
|
|
1954
|
+
}, [stackLength, screen, marketplace, callbacks, refreshCounter]);
|
|
1955
|
+
return { items, loading, error };
|
|
1956
|
+
}
|
|
1957
|
+
|
|
1958
|
+
// src/ui/PluginTUI.tsx
|
|
1959
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
1960
|
+
function PluginTUI({ callbacks, onClose, addMessage }) {
|
|
1961
|
+
const [stack, setStack] = (0, import_react15.useState)([{ screen: "main" }]);
|
|
1962
|
+
const [confirm, setConfirm] = (0, import_react15.useState)();
|
|
1963
|
+
const [refreshCounter, setRefreshCounter] = (0, import_react15.useState)(0);
|
|
1964
|
+
const current = stack[stack.length - 1] ?? { screen: "main" };
|
|
1965
|
+
const push = (0, import_react15.useCallback)((state) => {
|
|
1966
|
+
setStack((prev) => [...prev, state]);
|
|
1967
|
+
}, []);
|
|
1968
|
+
const pop = (0, import_react15.useCallback)(() => {
|
|
1969
|
+
setStack((prev) => {
|
|
1970
|
+
if (prev.length <= 1) {
|
|
1971
|
+
onClose();
|
|
1972
|
+
return prev;
|
|
1973
|
+
}
|
|
1974
|
+
return prev.slice(0, -1);
|
|
1975
|
+
});
|
|
1976
|
+
}, [onClose]);
|
|
1977
|
+
const popN = (0, import_react15.useCallback)(
|
|
1978
|
+
(n) => {
|
|
1979
|
+
setStack((prev) => {
|
|
1980
|
+
const next = prev.slice(0, Math.max(1, prev.length - n));
|
|
1981
|
+
if (next.length === 0) {
|
|
1982
|
+
onClose();
|
|
1983
|
+
return prev;
|
|
1984
|
+
}
|
|
1985
|
+
return next;
|
|
1986
|
+
});
|
|
1987
|
+
},
|
|
1988
|
+
[onClose]
|
|
1989
|
+
);
|
|
1990
|
+
const notify = (0, import_react15.useCallback)(
|
|
1991
|
+
(content) => {
|
|
1992
|
+
addMessage?.({ role: "system", content });
|
|
1993
|
+
},
|
|
1994
|
+
[addMessage]
|
|
1995
|
+
);
|
|
1996
|
+
const refresh = (0, import_react15.useCallback)(() => {
|
|
1997
|
+
setRefreshCounter((c) => c + 1);
|
|
1998
|
+
}, []);
|
|
1999
|
+
const nav = { push, pop, popN, notify, setConfirm, refresh };
|
|
2000
|
+
const { items, loading, error } = usePluginScreenData(
|
|
2001
|
+
current.screen,
|
|
2002
|
+
current.context?.marketplace,
|
|
2003
|
+
callbacks,
|
|
2004
|
+
refreshCounter,
|
|
2005
|
+
stack.length
|
|
2006
|
+
);
|
|
2007
|
+
const handleSelect = (0, import_react15.useCallback)(
|
|
1858
2008
|
(value) => {
|
|
1859
2009
|
const screen2 = current.screen;
|
|
1860
2010
|
const ctx = current.context;
|
|
@@ -1872,7 +2022,7 @@ function PluginTUI({ callbacks, onClose, addMessage }) {
|
|
|
1872
2022
|
},
|
|
1873
2023
|
[current, items, callbacks, push, pop, popN, notify, setConfirm, refresh]
|
|
1874
2024
|
);
|
|
1875
|
-
const handleTextSubmit = (0,
|
|
2025
|
+
const handleTextSubmit = (0, import_react15.useCallback)(
|
|
1876
2026
|
(value) => {
|
|
1877
2027
|
if (current.screen === "marketplace-add") {
|
|
1878
2028
|
callbacks.marketplaceAdd(value).then((name) => {
|
|
@@ -1980,9 +2130,12 @@ function PluginTUI({ callbacks, onClose, addMessage }) {
|
|
|
1980
2130
|
);
|
|
1981
2131
|
}
|
|
1982
2132
|
|
|
2133
|
+
// src/ui/SessionPicker.tsx
|
|
2134
|
+
var import_ink15 = require("ink");
|
|
2135
|
+
|
|
1983
2136
|
// src/ui/ListPicker.tsx
|
|
1984
|
-
var
|
|
1985
|
-
var
|
|
2137
|
+
var import_react16 = require("react");
|
|
2138
|
+
var import_ink14 = require("ink");
|
|
1986
2139
|
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
1987
2140
|
var DEFAULT_MAX_VISIBLE = 3;
|
|
1988
2141
|
function ListPicker({
|
|
@@ -1992,11 +2145,11 @@ function ListPicker({
|
|
|
1992
2145
|
onCancel,
|
|
1993
2146
|
maxVisible = DEFAULT_MAX_VISIBLE
|
|
1994
2147
|
}) {
|
|
1995
|
-
const [selectedIndex, setSelectedIndex] = (0,
|
|
1996
|
-
const [scrollOffset, setScrollOffset] = (0,
|
|
1997
|
-
const selectedRef = (0,
|
|
1998
|
-
const resolvedRef = (0,
|
|
1999
|
-
(0,
|
|
2148
|
+
const [selectedIndex, setSelectedIndex] = (0, import_react16.useState)(0);
|
|
2149
|
+
const [scrollOffset, setScrollOffset] = (0, import_react16.useState)(0);
|
|
2150
|
+
const selectedRef = (0, import_react16.useRef)(0);
|
|
2151
|
+
const resolvedRef = (0, import_react16.useRef)(false);
|
|
2152
|
+
(0, import_ink14.useInput)((_input, key) => {
|
|
2000
2153
|
if (resolvedRef.current) return;
|
|
2001
2154
|
if (key.escape) {
|
|
2002
2155
|
resolvedRef.current = true;
|
|
@@ -2027,19 +2180,19 @@ function ListPicker({
|
|
|
2027
2180
|
}
|
|
2028
2181
|
});
|
|
2029
2182
|
if (items.length === 0) {
|
|
2030
|
-
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
2183
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_ink14.Box, {});
|
|
2031
2184
|
}
|
|
2032
2185
|
const visibleItems = items.slice(scrollOffset, scrollOffset + maxVisible);
|
|
2033
2186
|
const hasMore = scrollOffset + maxVisible < items.length;
|
|
2034
2187
|
const hasLess = scrollOffset > 0;
|
|
2035
|
-
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
2036
|
-
hasLess && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
2188
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_ink14.Box, { flexDirection: "column", children: [
|
|
2189
|
+
hasLess && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_ink14.Text, { dimColor: true, children: [
|
|
2037
2190
|
" \u2191 ",
|
|
2038
2191
|
scrollOffset,
|
|
2039
2192
|
" more above"
|
|
2040
2193
|
] }),
|
|
2041
|
-
visibleItems.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
2042
|
-
hasMore && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
2194
|
+
visibleItems.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_ink14.Box, { marginBottom: 1, children: renderItem(item, scrollOffset + index === selectedIndex) }, scrollOffset + index)),
|
|
2195
|
+
hasMore && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_ink14.Text, { dimColor: true, children: [
|
|
2043
2196
|
" \u2193 ",
|
|
2044
2197
|
items.length - scrollOffset - maxVisible,
|
|
2045
2198
|
" more below"
|
|
@@ -2047,13 +2200,62 @@ function ListPicker({
|
|
|
2047
2200
|
] });
|
|
2048
2201
|
}
|
|
2049
2202
|
|
|
2050
|
-
// src/ui/
|
|
2203
|
+
// src/ui/SessionPicker.tsx
|
|
2051
2204
|
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
2052
|
-
var EXIT_DELAY_MS = 500;
|
|
2053
2205
|
var SESSION_ID_DISPLAY_LENGTH = 8;
|
|
2206
|
+
function SessionPicker({
|
|
2207
|
+
sessionStore,
|
|
2208
|
+
cwd,
|
|
2209
|
+
onSelect,
|
|
2210
|
+
onCancel
|
|
2211
|
+
}) {
|
|
2212
|
+
const sessions = (sessionStore?.list() ?? []).filter((s) => s.cwd === cwd);
|
|
2213
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_ink15.Box, { flexDirection: "column", paddingX: 1, marginBottom: 1, children: [
|
|
2214
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_ink15.Text, { bold: true, color: "cyan", children: "Select a session to resume (ESC to cancel):" }),
|
|
2215
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
2216
|
+
ListPicker,
|
|
2217
|
+
{
|
|
2218
|
+
items: sessions,
|
|
2219
|
+
renderItem: (session, isSelected) => {
|
|
2220
|
+
const lastMsg = session.messages.slice().reverse().find((m) => {
|
|
2221
|
+
const msg = m;
|
|
2222
|
+
return msg.role === "assistant" && msg.content;
|
|
2223
|
+
});
|
|
2224
|
+
const rawPreview = lastMsg?.content?.replace(/[\n\r]+/g, " ").trim() ?? "";
|
|
2225
|
+
const preview = rawPreview ? rawPreview.slice(0, 60) + (rawPreview.length > 60 ? "..." : "") : "";
|
|
2226
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_ink15.Text, { children: [
|
|
2227
|
+
isSelected ? "> " : " ",
|
|
2228
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_ink15.Text, { bold: true, children: session.name ?? session.id.slice(0, SESSION_ID_DISPLAY_LENGTH) }),
|
|
2229
|
+
" ",
|
|
2230
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_ink15.Text, { dimColor: true, children: new Date(session.updatedAt).toLocaleString(void 0, {
|
|
2231
|
+
month: "short",
|
|
2232
|
+
day: "numeric",
|
|
2233
|
+
hour: "2-digit",
|
|
2234
|
+
minute: "2-digit"
|
|
2235
|
+
}) }),
|
|
2236
|
+
" ",
|
|
2237
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_ink15.Text, { dimColor: true, children: [
|
|
2238
|
+
"msgs: ",
|
|
2239
|
+
session.messages.length
|
|
2240
|
+
] }),
|
|
2241
|
+
preview ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
|
|
2242
|
+
"\n ",
|
|
2243
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_ink15.Text, { color: "gray", children: preview })
|
|
2244
|
+
] }) : null
|
|
2245
|
+
] });
|
|
2246
|
+
},
|
|
2247
|
+
onSelect: (session) => onSelect(session.id),
|
|
2248
|
+
onCancel
|
|
2249
|
+
}
|
|
2250
|
+
)
|
|
2251
|
+
] });
|
|
2252
|
+
}
|
|
2253
|
+
|
|
2254
|
+
// src/ui/App.tsx
|
|
2255
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
2054
2256
|
function App(props) {
|
|
2055
|
-
const [activeSessionId, setActiveSessionId] = (0,
|
|
2056
|
-
return /* @__PURE__ */ (0,
|
|
2257
|
+
const [activeSessionId, setActiveSessionId] = (0, import_react17.useState)(props.resumeSessionId);
|
|
2258
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2057
2259
|
AppInner,
|
|
2058
2260
|
{
|
|
2059
2261
|
...props,
|
|
@@ -2064,7 +2266,6 @@ function App(props) {
|
|
|
2064
2266
|
);
|
|
2065
2267
|
}
|
|
2066
2268
|
function AppInner(props) {
|
|
2067
|
-
const { exit } = (0, import_ink14.useApp)();
|
|
2068
2269
|
const cwd = props.cwd;
|
|
2069
2270
|
const {
|
|
2070
2271
|
interactiveSession,
|
|
@@ -2092,83 +2293,32 @@ function AppInner(props) {
|
|
|
2092
2293
|
sessionName: props.sessionName
|
|
2093
2294
|
});
|
|
2094
2295
|
const pluginCallbacks = usePluginCallbacks(cwd);
|
|
2095
|
-
const [
|
|
2096
|
-
const
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2296
|
+
const [sessionName, setSessionName] = (0, import_react17.useState)(props.sessionName);
|
|
2297
|
+
const {
|
|
2298
|
+
handleSubmit,
|
|
2299
|
+
pendingModelId,
|
|
2300
|
+
showPluginTUI,
|
|
2301
|
+
showSessionPicker,
|
|
2302
|
+
setShowPluginTUI,
|
|
2303
|
+
setShowSessionPicker,
|
|
2304
|
+
handleModelConfirm
|
|
2305
|
+
} = useSideEffects({
|
|
2306
|
+
interactiveSession,
|
|
2307
|
+
addEntry,
|
|
2308
|
+
baseHandleSubmit,
|
|
2309
|
+
setSessionName
|
|
2310
|
+
});
|
|
2311
|
+
(0, import_react17.useEffect)(() => {
|
|
2103
2312
|
const name = interactiveSession?.getName?.();
|
|
2104
2313
|
if (name && !sessionName) setSessionName(name);
|
|
2105
2314
|
}, [interactiveSession, sessionName]);
|
|
2106
|
-
(0,
|
|
2315
|
+
(0, import_react17.useEffect)(() => {
|
|
2107
2316
|
const title = sessionName ? `Robota \u2014 ${sessionName}` : "Robota";
|
|
2108
2317
|
process.stdout.write(`\x1B]0;${title}\x07`);
|
|
2109
2318
|
}, [sessionName]);
|
|
2110
|
-
|
|
2111
|
-
await baseHandleSubmit(input);
|
|
2112
|
-
const sideEffects = interactiveSession;
|
|
2113
|
-
if (sideEffects._pendingModelId) {
|
|
2114
|
-
const modelId = sideEffects._pendingModelId;
|
|
2115
|
-
delete sideEffects._pendingModelId;
|
|
2116
|
-
pendingModelChangeRef.current = modelId;
|
|
2117
|
-
setPendingModelId(modelId);
|
|
2118
|
-
return;
|
|
2119
|
-
}
|
|
2120
|
-
if (sideEffects._pendingLanguage) {
|
|
2121
|
-
const lang = sideEffects._pendingLanguage;
|
|
2122
|
-
delete sideEffects._pendingLanguage;
|
|
2123
|
-
const settingsPath = getUserSettingsPath();
|
|
2124
|
-
const settings = readSettings(settingsPath);
|
|
2125
|
-
settings.language = lang;
|
|
2126
|
-
writeSettings(settingsPath, settings);
|
|
2127
|
-
addEntry(
|
|
2128
|
-
(0, import_agent_core4.messageToHistoryEntry)((0, import_agent_core4.createSystemMessage)(`Language set to "${lang}". Restarting...`))
|
|
2129
|
-
);
|
|
2130
|
-
setTimeout(() => exit(), EXIT_DELAY_MS);
|
|
2131
|
-
return;
|
|
2132
|
-
}
|
|
2133
|
-
if (sideEffects._resetRequested) {
|
|
2134
|
-
delete sideEffects._resetRequested;
|
|
2135
|
-
const settingsPath = getUserSettingsPath();
|
|
2136
|
-
if (deleteSettings(settingsPath)) {
|
|
2137
|
-
addEntry((0, import_agent_core4.messageToHistoryEntry)((0, import_agent_core4.createSystemMessage)(`Deleted ${settingsPath}. Exiting...`)));
|
|
2138
|
-
} else {
|
|
2139
|
-
addEntry((0, import_agent_core4.messageToHistoryEntry)((0, import_agent_core4.createSystemMessage)("No user settings found.")));
|
|
2140
|
-
}
|
|
2141
|
-
setTimeout(() => exit(), EXIT_DELAY_MS);
|
|
2142
|
-
return;
|
|
2143
|
-
}
|
|
2144
|
-
if (sideEffects._exitRequested) {
|
|
2145
|
-
delete sideEffects._exitRequested;
|
|
2146
|
-
setTimeout(() => exit(), EXIT_DELAY_MS);
|
|
2147
|
-
return;
|
|
2148
|
-
}
|
|
2149
|
-
if (sideEffects._triggerPluginTUI) {
|
|
2150
|
-
delete sideEffects._triggerPluginTUI;
|
|
2151
|
-
setShowPluginTUI(true);
|
|
2152
|
-
return;
|
|
2153
|
-
}
|
|
2154
|
-
if (sideEffects._triggerResumePicker) {
|
|
2155
|
-
delete sideEffects._triggerResumePicker;
|
|
2156
|
-
setShowSessionPicker(true);
|
|
2157
|
-
return;
|
|
2158
|
-
}
|
|
2159
|
-
if (sideEffects._sessionName) {
|
|
2160
|
-
const name = sideEffects._sessionName;
|
|
2161
|
-
delete sideEffects._sessionName;
|
|
2162
|
-
interactiveSession.setName(name);
|
|
2163
|
-
setSessionName(name);
|
|
2164
|
-
return;
|
|
2165
|
-
}
|
|
2166
|
-
};
|
|
2167
|
-
(0, import_ink14.useInput)(
|
|
2319
|
+
(0, import_ink16.useInput)(
|
|
2168
2320
|
(_input, key) => {
|
|
2169
|
-
if (key.escape && isThinking)
|
|
2170
|
-
handleAbort();
|
|
2171
|
-
}
|
|
2321
|
+
if (key.escape && isThinking) handleAbort();
|
|
2172
2322
|
},
|
|
2173
2323
|
{ isActive: !permissionRequest && !showPluginTUI && !showSessionPicker }
|
|
2174
2324
|
);
|
|
@@ -2180,117 +2330,60 @@ function AppInner(props) {
|
|
|
2180
2330
|
sessionId = session.getSessionId();
|
|
2181
2331
|
} catch {
|
|
2182
2332
|
}
|
|
2183
|
-
return /* @__PURE__ */ (0,
|
|
2184
|
-
/* @__PURE__ */ (0,
|
|
2185
|
-
/* @__PURE__ */ (0,
|
|
2333
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_ink16.Box, { flexDirection: "column", children: [
|
|
2334
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_ink16.Box, { flexDirection: "column", paddingX: 1, marginBottom: 1, children: [
|
|
2335
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_ink16.Text, { color: "cyan", bold: true, children: `
|
|
2186
2336
|
____ ___ ____ ___ _____ _
|
|
2187
2337
|
| _ \\ / _ \\| __ ) / _ \\_ _|/ \\
|
|
2188
2338
|
| |_) | | | | _ \\| | | || | / _ \\
|
|
2189
2339
|
| _ <| |_| | |_) | |_| || |/ ___ \\
|
|
2190
2340
|
|_| \\_\\\\___/|____/ \\___/ |_/_/ \\_\\
|
|
2191
2341
|
` }),
|
|
2192
|
-
/* @__PURE__ */ (0,
|
|
2342
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_ink16.Text, { dimColor: true, children: [
|
|
2193
2343
|
" v",
|
|
2194
2344
|
props.version ?? "0.0.0"
|
|
2195
2345
|
] })
|
|
2196
2346
|
] }),
|
|
2197
|
-
/* @__PURE__ */ (0,
|
|
2198
|
-
/* @__PURE__ */ (0,
|
|
2199
|
-
(isThinking || activeTools.length > 0) && /* @__PURE__ */ (0,
|
|
2347
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_ink16.Box, { flexDirection: "column", paddingX: 1, flexGrow: 1, children: [
|
|
2348
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(MessageList, { history }),
|
|
2349
|
+
(isThinking || activeTools.length > 0) && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_ink16.Box, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(StreamingIndicator, { text: streamingText, activeTools }) })
|
|
2200
2350
|
] }),
|
|
2201
|
-
permissionRequest && /* @__PURE__ */ (0,
|
|
2202
|
-
pendingModelId && /* @__PURE__ */ (0,
|
|
2351
|
+
permissionRequest && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(PermissionPrompt, { request: permissionRequest }),
|
|
2352
|
+
pendingModelId && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2203
2353
|
ConfirmPrompt,
|
|
2204
2354
|
{
|
|
2205
|
-
message: `Change model to ${(0,
|
|
2206
|
-
onSelect:
|
|
2207
|
-
setPendingModelId(null);
|
|
2208
|
-
pendingModelChangeRef.current = null;
|
|
2209
|
-
if (index === 0) {
|
|
2210
|
-
try {
|
|
2211
|
-
const settingsPath = getUserSettingsPath();
|
|
2212
|
-
updateModelInSettings(settingsPath, pendingModelId);
|
|
2213
|
-
addEntry(
|
|
2214
|
-
(0, import_agent_core4.messageToHistoryEntry)(
|
|
2215
|
-
(0, import_agent_core4.createSystemMessage)(
|
|
2216
|
-
`Model changed to ${(0, import_agent_core4.getModelName)(pendingModelId)}. Restarting...`
|
|
2217
|
-
)
|
|
2218
|
-
)
|
|
2219
|
-
);
|
|
2220
|
-
setTimeout(() => exit(), EXIT_DELAY_MS);
|
|
2221
|
-
} catch (err) {
|
|
2222
|
-
addEntry(
|
|
2223
|
-
(0, import_agent_core4.messageToHistoryEntry)(
|
|
2224
|
-
(0, import_agent_core4.createSystemMessage)(
|
|
2225
|
-
`Failed: ${err instanceof Error ? err.message : String(err)}`
|
|
2226
|
-
)
|
|
2227
|
-
)
|
|
2228
|
-
);
|
|
2229
|
-
}
|
|
2230
|
-
} else {
|
|
2231
|
-
addEntry((0, import_agent_core4.messageToHistoryEntry)((0, import_agent_core4.createSystemMessage)("Model change cancelled.")));
|
|
2232
|
-
}
|
|
2233
|
-
}
|
|
2355
|
+
message: `Change model to ${(0, import_agent_core5.getModelName)(pendingModelId)}? This will restart the session.`,
|
|
2356
|
+
onSelect: handleModelConfirm
|
|
2234
2357
|
}
|
|
2235
2358
|
),
|
|
2236
|
-
showPluginTUI && /* @__PURE__ */ (0,
|
|
2359
|
+
showPluginTUI && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2237
2360
|
PluginTUI,
|
|
2238
2361
|
{
|
|
2239
2362
|
callbacks: pluginCallbacks,
|
|
2240
2363
|
onClose: () => setShowPluginTUI(false),
|
|
2241
|
-
addMessage: (msg) => addEntry((0,
|
|
2364
|
+
addMessage: (msg) => addEntry((0, import_agent_core5.messageToHistoryEntry)((0, import_agent_core5.createSystemMessage)(msg.content)))
|
|
2242
2365
|
}
|
|
2243
2366
|
),
|
|
2244
|
-
showSessionPicker && /* @__PURE__ */ (0,
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
const preview = rawPreview ? rawPreview.slice(0, 60) + (rawPreview.length > 60 ? "..." : "") : "";
|
|
2257
|
-
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_ink14.Text, { children: [
|
|
2258
|
-
isSelected ? "> " : " ",
|
|
2259
|
-
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_ink14.Text, { bold: true, children: session.name ?? session.id.slice(0, SESSION_ID_DISPLAY_LENGTH) }),
|
|
2260
|
-
" ",
|
|
2261
|
-
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_ink14.Text, { dimColor: true, children: new Date(session.updatedAt).toLocaleString(void 0, {
|
|
2262
|
-
month: "short",
|
|
2263
|
-
day: "numeric",
|
|
2264
|
-
hour: "2-digit",
|
|
2265
|
-
minute: "2-digit"
|
|
2266
|
-
}) }),
|
|
2267
|
-
" ",
|
|
2268
|
-
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_ink14.Text, { dimColor: true, children: [
|
|
2269
|
-
"msgs: ",
|
|
2270
|
-
session.messages.length
|
|
2271
|
-
] }),
|
|
2272
|
-
preview ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
|
|
2273
|
-
"\n ",
|
|
2274
|
-
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_ink14.Text, { color: "gray", children: preview })
|
|
2275
|
-
] }) : null
|
|
2276
|
-
] });
|
|
2277
|
-
},
|
|
2278
|
-
onSelect: (session) => {
|
|
2279
|
-
setShowSessionPicker(false);
|
|
2280
|
-
props.onSessionSwitch(session.id);
|
|
2281
|
-
},
|
|
2282
|
-
onCancel: () => {
|
|
2283
|
-
setShowSessionPicker(false);
|
|
2284
|
-
addEntry((0, import_agent_core4.messageToHistoryEntry)((0, import_agent_core4.createSystemMessage)("Session resume cancelled.")));
|
|
2285
|
-
}
|
|
2367
|
+
showSessionPicker && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2368
|
+
SessionPicker,
|
|
2369
|
+
{
|
|
2370
|
+
sessionStore: props.sessionStore,
|
|
2371
|
+
cwd: props.cwd,
|
|
2372
|
+
onSelect: (id) => {
|
|
2373
|
+
setShowSessionPicker(false);
|
|
2374
|
+
props.onSessionSwitch(id);
|
|
2375
|
+
},
|
|
2376
|
+
onCancel: () => {
|
|
2377
|
+
setShowSessionPicker(false);
|
|
2378
|
+
addEntry((0, import_agent_core5.messageToHistoryEntry)((0, import_agent_core5.createSystemMessage)("Session resume cancelled.")));
|
|
2286
2379
|
}
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
/* @__PURE__ */ (0,
|
|
2380
|
+
}
|
|
2381
|
+
),
|
|
2382
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2290
2383
|
StatusBar,
|
|
2291
2384
|
{
|
|
2292
2385
|
permissionMode,
|
|
2293
|
-
modelName: props.modelId ? (0,
|
|
2386
|
+
modelName: props.modelId ? (0, import_agent_core5.getModelName)(props.modelId) : "",
|
|
2294
2387
|
sessionId,
|
|
2295
2388
|
messageCount: history.length,
|
|
2296
2389
|
isThinking,
|
|
@@ -2300,7 +2393,7 @@ function AppInner(props) {
|
|
|
2300
2393
|
sessionName
|
|
2301
2394
|
}
|
|
2302
2395
|
),
|
|
2303
|
-
/* @__PURE__ */ (0,
|
|
2396
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2304
2397
|
InputArea,
|
|
2305
2398
|
{
|
|
2306
2399
|
onSubmit: handleSubmit,
|
|
@@ -2312,12 +2405,12 @@ function AppInner(props) {
|
|
|
2312
2405
|
sessionName
|
|
2313
2406
|
}
|
|
2314
2407
|
),
|
|
2315
|
-
/* @__PURE__ */ (0,
|
|
2408
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_ink16.Text, { children: " " })
|
|
2316
2409
|
] });
|
|
2317
2410
|
}
|
|
2318
2411
|
|
|
2319
2412
|
// src/ui/render.tsx
|
|
2320
|
-
var
|
|
2413
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
2321
2414
|
function renderApp(options) {
|
|
2322
2415
|
process.on("unhandledRejection", (reason) => {
|
|
2323
2416
|
process.stderr.write(`
|
|
@@ -2331,7 +2424,7 @@ function renderApp(options) {
|
|
|
2331
2424
|
if (process.stdin.isTTY && process.stdout.isTTY) {
|
|
2332
2425
|
process.stdout.write("\x1B[?2004h");
|
|
2333
2426
|
}
|
|
2334
|
-
const instance = (0,
|
|
2427
|
+
const instance = (0, import_ink17.render)(/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(App, { ...options }), {
|
|
2335
2428
|
exitOnCtrlC: true
|
|
2336
2429
|
});
|
|
2337
2430
|
instance.waitUntilExit().then(() => {
|
|
@@ -2536,7 +2629,7 @@ async function startCli() {
|
|
|
2536
2629
|
process.stderr.write("Print mode (-p) requires a prompt argument.\n");
|
|
2537
2630
|
process.exit(1);
|
|
2538
2631
|
}
|
|
2539
|
-
const session = new
|
|
2632
|
+
const session = new import_agent_sdk4.InteractiveSession({
|
|
2540
2633
|
cwd,
|
|
2541
2634
|
provider,
|
|
2542
2635
|
permissionMode: args.permissionMode ?? "bypassPermissions",
|