@robota-sdk/agent-cli 3.0.0-beta.24 → 3.0.0-beta.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/node/bin.cjs +684 -120
- package/dist/node/bin.js +1 -1
- package/dist/node/{chunk-AKNLV5UA.js → chunk-QTZS5QXJ.js} +659 -90
- package/dist/node/index.cjs +689 -125
- package/dist/node/index.js +1 -1
- package/package.json +3 -3
package/dist/node/index.cjs
CHANGED
|
@@ -30,21 +30,21 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
-
Session: () =>
|
|
34
|
-
SessionStore: () =>
|
|
35
|
-
TRUST_TO_MODE: () =>
|
|
36
|
-
query: () =>
|
|
33
|
+
Session: () => import_agent_sdk6.Session,
|
|
34
|
+
SessionStore: () => import_agent_sdk6.SessionStore,
|
|
35
|
+
TRUST_TO_MODE: () => import_agent_sdk6.TRUST_TO_MODE,
|
|
36
|
+
query: () => import_agent_sdk6.query,
|
|
37
37
|
startCli: () => startCli
|
|
38
38
|
});
|
|
39
39
|
module.exports = __toCommonJS(index_exports);
|
|
40
|
-
var
|
|
40
|
+
var import_agent_sdk6 = require("@robota-sdk/agent-sdk");
|
|
41
41
|
|
|
42
42
|
// src/cli.ts
|
|
43
43
|
var import_node_fs3 = require("fs");
|
|
44
|
-
var
|
|
44
|
+
var import_node_path5 = require("path");
|
|
45
45
|
var import_node_url = require("url");
|
|
46
|
-
var
|
|
47
|
-
var
|
|
46
|
+
var import_agent_sdk4 = require("@robota-sdk/agent-sdk");
|
|
47
|
+
var import_agent_sdk5 = require("@robota-sdk/agent-sdk");
|
|
48
48
|
|
|
49
49
|
// src/utils/cli-args.ts
|
|
50
50
|
var import_node_util = require("util");
|
|
@@ -182,7 +182,7 @@ var PrintTerminal = class {
|
|
|
182
182
|
var import_ink11 = require("ink");
|
|
183
183
|
|
|
184
184
|
// src/ui/App.tsx
|
|
185
|
-
var
|
|
185
|
+
var import_react12 = require("react");
|
|
186
186
|
var import_ink10 = require("ink");
|
|
187
187
|
var import_agent_core3 = require("@robota-sdk/agent-core");
|
|
188
188
|
|
|
@@ -190,7 +190,7 @@ var import_agent_core3 = require("@robota-sdk/agent-core");
|
|
|
190
190
|
var import_react = require("react");
|
|
191
191
|
var import_agent_sdk = require("@robota-sdk/agent-sdk");
|
|
192
192
|
var TOOL_ARG_DISPLAY_MAX = 80;
|
|
193
|
-
var
|
|
193
|
+
var TAIL_KEEP = 30;
|
|
194
194
|
var NOOP_TERMINAL = {
|
|
195
195
|
write: () => {
|
|
196
196
|
},
|
|
@@ -249,13 +249,17 @@ function useSession(props) {
|
|
|
249
249
|
if (event.toolArgs) {
|
|
250
250
|
const firstVal = Object.values(event.toolArgs)[0];
|
|
251
251
|
const raw = typeof firstVal === "string" ? firstVal : JSON.stringify(firstVal ?? "");
|
|
252
|
-
firstArg = raw.length > TOOL_ARG_DISPLAY_MAX ? raw.slice(0,
|
|
252
|
+
firstArg = raw.length > TOOL_ARG_DISPLAY_MAX ? raw.slice(0, TOOL_ARG_DISPLAY_MAX - TAIL_KEEP - 3) + "..." + raw.slice(-TAIL_KEEP) : raw;
|
|
253
253
|
}
|
|
254
|
-
setActiveTools((prev) => [
|
|
254
|
+
setActiveTools((prev) => [
|
|
255
|
+
...prev,
|
|
256
|
+
{ toolName: event.toolName, firstArg, isRunning: true }
|
|
257
|
+
]);
|
|
255
258
|
} else {
|
|
259
|
+
const result = event.denied ? "denied" : event.success === false ? "error" : "success";
|
|
256
260
|
setActiveTools(
|
|
257
261
|
(prev) => prev.map(
|
|
258
|
-
(t) => t.toolName === event.toolName && t.isRunning ? { ...t, isRunning: false } : t
|
|
262
|
+
(t) => t.toolName === event.toolName && t.isRunning ? { ...t, isRunning: false, result } : t
|
|
259
263
|
)
|
|
260
264
|
);
|
|
261
265
|
}
|
|
@@ -279,7 +283,13 @@ function useSession(props) {
|
|
|
279
283
|
setStreamingText("");
|
|
280
284
|
setActiveTools([]);
|
|
281
285
|
}, []);
|
|
282
|
-
return {
|
|
286
|
+
return {
|
|
287
|
+
session: sessionRef.current,
|
|
288
|
+
permissionRequest,
|
|
289
|
+
streamingText,
|
|
290
|
+
clearStreamingText,
|
|
291
|
+
activeTools
|
|
292
|
+
};
|
|
283
293
|
}
|
|
284
294
|
|
|
285
295
|
// src/ui/hooks/useMessages.ts
|
|
@@ -402,7 +412,122 @@ function handleReset(addMessage) {
|
|
|
402
412
|
}
|
|
403
413
|
return { handled: true, exitRequested: true };
|
|
404
414
|
}
|
|
405
|
-
async function
|
|
415
|
+
async function handlePluginCommand(args, addMessage, callbacks) {
|
|
416
|
+
const parts = args.trim().split(/\s+/);
|
|
417
|
+
const subcommand = parts[0] ?? "";
|
|
418
|
+
const subArgs = parts.slice(1).join(" ").trim();
|
|
419
|
+
try {
|
|
420
|
+
switch (subcommand) {
|
|
421
|
+
case "":
|
|
422
|
+
case void 0: {
|
|
423
|
+
const plugins = await callbacks.listInstalled();
|
|
424
|
+
if (plugins.length === 0) {
|
|
425
|
+
addMessage({ role: "system", content: "No plugins installed." });
|
|
426
|
+
} else {
|
|
427
|
+
const lines = plugins.map(
|
|
428
|
+
(p) => ` ${p.name} \u2014 ${p.description} [${p.enabled ? "enabled" : "disabled"}]`
|
|
429
|
+
);
|
|
430
|
+
addMessage({ role: "system", content: `Installed plugins:
|
|
431
|
+
${lines.join("\n")}` });
|
|
432
|
+
}
|
|
433
|
+
return { handled: true };
|
|
434
|
+
}
|
|
435
|
+
case "install": {
|
|
436
|
+
if (!subArgs) {
|
|
437
|
+
addMessage({ role: "system", content: "Usage: /plugin install <name>@<marketplace>" });
|
|
438
|
+
return { handled: true };
|
|
439
|
+
}
|
|
440
|
+
await callbacks.install(subArgs);
|
|
441
|
+
addMessage({ role: "system", content: `Installed plugin: ${subArgs}` });
|
|
442
|
+
return { handled: true };
|
|
443
|
+
}
|
|
444
|
+
case "uninstall": {
|
|
445
|
+
if (!subArgs) {
|
|
446
|
+
addMessage({ role: "system", content: "Usage: /plugin uninstall <name>@<marketplace>" });
|
|
447
|
+
return { handled: true };
|
|
448
|
+
}
|
|
449
|
+
await callbacks.uninstall(subArgs);
|
|
450
|
+
addMessage({ role: "system", content: `Uninstalled plugin: ${subArgs}` });
|
|
451
|
+
return { handled: true };
|
|
452
|
+
}
|
|
453
|
+
case "enable": {
|
|
454
|
+
if (!subArgs) {
|
|
455
|
+
addMessage({ role: "system", content: "Usage: /plugin enable <name>@<marketplace>" });
|
|
456
|
+
return { handled: true };
|
|
457
|
+
}
|
|
458
|
+
await callbacks.enable(subArgs);
|
|
459
|
+
addMessage({ role: "system", content: `Enabled plugin: ${subArgs}` });
|
|
460
|
+
return { handled: true };
|
|
461
|
+
}
|
|
462
|
+
case "disable": {
|
|
463
|
+
if (!subArgs) {
|
|
464
|
+
addMessage({ role: "system", content: "Usage: /plugin disable <name>@<marketplace>" });
|
|
465
|
+
return { handled: true };
|
|
466
|
+
}
|
|
467
|
+
await callbacks.disable(subArgs);
|
|
468
|
+
addMessage({ role: "system", content: `Disabled plugin: ${subArgs}` });
|
|
469
|
+
return { handled: true };
|
|
470
|
+
}
|
|
471
|
+
case "marketplace": {
|
|
472
|
+
const mpParts = subArgs.split(/\s+/);
|
|
473
|
+
const mpSubcommand = mpParts[0] ?? "";
|
|
474
|
+
const mpArgs = mpParts.slice(1).join(" ").trim();
|
|
475
|
+
if (mpSubcommand === "add" && mpArgs) {
|
|
476
|
+
const registeredName = await callbacks.marketplaceAdd(mpArgs);
|
|
477
|
+
addMessage({
|
|
478
|
+
role: "system",
|
|
479
|
+
content: `Added marketplace: "${registeredName}" (from ${mpArgs})
|
|
480
|
+
Install plugins with: /plugin install <name>@${registeredName}`
|
|
481
|
+
});
|
|
482
|
+
return { handled: true };
|
|
483
|
+
} else if (mpSubcommand === "remove" && mpArgs) {
|
|
484
|
+
await callbacks.marketplaceRemove(mpArgs);
|
|
485
|
+
addMessage({
|
|
486
|
+
role: "system",
|
|
487
|
+
content: `Removed marketplace "${mpArgs}" and uninstalled its plugins.`
|
|
488
|
+
});
|
|
489
|
+
return { handled: true };
|
|
490
|
+
} else if (mpSubcommand === "update" && mpArgs) {
|
|
491
|
+
await callbacks.marketplaceUpdate(mpArgs);
|
|
492
|
+
addMessage({
|
|
493
|
+
role: "system",
|
|
494
|
+
content: `Updated marketplace "${mpArgs}".`
|
|
495
|
+
});
|
|
496
|
+
return { handled: true };
|
|
497
|
+
} else if (mpSubcommand === "list") {
|
|
498
|
+
const sources = await callbacks.marketplaceList();
|
|
499
|
+
if (sources.length === 0) {
|
|
500
|
+
addMessage({ role: "system", content: "No marketplace sources configured." });
|
|
501
|
+
} else {
|
|
502
|
+
const lines = sources.map((s) => ` ${s.name} (${s.type})`);
|
|
503
|
+
addMessage({ role: "system", content: `Marketplace sources:
|
|
504
|
+
${lines.join("\n")}` });
|
|
505
|
+
}
|
|
506
|
+
return { handled: true };
|
|
507
|
+
} else {
|
|
508
|
+
addMessage({
|
|
509
|
+
role: "system",
|
|
510
|
+
content: "Usage: /plugin marketplace add <source> | remove <name> | update <name> | list"
|
|
511
|
+
});
|
|
512
|
+
return { handled: true };
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
default:
|
|
516
|
+
addMessage({ role: "system", content: `Unknown plugin subcommand: ${subcommand}` });
|
|
517
|
+
return { handled: true };
|
|
518
|
+
}
|
|
519
|
+
} catch (error) {
|
|
520
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
521
|
+
addMessage({ role: "system", content: `Plugin error: ${message}` });
|
|
522
|
+
return { handled: true };
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
async function handleReloadPlugins(addMessage, callbacks) {
|
|
526
|
+
await callbacks.reloadPlugins();
|
|
527
|
+
addMessage({ role: "system", content: "Plugins reload complete." });
|
|
528
|
+
return { handled: true };
|
|
529
|
+
}
|
|
530
|
+
async function executeSlashCommand(cmd, args, session, addMessage, clearMessages, registry, pluginCallbacks) {
|
|
406
531
|
switch (cmd) {
|
|
407
532
|
case "help":
|
|
408
533
|
return handleHelp(addMessage);
|
|
@@ -426,10 +551,22 @@ async function executeSlashCommand(cmd, args, session, addMessage, clearMessages
|
|
|
426
551
|
return handleReset(addMessage);
|
|
427
552
|
case "exit":
|
|
428
553
|
return { handled: true, exitRequested: true };
|
|
554
|
+
case "plugin":
|
|
555
|
+
if (pluginCallbacks) {
|
|
556
|
+
return handlePluginCommand(args, addMessage, pluginCallbacks);
|
|
557
|
+
}
|
|
558
|
+
addMessage({ role: "system", content: "Plugin management is not available." });
|
|
559
|
+
return { handled: true };
|
|
560
|
+
case "reload-plugins":
|
|
561
|
+
if (pluginCallbacks) {
|
|
562
|
+
return handleReloadPlugins(addMessage, pluginCallbacks);
|
|
563
|
+
}
|
|
564
|
+
addMessage({ role: "system", content: "Plugin management is not available." });
|
|
565
|
+
return { handled: true };
|
|
429
566
|
default: {
|
|
430
|
-
const
|
|
431
|
-
if (
|
|
432
|
-
addMessage({ role: "system", content: `Invoking
|
|
567
|
+
const dynamicCmd = registry.getCommands().find((c) => c.name === cmd && (c.source === "skill" || c.source === "plugin"));
|
|
568
|
+
if (dynamicCmd) {
|
|
569
|
+
addMessage({ role: "system", content: `Invoking ${dynamicCmd.source}: ${cmd}` });
|
|
433
570
|
return { handled: false };
|
|
434
571
|
}
|
|
435
572
|
addMessage({ role: "system", content: `Unknown command "/${cmd}". Type /help for help.` });
|
|
@@ -440,14 +577,22 @@ async function executeSlashCommand(cmd, args, session, addMessage, clearMessages
|
|
|
440
577
|
|
|
441
578
|
// src/ui/hooks/useSlashCommands.ts
|
|
442
579
|
var EXIT_DELAY_MS = 500;
|
|
443
|
-
function useSlashCommands(session, addMessage, setMessages, exit, registry, pendingModelChangeRef, setPendingModelId) {
|
|
580
|
+
function useSlashCommands(session, addMessage, setMessages, exit, registry, pendingModelChangeRef, setPendingModelId, pluginCallbacks) {
|
|
444
581
|
return (0, import_react3.useCallback)(
|
|
445
582
|
async (input) => {
|
|
446
583
|
const parts = input.slice(1).split(/\s+/);
|
|
447
584
|
const cmd = parts[0]?.toLowerCase() ?? "";
|
|
448
585
|
const args = parts.slice(1).join(" ");
|
|
449
586
|
const clearMessages = () => setMessages([]);
|
|
450
|
-
const result = await executeSlashCommand(
|
|
587
|
+
const result = await executeSlashCommand(
|
|
588
|
+
cmd,
|
|
589
|
+
args,
|
|
590
|
+
session,
|
|
591
|
+
addMessage,
|
|
592
|
+
clearMessages,
|
|
593
|
+
registry,
|
|
594
|
+
pluginCallbacks
|
|
595
|
+
);
|
|
451
596
|
if (result.pendingModelId) {
|
|
452
597
|
pendingModelChangeRef.current = result.pendingModelId;
|
|
453
598
|
setPendingModelId(result.pendingModelId);
|
|
@@ -457,7 +602,16 @@ function useSlashCommands(session, addMessage, setMessages, exit, registry, pend
|
|
|
457
602
|
}
|
|
458
603
|
return result.handled;
|
|
459
604
|
},
|
|
460
|
-
[
|
|
605
|
+
[
|
|
606
|
+
session,
|
|
607
|
+
addMessage,
|
|
608
|
+
setMessages,
|
|
609
|
+
exit,
|
|
610
|
+
registry,
|
|
611
|
+
pendingModelChangeRef,
|
|
612
|
+
setPendingModelId,
|
|
613
|
+
pluginCallbacks
|
|
614
|
+
]
|
|
461
615
|
);
|
|
462
616
|
}
|
|
463
617
|
|
|
@@ -466,7 +620,7 @@ var import_react4 = require("react");
|
|
|
466
620
|
|
|
467
621
|
// src/utils/tool-call-extractor.ts
|
|
468
622
|
var TOOL_ARG_MAX_LENGTH = 80;
|
|
469
|
-
var
|
|
623
|
+
var TAIL_KEEP2 = 30;
|
|
470
624
|
function extractToolCalls(history, startIndex) {
|
|
471
625
|
const lines = [];
|
|
472
626
|
for (let i = startIndex; i < history.length; i++) {
|
|
@@ -474,7 +628,7 @@ function extractToolCalls(history, startIndex) {
|
|
|
474
628
|
if (msg.role === "assistant" && msg.toolCalls) {
|
|
475
629
|
for (const tc of msg.toolCalls) {
|
|
476
630
|
const value = parseFirstArgValue(tc.function.arguments);
|
|
477
|
-
const truncated = value.length > TOOL_ARG_MAX_LENGTH ? value.slice(0,
|
|
631
|
+
const truncated = value.length > TOOL_ARG_MAX_LENGTH ? value.slice(0, TOOL_ARG_MAX_LENGTH - TAIL_KEEP2 - 3) + "..." + value.slice(-TAIL_KEEP2) : value;
|
|
478
632
|
lines.push(`${tc.function.name}(${truncated})`);
|
|
479
633
|
}
|
|
480
634
|
}
|
|
@@ -492,16 +646,60 @@ function parseFirstArgValue(argsJson) {
|
|
|
492
646
|
}
|
|
493
647
|
|
|
494
648
|
// src/utils/skill-prompt.ts
|
|
495
|
-
|
|
649
|
+
var import_node_child_process = require("child_process");
|
|
650
|
+
function substituteVariables(content, args, context) {
|
|
651
|
+
const argParts = args ? args.split(/\s+/) : [];
|
|
652
|
+
let result = content;
|
|
653
|
+
result = result.replace(/\$ARGUMENTS\[(\d+)]/g, (_match, index) => {
|
|
654
|
+
return argParts[Number(index)] ?? "";
|
|
655
|
+
});
|
|
656
|
+
result = result.replace(/\$ARGUMENTS/g, args);
|
|
657
|
+
result = result.replace(/\$(\d)(?!\d|\w|\[)/g, (_match, digit) => {
|
|
658
|
+
return argParts[Number(digit)] ?? "";
|
|
659
|
+
});
|
|
660
|
+
result = result.replace(/\$\{CLAUDE_SESSION_ID}/g, context?.sessionId ?? "");
|
|
661
|
+
result = result.replace(/\$\{CLAUDE_SKILL_DIR}/g, context?.skillDir ?? "");
|
|
662
|
+
return result;
|
|
663
|
+
}
|
|
664
|
+
async function preprocessShellCommands(content) {
|
|
665
|
+
const shellPattern = /!`([^`]+)`/g;
|
|
666
|
+
if (!shellPattern.test(content)) {
|
|
667
|
+
return content;
|
|
668
|
+
}
|
|
669
|
+
shellPattern.lastIndex = 0;
|
|
670
|
+
let result = content;
|
|
671
|
+
let match;
|
|
672
|
+
const matches = [];
|
|
673
|
+
while ((match = shellPattern.exec(content)) !== null) {
|
|
674
|
+
matches.push({ full: match[0], command: match[1] });
|
|
675
|
+
}
|
|
676
|
+
for (const { full, command } of matches) {
|
|
677
|
+
let output = "";
|
|
678
|
+
try {
|
|
679
|
+
output = (0, import_node_child_process.execSync)(command, {
|
|
680
|
+
timeout: 5e3,
|
|
681
|
+
encoding: "utf-8",
|
|
682
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
683
|
+
}).trimEnd();
|
|
684
|
+
} catch {
|
|
685
|
+
output = "";
|
|
686
|
+
}
|
|
687
|
+
result = result.replace(full, output);
|
|
688
|
+
}
|
|
689
|
+
return result;
|
|
690
|
+
}
|
|
691
|
+
async function buildSkillPrompt(input, registry, context) {
|
|
496
692
|
const parts = input.slice(1).split(/\s+/);
|
|
497
693
|
const cmd = parts[0]?.toLowerCase() ?? "";
|
|
498
|
-
const skillCmd = registry.getCommands().find((c) => c.name === cmd && c.source === "skill");
|
|
694
|
+
const skillCmd = registry.getCommands().find((c) => c.name === cmd && (c.source === "skill" || c.source === "plugin"));
|
|
499
695
|
if (!skillCmd) return null;
|
|
500
696
|
const args = parts.slice(1).join(" ").trim();
|
|
501
697
|
const userInstruction = args || skillCmd.description;
|
|
502
698
|
if (skillCmd.skillContent) {
|
|
699
|
+
let processed = await preprocessShellCommands(skillCmd.skillContent);
|
|
700
|
+
processed = substituteVariables(processed, args, context);
|
|
503
701
|
return `<skill name="${cmd}">
|
|
504
|
-
${
|
|
702
|
+
${processed}
|
|
505
703
|
</skill>
|
|
506
704
|
|
|
507
705
|
Execute the "${cmd}" skill: ${userInstruction}`;
|
|
@@ -514,12 +712,12 @@ function syncContextState(session, setter) {
|
|
|
514
712
|
const ctx = session.getContextState();
|
|
515
713
|
setter({ percentage: ctx.usedPercentage, usedTokens: ctx.usedTokens, maxTokens: ctx.maxTokens });
|
|
516
714
|
}
|
|
517
|
-
async function runSessionPrompt(prompt, session, addMessage, clearStreamingText, setIsThinking, setContextState) {
|
|
715
|
+
async function runSessionPrompt(prompt, session, addMessage, clearStreamingText, setIsThinking, setContextState, rawInput) {
|
|
518
716
|
setIsThinking(true);
|
|
519
717
|
clearStreamingText();
|
|
520
718
|
const historyBefore = session.getHistory().length;
|
|
521
719
|
try {
|
|
522
|
-
const response = await session.run(prompt);
|
|
720
|
+
const response = await session.run(prompt, rawInput);
|
|
523
721
|
clearStreamingText();
|
|
524
722
|
const history = session.getHistory();
|
|
525
723
|
const toolLines = extractToolCalls(
|
|
@@ -527,7 +725,11 @@ async function runSessionPrompt(prompt, session, addMessage, clearStreamingText,
|
|
|
527
725
|
historyBefore
|
|
528
726
|
);
|
|
529
727
|
if (toolLines.length > 0) {
|
|
530
|
-
addMessage({
|
|
728
|
+
addMessage({
|
|
729
|
+
role: "tool",
|
|
730
|
+
content: toolLines.join("\n"),
|
|
731
|
+
toolName: `${toolLines.length} tools`
|
|
732
|
+
});
|
|
531
733
|
}
|
|
532
734
|
addMessage({ role: "assistant", content: response || "(empty response)" });
|
|
533
735
|
syncContextState(session, setContextState);
|
|
@@ -552,19 +754,48 @@ function useSubmitHandler(session, addMessage, handleSlashCommand, clearStreamin
|
|
|
552
754
|
syncContextState(session, setContextState);
|
|
553
755
|
return;
|
|
554
756
|
}
|
|
555
|
-
const prompt = buildSkillPrompt(input, registry);
|
|
757
|
+
const prompt = await buildSkillPrompt(input, registry);
|
|
556
758
|
if (!prompt) return;
|
|
557
|
-
|
|
759
|
+
const cmdName = input.slice(1).split(/\s+/)[0]?.toLowerCase() ?? "";
|
|
760
|
+
const qualifiedName = registry.resolveQualifiedName(cmdName);
|
|
761
|
+
const hookInput = qualifiedName ? `/${qualifiedName}${input.slice(1 + cmdName.length)}` : input;
|
|
762
|
+
return runSessionPrompt(
|
|
763
|
+
prompt,
|
|
764
|
+
session,
|
|
765
|
+
addMessage,
|
|
766
|
+
clearStreamingText,
|
|
767
|
+
setIsThinking,
|
|
768
|
+
setContextState,
|
|
769
|
+
hookInput
|
|
770
|
+
);
|
|
558
771
|
}
|
|
559
772
|
addMessage({ role: "user", content: input });
|
|
560
|
-
return runSessionPrompt(
|
|
773
|
+
return runSessionPrompt(
|
|
774
|
+
input,
|
|
775
|
+
session,
|
|
776
|
+
addMessage,
|
|
777
|
+
clearStreamingText,
|
|
778
|
+
setIsThinking,
|
|
779
|
+
setContextState
|
|
780
|
+
);
|
|
561
781
|
},
|
|
562
|
-
[
|
|
782
|
+
[
|
|
783
|
+
session,
|
|
784
|
+
addMessage,
|
|
785
|
+
handleSlashCommand,
|
|
786
|
+
clearStreamingText,
|
|
787
|
+
setIsThinking,
|
|
788
|
+
setContextState,
|
|
789
|
+
registry
|
|
790
|
+
]
|
|
563
791
|
);
|
|
564
792
|
}
|
|
565
793
|
|
|
566
794
|
// src/ui/hooks/useCommandRegistry.ts
|
|
567
795
|
var import_react5 = require("react");
|
|
796
|
+
var import_node_os2 = require("os");
|
|
797
|
+
var import_node_path3 = require("path");
|
|
798
|
+
var import_agent_sdk2 = require("@robota-sdk/agent-sdk");
|
|
568
799
|
|
|
569
800
|
// src/commands/command-registry.ts
|
|
570
801
|
var CommandRegistry = class {
|
|
@@ -582,6 +813,14 @@ var CommandRegistry = class {
|
|
|
582
813
|
const lower = filter.toLowerCase();
|
|
583
814
|
return all.filter((cmd) => cmd.name.toLowerCase().startsWith(lower));
|
|
584
815
|
}
|
|
816
|
+
/** Resolve a short name to its fully qualified plugin:name form */
|
|
817
|
+
resolveQualifiedName(shortName) {
|
|
818
|
+
const matches = this.getCommands().filter(
|
|
819
|
+
(c) => c.source === "plugin" && c.name.includes(":") && c.name.endsWith(`:${shortName}`)
|
|
820
|
+
);
|
|
821
|
+
if (matches.length !== 1) return null;
|
|
822
|
+
return matches[0].name;
|
|
823
|
+
}
|
|
585
824
|
/** Get subcommands for a specific command */
|
|
586
825
|
getSubcommands(commandName) {
|
|
587
826
|
const lower = commandName.toLowerCase();
|
|
@@ -648,6 +887,23 @@ function createBuiltinCommands() {
|
|
|
648
887
|
{ name: "cost", description: "Show session info", source: "builtin" },
|
|
649
888
|
{ name: "context", description: "Context window info", source: "builtin" },
|
|
650
889
|
{ name: "permissions", description: "Permission rules", source: "builtin" },
|
|
890
|
+
{
|
|
891
|
+
name: "plugin",
|
|
892
|
+
description: "Manage plugins",
|
|
893
|
+
source: "builtin",
|
|
894
|
+
subcommands: [
|
|
895
|
+
{ name: "install", description: "Install a plugin (name@marketplace)", source: "builtin" },
|
|
896
|
+
{
|
|
897
|
+
name: "uninstall",
|
|
898
|
+
description: "Uninstall a plugin (name@marketplace)",
|
|
899
|
+
source: "builtin"
|
|
900
|
+
},
|
|
901
|
+
{ name: "enable", description: "Enable a plugin (name@marketplace)", source: "builtin" },
|
|
902
|
+
{ name: "disable", description: "Disable a plugin (name@marketplace)", source: "builtin" },
|
|
903
|
+
{ name: "marketplace", description: "Manage marketplace sources", source: "builtin" }
|
|
904
|
+
]
|
|
905
|
+
},
|
|
906
|
+
{ name: "reload-plugins", description: "Reload all plugin resources", source: "builtin" },
|
|
651
907
|
{ name: "reset", description: "Delete settings and exit", source: "builtin" },
|
|
652
908
|
{ name: "exit", description: "Exit CLI", source: "builtin" }
|
|
653
909
|
];
|
|
@@ -667,25 +923,50 @@ var BuiltinCommandSource = class {
|
|
|
667
923
|
var import_node_fs2 = require("fs");
|
|
668
924
|
var import_node_path2 = require("path");
|
|
669
925
|
var import_node_os = require("os");
|
|
926
|
+
var BOOLEAN_KEYS = /* @__PURE__ */ new Set(["disable-model-invocation", "user-invocable"]);
|
|
927
|
+
var LIST_KEYS = /* @__PURE__ */ new Set(["allowed-tools"]);
|
|
928
|
+
function kebabToCamel(key) {
|
|
929
|
+
return key.replace(/-([a-z])/g, (_match, letter) => letter.toUpperCase());
|
|
930
|
+
}
|
|
670
931
|
function parseFrontmatter(content) {
|
|
671
932
|
const lines = content.split("\n");
|
|
672
933
|
if (lines[0]?.trim() !== "---") return null;
|
|
673
|
-
|
|
674
|
-
let description = "";
|
|
934
|
+
const result = {};
|
|
675
935
|
for (let i = 1; i < lines.length; i++) {
|
|
676
936
|
const line = lines[i];
|
|
677
937
|
if (line.trim() === "---") break;
|
|
678
|
-
const
|
|
679
|
-
if (
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
938
|
+
const match = line.match(/^([a-z][a-z0-9-]*):\s*(.+)/);
|
|
939
|
+
if (!match) continue;
|
|
940
|
+
const key = match[1];
|
|
941
|
+
const rawValue = match[2].trim();
|
|
942
|
+
const camelKey = kebabToCamel(key);
|
|
943
|
+
if (BOOLEAN_KEYS.has(key)) {
|
|
944
|
+
result[camelKey] = rawValue === "true";
|
|
945
|
+
} else if (LIST_KEYS.has(key)) {
|
|
946
|
+
result[camelKey] = rawValue.split(",").map((s) => s.trim());
|
|
947
|
+
} else {
|
|
948
|
+
result[camelKey] = rawValue;
|
|
686
949
|
}
|
|
687
950
|
}
|
|
688
|
-
return
|
|
951
|
+
return Object.keys(result).length > 0 ? result : null;
|
|
952
|
+
}
|
|
953
|
+
function buildCommand(frontmatter, content, fallbackName) {
|
|
954
|
+
const cmd = {
|
|
955
|
+
name: frontmatter?.name ?? fallbackName,
|
|
956
|
+
description: frontmatter?.description ?? `Skill: ${fallbackName}`,
|
|
957
|
+
source: "skill",
|
|
958
|
+
skillContent: content
|
|
959
|
+
};
|
|
960
|
+
if (frontmatter?.argumentHint !== void 0) cmd.argumentHint = frontmatter.argumentHint;
|
|
961
|
+
if (frontmatter?.disableModelInvocation !== void 0)
|
|
962
|
+
cmd.disableModelInvocation = frontmatter.disableModelInvocation;
|
|
963
|
+
if (frontmatter?.userInvocable !== void 0) cmd.userInvocable = frontmatter.userInvocable;
|
|
964
|
+
if (frontmatter?.allowedTools !== void 0) cmd.allowedTools = frontmatter.allowedTools;
|
|
965
|
+
if (frontmatter?.model !== void 0) cmd.model = frontmatter.model;
|
|
966
|
+
if (frontmatter?.effort !== void 0) cmd.effort = frontmatter.effort;
|
|
967
|
+
if (frontmatter?.context !== void 0) cmd.context = frontmatter.context;
|
|
968
|
+
if (frontmatter?.agent !== void 0) cmd.agent = frontmatter.agent;
|
|
969
|
+
return cmd;
|
|
689
970
|
}
|
|
690
971
|
function scanSkillsDir(skillsDir) {
|
|
691
972
|
if (!(0, import_node_fs2.existsSync)(skillsDir)) return [];
|
|
@@ -697,48 +978,246 @@ function scanSkillsDir(skillsDir) {
|
|
|
697
978
|
if (!(0, import_node_fs2.existsSync)(skillFile)) continue;
|
|
698
979
|
const content = (0, import_node_fs2.readFileSync)(skillFile, "utf-8");
|
|
699
980
|
const frontmatter = parseFrontmatter(content);
|
|
700
|
-
commands.push(
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
981
|
+
commands.push(buildCommand(frontmatter, content, entry.name));
|
|
982
|
+
}
|
|
983
|
+
return commands;
|
|
984
|
+
}
|
|
985
|
+
function scanCommandsDir(commandsDir) {
|
|
986
|
+
if (!(0, import_node_fs2.existsSync)(commandsDir)) return [];
|
|
987
|
+
const commands = [];
|
|
988
|
+
const entries = (0, import_node_fs2.readdirSync)(commandsDir, { withFileTypes: true });
|
|
989
|
+
for (const entry of entries) {
|
|
990
|
+
if (!entry.isFile() || !entry.name.endsWith(".md")) continue;
|
|
991
|
+
const filePath = (0, import_node_path2.join)(commandsDir, entry.name);
|
|
992
|
+
const content = (0, import_node_fs2.readFileSync)(filePath, "utf-8");
|
|
993
|
+
const frontmatter = parseFrontmatter(content);
|
|
994
|
+
const fallbackName = (0, import_node_path2.basename)(entry.name, ".md");
|
|
995
|
+
commands.push(buildCommand(frontmatter, content, fallbackName));
|
|
706
996
|
}
|
|
707
997
|
return commands;
|
|
708
998
|
}
|
|
709
999
|
var SkillCommandSource = class {
|
|
710
1000
|
name = "skill";
|
|
711
1001
|
cwd;
|
|
1002
|
+
home;
|
|
712
1003
|
cachedCommands = null;
|
|
713
|
-
constructor(cwd) {
|
|
1004
|
+
constructor(cwd, home) {
|
|
714
1005
|
this.cwd = cwd;
|
|
1006
|
+
this.home = home ?? (0, import_node_os.homedir)();
|
|
715
1007
|
}
|
|
716
1008
|
getCommands() {
|
|
717
1009
|
if (this.cachedCommands) return this.cachedCommands;
|
|
718
|
-
const
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
1010
|
+
const sources = [
|
|
1011
|
+
scanSkillsDir((0, import_node_path2.join)(this.cwd, ".claude", "skills")),
|
|
1012
|
+
// 1. project .claude/skills
|
|
1013
|
+
scanCommandsDir((0, import_node_path2.join)(this.cwd, ".claude", "commands")),
|
|
1014
|
+
// 2. project .claude/commands (legacy)
|
|
1015
|
+
scanSkillsDir((0, import_node_path2.join)(this.home, ".robota", "skills")),
|
|
1016
|
+
// 3. user ~/.robota/skills
|
|
1017
|
+
scanSkillsDir((0, import_node_path2.join)(this.cwd, ".agents", "skills"))
|
|
1018
|
+
// 4. project .agents/skills
|
|
1019
|
+
];
|
|
1020
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1021
|
+
const merged = [];
|
|
1022
|
+
for (const commands of sources) {
|
|
1023
|
+
for (const cmd of commands) {
|
|
1024
|
+
if (!seen.has(cmd.name)) {
|
|
1025
|
+
seen.add(cmd.name);
|
|
1026
|
+
merged.push(cmd);
|
|
1027
|
+
}
|
|
725
1028
|
}
|
|
726
1029
|
}
|
|
727
1030
|
this.cachedCommands = merged;
|
|
728
1031
|
return this.cachedCommands;
|
|
729
1032
|
}
|
|
1033
|
+
/** Get skills that models can invoke (excludes disableModelInvocation: true) */
|
|
1034
|
+
getModelInvocableSkills() {
|
|
1035
|
+
return this.getCommands().filter((cmd) => cmd.disableModelInvocation !== true);
|
|
1036
|
+
}
|
|
1037
|
+
/** Get skills that users can invoke (excludes userInvocable: false) */
|
|
1038
|
+
getUserInvocableSkills() {
|
|
1039
|
+
return this.getCommands().filter((cmd) => cmd.userInvocable !== false);
|
|
1040
|
+
}
|
|
1041
|
+
};
|
|
1042
|
+
|
|
1043
|
+
// src/commands/plugin-source.ts
|
|
1044
|
+
var PluginCommandSource = class {
|
|
1045
|
+
name = "plugin";
|
|
1046
|
+
plugins;
|
|
1047
|
+
constructor(plugins) {
|
|
1048
|
+
this.plugins = plugins;
|
|
1049
|
+
}
|
|
1050
|
+
getCommands() {
|
|
1051
|
+
const commands = [];
|
|
1052
|
+
for (const plugin of this.plugins) {
|
|
1053
|
+
for (const skill of plugin.skills) {
|
|
1054
|
+
const baseName = skill.name.includes("@") ? skill.name.split("@")[0] : skill.name;
|
|
1055
|
+
commands.push({
|
|
1056
|
+
name: baseName,
|
|
1057
|
+
description: `(${plugin.manifest.name}) ${skill.description}`,
|
|
1058
|
+
source: "plugin",
|
|
1059
|
+
skillContent: skill.skillContent,
|
|
1060
|
+
pluginDir: plugin.pluginDir
|
|
1061
|
+
});
|
|
1062
|
+
}
|
|
1063
|
+
for (const cmd of plugin.commands) {
|
|
1064
|
+
commands.push({
|
|
1065
|
+
name: cmd.name,
|
|
1066
|
+
description: cmd.description,
|
|
1067
|
+
source: "plugin",
|
|
1068
|
+
skillContent: cmd.skillContent,
|
|
1069
|
+
pluginDir: plugin.pluginDir
|
|
1070
|
+
});
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
return commands;
|
|
1074
|
+
}
|
|
730
1075
|
};
|
|
731
1076
|
|
|
732
1077
|
// src/ui/hooks/useCommandRegistry.ts
|
|
1078
|
+
function buildPluginEnv(plugin) {
|
|
1079
|
+
const dataDir = (0, import_node_path3.join)((0, import_node_path3.dirname)((0, import_node_path3.dirname)(plugin.pluginDir)), "data", plugin.manifest.name);
|
|
1080
|
+
return {
|
|
1081
|
+
CLAUDE_PLUGIN_ROOT: plugin.pluginDir,
|
|
1082
|
+
CLAUDE_PLUGIN_PATH: plugin.pluginDir,
|
|
1083
|
+
CLAUDE_PLUGIN_DATA: dataDir
|
|
1084
|
+
};
|
|
1085
|
+
}
|
|
1086
|
+
function mergePluginHooks(plugins) {
|
|
1087
|
+
const merged = {};
|
|
1088
|
+
for (const plugin of plugins) {
|
|
1089
|
+
const hooksObj = plugin.hooks;
|
|
1090
|
+
if (!hooksObj) continue;
|
|
1091
|
+
const pluginEnv = buildPluginEnv(plugin);
|
|
1092
|
+
const innerHooks = hooksObj.hooks ?? hooksObj;
|
|
1093
|
+
for (const [event, groups] of Object.entries(innerHooks)) {
|
|
1094
|
+
if (!Array.isArray(groups)) continue;
|
|
1095
|
+
if (!merged[event]) merged[event] = [];
|
|
1096
|
+
const resolved = groups.map((group) => {
|
|
1097
|
+
const resolved2 = resolvePluginRoot(group, plugin.pluginDir);
|
|
1098
|
+
if (typeof resolved2 === "object" && resolved2 !== null) {
|
|
1099
|
+
resolved2.env = pluginEnv;
|
|
1100
|
+
}
|
|
1101
|
+
return resolved2;
|
|
1102
|
+
});
|
|
1103
|
+
merged[event].push(...resolved);
|
|
1104
|
+
}
|
|
1105
|
+
}
|
|
1106
|
+
return merged;
|
|
1107
|
+
}
|
|
1108
|
+
function resolvePluginRoot(group, pluginDir) {
|
|
1109
|
+
if (typeof group !== "object" || group === null) return group;
|
|
1110
|
+
const obj = group;
|
|
1111
|
+
if (Array.isArray(obj.hooks)) {
|
|
1112
|
+
return {
|
|
1113
|
+
...obj,
|
|
1114
|
+
hooks: obj.hooks.map((h) => {
|
|
1115
|
+
if (typeof h !== "object" || h === null) return h;
|
|
1116
|
+
const hook = h;
|
|
1117
|
+
if (typeof hook.command === "string") {
|
|
1118
|
+
return {
|
|
1119
|
+
...hook,
|
|
1120
|
+
command: hook.command.replace(/\$\{CLAUDE_PLUGIN_ROOT\}/g, pluginDir)
|
|
1121
|
+
};
|
|
1122
|
+
}
|
|
1123
|
+
return hook;
|
|
1124
|
+
})
|
|
1125
|
+
};
|
|
1126
|
+
}
|
|
1127
|
+
return group;
|
|
1128
|
+
}
|
|
733
1129
|
function useCommandRegistry(cwd) {
|
|
734
|
-
const
|
|
735
|
-
if (
|
|
1130
|
+
const resultRef = (0, import_react5.useRef)(null);
|
|
1131
|
+
if (resultRef.current === null) {
|
|
736
1132
|
const registry = new CommandRegistry();
|
|
737
1133
|
registry.addSource(new BuiltinCommandSource());
|
|
738
1134
|
registry.addSource(new SkillCommandSource(cwd));
|
|
739
|
-
|
|
1135
|
+
let pluginHooks = {};
|
|
1136
|
+
const pluginsDir = (0, import_node_path3.join)((0, import_node_os2.homedir)(), ".robota", "plugins");
|
|
1137
|
+
const loader = new import_agent_sdk2.BundlePluginLoader(pluginsDir);
|
|
1138
|
+
try {
|
|
1139
|
+
const plugins = loader.loadPluginsSync();
|
|
1140
|
+
if (plugins.length > 0) {
|
|
1141
|
+
registry.addSource(new PluginCommandSource(plugins));
|
|
1142
|
+
pluginHooks = mergePluginHooks(plugins);
|
|
1143
|
+
}
|
|
1144
|
+
} catch {
|
|
1145
|
+
}
|
|
1146
|
+
resultRef.current = { registry, pluginHooks };
|
|
740
1147
|
}
|
|
741
|
-
return
|
|
1148
|
+
return resultRef.current;
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
// src/ui/hooks/usePluginCallbacks.ts
|
|
1152
|
+
var import_react6 = require("react");
|
|
1153
|
+
var import_node_os3 = require("os");
|
|
1154
|
+
var import_node_path4 = require("path");
|
|
1155
|
+
var import_agent_sdk3 = require("@robota-sdk/agent-sdk");
|
|
1156
|
+
function usePluginCallbacks(cwd) {
|
|
1157
|
+
return (0, import_react6.useMemo)(() => {
|
|
1158
|
+
const home = (0, import_node_os3.homedir)();
|
|
1159
|
+
const pluginsDir = (0, import_node_path4.join)(home, ".robota", "plugins");
|
|
1160
|
+
const userSettingsPath = (0, import_node_path4.join)(home, ".robota", "settings.json");
|
|
1161
|
+
const settingsStore = new import_agent_sdk3.PluginSettingsStore(userSettingsPath);
|
|
1162
|
+
const marketplace = new import_agent_sdk3.MarketplaceClient({ pluginsDir });
|
|
1163
|
+
const installer = new import_agent_sdk3.BundlePluginInstaller({
|
|
1164
|
+
pluginsDir,
|
|
1165
|
+
settingsStore,
|
|
1166
|
+
marketplaceClient: marketplace
|
|
1167
|
+
});
|
|
1168
|
+
const loader = new import_agent_sdk3.BundlePluginLoader(pluginsDir);
|
|
1169
|
+
return {
|
|
1170
|
+
listInstalled: async () => {
|
|
1171
|
+
const plugins = await loader.loadAll();
|
|
1172
|
+
return plugins.map((p) => ({
|
|
1173
|
+
name: p.manifest.name,
|
|
1174
|
+
description: p.manifest.description,
|
|
1175
|
+
enabled: true
|
|
1176
|
+
}));
|
|
1177
|
+
},
|
|
1178
|
+
install: async (pluginId) => {
|
|
1179
|
+
const [name, marketplaceName] = pluginId.split("@");
|
|
1180
|
+
if (!name || !marketplaceName) {
|
|
1181
|
+
throw new Error("Plugin ID must be in format: name@marketplace");
|
|
1182
|
+
}
|
|
1183
|
+
await installer.install(name, marketplaceName);
|
|
1184
|
+
},
|
|
1185
|
+
uninstall: async (pluginId) => {
|
|
1186
|
+
await installer.uninstall(pluginId);
|
|
1187
|
+
},
|
|
1188
|
+
enable: async (pluginId) => {
|
|
1189
|
+
await installer.enable(pluginId);
|
|
1190
|
+
},
|
|
1191
|
+
disable: async (pluginId) => {
|
|
1192
|
+
await installer.disable(pluginId);
|
|
1193
|
+
},
|
|
1194
|
+
marketplaceAdd: async (source) => {
|
|
1195
|
+
if (source.includes("/") && !source.includes(":")) {
|
|
1196
|
+
return marketplace.addMarketplace({ type: "github", repo: source });
|
|
1197
|
+
} else {
|
|
1198
|
+
return marketplace.addMarketplace({ type: "git", url: source });
|
|
1199
|
+
}
|
|
1200
|
+
},
|
|
1201
|
+
marketplaceRemove: async (name) => {
|
|
1202
|
+
const installedFromMarketplace = installer.getPluginsByMarketplace(name);
|
|
1203
|
+
for (const record of installedFromMarketplace) {
|
|
1204
|
+
await installer.uninstall(`${record.pluginName}@${record.marketplace}`);
|
|
1205
|
+
}
|
|
1206
|
+
marketplace.removeMarketplace(name);
|
|
1207
|
+
},
|
|
1208
|
+
marketplaceUpdate: async (name) => {
|
|
1209
|
+
marketplace.updateMarketplace(name);
|
|
1210
|
+
},
|
|
1211
|
+
marketplaceList: async () => {
|
|
1212
|
+
return marketplace.listMarketplaces().map((m) => ({
|
|
1213
|
+
name: m.name,
|
|
1214
|
+
type: m.source.type
|
|
1215
|
+
}));
|
|
1216
|
+
},
|
|
1217
|
+
reloadPlugins: async () => {
|
|
1218
|
+
}
|
|
1219
|
+
};
|
|
1220
|
+
}, [cwd]);
|
|
742
1221
|
}
|
|
743
1222
|
|
|
744
1223
|
// src/ui/MessageList.tsx
|
|
@@ -775,13 +1254,39 @@ function RoleLabel({ role }) {
|
|
|
775
1254
|
" "
|
|
776
1255
|
] });
|
|
777
1256
|
case "tool":
|
|
778
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink.Text, { color: "
|
|
1257
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink.Text, { color: "white", bold: true, children: [
|
|
779
1258
|
"Tool:",
|
|
780
1259
|
" "
|
|
781
1260
|
] });
|
|
782
1261
|
}
|
|
783
1262
|
}
|
|
1263
|
+
function ToolMessage({ message }) {
|
|
1264
|
+
const lines = message.content.split("\n").filter((l) => l.trim());
|
|
1265
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink.Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
1266
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink.Box, { children: [
|
|
1267
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink.Text, { color: "white", bold: true, children: [
|
|
1268
|
+
"Tool:",
|
|
1269
|
+
" "
|
|
1270
|
+
] }),
|
|
1271
|
+
message.toolName && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink.Text, { color: "white", dimColor: true, children: [
|
|
1272
|
+
"[",
|
|
1273
|
+
message.toolName,
|
|
1274
|
+
"]"
|
|
1275
|
+
] })
|
|
1276
|
+
] }),
|
|
1277
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Text, { children: " " }),
|
|
1278
|
+
lines.map((line, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink.Text, { color: "green", children: [
|
|
1279
|
+
" ",
|
|
1280
|
+
"\u2713",
|
|
1281
|
+
" ",
|
|
1282
|
+
line
|
|
1283
|
+
] }, i))
|
|
1284
|
+
] });
|
|
1285
|
+
}
|
|
784
1286
|
function MessageItem({ message }) {
|
|
1287
|
+
if (message.role === "tool") {
|
|
1288
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ToolMessage, { message });
|
|
1289
|
+
}
|
|
785
1290
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink.Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
786
1291
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink.Box, { children: [
|
|
787
1292
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(RoleLabel, { role: message.role }),
|
|
@@ -861,11 +1366,11 @@ function StatusBar({
|
|
|
861
1366
|
}
|
|
862
1367
|
|
|
863
1368
|
// src/ui/InputArea.tsx
|
|
864
|
-
var
|
|
1369
|
+
var import_react9 = __toESM(require("react"), 1);
|
|
865
1370
|
var import_ink6 = require("ink");
|
|
866
1371
|
|
|
867
1372
|
// src/ui/CjkTextInput.tsx
|
|
868
|
-
var
|
|
1373
|
+
var import_react7 = require("react");
|
|
869
1374
|
var import_ink3 = require("ink");
|
|
870
1375
|
var import_chalk = __toESM(require("chalk"), 1);
|
|
871
1376
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
@@ -885,9 +1390,9 @@ function CjkTextInput({
|
|
|
885
1390
|
focus = true,
|
|
886
1391
|
showCursor = true
|
|
887
1392
|
}) {
|
|
888
|
-
const valueRef = (0,
|
|
889
|
-
const cursorRef = (0,
|
|
890
|
-
const [, forceRender] = (0,
|
|
1393
|
+
const valueRef = (0, import_react7.useRef)(value);
|
|
1394
|
+
const cursorRef = (0, import_react7.useRef)(value.length);
|
|
1395
|
+
const [, forceRender] = (0, import_react7.useState)(0);
|
|
891
1396
|
if (value !== valueRef.current) {
|
|
892
1397
|
valueRef.current = value;
|
|
893
1398
|
if (cursorRef.current > value.length) {
|
|
@@ -964,15 +1469,15 @@ function renderWithCursor(value, cursorOffset, placeholder, showCursor) {
|
|
|
964
1469
|
}
|
|
965
1470
|
|
|
966
1471
|
// src/ui/WaveText.tsx
|
|
967
|
-
var
|
|
1472
|
+
var import_react8 = require("react");
|
|
968
1473
|
var import_ink4 = require("ink");
|
|
969
1474
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
970
1475
|
var WAVE_COLORS = ["#666666", "#888888", "#aaaaaa", "#888888"];
|
|
971
1476
|
var INTERVAL_MS = 400;
|
|
972
1477
|
var CHARS_PER_GROUP = 4;
|
|
973
1478
|
function WaveText({ text }) {
|
|
974
|
-
const [tick, setTick] = (0,
|
|
975
|
-
(0,
|
|
1479
|
+
const [tick, setTick] = (0, import_react8.useState)(0);
|
|
1480
|
+
(0, import_react8.useEffect)(() => {
|
|
976
1481
|
const timer = setInterval(() => {
|
|
977
1482
|
setTick((prev) => prev + 1);
|
|
978
1483
|
}, INTERVAL_MS);
|
|
@@ -1038,16 +1543,16 @@ function parseSlashInput(value) {
|
|
|
1038
1543
|
return { isSlash: true, parentCommand: parent, filter: rest };
|
|
1039
1544
|
}
|
|
1040
1545
|
function useAutocomplete(value, registry) {
|
|
1041
|
-
const [selectedIndex, setSelectedIndex] = (0,
|
|
1042
|
-
const [dismissed, setDismissed] = (0,
|
|
1043
|
-
const prevValueRef =
|
|
1546
|
+
const [selectedIndex, setSelectedIndex] = (0, import_react9.useState)(0);
|
|
1547
|
+
const [dismissed, setDismissed] = (0, import_react9.useState)(false);
|
|
1548
|
+
const prevValueRef = import_react9.default.useRef(value);
|
|
1044
1549
|
if (prevValueRef.current !== value) {
|
|
1045
1550
|
prevValueRef.current = value;
|
|
1046
1551
|
if (dismissed) setDismissed(false);
|
|
1047
1552
|
}
|
|
1048
1553
|
const parsed = parseSlashInput(value);
|
|
1049
1554
|
const isSubcommandMode = parsed.isSlash && parsed.parentCommand.length > 0;
|
|
1050
|
-
const filteredCommands = (0,
|
|
1555
|
+
const filteredCommands = (0, import_react9.useMemo)(() => {
|
|
1051
1556
|
if (!registry || !parsed.isSlash || dismissed) return [];
|
|
1052
1557
|
if (isSubcommandMode) {
|
|
1053
1558
|
const subs = registry.getSubcommands(parsed.parentCommand);
|
|
@@ -1081,7 +1586,7 @@ function useAutocomplete(value, registry) {
|
|
|
1081
1586
|
};
|
|
1082
1587
|
}
|
|
1083
1588
|
function InputArea({ onSubmit, isDisabled, registry }) {
|
|
1084
|
-
const [value, setValue] = (0,
|
|
1589
|
+
const [value, setValue] = (0, import_react9.useState)("");
|
|
1085
1590
|
const {
|
|
1086
1591
|
showPopup,
|
|
1087
1592
|
filteredCommands,
|
|
@@ -1090,7 +1595,7 @@ function InputArea({ onSubmit, isDisabled, registry }) {
|
|
|
1090
1595
|
isSubcommandMode,
|
|
1091
1596
|
setShowPopup
|
|
1092
1597
|
} = useAutocomplete(value, registry);
|
|
1093
|
-
const handleSubmit = (0,
|
|
1598
|
+
const handleSubmit = (0, import_react9.useCallback)(
|
|
1094
1599
|
(text) => {
|
|
1095
1600
|
const trimmed = text.trim();
|
|
1096
1601
|
if (trimmed.length === 0) return;
|
|
@@ -1103,7 +1608,7 @@ function InputArea({ onSubmit, isDisabled, registry }) {
|
|
|
1103
1608
|
},
|
|
1104
1609
|
[showPopup, filteredCommands, selectedIndex, onSubmit]
|
|
1105
1610
|
);
|
|
1106
|
-
const selectCommand = (0,
|
|
1611
|
+
const selectCommand = (0, import_react9.useCallback)(
|
|
1107
1612
|
(cmd) => {
|
|
1108
1613
|
const parsed = parseSlashInput(value);
|
|
1109
1614
|
if (parsed.parentCommand) {
|
|
@@ -1164,7 +1669,7 @@ function InputArea({ onSubmit, isDisabled, registry }) {
|
|
|
1164
1669
|
}
|
|
1165
1670
|
|
|
1166
1671
|
// src/ui/ConfirmPrompt.tsx
|
|
1167
|
-
var
|
|
1672
|
+
var import_react10 = require("react");
|
|
1168
1673
|
var import_ink7 = require("ink");
|
|
1169
1674
|
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
1170
1675
|
function ConfirmPrompt({
|
|
@@ -1172,9 +1677,9 @@ function ConfirmPrompt({
|
|
|
1172
1677
|
options = ["Yes", "No"],
|
|
1173
1678
|
onSelect
|
|
1174
1679
|
}) {
|
|
1175
|
-
const [selected, setSelected] = (0,
|
|
1176
|
-
const resolvedRef = (0,
|
|
1177
|
-
const doSelect = (0,
|
|
1680
|
+
const [selected, setSelected] = (0, import_react10.useState)(0);
|
|
1681
|
+
const resolvedRef = (0, import_react10.useRef)(false);
|
|
1682
|
+
const doSelect = (0, import_react10.useCallback)(
|
|
1178
1683
|
(index) => {
|
|
1179
1684
|
if (resolvedRef.current) return;
|
|
1180
1685
|
resolvedRef.current = true;
|
|
@@ -1207,7 +1712,7 @@ function ConfirmPrompt({
|
|
|
1207
1712
|
}
|
|
1208
1713
|
|
|
1209
1714
|
// src/ui/PermissionPrompt.tsx
|
|
1210
|
-
var
|
|
1715
|
+
var import_react11 = __toESM(require("react"), 1);
|
|
1211
1716
|
var import_ink8 = require("ink");
|
|
1212
1717
|
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
1213
1718
|
var OPTIONS = ["Allow", "Allow always (this session)", "Deny"];
|
|
@@ -1217,15 +1722,15 @@ function formatArgs(args) {
|
|
|
1217
1722
|
return entries.map(([k, v]) => `${k}: ${typeof v === "string" ? v : JSON.stringify(v)}`).join(", ");
|
|
1218
1723
|
}
|
|
1219
1724
|
function PermissionPrompt({ request }) {
|
|
1220
|
-
const [selected, setSelected] =
|
|
1221
|
-
const resolvedRef =
|
|
1222
|
-
const prevRequestRef =
|
|
1725
|
+
const [selected, setSelected] = import_react11.default.useState(0);
|
|
1726
|
+
const resolvedRef = import_react11.default.useRef(false);
|
|
1727
|
+
const prevRequestRef = import_react11.default.useRef(request);
|
|
1223
1728
|
if (prevRequestRef.current !== request) {
|
|
1224
1729
|
prevRequestRef.current = request;
|
|
1225
1730
|
resolvedRef.current = false;
|
|
1226
1731
|
setSelected(0);
|
|
1227
1732
|
}
|
|
1228
|
-
const doResolve =
|
|
1733
|
+
const doResolve = import_react11.default.useCallback(
|
|
1229
1734
|
(index) => {
|
|
1230
1735
|
if (resolvedRef.current) return;
|
|
1231
1736
|
resolvedRef.current = true;
|
|
@@ -1273,6 +1778,12 @@ function PermissionPrompt({ request }) {
|
|
|
1273
1778
|
// src/ui/StreamingIndicator.tsx
|
|
1274
1779
|
var import_ink9 = require("ink");
|
|
1275
1780
|
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
1781
|
+
function getToolStyle(t) {
|
|
1782
|
+
if (t.isRunning) return { color: "yellow", icon: "\u27F3", strikethrough: false };
|
|
1783
|
+
if (t.result === "error") return { color: "red", icon: "\u2717", strikethrough: true };
|
|
1784
|
+
if (t.result === "denied") return { color: "yellowBright", icon: "\u2298", strikethrough: true };
|
|
1785
|
+
return { color: "green", icon: "\u2713", strikethrough: false };
|
|
1786
|
+
}
|
|
1276
1787
|
function StreamingIndicator({ text, activeTools }) {
|
|
1277
1788
|
const hasTools = activeTools.length > 0;
|
|
1278
1789
|
const hasText = text.length > 0;
|
|
@@ -1281,17 +1792,20 @@ function StreamingIndicator({ text, activeTools }) {
|
|
|
1281
1792
|
}
|
|
1282
1793
|
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_ink9.Box, { flexDirection: "column", children: [
|
|
1283
1794
|
hasTools && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_ink9.Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
1284
|
-
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_ink9.Text, { color: "
|
|
1795
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_ink9.Text, { color: "white", bold: true, children: "Tools:" }),
|
|
1285
1796
|
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_ink9.Text, { children: " " }),
|
|
1286
|
-
activeTools.map((t, i) =>
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1797
|
+
activeTools.map((t, i) => {
|
|
1798
|
+
const { color, icon, strikethrough } = getToolStyle(t);
|
|
1799
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_ink9.Text, { color, strikethrough, children: [
|
|
1800
|
+
" ",
|
|
1801
|
+
icon,
|
|
1802
|
+
" ",
|
|
1803
|
+
t.toolName,
|
|
1804
|
+
"(",
|
|
1805
|
+
t.firstArg,
|
|
1806
|
+
")"
|
|
1807
|
+
] }, `${t.toolName}-${i}`);
|
|
1808
|
+
})
|
|
1295
1809
|
] }),
|
|
1296
1810
|
hasText && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_ink9.Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
1297
1811
|
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_ink9.Text, { color: "cyan", bold: true, children: "Robota:" }),
|
|
@@ -1304,20 +1818,46 @@ function StreamingIndicator({ text, activeTools }) {
|
|
|
1304
1818
|
// src/ui/App.tsx
|
|
1305
1819
|
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
1306
1820
|
var EXIT_DELAY_MS2 = 500;
|
|
1821
|
+
function mergeHooksIntoConfig(configHooks, pluginHooks) {
|
|
1822
|
+
const pluginKeys = Object.keys(pluginHooks);
|
|
1823
|
+
if (pluginKeys.length === 0) return configHooks;
|
|
1824
|
+
const merged = {};
|
|
1825
|
+
for (const [event, groups] of Object.entries(pluginHooks)) {
|
|
1826
|
+
merged[event] = [...groups];
|
|
1827
|
+
}
|
|
1828
|
+
if (configHooks) {
|
|
1829
|
+
for (const [event, groups] of Object.entries(configHooks)) {
|
|
1830
|
+
if (!Array.isArray(groups)) continue;
|
|
1831
|
+
if (!merged[event]) merged[event] = [];
|
|
1832
|
+
merged[event].push(...groups);
|
|
1833
|
+
}
|
|
1834
|
+
}
|
|
1835
|
+
return merged;
|
|
1836
|
+
}
|
|
1307
1837
|
function App(props) {
|
|
1308
1838
|
const { exit } = (0, import_ink10.useApp)();
|
|
1309
|
-
const {
|
|
1839
|
+
const { registry, pluginHooks } = useCommandRegistry(props.cwd ?? process.cwd());
|
|
1840
|
+
const configWithPluginHooks = {
|
|
1841
|
+
...props.config,
|
|
1842
|
+
hooks: mergeHooksIntoConfig(
|
|
1843
|
+
props.config.hooks,
|
|
1844
|
+
pluginHooks
|
|
1845
|
+
)
|
|
1846
|
+
};
|
|
1847
|
+
const { session, permissionRequest, streamingText, clearStreamingText, activeTools } = useSession(
|
|
1848
|
+
{ ...props, config: configWithPluginHooks }
|
|
1849
|
+
);
|
|
1310
1850
|
const { messages, setMessages, addMessage } = useMessages();
|
|
1311
|
-
const [isThinking, setIsThinking] = (0,
|
|
1851
|
+
const [isThinking, setIsThinking] = (0, import_react12.useState)(false);
|
|
1312
1852
|
const initialCtx = session.getContextState();
|
|
1313
|
-
const [contextState, setContextState] = (0,
|
|
1853
|
+
const [contextState, setContextState] = (0, import_react12.useState)({
|
|
1314
1854
|
percentage: initialCtx.usedPercentage,
|
|
1315
1855
|
usedTokens: initialCtx.usedTokens,
|
|
1316
1856
|
maxTokens: initialCtx.maxTokens
|
|
1317
1857
|
});
|
|
1318
|
-
const
|
|
1319
|
-
const
|
|
1320
|
-
const
|
|
1858
|
+
const pendingModelChangeRef = (0, import_react12.useRef)(null);
|
|
1859
|
+
const [pendingModelId, setPendingModelId] = (0, import_react12.useState)(null);
|
|
1860
|
+
const pluginCallbacks = usePluginCallbacks(props.cwd ?? process.cwd());
|
|
1321
1861
|
const handleSlashCommand = useSlashCommands(
|
|
1322
1862
|
session,
|
|
1323
1863
|
addMessage,
|
|
@@ -1325,7 +1865,8 @@ function App(props) {
|
|
|
1325
1865
|
exit,
|
|
1326
1866
|
registry,
|
|
1327
1867
|
pendingModelChangeRef,
|
|
1328
|
-
setPendingModelId
|
|
1868
|
+
setPendingModelId,
|
|
1869
|
+
pluginCallbacks
|
|
1329
1870
|
);
|
|
1330
1871
|
const handleSubmit = useSubmitHandler(
|
|
1331
1872
|
session,
|
|
@@ -1441,23 +1982,24 @@ function renderApp(options) {
|
|
|
1441
1982
|
|
|
1442
1983
|
// src/cli.ts
|
|
1443
1984
|
var import_meta = {};
|
|
1444
|
-
function
|
|
1445
|
-
if (!(0, import_node_fs3.existsSync)(filePath)) return
|
|
1985
|
+
function checkSettingsFile(filePath) {
|
|
1986
|
+
if (!(0, import_node_fs3.existsSync)(filePath)) return "missing";
|
|
1446
1987
|
try {
|
|
1447
1988
|
const raw = (0, import_node_fs3.readFileSync)(filePath, "utf8").trim();
|
|
1448
|
-
if (raw.length === 0) return
|
|
1989
|
+
if (raw.length === 0) return "incomplete";
|
|
1449
1990
|
const parsed = JSON.parse(raw);
|
|
1450
1991
|
const provider = parsed.provider;
|
|
1451
|
-
|
|
1992
|
+
if (!provider?.apiKey) return "incomplete";
|
|
1993
|
+
return "valid";
|
|
1452
1994
|
} catch {
|
|
1453
|
-
return
|
|
1995
|
+
return "corrupt";
|
|
1454
1996
|
}
|
|
1455
1997
|
}
|
|
1456
1998
|
function readVersion() {
|
|
1457
1999
|
try {
|
|
1458
2000
|
const thisFile = (0, import_node_url.fileURLToPath)(import_meta.url);
|
|
1459
|
-
const dir = (0,
|
|
1460
|
-
const candidates = [(0,
|
|
2001
|
+
const dir = (0, import_node_path5.dirname)(thisFile);
|
|
2002
|
+
const candidates = [(0, import_node_path5.join)(dir, "..", "..", "package.json"), (0, import_node_path5.join)(dir, "..", "package.json")];
|
|
1461
2003
|
for (const pkgPath of candidates) {
|
|
1462
2004
|
try {
|
|
1463
2005
|
const raw = (0, import_node_fs3.readFileSync)(pkgPath, "utf-8");
|
|
@@ -1510,14 +2052,36 @@ function promptInput(label, masked = false) {
|
|
|
1510
2052
|
}
|
|
1511
2053
|
async function ensureConfig(cwd) {
|
|
1512
2054
|
const userPath = getUserSettingsPath();
|
|
1513
|
-
const projectPath = (0,
|
|
1514
|
-
const localPath = (0,
|
|
1515
|
-
|
|
2055
|
+
const projectPath = (0, import_node_path5.join)(cwd, ".robota", "settings.json");
|
|
2056
|
+
const localPath = (0, import_node_path5.join)(cwd, ".robota", "settings.local.json");
|
|
2057
|
+
const paths = [userPath, projectPath, localPath];
|
|
2058
|
+
const checks = paths.map((p) => ({ path: p, status: checkSettingsFile(p) }));
|
|
2059
|
+
if (checks.some((c) => c.status === "valid")) {
|
|
1516
2060
|
return;
|
|
1517
2061
|
}
|
|
2062
|
+
const corrupt = checks.filter((c) => c.status === "corrupt");
|
|
2063
|
+
const incomplete = checks.filter((c) => c.status === "incomplete");
|
|
1518
2064
|
process.stdout.write("\n");
|
|
1519
|
-
|
|
1520
|
-
|
|
2065
|
+
if (corrupt.length > 0) {
|
|
2066
|
+
for (const c of corrupt) {
|
|
2067
|
+
process.stderr.write(` ERROR: Settings file is corrupt (invalid JSON): ${c.path}
|
|
2068
|
+
`);
|
|
2069
|
+
}
|
|
2070
|
+
process.stdout.write("\n");
|
|
2071
|
+
}
|
|
2072
|
+
if (incomplete.length > 0) {
|
|
2073
|
+
for (const c of incomplete) {
|
|
2074
|
+
process.stderr.write(` WARNING: Settings file is missing provider.apiKey: ${c.path}
|
|
2075
|
+
`);
|
|
2076
|
+
}
|
|
2077
|
+
process.stdout.write("\n");
|
|
2078
|
+
}
|
|
2079
|
+
if (corrupt.length === 0 && incomplete.length === 0) {
|
|
2080
|
+
process.stdout.write(" Welcome to Robota CLI!\n");
|
|
2081
|
+
process.stdout.write(" No configuration found. Let's set up.\n");
|
|
2082
|
+
} else {
|
|
2083
|
+
process.stdout.write(" Reconfiguring...\n");
|
|
2084
|
+
}
|
|
1521
2085
|
process.stdout.write("\n");
|
|
1522
2086
|
const apiKey = await promptInput(" Anthropic API key: ", true);
|
|
1523
2087
|
if (!apiKey) {
|
|
@@ -1525,7 +2089,7 @@ async function ensureConfig(cwd) {
|
|
|
1525
2089
|
process.exit(1);
|
|
1526
2090
|
}
|
|
1527
2091
|
const language = await promptInput(" Response language (ko/en/ja/zh, default: en): ");
|
|
1528
|
-
const settingsDir = (0,
|
|
2092
|
+
const settingsDir = (0, import_node_path5.dirname)(userPath);
|
|
1529
2093
|
(0, import_node_fs3.mkdirSync)(settingsDir, { recursive: true });
|
|
1530
2094
|
const settings = {
|
|
1531
2095
|
provider: {
|
|
@@ -1566,9 +2130,9 @@ async function startCli() {
|
|
|
1566
2130
|
const cwd = process.cwd();
|
|
1567
2131
|
await ensureConfig(cwd);
|
|
1568
2132
|
const [config, context, projectInfo] = await Promise.all([
|
|
1569
|
-
(0,
|
|
1570
|
-
(0,
|
|
1571
|
-
(0,
|
|
2133
|
+
(0, import_agent_sdk4.loadConfig)(cwd),
|
|
2134
|
+
(0, import_agent_sdk4.loadContext)(cwd),
|
|
2135
|
+
(0, import_agent_sdk4.detectProject)(cwd)
|
|
1572
2136
|
]);
|
|
1573
2137
|
if (args.model !== void 0) {
|
|
1574
2138
|
config.provider.model = args.model;
|
|
@@ -1576,7 +2140,7 @@ async function startCli() {
|
|
|
1576
2140
|
if (args.language !== void 0) {
|
|
1577
2141
|
config.language = args.language;
|
|
1578
2142
|
}
|
|
1579
|
-
const sessionStore = new
|
|
2143
|
+
const sessionStore = new import_agent_sdk4.SessionStore();
|
|
1580
2144
|
if (args.printMode) {
|
|
1581
2145
|
const prompt = args.positional.join(" ").trim();
|
|
1582
2146
|
if (prompt.length === 0) {
|
|
@@ -1584,15 +2148,15 @@ async function startCli() {
|
|
|
1584
2148
|
process.exit(1);
|
|
1585
2149
|
}
|
|
1586
2150
|
const terminal = new PrintTerminal();
|
|
1587
|
-
const paths = (0,
|
|
1588
|
-
const session = (0,
|
|
2151
|
+
const paths = (0, import_agent_sdk4.projectPaths)(cwd);
|
|
2152
|
+
const session = (0, import_agent_sdk4.createSession)({
|
|
1589
2153
|
config,
|
|
1590
2154
|
context,
|
|
1591
2155
|
terminal,
|
|
1592
|
-
sessionLogger: new
|
|
2156
|
+
sessionLogger: new import_agent_sdk4.FileSessionLogger(paths.logs),
|
|
1593
2157
|
projectInfo,
|
|
1594
2158
|
permissionMode: args.permissionMode,
|
|
1595
|
-
promptForApproval:
|
|
2159
|
+
promptForApproval: import_agent_sdk5.promptForApproval
|
|
1596
2160
|
});
|
|
1597
2161
|
const response = await session.run(prompt);
|
|
1598
2162
|
process.stdout.write(response + "\n");
|