@robota-sdk/agent-cli 3.0.0-beta.60 → 3.0.0-beta.62
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/README.ko.md +297 -0
- package/README.md +76 -37
- package/bin/robota.cjs +43 -0
- package/dist/node/bin.js +6019 -3
- package/dist/node/{chunk-GHQHUBHC.js → chunk-6US65UBD.js} +2314 -2043
- package/dist/node/{chunk-6XQKLNRF.js → chunk-7D75HL37.js} +28 -8
- package/dist/node/chunk-BENOH47A.js +287 -0
- package/dist/node/cli-N6TYREZG.js +9 -0
- package/dist/node/index.cjs +917 -556
- package/dist/node/index.js +5813 -8
- package/dist/node/subagents/child-process-subagent-worker.cjs +249 -0
- package/dist/node/subagents/child-process-subagent-worker.d.cts +2 -0
- package/dist/node/subagents/child-process-subagent-worker.js +1 -1
- package/package.json +39 -32
package/dist/node/index.cjs
CHANGED
|
@@ -28,8 +28,8 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
28
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
29
|
|
|
30
30
|
// src/index.ts
|
|
31
|
-
var
|
|
32
|
-
__export(
|
|
31
|
+
var src_exports = {};
|
|
32
|
+
__export(src_exports, {
|
|
33
33
|
ChildProcessSubagentRunner: () => ChildProcessSubagentRunner,
|
|
34
34
|
GitWorktreeIsolationAdapter: () => GitWorktreeIsolationAdapter,
|
|
35
35
|
createChildProcessSubagentRunnerFactory: () => createChildProcessSubagentRunnerFactory,
|
|
@@ -37,7 +37,7 @@ __export(index_exports, {
|
|
|
37
37
|
createManagedShellProcessRunner: () => createManagedShellProcessRunner,
|
|
38
38
|
startCli: () => startCli
|
|
39
39
|
});
|
|
40
|
-
module.exports = __toCommonJS(
|
|
40
|
+
module.exports = __toCommonJS(src_exports);
|
|
41
41
|
|
|
42
42
|
// src/cli.ts
|
|
43
43
|
var import_node_fs8 = require("fs");
|
|
@@ -52,7 +52,6 @@ var import_agent_command_exit = require("@robota-sdk/agent-command-exit");
|
|
|
52
52
|
var import_agent_command_help = require("@robota-sdk/agent-command-help");
|
|
53
53
|
var import_agent_command_language = require("@robota-sdk/agent-command-language");
|
|
54
54
|
var import_agent_command_memory = require("@robota-sdk/agent-command-memory");
|
|
55
|
-
var import_agent_command_mode = require("@robota-sdk/agent-command-mode");
|
|
56
55
|
var import_agent_command_model = require("@robota-sdk/agent-command-model");
|
|
57
56
|
var import_agent_command_permissions = require("@robota-sdk/agent-command-permissions");
|
|
58
57
|
var import_agent_command_plugin = require("@robota-sdk/agent-command-plugin");
|
|
@@ -60,8 +59,9 @@ var import_agent_command_reset = require("@robota-sdk/agent-command-reset");
|
|
|
60
59
|
var import_agent_command_rewind = require("@robota-sdk/agent-command-rewind");
|
|
61
60
|
var import_agent_command_statusline = require("@robota-sdk/agent-command-statusline");
|
|
62
61
|
var import_agent_command_session = require("@robota-sdk/agent-command-session");
|
|
63
|
-
var
|
|
64
|
-
var
|
|
62
|
+
var import_agent_command_skills = require("@robota-sdk/agent-command-skills");
|
|
63
|
+
var import_agent_command_user_local2 = require("@robota-sdk/agent-command-user-local");
|
|
64
|
+
var import_agent_sdk15 = require("@robota-sdk/agent-sdk");
|
|
65
65
|
|
|
66
66
|
// src/utils/cli-args.ts
|
|
67
67
|
var import_node_util = require("util");
|
|
@@ -99,8 +99,12 @@ function parseCliArgs() {
|
|
|
99
99
|
"fork-session": { type: "boolean", default: false },
|
|
100
100
|
name: { type: "string", short: "n" },
|
|
101
101
|
"output-format": { type: "string" },
|
|
102
|
+
format: { type: "string" },
|
|
103
|
+
summary: { type: "string" },
|
|
104
|
+
source: { type: "string" },
|
|
102
105
|
"system-prompt": { type: "string" },
|
|
103
106
|
"append-system-prompt": { type: "string" },
|
|
107
|
+
"task-file": { type: "string" },
|
|
104
108
|
version: { type: "boolean", default: false },
|
|
105
109
|
reset: { type: "boolean", default: false },
|
|
106
110
|
bare: { type: "boolean", default: false },
|
|
@@ -117,7 +121,10 @@ function parseCliArgs() {
|
|
|
117
121
|
"set-current": { type: "boolean", default: false },
|
|
118
122
|
"settings-scope": { type: "string" },
|
|
119
123
|
"check-update": { type: "boolean", default: false },
|
|
120
|
-
"disable-update-check": { type: "boolean", default: false }
|
|
124
|
+
"disable-update-check": { type: "boolean", default: false },
|
|
125
|
+
web: { type: "boolean", default: false },
|
|
126
|
+
"web-port": { type: "string" },
|
|
127
|
+
"no-open": { type: "boolean", default: false }
|
|
121
128
|
}
|
|
122
129
|
});
|
|
123
130
|
return {
|
|
@@ -132,8 +139,12 @@ function parseCliArgs() {
|
|
|
132
139
|
forkSession: values["fork-session"] ?? false,
|
|
133
140
|
sessionName: values["name"],
|
|
134
141
|
outputFormat: values["output-format"],
|
|
142
|
+
format: values["format"],
|
|
143
|
+
summary: values["summary"],
|
|
144
|
+
source: values["source"],
|
|
135
145
|
systemPrompt: values["system-prompt"],
|
|
136
146
|
appendSystemPrompt: values["append-system-prompt"],
|
|
147
|
+
taskFile: values["task-file"],
|
|
137
148
|
version: values["version"] ?? false,
|
|
138
149
|
reset: values["reset"] ?? false,
|
|
139
150
|
bare: values["bare"] ?? false,
|
|
@@ -150,9 +161,23 @@ function parseCliArgs() {
|
|
|
150
161
|
setCurrent: values["set-current"] ?? false,
|
|
151
162
|
settingsScope: values["settings-scope"],
|
|
152
163
|
checkUpdate: values["check-update"] ?? false,
|
|
153
|
-
disableUpdateCheck: values["disable-update-check"] ?? false
|
|
164
|
+
disableUpdateCheck: values["disable-update-check"] ?? false,
|
|
165
|
+
web: values["web"] ?? false,
|
|
166
|
+
webPort: parseWebPort(values["web-port"]),
|
|
167
|
+
noOpen: values["no-open"] ?? false
|
|
154
168
|
};
|
|
155
169
|
}
|
|
170
|
+
var DEFAULT_WEB_PORT = 7070;
|
|
171
|
+
function parseWebPort(raw) {
|
|
172
|
+
if (raw === void 0) return DEFAULT_WEB_PORT;
|
|
173
|
+
const n = parseInt(raw, 10);
|
|
174
|
+
if (isNaN(n) || n < 1 || n > 65535) {
|
|
175
|
+
process.stderr.write(`Invalid --web-port "${raw}". Must be 1\u201365535.
|
|
176
|
+
`);
|
|
177
|
+
process.exit(1);
|
|
178
|
+
}
|
|
179
|
+
return n;
|
|
180
|
+
}
|
|
156
181
|
|
|
157
182
|
// src/utils/settings-io.ts
|
|
158
183
|
var import_node_fs = require("fs");
|
|
@@ -190,6 +215,7 @@ var import_node_path2 = require("path");
|
|
|
190
215
|
|
|
191
216
|
// src/utils/provider-default-definitions.ts
|
|
192
217
|
var import_agent_provider_anthropic = require("@robota-sdk/agent-provider-anthropic");
|
|
218
|
+
var import_agent_provider_deepseek = require("@robota-sdk/agent-provider-deepseek");
|
|
193
219
|
var import_agent_provider_gemma = require("@robota-sdk/agent-provider-gemma");
|
|
194
220
|
var import_agent_provider_gemini = require("@robota-sdk/agent-provider-gemini");
|
|
195
221
|
var import_agent_provider_openai = require("@robota-sdk/agent-provider-openai");
|
|
@@ -199,7 +225,8 @@ var DEFAULT_PROVIDER_DEFINITIONS = [
|
|
|
199
225
|
(0, import_agent_provider_openai.createOpenAIProviderDefinition)(),
|
|
200
226
|
(0, import_agent_provider_gemini.createGeminiProviderDefinition)(),
|
|
201
227
|
(0, import_agent_provider_gemma.createGemmaProviderDefinition)(),
|
|
202
|
-
(0, import_agent_provider_qwen.createQwenProviderDefinition)()
|
|
228
|
+
(0, import_agent_provider_qwen.createQwenProviderDefinition)(),
|
|
229
|
+
(0, import_agent_provider_deepseek.createDeepSeekProviderDefinition)()
|
|
203
230
|
];
|
|
204
231
|
|
|
205
232
|
// src/utils/provider-definition.ts
|
|
@@ -335,8 +362,11 @@ function createProviderFromConfig(settings, providerDefinitions) {
|
|
|
335
362
|
`Unknown provider: ${settings.name}. Currently supported: ${(0, import_agent_core.formatSupportedProviderTypes)(providerDefinitions)}`
|
|
336
363
|
);
|
|
337
364
|
}
|
|
338
|
-
|
|
339
|
-
|
|
365
|
+
const credentialRequirement = (0, import_agent_core.getProviderCredentialRequirement)(definition);
|
|
366
|
+
if (credentialRequirement !== void 0 && !hasRequiredProviderCredential(settings, credentialRequirement)) {
|
|
367
|
+
throw new Error(
|
|
368
|
+
`Provider ${settings.name} requires ${formatCredentialRequirement(credentialRequirement)}`
|
|
369
|
+
);
|
|
340
370
|
}
|
|
341
371
|
return definition.createProvider(settings);
|
|
342
372
|
}
|
|
@@ -346,6 +376,16 @@ function createProviderFromSettings(cwd, modelOverride, options = {}) {
|
|
|
346
376
|
const model = modelOverride ?? settings.model;
|
|
347
377
|
return createProviderFromConfig({ ...settings, model }, providerDefinitions);
|
|
348
378
|
}
|
|
379
|
+
function hasRequiredProviderCredential(settings, requirement) {
|
|
380
|
+
return requirement.anyOf.some((field) => hasProviderCredentialValue(settings, field));
|
|
381
|
+
}
|
|
382
|
+
function hasProviderCredentialValue(settings, field) {
|
|
383
|
+
const value = settings[field];
|
|
384
|
+
return value !== void 0 && value.length > 0;
|
|
385
|
+
}
|
|
386
|
+
function formatCredentialRequirement(requirement) {
|
|
387
|
+
return requirement.anyOf.join(" or ");
|
|
388
|
+
}
|
|
349
389
|
function getProviderDefinitions(options) {
|
|
350
390
|
return options.providerDefinitions ?? DEFAULT_PROVIDER_DEFINITIONS;
|
|
351
391
|
}
|
|
@@ -372,23 +412,40 @@ function isUsableProviderProfile(type, profile, providerDefinitions) {
|
|
|
372
412
|
if (!profile) {
|
|
373
413
|
return false;
|
|
374
414
|
}
|
|
375
|
-
if ((0, import_agent_sdk.hasUsableSecretReference)(profile.apiKey)) {
|
|
376
|
-
return true;
|
|
377
|
-
}
|
|
378
415
|
if (!type) {
|
|
379
|
-
return
|
|
416
|
+
return (0, import_agent_sdk.hasUsableSecretReference)(profile.apiKey);
|
|
380
417
|
}
|
|
381
418
|
const definition = (0, import_agent_core.findProviderDefinition)(providerDefinitions, type);
|
|
382
419
|
if (definition === void 0) {
|
|
383
420
|
return false;
|
|
384
421
|
}
|
|
385
|
-
|
|
422
|
+
const credentialRequirement = (0, import_agent_core.getProviderCredentialRequirement)(definition);
|
|
423
|
+
if (credentialRequirement === void 0) {
|
|
424
|
+
return true;
|
|
425
|
+
}
|
|
426
|
+
return hasUsableRequiredProviderCredential(profile, definition, credentialRequirement);
|
|
427
|
+
}
|
|
428
|
+
function hasUsableRequiredProviderCredential(profile, definition, requirement) {
|
|
429
|
+
return requirement.anyOf.some(
|
|
430
|
+
(field) => (0, import_agent_sdk.hasUsableSecretReference)(resolveProviderCredentialValue(field, profile, definition))
|
|
431
|
+
);
|
|
432
|
+
}
|
|
433
|
+
function resolveProviderCredentialValue(field, profile, definition) {
|
|
434
|
+
return profile[field] ?? definition.defaults?.[field];
|
|
386
435
|
}
|
|
387
436
|
|
|
388
437
|
// src/utils/provider-settings.ts
|
|
389
438
|
var import_agent_sdk2 = require("@robota-sdk/agent-sdk");
|
|
390
439
|
|
|
391
440
|
// src/utils/provider-configuration.ts
|
|
441
|
+
function resolveProviderSettingsWriteTargetPath(cwd, options = {}) {
|
|
442
|
+
const settingsPaths = options.settingsPaths ?? getProviderSettingsPaths(cwd);
|
|
443
|
+
const targetPath = findLastPathWithCurrentProvider(settingsPaths) ?? settingsPaths[0];
|
|
444
|
+
if (targetPath === void 0) {
|
|
445
|
+
throw new Error("No settings path available for provider update");
|
|
446
|
+
}
|
|
447
|
+
return targetPath;
|
|
448
|
+
}
|
|
392
449
|
function readProviderDocument(settingsPath) {
|
|
393
450
|
return readSettings(settingsPath);
|
|
394
451
|
}
|
|
@@ -471,6 +528,15 @@ function findLastPathWithLegacyProvider(settingsPaths) {
|
|
|
471
528
|
}
|
|
472
529
|
return void 0;
|
|
473
530
|
}
|
|
531
|
+
function findLastPathWithCurrentProvider(settingsPaths) {
|
|
532
|
+
for (let index = settingsPaths.length - 1; index >= 0; index -= 1) {
|
|
533
|
+
const settingsPath = settingsPaths[index];
|
|
534
|
+
if (settingsPath === void 0) continue;
|
|
535
|
+
const settings = readProviderDocument(settingsPath);
|
|
536
|
+
if (settings.currentProvider !== void 0) return settingsPath;
|
|
537
|
+
}
|
|
538
|
+
return void 0;
|
|
539
|
+
}
|
|
474
540
|
|
|
475
541
|
// src/utils/provider-setup-flow.ts
|
|
476
542
|
var import_agent_sdk3 = require("@robota-sdk/agent-sdk");
|
|
@@ -496,7 +562,8 @@ function handleProviderConfigurationArgs(cwd, args, providerDefinitions = DEFAUL
|
|
|
496
562
|
return !args.printMode && args.positional.length === 0;
|
|
497
563
|
}
|
|
498
564
|
if (args.provider && args.setCurrent) {
|
|
499
|
-
|
|
565
|
+
const switchSettingsPath = args.settingsScope === void 0 ? resolveProviderSettingsWriteTargetPath(cwd) : settingsPath;
|
|
566
|
+
applyProviderSwitch(switchSettingsPath, args.provider, {
|
|
500
567
|
knownProviders: readMergedProviderSettings(cwd).providers
|
|
501
568
|
});
|
|
502
569
|
process.stdout.write(`Current provider set to ${args.provider}
|
|
@@ -530,7 +597,9 @@ async function runInteractiveProviderSetup(cwd, args, promptInput2, providerDefi
|
|
|
530
597
|
const providerChoice = await promptInput2((0, import_agent_sdk3.formatProviderSetupSelectionPrompt)(providerDefinitions));
|
|
531
598
|
const type = (0, import_agent_sdk3.resolveProviderSetupSelection)(providerChoice, providerDefinitions);
|
|
532
599
|
const settingsPath = getSettingsPathForScope(cwd, args.settingsScope);
|
|
533
|
-
const input = await (0, import_agent_sdk3.runProviderSetupPromptFlow)(type, promptInput2, providerDefinitions
|
|
600
|
+
const input = await (0, import_agent_sdk3.runProviderSetupPromptFlow)(type, promptInput2, providerDefinitions, {
|
|
601
|
+
existingProfileNames: Object.keys(readMergedProviderSettings(cwd).providers ?? {})
|
|
602
|
+
});
|
|
534
603
|
applyProviderConfiguration(settingsPath, input, {
|
|
535
604
|
providerDefinitions
|
|
536
605
|
});
|
|
@@ -613,66 +682,60 @@ function formatConfigureProviderExample(definition) {
|
|
|
613
682
|
var import_agent_transport_headless = require("@robota-sdk/agent-transport-headless");
|
|
614
683
|
|
|
615
684
|
// src/ui/render.tsx
|
|
616
|
-
var
|
|
685
|
+
var import_ink24 = require("ink");
|
|
617
686
|
|
|
618
687
|
// src/ui/App.tsx
|
|
619
|
-
var
|
|
620
|
-
var
|
|
688
|
+
var import_react20 = require("react");
|
|
689
|
+
var import_ink23 = require("ink");
|
|
690
|
+
var import_agent_sdk9 = require("@robota-sdk/agent-sdk");
|
|
621
691
|
var import_agent_core11 = require("@robota-sdk/agent-core");
|
|
622
692
|
|
|
623
693
|
// src/ui/hooks/useInteractiveSession.ts
|
|
624
694
|
var import_react2 = require("react");
|
|
695
|
+
var import_open = __toESM(require("open"), 1);
|
|
625
696
|
var import_agent_sdk5 = require("@robota-sdk/agent-sdk");
|
|
626
|
-
var import_agent_core3 = require("@robota-sdk/agent-core");
|
|
627
697
|
|
|
628
|
-
// src/
|
|
629
|
-
var
|
|
630
|
-
var
|
|
631
|
-
var
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
}
|
|
664
|
-
return state.status;
|
|
665
|
-
}
|
|
666
|
-
function shouldHideAtNextUserTurn(state) {
|
|
667
|
-
return state.status === "completed" && !state.error && (state.result?.exitCode === void 0 || state.result.exitCode === SUCCESS_EXIT_CODE) && !state.result?.signalCode && !state.worktreePath && !state.branchName;
|
|
668
|
-
}
|
|
669
|
-
function trimBackgroundPreview(value) {
|
|
670
|
-
if (!value) return void 0;
|
|
671
|
-
const preview = value.trim().replace(BACKGROUND_PREVIEW_WHITESPACE, BACKGROUND_PREVIEW_SEPARATOR);
|
|
672
|
-
if (!preview) return void 0;
|
|
673
|
-
return preview.length > BACKGROUND_PREVIEW_LENGTH ? `${preview.slice(0, BACKGROUND_PREVIEW_LENGTH)}...` : preview;
|
|
698
|
+
// src/web-sidecar/web-sidecar-server.ts
|
|
699
|
+
var import_node_http = require("http");
|
|
700
|
+
var import_ws = require("ws");
|
|
701
|
+
var import_agent_transport_ws = require("@robota-sdk/agent-transport-ws");
|
|
702
|
+
function startWebSidecarServer(session, port) {
|
|
703
|
+
return new Promise((resolve3, reject) => {
|
|
704
|
+
const httpServer = (0, import_node_http.createServer)((_req, res) => {
|
|
705
|
+
res.writeHead(200, { "Content-Type": "text/plain" });
|
|
706
|
+
res.end("Robota web monitor sidecar");
|
|
707
|
+
});
|
|
708
|
+
const wss = new import_ws.WebSocketServer({ server: httpServer });
|
|
709
|
+
wss.on("connection", (ws) => {
|
|
710
|
+
const send = (message) => {
|
|
711
|
+
if (ws.readyState === import_ws.WebSocket.OPEN) {
|
|
712
|
+
ws.send(JSON.stringify(message));
|
|
713
|
+
}
|
|
714
|
+
};
|
|
715
|
+
const { onMessage, cleanup } = (0, import_agent_transport_ws.createWsHandler)({ session, send });
|
|
716
|
+
ws.on("message", (data) => onMessage(String(data)));
|
|
717
|
+
ws.on("close", cleanup);
|
|
718
|
+
ws.on("error", cleanup);
|
|
719
|
+
const messages = session.getMessages();
|
|
720
|
+
send({ type: "messages", messages });
|
|
721
|
+
});
|
|
722
|
+
httpServer.on("error", reject);
|
|
723
|
+
httpServer.listen(port, "127.0.0.1", () => {
|
|
724
|
+
resolve3({
|
|
725
|
+
port,
|
|
726
|
+
stop: () => new Promise((res) => {
|
|
727
|
+
wss.close(() => {
|
|
728
|
+
httpServer.close(() => res());
|
|
729
|
+
});
|
|
730
|
+
})
|
|
731
|
+
});
|
|
732
|
+
});
|
|
733
|
+
});
|
|
674
734
|
}
|
|
675
735
|
|
|
736
|
+
// src/ui/hooks/useInteractiveSession.ts
|
|
737
|
+
var import_agent_core3 = require("@robota-sdk/agent-core");
|
|
738
|
+
|
|
676
739
|
// src/ui/tui-state-manager.ts
|
|
677
740
|
var MAX_RENDERED_MESSAGES = 100;
|
|
678
741
|
var STREAMING_DEBOUNCE_MS = 300;
|
|
@@ -704,13 +767,12 @@ var TuiStateManager = class {
|
|
|
704
767
|
isAborting = false;
|
|
705
768
|
pendingPrompt = null;
|
|
706
769
|
contextState = { percentage: 0, usedTokens: 0, maxTokens: 0 };
|
|
707
|
-
|
|
770
|
+
executionWorkspaceSnapshot = null;
|
|
771
|
+
selectedExecutionEntryId;
|
|
708
772
|
/** Called after any state change. React hook sets this to trigger re-render. */
|
|
709
773
|
onChange = null;
|
|
710
774
|
// ── Internal ──────────────────────────────────────────────────
|
|
711
775
|
streamBuf = "";
|
|
712
|
-
backgroundTextBuffers = /* @__PURE__ */ new Map();
|
|
713
|
-
backgroundTasksHiddenOnNextTurn = /* @__PURE__ */ new Set();
|
|
714
776
|
debouncedStreamNotify = createDebouncedNotify(() => this.notify(), STREAMING_DEBOUNCE_MS);
|
|
715
777
|
notify() {
|
|
716
778
|
this.onChange?.();
|
|
@@ -779,30 +841,6 @@ var TuiStateManager = class {
|
|
|
779
841
|
maxTokens: state.maxTokens
|
|
780
842
|
});
|
|
781
843
|
};
|
|
782
|
-
onBackgroundTaskEvent = (event) => {
|
|
783
|
-
if ("task" in event) {
|
|
784
|
-
this.upsertBackgroundTask(event.task);
|
|
785
|
-
return;
|
|
786
|
-
}
|
|
787
|
-
if (event.type === "background_task_closed") {
|
|
788
|
-
this.backgroundTextBuffers.delete(event.taskId);
|
|
789
|
-
this.backgroundTasksHiddenOnNextTurn.delete(event.taskId);
|
|
790
|
-
this.backgroundTasks = this.backgroundTasks.filter((task) => task.id !== event.taskId);
|
|
791
|
-
this.notify();
|
|
792
|
-
return;
|
|
793
|
-
}
|
|
794
|
-
if (event.type === "background_task_text_delta") {
|
|
795
|
-
this.appendBackgroundTaskText(event.taskId, event.delta);
|
|
796
|
-
return;
|
|
797
|
-
}
|
|
798
|
-
if (event.type === "background_task_tool_start") {
|
|
799
|
-
this.updateBackgroundTaskAction(event.taskId, event.firstArg ?? event.toolName);
|
|
800
|
-
return;
|
|
801
|
-
}
|
|
802
|
-
if (event.type === "background_task_tool_end") {
|
|
803
|
-
this.updateBackgroundTaskAction(event.taskId, event.success ? void 0 : event.error);
|
|
804
|
-
}
|
|
805
|
-
};
|
|
806
844
|
// ── State updates from external sources ───────────────────────
|
|
807
845
|
/** Sync history from InteractiveSession */
|
|
808
846
|
syncHistory(entries) {
|
|
@@ -839,56 +877,30 @@ var TuiStateManager = class {
|
|
|
839
877
|
this.contextState = state;
|
|
840
878
|
this.notify();
|
|
841
879
|
}
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
const
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
this.
|
|
851
|
-
}
|
|
852
|
-
upsertBackgroundTask(state) {
|
|
853
|
-
const partialText = state.result ? void 0 : this.backgroundTextBuffers.get(state.id);
|
|
854
|
-
const viewModel = toBackgroundTaskViewModel(state, partialText);
|
|
855
|
-
const index = this.backgroundTasks.findIndex((task) => task.id === state.id);
|
|
856
|
-
if (index === -1) {
|
|
857
|
-
this.backgroundTasks = [...this.backgroundTasks, viewModel];
|
|
858
|
-
} else {
|
|
859
|
-
const updated = [...this.backgroundTasks];
|
|
860
|
-
updated[index] = viewModel;
|
|
861
|
-
this.backgroundTasks = updated;
|
|
862
|
-
}
|
|
863
|
-
if (state.status === "completed" || state.status === "failed" || state.status === "cancelled") {
|
|
864
|
-
this.backgroundTextBuffers.delete(state.id);
|
|
865
|
-
}
|
|
866
|
-
if (shouldHideAtNextUserTurn(state)) {
|
|
867
|
-
this.backgroundTasksHiddenOnNextTurn.add(state.id);
|
|
868
|
-
} else {
|
|
869
|
-
this.backgroundTasksHiddenOnNextTurn.delete(state.id);
|
|
870
|
-
}
|
|
871
|
-
this.notify();
|
|
872
|
-
}
|
|
873
|
-
appendBackgroundTaskText(taskId, delta) {
|
|
874
|
-
const nextText = `${this.backgroundTextBuffers.get(taskId) ?? ""}${delta}`;
|
|
875
|
-
this.backgroundTextBuffers.set(taskId, nextText);
|
|
876
|
-
this.backgroundTasks = this.backgroundTasks.map(
|
|
877
|
-
(task) => task.id === taskId ? { ...task, resultPreview: trimBackgroundPreview(nextText) } : task
|
|
878
|
-
);
|
|
880
|
+
syncExecutionWorkspaceSnapshot(snapshot) {
|
|
881
|
+
const currentSelection = this.selectedExecutionEntryId;
|
|
882
|
+
const hasCurrentSelection = currentSelection !== void 0 && snapshot.entries.some((entry) => entry.id === currentSelection);
|
|
883
|
+
const selectedExecutionEntryId = hasCurrentSelection ? currentSelection : snapshot.selectedEntryId ?? snapshot.entries[0]?.id;
|
|
884
|
+
this.executionWorkspaceSnapshot = {
|
|
885
|
+
...snapshot,
|
|
886
|
+
...selectedExecutionEntryId ? { selectedEntryId: selectedExecutionEntryId } : {}
|
|
887
|
+
};
|
|
888
|
+
this.selectedExecutionEntryId = selectedExecutionEntryId;
|
|
879
889
|
this.notify();
|
|
880
890
|
}
|
|
881
|
-
|
|
882
|
-
this.
|
|
883
|
-
|
|
884
|
-
|
|
891
|
+
selectExecutionWorkspaceEntry(entryId) {
|
|
892
|
+
if (!this.executionWorkspaceSnapshot?.entries.some((entry) => entry.id === entryId)) return;
|
|
893
|
+
this.selectedExecutionEntryId = entryId;
|
|
894
|
+
this.executionWorkspaceSnapshot = {
|
|
895
|
+
...this.executionWorkspaceSnapshot,
|
|
896
|
+
selectedEntryId: entryId
|
|
897
|
+
};
|
|
885
898
|
this.notify();
|
|
886
899
|
}
|
|
887
900
|
};
|
|
888
901
|
|
|
889
902
|
// src/ui/hooks/useSlashRouting.ts
|
|
890
903
|
var import_react = require("react");
|
|
891
|
-
var import_node_crypto = require("crypto");
|
|
892
904
|
var import_agent_core2 = require("@robota-sdk/agent-core");
|
|
893
905
|
|
|
894
906
|
// src/plugins/plugin-command-source-loader.ts
|
|
@@ -917,10 +929,9 @@ function reloadPluginCommandSource(registry) {
|
|
|
917
929
|
}
|
|
918
930
|
|
|
919
931
|
// src/ui/hooks/useSlashRouting.ts
|
|
920
|
-
function useSlashRouting(interactiveSession, registry, manager) {
|
|
932
|
+
function useSlashRouting(interactiveSession, registry, manager, commandEffectQueue) {
|
|
921
933
|
return (0, import_react.useCallback)(
|
|
922
934
|
async (input) => {
|
|
923
|
-
manager.onUserTurnAccepted();
|
|
924
935
|
if (!input.startsWith("/")) {
|
|
925
936
|
await interactiveSession.submit(input);
|
|
926
937
|
manager.setPendingPrompt(interactiveSession.getPendingPrompt());
|
|
@@ -931,10 +942,11 @@ function useSlashRouting(interactiveSession, registry, manager) {
|
|
|
931
942
|
const args = parts.slice(1).join(" ");
|
|
932
943
|
const result = await interactiveSession.executeCommand(cmd, args);
|
|
933
944
|
if (result) {
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
945
|
+
if (result.effects?.some((effect) => effect.type === "session-execution-started")) {
|
|
946
|
+
manager.setPendingPrompt(interactiveSession.getPendingPrompt());
|
|
947
|
+
return;
|
|
948
|
+
}
|
|
949
|
+
applySystemCommandResult(result, interactiveSession, registry, manager, commandEffectQueue);
|
|
938
950
|
return;
|
|
939
951
|
}
|
|
940
952
|
manager.addEntry(
|
|
@@ -943,18 +955,17 @@ function useSlashRouting(interactiveSession, registry, manager) {
|
|
|
943
955
|
)
|
|
944
956
|
);
|
|
945
957
|
},
|
|
946
|
-
[interactiveSession, registry, manager]
|
|
958
|
+
[interactiveSession, registry, manager, commandEffectQueue]
|
|
947
959
|
);
|
|
948
960
|
}
|
|
949
|
-
function applySystemCommandResult(result, interactiveSession, registry, manager) {
|
|
961
|
+
function applySystemCommandResult(result, interactiveSession, registry, manager, commandEffectQueue) {
|
|
950
962
|
const pendingEffects = applyImmediateCommandEffects(result.effects, registry, manager);
|
|
951
963
|
manager.addEntry((0, import_agent_core2.messageToHistoryEntry)((0, import_agent_core2.createSystemMessage)(result.message)));
|
|
952
|
-
const effects = getEffects(interactiveSession);
|
|
953
964
|
if (result.interaction !== void 0) {
|
|
954
|
-
|
|
965
|
+
commandEffectQueue.enqueueInteraction(result.interaction);
|
|
955
966
|
}
|
|
956
967
|
if (pendingEffects.length > 0) {
|
|
957
|
-
|
|
968
|
+
commandEffectQueue.enqueueEffects(pendingEffects);
|
|
958
969
|
}
|
|
959
970
|
const ctx = interactiveSession.getContextState();
|
|
960
971
|
manager.setContextState({
|
|
@@ -979,37 +990,42 @@ function applyImmediateCommandEffects(effects, registry, manager) {
|
|
|
979
990
|
}
|
|
980
991
|
return pendingEffects;
|
|
981
992
|
}
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
993
|
+
|
|
994
|
+
// src/ui/hooks/command-effect-queue.ts
|
|
995
|
+
var CommandEffectQueue = class {
|
|
996
|
+
queue = [];
|
|
997
|
+
enqueueInteraction(interaction) {
|
|
998
|
+
this.queue.push({ type: "interaction", interaction });
|
|
986
999
|
}
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
const args = input.slice(1 + cmd.length).trimStart();
|
|
999
|
-
const qualifiedName = registry.resolveQualifiedName(cmd);
|
|
1000
|
-
const hookInput = qualifiedName ? `/${qualifiedName}${input.slice(1 + cmd.length)}` : input;
|
|
1001
|
-
await interactiveSession.executeSkillCommand(skillCmd, args, input, hookInput);
|
|
1002
|
-
manager.setPendingPrompt(interactiveSession.getPendingPrompt());
|
|
1003
|
-
return true;
|
|
1004
|
-
}
|
|
1005
|
-
function getEffects(interactiveSession) {
|
|
1006
|
-
return interactiveSession;
|
|
1007
|
-
}
|
|
1000
|
+
enqueueEffects(effects) {
|
|
1001
|
+
if (effects.length === 0) return;
|
|
1002
|
+
this.queue.push({ type: "effects", effects: [...effects] });
|
|
1003
|
+
}
|
|
1004
|
+
drain() {
|
|
1005
|
+
return this.queue.shift();
|
|
1006
|
+
}
|
|
1007
|
+
clear() {
|
|
1008
|
+
this.queue.length = 0;
|
|
1009
|
+
}
|
|
1010
|
+
};
|
|
1008
1011
|
|
|
1009
1012
|
// src/ui/hooks/useInteractiveSession.ts
|
|
1010
1013
|
function applyCompactEventToManager(interactiveSession, manager) {
|
|
1011
1014
|
manager.syncHistory(interactiveSession.getFullHistory());
|
|
1012
1015
|
}
|
|
1016
|
+
function applySkillActivationEventToManager(interactiveSession, manager) {
|
|
1017
|
+
manager.syncHistory(interactiveSession.getFullHistory());
|
|
1018
|
+
}
|
|
1019
|
+
function syncExecutionWorkspaceFromSession(interactiveSession, manager) {
|
|
1020
|
+
try {
|
|
1021
|
+
manager.syncExecutionWorkspaceSnapshot(
|
|
1022
|
+
interactiveSession.getExecutionWorkspaceSnapshot({
|
|
1023
|
+
selectedEntryId: manager.selectedExecutionEntryId
|
|
1024
|
+
})
|
|
1025
|
+
);
|
|
1026
|
+
} catch {
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1013
1029
|
function initializeSession(props, permissionHandler) {
|
|
1014
1030
|
const interactiveSession = new import_agent_sdk5.InteractiveSession({
|
|
1015
1031
|
cwd: props.cwd,
|
|
@@ -1027,14 +1043,13 @@ function initializeSession(props, permissionHandler) {
|
|
|
1027
1043
|
commandHostAdapters: props.commandHostAdapters
|
|
1028
1044
|
});
|
|
1029
1045
|
const registry = new import_agent_sdk5.CommandRegistry();
|
|
1030
|
-
registry.addModule((0, import_agent_sdk5.createBuiltinCommandModule)());
|
|
1031
1046
|
for (const module2 of props.commandModules ?? []) {
|
|
1032
1047
|
registry.addModule(module2);
|
|
1033
1048
|
}
|
|
1034
|
-
registry.addSource(new import_agent_sdk5.SkillCommandSource(props.cwd));
|
|
1035
1049
|
reloadPluginCommandSource(registry);
|
|
1036
1050
|
const manager = new TuiStateManager();
|
|
1037
|
-
|
|
1051
|
+
const commandEffectQueue = new CommandEffectQueue();
|
|
1052
|
+
return { interactiveSession, registry, manager, commandEffectQueue };
|
|
1038
1053
|
}
|
|
1039
1054
|
function useInteractiveSession(props) {
|
|
1040
1055
|
const [, forceRender] = (0, import_react2.useState)(0);
|
|
@@ -1063,8 +1078,8 @@ function useInteractiveSession(props) {
|
|
|
1063
1078
|
});
|
|
1064
1079
|
}, []);
|
|
1065
1080
|
const permissionHandler = (0, import_react2.useCallback)(
|
|
1066
|
-
(toolName, toolArgs) => new Promise((
|
|
1067
|
-
permissionQueueRef.current.push({ toolName, toolArgs, resolve:
|
|
1081
|
+
(toolName, toolArgs) => new Promise((resolve3) => {
|
|
1082
|
+
permissionQueueRef.current.push({ toolName, toolArgs, resolve: resolve3 });
|
|
1068
1083
|
processNextPermission();
|
|
1069
1084
|
}),
|
|
1070
1085
|
[processNextPermission]
|
|
@@ -1073,7 +1088,7 @@ function useInteractiveSession(props) {
|
|
|
1073
1088
|
if (stateRef.current === null) {
|
|
1074
1089
|
stateRef.current = initializeSession(props, permissionHandler);
|
|
1075
1090
|
}
|
|
1076
|
-
const { interactiveSession, registry, manager } = stateRef.current;
|
|
1091
|
+
const { interactiveSession, registry, manager, commandEffectQueue } = stateRef.current;
|
|
1077
1092
|
manager.onChange = () => forceRender((n) => n + 1);
|
|
1078
1093
|
if (manager.history.length === 0) {
|
|
1079
1094
|
const restored = interactiveSession.getFullHistory();
|
|
@@ -1081,8 +1096,32 @@ function useInteractiveSession(props) {
|
|
|
1081
1096
|
manager.syncHistory(restored);
|
|
1082
1097
|
}
|
|
1083
1098
|
}
|
|
1099
|
+
(0, import_react2.useEffect)(() => {
|
|
1100
|
+
if (!props.webPort) return;
|
|
1101
|
+
const port = props.webPort;
|
|
1102
|
+
let stopped = false;
|
|
1103
|
+
let stopFn = null;
|
|
1104
|
+
startWebSidecarServer(interactiveSession, port).then((server) => {
|
|
1105
|
+
stopFn = server.stop;
|
|
1106
|
+
if (stopped) {
|
|
1107
|
+
server.stop().catch(() => void 0);
|
|
1108
|
+
return;
|
|
1109
|
+
}
|
|
1110
|
+
const shouldOpen = !props.noOpen && !process.env["ROBOTA_NO_OPEN"];
|
|
1111
|
+
const monitorUrl = process.env["ROBOTA_MONITOR_URL"] ?? "http://localhost:7071/monitor";
|
|
1112
|
+
if (shouldOpen) {
|
|
1113
|
+
(0, import_open.default)(monitorUrl).catch(() => void 0);
|
|
1114
|
+
}
|
|
1115
|
+
}).catch(() => void 0);
|
|
1116
|
+
return () => {
|
|
1117
|
+
stopped = true;
|
|
1118
|
+
if (stopFn) stopFn().catch(() => void 0);
|
|
1119
|
+
};
|
|
1120
|
+
}, [interactiveSession, props.webPort, props.noOpen]);
|
|
1084
1121
|
(0, import_react2.useEffect)(() => {
|
|
1085
1122
|
const onCompact = () => applyCompactEventToManager(interactiveSession, manager);
|
|
1123
|
+
const onSkillActivation = () => applySkillActivationEventToManager(interactiveSession, manager);
|
|
1124
|
+
const onExecutionWorkspaceEvent = (event) => manager.syncExecutionWorkspaceSnapshot(event.snapshot);
|
|
1086
1125
|
interactiveSession.on("text_delta", manager.onTextDelta);
|
|
1087
1126
|
interactiveSession.on("tool_start", manager.onToolStart);
|
|
1088
1127
|
interactiveSession.on("tool_end", manager.onToolEnd);
|
|
@@ -1092,7 +1131,8 @@ function useInteractiveSession(props) {
|
|
|
1092
1131
|
interactiveSession.on("error", manager.onError);
|
|
1093
1132
|
interactiveSession.on("context_update", manager.onContextUpdate);
|
|
1094
1133
|
interactiveSession.on("compact", onCompact);
|
|
1095
|
-
interactiveSession.on("
|
|
1134
|
+
interactiveSession.on("skill_activation", onSkillActivation);
|
|
1135
|
+
interactiveSession.on("execution_workspace_event", onExecutionWorkspaceEvent);
|
|
1096
1136
|
const initCheck = setInterval(() => {
|
|
1097
1137
|
try {
|
|
1098
1138
|
const ctx = interactiveSession.getContextState();
|
|
@@ -1105,6 +1145,7 @@ function useInteractiveSession(props) {
|
|
|
1105
1145
|
if (restored.length > 0) {
|
|
1106
1146
|
manager.syncHistory(restored);
|
|
1107
1147
|
}
|
|
1148
|
+
syncExecutionWorkspaceFromSession(interactiveSession, manager);
|
|
1108
1149
|
clearInterval(initCheck);
|
|
1109
1150
|
} catch {
|
|
1110
1151
|
}
|
|
@@ -1120,16 +1161,18 @@ function useInteractiveSession(props) {
|
|
|
1120
1161
|
interactiveSession.off("error", manager.onError);
|
|
1121
1162
|
interactiveSession.off("context_update", manager.onContextUpdate);
|
|
1122
1163
|
interactiveSession.off("compact", onCompact);
|
|
1123
|
-
interactiveSession.off("
|
|
1164
|
+
interactiveSession.off("skill_activation", onSkillActivation);
|
|
1165
|
+
interactiveSession.off("execution_workspace_event", onExecutionWorkspaceEvent);
|
|
1124
1166
|
};
|
|
1125
1167
|
}, [interactiveSession, manager]);
|
|
1126
1168
|
(0, import_react2.useEffect)(() => {
|
|
1127
1169
|
manager.syncHistory(interactiveSession.getFullHistory());
|
|
1170
|
+
syncExecutionWorkspaceFromSession(interactiveSession, manager);
|
|
1128
1171
|
if (!manager.isThinking) {
|
|
1129
1172
|
manager.setPendingPrompt(interactiveSession.getPendingPrompt());
|
|
1130
1173
|
}
|
|
1131
1174
|
}, [manager.isThinking, interactiveSession, manager]);
|
|
1132
|
-
const handleSubmit = useSlashRouting(interactiveSession, registry, manager);
|
|
1175
|
+
const handleSubmit = useSlashRouting(interactiveSession, registry, manager, commandEffectQueue);
|
|
1133
1176
|
const handleAbort = (0, import_react2.useCallback)(() => {
|
|
1134
1177
|
manager.setAborting(true);
|
|
1135
1178
|
interactiveSession.abort();
|
|
@@ -1147,9 +1190,18 @@ function useInteractiveSession(props) {
|
|
|
1147
1190
|
},
|
|
1148
1191
|
[interactiveSession, manager, isShuttingDown]
|
|
1149
1192
|
);
|
|
1193
|
+
const selectExecutionWorkspaceEntry = (0, import_react2.useCallback)(
|
|
1194
|
+
(entryId) => manager.selectExecutionWorkspaceEntry(entryId),
|
|
1195
|
+
[manager]
|
|
1196
|
+
);
|
|
1197
|
+
const readExecutionWorkspaceDetail = (0, import_react2.useCallback)(
|
|
1198
|
+
(entryId) => interactiveSession.readExecutionWorkspaceDetail(entryId),
|
|
1199
|
+
[interactiveSession]
|
|
1200
|
+
);
|
|
1150
1201
|
return {
|
|
1151
1202
|
interactiveSession,
|
|
1152
1203
|
registry,
|
|
1204
|
+
commandEffectQueue,
|
|
1153
1205
|
history: manager.history,
|
|
1154
1206
|
addEntry: (entry) => manager.addEntry(entry),
|
|
1155
1207
|
streamingText: manager.streamingText,
|
|
@@ -1158,13 +1210,16 @@ function useInteractiveSession(props) {
|
|
|
1158
1210
|
isAborting: manager.isAborting,
|
|
1159
1211
|
isShuttingDown,
|
|
1160
1212
|
pendingPrompt: manager.pendingPrompt,
|
|
1161
|
-
|
|
1213
|
+
executionWorkspaceSnapshot: manager.executionWorkspaceSnapshot,
|
|
1214
|
+
selectedExecutionEntryId: manager.selectedExecutionEntryId,
|
|
1162
1215
|
permissionRequest,
|
|
1163
1216
|
contextState: manager.contextState,
|
|
1164
1217
|
handleSubmit,
|
|
1165
1218
|
handleAbort,
|
|
1166
1219
|
handleCancelQueue,
|
|
1167
|
-
handleShutdown
|
|
1220
|
+
handleShutdown,
|
|
1221
|
+
selectExecutionWorkspaceEntry,
|
|
1222
|
+
readExecutionWorkspaceDetail
|
|
1168
1223
|
};
|
|
1169
1224
|
}
|
|
1170
1225
|
|
|
@@ -1433,10 +1488,12 @@ function useSideEffects({
|
|
|
1433
1488
|
cwd,
|
|
1434
1489
|
providerOverride,
|
|
1435
1490
|
interactiveSession,
|
|
1491
|
+
commandEffectQueue,
|
|
1436
1492
|
addEntry,
|
|
1437
1493
|
baseHandleSubmit,
|
|
1438
1494
|
setSessionName,
|
|
1439
|
-
setStatusLineSettings
|
|
1495
|
+
setStatusLineSettings,
|
|
1496
|
+
showSessionPickerOnStart
|
|
1440
1497
|
}) {
|
|
1441
1498
|
const { exit } = (0, import_ink.useApp)();
|
|
1442
1499
|
const [pendingModelId, setPendingModelId] = (0, import_react4.useState)(null);
|
|
@@ -1444,7 +1501,7 @@ function useSideEffects({
|
|
|
1444
1501
|
const [pendingInteractionPrompt, setPendingInteractionPrompt] = (0, import_react4.useState)(null);
|
|
1445
1502
|
const commandInteractionRef = (0, import_react4.useRef)(null);
|
|
1446
1503
|
const [showPluginTUI, setShowPluginTUI] = (0, import_react4.useState)(false);
|
|
1447
|
-
const [showSessionPicker, setShowSessionPicker] = (0, import_react4.useState)(false);
|
|
1504
|
+
const [showSessionPicker, setShowSessionPicker] = (0, import_react4.useState)(showSessionPickerOnStart ?? false);
|
|
1448
1505
|
const requestShutdown = (0, import_react4.useCallback)(
|
|
1449
1506
|
(reason, message) => {
|
|
1450
1507
|
addEntry((0, import_agent_core6.messageToHistoryEntry)((0, import_agent_core6.createSystemMessage)("Shutting down...")));
|
|
@@ -1485,33 +1542,31 @@ function useSideEffects({
|
|
|
1485
1542
|
commandInteractionRef.current = null;
|
|
1486
1543
|
setPendingInteractionPrompt(null);
|
|
1487
1544
|
if (result.effects !== void 0 && result.effects.length > 0) {
|
|
1488
|
-
applyEffects(result.effects, interactiveSession);
|
|
1545
|
+
applyEffects(result.effects, getHostSideEffects(interactiveSession));
|
|
1489
1546
|
}
|
|
1490
1547
|
},
|
|
1491
1548
|
[addEntry, applyEffects, interactiveSession]
|
|
1492
1549
|
);
|
|
1493
1550
|
const applyQueuedCommandState = (0, import_react4.useCallback)(
|
|
1494
1551
|
(sideEffects) => {
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1552
|
+
const queued = commandEffectQueue.drain();
|
|
1553
|
+
if (queued === void 0) {
|
|
1554
|
+
return false;
|
|
1555
|
+
}
|
|
1556
|
+
if (queued.type === "interaction") {
|
|
1557
|
+
const { interaction } = queued;
|
|
1498
1558
|
commandInteractionRef.current = interaction;
|
|
1499
1559
|
setPendingInteractionPrompt(interaction.prompt);
|
|
1500
1560
|
return true;
|
|
1501
1561
|
}
|
|
1502
|
-
|
|
1503
|
-
const effects = sideEffects._pendingCommandEffects;
|
|
1504
|
-
delete sideEffects._pendingCommandEffects;
|
|
1505
|
-
return applyEffects(effects, sideEffects);
|
|
1506
|
-
}
|
|
1507
|
-
return false;
|
|
1562
|
+
return applyEffects(queued.effects, sideEffects);
|
|
1508
1563
|
},
|
|
1509
|
-
[applyEffects]
|
|
1564
|
+
[applyEffects, commandEffectQueue]
|
|
1510
1565
|
);
|
|
1511
1566
|
const handleSubmit = (0, import_react4.useCallback)(
|
|
1512
1567
|
async (input) => {
|
|
1513
1568
|
await baseHandleSubmit(input);
|
|
1514
|
-
const sideEffects = interactiveSession;
|
|
1569
|
+
const sideEffects = getHostSideEffects(interactiveSession);
|
|
1515
1570
|
if (applyQueuedCommandState(sideEffects)) return;
|
|
1516
1571
|
if (sideEffects._pendingModelId) {
|
|
1517
1572
|
const modelId = sideEffects._pendingModelId;
|
|
@@ -1622,6 +1677,9 @@ function useSideEffects({
|
|
|
1622
1677
|
handleInteractionCancel
|
|
1623
1678
|
};
|
|
1624
1679
|
}
|
|
1680
|
+
function getHostSideEffects(interactiveSession) {
|
|
1681
|
+
return interactiveSession;
|
|
1682
|
+
}
|
|
1625
1683
|
|
|
1626
1684
|
// src/ui/hooks/useStatusLineSettings.ts
|
|
1627
1685
|
var import_react5 = require("react");
|
|
@@ -1639,10 +1697,12 @@ var import_agent_core8 = require("@robota-sdk/agent-core");
|
|
|
1639
1697
|
// src/ui/render-markdown.ts
|
|
1640
1698
|
var import_marked = require("marked");
|
|
1641
1699
|
var import_marked_terminal = __toESM(require("marked-terminal"), 1);
|
|
1642
|
-
var
|
|
1643
|
-
var
|
|
1700
|
+
var ANSI_LIGHT_RED = "\x1B[38;5;210m";
|
|
1701
|
+
var ANSI_LIGHT_GREEN = "\x1B[38;5;120m";
|
|
1644
1702
|
var ANSI_CYAN = "\x1B[36m";
|
|
1645
1703
|
var ANSI_DIM = "\x1B[2m";
|
|
1704
|
+
var ANSI_DARK_RED_BACKGROUND = "\x1B[48;5;52m";
|
|
1705
|
+
var ANSI_DARK_GREEN_BACKGROUND = "\x1B[48;5;22m";
|
|
1646
1706
|
var ANSI_RESET = "\x1B[0m";
|
|
1647
1707
|
var CODE_BLOCK_INDENT = " ";
|
|
1648
1708
|
var ZERO_COLOR = "0";
|
|
@@ -1662,36 +1722,59 @@ function shouldUseColor(option) {
|
|
|
1662
1722
|
function isDiffLanguage(language) {
|
|
1663
1723
|
return language?.trim().toLowerCase() === "diff";
|
|
1664
1724
|
}
|
|
1665
|
-
function
|
|
1725
|
+
function styleAddedOrRemovedDiffRow(line, rowWidth, color) {
|
|
1726
|
+
const row = `${CODE_BLOCK_INDENT}${line}`.padEnd(rowWidth);
|
|
1666
1727
|
if (!color) {
|
|
1667
|
-
return
|
|
1728
|
+
return row.trimEnd();
|
|
1668
1729
|
}
|
|
1669
1730
|
if (line.startsWith("+")) {
|
|
1670
|
-
return `${
|
|
1731
|
+
return `${ANSI_DARK_GREEN_BACKGROUND}${ANSI_LIGHT_GREEN}${row}${ANSI_RESET}`;
|
|
1671
1732
|
}
|
|
1672
1733
|
if (line.startsWith("-")) {
|
|
1673
|
-
return `${
|
|
1734
|
+
return `${ANSI_DARK_RED_BACKGROUND}${ANSI_LIGHT_RED}${row}${ANSI_RESET}`;
|
|
1735
|
+
}
|
|
1736
|
+
return row.trimEnd();
|
|
1737
|
+
}
|
|
1738
|
+
function colorizeDiffLine(line, color, rowWidth) {
|
|
1739
|
+
if (line.startsWith("+") || line.startsWith("-")) {
|
|
1740
|
+
return styleAddedOrRemovedDiffRow(line, rowWidth, color);
|
|
1741
|
+
}
|
|
1742
|
+
const row = `${CODE_BLOCK_INDENT}${line}`;
|
|
1743
|
+
if (!color) {
|
|
1744
|
+
return row;
|
|
1674
1745
|
}
|
|
1675
1746
|
if (line.startsWith("@@")) {
|
|
1676
|
-
return `${ANSI_CYAN}${
|
|
1747
|
+
return `${ANSI_CYAN}${row}${ANSI_RESET}`;
|
|
1677
1748
|
}
|
|
1678
1749
|
if (line.startsWith("diff ") || line.startsWith("index ")) {
|
|
1679
|
-
return `${ANSI_DIM}${
|
|
1750
|
+
return `${ANSI_DIM}${row}${ANSI_RESET}`;
|
|
1751
|
+
}
|
|
1752
|
+
return row;
|
|
1753
|
+
}
|
|
1754
|
+
function resolveDiffRowWidth(lines, requestedWidth) {
|
|
1755
|
+
const minimumWidth = lines.reduce(
|
|
1756
|
+
(maxWidth, line) => Math.max(maxWidth, CODE_BLOCK_INDENT.length + line.length),
|
|
1757
|
+
0
|
|
1758
|
+
);
|
|
1759
|
+
if (requestedWidth === void 0) {
|
|
1760
|
+
return minimumWidth;
|
|
1680
1761
|
}
|
|
1681
|
-
return
|
|
1762
|
+
return Math.max(minimumWidth, requestedWidth);
|
|
1682
1763
|
}
|
|
1683
|
-
function renderDiffCodeBlock(code, color) {
|
|
1684
|
-
const
|
|
1764
|
+
function renderDiffCodeBlock(code, color, codeBlockWidth) {
|
|
1765
|
+
const lines = code.split("\n");
|
|
1766
|
+
const rowWidth = resolveDiffRowWidth(lines, codeBlockWidth);
|
|
1767
|
+
const body = lines.map((line) => colorizeDiffLine(line, color, rowWidth)).join("\n");
|
|
1685
1768
|
return `${body}
|
|
1686
1769
|
|
|
1687
1770
|
`;
|
|
1688
1771
|
}
|
|
1689
|
-
function createTerminalRenderer(color) {
|
|
1772
|
+
function createTerminalRenderer(color, codeBlockWidth) {
|
|
1690
1773
|
const renderer = new TerminalRendererConstructor(void 0, { ignoreIllegals: true });
|
|
1691
1774
|
const renderCode = renderer.code.bind(renderer);
|
|
1692
1775
|
renderer.code = (code, language, escaped) => {
|
|
1693
1776
|
if (isDiffLanguage(language)) {
|
|
1694
|
-
return renderDiffCodeBlock(code, color);
|
|
1777
|
+
return renderDiffCodeBlock(code, color, codeBlockWidth);
|
|
1695
1778
|
}
|
|
1696
1779
|
return renderCode(code, language, escaped);
|
|
1697
1780
|
};
|
|
@@ -1699,7 +1782,7 @@ function createTerminalRenderer(color) {
|
|
|
1699
1782
|
}
|
|
1700
1783
|
function renderMarkdown(md, options = {}) {
|
|
1701
1784
|
const result = import_marked.marked.parse(md, {
|
|
1702
|
-
renderer: createTerminalRenderer(shouldUseColor(options.color))
|
|
1785
|
+
renderer: createTerminalRenderer(shouldUseColor(options.color), options.codeBlockWidth)
|
|
1703
1786
|
});
|
|
1704
1787
|
return typeof result === "string" ? result.trimEnd() : md;
|
|
1705
1788
|
}
|
|
@@ -1818,7 +1901,7 @@ function formatUsageTokenCount(tokens) {
|
|
|
1818
1901
|
|
|
1819
1902
|
// src/ui/command-output-summary.ts
|
|
1820
1903
|
var MAX_PREVIEW_LINES = 4;
|
|
1821
|
-
var
|
|
1904
|
+
var SUCCESS_EXIT_CODE = 0;
|
|
1822
1905
|
var COMMAND_TOOL_NAMES = /* @__PURE__ */ new Set(["Bash", "BackgroundProcess"]);
|
|
1823
1906
|
function formatCommandOutputSummary(tool) {
|
|
1824
1907
|
if (!COMMAND_TOOL_NAMES.has(tool.toolName) || !tool.toolResultData) return void 0;
|
|
@@ -1829,7 +1912,7 @@ function formatCommandOutputSummary(tool) {
|
|
|
1829
1912
|
const lines = trimTrailingBlankLines(splitOutputLines(output));
|
|
1830
1913
|
const previewLines = lines.slice(0, MAX_PREVIEW_LINES);
|
|
1831
1914
|
const omittedLineCount = Math.max(0, lines.length - previewLines.length);
|
|
1832
|
-
const isFailed = tool.result === "error" || successValue === false || exitCode !== void 0 && exitCode !==
|
|
1915
|
+
const isFailed = tool.result === "error" || successValue === false || exitCode !== void 0 && exitCode !== SUCCESS_EXIT_CODE;
|
|
1833
1916
|
return {
|
|
1834
1917
|
status: isFailed ? "error" : "success",
|
|
1835
1918
|
statusLabel: formatStatusLabel(isFailed, exitCode),
|
|
@@ -1859,7 +1942,7 @@ function buildOutputText(raw, parsed) {
|
|
|
1859
1942
|
return lines.join("\n");
|
|
1860
1943
|
}
|
|
1861
1944
|
function formatStatusLabel(isFailed, exitCode) {
|
|
1862
|
-
if (exitCode !== void 0 && exitCode !==
|
|
1945
|
+
if (exitCode !== void 0 && exitCode !== SUCCESS_EXIT_CODE) return `exit ${exitCode}`;
|
|
1863
1946
|
return isFailed ? "error" : "ok";
|
|
1864
1947
|
}
|
|
1865
1948
|
function splitOutputLines(output) {
|
|
@@ -2211,11 +2294,7 @@ function StatusActivityText({
|
|
|
2211
2294
|
activeBackgroundTaskCount,
|
|
2212
2295
|
hasPendingPrompt
|
|
2213
2296
|
});
|
|
2214
|
-
return /* @__PURE__ */ (0, import_jsx_runtime5.
|
|
2215
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_ink6.Text, { color: "cyan", bold: true, children: "Activity:" }),
|
|
2216
|
-
" ",
|
|
2217
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_ink6.Text, { color: activity.color, bold: activity.kind !== "idle", children: activity.text })
|
|
2218
|
-
] });
|
|
2297
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_ink6.Text, { color: activity.color, bold: activity.kind !== "idle", children: activity.text });
|
|
2219
2298
|
}
|
|
2220
2299
|
function ContextText({
|
|
2221
2300
|
percentage,
|
|
@@ -2239,77 +2318,79 @@ function ModeText({ permissionMode }) {
|
|
|
2239
2318
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_ink6.Text, { children: permissionMode })
|
|
2240
2319
|
] });
|
|
2241
2320
|
}
|
|
2242
|
-
function
|
|
2243
|
-
permissionMode
|
|
2321
|
+
function shouldShowPermissionMode(permissionMode) {
|
|
2322
|
+
return permissionMode !== "default";
|
|
2323
|
+
}
|
|
2324
|
+
function ProviderText({
|
|
2244
2325
|
modelName,
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
activeBackgroundTaskCount,
|
|
2248
|
-
hasPendingPrompt,
|
|
2249
|
-
contextPercentage,
|
|
2250
|
-
contextUsedTokens,
|
|
2251
|
-
contextMaxTokens,
|
|
2252
|
-
sessionName,
|
|
2253
|
-
gitBranch,
|
|
2254
|
-
showGitBranch
|
|
2326
|
+
providerProfileName,
|
|
2327
|
+
providerType
|
|
2255
2328
|
}) {
|
|
2256
|
-
|
|
2329
|
+
if (providerProfileName !== void 0 && providerType !== void 0) {
|
|
2330
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_ink6.Text, { dimColor: true, children: [
|
|
2331
|
+
providerProfileName,
|
|
2332
|
+
" (",
|
|
2333
|
+
providerType,
|
|
2334
|
+
") ",
|
|
2335
|
+
modelName
|
|
2336
|
+
] });
|
|
2337
|
+
}
|
|
2338
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_ink6.Text, { dimColor: true, children: modelName });
|
|
2339
|
+
}
|
|
2340
|
+
function StatusLeft(props) {
|
|
2341
|
+
const shouldShowGitBranch = props.showGitBranch && props.gitBranch !== void 0 && props.gitBranch.length > 0;
|
|
2342
|
+
const showPermissionMode = shouldShowPermissionMode(props.permissionMode);
|
|
2257
2343
|
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_ink6.Text, { children: [
|
|
2258
2344
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2259
2345
|
StatusActivityText,
|
|
2260
2346
|
{
|
|
2261
|
-
isThinking,
|
|
2262
|
-
activeToolCount,
|
|
2263
|
-
activeBackgroundTaskCount,
|
|
2264
|
-
hasPendingPrompt
|
|
2347
|
+
isThinking: props.isThinking,
|
|
2348
|
+
activeToolCount: props.activeToolCount,
|
|
2349
|
+
activeBackgroundTaskCount: props.activeBackgroundTaskCount,
|
|
2350
|
+
hasPendingPrompt: props.hasPendingPrompt
|
|
2265
2351
|
}
|
|
2266
2352
|
),
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2353
|
+
showPermissionMode && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
2354
|
+
" | ",
|
|
2355
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ModeText, { permissionMode: props.permissionMode })
|
|
2356
|
+
] }),
|
|
2357
|
+
props.sessionName && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
2270
2358
|
" | ",
|
|
2271
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_ink6.Text, { color: "magenta", children: sessionName })
|
|
2359
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_ink6.Text, { color: "magenta", children: props.sessionName })
|
|
2272
2360
|
] }),
|
|
2273
2361
|
shouldShowGitBranch && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
2274
2362
|
" | ",
|
|
2275
2363
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_ink6.Text, { dimColor: true, children: [
|
|
2276
2364
|
"git: ",
|
|
2277
|
-
gitBranch
|
|
2365
|
+
props.gitBranch
|
|
2278
2366
|
] })
|
|
2279
2367
|
] }),
|
|
2280
2368
|
" | ",
|
|
2281
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2369
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2370
|
+
ProviderText,
|
|
2371
|
+
{
|
|
2372
|
+
modelName: props.modelName,
|
|
2373
|
+
providerProfileName: props.providerProfileName,
|
|
2374
|
+
providerType: props.providerType
|
|
2375
|
+
}
|
|
2376
|
+
),
|
|
2282
2377
|
" | ",
|
|
2283
2378
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2284
2379
|
ContextText,
|
|
2285
2380
|
{
|
|
2286
|
-
percentage: contextPercentage,
|
|
2287
|
-
usedTokens: contextUsedTokens,
|
|
2288
|
-
maxTokens: contextMaxTokens
|
|
2381
|
+
percentage: props.contextPercentage,
|
|
2382
|
+
usedTokens: props.contextUsedTokens,
|
|
2383
|
+
maxTokens: props.contextMaxTokens
|
|
2289
2384
|
}
|
|
2290
2385
|
)
|
|
2291
2386
|
] });
|
|
2292
2387
|
}
|
|
2293
|
-
function StatusRight({
|
|
2294
|
-
isThinking,
|
|
2295
|
-
messageCount
|
|
2296
|
-
}) {
|
|
2297
|
-
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_ink6.Text, { children: [
|
|
2298
|
-
isThinking && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
2299
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_ink6.Text, { color: "yellow", children: "thinking..." }),
|
|
2300
|
-
" "
|
|
2301
|
-
] }),
|
|
2302
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_ink6.Text, { dimColor: true, children: [
|
|
2303
|
-
"msgs: ",
|
|
2304
|
-
messageCount
|
|
2305
|
-
] })
|
|
2306
|
-
] });
|
|
2307
|
-
}
|
|
2308
2388
|
function StatusBar({
|
|
2309
2389
|
permissionMode,
|
|
2310
2390
|
modelName,
|
|
2391
|
+
providerProfileName,
|
|
2392
|
+
providerType,
|
|
2311
2393
|
sessionId: _sessionId,
|
|
2312
|
-
messageCount,
|
|
2313
2394
|
isThinking,
|
|
2314
2395
|
activeToolCount = 0,
|
|
2315
2396
|
activeBackgroundTaskCount = 0,
|
|
@@ -2321,7 +2402,7 @@ function StatusBar({
|
|
|
2321
2402
|
gitBranch,
|
|
2322
2403
|
showGitBranch = true
|
|
2323
2404
|
}) {
|
|
2324
|
-
return /* @__PURE__ */ (0, import_jsx_runtime5.
|
|
2405
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2325
2406
|
import_ink6.Box,
|
|
2326
2407
|
{
|
|
2327
2408
|
borderStyle: "single",
|
|
@@ -2329,26 +2410,25 @@ function StatusBar({
|
|
|
2329
2410
|
paddingLeft: 1,
|
|
2330
2411
|
paddingRight: 1,
|
|
2331
2412
|
justifyContent: "space-between",
|
|
2332
|
-
children:
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
]
|
|
2413
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2414
|
+
StatusLeft,
|
|
2415
|
+
{
|
|
2416
|
+
permissionMode,
|
|
2417
|
+
modelName,
|
|
2418
|
+
providerProfileName,
|
|
2419
|
+
providerType,
|
|
2420
|
+
isThinking,
|
|
2421
|
+
activeToolCount,
|
|
2422
|
+
activeBackgroundTaskCount,
|
|
2423
|
+
hasPendingPrompt,
|
|
2424
|
+
contextPercentage,
|
|
2425
|
+
contextUsedTokens,
|
|
2426
|
+
contextMaxTokens,
|
|
2427
|
+
sessionName,
|
|
2428
|
+
gitBranch,
|
|
2429
|
+
showGitBranch
|
|
2430
|
+
}
|
|
2431
|
+
)
|
|
2352
2432
|
}
|
|
2353
2433
|
);
|
|
2354
2434
|
}
|
|
@@ -2359,8 +2439,9 @@ function SessionStatusBar({
|
|
|
2359
2439
|
cwd,
|
|
2360
2440
|
permissionMode,
|
|
2361
2441
|
modelId,
|
|
2442
|
+
providerProfileName,
|
|
2443
|
+
providerType,
|
|
2362
2444
|
sessionId,
|
|
2363
|
-
messageCount,
|
|
2364
2445
|
isThinking,
|
|
2365
2446
|
activeToolCount,
|
|
2366
2447
|
activeBackgroundTaskCount,
|
|
@@ -2376,8 +2457,9 @@ function SessionStatusBar({
|
|
|
2376
2457
|
{
|
|
2377
2458
|
permissionMode,
|
|
2378
2459
|
modelName: modelId ? (0, import_agent_core10.getModelName)(modelId) : "",
|
|
2460
|
+
providerProfileName,
|
|
2461
|
+
providerType,
|
|
2379
2462
|
sessionId,
|
|
2380
|
-
messageCount,
|
|
2381
2463
|
isThinking,
|
|
2382
2464
|
activeToolCount,
|
|
2383
2465
|
activeBackgroundTaskCount,
|
|
@@ -3405,6 +3487,7 @@ function submitTextPromptValue(state, options) {
|
|
|
3405
3487
|
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
3406
3488
|
function TextPrompt({
|
|
3407
3489
|
title,
|
|
3490
|
+
description,
|
|
3408
3491
|
placeholder,
|
|
3409
3492
|
onSubmit,
|
|
3410
3493
|
onCancel,
|
|
@@ -3429,12 +3512,11 @@ function TextPrompt({
|
|
|
3429
3512
|
);
|
|
3430
3513
|
(0, import_ink13.useInput)((input, key) => {
|
|
3431
3514
|
const action = getTextPromptInputAction(input, key);
|
|
3432
|
-
if (action !== void 0)
|
|
3433
|
-
applyAction(action);
|
|
3434
|
-
}
|
|
3515
|
+
if (action !== void 0) applyAction(action);
|
|
3435
3516
|
});
|
|
3436
3517
|
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_ink13.Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
|
|
3437
3518
|
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_ink13.Text, { color: "yellow", bold: true, children: title }),
|
|
3519
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(PromptDescription, { description }),
|
|
3438
3520
|
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_ink13.Box, { marginTop: 1, children: [
|
|
3439
3521
|
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_ink13.Text, { color: "cyan", children: "> " }),
|
|
3440
3522
|
state.value ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_ink13.Text, { children: masked ? "*".repeat(state.value.length) : state.value }) : placeholder ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_ink13.Text, { dimColor: true, children: placeholder }) : null,
|
|
@@ -3444,6 +3526,12 @@ function TextPrompt({
|
|
|
3444
3526
|
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_ink13.Text, { dimColor: true, children: " Enter Submit Esc Cancel" })
|
|
3445
3527
|
] });
|
|
3446
3528
|
}
|
|
3529
|
+
function PromptDescription({ description }) {
|
|
3530
|
+
if (description === void 0 || description.length === 0) {
|
|
3531
|
+
return null;
|
|
3532
|
+
}
|
|
3533
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_ink13.Text, { dimColor: true, children: description });
|
|
3534
|
+
}
|
|
3447
3535
|
|
|
3448
3536
|
// src/ui/InteractivePrompt.tsx
|
|
3449
3537
|
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
@@ -3457,6 +3545,7 @@ function InteractivePrompt({
|
|
|
3457
3545
|
TextPrompt,
|
|
3458
3546
|
{
|
|
3459
3547
|
title: prompt.title,
|
|
3548
|
+
description: prompt.description,
|
|
3460
3549
|
placeholder: prompt.placeholder,
|
|
3461
3550
|
allowEmpty: prompt.allowEmpty,
|
|
3462
3551
|
masked: prompt.masked,
|
|
@@ -3469,6 +3558,7 @@ function InteractivePrompt({
|
|
|
3469
3558
|
}
|
|
3470
3559
|
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_ink14.Box, { flexDirection: "column", children: [
|
|
3471
3560
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_ink14.Text, { bold: true, children: prompt.title }),
|
|
3561
|
+
prompt.description !== void 0 && prompt.description.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_ink14.Text, { dimColor: true, children: prompt.description }),
|
|
3472
3562
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
3473
3563
|
ListPicker,
|
|
3474
3564
|
{
|
|
@@ -4059,26 +4149,20 @@ function PluginTUI({ callbacks, onClose, addMessage }) {
|
|
|
4059
4149
|
var import_ink18 = require("ink");
|
|
4060
4150
|
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
4061
4151
|
var SESSION_ID_DISPLAY_LENGTH = 8;
|
|
4152
|
+
var SESSION_PREVIEW_DISPLAY_LENGTH = 60;
|
|
4062
4153
|
function SessionPicker({
|
|
4063
|
-
|
|
4064
|
-
cwd,
|
|
4154
|
+
sessions,
|
|
4065
4155
|
onSelect,
|
|
4066
4156
|
onCancel
|
|
4067
4157
|
}) {
|
|
4068
|
-
const sessions = (sessionStore?.list() ?? []).filter((s) => s.cwd === cwd);
|
|
4069
4158
|
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_ink18.Box, { flexDirection: "column", paddingX: 1, marginBottom: 1, children: [
|
|
4070
4159
|
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_ink18.Text, { bold: true, color: "cyan", children: "Select a session to resume (ESC to cancel):" }),
|
|
4071
4160
|
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4072
4161
|
ListPicker,
|
|
4073
4162
|
{
|
|
4074
|
-
items: sessions,
|
|
4163
|
+
items: [...sessions],
|
|
4075
4164
|
renderItem: (session, isSelected) => {
|
|
4076
|
-
const
|
|
4077
|
-
const msg = m;
|
|
4078
|
-
return msg.role === "assistant" && msg.content;
|
|
4079
|
-
});
|
|
4080
|
-
const rawPreview = lastMsg?.content?.replace(/[\n\r]+/g, " ").trim() ?? "";
|
|
4081
|
-
const preview = rawPreview ? rawPreview.slice(0, 60) + (rawPreview.length > 60 ? "..." : "") : "";
|
|
4165
|
+
const preview = session.preview ? session.preview.slice(0, SESSION_PREVIEW_DISPLAY_LENGTH) + (session.preview.length > SESSION_PREVIEW_DISPLAY_LENGTH ? "..." : "") : "";
|
|
4082
4166
|
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_ink18.Text, { children: [
|
|
4083
4167
|
isSelected ? "> " : " ",
|
|
4084
4168
|
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_ink18.Text, { bold: true, children: session.name ?? session.id.slice(0, SESSION_ID_DISPLAY_LENGTH) }),
|
|
@@ -4092,7 +4176,7 @@ function SessionPicker({
|
|
|
4092
4176
|
" ",
|
|
4093
4177
|
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_ink18.Text, { dimColor: true, children: [
|
|
4094
4178
|
"msgs: ",
|
|
4095
|
-
session.
|
|
4179
|
+
session.messageCount
|
|
4096
4180
|
] }),
|
|
4097
4181
|
preview ? /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_runtime19.Fragment, { children: [
|
|
4098
4182
|
"\n ",
|
|
@@ -4110,115 +4194,281 @@ function SessionPicker({
|
|
|
4110
4194
|
// src/ui/BackgroundTaskPanel.tsx
|
|
4111
4195
|
var import_ink19 = require("ink");
|
|
4112
4196
|
|
|
4113
|
-
// src/ui/
|
|
4114
|
-
var
|
|
4115
|
-
|
|
4116
|
-
|
|
4117
|
-
|
|
4118
|
-
|
|
4119
|
-
|
|
4120
|
-
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
return {
|
|
4128
|
-
...row,
|
|
4129
|
-
accessibleText: formatAccessibleText(row)
|
|
4130
|
-
};
|
|
4197
|
+
// src/ui/execution-workspace-view-model.ts
|
|
4198
|
+
var ACTIVE_STATUSES = [
|
|
4199
|
+
"active",
|
|
4200
|
+
"queued",
|
|
4201
|
+
"running",
|
|
4202
|
+
"waiting_permission"
|
|
4203
|
+
];
|
|
4204
|
+
var DETAIL_RECORD_TEXT_LIMIT = 160;
|
|
4205
|
+
var PREVIEW_WHITESPACE = /\s+/g;
|
|
4206
|
+
var PREVIEW_SEPARATOR = " ";
|
|
4207
|
+
function getDefaultBackgroundWorkspaceEntries(snapshot) {
|
|
4208
|
+
return (snapshot?.entries ?? []).filter(
|
|
4209
|
+
(entry) => entry.kind === "background_task" && entry.visibility === "default"
|
|
4210
|
+
);
|
|
4131
4211
|
}
|
|
4132
|
-
function
|
|
4133
|
-
|
|
4134
|
-
|
|
4135
|
-
|
|
4136
|
-
return "cyan";
|
|
4212
|
+
function countActiveBackgroundWorkspaceEntries(snapshot) {
|
|
4213
|
+
return getDefaultBackgroundWorkspaceEntries(snapshot).filter(
|
|
4214
|
+
(entry) => ACTIVE_STATUSES.includes(entry.status)
|
|
4215
|
+
).length;
|
|
4137
4216
|
}
|
|
4138
|
-
function
|
|
4139
|
-
|
|
4140
|
-
|
|
4217
|
+
function formatExecutionWorkspaceEntryRow(entry, options = {}) {
|
|
4218
|
+
const isSelected = entry.id === options.selectedEntryId;
|
|
4219
|
+
const row = {
|
|
4220
|
+
id: entry.id,
|
|
4221
|
+
radio: isSelected ? "\u25CF" : "\u25CB",
|
|
4222
|
+
title: formatEntryTitle(entry),
|
|
4223
|
+
subtitle: formatEntrySubtitle(entry),
|
|
4224
|
+
statusLabel: formatStatusLabel2(entry.status),
|
|
4225
|
+
preview: trimPreview(entry.preview ?? entry.currentAction),
|
|
4226
|
+
color: getEntryColor(entry),
|
|
4227
|
+
isSelected
|
|
4228
|
+
};
|
|
4229
|
+
return { ...row, accessibleText: formatAccessibleText(row) };
|
|
4230
|
+
}
|
|
4231
|
+
function formatExecutionDetailRecord(record) {
|
|
4232
|
+
const text = record.text.trim().replace(PREVIEW_WHITESPACE, PREVIEW_SEPARATOR);
|
|
4233
|
+
if (!text) return record.kind;
|
|
4234
|
+
return text.length > DETAIL_RECORD_TEXT_LIMIT ? `${text.slice(0, DETAIL_RECORD_TEXT_LIMIT)}...` : text;
|
|
4235
|
+
}
|
|
4236
|
+
function formatEntryTitle(entry) {
|
|
4237
|
+
if (entry.kind === "main_thread") return entry.title;
|
|
4238
|
+
if (entry.kind === "background_group") return `${entry.title} group`;
|
|
4239
|
+
if (entry.taskKind === "agent") return `${entry.title} agent`;
|
|
4240
|
+
if (entry.taskKind === "process") return entry.title || "Process";
|
|
4241
|
+
return entry.title;
|
|
4242
|
+
}
|
|
4243
|
+
function formatEntrySubtitle(entry) {
|
|
4244
|
+
if (entry.kind === "main_thread") return entry.subtitle;
|
|
4245
|
+
const parts = [
|
|
4246
|
+
entry.taskKind,
|
|
4247
|
+
entry.subtitle,
|
|
4248
|
+
entry.attention === "none" ? void 0 : entry.attention
|
|
4249
|
+
];
|
|
4250
|
+
return parts.filter((part) => typeof part === "string" && part.length > 0).join(" \xB7 ") || void 0;
|
|
4141
4251
|
}
|
|
4142
|
-
function
|
|
4143
|
-
|
|
4144
|
-
if (task.kind === "process") return task.label || "Process";
|
|
4145
|
-
return task.label;
|
|
4252
|
+
function formatStatusLabel2(status) {
|
|
4253
|
+
return status.replace(/_/g, " ");
|
|
4146
4254
|
}
|
|
4147
|
-
function
|
|
4148
|
-
|
|
4149
|
-
if (
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
|
|
4154
|
-
segments.push(task.statusLabel === "timed out" ? "timed out" : "failed");
|
|
4155
|
-
}
|
|
4156
|
-
if (task.status === "cancelled") {
|
|
4157
|
-
segments.push("cancelled");
|
|
4158
|
-
}
|
|
4159
|
-
if (task.timeoutReason) {
|
|
4160
|
-
segments.push(task.timeoutReason);
|
|
4161
|
-
}
|
|
4162
|
-
if (task.status === "completed" && task.exitCode !== void 0 && task.exitCode !== SUCCESS_EXIT_CODE3) {
|
|
4163
|
-
segments.push(`exit ${task.exitCode}`);
|
|
4164
|
-
}
|
|
4165
|
-
if (task.signalCode) {
|
|
4166
|
-
segments.push(`signal ${task.signalCode}`);
|
|
4167
|
-
}
|
|
4168
|
-
if (task.worktreePath || task.branchName) {
|
|
4169
|
-
segments.push("worktree");
|
|
4170
|
-
}
|
|
4171
|
-
return segments;
|
|
4255
|
+
function getEntryColor(entry) {
|
|
4256
|
+
if (entry.attention === "failed" || entry.status === "failed") return "red";
|
|
4257
|
+
if (entry.attention === "permission" || entry.status === "waiting_permission") return "yellow";
|
|
4258
|
+
if (entry.status === "completed") return "green";
|
|
4259
|
+
if (entry.status === "cancelled") return "yellow";
|
|
4260
|
+
if (ACTIVE_STATUSES.includes(entry.status)) return "cyan";
|
|
4261
|
+
return "white";
|
|
4172
4262
|
}
|
|
4173
|
-
function
|
|
4174
|
-
|
|
4175
|
-
if (task.worktreePath) return task.worktreePath;
|
|
4176
|
-
const preview = task.errorPreview ?? task.resultPreview ?? task.currentAction ?? task.preview;
|
|
4263
|
+
function trimPreview(value) {
|
|
4264
|
+
const preview = value?.trim().replace(PREVIEW_WHITESPACE, PREVIEW_SEPARATOR);
|
|
4177
4265
|
return preview || void 0;
|
|
4178
4266
|
}
|
|
4179
|
-
function
|
|
4180
|
-
|
|
4181
|
-
|
|
4182
|
-
if (Number.isNaN(timestamp)) return void 0;
|
|
4183
|
-
const seconds = Math.max(0, Math.floor((now - timestamp) / MS_PER_SECOND));
|
|
4184
|
-
if (seconds < SECONDS_PER_MINUTE) return `${seconds}s`;
|
|
4185
|
-
const minutes = Math.floor(seconds / SECONDS_PER_MINUTE);
|
|
4186
|
-
if (minutes < MINUTES_PER_HOUR) return `${minutes}m`;
|
|
4187
|
-
return `${Math.floor(minutes / MINUTES_PER_HOUR)}h`;
|
|
4267
|
+
function formatAccessibleText(row) {
|
|
4268
|
+
const parts = [row.radio, row.title, row.statusLabel, row.subtitle, row.preview];
|
|
4269
|
+
return parts.filter((part) => typeof part === "string" && part.length > 0).join(" \xB7 ");
|
|
4188
4270
|
}
|
|
4189
|
-
|
|
4190
|
-
|
|
4271
|
+
|
|
4272
|
+
// src/ui/background-task-row-format.ts
|
|
4273
|
+
function formatBackgroundTaskRow(entry, options = {}) {
|
|
4274
|
+
const row = formatExecutionWorkspaceEntryRow(entry);
|
|
4275
|
+
const marker = isActiveEntry(entry) ? "\u25A1" : "\u25A0";
|
|
4276
|
+
const segments = [row.statusLabel, row.subtitle].filter(
|
|
4277
|
+
(segment) => typeof segment === "string" && segment.length > 0
|
|
4278
|
+
);
|
|
4279
|
+
return {
|
|
4280
|
+
connector: options.isLast === false ? "\u251C" : "\u2514",
|
|
4281
|
+
marker,
|
|
4282
|
+
color: row.color,
|
|
4283
|
+
label: row.title,
|
|
4284
|
+
segments,
|
|
4285
|
+
preview: row.preview,
|
|
4286
|
+
accessibleText: [
|
|
4287
|
+
`${options.isLast === false ? "\u251C" : "\u2514"} ${marker} ${row.title}`,
|
|
4288
|
+
...segments,
|
|
4289
|
+
row.preview
|
|
4290
|
+
].filter((part) => typeof part === "string" && part.length > 0).join(" \xB7 ")
|
|
4291
|
+
};
|
|
4191
4292
|
}
|
|
4192
|
-
function
|
|
4193
|
-
|
|
4194
|
-
if (row.preview) parts.push(row.preview);
|
|
4195
|
-
return parts.join(" \xB7 ");
|
|
4293
|
+
function isActiveEntry(entry) {
|
|
4294
|
+
return entry.status === "active" || entry.status === "queued" || entry.status === "running" || entry.status === "waiting_permission";
|
|
4196
4295
|
}
|
|
4197
4296
|
|
|
4198
4297
|
// src/ui/BackgroundTaskPanel.tsx
|
|
4199
4298
|
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
4200
|
-
function BackgroundTaskPanel({
|
|
4201
|
-
if (
|
|
4299
|
+
function BackgroundTaskPanel({ entries }) {
|
|
4300
|
+
if (entries.length === 0) return null;
|
|
4202
4301
|
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_ink19.Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
4203
4302
|
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_ink19.Text, { color: "cyan", bold: true, children: "Background work" }),
|
|
4204
|
-
|
|
4205
|
-
const row = formatBackgroundTaskRow(
|
|
4303
|
+
entries.map((entry, index) => {
|
|
4304
|
+
const row = formatBackgroundTaskRow(entry, { isLast: index === entries.length - 1 });
|
|
4206
4305
|
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_ink19.Text, { children: [
|
|
4207
4306
|
`${row.connector} `,
|
|
4208
4307
|
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_ink19.Text, { color: row.color, children: row.marker }),
|
|
4209
4308
|
` ${row.label}`,
|
|
4210
4309
|
row.segments.map((segment, segmentIndex) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_ink19.Text, { dimColor: true, children: ` \xB7 ${segment}` }, `${segment}-${segmentIndex}`)),
|
|
4211
4310
|
row.preview ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_ink19.Text, { dimColor: true, children: ` \xB7 ${row.preview}` }) : null
|
|
4212
|
-
] },
|
|
4311
|
+
] }, entry.id);
|
|
4213
4312
|
})
|
|
4214
4313
|
] });
|
|
4215
4314
|
}
|
|
4216
4315
|
|
|
4217
|
-
// src/ui/
|
|
4316
|
+
// src/ui/ExecutionWorkspaceSwitcher.tsx
|
|
4317
|
+
var import_react19 = require("react");
|
|
4218
4318
|
var import_ink20 = require("ink");
|
|
4219
4319
|
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
4320
|
+
var MAX_VISIBLE_WORKSPACE_ENTRIES = 8;
|
|
4321
|
+
function ExecutionWorkspaceSwitcher({
|
|
4322
|
+
snapshot,
|
|
4323
|
+
selectedEntryId,
|
|
4324
|
+
onSelect,
|
|
4325
|
+
onClose
|
|
4326
|
+
}) {
|
|
4327
|
+
const entries = [...snapshot?.entries ?? []];
|
|
4328
|
+
const { normalized, visibleEntries, applyAction } = useWorkspaceSwitcherSelection({
|
|
4329
|
+
entries,
|
|
4330
|
+
selectedEntryId,
|
|
4331
|
+
onSelect,
|
|
4332
|
+
onClose
|
|
4333
|
+
});
|
|
4334
|
+
(0, import_ink20.useInput)((_input, key) => {
|
|
4335
|
+
const action = getVerticalSelectionInputAction(key);
|
|
4336
|
+
if (action !== void 0) applyAction(action);
|
|
4337
|
+
});
|
|
4338
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_ink20.Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, children: [
|
|
4339
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_ink20.Text, { color: "cyan", bold: true, children: "Execution workspace" }),
|
|
4340
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_ink20.Box, { flexDirection: "column", marginTop: 1, children: visibleEntries.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_ink20.Text, { dimColor: true, children: "No workspace entries" }) : visibleEntries.map((entry, index) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4341
|
+
ExecutionWorkspaceSwitcherRow,
|
|
4342
|
+
{
|
|
4343
|
+
entry,
|
|
4344
|
+
isFocused: normalized.scrollOffset + index === normalized.selectedIndex,
|
|
4345
|
+
selectedEntryId
|
|
4346
|
+
},
|
|
4347
|
+
entry.id
|
|
4348
|
+
)) }),
|
|
4349
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_ink20.Text, { dimColor: true, children: "Ctrl+B Close \u2191\u2193 Navigate Enter Switch Esc Close" })
|
|
4350
|
+
] });
|
|
4351
|
+
}
|
|
4352
|
+
function useWorkspaceSwitcherSelection({
|
|
4353
|
+
entries,
|
|
4354
|
+
selectedEntryId,
|
|
4355
|
+
onSelect,
|
|
4356
|
+
onClose
|
|
4357
|
+
}) {
|
|
4358
|
+
const [state, setState] = (0, import_react19.useState)(() => createSelectionFlowState());
|
|
4359
|
+
const stateRef = (0, import_react19.useRef)(state);
|
|
4360
|
+
(0, import_react19.useEffect)(() => {
|
|
4361
|
+
const selectedIndex = Math.max(
|
|
4362
|
+
0,
|
|
4363
|
+
entries.findIndex((entry) => entry.id === selectedEntryId)
|
|
4364
|
+
);
|
|
4365
|
+
const nextState = createNormalizedSelection({ selectedIndex, itemCount: entries.length });
|
|
4366
|
+
stateRef.current = nextState;
|
|
4367
|
+
setState(nextState);
|
|
4368
|
+
}, [entries.length, selectedEntryId]);
|
|
4369
|
+
const normalized = createNormalizedSelection({
|
|
4370
|
+
selectedIndex: state.selectedIndex,
|
|
4371
|
+
scrollOffset: state.scrollOffset,
|
|
4372
|
+
itemCount: entries.length
|
|
4373
|
+
});
|
|
4374
|
+
if (normalized !== state) stateRef.current = normalized;
|
|
4375
|
+
return {
|
|
4376
|
+
normalized,
|
|
4377
|
+
visibleEntries: entries.slice(
|
|
4378
|
+
normalized.scrollOffset,
|
|
4379
|
+
normalized.scrollOffset + MAX_VISIBLE_WORKSPACE_ENTRIES
|
|
4380
|
+
),
|
|
4381
|
+
applyAction: createApplyAction({ entries, stateRef, setState, onSelect, onClose })
|
|
4382
|
+
};
|
|
4383
|
+
}
|
|
4384
|
+
function createApplyAction({
|
|
4385
|
+
entries,
|
|
4386
|
+
stateRef,
|
|
4387
|
+
setState,
|
|
4388
|
+
onSelect,
|
|
4389
|
+
onClose
|
|
4390
|
+
}) {
|
|
4391
|
+
return (action) => {
|
|
4392
|
+
const result = applySelectionInput(stateRef.current, action, {
|
|
4393
|
+
itemCount: entries.length,
|
|
4394
|
+
maxVisible: MAX_VISIBLE_WORKSPACE_ENTRIES
|
|
4395
|
+
});
|
|
4396
|
+
const nextState = result.effect.type === "select" || result.effect.type === "cancel" ? { ...result.state, resolved: false } : result.state;
|
|
4397
|
+
stateRef.current = nextState;
|
|
4398
|
+
setState(nextState);
|
|
4399
|
+
if (result.effect.type === "cancel") {
|
|
4400
|
+
onClose();
|
|
4401
|
+
} else if (result.effect.type === "select") {
|
|
4402
|
+
const entry = entries[result.effect.index];
|
|
4403
|
+
if (entry) onSelect(entry.id);
|
|
4404
|
+
}
|
|
4405
|
+
};
|
|
4406
|
+
}
|
|
4407
|
+
function createNormalizedSelection(input) {
|
|
4408
|
+
return normalizeSelectionState(
|
|
4409
|
+
{
|
|
4410
|
+
selectedIndex: input.selectedIndex,
|
|
4411
|
+
scrollOffset: input.scrollOffset ?? 0,
|
|
4412
|
+
resolved: false
|
|
4413
|
+
},
|
|
4414
|
+
{ itemCount: input.itemCount, maxVisible: MAX_VISIBLE_WORKSPACE_ENTRIES }
|
|
4415
|
+
);
|
|
4416
|
+
}
|
|
4417
|
+
function ExecutionWorkspaceSwitcherRow({
|
|
4418
|
+
entry,
|
|
4419
|
+
isFocused,
|
|
4420
|
+
selectedEntryId
|
|
4421
|
+
}) {
|
|
4422
|
+
const row = formatExecutionWorkspaceEntryRow(entry, { selectedEntryId });
|
|
4423
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_ink20.Text, { children: [
|
|
4424
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_ink20.Text, { color: isFocused ? "cyan" : void 0, bold: isFocused, children: isFocused ? "> " : " " }),
|
|
4425
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_ink20.Text, { color: row.color, children: row.radio }),
|
|
4426
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_ink20.Text, { color: isFocused ? "cyan" : void 0, bold: isFocused, children: ` ${row.title}` }),
|
|
4427
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_ink20.Text, { dimColor: true, children: ` \xB7 ${row.statusLabel}` }),
|
|
4428
|
+
row.subtitle ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_ink20.Text, { dimColor: true, children: ` \xB7 ${row.subtitle}` }) : null,
|
|
4429
|
+
row.preview ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_ink20.Text, { dimColor: true, children: ` \xB7 ${row.preview}` }) : null
|
|
4430
|
+
] });
|
|
4431
|
+
}
|
|
4432
|
+
|
|
4433
|
+
// src/ui/ExecutionWorkspaceDetailPane.tsx
|
|
4434
|
+
var import_ink21 = require("ink");
|
|
4435
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
4436
|
+
var MAX_VISIBLE_DETAIL_RECORDS = 12;
|
|
4437
|
+
function ExecutionWorkspaceDetailPane({
|
|
4438
|
+
entry,
|
|
4439
|
+
page,
|
|
4440
|
+
loading,
|
|
4441
|
+
error
|
|
4442
|
+
}) {
|
|
4443
|
+
const row = formatExecutionWorkspaceEntryRow(entry, { selectedEntryId: entry.id });
|
|
4444
|
+
const records = page?.records.slice(-MAX_VISIBLE_DETAIL_RECORDS) ?? [];
|
|
4445
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_ink21.Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
4446
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_ink21.Text, { color: "cyan", bold: true, children: `Viewing ${row.title}` }),
|
|
4447
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_ink21.Text, { dimColor: true, children: [
|
|
4448
|
+
row.statusLabel,
|
|
4449
|
+
row.subtitle ? ` \xB7 ${row.subtitle}` : "",
|
|
4450
|
+
row.preview ? ` \xB7 ${row.preview}` : ""
|
|
4451
|
+
] }),
|
|
4452
|
+
loading ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_ink21.Text, { dimColor: true, children: "Loading workspace detail..." }) : null,
|
|
4453
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_ink21.Text, { color: "red", children: error }) : null,
|
|
4454
|
+
!loading && !error && records.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_ink21.Text, { dimColor: true, children: "No detail yet" }) : null,
|
|
4455
|
+
!loading && !error && records.map((record) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_ink21.Text, { color: getDetailRecordColor(record.kind), children: formatExecutionDetailRecord(record) }, record.id)),
|
|
4456
|
+
page?.nextCursor ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_ink21.Text, { dimColor: true, children: "... more detail available" }) : null
|
|
4457
|
+
] });
|
|
4458
|
+
}
|
|
4459
|
+
function getDetailRecordColor(kind) {
|
|
4460
|
+
if (kind === "error") return "red";
|
|
4461
|
+
if (kind === "result") return "green";
|
|
4462
|
+
if (kind === "process_output") return "white";
|
|
4463
|
+
if (kind === "group_summary") return "cyan";
|
|
4464
|
+
return void 0;
|
|
4465
|
+
}
|
|
4466
|
+
|
|
4467
|
+
// src/ui/UpdateNotice.tsx
|
|
4468
|
+
var import_ink22 = require("ink");
|
|
4469
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
4220
4470
|
function UpdateNotice({ message }) {
|
|
4221
|
-
return /* @__PURE__ */ (0,
|
|
4471
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_ink22.Box, { paddingX: 1, marginBottom: 1, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_ink22.Text, { color: "yellow", children: message }) });
|
|
4222
4472
|
}
|
|
4223
4473
|
|
|
4224
4474
|
// src/utils/update-check.ts
|
|
@@ -4313,10 +4563,10 @@ function comparePrereleaseIdentifier(left, right) {
|
|
|
4313
4563
|
var CLI_UPDATE_PACKAGE_NAME = "@robota-sdk/agent-cli";
|
|
4314
4564
|
var CLI_UPDATE_REGISTRY_URL = "https://registry.npmjs.org";
|
|
4315
4565
|
var HOURS_PER_DAY = 24;
|
|
4316
|
-
var
|
|
4317
|
-
var
|
|
4318
|
-
var
|
|
4319
|
-
var CLI_UPDATE_CACHE_TTL_MS = HOURS_PER_DAY *
|
|
4566
|
+
var MINUTES_PER_HOUR = 60;
|
|
4567
|
+
var SECONDS_PER_MINUTE = 60;
|
|
4568
|
+
var MS_PER_SECOND = 1e3;
|
|
4569
|
+
var CLI_UPDATE_CACHE_TTL_MS = HOURS_PER_DAY * MINUTES_PER_HOUR * SECONDS_PER_MINUTE * MS_PER_SECOND;
|
|
4320
4570
|
var CLI_UPDATE_TIMEOUT_MS = 1500;
|
|
4321
4571
|
var DEFAULT_INSTALL_COMMAND = "npm install -g '@robota-sdk/agent-cli@latest'";
|
|
4322
4572
|
function getUserUpdateCheckCachePath(home = process.env.HOME ?? process.env.USERPROFILE ?? "/") {
|
|
@@ -4485,15 +4735,22 @@ function isJsonObject(value) {
|
|
|
4485
4735
|
}
|
|
4486
4736
|
|
|
4487
4737
|
// src/ui/App.tsx
|
|
4488
|
-
var
|
|
4738
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
4489
4739
|
function App(props) {
|
|
4490
|
-
const [activeSessionId, setActiveSessionId] = (0,
|
|
4491
|
-
|
|
4740
|
+
const [activeSessionId, setActiveSessionId] = (0, import_react20.useState)(props.resumeSessionId);
|
|
4741
|
+
const [showInitialSessionPicker, setShowInitialSessionPicker] = (0, import_react20.useState)(
|
|
4742
|
+
props.showSessionPickerOnStart ?? false
|
|
4743
|
+
);
|
|
4744
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
4492
4745
|
AppInner,
|
|
4493
4746
|
{
|
|
4494
4747
|
...props,
|
|
4748
|
+
showSessionPickerOnStart: showInitialSessionPicker,
|
|
4495
4749
|
resumeSessionId: activeSessionId,
|
|
4496
|
-
onSessionSwitch: (sessionId) =>
|
|
4750
|
+
onSessionSwitch: (sessionId) => {
|
|
4751
|
+
setShowInitialSessionPicker(false);
|
|
4752
|
+
setActiveSessionId(sessionId);
|
|
4753
|
+
}
|
|
4497
4754
|
},
|
|
4498
4755
|
activeSessionId ?? "__new__"
|
|
4499
4756
|
);
|
|
@@ -4503,6 +4760,7 @@ function AppInner(props) {
|
|
|
4503
4760
|
const {
|
|
4504
4761
|
interactiveSession,
|
|
4505
4762
|
registry,
|
|
4763
|
+
commandEffectQueue,
|
|
4506
4764
|
history,
|
|
4507
4765
|
addEntry,
|
|
4508
4766
|
streamingText,
|
|
@@ -4511,7 +4769,10 @@ function AppInner(props) {
|
|
|
4511
4769
|
isAborting,
|
|
4512
4770
|
isShuttingDown,
|
|
4513
4771
|
pendingPrompt,
|
|
4514
|
-
|
|
4772
|
+
executionWorkspaceSnapshot,
|
|
4773
|
+
selectedExecutionEntryId,
|
|
4774
|
+
selectExecutionWorkspaceEntry,
|
|
4775
|
+
readExecutionWorkspaceDetail,
|
|
4515
4776
|
permissionRequest,
|
|
4516
4777
|
contextState,
|
|
4517
4778
|
handleSubmit: baseHandleSubmit,
|
|
@@ -4530,17 +4791,31 @@ function AppInner(props) {
|
|
|
4530
4791
|
backgroundTaskRunners: props.backgroundTaskRunners,
|
|
4531
4792
|
subagentRunnerFactory: props.subagentRunnerFactory,
|
|
4532
4793
|
commandModules: props.commandModules,
|
|
4533
|
-
commandHostAdapters: props.commandHostAdapters
|
|
4794
|
+
commandHostAdapters: props.commandHostAdapters,
|
|
4795
|
+
webPort: props.webPort,
|
|
4796
|
+
noOpen: props.noOpen
|
|
4534
4797
|
});
|
|
4535
4798
|
const fallbackPluginCallbacks = usePluginCallbacks(cwd);
|
|
4536
4799
|
const pluginCallbacks = props.commandHostAdapters?.plugin ?? fallbackPluginCallbacks;
|
|
4537
|
-
const { exit } = (0,
|
|
4538
|
-
const [sessionName, setSessionName] = (0,
|
|
4539
|
-
const [updateNotice, setUpdateNotice] = (0,
|
|
4800
|
+
const { exit } = (0, import_ink23.useApp)();
|
|
4801
|
+
const [sessionName, setSessionName] = (0, import_react20.useState)(props.sessionName);
|
|
4802
|
+
const [updateNotice, setUpdateNotice] = (0, import_react20.useState)();
|
|
4803
|
+
const [showExecutionWorkspaceSwitcher, setShowExecutionWorkspaceSwitcher] = (0, import_react20.useState)(false);
|
|
4804
|
+
const [executionDetailPage, setExecutionDetailPage] = (0, import_react20.useState)(null);
|
|
4805
|
+
const [executionDetailError, setExecutionDetailError] = (0, import_react20.useState)();
|
|
4806
|
+
const [isExecutionDetailLoading, setIsExecutionDetailLoading] = (0, import_react20.useState)(false);
|
|
4540
4807
|
const [statusLineSettings, setStatusLineSettings] = useStatusLineSettings();
|
|
4541
|
-
const
|
|
4542
|
-
(
|
|
4543
|
-
|
|
4808
|
+
const backgroundWorkspaceEntries = (0, import_react20.useMemo)(
|
|
4809
|
+
() => getDefaultBackgroundWorkspaceEntries(executionWorkspaceSnapshot),
|
|
4810
|
+
[executionWorkspaceSnapshot]
|
|
4811
|
+
);
|
|
4812
|
+
const activeBackgroundTaskCount = countActiveBackgroundWorkspaceEntries(
|
|
4813
|
+
executionWorkspaceSnapshot
|
|
4814
|
+
);
|
|
4815
|
+
const selectedExecutionEntry = (0, import_react20.useMemo)(
|
|
4816
|
+
() => executionWorkspaceSnapshot?.entries.find((entry) => entry.id === selectedExecutionEntryId),
|
|
4817
|
+
[executionWorkspaceSnapshot, selectedExecutionEntryId]
|
|
4818
|
+
);
|
|
4544
4819
|
const {
|
|
4545
4820
|
handleSubmit,
|
|
4546
4821
|
pendingModelId,
|
|
@@ -4556,16 +4831,18 @@ function AppInner(props) {
|
|
|
4556
4831
|
cwd,
|
|
4557
4832
|
providerOverride: props.providerOverride,
|
|
4558
4833
|
interactiveSession,
|
|
4834
|
+
commandEffectQueue,
|
|
4559
4835
|
addEntry,
|
|
4560
4836
|
baseHandleSubmit,
|
|
4561
4837
|
setSessionName,
|
|
4562
|
-
setStatusLineSettings
|
|
4838
|
+
setStatusLineSettings,
|
|
4839
|
+
showSessionPickerOnStart: props.showSessionPickerOnStart
|
|
4563
4840
|
});
|
|
4564
|
-
(0,
|
|
4841
|
+
(0, import_react20.useEffect)(() => {
|
|
4565
4842
|
const name = interactiveSession?.getName?.();
|
|
4566
4843
|
if (name && !sessionName) setSessionName(name);
|
|
4567
4844
|
}, [interactiveSession, sessionName]);
|
|
4568
|
-
(0,
|
|
4845
|
+
(0, import_react20.useEffect)(() => {
|
|
4569
4846
|
let isMounted = true;
|
|
4570
4847
|
props.startupUpdateNoticePromise?.then((notice) => {
|
|
4571
4848
|
if (isMounted && notice !== void 0) {
|
|
@@ -4577,20 +4854,27 @@ function AppInner(props) {
|
|
|
4577
4854
|
isMounted = false;
|
|
4578
4855
|
};
|
|
4579
4856
|
}, [props.startupUpdateNoticePromise]);
|
|
4580
|
-
(0,
|
|
4857
|
+
(0, import_react20.useEffect)(() => {
|
|
4581
4858
|
const title = sessionName ? `Robota \u2014 ${sessionName}` : "Robota";
|
|
4582
4859
|
process.stdout.write(`\x1B]0;${title}\x07`);
|
|
4583
4860
|
}, [sessionName]);
|
|
4584
|
-
(0,
|
|
4861
|
+
(0, import_ink23.useInput)((_input, key) => {
|
|
4585
4862
|
if (!key.escape || !isThinking) return;
|
|
4586
|
-
if (permissionRequest || showPluginTUI || showSessionPicker)
|
|
4863
|
+
if (permissionRequest || showPluginTUI || showSessionPicker || showExecutionWorkspaceSwitcher) {
|
|
4864
|
+
return;
|
|
4865
|
+
}
|
|
4587
4866
|
handleAbort();
|
|
4588
4867
|
});
|
|
4589
|
-
(0,
|
|
4868
|
+
(0, import_ink23.useInput)((input, key) => {
|
|
4869
|
+
if (!key.ctrl || input !== "b") return;
|
|
4870
|
+
if (permissionRequest || showPluginTUI || showSessionPicker || isShuttingDown) return;
|
|
4871
|
+
setShowExecutionWorkspaceSwitcher((shown) => !shown);
|
|
4872
|
+
});
|
|
4873
|
+
(0, import_ink23.useInput)((input, key) => {
|
|
4590
4874
|
if (!key.ctrl || input !== "c" || isShuttingDown) return;
|
|
4591
4875
|
void handleShutdown("prompt_input_exit").finally(() => exit());
|
|
4592
4876
|
});
|
|
4593
|
-
(0,
|
|
4877
|
+
(0, import_react20.useEffect)(() => {
|
|
4594
4878
|
const onSigterm = () => {
|
|
4595
4879
|
if (isShuttingDown) return;
|
|
4596
4880
|
void handleShutdown("other").finally(() => exit());
|
|
@@ -4602,6 +4886,29 @@ function AppInner(props) {
|
|
|
4602
4886
|
process.off("SIGTERM", onSigterm);
|
|
4603
4887
|
};
|
|
4604
4888
|
}, [handleShutdown, exit, isShuttingDown]);
|
|
4889
|
+
(0, import_react20.useEffect)(() => {
|
|
4890
|
+
if (!selectedExecutionEntry || selectedExecutionEntry.kind === "main_thread") {
|
|
4891
|
+
setExecutionDetailPage(null);
|
|
4892
|
+
setExecutionDetailError(void 0);
|
|
4893
|
+
setIsExecutionDetailLoading(false);
|
|
4894
|
+
return;
|
|
4895
|
+
}
|
|
4896
|
+
let isCurrent = true;
|
|
4897
|
+
setIsExecutionDetailLoading(true);
|
|
4898
|
+
setExecutionDetailError(void 0);
|
|
4899
|
+
readExecutionWorkspaceDetail(selectedExecutionEntry.id).then((page) => {
|
|
4900
|
+
if (!isCurrent) return;
|
|
4901
|
+
setExecutionDetailPage(page);
|
|
4902
|
+
setIsExecutionDetailLoading(false);
|
|
4903
|
+
}).catch((error) => {
|
|
4904
|
+
if (!isCurrent) return;
|
|
4905
|
+
setExecutionDetailError(error.message);
|
|
4906
|
+
setIsExecutionDetailLoading(false);
|
|
4907
|
+
});
|
|
4908
|
+
return () => {
|
|
4909
|
+
isCurrent = false;
|
|
4910
|
+
};
|
|
4911
|
+
}, [executionWorkspaceSnapshot, readExecutionWorkspaceDetail, selectedExecutionEntry]);
|
|
4605
4912
|
let permissionMode = props.permissionMode ?? "default";
|
|
4606
4913
|
let sessionId = "";
|
|
4607
4914
|
try {
|
|
@@ -4610,25 +4917,33 @@ function AppInner(props) {
|
|
|
4610
4917
|
sessionId = session.getSessionId();
|
|
4611
4918
|
} catch {
|
|
4612
4919
|
}
|
|
4613
|
-
return /* @__PURE__ */ (0,
|
|
4614
|
-
/* @__PURE__ */ (0,
|
|
4615
|
-
/* @__PURE__ */ (0,
|
|
4920
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_ink23.Box, { flexDirection: "column", children: [
|
|
4921
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_ink23.Box, { flexDirection: "column", paddingX: 1, marginBottom: 1, children: [
|
|
4922
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_ink23.Text, { color: "cyan", bold: true, children: `
|
|
4616
4923
|
____ ___ ____ ___ _____ _
|
|
4617
4924
|
| _ \\ / _ \\| __ ) / _ \\_ _|/ \\
|
|
4618
4925
|
| |_) | | | | _ \\| | | || | / _ \\
|
|
4619
4926
|
| _ <| |_| | |_) | |_| || |/ ___ \\
|
|
4620
4927
|
|_| \\_\\\\___/|____/ \\___/ |_/_/ \\_\\
|
|
4621
4928
|
` }),
|
|
4622
|
-
/* @__PURE__ */ (0,
|
|
4929
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_ink23.Text, { dimColor: true, children: [
|
|
4623
4930
|
" v",
|
|
4624
4931
|
props.version ?? "0.0.0"
|
|
4625
4932
|
] })
|
|
4626
4933
|
] }),
|
|
4627
|
-
updateNotice && /* @__PURE__ */ (0,
|
|
4628
|
-
/* @__PURE__ */ (0,
|
|
4629
|
-
/* @__PURE__ */ (0,
|
|
4630
|
-
|
|
4631
|
-
|
|
4934
|
+
updateNotice && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(UpdateNotice, { message: formatCliUpdateNotice(updateNotice) }),
|
|
4935
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_ink23.Box, { flexDirection: "column", paddingX: 1, flexGrow: 1, children: [
|
|
4936
|
+
selectedExecutionEntry && selectedExecutionEntry.kind !== "main_thread" ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
4937
|
+
ExecutionWorkspaceDetailPane,
|
|
4938
|
+
{
|
|
4939
|
+
entry: selectedExecutionEntry,
|
|
4940
|
+
page: executionDetailPage,
|
|
4941
|
+
loading: isExecutionDetailLoading,
|
|
4942
|
+
error: executionDetailError
|
|
4943
|
+
}
|
|
4944
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(MessageList, { history }),
|
|
4945
|
+
isShuttingDown && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_ink23.Box, { marginBottom: 1, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_ink23.Text, { color: "yellow", children: "Shutting down..." }) }),
|
|
4946
|
+
(isThinking || activeTools.length > 0) && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_ink23.Box, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
4632
4947
|
StreamingIndicator,
|
|
4633
4948
|
{
|
|
4634
4949
|
text: streamingText,
|
|
@@ -4636,17 +4951,26 @@ function AppInner(props) {
|
|
|
4636
4951
|
isThinking
|
|
4637
4952
|
}
|
|
4638
4953
|
) }),
|
|
4639
|
-
/* @__PURE__ */ (0,
|
|
4954
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(BackgroundTaskPanel, { entries: backgroundWorkspaceEntries })
|
|
4640
4955
|
] }),
|
|
4641
|
-
|
|
4642
|
-
|
|
4956
|
+
showExecutionWorkspaceSwitcher && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
4957
|
+
ExecutionWorkspaceSwitcher,
|
|
4958
|
+
{
|
|
4959
|
+
snapshot: executionWorkspaceSnapshot,
|
|
4960
|
+
selectedEntryId: selectedExecutionEntryId,
|
|
4961
|
+
onSelect: selectExecutionWorkspaceEntry,
|
|
4962
|
+
onClose: () => setShowExecutionWorkspaceSwitcher(false)
|
|
4963
|
+
}
|
|
4964
|
+
),
|
|
4965
|
+
permissionRequest && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(PermissionPrompt, { request: permissionRequest }),
|
|
4966
|
+
pendingModelId && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
4643
4967
|
ConfirmPrompt,
|
|
4644
4968
|
{
|
|
4645
4969
|
message: formatModelChangeConfirmationMessage(pendingModelId),
|
|
4646
4970
|
onSelect: handleModelConfirm
|
|
4647
4971
|
}
|
|
4648
4972
|
),
|
|
4649
|
-
pendingInteractionPrompt && /* @__PURE__ */ (0,
|
|
4973
|
+
pendingInteractionPrompt && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
4650
4974
|
InteractivePrompt,
|
|
4651
4975
|
{
|
|
4652
4976
|
prompt: pendingInteractionPrompt,
|
|
@@ -4654,7 +4978,7 @@ function AppInner(props) {
|
|
|
4654
4978
|
onCancel: handleInteractionCancel
|
|
4655
4979
|
}
|
|
4656
4980
|
),
|
|
4657
|
-
showPluginTUI && /* @__PURE__ */ (0,
|
|
4981
|
+
showPluginTUI && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
4658
4982
|
PluginTUI,
|
|
4659
4983
|
{
|
|
4660
4984
|
callbacks: pluginCallbacks,
|
|
@@ -4662,11 +4986,10 @@ function AppInner(props) {
|
|
|
4662
4986
|
addMessage: (msg) => addEntry((0, import_agent_core11.messageToHistoryEntry)((0, import_agent_core11.createSystemMessage)(msg.content)))
|
|
4663
4987
|
}
|
|
4664
4988
|
),
|
|
4665
|
-
showSessionPicker && /* @__PURE__ */ (0,
|
|
4989
|
+
showSessionPicker && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
4666
4990
|
SessionPicker,
|
|
4667
4991
|
{
|
|
4668
|
-
|
|
4669
|
-
cwd: props.cwd,
|
|
4992
|
+
sessions: (0, import_agent_sdk9.listResumableSessionSummaries)(props.sessionStore, props.cwd),
|
|
4670
4993
|
onSelect: (id) => {
|
|
4671
4994
|
setShowSessionPicker(false);
|
|
4672
4995
|
props.onSessionSwitch(id);
|
|
@@ -4677,14 +5000,15 @@ function AppInner(props) {
|
|
|
4677
5000
|
}
|
|
4678
5001
|
}
|
|
4679
5002
|
),
|
|
4680
|
-
/* @__PURE__ */ (0,
|
|
5003
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
4681
5004
|
SessionStatusBar,
|
|
4682
5005
|
{
|
|
4683
5006
|
cwd,
|
|
4684
5007
|
permissionMode,
|
|
4685
5008
|
modelId: props.modelId,
|
|
5009
|
+
providerProfileName: props.providerProfileName,
|
|
5010
|
+
providerType: props.providerType,
|
|
4686
5011
|
sessionId,
|
|
4687
|
-
messageCount: history.length,
|
|
4688
5012
|
isThinking,
|
|
4689
5013
|
activeToolCount: activeTools.length,
|
|
4690
5014
|
activeBackgroundTaskCount,
|
|
@@ -4694,12 +5018,12 @@ function AppInner(props) {
|
|
|
4694
5018
|
settings: statusLineSettings
|
|
4695
5019
|
}
|
|
4696
5020
|
),
|
|
4697
|
-
/* @__PURE__ */ (0,
|
|
5021
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
4698
5022
|
InputArea,
|
|
4699
5023
|
{
|
|
4700
5024
|
onSubmit: handleSubmit,
|
|
4701
5025
|
onCancelQueue: handleCancelQueue,
|
|
4702
|
-
isDisabled: !!permissionRequest || showPluginTUI || showSessionPicker || isShuttingDown || pendingInteractionPrompt !== null || isThinking && !!pendingPrompt,
|
|
5026
|
+
isDisabled: !!permissionRequest || showPluginTUI || showSessionPicker || showExecutionWorkspaceSwitcher || isShuttingDown || pendingInteractionPrompt !== null || isThinking && !!pendingPrompt,
|
|
4703
5027
|
isAborting,
|
|
4704
5028
|
pendingPrompt,
|
|
4705
5029
|
registry,
|
|
@@ -4707,12 +5031,12 @@ function AppInner(props) {
|
|
|
4707
5031
|
history
|
|
4708
5032
|
}
|
|
4709
5033
|
),
|
|
4710
|
-
/* @__PURE__ */ (0,
|
|
5034
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_ink23.Text, { children: " " })
|
|
4711
5035
|
] });
|
|
4712
5036
|
}
|
|
4713
5037
|
|
|
4714
5038
|
// src/ui/render.tsx
|
|
4715
|
-
var
|
|
5039
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
4716
5040
|
function renderApp(options) {
|
|
4717
5041
|
process.on("unhandledRejection", (reason) => {
|
|
4718
5042
|
process.stderr.write(`
|
|
@@ -4723,7 +5047,7 @@ function renderApp(options) {
|
|
|
4723
5047
|
`);
|
|
4724
5048
|
}
|
|
4725
5049
|
});
|
|
4726
|
-
const instance = (0,
|
|
5050
|
+
const instance = (0, import_ink24.render)(/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(App, { ...options }), {
|
|
4727
5051
|
exitOnCtrlC: false
|
|
4728
5052
|
});
|
|
4729
5053
|
instance.waitUntilExit().then(() => {
|
|
@@ -4740,43 +5064,14 @@ function renderApp(options) {
|
|
|
4740
5064
|
|
|
4741
5065
|
// src/background/managed-shell-process-runner.ts
|
|
4742
5066
|
var import_node_child_process = require("child_process");
|
|
4743
|
-
var
|
|
5067
|
+
var import_agent_sdk10 = require("@robota-sdk/agent-sdk");
|
|
4744
5068
|
var DEFAULT_OUTPUT_LIMIT_BYTES = 3e4;
|
|
4745
5069
|
var DEFAULT_KILL_GRACE_MS = 2e3;
|
|
4746
|
-
var LOG_PAGE_SIZE = 200;
|
|
4747
|
-
function createCapture(limitBytes) {
|
|
4748
|
-
const chunks = [];
|
|
4749
|
-
let capturedBytes = 0;
|
|
4750
|
-
let truncated = false;
|
|
4751
|
-
return {
|
|
4752
|
-
appendOutput(text) {
|
|
4753
|
-
if (truncated) return;
|
|
4754
|
-
const remaining = limitBytes - capturedBytes;
|
|
4755
|
-
const buffer = Buffer.from(text, "utf8");
|
|
4756
|
-
if (buffer.byteLength <= remaining) {
|
|
4757
|
-
chunks.push(text);
|
|
4758
|
-
capturedBytes += buffer.byteLength;
|
|
4759
|
-
return;
|
|
4760
|
-
}
|
|
4761
|
-
chunks.push(buffer.subarray(0, Math.max(remaining, 0)).toString("utf8"));
|
|
4762
|
-
chunks.push("\n[output truncated]\n");
|
|
4763
|
-
truncated = true;
|
|
4764
|
-
},
|
|
4765
|
-
getOutput() {
|
|
4766
|
-
return chunks.join("");
|
|
4767
|
-
}
|
|
4768
|
-
};
|
|
4769
|
-
}
|
|
4770
|
-
function appendLog(lines, source, text) {
|
|
4771
|
-
for (const line of text.split(/\r?\n/)) {
|
|
4772
|
-
if (line.length > 0) lines.push(`[${source}] ${line}`);
|
|
4773
|
-
}
|
|
4774
|
-
}
|
|
4775
5070
|
function resolveShell(request) {
|
|
4776
5071
|
return { command: request.shell ?? "sh", args: ["-c", request.command] };
|
|
4777
5072
|
}
|
|
4778
5073
|
function sendInput(child, input) {
|
|
4779
|
-
return new Promise((
|
|
5074
|
+
return new Promise((resolve3, reject) => {
|
|
4780
5075
|
const onError = (error) => {
|
|
4781
5076
|
child.stdin.off("error", onError);
|
|
4782
5077
|
reject(error);
|
|
@@ -4784,7 +5079,7 @@ function sendInput(child, input) {
|
|
|
4784
5079
|
child.stdin.once("error", onError);
|
|
4785
5080
|
child.stdin.end(input, () => {
|
|
4786
5081
|
child.stdin.off("error", onError);
|
|
4787
|
-
|
|
5082
|
+
resolve3();
|
|
4788
5083
|
});
|
|
4789
5084
|
});
|
|
4790
5085
|
}
|
|
@@ -4794,7 +5089,7 @@ function createManagedShellProcessRunner(options = {}) {
|
|
|
4794
5089
|
kind: "process",
|
|
4795
5090
|
start(task) {
|
|
4796
5091
|
if (task.request.kind !== "process") {
|
|
4797
|
-
throw new
|
|
5092
|
+
throw new import_agent_sdk10.BackgroundTaskError("runner", `Invalid process task kind: ${task.request.kind}`);
|
|
4798
5093
|
}
|
|
4799
5094
|
return startProcessTask(task.taskId, task.request, killGraceMs);
|
|
4800
5095
|
}
|
|
@@ -4811,7 +5106,9 @@ function startProcessTask(taskId, request, killGraceMs) {
|
|
|
4811
5106
|
stdio: ["pipe", "pipe", "pipe"]
|
|
4812
5107
|
}),
|
|
4813
5108
|
logs: [],
|
|
4814
|
-
capture:
|
|
5109
|
+
capture: (0, import_agent_sdk10.createLimitedOutputCapture)({
|
|
5110
|
+
limitBytes: request.outputLimitBytes ?? DEFAULT_OUTPUT_LIMIT_BYTES
|
|
5111
|
+
}),
|
|
4815
5112
|
killGraceMs
|
|
4816
5113
|
};
|
|
4817
5114
|
const result = createProcessResult(runtime);
|
|
@@ -4819,11 +5116,15 @@ function startProcessTask(taskId, request, killGraceMs) {
|
|
|
4819
5116
|
}
|
|
4820
5117
|
function createProcessResult(runtime) {
|
|
4821
5118
|
let settled = false;
|
|
4822
|
-
return new Promise((
|
|
5119
|
+
return new Promise((resolve3, reject) => {
|
|
4823
5120
|
const timeoutTimer = runtime.request.timeoutMs ? setTimeout(() => {
|
|
4824
|
-
|
|
5121
|
+
(0, import_agent_sdk10.appendPrefixedLogLines)(
|
|
5122
|
+
runtime.logs,
|
|
5123
|
+
"system",
|
|
5124
|
+
`timed out after ${runtime.request.timeoutMs}ms`
|
|
5125
|
+
);
|
|
4825
5126
|
runtime.child.kill("SIGTERM");
|
|
4826
|
-
rejectOnceLocal(new
|
|
5127
|
+
rejectOnceLocal(new import_agent_sdk10.BackgroundTaskError("timeout", "Background process timed out"));
|
|
4827
5128
|
}, runtime.request.timeoutMs) : void 0;
|
|
4828
5129
|
function clearTimers() {
|
|
4829
5130
|
if (timeoutTimer) clearTimeout(timeoutTimer);
|
|
@@ -4833,7 +5134,7 @@ function createProcessResult(runtime) {
|
|
|
4833
5134
|
if (settled) return;
|
|
4834
5135
|
settled = true;
|
|
4835
5136
|
clearTimers();
|
|
4836
|
-
|
|
5137
|
+
resolve3({
|
|
4837
5138
|
taskId: runtime.taskId,
|
|
4838
5139
|
kind: "process",
|
|
4839
5140
|
output: runtime.capture.getOutput(),
|
|
@@ -4849,8 +5150,8 @@ function createProcessResult(runtime) {
|
|
|
4849
5150
|
}
|
|
4850
5151
|
attachOutputListeners(runtime);
|
|
4851
5152
|
runtime.child.on("error", (error) => {
|
|
4852
|
-
|
|
4853
|
-
rejectOnceLocal(new
|
|
5153
|
+
(0, import_agent_sdk10.appendPrefixedLogLines)(runtime.logs, "system", error.message);
|
|
5154
|
+
rejectOnceLocal(new import_agent_sdk10.BackgroundTaskError("process", error.message));
|
|
4854
5155
|
});
|
|
4855
5156
|
runtime.child.on("close", (code, signal) => {
|
|
4856
5157
|
resolveOnce(code ?? void 0, signal ?? void 0);
|
|
@@ -4880,40 +5181,37 @@ function attachOutputListeners(runtime) {
|
|
|
4880
5181
|
runtime.child.stdout.on("data", (chunk) => {
|
|
4881
5182
|
const text = chunk.toString("utf8");
|
|
4882
5183
|
runtime.capture.appendOutput(text);
|
|
4883
|
-
|
|
5184
|
+
(0, import_agent_sdk10.appendPrefixedLogLines)(runtime.logs, "stdout", text);
|
|
4884
5185
|
});
|
|
4885
5186
|
runtime.child.stderr.on("data", (chunk) => {
|
|
4886
5187
|
const text = chunk.toString("utf8");
|
|
4887
5188
|
runtime.capture.appendOutput(text);
|
|
4888
|
-
|
|
5189
|
+
(0, import_agent_sdk10.appendPrefixedLogLines)(runtime.logs, "stderr", text);
|
|
4889
5190
|
});
|
|
4890
5191
|
}
|
|
4891
5192
|
function cancelProcess(runtime, reason) {
|
|
4892
|
-
|
|
5193
|
+
(0, import_agent_sdk10.appendPrefixedLogLines)(
|
|
5194
|
+
runtime.logs,
|
|
5195
|
+
"system",
|
|
5196
|
+
reason ? `cancel requested: ${reason}` : "cancel requested"
|
|
5197
|
+
);
|
|
4893
5198
|
if (!runtime.child.killed) runtime.child.kill("SIGTERM");
|
|
4894
5199
|
runtime.killTimer = setTimeout(() => {
|
|
4895
5200
|
if (!runtime.child.killed) runtime.child.kill("SIGKILL");
|
|
4896
5201
|
}, runtime.killGraceMs);
|
|
4897
5202
|
}
|
|
4898
5203
|
function readProcessLog(runtime, cursor) {
|
|
4899
|
-
|
|
4900
|
-
const nextOffset = Math.min(offset + LOG_PAGE_SIZE, runtime.logs.length);
|
|
4901
|
-
return {
|
|
4902
|
-
taskId: runtime.taskId,
|
|
4903
|
-
cursor,
|
|
4904
|
-
nextCursor: nextOffset < runtime.logs.length ? { offset: nextOffset } : void 0,
|
|
4905
|
-
lines: runtime.logs.slice(offset, nextOffset)
|
|
4906
|
-
};
|
|
5204
|
+
return (0, import_agent_sdk10.createBackgroundTaskLogPage)(runtime.taskId, runtime.logs, cursor);
|
|
4907
5205
|
}
|
|
4908
5206
|
|
|
4909
5207
|
// src/subagents/child-process-subagent-runner.ts
|
|
4910
5208
|
var import_node_child_process3 = require("child_process");
|
|
4911
5209
|
var import_node_fs7 = require("fs");
|
|
4912
5210
|
var import_node_path9 = require("path");
|
|
4913
|
-
var
|
|
5211
|
+
var import_agent_sdk14 = require("@robota-sdk/agent-sdk");
|
|
4914
5212
|
|
|
4915
5213
|
// src/subagents/child-process-subagent-runner-result.ts
|
|
4916
|
-
var
|
|
5214
|
+
var import_agent_sdk12 = require("@robota-sdk/agent-sdk");
|
|
4917
5215
|
|
|
4918
5216
|
// src/subagents/child-process-subagent-ipc.ts
|
|
4919
5217
|
function isRecord2(value) {
|
|
@@ -4945,7 +5243,7 @@ function isSubagentWorkerChildMessage(value) {
|
|
|
4945
5243
|
}
|
|
4946
5244
|
|
|
4947
5245
|
// src/subagents/child-process-subagent-transport.ts
|
|
4948
|
-
var
|
|
5246
|
+
var import_agent_sdk11 = require("@robota-sdk/agent-sdk");
|
|
4949
5247
|
function handleWorkerMessage(message, startWorker, resolveOnce, rejectOnce, emit) {
|
|
4950
5248
|
switch (message.type) {
|
|
4951
5249
|
case "ready":
|
|
@@ -4955,10 +5253,10 @@ function handleWorkerMessage(message, startWorker, resolveOnce, rejectOnce, emit
|
|
|
4955
5253
|
resolveOnce(message.output);
|
|
4956
5254
|
break;
|
|
4957
5255
|
case "error":
|
|
4958
|
-
rejectOnce(new
|
|
5256
|
+
rejectOnce(new import_agent_sdk11.BackgroundTaskError("runner", message.message));
|
|
4959
5257
|
break;
|
|
4960
5258
|
case "cancelled":
|
|
4961
|
-
rejectOnce(new
|
|
5259
|
+
rejectOnce(new import_agent_sdk11.BackgroundTaskError("runner", message.reason ?? "Subagent worker cancelled"));
|
|
4962
5260
|
break;
|
|
4963
5261
|
case "text_delta":
|
|
4964
5262
|
emit?.({ type: "background_task_text_delta", delta: message.delta });
|
|
@@ -4978,7 +5276,7 @@ function handleWorkerMessage(message, startWorker, resolveOnce, rejectOnce, emit
|
|
|
4978
5276
|
});
|
|
4979
5277
|
break;
|
|
4980
5278
|
default:
|
|
4981
|
-
rejectOnce(new
|
|
5279
|
+
rejectOnce(new import_agent_sdk11.BackgroundTaskError("runner", "Unhandled subagent worker message"));
|
|
4982
5280
|
}
|
|
4983
5281
|
}
|
|
4984
5282
|
function extractFirstArg(toolArgs) {
|
|
@@ -4988,9 +5286,9 @@ function extractFirstArg(toolArgs) {
|
|
|
4988
5286
|
return typeof firstValue === "object" ? JSON.stringify(firstValue) : String(firstValue);
|
|
4989
5287
|
}
|
|
4990
5288
|
function sendWorkerMessage(child, message) {
|
|
4991
|
-
return new Promise((
|
|
5289
|
+
return new Promise((resolve3, reject) => {
|
|
4992
5290
|
if (!child.connected) {
|
|
4993
|
-
reject(new
|
|
5291
|
+
reject(new import_agent_sdk11.BackgroundTaskError("crash", "Subagent worker IPC channel is closed"));
|
|
4994
5292
|
return;
|
|
4995
5293
|
}
|
|
4996
5294
|
child.send(message, (error) => {
|
|
@@ -4998,7 +5296,7 @@ function sendWorkerMessage(child, message) {
|
|
|
4998
5296
|
reject(error);
|
|
4999
5297
|
return;
|
|
5000
5298
|
}
|
|
5001
|
-
|
|
5299
|
+
resolve3();
|
|
5002
5300
|
});
|
|
5003
5301
|
});
|
|
5004
5302
|
}
|
|
@@ -5015,14 +5313,14 @@ async function cancelChildProcess(runtime, reason) {
|
|
|
5015
5313
|
|
|
5016
5314
|
// src/subagents/child-process-subagent-runner-result.ts
|
|
5017
5315
|
function createChildProcessSubagentResult(options) {
|
|
5018
|
-
return new Promise((
|
|
5019
|
-
new ChildProcessSubagentResultController(options,
|
|
5316
|
+
return new Promise((resolve3, reject) => {
|
|
5317
|
+
new ChildProcessSubagentResultController(options, resolve3, reject).start();
|
|
5020
5318
|
});
|
|
5021
5319
|
}
|
|
5022
5320
|
var ChildProcessSubagentResultController = class {
|
|
5023
|
-
constructor(options,
|
|
5321
|
+
constructor(options, resolve3, reject) {
|
|
5024
5322
|
this.options = options;
|
|
5025
|
-
this.resolve =
|
|
5323
|
+
this.resolve = resolve3;
|
|
5026
5324
|
this.reject = reject;
|
|
5027
5325
|
this.timeoutTimer = createTimeoutTimer(this.options.runtime, (error) => this.rejectOnce(error));
|
|
5028
5326
|
}
|
|
@@ -5051,7 +5349,7 @@ var ChildProcessSubagentResultController = class {
|
|
|
5051
5349
|
onMessage = (message) => {
|
|
5052
5350
|
if (!isSubagentWorkerChildMessage(message)) {
|
|
5053
5351
|
this.rejectOnce(
|
|
5054
|
-
new
|
|
5352
|
+
new import_agent_sdk12.BackgroundTaskError("runner", "Received malformed subagent worker message")
|
|
5055
5353
|
);
|
|
5056
5354
|
return;
|
|
5057
5355
|
}
|
|
@@ -5059,11 +5357,11 @@ var ChildProcessSubagentResultController = class {
|
|
|
5059
5357
|
handleWorkerMessage(message, this.startWorker, this.resolveOnce, this.rejectOnce, job.emit);
|
|
5060
5358
|
};
|
|
5061
5359
|
onError = (error) => {
|
|
5062
|
-
this.rejectOnce(new
|
|
5360
|
+
this.rejectOnce(new import_agent_sdk12.BackgroundTaskError("crash", error.message));
|
|
5063
5361
|
};
|
|
5064
5362
|
onExit = (code, signal) => {
|
|
5065
5363
|
if (this.settled) return;
|
|
5066
|
-
this.rejectOnce(new
|
|
5364
|
+
this.rejectOnce(new import_agent_sdk12.BackgroundTaskError("crash", formatEarlyExitMessage(code, signal)));
|
|
5067
5365
|
};
|
|
5068
5366
|
resolveOnce = (output) => {
|
|
5069
5367
|
if (this.settled) return;
|
|
@@ -5103,7 +5401,7 @@ function createCancellationResult(jobId) {
|
|
|
5103
5401
|
reject(reason) {
|
|
5104
5402
|
if (settled) return;
|
|
5105
5403
|
settled = true;
|
|
5106
|
-
rejectFn(new
|
|
5404
|
+
rejectFn(new import_agent_sdk12.BackgroundTaskError("runner", reason ?? `Subagent job cancelled: ${jobId}`));
|
|
5107
5405
|
}
|
|
5108
5406
|
};
|
|
5109
5407
|
}
|
|
@@ -5111,7 +5409,7 @@ function createTimeoutTimer(runtime, rejectOnce) {
|
|
|
5111
5409
|
if (!runtime.job.request.timeoutMs) return void 0;
|
|
5112
5410
|
return setTimeout(() => {
|
|
5113
5411
|
void cancelChildProcess(runtime, "Subagent worker timed out");
|
|
5114
|
-
rejectOnce(new
|
|
5412
|
+
rejectOnce(new import_agent_sdk12.BackgroundTaskError("timeout", "Subagent worker timed out"));
|
|
5115
5413
|
}, runtime.job.request.timeoutMs);
|
|
5116
5414
|
}
|
|
5117
5415
|
function toSubagentResult(job, output, resolveTranscriptPath) {
|
|
@@ -5129,10 +5427,10 @@ function formatEarlyExitMessage(code, signal) {
|
|
|
5129
5427
|
|
|
5130
5428
|
// src/subagents/git-worktree-isolation-adapter.ts
|
|
5131
5429
|
var import_node_child_process2 = require("child_process");
|
|
5132
|
-
var
|
|
5430
|
+
var import_node_crypto = require("crypto");
|
|
5133
5431
|
var import_node_fs6 = require("fs");
|
|
5134
5432
|
var import_node_path8 = require("path");
|
|
5135
|
-
var
|
|
5433
|
+
var import_agent_sdk13 = require("@robota-sdk/agent-sdk");
|
|
5136
5434
|
var WORKTREE_DIR = ".robota/worktrees";
|
|
5137
5435
|
var BRANCH_PREFIX = "robota";
|
|
5138
5436
|
var GIT_ENCODING = "utf8";
|
|
@@ -5155,7 +5453,7 @@ var GitWorktreeIsolationAdapter = class {
|
|
|
5155
5453
|
}
|
|
5156
5454
|
prepare(request) {
|
|
5157
5455
|
if (this.maxCreateAttempts < 1) {
|
|
5158
|
-
throw new
|
|
5456
|
+
throw new import_agent_sdk13.BackgroundTaskError("runner", "Git worktree creation attempts must be at least 1");
|
|
5159
5457
|
}
|
|
5160
5458
|
const repoRoot = resolveRepoRoot(request.cwd);
|
|
5161
5459
|
const baseRevision = runGit(repoRoot, ["rev-parse", "HEAD"]).trim();
|
|
@@ -5176,7 +5474,7 @@ var GitWorktreeIsolationAdapter = class {
|
|
|
5176
5474
|
if (!isCollisionError(lastError)) throw lastError;
|
|
5177
5475
|
}
|
|
5178
5476
|
}
|
|
5179
|
-
throw new
|
|
5477
|
+
throw new import_agent_sdk13.BackgroundTaskError(
|
|
5180
5478
|
"runner",
|
|
5181
5479
|
`Unable to create Git worktree after ${this.maxCreateAttempts} attempts due to branch or path collisions. Last error: ${lastError?.message ?? "unknown error"}`
|
|
5182
5480
|
);
|
|
@@ -5202,7 +5500,7 @@ function runGit(cwd, args) {
|
|
|
5202
5500
|
});
|
|
5203
5501
|
} catch (error) {
|
|
5204
5502
|
const message = error instanceof Error ? error.message : String(error);
|
|
5205
|
-
throw new
|
|
5503
|
+
throw new import_agent_sdk13.BackgroundTaskError("runner", `git ${args.join(" ")} failed: ${message}`);
|
|
5206
5504
|
}
|
|
5207
5505
|
}
|
|
5208
5506
|
function createGitEnvironment() {
|
|
@@ -5219,14 +5517,14 @@ function resolveRepoRoot(cwd) {
|
|
|
5219
5517
|
return runGit(cwd, ["rev-parse", "--show-toplevel"]).trim();
|
|
5220
5518
|
} catch (error) {
|
|
5221
5519
|
const message = error instanceof Error ? error.message : String(error);
|
|
5222
|
-
throw new
|
|
5520
|
+
throw new import_agent_sdk13.BackgroundTaskError(
|
|
5223
5521
|
"runner",
|
|
5224
5522
|
`Worktree isolation requires a Git repository. Run from a Git worktree or request isolation "none". Details: ${message}`
|
|
5225
5523
|
);
|
|
5226
5524
|
}
|
|
5227
5525
|
}
|
|
5228
5526
|
function createShortId() {
|
|
5229
|
-
return (0,
|
|
5527
|
+
return (0, import_node_crypto.randomUUID)().slice(0, SHORT_ID_LENGTH);
|
|
5230
5528
|
}
|
|
5231
5529
|
function normalizeShortId(value) {
|
|
5232
5530
|
const sanitized = sanitizePathSegment(value).slice(0, SHORT_ID_LENGTH);
|
|
@@ -5245,12 +5543,11 @@ function isCollisionError(error) {
|
|
|
5245
5543
|
|
|
5246
5544
|
// src/subagents/child-process-subagent-runner.ts
|
|
5247
5545
|
var DEFAULT_KILL_GRACE_MS2 = 2e3;
|
|
5248
|
-
var LOG_PAGE_SIZE2 = 200;
|
|
5249
5546
|
function createChildProcessSubagentRunnerFactory(options = {}) {
|
|
5250
5547
|
return (deps) => {
|
|
5251
5548
|
const runner = new ChildProcessSubagentRunner(deps, options);
|
|
5252
5549
|
if (options.worktreeIsolation === false) return runner;
|
|
5253
|
-
return (0,
|
|
5550
|
+
return (0, import_agent_sdk14.createWorktreeSubagentRunner)({
|
|
5254
5551
|
runner,
|
|
5255
5552
|
worktreeAdapter: options.worktreeAdapter ?? createGitWorktreeIsolationAdapter(),
|
|
5256
5553
|
hooks: deps.config.hooks,
|
|
@@ -5332,9 +5629,9 @@ var ChildProcessSubagentRunner = class {
|
|
|
5332
5629
|
}
|
|
5333
5630
|
};
|
|
5334
5631
|
function resolveAgentDefinition(agentType, customRegistry) {
|
|
5335
|
-
const definition = customRegistry?.(agentType) ?? (0,
|
|
5632
|
+
const definition = customRegistry?.(agentType) ?? (0, import_agent_sdk14.getBuiltInAgent)(agentType);
|
|
5336
5633
|
if (!definition) {
|
|
5337
|
-
throw new
|
|
5634
|
+
throw new import_agent_sdk14.BackgroundTaskError("validation", `Unknown agent type: ${agentType}`);
|
|
5338
5635
|
}
|
|
5339
5636
|
return definition;
|
|
5340
5637
|
}
|
|
@@ -5383,7 +5680,6 @@ function resolveDefaultExecArgv(workerPath) {
|
|
|
5383
5680
|
return [...process.execArgv, "--import", "tsx"];
|
|
5384
5681
|
}
|
|
5385
5682
|
function readTranscriptLog(jobId, transcriptPath, cursor) {
|
|
5386
|
-
const offset = cursor?.offset ?? 0;
|
|
5387
5683
|
if (!(0, import_node_fs7.existsSync)(transcriptPath)) {
|
|
5388
5684
|
return {
|
|
5389
5685
|
taskId: jobId,
|
|
@@ -5392,13 +5688,30 @@ function readTranscriptLog(jobId, transcriptPath, cursor) {
|
|
|
5392
5688
|
};
|
|
5393
5689
|
}
|
|
5394
5690
|
const lines = (0, import_node_fs7.readFileSync)(transcriptPath, "utf8").split(/\r?\n/).filter(Boolean);
|
|
5395
|
-
|
|
5396
|
-
|
|
5397
|
-
|
|
5398
|
-
|
|
5399
|
-
|
|
5400
|
-
|
|
5401
|
-
|
|
5691
|
+
return (0, import_agent_sdk14.createBackgroundTaskLogPage)(jobId, lines, cursor);
|
|
5692
|
+
}
|
|
5693
|
+
|
|
5694
|
+
// src/user-local-direct-command.ts
|
|
5695
|
+
var import_agent_command_user_local = require("@robota-sdk/agent-command-user-local");
|
|
5696
|
+
async function runUserLocalDirectCommandIfRequested(args, cwd) {
|
|
5697
|
+
if (args.positional[0] !== "user-local") {
|
|
5698
|
+
return false;
|
|
5699
|
+
}
|
|
5700
|
+
const result = await (0, import_agent_command_user_local.executeUserLocalDirectCommand)({
|
|
5701
|
+
cwd,
|
|
5702
|
+
argv: args.positional.slice(1),
|
|
5703
|
+
format: args.format,
|
|
5704
|
+
summary: args.summary,
|
|
5705
|
+
source: args.source
|
|
5706
|
+
});
|
|
5707
|
+
const output = result.message.endsWith("\n") ? result.message : `${result.message}
|
|
5708
|
+
`;
|
|
5709
|
+
if (!result.success) {
|
|
5710
|
+
process.stderr.write(output);
|
|
5711
|
+
process.exit(1);
|
|
5712
|
+
}
|
|
5713
|
+
process.stdout.write(output);
|
|
5714
|
+
return true;
|
|
5402
5715
|
}
|
|
5403
5716
|
|
|
5404
5717
|
// src/cli.ts
|
|
@@ -5424,11 +5737,19 @@ function readVersion() {
|
|
|
5424
5737
|
}
|
|
5425
5738
|
}
|
|
5426
5739
|
function promptInput(label, masked = false) {
|
|
5427
|
-
return new Promise((
|
|
5740
|
+
return new Promise((resolve3, reject) => {
|
|
5428
5741
|
process.stdout.write(label);
|
|
5429
5742
|
let input = "";
|
|
5430
5743
|
const stdin = process.stdin;
|
|
5431
5744
|
const wasRaw = stdin.isRaw;
|
|
5745
|
+
if (!stdin.isTTY) {
|
|
5746
|
+
reject(
|
|
5747
|
+
new Error(
|
|
5748
|
+
"Cannot prompt for input: stdin is not a TTY.\nSet your API key via environment variable instead:\n ANTHROPIC_API_KEY=<key> robota\n OPENAI_API_KEY=<key> robota"
|
|
5749
|
+
)
|
|
5750
|
+
);
|
|
5751
|
+
return;
|
|
5752
|
+
}
|
|
5432
5753
|
stdin.setRawMode(true);
|
|
5433
5754
|
stdin.resume();
|
|
5434
5755
|
stdin.setEncoding("utf8");
|
|
@@ -5439,7 +5760,7 @@ function promptInput(label, masked = false) {
|
|
|
5439
5760
|
stdin.setRawMode(wasRaw ?? false);
|
|
5440
5761
|
stdin.pause();
|
|
5441
5762
|
process.stdout.write("\n");
|
|
5442
|
-
|
|
5763
|
+
resolve3(input.trim());
|
|
5443
5764
|
return;
|
|
5444
5765
|
} else if (ch === "\x7F" || ch === "\b") {
|
|
5445
5766
|
if (input.length > 0) {
|
|
@@ -5458,6 +5779,15 @@ function promptInput(label, masked = false) {
|
|
|
5458
5779
|
stdin.on("data", onData);
|
|
5459
5780
|
});
|
|
5460
5781
|
}
|
|
5782
|
+
function readTaskFilePrompt(cwd, taskFile) {
|
|
5783
|
+
const taskPath = (0, import_node_path10.resolve)(cwd, taskFile);
|
|
5784
|
+
const content = (0, import_node_fs8.readFileSync)(taskPath, "utf8").trim();
|
|
5785
|
+
if (content.length === 0) {
|
|
5786
|
+
throw new Error(`Task file is empty: ${taskFile}`);
|
|
5787
|
+
}
|
|
5788
|
+
return `Task file (${taskFile}):
|
|
5789
|
+
${content}`;
|
|
5790
|
+
}
|
|
5461
5791
|
function resetConfig() {
|
|
5462
5792
|
const userPath = getUserSettingsPath();
|
|
5463
5793
|
if (deleteSettings(userPath)) {
|
|
@@ -5467,6 +5797,43 @@ function resetConfig() {
|
|
|
5467
5797
|
process.stdout.write("No user settings found.\n");
|
|
5468
5798
|
}
|
|
5469
5799
|
}
|
|
5800
|
+
function createDefaultCliCommandModules({
|
|
5801
|
+
cwd,
|
|
5802
|
+
providerDefinitions
|
|
5803
|
+
}) {
|
|
5804
|
+
return [
|
|
5805
|
+
(0, import_agent_command_skills.createSkillsCommandModule)({ cwd }),
|
|
5806
|
+
(0, import_agent_command_help.createHelpCommandModule)(),
|
|
5807
|
+
(0, import_agent_command_agent.createAgentCommandModule)(),
|
|
5808
|
+
(0, import_agent_command_model.createModelCommandModule)({
|
|
5809
|
+
providerDefinitions,
|
|
5810
|
+
settings: {
|
|
5811
|
+
readMergedSettings: () => readMergedProviderSettings(cwd)
|
|
5812
|
+
}
|
|
5813
|
+
}),
|
|
5814
|
+
(0, import_agent_command_permissions.createPermissionsCommandModule)(),
|
|
5815
|
+
(0, import_agent_command_language.createLanguageCommandModule)(),
|
|
5816
|
+
(0, import_agent_command_background.createBackgroundCommandModule)(),
|
|
5817
|
+
(0, import_agent_command_memory.createMemoryCommandModule)(),
|
|
5818
|
+
(0, import_agent_command_user_local2.createUserLocalCommandModule)(),
|
|
5819
|
+
(0, import_agent_command_compact.createCompactCommandModule)(),
|
|
5820
|
+
(0, import_agent_command_context.createContextCommandModule)(),
|
|
5821
|
+
(0, import_agent_command_exit.createExitCommandModule)(),
|
|
5822
|
+
(0, import_agent_command_session.createSessionCommandModule)(),
|
|
5823
|
+
(0, import_agent_command_reset.createResetCommandModule)(),
|
|
5824
|
+
(0, import_agent_command_rewind.createRewindCommandModule)(),
|
|
5825
|
+
(0, import_agent_command_statusline.createStatusLineCommandModule)(),
|
|
5826
|
+
(0, import_agent_command_plugin.createPluginCommandModule)(),
|
|
5827
|
+
(0, import_agent_command_provider.createProviderCommandModule)({
|
|
5828
|
+
providerDefinitions,
|
|
5829
|
+
settings: {
|
|
5830
|
+
readMergedSettings: () => readMergedProviderSettings(cwd),
|
|
5831
|
+
readTargetSettings: () => readSettings(resolveProviderSettingsWriteTargetPath(cwd)),
|
|
5832
|
+
writeTargetSettings: (settings) => writeSettings(resolveProviderSettingsWriteTargetPath(cwd), settings)
|
|
5833
|
+
}
|
|
5834
|
+
})
|
|
5835
|
+
];
|
|
5836
|
+
}
|
|
5470
5837
|
async function startCli(options = {}) {
|
|
5471
5838
|
const args = parseCliArgs();
|
|
5472
5839
|
const version = readVersion();
|
|
@@ -5492,6 +5859,9 @@ async function startCli(options = {}) {
|
|
|
5492
5859
|
return;
|
|
5493
5860
|
}
|
|
5494
5861
|
const cwd = process.cwd();
|
|
5862
|
+
if (await runUserLocalDirectCommandIfRequested(args, cwd)) {
|
|
5863
|
+
return;
|
|
5864
|
+
}
|
|
5495
5865
|
const commandHostAdapters = {
|
|
5496
5866
|
settings: {
|
|
5497
5867
|
read: () => readSettings(getUserSettingsPath()),
|
|
@@ -5501,30 +5871,7 @@ async function startCli(options = {}) {
|
|
|
5501
5871
|
};
|
|
5502
5872
|
const providerDefinitions = options.providerDefinitions ?? DEFAULT_PROVIDER_DEFINITIONS;
|
|
5503
5873
|
const commandModules = [
|
|
5504
|
-
(
|
|
5505
|
-
(0, import_agent_command_agent.createAgentCommandModule)(),
|
|
5506
|
-
(0, import_agent_command_model.createModelCommandModule)(),
|
|
5507
|
-
(0, import_agent_command_mode.createModeCommandModule)(),
|
|
5508
|
-
(0, import_agent_command_permissions.createPermissionsCommandModule)(),
|
|
5509
|
-
(0, import_agent_command_language.createLanguageCommandModule)(),
|
|
5510
|
-
(0, import_agent_command_background.createBackgroundCommandModule)(),
|
|
5511
|
-
(0, import_agent_command_memory.createMemoryCommandModule)(),
|
|
5512
|
-
(0, import_agent_command_compact.createCompactCommandModule)(),
|
|
5513
|
-
(0, import_agent_command_context.createContextCommandModule)(),
|
|
5514
|
-
(0, import_agent_command_exit.createExitCommandModule)(),
|
|
5515
|
-
(0, import_agent_command_session.createSessionCommandModule)(),
|
|
5516
|
-
(0, import_agent_command_reset.createResetCommandModule)(),
|
|
5517
|
-
(0, import_agent_command_rewind.createRewindCommandModule)(),
|
|
5518
|
-
(0, import_agent_command_statusline.createStatusLineCommandModule)(),
|
|
5519
|
-
(0, import_agent_command_plugin.createPluginCommandModule)(),
|
|
5520
|
-
(0, import_agent_command_provider.createProviderCommandModule)({
|
|
5521
|
-
providerDefinitions,
|
|
5522
|
-
settings: {
|
|
5523
|
-
readMergedSettings: () => readMergedProviderSettings(cwd),
|
|
5524
|
-
readTargetSettings: () => readSettings(getUserSettingsPath()),
|
|
5525
|
-
writeTargetSettings: (settings) => writeSettings(getUserSettingsPath(), settings)
|
|
5526
|
-
}
|
|
5527
|
-
}),
|
|
5874
|
+
...createDefaultCliCommandModules({ cwd, providerDefinitions }),
|
|
5528
5875
|
...options.commandModules ?? []
|
|
5529
5876
|
];
|
|
5530
5877
|
const startupUpdateNoticePromise = shouldRunStartupCliUpdateCheck(args) ? getStartupCliUpdateNotice({ currentVersion: version }) : void 0;
|
|
@@ -5543,31 +5890,28 @@ async function startCli(options = {}) {
|
|
|
5543
5890
|
process.exit(1);
|
|
5544
5891
|
}
|
|
5545
5892
|
const providerOptions = args.provider ? { providerOverride: args.provider, providerDefinitions } : { providerDefinitions };
|
|
5893
|
+
const activeProviderSettings = readMergedProviderSettings(cwd);
|
|
5894
|
+
const providerProfileName = args.provider ?? activeProviderSettings.currentProvider;
|
|
5546
5895
|
const providerSettings = readProviderSettings(cwd, providerOptions);
|
|
5547
5896
|
const modelId = args.model ?? providerSettings.model;
|
|
5548
5897
|
const provider = createProviderFromSettings(cwd, args.model, providerOptions);
|
|
5549
5898
|
const backgroundTaskRunners = [createManagedShellProcessRunner()];
|
|
5550
|
-
const paths = (0,
|
|
5899
|
+
const paths = (0, import_agent_sdk15.projectPaths)(cwd);
|
|
5551
5900
|
const subagentRunnerFactory = createChildProcessSubagentRunnerFactory({
|
|
5552
5901
|
providerConfig: { ...providerSettings, model: modelId },
|
|
5553
5902
|
logsDir: paths.logs
|
|
5554
5903
|
});
|
|
5555
|
-
const sessionStore =
|
|
5904
|
+
const sessionStore = (0, import_agent_sdk15.createProjectSessionStore)(cwd);
|
|
5556
5905
|
let resumeSessionId;
|
|
5906
|
+
let showSessionPickerOnStart = false;
|
|
5557
5907
|
if (args.continueMode) {
|
|
5558
|
-
|
|
5559
|
-
if (sessions.length > 0) {
|
|
5560
|
-
resumeSessionId = sessions[0].id;
|
|
5561
|
-
}
|
|
5908
|
+
resumeSessionId = (0, import_agent_sdk15.resolveLatestSessionId)(sessionStore, cwd);
|
|
5562
5909
|
} else if (args.resumeId !== void 0) {
|
|
5563
5910
|
if (args.resumeId === "") {
|
|
5564
|
-
|
|
5911
|
+
showSessionPickerOnStart = true;
|
|
5565
5912
|
} else {
|
|
5566
|
-
|
|
5567
|
-
|
|
5568
|
-
if (match) {
|
|
5569
|
-
resumeSessionId = match.id;
|
|
5570
|
-
} else {
|
|
5913
|
+
resumeSessionId = (0, import_agent_sdk15.resolveSessionIdByIdOrName)(sessionStore, args.resumeId);
|
|
5914
|
+
if (resumeSessionId === void 0) {
|
|
5571
5915
|
process.stderr.write(`Session not found: ${args.resumeId}
|
|
5572
5916
|
`);
|
|
5573
5917
|
process.exit(1);
|
|
@@ -5589,13 +5933,25 @@ async function startCli(options = {}) {
|
|
|
5589
5933
|
}
|
|
5590
5934
|
const appendParts = [];
|
|
5591
5935
|
if (args.appendSystemPrompt) appendParts.push(args.appendSystemPrompt);
|
|
5936
|
+
if (args.taskFile) {
|
|
5937
|
+
try {
|
|
5938
|
+
appendParts.push(readTaskFilePrompt(cwd, args.taskFile));
|
|
5939
|
+
} catch (error) {
|
|
5940
|
+
process.stderr.write(`${error instanceof Error ? error.message : String(error)}
|
|
5941
|
+
`);
|
|
5942
|
+
process.exit(1);
|
|
5943
|
+
}
|
|
5944
|
+
}
|
|
5592
5945
|
if (args.jsonSchema)
|
|
5593
5946
|
appendParts.push(
|
|
5594
5947
|
`Respond with valid JSON only, matching this JSON schema:
|
|
5595
5948
|
${args.jsonSchema}`
|
|
5596
5949
|
);
|
|
5597
5950
|
const appendSystemPrompt = appendParts.length > 0 ? appendParts.join("\n\n") : void 0;
|
|
5598
|
-
|
|
5951
|
+
if (args.systemPrompt) {
|
|
5952
|
+
process.stderr.write("Warning: --system-prompt is not yet functional and will be ignored.\n");
|
|
5953
|
+
}
|
|
5954
|
+
const session = new import_agent_sdk15.InteractiveSession({
|
|
5599
5955
|
cwd,
|
|
5600
5956
|
provider,
|
|
5601
5957
|
permissionMode: args.permissionMode ?? "bypassPermissions",
|
|
@@ -5623,6 +5979,8 @@ ${args.jsonSchema}`
|
|
|
5623
5979
|
cwd,
|
|
5624
5980
|
provider,
|
|
5625
5981
|
providerOverride: args.provider,
|
|
5982
|
+
providerProfileName,
|
|
5983
|
+
providerType: providerSettings.name,
|
|
5626
5984
|
modelId,
|
|
5627
5985
|
language: args.language,
|
|
5628
5986
|
permissionMode: args.permissionMode,
|
|
@@ -5630,13 +5988,16 @@ ${args.jsonSchema}`
|
|
|
5630
5988
|
version,
|
|
5631
5989
|
sessionStore,
|
|
5632
5990
|
resumeSessionId,
|
|
5991
|
+
showSessionPickerOnStart,
|
|
5633
5992
|
forkSession: args.forkSession,
|
|
5634
5993
|
sessionName: args.sessionName,
|
|
5635
5994
|
backgroundTaskRunners,
|
|
5636
5995
|
subagentRunnerFactory,
|
|
5637
5996
|
commandModules,
|
|
5638
5997
|
commandHostAdapters,
|
|
5639
|
-
startupUpdateNoticePromise
|
|
5998
|
+
startupUpdateNoticePromise,
|
|
5999
|
+
webPort: args.web ? args.webPort : void 0,
|
|
6000
|
+
noOpen: args.noOpen
|
|
5640
6001
|
});
|
|
5641
6002
|
}
|
|
5642
6003
|
// Annotate the CommonJS export names for ESM import in node:
|