@robota-sdk/agent-cli 3.0.0-beta.17 → 3.0.0-beta.19
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 +353 -290
- package/dist/node/bin.js +1 -1
- package/dist/node/{chunk-4WB3L3RU.js → chunk-RE4JCNEA.js} +342 -279
- package/dist/node/index.cjs +353 -290
- package/dist/node/index.js +1 -1
- package/package.json +3 -3
package/dist/node/index.cjs
CHANGED
|
@@ -177,11 +177,126 @@ var PrintTerminal = class {
|
|
|
177
177
|
};
|
|
178
178
|
|
|
179
179
|
// src/ui/render.tsx
|
|
180
|
-
var
|
|
180
|
+
var import_ink11 = require("ink");
|
|
181
181
|
|
|
182
182
|
// src/ui/App.tsx
|
|
183
|
-
var
|
|
184
|
-
var
|
|
183
|
+
var import_react11 = require("react");
|
|
184
|
+
var import_ink10 = require("ink");
|
|
185
|
+
var import_agent_core3 = require("@robota-sdk/agent-core");
|
|
186
|
+
|
|
187
|
+
// src/ui/hooks/useSession.ts
|
|
188
|
+
var import_react = require("react");
|
|
189
|
+
var import_agent_sdk = require("@robota-sdk/agent-sdk");
|
|
190
|
+
var TOOL_ARG_DISPLAY_MAX = 80;
|
|
191
|
+
var TOOL_ARG_TRUNCATE_AT = 77;
|
|
192
|
+
var NOOP_TERMINAL = {
|
|
193
|
+
write: () => {
|
|
194
|
+
},
|
|
195
|
+
writeLine: () => {
|
|
196
|
+
},
|
|
197
|
+
writeMarkdown: () => {
|
|
198
|
+
},
|
|
199
|
+
writeError: () => {
|
|
200
|
+
},
|
|
201
|
+
prompt: () => Promise.resolve(""),
|
|
202
|
+
select: () => Promise.resolve(0),
|
|
203
|
+
spinner: () => ({ stop: () => {
|
|
204
|
+
}, update: () => {
|
|
205
|
+
} })
|
|
206
|
+
};
|
|
207
|
+
function useSession(props) {
|
|
208
|
+
const [permissionRequest, setPermissionRequest] = (0, import_react.useState)(null);
|
|
209
|
+
const [streamingText, setStreamingText] = (0, import_react.useState)("");
|
|
210
|
+
const [activeTools, setActiveTools] = (0, import_react.useState)([]);
|
|
211
|
+
const permissionQueueRef = (0, import_react.useRef)([]);
|
|
212
|
+
const processingRef = (0, import_react.useRef)(false);
|
|
213
|
+
const processNextPermission = (0, import_react.useCallback)(() => {
|
|
214
|
+
if (processingRef.current) return;
|
|
215
|
+
const next = permissionQueueRef.current[0];
|
|
216
|
+
if (!next) {
|
|
217
|
+
setPermissionRequest(null);
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
processingRef.current = true;
|
|
221
|
+
setPermissionRequest({
|
|
222
|
+
toolName: next.toolName,
|
|
223
|
+
toolArgs: next.toolArgs,
|
|
224
|
+
resolve: (result) => {
|
|
225
|
+
permissionQueueRef.current.shift();
|
|
226
|
+
processingRef.current = false;
|
|
227
|
+
setPermissionRequest(null);
|
|
228
|
+
next.resolve(result);
|
|
229
|
+
setTimeout(() => processNextPermission(), 0);
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
}, []);
|
|
233
|
+
const sessionRef = (0, import_react.useRef)(null);
|
|
234
|
+
if (sessionRef.current === null) {
|
|
235
|
+
const permissionHandler = (toolName, toolArgs) => {
|
|
236
|
+
return new Promise((resolve) => {
|
|
237
|
+
permissionQueueRef.current.push({ toolName, toolArgs, resolve });
|
|
238
|
+
processNextPermission();
|
|
239
|
+
});
|
|
240
|
+
};
|
|
241
|
+
const onTextDelta = (delta) => {
|
|
242
|
+
setStreamingText((prev) => prev + delta);
|
|
243
|
+
};
|
|
244
|
+
const onToolExecution = (event) => {
|
|
245
|
+
if (event.type === "start") {
|
|
246
|
+
let firstArg = "";
|
|
247
|
+
if (event.toolArgs) {
|
|
248
|
+
const firstVal = Object.values(event.toolArgs)[0];
|
|
249
|
+
const raw = typeof firstVal === "string" ? firstVal : JSON.stringify(firstVal ?? "");
|
|
250
|
+
firstArg = raw.length > TOOL_ARG_DISPLAY_MAX ? raw.slice(0, TOOL_ARG_TRUNCATE_AT) + "..." : raw;
|
|
251
|
+
}
|
|
252
|
+
setActiveTools((prev) => [...prev, { toolName: event.toolName, firstArg, isRunning: true }]);
|
|
253
|
+
} else {
|
|
254
|
+
setActiveTools(
|
|
255
|
+
(prev) => prev.map(
|
|
256
|
+
(t) => t.toolName === event.toolName && t.isRunning ? { ...t, isRunning: false } : t
|
|
257
|
+
)
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
const paths = (0, import_agent_sdk.projectPaths)(props.cwd ?? process.cwd());
|
|
262
|
+
sessionRef.current = (0, import_agent_sdk.createSession)({
|
|
263
|
+
config: props.config,
|
|
264
|
+
context: props.context,
|
|
265
|
+
terminal: NOOP_TERMINAL,
|
|
266
|
+
sessionLogger: new import_agent_sdk.FileSessionLogger(paths.logs),
|
|
267
|
+
projectInfo: props.projectInfo,
|
|
268
|
+
sessionStore: props.sessionStore,
|
|
269
|
+
permissionMode: props.permissionMode,
|
|
270
|
+
maxTurns: props.maxTurns,
|
|
271
|
+
permissionHandler,
|
|
272
|
+
onTextDelta,
|
|
273
|
+
onToolExecution
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
const clearStreamingText = (0, import_react.useCallback)(() => {
|
|
277
|
+
setStreamingText("");
|
|
278
|
+
setActiveTools([]);
|
|
279
|
+
}, []);
|
|
280
|
+
return { session: sessionRef.current, permissionRequest, streamingText, clearStreamingText, activeTools };
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// src/ui/hooks/useMessages.ts
|
|
284
|
+
var import_react2 = require("react");
|
|
285
|
+
var msgIdCounter = 0;
|
|
286
|
+
function nextId() {
|
|
287
|
+
msgIdCounter += 1;
|
|
288
|
+
return `msg_${msgIdCounter}`;
|
|
289
|
+
}
|
|
290
|
+
function useMessages() {
|
|
291
|
+
const [messages, setMessages] = (0, import_react2.useState)([]);
|
|
292
|
+
const addMessage = (0, import_react2.useCallback)((msg) => {
|
|
293
|
+
setMessages((prev) => [...prev, { ...msg, id: nextId(), timestamp: /* @__PURE__ */ new Date() }]);
|
|
294
|
+
}, []);
|
|
295
|
+
return { messages, setMessages, addMessage };
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// src/ui/hooks/useSlashCommands.ts
|
|
299
|
+
var import_react3 = require("react");
|
|
185
300
|
|
|
186
301
|
// src/commands/slash-executor.ts
|
|
187
302
|
var VALID_MODES2 = ["plan", "default", "acceptEdits", "bypassPermissions"];
|
|
@@ -306,9 +421,133 @@ async function executeSlashCommand(cmd, args, session, addMessage, clearMessages
|
|
|
306
421
|
}
|
|
307
422
|
}
|
|
308
423
|
|
|
309
|
-
// src/ui/
|
|
310
|
-
var
|
|
311
|
-
|
|
424
|
+
// src/ui/hooks/useSlashCommands.ts
|
|
425
|
+
var EXIT_DELAY_MS = 500;
|
|
426
|
+
function useSlashCommands(session, addMessage, setMessages, exit, registry, pendingModelChangeRef, setPendingModelId) {
|
|
427
|
+
return (0, import_react3.useCallback)(
|
|
428
|
+
async (input) => {
|
|
429
|
+
const parts = input.slice(1).split(/\s+/);
|
|
430
|
+
const cmd = parts[0]?.toLowerCase() ?? "";
|
|
431
|
+
const args = parts.slice(1).join(" ");
|
|
432
|
+
const clearMessages = () => setMessages([]);
|
|
433
|
+
const result = await executeSlashCommand(cmd, args, session, addMessage, clearMessages, registry);
|
|
434
|
+
if (result.pendingModelId) {
|
|
435
|
+
pendingModelChangeRef.current = result.pendingModelId;
|
|
436
|
+
setPendingModelId(result.pendingModelId);
|
|
437
|
+
}
|
|
438
|
+
if (result.exitRequested) {
|
|
439
|
+
setTimeout(() => exit(), EXIT_DELAY_MS);
|
|
440
|
+
}
|
|
441
|
+
return result.handled;
|
|
442
|
+
},
|
|
443
|
+
[session, addMessage, setMessages, exit, registry, pendingModelChangeRef, setPendingModelId]
|
|
444
|
+
);
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
// src/ui/hooks/useSubmitHandler.ts
|
|
448
|
+
var import_react4 = require("react");
|
|
449
|
+
|
|
450
|
+
// src/utils/tool-call-extractor.ts
|
|
451
|
+
var TOOL_ARG_MAX_LENGTH = 80;
|
|
452
|
+
var TOOL_ARG_TRUNCATE_LENGTH = 77;
|
|
453
|
+
function extractToolCalls(history, startIndex) {
|
|
454
|
+
const lines = [];
|
|
455
|
+
for (let i = startIndex; i < history.length; i++) {
|
|
456
|
+
const msg = history[i];
|
|
457
|
+
if (msg.role === "assistant" && msg.toolCalls) {
|
|
458
|
+
for (const tc of msg.toolCalls) {
|
|
459
|
+
const value = parseFirstArgValue(tc.function.arguments);
|
|
460
|
+
const truncated = value.length > TOOL_ARG_MAX_LENGTH ? value.slice(0, TOOL_ARG_TRUNCATE_LENGTH) + "..." : value;
|
|
461
|
+
lines.push(`${tc.function.name}(${truncated})`);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
return lines;
|
|
466
|
+
}
|
|
467
|
+
function parseFirstArgValue(argsJson) {
|
|
468
|
+
try {
|
|
469
|
+
const parsed = JSON.parse(argsJson);
|
|
470
|
+
const firstVal = Object.values(parsed)[0];
|
|
471
|
+
return typeof firstVal === "string" ? firstVal : JSON.stringify(firstVal);
|
|
472
|
+
} catch {
|
|
473
|
+
return argsJson;
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
// src/utils/skill-prompt.ts
|
|
478
|
+
function buildSkillPrompt(input, registry) {
|
|
479
|
+
const parts = input.slice(1).split(/\s+/);
|
|
480
|
+
const cmd = parts[0]?.toLowerCase() ?? "";
|
|
481
|
+
const skillCmd = registry.getCommands().find((c) => c.name === cmd && c.source === "skill");
|
|
482
|
+
if (!skillCmd) return null;
|
|
483
|
+
const args = parts.slice(1).join(" ").trim();
|
|
484
|
+
const userInstruction = args || skillCmd.description;
|
|
485
|
+
if (skillCmd.skillContent) {
|
|
486
|
+
return `<skill name="${cmd}">
|
|
487
|
+
${skillCmd.skillContent}
|
|
488
|
+
</skill>
|
|
489
|
+
|
|
490
|
+
Execute the "${cmd}" skill: ${userInstruction}`;
|
|
491
|
+
}
|
|
492
|
+
return `Use the "${cmd}" skill: ${userInstruction}`;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
// src/ui/hooks/useSubmitHandler.ts
|
|
496
|
+
function syncContextState(session, setter) {
|
|
497
|
+
const ctx = session.getContextState();
|
|
498
|
+
setter({ percentage: ctx.usedPercentage, usedTokens: ctx.usedTokens, maxTokens: ctx.maxTokens });
|
|
499
|
+
}
|
|
500
|
+
async function runSessionPrompt(prompt, session, addMessage, clearStreamingText, setIsThinking, setContextState) {
|
|
501
|
+
setIsThinking(true);
|
|
502
|
+
clearStreamingText();
|
|
503
|
+
const historyBefore = session.getHistory().length;
|
|
504
|
+
try {
|
|
505
|
+
const response = await session.run(prompt);
|
|
506
|
+
clearStreamingText();
|
|
507
|
+
const history = session.getHistory();
|
|
508
|
+
const toolLines = extractToolCalls(
|
|
509
|
+
history,
|
|
510
|
+
historyBefore
|
|
511
|
+
);
|
|
512
|
+
if (toolLines.length > 0) {
|
|
513
|
+
addMessage({ role: "tool", content: toolLines.join("\n"), toolName: `${toolLines.length} tools` });
|
|
514
|
+
}
|
|
515
|
+
addMessage({ role: "assistant", content: response || "(empty response)" });
|
|
516
|
+
syncContextState(session, setContextState);
|
|
517
|
+
} catch (err) {
|
|
518
|
+
clearStreamingText();
|
|
519
|
+
if (err instanceof DOMException && err.name === "AbortError") {
|
|
520
|
+
addMessage({ role: "system", content: "Cancelled." });
|
|
521
|
+
} else {
|
|
522
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
523
|
+
addMessage({ role: "system", content: `Error: ${errMsg}` });
|
|
524
|
+
}
|
|
525
|
+
} finally {
|
|
526
|
+
setIsThinking(false);
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
function useSubmitHandler(session, addMessage, handleSlashCommand, clearStreamingText, setIsThinking, setContextState, registry) {
|
|
530
|
+
return (0, import_react4.useCallback)(
|
|
531
|
+
async (input) => {
|
|
532
|
+
if (input.startsWith("/")) {
|
|
533
|
+
const handled = await handleSlashCommand(input);
|
|
534
|
+
if (handled) {
|
|
535
|
+
syncContextState(session, setContextState);
|
|
536
|
+
return;
|
|
537
|
+
}
|
|
538
|
+
const prompt = buildSkillPrompt(input, registry);
|
|
539
|
+
if (!prompt) return;
|
|
540
|
+
return runSessionPrompt(prompt, session, addMessage, clearStreamingText, setIsThinking, setContextState);
|
|
541
|
+
}
|
|
542
|
+
addMessage({ role: "user", content: input });
|
|
543
|
+
return runSessionPrompt(input, session, addMessage, clearStreamingText, setIsThinking, setContextState);
|
|
544
|
+
},
|
|
545
|
+
[session, addMessage, handleSlashCommand, clearStreamingText, setIsThinking, setContextState, registry]
|
|
546
|
+
);
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
// src/ui/hooks/useCommandRegistry.ts
|
|
550
|
+
var import_react5 = require("react");
|
|
312
551
|
|
|
313
552
|
// src/commands/command-registry.ts
|
|
314
553
|
var CommandRegistry = class {
|
|
@@ -462,6 +701,18 @@ var SkillCommandSource = class {
|
|
|
462
701
|
}
|
|
463
702
|
};
|
|
464
703
|
|
|
704
|
+
// src/ui/hooks/useCommandRegistry.ts
|
|
705
|
+
function useCommandRegistry(cwd) {
|
|
706
|
+
const registryRef = (0, import_react5.useRef)(null);
|
|
707
|
+
if (registryRef.current === null) {
|
|
708
|
+
const registry = new CommandRegistry();
|
|
709
|
+
registry.addSource(new BuiltinCommandSource());
|
|
710
|
+
registry.addSource(new SkillCommandSource(cwd));
|
|
711
|
+
registryRef.current = registry;
|
|
712
|
+
}
|
|
713
|
+
return registryRef.current;
|
|
714
|
+
}
|
|
715
|
+
|
|
465
716
|
// src/ui/MessageList.tsx
|
|
466
717
|
var import_ink = require("ink");
|
|
467
718
|
|
|
@@ -582,11 +833,11 @@ function StatusBar({
|
|
|
582
833
|
}
|
|
583
834
|
|
|
584
835
|
// src/ui/InputArea.tsx
|
|
585
|
-
var
|
|
836
|
+
var import_react8 = __toESM(require("react"), 1);
|
|
586
837
|
var import_ink6 = require("ink");
|
|
587
838
|
|
|
588
839
|
// src/ui/CjkTextInput.tsx
|
|
589
|
-
var
|
|
840
|
+
var import_react6 = require("react");
|
|
590
841
|
var import_ink3 = require("ink");
|
|
591
842
|
var import_chalk = __toESM(require("chalk"), 1);
|
|
592
843
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
@@ -606,9 +857,9 @@ function CjkTextInput({
|
|
|
606
857
|
focus = true,
|
|
607
858
|
showCursor = true
|
|
608
859
|
}) {
|
|
609
|
-
const valueRef = (0,
|
|
610
|
-
const cursorRef = (0,
|
|
611
|
-
const [, forceRender] = (0,
|
|
860
|
+
const valueRef = (0, import_react6.useRef)(value);
|
|
861
|
+
const cursorRef = (0, import_react6.useRef)(value.length);
|
|
862
|
+
const [, forceRender] = (0, import_react6.useState)(0);
|
|
612
863
|
if (value !== valueRef.current) {
|
|
613
864
|
valueRef.current = value;
|
|
614
865
|
if (cursorRef.current > value.length) {
|
|
@@ -685,15 +936,15 @@ function renderWithCursor(value, cursorOffset, placeholder, showCursor) {
|
|
|
685
936
|
}
|
|
686
937
|
|
|
687
938
|
// src/ui/WaveText.tsx
|
|
688
|
-
var
|
|
939
|
+
var import_react7 = require("react");
|
|
689
940
|
var import_ink4 = require("ink");
|
|
690
941
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
691
942
|
var WAVE_COLORS = ["#666666", "#888888", "#aaaaaa", "#888888"];
|
|
692
943
|
var INTERVAL_MS = 400;
|
|
693
944
|
var CHARS_PER_GROUP = 4;
|
|
694
945
|
function WaveText({ text }) {
|
|
695
|
-
const [tick, setTick] = (0,
|
|
696
|
-
(0,
|
|
946
|
+
const [tick, setTick] = (0, import_react7.useState)(0);
|
|
947
|
+
(0, import_react7.useEffect)(() => {
|
|
697
948
|
const timer = setInterval(() => {
|
|
698
949
|
setTick((prev) => prev + 1);
|
|
699
950
|
}, INTERVAL_MS);
|
|
@@ -759,16 +1010,16 @@ function parseSlashInput(value) {
|
|
|
759
1010
|
return { isSlash: true, parentCommand: parent, filter: rest };
|
|
760
1011
|
}
|
|
761
1012
|
function useAutocomplete(value, registry) {
|
|
762
|
-
const [selectedIndex, setSelectedIndex] = (0,
|
|
763
|
-
const [dismissed, setDismissed] = (0,
|
|
764
|
-
const prevValueRef =
|
|
1013
|
+
const [selectedIndex, setSelectedIndex] = (0, import_react8.useState)(0);
|
|
1014
|
+
const [dismissed, setDismissed] = (0, import_react8.useState)(false);
|
|
1015
|
+
const prevValueRef = import_react8.default.useRef(value);
|
|
765
1016
|
if (prevValueRef.current !== value) {
|
|
766
1017
|
prevValueRef.current = value;
|
|
767
1018
|
if (dismissed) setDismissed(false);
|
|
768
1019
|
}
|
|
769
1020
|
const parsed = parseSlashInput(value);
|
|
770
1021
|
const isSubcommandMode = parsed.isSlash && parsed.parentCommand.length > 0;
|
|
771
|
-
const filteredCommands = (0,
|
|
1022
|
+
const filteredCommands = (0, import_react8.useMemo)(() => {
|
|
772
1023
|
if (!registry || !parsed.isSlash || dismissed) return [];
|
|
773
1024
|
if (isSubcommandMode) {
|
|
774
1025
|
const subs = registry.getSubcommands(parsed.parentCommand);
|
|
@@ -802,7 +1053,7 @@ function useAutocomplete(value, registry) {
|
|
|
802
1053
|
};
|
|
803
1054
|
}
|
|
804
1055
|
function InputArea({ onSubmit, isDisabled, registry }) {
|
|
805
|
-
const [value, setValue] = (0,
|
|
1056
|
+
const [value, setValue] = (0, import_react8.useState)("");
|
|
806
1057
|
const {
|
|
807
1058
|
showPopup,
|
|
808
1059
|
filteredCommands,
|
|
@@ -811,7 +1062,7 @@ function InputArea({ onSubmit, isDisabled, registry }) {
|
|
|
811
1062
|
isSubcommandMode,
|
|
812
1063
|
setShowPopup
|
|
813
1064
|
} = useAutocomplete(value, registry);
|
|
814
|
-
const handleSubmit = (0,
|
|
1065
|
+
const handleSubmit = (0, import_react8.useCallback)(
|
|
815
1066
|
(text) => {
|
|
816
1067
|
const trimmed = text.trim();
|
|
817
1068
|
if (trimmed.length === 0) return;
|
|
@@ -824,7 +1075,7 @@ function InputArea({ onSubmit, isDisabled, registry }) {
|
|
|
824
1075
|
},
|
|
825
1076
|
[showPopup, filteredCommands, selectedIndex, onSubmit]
|
|
826
1077
|
);
|
|
827
|
-
const selectCommand = (0,
|
|
1078
|
+
const selectCommand = (0, import_react8.useCallback)(
|
|
828
1079
|
(cmd) => {
|
|
829
1080
|
const parsed = parseSlashInput(value);
|
|
830
1081
|
if (parsed.parentCommand) {
|
|
@@ -885,7 +1136,7 @@ function InputArea({ onSubmit, isDisabled, registry }) {
|
|
|
885
1136
|
}
|
|
886
1137
|
|
|
887
1138
|
// src/ui/ConfirmPrompt.tsx
|
|
888
|
-
var
|
|
1139
|
+
var import_react9 = require("react");
|
|
889
1140
|
var import_ink7 = require("ink");
|
|
890
1141
|
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
891
1142
|
function ConfirmPrompt({
|
|
@@ -893,9 +1144,9 @@ function ConfirmPrompt({
|
|
|
893
1144
|
options = ["Yes", "No"],
|
|
894
1145
|
onSelect
|
|
895
1146
|
}) {
|
|
896
|
-
const [selected, setSelected] = (0,
|
|
897
|
-
const resolvedRef = (0,
|
|
898
|
-
const doSelect = (0,
|
|
1147
|
+
const [selected, setSelected] = (0, import_react9.useState)(0);
|
|
1148
|
+
const resolvedRef = (0, import_react9.useRef)(false);
|
|
1149
|
+
const doSelect = (0, import_react9.useCallback)(
|
|
899
1150
|
(index) => {
|
|
900
1151
|
if (resolvedRef.current) return;
|
|
901
1152
|
resolvedRef.current = true;
|
|
@@ -928,7 +1179,7 @@ function ConfirmPrompt({
|
|
|
928
1179
|
}
|
|
929
1180
|
|
|
930
1181
|
// src/ui/PermissionPrompt.tsx
|
|
931
|
-
var
|
|
1182
|
+
var import_react10 = __toESM(require("react"), 1);
|
|
932
1183
|
var import_ink8 = require("ink");
|
|
933
1184
|
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
934
1185
|
var OPTIONS = ["Allow", "Allow always (this session)", "Deny"];
|
|
@@ -938,15 +1189,15 @@ function formatArgs(args) {
|
|
|
938
1189
|
return entries.map(([k, v]) => `${k}: ${typeof v === "string" ? v : JSON.stringify(v)}`).join(", ");
|
|
939
1190
|
}
|
|
940
1191
|
function PermissionPrompt({ request }) {
|
|
941
|
-
const [selected, setSelected] =
|
|
942
|
-
const resolvedRef =
|
|
943
|
-
const prevRequestRef =
|
|
1192
|
+
const [selected, setSelected] = import_react10.default.useState(0);
|
|
1193
|
+
const resolvedRef = import_react10.default.useRef(false);
|
|
1194
|
+
const prevRequestRef = import_react10.default.useRef(request);
|
|
944
1195
|
if (prevRequestRef.current !== request) {
|
|
945
1196
|
prevRequestRef.current = request;
|
|
946
1197
|
resolvedRef.current = false;
|
|
947
1198
|
setSelected(0);
|
|
948
1199
|
}
|
|
949
|
-
const doResolve =
|
|
1200
|
+
const doResolve = import_react10.default.useCallback(
|
|
950
1201
|
(index) => {
|
|
951
1202
|
if (resolvedRef.current) return;
|
|
952
1203
|
resolvedRef.current = true;
|
|
@@ -991,254 +1242,54 @@ function PermissionPrompt({ request }) {
|
|
|
991
1242
|
] });
|
|
992
1243
|
}
|
|
993
1244
|
|
|
994
|
-
// src/
|
|
995
|
-
var
|
|
996
|
-
var TOOL_ARG_TRUNCATE_LENGTH = 77;
|
|
997
|
-
function extractToolCalls(history, startIndex) {
|
|
998
|
-
const lines = [];
|
|
999
|
-
for (let i = startIndex; i < history.length; i++) {
|
|
1000
|
-
const msg = history[i];
|
|
1001
|
-
if (msg.role === "assistant" && msg.toolCalls) {
|
|
1002
|
-
for (const tc of msg.toolCalls) {
|
|
1003
|
-
const value = parseFirstArgValue(tc.function.arguments);
|
|
1004
|
-
const truncated = value.length > TOOL_ARG_MAX_LENGTH ? value.slice(0, TOOL_ARG_TRUNCATE_LENGTH) + "..." : value;
|
|
1005
|
-
lines.push(`${tc.function.name}(${truncated})`);
|
|
1006
|
-
}
|
|
1007
|
-
}
|
|
1008
|
-
}
|
|
1009
|
-
return lines;
|
|
1010
|
-
}
|
|
1011
|
-
function parseFirstArgValue(argsJson) {
|
|
1012
|
-
try {
|
|
1013
|
-
const parsed = JSON.parse(argsJson);
|
|
1014
|
-
const firstVal = Object.values(parsed)[0];
|
|
1015
|
-
return typeof firstVal === "string" ? firstVal : JSON.stringify(firstVal);
|
|
1016
|
-
} catch {
|
|
1017
|
-
return argsJson;
|
|
1018
|
-
}
|
|
1019
|
-
}
|
|
1020
|
-
|
|
1021
|
-
// src/ui/App.tsx
|
|
1245
|
+
// src/ui/StreamingIndicator.tsx
|
|
1246
|
+
var import_ink9 = require("ink");
|
|
1022
1247
|
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
}
|
|
1028
|
-
var NOOP_TERMINAL = {
|
|
1029
|
-
write: () => {
|
|
1030
|
-
},
|
|
1031
|
-
writeLine: () => {
|
|
1032
|
-
},
|
|
1033
|
-
writeMarkdown: () => {
|
|
1034
|
-
},
|
|
1035
|
-
writeError: () => {
|
|
1036
|
-
},
|
|
1037
|
-
prompt: () => Promise.resolve(""),
|
|
1038
|
-
select: () => Promise.resolve(0),
|
|
1039
|
-
spinner: () => ({ stop: () => {
|
|
1040
|
-
}, update: () => {
|
|
1041
|
-
} })
|
|
1042
|
-
};
|
|
1043
|
-
function useSession(props) {
|
|
1044
|
-
const [permissionRequest, setPermissionRequest] = (0, import_react6.useState)(null);
|
|
1045
|
-
const [streamingText, setStreamingText] = (0, import_react6.useState)("");
|
|
1046
|
-
const permissionQueueRef = (0, import_react6.useRef)([]);
|
|
1047
|
-
const processingRef = (0, import_react6.useRef)(false);
|
|
1048
|
-
const processNextPermission = (0, import_react6.useCallback)(() => {
|
|
1049
|
-
if (processingRef.current) return;
|
|
1050
|
-
const next = permissionQueueRef.current[0];
|
|
1051
|
-
if (!next) {
|
|
1052
|
-
setPermissionRequest(null);
|
|
1053
|
-
return;
|
|
1054
|
-
}
|
|
1055
|
-
processingRef.current = true;
|
|
1056
|
-
setPermissionRequest({
|
|
1057
|
-
toolName: next.toolName,
|
|
1058
|
-
toolArgs: next.toolArgs,
|
|
1059
|
-
resolve: (result) => {
|
|
1060
|
-
permissionQueueRef.current.shift();
|
|
1061
|
-
processingRef.current = false;
|
|
1062
|
-
setPermissionRequest(null);
|
|
1063
|
-
next.resolve(result);
|
|
1064
|
-
setTimeout(() => processNextPermission(), 0);
|
|
1065
|
-
}
|
|
1066
|
-
});
|
|
1067
|
-
}, []);
|
|
1068
|
-
const sessionRef = (0, import_react6.useRef)(null);
|
|
1069
|
-
if (sessionRef.current === null) {
|
|
1070
|
-
const permissionHandler = (toolName, toolArgs) => {
|
|
1071
|
-
return new Promise((resolve) => {
|
|
1072
|
-
permissionQueueRef.current.push({ toolName, toolArgs, resolve });
|
|
1073
|
-
processNextPermission();
|
|
1074
|
-
});
|
|
1075
|
-
};
|
|
1076
|
-
const onTextDelta = (delta) => {
|
|
1077
|
-
setStreamingText((prev) => prev + delta);
|
|
1078
|
-
};
|
|
1079
|
-
const paths = (0, import_agent_sdk.projectPaths)(props.cwd ?? process.cwd());
|
|
1080
|
-
sessionRef.current = (0, import_agent_sdk.createSession)({
|
|
1081
|
-
config: props.config,
|
|
1082
|
-
context: props.context,
|
|
1083
|
-
terminal: NOOP_TERMINAL,
|
|
1084
|
-
sessionLogger: new import_agent_sdk.FileSessionLogger(paths.logs),
|
|
1085
|
-
projectInfo: props.projectInfo,
|
|
1086
|
-
sessionStore: props.sessionStore,
|
|
1087
|
-
permissionMode: props.permissionMode,
|
|
1088
|
-
maxTurns: props.maxTurns,
|
|
1089
|
-
permissionHandler,
|
|
1090
|
-
onTextDelta
|
|
1091
|
-
});
|
|
1248
|
+
function StreamingIndicator({ text, activeTools }) {
|
|
1249
|
+
const hasTools = activeTools.length > 0;
|
|
1250
|
+
const hasText = text.length > 0;
|
|
1251
|
+
if (!hasTools && !hasText) {
|
|
1252
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_ink9.Text, { color: "yellow", children: "Thinking..." });
|
|
1092
1253
|
}
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
}
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
const args = parts.slice(1).join(" ");
|
|
1110
|
-
const clearMessages = () => setMessages([]);
|
|
1111
|
-
const result = await executeSlashCommand(cmd, args, session, addMessage, clearMessages, registry);
|
|
1112
|
-
if (result.pendingModelId) {
|
|
1113
|
-
pendingModelChangeRef.current = result.pendingModelId;
|
|
1114
|
-
setPendingModelId(result.pendingModelId);
|
|
1115
|
-
}
|
|
1116
|
-
if (result.exitRequested) {
|
|
1117
|
-
setTimeout(() => exit(), EXIT_DELAY_MS);
|
|
1118
|
-
}
|
|
1119
|
-
return result.handled;
|
|
1120
|
-
},
|
|
1121
|
-
[session, addMessage, setMessages, exit, registry, pendingModelChangeRef, setPendingModelId]
|
|
1122
|
-
);
|
|
1123
|
-
}
|
|
1124
|
-
function StreamingIndicator({ text }) {
|
|
1125
|
-
if (text) {
|
|
1126
|
-
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_ink9.Box, { flexDirection: "column", children: [
|
|
1127
|
-
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_ink9.Text, { color: "cyan", bold: true, children: [
|
|
1128
|
-
"Robota:",
|
|
1129
|
-
" "
|
|
1130
|
-
] }),
|
|
1254
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_ink9.Box, { flexDirection: "column", children: [
|
|
1255
|
+
hasTools && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_ink9.Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
1256
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_ink9.Text, { color: "gray", bold: true, children: "Tools:" }),
|
|
1257
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_ink9.Text, { children: " " }),
|
|
1258
|
+
activeTools.map((t, i) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_ink9.Text, { color: t.isRunning ? "yellow" : "green", children: [
|
|
1259
|
+
" ",
|
|
1260
|
+
t.isRunning ? "\u27F3" : "\u2713",
|
|
1261
|
+
" ",
|
|
1262
|
+
t.toolName,
|
|
1263
|
+
"(",
|
|
1264
|
+
t.firstArg,
|
|
1265
|
+
")"
|
|
1266
|
+
] }, `${t.toolName}-${i}`))
|
|
1267
|
+
] }),
|
|
1268
|
+
hasText && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_ink9.Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
1269
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_ink9.Text, { color: "cyan", bold: true, children: "Robota:" }),
|
|
1131
1270
|
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_ink9.Text, { children: " " }),
|
|
1132
1271
|
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_ink9.Box, { marginLeft: 2, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_ink9.Text, { wrap: "wrap", children: renderMarkdown(text) }) })
|
|
1133
|
-
] })
|
|
1134
|
-
}
|
|
1135
|
-
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_ink9.Text, { color: "yellow", children: "Thinking..." });
|
|
1136
|
-
}
|
|
1137
|
-
async function runSessionPrompt(prompt, session, addMessage, clearStreamingText, setIsThinking, setContextPercentage) {
|
|
1138
|
-
setIsThinking(true);
|
|
1139
|
-
clearStreamingText();
|
|
1140
|
-
const historyBefore = session.getHistory().length;
|
|
1141
|
-
try {
|
|
1142
|
-
const response = await session.run(prompt);
|
|
1143
|
-
clearStreamingText();
|
|
1144
|
-
const history = session.getHistory();
|
|
1145
|
-
const toolLines = extractToolCalls(
|
|
1146
|
-
history,
|
|
1147
|
-
historyBefore
|
|
1148
|
-
);
|
|
1149
|
-
if (toolLines.length > 0) {
|
|
1150
|
-
addMessage({ role: "tool", content: toolLines.join("\n"), toolName: `${toolLines.length} tools` });
|
|
1151
|
-
}
|
|
1152
|
-
addMessage({ role: "assistant", content: response || "(empty response)" });
|
|
1153
|
-
setContextPercentage(session.getContextState().usedPercentage);
|
|
1154
|
-
} catch (err) {
|
|
1155
|
-
clearStreamingText();
|
|
1156
|
-
if (err instanceof DOMException && err.name === "AbortError") {
|
|
1157
|
-
addMessage({ role: "system", content: "Cancelled." });
|
|
1158
|
-
} else {
|
|
1159
|
-
const errMsg = err instanceof Error ? err.message : String(err);
|
|
1160
|
-
addMessage({ role: "system", content: `Error: ${errMsg}` });
|
|
1161
|
-
}
|
|
1162
|
-
} finally {
|
|
1163
|
-
setIsThinking(false);
|
|
1164
|
-
}
|
|
1272
|
+
] })
|
|
1273
|
+
] });
|
|
1165
1274
|
}
|
|
1166
|
-
function buildSkillPrompt(input, registry) {
|
|
1167
|
-
const parts = input.slice(1).split(/\s+/);
|
|
1168
|
-
const cmd = parts[0]?.toLowerCase() ?? "";
|
|
1169
|
-
const skillCmd = registry.getCommands().find((c) => c.name === cmd && c.source === "skill");
|
|
1170
|
-
if (!skillCmd) return null;
|
|
1171
|
-
const args = parts.slice(1).join(" ").trim();
|
|
1172
|
-
const userInstruction = args || skillCmd.description;
|
|
1173
|
-
if (skillCmd.skillContent) {
|
|
1174
|
-
return `<skill name="${cmd}">
|
|
1175
|
-
${skillCmd.skillContent}
|
|
1176
|
-
</skill>
|
|
1177
1275
|
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
}
|
|
1182
|
-
function useSubmitHandler(session, addMessage, handleSlashCommand, clearStreamingText, setIsThinking, setContextPercentage, registry) {
|
|
1183
|
-
return (0, import_react6.useCallback)(
|
|
1184
|
-
async (input) => {
|
|
1185
|
-
if (input.startsWith("/")) {
|
|
1186
|
-
const handled = await handleSlashCommand(input);
|
|
1187
|
-
if (handled) {
|
|
1188
|
-
setContextPercentage(session.getContextState().usedPercentage);
|
|
1189
|
-
return;
|
|
1190
|
-
}
|
|
1191
|
-
const prompt = buildSkillPrompt(input, registry);
|
|
1192
|
-
if (!prompt) return;
|
|
1193
|
-
return runSessionPrompt(
|
|
1194
|
-
prompt,
|
|
1195
|
-
session,
|
|
1196
|
-
addMessage,
|
|
1197
|
-
clearStreamingText,
|
|
1198
|
-
setIsThinking,
|
|
1199
|
-
setContextPercentage
|
|
1200
|
-
);
|
|
1201
|
-
}
|
|
1202
|
-
addMessage({ role: "user", content: input });
|
|
1203
|
-
return runSessionPrompt(
|
|
1204
|
-
input,
|
|
1205
|
-
session,
|
|
1206
|
-
addMessage,
|
|
1207
|
-
clearStreamingText,
|
|
1208
|
-
setIsThinking,
|
|
1209
|
-
setContextPercentage
|
|
1210
|
-
);
|
|
1211
|
-
},
|
|
1212
|
-
[
|
|
1213
|
-
session,
|
|
1214
|
-
addMessage,
|
|
1215
|
-
handleSlashCommand,
|
|
1216
|
-
clearStreamingText,
|
|
1217
|
-
setIsThinking,
|
|
1218
|
-
setContextPercentage,
|
|
1219
|
-
registry
|
|
1220
|
-
]
|
|
1221
|
-
);
|
|
1222
|
-
}
|
|
1223
|
-
function useCommandRegistry(cwd) {
|
|
1224
|
-
const registryRef = (0, import_react6.useRef)(null);
|
|
1225
|
-
if (registryRef.current === null) {
|
|
1226
|
-
const registry = new CommandRegistry();
|
|
1227
|
-
registry.addSource(new BuiltinCommandSource());
|
|
1228
|
-
registry.addSource(new SkillCommandSource(cwd));
|
|
1229
|
-
registryRef.current = registry;
|
|
1230
|
-
}
|
|
1231
|
-
return registryRef.current;
|
|
1232
|
-
}
|
|
1276
|
+
// src/ui/App.tsx
|
|
1277
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
1278
|
+
var EXIT_DELAY_MS2 = 500;
|
|
1233
1279
|
function App(props) {
|
|
1234
|
-
const { exit } = (0,
|
|
1235
|
-
const { session, permissionRequest, streamingText, clearStreamingText } = useSession(props);
|
|
1280
|
+
const { exit } = (0, import_ink10.useApp)();
|
|
1281
|
+
const { session, permissionRequest, streamingText, clearStreamingText, activeTools } = useSession(props);
|
|
1236
1282
|
const { messages, setMessages, addMessage } = useMessages();
|
|
1237
|
-
const [isThinking, setIsThinking] = (0,
|
|
1238
|
-
const
|
|
1283
|
+
const [isThinking, setIsThinking] = (0, import_react11.useState)(false);
|
|
1284
|
+
const initialCtx = session.getContextState();
|
|
1285
|
+
const [contextState, setContextState] = (0, import_react11.useState)({
|
|
1286
|
+
percentage: initialCtx.usedPercentage,
|
|
1287
|
+
usedTokens: initialCtx.usedTokens,
|
|
1288
|
+
maxTokens: initialCtx.maxTokens
|
|
1289
|
+
});
|
|
1239
1290
|
const registry = useCommandRegistry(props.cwd ?? process.cwd());
|
|
1240
|
-
const pendingModelChangeRef = (0,
|
|
1241
|
-
const [pendingModelId, setPendingModelId] = (0,
|
|
1291
|
+
const pendingModelChangeRef = (0, import_react11.useRef)(null);
|
|
1292
|
+
const [pendingModelId, setPendingModelId] = (0, import_react11.useState)(null);
|
|
1242
1293
|
const handleSlashCommand = useSlashCommands(session, addMessage, setMessages, exit, registry, pendingModelChangeRef, setPendingModelId);
|
|
1243
1294
|
const handleSubmit = useSubmitHandler(
|
|
1244
1295
|
session,
|
|
@@ -1246,36 +1297,36 @@ function App(props) {
|
|
|
1246
1297
|
handleSlashCommand,
|
|
1247
1298
|
clearStreamingText,
|
|
1248
1299
|
setIsThinking,
|
|
1249
|
-
|
|
1300
|
+
setContextState,
|
|
1250
1301
|
registry
|
|
1251
1302
|
);
|
|
1252
|
-
(0,
|
|
1303
|
+
(0, import_ink10.useInput)(
|
|
1253
1304
|
(_input, key) => {
|
|
1254
1305
|
if (key.ctrl && _input === "c") exit();
|
|
1255
1306
|
if (key.escape && isThinking) session.abort();
|
|
1256
1307
|
},
|
|
1257
1308
|
{ isActive: !permissionRequest }
|
|
1258
1309
|
);
|
|
1259
|
-
return /* @__PURE__ */ (0,
|
|
1260
|
-
/* @__PURE__ */ (0,
|
|
1261
|
-
/* @__PURE__ */ (0,
|
|
1310
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_ink10.Box, { flexDirection: "column", children: [
|
|
1311
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_ink10.Box, { flexDirection: "column", paddingX: 1, marginBottom: 1, children: [
|
|
1312
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_ink10.Text, { color: "cyan", bold: true, children: `
|
|
1262
1313
|
____ ___ ____ ___ _____ _
|
|
1263
1314
|
| _ \\ / _ \\| __ ) / _ \\_ _|/ \\
|
|
1264
1315
|
| |_) | | | | _ \\| | | || | / _ \\
|
|
1265
1316
|
| _ <| |_| | |_) | |_| || |/ ___ \\
|
|
1266
1317
|
|_| \\_\\\\___/|____/ \\___/ |_/_/ \\_\\
|
|
1267
1318
|
` }),
|
|
1268
|
-
/* @__PURE__ */ (0,
|
|
1319
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_ink10.Text, { dimColor: true, children: [
|
|
1269
1320
|
" v",
|
|
1270
1321
|
props.version ?? "0.0.0"
|
|
1271
1322
|
] })
|
|
1272
1323
|
] }),
|
|
1273
|
-
/* @__PURE__ */ (0,
|
|
1274
|
-
/* @__PURE__ */ (0,
|
|
1275
|
-
isThinking && /* @__PURE__ */ (0,
|
|
1324
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_ink10.Box, { flexDirection: "column", paddingX: 1, flexGrow: 1, children: [
|
|
1325
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(MessageList, { messages }),
|
|
1326
|
+
isThinking && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_ink10.Box, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(StreamingIndicator, { text: streamingText, activeTools }) })
|
|
1276
1327
|
] }),
|
|
1277
|
-
permissionRequest && /* @__PURE__ */ (0,
|
|
1278
|
-
pendingModelId && /* @__PURE__ */ (0,
|
|
1328
|
+
permissionRequest && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(PermissionPrompt, { request: permissionRequest }),
|
|
1329
|
+
pendingModelId && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1279
1330
|
ConfirmPrompt,
|
|
1280
1331
|
{
|
|
1281
1332
|
message: `Change model to ${(0, import_agent_core3.getModelName)(pendingModelId)}? This will restart the session.`,
|
|
@@ -1287,7 +1338,7 @@ function App(props) {
|
|
|
1287
1338
|
const settingsPath = getUserSettingsPath();
|
|
1288
1339
|
updateModelInSettings(settingsPath, pendingModelId);
|
|
1289
1340
|
addMessage({ role: "system", content: `Model changed to ${(0, import_agent_core3.getModelName)(pendingModelId)}. Restarting...` });
|
|
1290
|
-
setTimeout(() => exit(),
|
|
1341
|
+
setTimeout(() => exit(), EXIT_DELAY_MS2);
|
|
1291
1342
|
} catch (err) {
|
|
1292
1343
|
addMessage({ role: "system", content: `Failed: ${err instanceof Error ? err.message : String(err)}` });
|
|
1293
1344
|
}
|
|
@@ -1297,7 +1348,7 @@ function App(props) {
|
|
|
1297
1348
|
}
|
|
1298
1349
|
}
|
|
1299
1350
|
),
|
|
1300
|
-
/* @__PURE__ */ (0,
|
|
1351
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1301
1352
|
StatusBar,
|
|
1302
1353
|
{
|
|
1303
1354
|
permissionMode: session.getPermissionMode(),
|
|
@@ -1305,12 +1356,12 @@ function App(props) {
|
|
|
1305
1356
|
sessionId: session.getSessionId(),
|
|
1306
1357
|
messageCount: messages.length,
|
|
1307
1358
|
isThinking,
|
|
1308
|
-
contextPercentage,
|
|
1309
|
-
contextUsedTokens:
|
|
1310
|
-
contextMaxTokens:
|
|
1359
|
+
contextPercentage: contextState.percentage,
|
|
1360
|
+
contextUsedTokens: contextState.usedTokens,
|
|
1361
|
+
contextMaxTokens: contextState.maxTokens
|
|
1311
1362
|
}
|
|
1312
1363
|
),
|
|
1313
|
-
/* @__PURE__ */ (0,
|
|
1364
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1314
1365
|
InputArea,
|
|
1315
1366
|
{
|
|
1316
1367
|
onSubmit: handleSubmit,
|
|
@@ -1318,12 +1369,12 @@ function App(props) {
|
|
|
1318
1369
|
registry
|
|
1319
1370
|
}
|
|
1320
1371
|
),
|
|
1321
|
-
/* @__PURE__ */ (0,
|
|
1372
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_ink10.Text, { children: " " })
|
|
1322
1373
|
] });
|
|
1323
1374
|
}
|
|
1324
1375
|
|
|
1325
1376
|
// src/ui/render.tsx
|
|
1326
|
-
var
|
|
1377
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
1327
1378
|
function renderApp(options) {
|
|
1328
1379
|
process.on("unhandledRejection", (reason) => {
|
|
1329
1380
|
process.stderr.write(`
|
|
@@ -1334,7 +1385,7 @@ function renderApp(options) {
|
|
|
1334
1385
|
`);
|
|
1335
1386
|
}
|
|
1336
1387
|
});
|
|
1337
|
-
const instance = (0,
|
|
1388
|
+
const instance = (0, import_ink11.render)(/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(App, { ...options }), {
|
|
1338
1389
|
exitOnCtrlC: true
|
|
1339
1390
|
});
|
|
1340
1391
|
instance.waitUntilExit().catch((err) => {
|
|
@@ -1348,6 +1399,18 @@ function renderApp(options) {
|
|
|
1348
1399
|
|
|
1349
1400
|
// src/cli.ts
|
|
1350
1401
|
var import_meta = {};
|
|
1402
|
+
function hasValidSettingsFile(filePath) {
|
|
1403
|
+
if (!(0, import_node_fs3.existsSync)(filePath)) return false;
|
|
1404
|
+
try {
|
|
1405
|
+
const raw = (0, import_node_fs3.readFileSync)(filePath, "utf8").trim();
|
|
1406
|
+
if (raw.length === 0) return false;
|
|
1407
|
+
const parsed = JSON.parse(raw);
|
|
1408
|
+
const provider = parsed.provider;
|
|
1409
|
+
return !!provider?.apiKey;
|
|
1410
|
+
} catch {
|
|
1411
|
+
return false;
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1351
1414
|
function readVersion() {
|
|
1352
1415
|
try {
|
|
1353
1416
|
const thisFile = (0, import_node_url.fileURLToPath)(import_meta.url);
|
|
@@ -1372,7 +1435,7 @@ async function ensureConfig(cwd) {
|
|
|
1372
1435
|
const userPath = getUserSettingsPath();
|
|
1373
1436
|
const projectPath = (0, import_node_path3.join)(cwd, ".robota", "settings.json");
|
|
1374
1437
|
const localPath = (0, import_node_path3.join)(cwd, ".robota", "settings.local.json");
|
|
1375
|
-
if ((
|
|
1438
|
+
if (hasValidSettingsFile(userPath) || hasValidSettingsFile(projectPath) || hasValidSettingsFile(localPath)) {
|
|
1376
1439
|
return;
|
|
1377
1440
|
}
|
|
1378
1441
|
process.stdout.write("\n");
|