@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/bin.cjs
CHANGED
|
@@ -30,26 +30,7 @@ var import_node_path2 = require("path");
|
|
|
30
30
|
var import_node_url = require("url");
|
|
31
31
|
var readline = __toESM(require("readline"), 1);
|
|
32
32
|
var import_agent_sdk2 = require("@robota-sdk/agent-sdk");
|
|
33
|
-
|
|
34
|
-
// src/permissions/permission-prompt.ts
|
|
35
|
-
var import_chalk = __toESM(require("chalk"), 1);
|
|
36
|
-
var PERMISSION_OPTIONS = ["Allow", "Deny"];
|
|
37
|
-
var ALLOW_INDEX = 0;
|
|
38
|
-
function formatArgs(toolArgs) {
|
|
39
|
-
const entries = Object.entries(toolArgs);
|
|
40
|
-
if (entries.length === 0) {
|
|
41
|
-
return "(no arguments)";
|
|
42
|
-
}
|
|
43
|
-
return entries.map(([k, v]) => `${k}: ${typeof v === "string" ? v : JSON.stringify(v)}`).join(", ");
|
|
44
|
-
}
|
|
45
|
-
async function promptForApproval(terminal, toolName, toolArgs) {
|
|
46
|
-
terminal.writeLine("");
|
|
47
|
-
terminal.writeLine(import_chalk.default.yellow(`[Permission Required] Tool: ${toolName}`));
|
|
48
|
-
terminal.writeLine(import_chalk.default.dim(` ${formatArgs(toolArgs)}`));
|
|
49
|
-
terminal.writeLine("");
|
|
50
|
-
const selected = await terminal.select(PERMISSION_OPTIONS, ALLOW_INDEX);
|
|
51
|
-
return selected === ALLOW_INDEX;
|
|
52
|
-
}
|
|
33
|
+
var import_agent_sdk3 = require("@robota-sdk/agent-sdk");
|
|
53
34
|
|
|
54
35
|
// src/ui/render.tsx
|
|
55
36
|
var import_ink9 = require("ink");
|
|
@@ -119,6 +100,7 @@ function createBuiltinCommands() {
|
|
|
119
100
|
{ name: "cost", description: "Show session info", source: "builtin" },
|
|
120
101
|
{ name: "context", description: "Context window info", source: "builtin" },
|
|
121
102
|
{ name: "permissions", description: "Permission rules", source: "builtin" },
|
|
103
|
+
{ name: "reset", description: "Delete settings and exit", source: "builtin" },
|
|
122
104
|
{ name: "exit", description: "Exit CLI", source: "builtin" }
|
|
123
105
|
];
|
|
124
106
|
}
|
|
@@ -170,7 +152,8 @@ function scanSkillsDir(skillsDir) {
|
|
|
170
152
|
commands.push({
|
|
171
153
|
name: frontmatter?.name ?? entry.name,
|
|
172
154
|
description: frontmatter?.description ?? `Skill: ${entry.name}`,
|
|
173
|
-
source: "skill"
|
|
155
|
+
source: "skill",
|
|
156
|
+
skillContent: content
|
|
174
157
|
});
|
|
175
158
|
}
|
|
176
159
|
return commands;
|
|
@@ -324,7 +307,7 @@ var import_ink6 = require("ink");
|
|
|
324
307
|
var import_react = require("react");
|
|
325
308
|
var import_ink3 = require("ink");
|
|
326
309
|
var import_string_width = __toESM(require("string-width"), 1);
|
|
327
|
-
var
|
|
310
|
+
var import_chalk = __toESM(require("chalk"), 1);
|
|
328
311
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
329
312
|
function CjkTextInput({
|
|
330
313
|
value,
|
|
@@ -346,71 +329,81 @@ function CjkTextInput({
|
|
|
346
329
|
}
|
|
347
330
|
(0, import_ink3.useInput)(
|
|
348
331
|
(input, key) => {
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
if (key.return) {
|
|
353
|
-
onSubmit?.(valueRef.current);
|
|
354
|
-
return;
|
|
355
|
-
}
|
|
356
|
-
if (key.leftArrow) {
|
|
357
|
-
if (cursorRef.current > 0) {
|
|
358
|
-
cursorRef.current -= 1;
|
|
359
|
-
forceRender((n) => n + 1);
|
|
332
|
+
try {
|
|
333
|
+
if (key.upArrow || key.downArrow || key.ctrl && input === "c" || key.tab || key.shift && key.tab) {
|
|
334
|
+
return;
|
|
360
335
|
}
|
|
361
|
-
return
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
if (cursorRef.current < valueRef.current.length) {
|
|
365
|
-
cursorRef.current += 1;
|
|
366
|
-
forceRender((n) => n + 1);
|
|
336
|
+
if (key.return) {
|
|
337
|
+
onSubmit?.(valueRef.current);
|
|
338
|
+
return;
|
|
367
339
|
}
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
cursorRef.current -= 1;
|
|
375
|
-
valueRef.current = next2;
|
|
376
|
-
onChange(next2);
|
|
340
|
+
if (key.leftArrow) {
|
|
341
|
+
if (cursorRef.current > 0) {
|
|
342
|
+
cursorRef.current -= 1;
|
|
343
|
+
forceRender((n) => n + 1);
|
|
344
|
+
}
|
|
345
|
+
return;
|
|
377
346
|
}
|
|
378
|
-
|
|
347
|
+
if (key.rightArrow) {
|
|
348
|
+
if (cursorRef.current < valueRef.current.length) {
|
|
349
|
+
cursorRef.current += 1;
|
|
350
|
+
forceRender((n) => n + 1);
|
|
351
|
+
}
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
if (key.backspace || key.delete) {
|
|
355
|
+
if (cursorRef.current > 0) {
|
|
356
|
+
const v2 = valueRef.current;
|
|
357
|
+
const next2 = v2.slice(0, cursorRef.current - 1) + v2.slice(cursorRef.current);
|
|
358
|
+
cursorRef.current -= 1;
|
|
359
|
+
valueRef.current = next2;
|
|
360
|
+
onChange(next2);
|
|
361
|
+
}
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
if (!input || input.length === 0) return;
|
|
365
|
+
const printable = input.replace(/[\x00-\x1f\x7f]/g, "");
|
|
366
|
+
if (printable.length === 0) return;
|
|
367
|
+
const v = valueRef.current;
|
|
368
|
+
const c = cursorRef.current;
|
|
369
|
+
const next = v.slice(0, c) + printable + v.slice(c);
|
|
370
|
+
cursorRef.current = c + printable.length;
|
|
371
|
+
valueRef.current = next;
|
|
372
|
+
onChange(next);
|
|
373
|
+
} catch {
|
|
379
374
|
}
|
|
380
|
-
const v = valueRef.current;
|
|
381
|
-
const c = cursorRef.current;
|
|
382
|
-
const next = v.slice(0, c) + input + v.slice(c);
|
|
383
|
-
cursorRef.current = c + input.length;
|
|
384
|
-
valueRef.current = next;
|
|
385
|
-
onChange(next);
|
|
386
375
|
},
|
|
387
376
|
{ isActive: focus }
|
|
388
377
|
);
|
|
389
378
|
if (showCursor && focus) {
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
379
|
+
try {
|
|
380
|
+
const textBeforeCursor = [...valueRef.current].slice(0, cursorRef.current).join("");
|
|
381
|
+
const cursorX = 4 + (0, import_string_width.default)(textBeforeCursor);
|
|
382
|
+
setCursorPosition({ x: cursorX, y: 0 });
|
|
383
|
+
} catch {
|
|
384
|
+
setCursorPosition({ x: 4, y: 0 });
|
|
385
|
+
}
|
|
393
386
|
}
|
|
394
387
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_ink3.Text, { children: renderWithCursor(valueRef.current, cursorRef.current, placeholder, showCursor && focus) });
|
|
395
388
|
}
|
|
396
389
|
function renderWithCursor(value, cursorOffset, placeholder, showCursor) {
|
|
397
390
|
if (!showCursor) {
|
|
398
|
-
return value.length > 0 ? value : placeholder ?
|
|
391
|
+
return value.length > 0 ? value : placeholder ? import_chalk.default.gray(placeholder) : "";
|
|
399
392
|
}
|
|
400
393
|
if (value.length === 0) {
|
|
401
394
|
if (placeholder.length > 0) {
|
|
402
|
-
return
|
|
395
|
+
return import_chalk.default.inverse(placeholder[0]) + import_chalk.default.gray(placeholder.slice(1));
|
|
403
396
|
}
|
|
404
|
-
return
|
|
397
|
+
return import_chalk.default.inverse(" ");
|
|
405
398
|
}
|
|
406
399
|
const chars = [...value];
|
|
407
400
|
let rendered = "";
|
|
408
401
|
for (let i = 0; i < chars.length; i++) {
|
|
409
402
|
const char = chars[i] ?? "";
|
|
410
|
-
rendered += i === cursorOffset ?
|
|
403
|
+
rendered += i === cursorOffset ? import_chalk.default.inverse(char) : char;
|
|
411
404
|
}
|
|
412
405
|
if (cursorOffset >= chars.length) {
|
|
413
|
-
rendered +=
|
|
406
|
+
rendered += import_chalk.default.inverse(" ");
|
|
414
407
|
}
|
|
415
408
|
return rendered;
|
|
416
409
|
}
|
|
@@ -625,8 +618,8 @@ function InputArea({ onSubmit, isDisabled, registry }) {
|
|
|
625
618
|
var import_react4 = __toESM(require("react"), 1);
|
|
626
619
|
var import_ink7 = require("ink");
|
|
627
620
|
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
628
|
-
var OPTIONS = ["Allow", "Deny"];
|
|
629
|
-
function
|
|
621
|
+
var OPTIONS = ["Allow", "Allow always (this session)", "Deny"];
|
|
622
|
+
function formatArgs(args) {
|
|
630
623
|
const entries = Object.entries(args);
|
|
631
624
|
if (entries.length === 0) return "(no arguments)";
|
|
632
625
|
return entries.map(([k, v]) => `${k}: ${typeof v === "string" ? v : JSON.stringify(v)}`).join(", ");
|
|
@@ -641,10 +634,12 @@ function PermissionPrompt({ request }) {
|
|
|
641
634
|
setSelected(0);
|
|
642
635
|
}
|
|
643
636
|
const doResolve = import_react4.default.useCallback(
|
|
644
|
-
(
|
|
637
|
+
(index) => {
|
|
645
638
|
if (resolvedRef.current) return;
|
|
646
639
|
resolvedRef.current = true;
|
|
647
|
-
request.resolve(
|
|
640
|
+
if (index === 0) request.resolve(true);
|
|
641
|
+
else if (index === 1) request.resolve("allow-session");
|
|
642
|
+
else request.resolve(false);
|
|
648
643
|
},
|
|
649
644
|
[request]
|
|
650
645
|
);
|
|
@@ -655,11 +650,13 @@ function PermissionPrompt({ request }) {
|
|
|
655
650
|
} else if (key.downArrow || key.rightArrow) {
|
|
656
651
|
setSelected((prev) => prev < OPTIONS.length - 1 ? prev + 1 : prev);
|
|
657
652
|
} else if (key.return) {
|
|
658
|
-
doResolve(selected
|
|
659
|
-
} else if (input === "y" || input === "
|
|
660
|
-
doResolve(
|
|
661
|
-
} else if (input === "
|
|
662
|
-
doResolve(
|
|
653
|
+
doResolve(selected);
|
|
654
|
+
} else if (input === "y" || input === "1") {
|
|
655
|
+
doResolve(0);
|
|
656
|
+
} else if (input === "a" || input === "2") {
|
|
657
|
+
doResolve(1);
|
|
658
|
+
} else if (input === "n" || input === "d" || input === "3") {
|
|
659
|
+
doResolve(2);
|
|
663
660
|
}
|
|
664
661
|
});
|
|
665
662
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_ink7.Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
|
|
@@ -671,7 +668,7 @@ function PermissionPrompt({ request }) {
|
|
|
671
668
|
] }),
|
|
672
669
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_ink7.Text, { dimColor: true, children: [
|
|
673
670
|
" ",
|
|
674
|
-
|
|
671
|
+
formatArgs(request.toolArgs)
|
|
675
672
|
] }),
|
|
676
673
|
/* @__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: [
|
|
677
674
|
i === selected ? "> " : " ",
|
|
@@ -719,11 +716,11 @@ function useSession(props) {
|
|
|
719
716
|
setPermissionRequest({
|
|
720
717
|
toolName: next.toolName,
|
|
721
718
|
toolArgs: next.toolArgs,
|
|
722
|
-
resolve: (
|
|
719
|
+
resolve: (result) => {
|
|
723
720
|
permissionQueueRef.current.shift();
|
|
724
721
|
processingRef.current = false;
|
|
725
722
|
setPermissionRequest(null);
|
|
726
|
-
next.resolve(
|
|
723
|
+
next.resolve(result);
|
|
727
724
|
setTimeout(() => processNextPermission(), 0);
|
|
728
725
|
}
|
|
729
726
|
});
|
|
@@ -739,10 +736,12 @@ function useSession(props) {
|
|
|
739
736
|
const onTextDelta = (delta) => {
|
|
740
737
|
setStreamingText((prev) => prev + delta);
|
|
741
738
|
};
|
|
742
|
-
|
|
739
|
+
const paths = (0, import_agent_sdk.projectPaths)(props.cwd ?? process.cwd());
|
|
740
|
+
sessionRef.current = (0, import_agent_sdk.createSession)({
|
|
743
741
|
config: props.config,
|
|
744
742
|
context: props.context,
|
|
745
743
|
terminal: NOOP_TERMINAL,
|
|
744
|
+
sessionLogger: new import_agent_sdk.FileSessionLogger(paths.logs),
|
|
746
745
|
projectInfo: props.projectInfo,
|
|
747
746
|
sessionStore: props.sessionStore,
|
|
748
747
|
permissionMode: props.permissionMode,
|
|
@@ -768,6 +767,7 @@ var HELP_TEXT = [
|
|
|
768
767
|
" /compact [instr] \u2014 Compact context (optional focus instructions)",
|
|
769
768
|
" /mode [m] \u2014 Show/change permission mode",
|
|
770
769
|
" /cost \u2014 Show session info",
|
|
770
|
+
" /reset \u2014 Delete settings and exit",
|
|
771
771
|
" /exit \u2014 Exit CLI"
|
|
772
772
|
].join("\n");
|
|
773
773
|
function handleModeCommand(arg, session, addMessage) {
|
|
@@ -813,6 +813,39 @@ async function executeSlashCommand(cmd, parts, session, addMessage, setMessages,
|
|
|
813
813
|
Messages: ${session.getMessageCount()}`
|
|
814
814
|
});
|
|
815
815
|
return true;
|
|
816
|
+
case "permissions": {
|
|
817
|
+
const mode = session.getPermissionMode();
|
|
818
|
+
const sessionAllowed = session.getSessionAllowedTools();
|
|
819
|
+
const lines = [`Permission mode: ${mode}`];
|
|
820
|
+
if (sessionAllowed.length > 0) {
|
|
821
|
+
lines.push(`Session-approved tools: ${sessionAllowed.join(", ")}`);
|
|
822
|
+
} else {
|
|
823
|
+
lines.push("No session-approved tools.");
|
|
824
|
+
}
|
|
825
|
+
addMessage({ role: "system", content: lines.join("\n") });
|
|
826
|
+
return true;
|
|
827
|
+
}
|
|
828
|
+
case "context": {
|
|
829
|
+
const ctx = session.getContextState();
|
|
830
|
+
addMessage({
|
|
831
|
+
role: "system",
|
|
832
|
+
content: `Context: ${ctx.usedTokens.toLocaleString()} / ${ctx.maxTokens.toLocaleString()} tokens (${Math.round(ctx.usedPercentage)}%)`
|
|
833
|
+
});
|
|
834
|
+
return true;
|
|
835
|
+
}
|
|
836
|
+
case "reset": {
|
|
837
|
+
const { existsSync: exists, unlinkSync: unlink } = await import("fs");
|
|
838
|
+
const home = process.env.HOME ?? process.env.USERPROFILE ?? "/";
|
|
839
|
+
const settingsPath = `${home}/.robota/settings.json`;
|
|
840
|
+
if (exists(settingsPath)) {
|
|
841
|
+
unlink(settingsPath);
|
|
842
|
+
addMessage({ role: "system", content: `Deleted ${settingsPath}. Exiting...` });
|
|
843
|
+
} else {
|
|
844
|
+
addMessage({ role: "system", content: "No user settings found." });
|
|
845
|
+
}
|
|
846
|
+
setTimeout(() => exit(), 500);
|
|
847
|
+
return true;
|
|
848
|
+
}
|
|
816
849
|
case "exit":
|
|
817
850
|
exit();
|
|
818
851
|
return true;
|
|
@@ -853,15 +886,42 @@ function StreamingIndicator({ text }) {
|
|
|
853
886
|
async function runSessionPrompt(prompt, session, addMessage, clearStreamingText, setIsThinking, setContextPercentage) {
|
|
854
887
|
setIsThinking(true);
|
|
855
888
|
clearStreamingText();
|
|
889
|
+
const historyBefore = session.getHistory().length;
|
|
856
890
|
try {
|
|
857
891
|
const response = await session.run(prompt);
|
|
858
892
|
clearStreamingText();
|
|
893
|
+
const history = session.getHistory();
|
|
894
|
+
const toolLines = [];
|
|
895
|
+
for (let i = historyBefore; i < history.length; i++) {
|
|
896
|
+
const msg = history[i];
|
|
897
|
+
if (msg.role === "assistant" && msg.toolCalls) {
|
|
898
|
+
for (const tc of msg.toolCalls) {
|
|
899
|
+
let value = "";
|
|
900
|
+
try {
|
|
901
|
+
const parsed = JSON.parse(tc.function.arguments);
|
|
902
|
+
const firstVal = Object.values(parsed)[0];
|
|
903
|
+
value = typeof firstVal === "string" ? firstVal : JSON.stringify(firstVal);
|
|
904
|
+
} catch {
|
|
905
|
+
value = tc.function.arguments;
|
|
906
|
+
}
|
|
907
|
+
const truncated = value.length > 80 ? value.slice(0, 77) + "..." : value;
|
|
908
|
+
toolLines.push(`${tc.function.name}(${truncated})`);
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
if (toolLines.length > 0) {
|
|
913
|
+
addMessage({ role: "tool", content: toolLines.join("\n"), toolName: `${toolLines.length} tools` });
|
|
914
|
+
}
|
|
859
915
|
addMessage({ role: "assistant", content: response || "(empty response)" });
|
|
860
916
|
setContextPercentage(session.getContextState().usedPercentage);
|
|
861
917
|
} catch (err) {
|
|
862
918
|
clearStreamingText();
|
|
863
|
-
|
|
864
|
-
|
|
919
|
+
if (err instanceof DOMException && err.name === "AbortError") {
|
|
920
|
+
addMessage({ role: "system", content: "Cancelled." });
|
|
921
|
+
} else {
|
|
922
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
923
|
+
addMessage({ role: "system", content: `Error: ${errMsg}` });
|
|
924
|
+
}
|
|
865
925
|
} finally {
|
|
866
926
|
setIsThinking(false);
|
|
867
927
|
}
|
|
@@ -872,7 +932,15 @@ function buildSkillPrompt(input, registry) {
|
|
|
872
932
|
const skillCmd = registry.getCommands().find((c) => c.name === cmd && c.source === "skill");
|
|
873
933
|
if (!skillCmd) return null;
|
|
874
934
|
const args = parts.slice(1).join(" ").trim();
|
|
875
|
-
|
|
935
|
+
const userInstruction = args || skillCmd.description;
|
|
936
|
+
if (skillCmd.skillContent) {
|
|
937
|
+
return `<skill name="${cmd}">
|
|
938
|
+
${skillCmd.skillContent}
|
|
939
|
+
</skill>
|
|
940
|
+
|
|
941
|
+
Execute the "${cmd}" skill: ${userInstruction}`;
|
|
942
|
+
}
|
|
943
|
+
return `Use the "${cmd}" skill: ${userInstruction}`;
|
|
876
944
|
}
|
|
877
945
|
function useSubmitHandler(session, addMessage, handleSlashCommand, clearStreamingText, setIsThinking, setContextPercentage, registry) {
|
|
878
946
|
return (0, import_react5.useCallback)(
|
|
@@ -945,8 +1013,9 @@ function App(props) {
|
|
|
945
1013
|
(0, import_ink8.useInput)(
|
|
946
1014
|
(_input, key) => {
|
|
947
1015
|
if (key.ctrl && _input === "c") exit();
|
|
1016
|
+
if (key.escape && isThinking) session.abort();
|
|
948
1017
|
},
|
|
949
|
-
{ isActive: !permissionRequest
|
|
1018
|
+
{ isActive: !permissionRequest }
|
|
950
1019
|
);
|
|
951
1020
|
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_ink8.Box, { flexDirection: "column", children: [
|
|
952
1021
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_ink8.Box, { flexDirection: "column", paddingX: 1, marginBottom: 1, children: [
|
|
@@ -1067,7 +1136,8 @@ function parseCliArgs() {
|
|
|
1067
1136
|
model: { type: "string" },
|
|
1068
1137
|
"permission-mode": { type: "string" },
|
|
1069
1138
|
"max-turns": { type: "string" },
|
|
1070
|
-
version: { type: "boolean", default: false }
|
|
1139
|
+
version: { type: "boolean", default: false },
|
|
1140
|
+
reset: { type: "boolean", default: false }
|
|
1071
1141
|
}
|
|
1072
1142
|
});
|
|
1073
1143
|
return {
|
|
@@ -1078,7 +1148,8 @@ function parseCliArgs() {
|
|
|
1078
1148
|
model: values["model"],
|
|
1079
1149
|
permissionMode: parsePermissionMode(values["permission-mode"]),
|
|
1080
1150
|
maxTurns: parseMaxTurns(values["max-turns"]),
|
|
1081
|
-
version: values["version"] ?? false
|
|
1151
|
+
version: values["version"] ?? false,
|
|
1152
|
+
reset: values["reset"] ?? false
|
|
1082
1153
|
};
|
|
1083
1154
|
}
|
|
1084
1155
|
var PrintTerminal = class {
|
|
@@ -1129,6 +1200,83 @@ var PrintTerminal = class {
|
|
|
1129
1200
|
} };
|
|
1130
1201
|
}
|
|
1131
1202
|
};
|
|
1203
|
+
function getUserSettingsPath() {
|
|
1204
|
+
const home = process.env.HOME ?? process.env.USERPROFILE ?? "/";
|
|
1205
|
+
return (0, import_node_path2.join)(home, ".robota", "settings.json");
|
|
1206
|
+
}
|
|
1207
|
+
async function ensureConfig(cwd) {
|
|
1208
|
+
const userPath = getUserSettingsPath();
|
|
1209
|
+
const projectPath = (0, import_node_path2.join)(cwd, ".robota", "settings.json");
|
|
1210
|
+
const localPath = (0, import_node_path2.join)(cwd, ".robota", "settings.local.json");
|
|
1211
|
+
if ((0, import_node_fs2.existsSync)(userPath) || (0, import_node_fs2.existsSync)(projectPath) || (0, import_node_fs2.existsSync)(localPath)) {
|
|
1212
|
+
return;
|
|
1213
|
+
}
|
|
1214
|
+
process.stdout.write("\n");
|
|
1215
|
+
process.stdout.write(" Welcome to Robota CLI!\n");
|
|
1216
|
+
process.stdout.write(" No configuration found. Let's set up your API key.\n");
|
|
1217
|
+
process.stdout.write("\n");
|
|
1218
|
+
const apiKey = await new Promise((resolve) => {
|
|
1219
|
+
process.stdout.write(" Anthropic API key: ");
|
|
1220
|
+
let input = "";
|
|
1221
|
+
const stdin = process.stdin;
|
|
1222
|
+
const wasRaw = stdin.isRaw;
|
|
1223
|
+
stdin.setRawMode(true);
|
|
1224
|
+
stdin.resume();
|
|
1225
|
+
stdin.setEncoding("utf8");
|
|
1226
|
+
const onData = (data) => {
|
|
1227
|
+
for (const ch of data) {
|
|
1228
|
+
if (ch === "\r" || ch === "\n") {
|
|
1229
|
+
stdin.removeListener("data", onData);
|
|
1230
|
+
stdin.setRawMode(wasRaw ?? false);
|
|
1231
|
+
stdin.pause();
|
|
1232
|
+
process.stdout.write("\n");
|
|
1233
|
+
resolve(input.trim());
|
|
1234
|
+
return;
|
|
1235
|
+
} else if (ch === "\x7F" || ch === "\b") {
|
|
1236
|
+
if (input.length > 0) {
|
|
1237
|
+
input = input.slice(0, -1);
|
|
1238
|
+
process.stdout.write("\b \b");
|
|
1239
|
+
}
|
|
1240
|
+
} else if (ch === "") {
|
|
1241
|
+
process.stdout.write("\n");
|
|
1242
|
+
process.exit(0);
|
|
1243
|
+
} else if (ch.charCodeAt(0) >= 32) {
|
|
1244
|
+
input += ch;
|
|
1245
|
+
process.stdout.write("*");
|
|
1246
|
+
}
|
|
1247
|
+
}
|
|
1248
|
+
};
|
|
1249
|
+
stdin.on("data", onData);
|
|
1250
|
+
});
|
|
1251
|
+
if (!apiKey) {
|
|
1252
|
+
process.stderr.write("\n No API key provided. Exiting.\n");
|
|
1253
|
+
process.exit(1);
|
|
1254
|
+
}
|
|
1255
|
+
const settingsDir = (0, import_node_path2.dirname)(userPath);
|
|
1256
|
+
(0, import_node_fs2.mkdirSync)(settingsDir, { recursive: true });
|
|
1257
|
+
const settings = {
|
|
1258
|
+
provider: {
|
|
1259
|
+
name: "anthropic",
|
|
1260
|
+
model: "claude-sonnet-4-6",
|
|
1261
|
+
apiKey
|
|
1262
|
+
}
|
|
1263
|
+
};
|
|
1264
|
+
(0, import_node_fs2.writeFileSync)(userPath, JSON.stringify(settings, null, 2) + "\n", "utf8");
|
|
1265
|
+
process.stdout.write(`
|
|
1266
|
+
Config saved to ${userPath}
|
|
1267
|
+
|
|
1268
|
+
`);
|
|
1269
|
+
}
|
|
1270
|
+
function resetConfig() {
|
|
1271
|
+
const userPath = getUserSettingsPath();
|
|
1272
|
+
if ((0, import_node_fs2.existsSync)(userPath)) {
|
|
1273
|
+
(0, import_node_fs2.unlinkSync)(userPath);
|
|
1274
|
+
process.stdout.write(`Deleted ${userPath}
|
|
1275
|
+
`);
|
|
1276
|
+
} else {
|
|
1277
|
+
process.stdout.write("No user settings found.\n");
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1132
1280
|
async function startCli() {
|
|
1133
1281
|
const args = parseCliArgs();
|
|
1134
1282
|
if (args.version) {
|
|
@@ -1136,7 +1284,12 @@ async function startCli() {
|
|
|
1136
1284
|
`);
|
|
1137
1285
|
return;
|
|
1138
1286
|
}
|
|
1287
|
+
if (args.reset) {
|
|
1288
|
+
resetConfig();
|
|
1289
|
+
return;
|
|
1290
|
+
}
|
|
1139
1291
|
const cwd = process.cwd();
|
|
1292
|
+
await ensureConfig(cwd);
|
|
1140
1293
|
const [config, context, projectInfo] = await Promise.all([
|
|
1141
1294
|
(0, import_agent_sdk2.loadConfig)(cwd),
|
|
1142
1295
|
(0, import_agent_sdk2.loadContext)(cwd),
|
|
@@ -1153,14 +1306,15 @@ async function startCli() {
|
|
|
1153
1306
|
process.exit(1);
|
|
1154
1307
|
}
|
|
1155
1308
|
const terminal = new PrintTerminal();
|
|
1156
|
-
const
|
|
1309
|
+
const paths = (0, import_agent_sdk2.projectPaths)(cwd);
|
|
1310
|
+
const session = (0, import_agent_sdk2.createSession)({
|
|
1157
1311
|
config,
|
|
1158
1312
|
context,
|
|
1159
1313
|
terminal,
|
|
1314
|
+
sessionLogger: new import_agent_sdk2.FileSessionLogger(paths.logs),
|
|
1160
1315
|
projectInfo,
|
|
1161
1316
|
permissionMode: args.permissionMode,
|
|
1162
|
-
|
|
1163
|
-
promptForApproval
|
|
1317
|
+
promptForApproval: import_agent_sdk3.promptForApproval
|
|
1164
1318
|
});
|
|
1165
1319
|
const response = await session.run(prompt);
|
|
1166
1320
|
process.stdout.write(response + "\n");
|
|
@@ -1178,6 +1332,16 @@ async function startCli() {
|
|
|
1178
1332
|
}
|
|
1179
1333
|
|
|
1180
1334
|
// src/bin.ts
|
|
1335
|
+
process.on("uncaughtException", (err) => {
|
|
1336
|
+
const msg = err.message ?? "";
|
|
1337
|
+
const isLikelyIME = msg.includes("string-width") || msg.includes("setCursorPosition") || msg.includes("getStringWidth") || msg.includes("slice") || msg.includes("charCodeAt");
|
|
1338
|
+
if (isLikelyIME) {
|
|
1339
|
+
process.stderr.write(`[robota] IME error suppressed: ${msg}
|
|
1340
|
+
`);
|
|
1341
|
+
return;
|
|
1342
|
+
}
|
|
1343
|
+
throw err;
|
|
1344
|
+
});
|
|
1181
1345
|
startCli().catch((err) => {
|
|
1182
1346
|
const message = err instanceof Error ? err.message : String(err);
|
|
1183
1347
|
process.stderr.write(message + "\n");
|
package/dist/node/bin.js
CHANGED
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
startCli
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-CT2VGJIF.js";
|
|
5
5
|
|
|
6
6
|
// src/bin.ts
|
|
7
|
+
process.on("uncaughtException", (err) => {
|
|
8
|
+
const msg = err.message ?? "";
|
|
9
|
+
const isLikelyIME = msg.includes("string-width") || msg.includes("setCursorPosition") || msg.includes("getStringWidth") || msg.includes("slice") || msg.includes("charCodeAt");
|
|
10
|
+
if (isLikelyIME) {
|
|
11
|
+
process.stderr.write(`[robota] IME error suppressed: ${msg}
|
|
12
|
+
`);
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
throw err;
|
|
16
|
+
});
|
|
7
17
|
startCli().catch((err) => {
|
|
8
18
|
const message = err instanceof Error ? err.message : String(err);
|
|
9
19
|
process.stderr.write(message + "\n");
|