@robota-sdk/agent-cli 3.0.0-beta.1 → 3.0.0-beta.11
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 +249 -85
- package/dist/node/bin.js +11 -1
- package/dist/node/{chunk-C56WFH5S.js → chunk-CT2VGJIF.js} +243 -88
- package/dist/node/index.cjs +244 -90
- package/dist/node/index.js +1 -1
- package/package.json +3 -3
package/dist/node/index.cjs
CHANGED
|
@@ -30,14 +30,14 @@ 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_sdk4.Session,
|
|
34
|
+
SessionStore: () => import_agent_sdk4.SessionStore,
|
|
35
|
+
TRUST_TO_MODE: () => import_agent_sdk4.TRUST_TO_MODE,
|
|
36
|
+
query: () => import_agent_sdk4.query,
|
|
37
37
|
startCli: () => startCli
|
|
38
38
|
});
|
|
39
39
|
module.exports = __toCommonJS(index_exports);
|
|
40
|
-
var
|
|
40
|
+
var import_agent_sdk4 = require("@robota-sdk/agent-sdk");
|
|
41
41
|
|
|
42
42
|
// src/cli.ts
|
|
43
43
|
var import_node_util = require("util");
|
|
@@ -46,26 +46,7 @@ var import_node_path2 = require("path");
|
|
|
46
46
|
var import_node_url = require("url");
|
|
47
47
|
var readline = __toESM(require("readline"), 1);
|
|
48
48
|
var import_agent_sdk2 = require("@robota-sdk/agent-sdk");
|
|
49
|
-
|
|
50
|
-
// src/permissions/permission-prompt.ts
|
|
51
|
-
var import_chalk = __toESM(require("chalk"), 1);
|
|
52
|
-
var PERMISSION_OPTIONS = ["Allow", "Deny"];
|
|
53
|
-
var ALLOW_INDEX = 0;
|
|
54
|
-
function formatArgs(toolArgs) {
|
|
55
|
-
const entries = Object.entries(toolArgs);
|
|
56
|
-
if (entries.length === 0) {
|
|
57
|
-
return "(no arguments)";
|
|
58
|
-
}
|
|
59
|
-
return entries.map(([k, v]) => `${k}: ${typeof v === "string" ? v : JSON.stringify(v)}`).join(", ");
|
|
60
|
-
}
|
|
61
|
-
async function promptForApproval(terminal, toolName, toolArgs) {
|
|
62
|
-
terminal.writeLine("");
|
|
63
|
-
terminal.writeLine(import_chalk.default.yellow(`[Permission Required] Tool: ${toolName}`));
|
|
64
|
-
terminal.writeLine(import_chalk.default.dim(` ${formatArgs(toolArgs)}`));
|
|
65
|
-
terminal.writeLine("");
|
|
66
|
-
const selected = await terminal.select(PERMISSION_OPTIONS, ALLOW_INDEX);
|
|
67
|
-
return selected === ALLOW_INDEX;
|
|
68
|
-
}
|
|
49
|
+
var import_agent_sdk3 = require("@robota-sdk/agent-sdk");
|
|
69
50
|
|
|
70
51
|
// src/ui/render.tsx
|
|
71
52
|
var import_ink9 = require("ink");
|
|
@@ -135,6 +116,7 @@ function createBuiltinCommands() {
|
|
|
135
116
|
{ name: "cost", description: "Show session info", source: "builtin" },
|
|
136
117
|
{ name: "context", description: "Context window info", source: "builtin" },
|
|
137
118
|
{ name: "permissions", description: "Permission rules", source: "builtin" },
|
|
119
|
+
{ name: "reset", description: "Delete settings and exit", source: "builtin" },
|
|
138
120
|
{ name: "exit", description: "Exit CLI", source: "builtin" }
|
|
139
121
|
];
|
|
140
122
|
}
|
|
@@ -186,7 +168,8 @@ function scanSkillsDir(skillsDir) {
|
|
|
186
168
|
commands.push({
|
|
187
169
|
name: frontmatter?.name ?? entry.name,
|
|
188
170
|
description: frontmatter?.description ?? `Skill: ${entry.name}`,
|
|
189
|
-
source: "skill"
|
|
171
|
+
source: "skill",
|
|
172
|
+
skillContent: content
|
|
190
173
|
});
|
|
191
174
|
}
|
|
192
175
|
return commands;
|
|
@@ -340,7 +323,7 @@ var import_ink6 = require("ink");
|
|
|
340
323
|
var import_react = require("react");
|
|
341
324
|
var import_ink3 = require("ink");
|
|
342
325
|
var import_string_width = __toESM(require("string-width"), 1);
|
|
343
|
-
var
|
|
326
|
+
var import_chalk = __toESM(require("chalk"), 1);
|
|
344
327
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
345
328
|
function CjkTextInput({
|
|
346
329
|
value,
|
|
@@ -362,71 +345,81 @@ function CjkTextInput({
|
|
|
362
345
|
}
|
|
363
346
|
(0, import_ink3.useInput)(
|
|
364
347
|
(input, key) => {
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
if (key.return) {
|
|
369
|
-
onSubmit?.(valueRef.current);
|
|
370
|
-
return;
|
|
371
|
-
}
|
|
372
|
-
if (key.leftArrow) {
|
|
373
|
-
if (cursorRef.current > 0) {
|
|
374
|
-
cursorRef.current -= 1;
|
|
375
|
-
forceRender((n) => n + 1);
|
|
348
|
+
try {
|
|
349
|
+
if (key.upArrow || key.downArrow || key.ctrl && input === "c" || key.tab || key.shift && key.tab) {
|
|
350
|
+
return;
|
|
376
351
|
}
|
|
377
|
-
return
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
if (cursorRef.current < valueRef.current.length) {
|
|
381
|
-
cursorRef.current += 1;
|
|
382
|
-
forceRender((n) => n + 1);
|
|
352
|
+
if (key.return) {
|
|
353
|
+
onSubmit?.(valueRef.current);
|
|
354
|
+
return;
|
|
383
355
|
}
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
cursorRef.current -= 1;
|
|
391
|
-
valueRef.current = next2;
|
|
392
|
-
onChange(next2);
|
|
356
|
+
if (key.leftArrow) {
|
|
357
|
+
if (cursorRef.current > 0) {
|
|
358
|
+
cursorRef.current -= 1;
|
|
359
|
+
forceRender((n) => n + 1);
|
|
360
|
+
}
|
|
361
|
+
return;
|
|
393
362
|
}
|
|
394
|
-
|
|
363
|
+
if (key.rightArrow) {
|
|
364
|
+
if (cursorRef.current < valueRef.current.length) {
|
|
365
|
+
cursorRef.current += 1;
|
|
366
|
+
forceRender((n) => n + 1);
|
|
367
|
+
}
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
if (key.backspace || key.delete) {
|
|
371
|
+
if (cursorRef.current > 0) {
|
|
372
|
+
const v2 = valueRef.current;
|
|
373
|
+
const next2 = v2.slice(0, cursorRef.current - 1) + v2.slice(cursorRef.current);
|
|
374
|
+
cursorRef.current -= 1;
|
|
375
|
+
valueRef.current = next2;
|
|
376
|
+
onChange(next2);
|
|
377
|
+
}
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
if (!input || input.length === 0) return;
|
|
381
|
+
const printable = input.replace(/[\x00-\x1f\x7f]/g, "");
|
|
382
|
+
if (printable.length === 0) return;
|
|
383
|
+
const v = valueRef.current;
|
|
384
|
+
const c = cursorRef.current;
|
|
385
|
+
const next = v.slice(0, c) + printable + v.slice(c);
|
|
386
|
+
cursorRef.current = c + printable.length;
|
|
387
|
+
valueRef.current = next;
|
|
388
|
+
onChange(next);
|
|
389
|
+
} catch {
|
|
395
390
|
}
|
|
396
|
-
const v = valueRef.current;
|
|
397
|
-
const c = cursorRef.current;
|
|
398
|
-
const next = v.slice(0, c) + input + v.slice(c);
|
|
399
|
-
cursorRef.current = c + input.length;
|
|
400
|
-
valueRef.current = next;
|
|
401
|
-
onChange(next);
|
|
402
391
|
},
|
|
403
392
|
{ isActive: focus }
|
|
404
393
|
);
|
|
405
394
|
if (showCursor && focus) {
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
395
|
+
try {
|
|
396
|
+
const textBeforeCursor = [...valueRef.current].slice(0, cursorRef.current).join("");
|
|
397
|
+
const cursorX = 4 + (0, import_string_width.default)(textBeforeCursor);
|
|
398
|
+
setCursorPosition({ x: cursorX, y: 0 });
|
|
399
|
+
} catch {
|
|
400
|
+
setCursorPosition({ x: 4, y: 0 });
|
|
401
|
+
}
|
|
409
402
|
}
|
|
410
403
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ink3.Text, { children: renderWithCursor(valueRef.current, cursorRef.current, placeholder, showCursor && focus) });
|
|
411
404
|
}
|
|
412
405
|
function renderWithCursor(value, cursorOffset, placeholder, showCursor) {
|
|
413
406
|
if (!showCursor) {
|
|
414
|
-
return value.length > 0 ? value : placeholder ?
|
|
407
|
+
return value.length > 0 ? value : placeholder ? import_chalk.default.gray(placeholder) : "";
|
|
415
408
|
}
|
|
416
409
|
if (value.length === 0) {
|
|
417
410
|
if (placeholder.length > 0) {
|
|
418
|
-
return
|
|
411
|
+
return import_chalk.default.inverse(placeholder[0]) + import_chalk.default.gray(placeholder.slice(1));
|
|
419
412
|
}
|
|
420
|
-
return
|
|
413
|
+
return import_chalk.default.inverse(" ");
|
|
421
414
|
}
|
|
422
415
|
const chars = [...value];
|
|
423
416
|
let rendered = "";
|
|
424
417
|
for (let i = 0; i < chars.length; i++) {
|
|
425
418
|
const char = chars[i] ?? "";
|
|
426
|
-
rendered += i === cursorOffset ?
|
|
419
|
+
rendered += i === cursorOffset ? import_chalk.default.inverse(char) : char;
|
|
427
420
|
}
|
|
428
421
|
if (cursorOffset >= chars.length) {
|
|
429
|
-
rendered +=
|
|
422
|
+
rendered += import_chalk.default.inverse(" ");
|
|
430
423
|
}
|
|
431
424
|
return rendered;
|
|
432
425
|
}
|
|
@@ -641,8 +634,8 @@ function InputArea({ onSubmit, isDisabled, registry }) {
|
|
|
641
634
|
var import_react4 = __toESM(require("react"), 1);
|
|
642
635
|
var import_ink7 = require("ink");
|
|
643
636
|
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
644
|
-
var OPTIONS = ["Allow", "Deny"];
|
|
645
|
-
function
|
|
637
|
+
var OPTIONS = ["Allow", "Allow always (this session)", "Deny"];
|
|
638
|
+
function formatArgs(args) {
|
|
646
639
|
const entries = Object.entries(args);
|
|
647
640
|
if (entries.length === 0) return "(no arguments)";
|
|
648
641
|
return entries.map(([k, v]) => `${k}: ${typeof v === "string" ? v : JSON.stringify(v)}`).join(", ");
|
|
@@ -657,10 +650,12 @@ function PermissionPrompt({ request }) {
|
|
|
657
650
|
setSelected(0);
|
|
658
651
|
}
|
|
659
652
|
const doResolve = import_react4.default.useCallback(
|
|
660
|
-
(
|
|
653
|
+
(index) => {
|
|
661
654
|
if (resolvedRef.current) return;
|
|
662
655
|
resolvedRef.current = true;
|
|
663
|
-
request.resolve(
|
|
656
|
+
if (index === 0) request.resolve(true);
|
|
657
|
+
else if (index === 1) request.resolve("allow-session");
|
|
658
|
+
else request.resolve(false);
|
|
664
659
|
},
|
|
665
660
|
[request]
|
|
666
661
|
);
|
|
@@ -671,11 +666,13 @@ function PermissionPrompt({ request }) {
|
|
|
671
666
|
} else if (key.downArrow || key.rightArrow) {
|
|
672
667
|
setSelected((prev) => prev < OPTIONS.length - 1 ? prev + 1 : prev);
|
|
673
668
|
} else if (key.return) {
|
|
674
|
-
doResolve(selected
|
|
675
|
-
} else if (input === "y" || input === "
|
|
676
|
-
doResolve(
|
|
677
|
-
} else if (input === "
|
|
678
|
-
doResolve(
|
|
669
|
+
doResolve(selected);
|
|
670
|
+
} else if (input === "y" || input === "1") {
|
|
671
|
+
doResolve(0);
|
|
672
|
+
} else if (input === "a" || input === "2") {
|
|
673
|
+
doResolve(1);
|
|
674
|
+
} else if (input === "n" || input === "d" || input === "3") {
|
|
675
|
+
doResolve(2);
|
|
679
676
|
}
|
|
680
677
|
});
|
|
681
678
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_ink7.Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
|
|
@@ -687,7 +684,7 @@ function PermissionPrompt({ request }) {
|
|
|
687
684
|
] }),
|
|
688
685
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_ink7.Text, { dimColor: true, children: [
|
|
689
686
|
" ",
|
|
690
|
-
|
|
687
|
+
formatArgs(request.toolArgs)
|
|
691
688
|
] }),
|
|
692
689
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_ink7.Box, { marginTop: 1, children: OPTIONS.map((opt, i) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_ink7.Box, { marginRight: 2, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_ink7.Text, { color: i === selected ? "cyan" : void 0, bold: i === selected, children: [
|
|
693
690
|
i === selected ? "> " : " ",
|
|
@@ -735,11 +732,11 @@ function useSession(props) {
|
|
|
735
732
|
setPermissionRequest({
|
|
736
733
|
toolName: next.toolName,
|
|
737
734
|
toolArgs: next.toolArgs,
|
|
738
|
-
resolve: (
|
|
735
|
+
resolve: (result) => {
|
|
739
736
|
permissionQueueRef.current.shift();
|
|
740
737
|
processingRef.current = false;
|
|
741
738
|
setPermissionRequest(null);
|
|
742
|
-
next.resolve(
|
|
739
|
+
next.resolve(result);
|
|
743
740
|
setTimeout(() => processNextPermission(), 0);
|
|
744
741
|
}
|
|
745
742
|
});
|
|
@@ -755,10 +752,12 @@ function useSession(props) {
|
|
|
755
752
|
const onTextDelta = (delta) => {
|
|
756
753
|
setStreamingText((prev) => prev + delta);
|
|
757
754
|
};
|
|
758
|
-
|
|
755
|
+
const paths = (0, import_agent_sdk.projectPaths)(props.cwd ?? process.cwd());
|
|
756
|
+
sessionRef.current = (0, import_agent_sdk.createSession)({
|
|
759
757
|
config: props.config,
|
|
760
758
|
context: props.context,
|
|
761
759
|
terminal: NOOP_TERMINAL,
|
|
760
|
+
sessionLogger: new import_agent_sdk.FileSessionLogger(paths.logs),
|
|
762
761
|
projectInfo: props.projectInfo,
|
|
763
762
|
sessionStore: props.sessionStore,
|
|
764
763
|
permissionMode: props.permissionMode,
|
|
@@ -784,6 +783,7 @@ var HELP_TEXT = [
|
|
|
784
783
|
" /compact [instr] \u2014 Compact context (optional focus instructions)",
|
|
785
784
|
" /mode [m] \u2014 Show/change permission mode",
|
|
786
785
|
" /cost \u2014 Show session info",
|
|
786
|
+
" /reset \u2014 Delete settings and exit",
|
|
787
787
|
" /exit \u2014 Exit CLI"
|
|
788
788
|
].join("\n");
|
|
789
789
|
function handleModeCommand(arg, session, addMessage) {
|
|
@@ -829,6 +829,39 @@ async function executeSlashCommand(cmd, parts, session, addMessage, setMessages,
|
|
|
829
829
|
Messages: ${session.getMessageCount()}`
|
|
830
830
|
});
|
|
831
831
|
return true;
|
|
832
|
+
case "permissions": {
|
|
833
|
+
const mode = session.getPermissionMode();
|
|
834
|
+
const sessionAllowed = session.getSessionAllowedTools();
|
|
835
|
+
const lines = [`Permission mode: ${mode}`];
|
|
836
|
+
if (sessionAllowed.length > 0) {
|
|
837
|
+
lines.push(`Session-approved tools: ${sessionAllowed.join(", ")}`);
|
|
838
|
+
} else {
|
|
839
|
+
lines.push("No session-approved tools.");
|
|
840
|
+
}
|
|
841
|
+
addMessage({ role: "system", content: lines.join("\n") });
|
|
842
|
+
return true;
|
|
843
|
+
}
|
|
844
|
+
case "context": {
|
|
845
|
+
const ctx = session.getContextState();
|
|
846
|
+
addMessage({
|
|
847
|
+
role: "system",
|
|
848
|
+
content: `Context: ${ctx.usedTokens.toLocaleString()} / ${ctx.maxTokens.toLocaleString()} tokens (${Math.round(ctx.usedPercentage)}%)`
|
|
849
|
+
});
|
|
850
|
+
return true;
|
|
851
|
+
}
|
|
852
|
+
case "reset": {
|
|
853
|
+
const { existsSync: exists, unlinkSync: unlink } = await import("fs");
|
|
854
|
+
const home = process.env.HOME ?? process.env.USERPROFILE ?? "/";
|
|
855
|
+
const settingsPath = `${home}/.robota/settings.json`;
|
|
856
|
+
if (exists(settingsPath)) {
|
|
857
|
+
unlink(settingsPath);
|
|
858
|
+
addMessage({ role: "system", content: `Deleted ${settingsPath}. Exiting...` });
|
|
859
|
+
} else {
|
|
860
|
+
addMessage({ role: "system", content: "No user settings found." });
|
|
861
|
+
}
|
|
862
|
+
setTimeout(() => exit(), 500);
|
|
863
|
+
return true;
|
|
864
|
+
}
|
|
832
865
|
case "exit":
|
|
833
866
|
exit();
|
|
834
867
|
return true;
|
|
@@ -869,15 +902,42 @@ function StreamingIndicator({ text }) {
|
|
|
869
902
|
async function runSessionPrompt(prompt, session, addMessage, clearStreamingText, setIsThinking, setContextPercentage) {
|
|
870
903
|
setIsThinking(true);
|
|
871
904
|
clearStreamingText();
|
|
905
|
+
const historyBefore = session.getHistory().length;
|
|
872
906
|
try {
|
|
873
907
|
const response = await session.run(prompt);
|
|
874
908
|
clearStreamingText();
|
|
909
|
+
const history = session.getHistory();
|
|
910
|
+
const toolLines = [];
|
|
911
|
+
for (let i = historyBefore; i < history.length; i++) {
|
|
912
|
+
const msg = history[i];
|
|
913
|
+
if (msg.role === "assistant" && msg.toolCalls) {
|
|
914
|
+
for (const tc of msg.toolCalls) {
|
|
915
|
+
let value = "";
|
|
916
|
+
try {
|
|
917
|
+
const parsed = JSON.parse(tc.function.arguments);
|
|
918
|
+
const firstVal = Object.values(parsed)[0];
|
|
919
|
+
value = typeof firstVal === "string" ? firstVal : JSON.stringify(firstVal);
|
|
920
|
+
} catch {
|
|
921
|
+
value = tc.function.arguments;
|
|
922
|
+
}
|
|
923
|
+
const truncated = value.length > 80 ? value.slice(0, 77) + "..." : value;
|
|
924
|
+
toolLines.push(`${tc.function.name}(${truncated})`);
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
if (toolLines.length > 0) {
|
|
929
|
+
addMessage({ role: "tool", content: toolLines.join("\n"), toolName: `${toolLines.length} tools` });
|
|
930
|
+
}
|
|
875
931
|
addMessage({ role: "assistant", content: response || "(empty response)" });
|
|
876
932
|
setContextPercentage(session.getContextState().usedPercentage);
|
|
877
933
|
} catch (err) {
|
|
878
934
|
clearStreamingText();
|
|
879
|
-
|
|
880
|
-
|
|
935
|
+
if (err instanceof DOMException && err.name === "AbortError") {
|
|
936
|
+
addMessage({ role: "system", content: "Cancelled." });
|
|
937
|
+
} else {
|
|
938
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
939
|
+
addMessage({ role: "system", content: `Error: ${errMsg}` });
|
|
940
|
+
}
|
|
881
941
|
} finally {
|
|
882
942
|
setIsThinking(false);
|
|
883
943
|
}
|
|
@@ -888,7 +948,15 @@ function buildSkillPrompt(input, registry) {
|
|
|
888
948
|
const skillCmd = registry.getCommands().find((c) => c.name === cmd && c.source === "skill");
|
|
889
949
|
if (!skillCmd) return null;
|
|
890
950
|
const args = parts.slice(1).join(" ").trim();
|
|
891
|
-
|
|
951
|
+
const userInstruction = args || skillCmd.description;
|
|
952
|
+
if (skillCmd.skillContent) {
|
|
953
|
+
return `<skill name="${cmd}">
|
|
954
|
+
${skillCmd.skillContent}
|
|
955
|
+
</skill>
|
|
956
|
+
|
|
957
|
+
Execute the "${cmd}" skill: ${userInstruction}`;
|
|
958
|
+
}
|
|
959
|
+
return `Use the "${cmd}" skill: ${userInstruction}`;
|
|
892
960
|
}
|
|
893
961
|
function useSubmitHandler(session, addMessage, handleSlashCommand, clearStreamingText, setIsThinking, setContextPercentage, registry) {
|
|
894
962
|
return (0, import_react5.useCallback)(
|
|
@@ -961,8 +1029,9 @@ function App(props) {
|
|
|
961
1029
|
(0, import_ink8.useInput)(
|
|
962
1030
|
(_input, key) => {
|
|
963
1031
|
if (key.ctrl && _input === "c") exit();
|
|
1032
|
+
if (key.escape && isThinking) session.abort();
|
|
964
1033
|
},
|
|
965
|
-
{ isActive: !permissionRequest
|
|
1034
|
+
{ isActive: !permissionRequest }
|
|
966
1035
|
);
|
|
967
1036
|
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_ink8.Box, { flexDirection: "column", children: [
|
|
968
1037
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_ink8.Box, { flexDirection: "column", paddingX: 1, marginBottom: 1, children: [
|
|
@@ -1083,7 +1152,8 @@ function parseCliArgs() {
|
|
|
1083
1152
|
model: { type: "string" },
|
|
1084
1153
|
"permission-mode": { type: "string" },
|
|
1085
1154
|
"max-turns": { type: "string" },
|
|
1086
|
-
version: { type: "boolean", default: false }
|
|
1155
|
+
version: { type: "boolean", default: false },
|
|
1156
|
+
reset: { type: "boolean", default: false }
|
|
1087
1157
|
}
|
|
1088
1158
|
});
|
|
1089
1159
|
return {
|
|
@@ -1094,7 +1164,8 @@ function parseCliArgs() {
|
|
|
1094
1164
|
model: values["model"],
|
|
1095
1165
|
permissionMode: parsePermissionMode(values["permission-mode"]),
|
|
1096
1166
|
maxTurns: parseMaxTurns(values["max-turns"]),
|
|
1097
|
-
version: values["version"] ?? false
|
|
1167
|
+
version: values["version"] ?? false,
|
|
1168
|
+
reset: values["reset"] ?? false
|
|
1098
1169
|
};
|
|
1099
1170
|
}
|
|
1100
1171
|
var PrintTerminal = class {
|
|
@@ -1145,6 +1216,83 @@ var PrintTerminal = class {
|
|
|
1145
1216
|
} };
|
|
1146
1217
|
}
|
|
1147
1218
|
};
|
|
1219
|
+
function getUserSettingsPath() {
|
|
1220
|
+
const home = process.env.HOME ?? process.env.USERPROFILE ?? "/";
|
|
1221
|
+
return (0, import_node_path2.join)(home, ".robota", "settings.json");
|
|
1222
|
+
}
|
|
1223
|
+
async function ensureConfig(cwd) {
|
|
1224
|
+
const userPath = getUserSettingsPath();
|
|
1225
|
+
const projectPath = (0, import_node_path2.join)(cwd, ".robota", "settings.json");
|
|
1226
|
+
const localPath = (0, import_node_path2.join)(cwd, ".robota", "settings.local.json");
|
|
1227
|
+
if ((0, import_node_fs2.existsSync)(userPath) || (0, import_node_fs2.existsSync)(projectPath) || (0, import_node_fs2.existsSync)(localPath)) {
|
|
1228
|
+
return;
|
|
1229
|
+
}
|
|
1230
|
+
process.stdout.write("\n");
|
|
1231
|
+
process.stdout.write(" Welcome to Robota CLI!\n");
|
|
1232
|
+
process.stdout.write(" No configuration found. Let's set up your API key.\n");
|
|
1233
|
+
process.stdout.write("\n");
|
|
1234
|
+
const apiKey = await new Promise((resolve) => {
|
|
1235
|
+
process.stdout.write(" Anthropic API key: ");
|
|
1236
|
+
let input = "";
|
|
1237
|
+
const stdin = process.stdin;
|
|
1238
|
+
const wasRaw = stdin.isRaw;
|
|
1239
|
+
stdin.setRawMode(true);
|
|
1240
|
+
stdin.resume();
|
|
1241
|
+
stdin.setEncoding("utf8");
|
|
1242
|
+
const onData = (data) => {
|
|
1243
|
+
for (const ch of data) {
|
|
1244
|
+
if (ch === "\r" || ch === "\n") {
|
|
1245
|
+
stdin.removeListener("data", onData);
|
|
1246
|
+
stdin.setRawMode(wasRaw ?? false);
|
|
1247
|
+
stdin.pause();
|
|
1248
|
+
process.stdout.write("\n");
|
|
1249
|
+
resolve(input.trim());
|
|
1250
|
+
return;
|
|
1251
|
+
} else if (ch === "\x7F" || ch === "\b") {
|
|
1252
|
+
if (input.length > 0) {
|
|
1253
|
+
input = input.slice(0, -1);
|
|
1254
|
+
process.stdout.write("\b \b");
|
|
1255
|
+
}
|
|
1256
|
+
} else if (ch === "") {
|
|
1257
|
+
process.stdout.write("\n");
|
|
1258
|
+
process.exit(0);
|
|
1259
|
+
} else if (ch.charCodeAt(0) >= 32) {
|
|
1260
|
+
input += ch;
|
|
1261
|
+
process.stdout.write("*");
|
|
1262
|
+
}
|
|
1263
|
+
}
|
|
1264
|
+
};
|
|
1265
|
+
stdin.on("data", onData);
|
|
1266
|
+
});
|
|
1267
|
+
if (!apiKey) {
|
|
1268
|
+
process.stderr.write("\n No API key provided. Exiting.\n");
|
|
1269
|
+
process.exit(1);
|
|
1270
|
+
}
|
|
1271
|
+
const settingsDir = (0, import_node_path2.dirname)(userPath);
|
|
1272
|
+
(0, import_node_fs2.mkdirSync)(settingsDir, { recursive: true });
|
|
1273
|
+
const settings = {
|
|
1274
|
+
provider: {
|
|
1275
|
+
name: "anthropic",
|
|
1276
|
+
model: "claude-sonnet-4-6",
|
|
1277
|
+
apiKey
|
|
1278
|
+
}
|
|
1279
|
+
};
|
|
1280
|
+
(0, import_node_fs2.writeFileSync)(userPath, JSON.stringify(settings, null, 2) + "\n", "utf8");
|
|
1281
|
+
process.stdout.write(`
|
|
1282
|
+
Config saved to ${userPath}
|
|
1283
|
+
|
|
1284
|
+
`);
|
|
1285
|
+
}
|
|
1286
|
+
function resetConfig() {
|
|
1287
|
+
const userPath = getUserSettingsPath();
|
|
1288
|
+
if ((0, import_node_fs2.existsSync)(userPath)) {
|
|
1289
|
+
(0, import_node_fs2.unlinkSync)(userPath);
|
|
1290
|
+
process.stdout.write(`Deleted ${userPath}
|
|
1291
|
+
`);
|
|
1292
|
+
} else {
|
|
1293
|
+
process.stdout.write("No user settings found.\n");
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
1148
1296
|
async function startCli() {
|
|
1149
1297
|
const args = parseCliArgs();
|
|
1150
1298
|
if (args.version) {
|
|
@@ -1152,7 +1300,12 @@ async function startCli() {
|
|
|
1152
1300
|
`);
|
|
1153
1301
|
return;
|
|
1154
1302
|
}
|
|
1303
|
+
if (args.reset) {
|
|
1304
|
+
resetConfig();
|
|
1305
|
+
return;
|
|
1306
|
+
}
|
|
1155
1307
|
const cwd = process.cwd();
|
|
1308
|
+
await ensureConfig(cwd);
|
|
1156
1309
|
const [config, context, projectInfo] = await Promise.all([
|
|
1157
1310
|
(0, import_agent_sdk2.loadConfig)(cwd),
|
|
1158
1311
|
(0, import_agent_sdk2.loadContext)(cwd),
|
|
@@ -1169,14 +1322,15 @@ async function startCli() {
|
|
|
1169
1322
|
process.exit(1);
|
|
1170
1323
|
}
|
|
1171
1324
|
const terminal = new PrintTerminal();
|
|
1172
|
-
const
|
|
1325
|
+
const paths = (0, import_agent_sdk2.projectPaths)(cwd);
|
|
1326
|
+
const session = (0, import_agent_sdk2.createSession)({
|
|
1173
1327
|
config,
|
|
1174
1328
|
context,
|
|
1175
1329
|
terminal,
|
|
1330
|
+
sessionLogger: new import_agent_sdk2.FileSessionLogger(paths.logs),
|
|
1176
1331
|
projectInfo,
|
|
1177
1332
|
permissionMode: args.permissionMode,
|
|
1178
|
-
|
|
1179
|
-
promptForApproval
|
|
1333
|
+
promptForApproval: import_agent_sdk3.promptForApproval
|
|
1180
1334
|
});
|
|
1181
1335
|
const response = await session.run(prompt);
|
|
1182
1336
|
process.stdout.write(response + "\n");
|
package/dist/node/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@robota-sdk/agent-cli",
|
|
3
|
-
"version": "3.0.0-beta.
|
|
3
|
+
"version": "3.0.0-beta.11",
|
|
4
4
|
"description": "AI coding assistant CLI built on Robota SDK",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
"marked-terminal": "^7.3.0",
|
|
36
36
|
"react": "19.2.4",
|
|
37
37
|
"string-width": "^8.2.0",
|
|
38
|
-
"@robota-sdk/agent-core": "3.0.0-beta.
|
|
39
|
-
"@robota-sdk/agent-sdk": "3.0.0-beta.
|
|
38
|
+
"@robota-sdk/agent-core": "3.0.0-beta.11",
|
|
39
|
+
"@robota-sdk/agent-sdk": "3.0.0-beta.11"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@types/marked": "^6.0.0",
|