@robota-sdk/agent-cli 3.0.0-beta.59 → 3.0.0-beta.60
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.md +29 -22
- package/dist/node/bin.js +3 -4
- package/dist/node/{chunk-4ZX5RLIX.js → chunk-6XQKLNRF.js} +20 -29
- package/dist/node/{chunk-B522YHTK.js → chunk-GHQHUBHC.js} +703 -919
- package/dist/node/index.cjs +747 -997
- package/dist/node/index.d.cts +5 -0
- package/dist/node/index.d.ts +5 -0
- package/dist/node/index.js +2 -2
- package/dist/node/subagents/child-process-subagent-worker.js +1 -1
- package/package.json +27 -11
package/dist/node/index.cjs
CHANGED
|
@@ -43,7 +43,24 @@ module.exports = __toCommonJS(index_exports);
|
|
|
43
43
|
var import_node_fs8 = require("fs");
|
|
44
44
|
var import_node_path10 = require("path");
|
|
45
45
|
var import_node_url = require("url");
|
|
46
|
-
var
|
|
46
|
+
var import_agent_command_agent = require("@robota-sdk/agent-command-agent");
|
|
47
|
+
var import_agent_command_background = require("@robota-sdk/agent-command-background");
|
|
48
|
+
var import_agent_command_provider = require("@robota-sdk/agent-command-provider");
|
|
49
|
+
var import_agent_command_compact = require("@robota-sdk/agent-command-compact");
|
|
50
|
+
var import_agent_command_context = require("@robota-sdk/agent-command-context");
|
|
51
|
+
var import_agent_command_exit = require("@robota-sdk/agent-command-exit");
|
|
52
|
+
var import_agent_command_help = require("@robota-sdk/agent-command-help");
|
|
53
|
+
var import_agent_command_language = require("@robota-sdk/agent-command-language");
|
|
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
|
+
var import_agent_command_model = require("@robota-sdk/agent-command-model");
|
|
57
|
+
var import_agent_command_permissions = require("@robota-sdk/agent-command-permissions");
|
|
58
|
+
var import_agent_command_plugin = require("@robota-sdk/agent-command-plugin");
|
|
59
|
+
var import_agent_command_reset = require("@robota-sdk/agent-command-reset");
|
|
60
|
+
var import_agent_command_rewind = require("@robota-sdk/agent-command-rewind");
|
|
61
|
+
var import_agent_command_statusline = require("@robota-sdk/agent-command-statusline");
|
|
62
|
+
var import_agent_command_session = require("@robota-sdk/agent-command-session");
|
|
63
|
+
var import_agent_sdk14 = require("@robota-sdk/agent-sdk");
|
|
47
64
|
var import_agent_sessions = require("@robota-sdk/agent-sessions");
|
|
48
65
|
|
|
49
66
|
// src/utils/cli-args.ts
|
|
@@ -159,28 +176,6 @@ function writeSettings(path, settings) {
|
|
|
159
176
|
(0, import_node_fs.mkdirSync)((0, import_node_path.dirname)(path), { recursive: true });
|
|
160
177
|
(0, import_node_fs.writeFileSync)(path, JSON.stringify(settings, null, 2) + "\n", "utf8");
|
|
161
178
|
}
|
|
162
|
-
function updateModelInSettings(settingsPath, modelId) {
|
|
163
|
-
const settings = readSettings(settingsPath);
|
|
164
|
-
const currentProvider = settings.currentProvider;
|
|
165
|
-
const providers = settings.providers;
|
|
166
|
-
if (typeof currentProvider === "string" && isSettingsData(providers)) {
|
|
167
|
-
const providerMap = providers;
|
|
168
|
-
providerMap[currentProvider] = {
|
|
169
|
-
...isSettingsData(providerMap[currentProvider]) ? providerMap[currentProvider] : {},
|
|
170
|
-
model: modelId
|
|
171
|
-
};
|
|
172
|
-
settings.providers = providerMap;
|
|
173
|
-
} else {
|
|
174
|
-
settings.provider = {
|
|
175
|
-
...isSettingsData(settings.provider) ? settings.provider : {},
|
|
176
|
-
model: modelId
|
|
177
|
-
};
|
|
178
|
-
}
|
|
179
|
-
writeSettings(settingsPath, settings);
|
|
180
|
-
}
|
|
181
|
-
function isSettingsData(value) {
|
|
182
|
-
return value !== null && typeof value === "object" && !Array.isArray(value) && !(value instanceof Date);
|
|
183
|
-
}
|
|
184
179
|
function deleteSettings(path) {
|
|
185
180
|
if ((0, import_node_fs.existsSync)(path)) {
|
|
186
181
|
(0, import_node_fs.unlinkSync)(path);
|
|
@@ -192,7 +187,6 @@ function deleteSettings(path) {
|
|
|
192
187
|
// src/utils/provider-factory.ts
|
|
193
188
|
var import_node_fs2 = require("fs");
|
|
194
189
|
var import_node_path2 = require("path");
|
|
195
|
-
var import_node_os = require("os");
|
|
196
190
|
|
|
197
191
|
// src/utils/provider-default-definitions.ts
|
|
198
192
|
var import_agent_provider_anthropic = require("@robota-sdk/agent-provider-anthropic");
|
|
@@ -212,31 +206,7 @@ var DEFAULT_PROVIDER_DEFINITIONS = [
|
|
|
212
206
|
var import_agent_core = require("@robota-sdk/agent-core");
|
|
213
207
|
|
|
214
208
|
// src/utils/env-ref.ts
|
|
215
|
-
var
|
|
216
|
-
function isEnvReference(value) {
|
|
217
|
-
return value.startsWith(ENV_REFERENCE_PREFIX);
|
|
218
|
-
}
|
|
219
|
-
function getEnvReferenceName(value) {
|
|
220
|
-
if (!isEnvReference(value)) {
|
|
221
|
-
return void 0;
|
|
222
|
-
}
|
|
223
|
-
const envName = value.slice(ENV_REFERENCE_PREFIX.length).trim();
|
|
224
|
-
return envName.length > 0 ? envName : void 0;
|
|
225
|
-
}
|
|
226
|
-
function resolveEnvReference(value) {
|
|
227
|
-
const envName = getEnvReferenceName(value);
|
|
228
|
-
if (envName === void 0) {
|
|
229
|
-
return value;
|
|
230
|
-
}
|
|
231
|
-
const resolved = process.env[envName];
|
|
232
|
-
return resolved !== void 0 && resolved.length > 0 ? resolved : void 0;
|
|
233
|
-
}
|
|
234
|
-
function hasUsableSecretReference(value) {
|
|
235
|
-
if (value === void 0 || value.length === 0) {
|
|
236
|
-
return false;
|
|
237
|
-
}
|
|
238
|
-
return resolveEnvReference(value) !== void 0;
|
|
239
|
-
}
|
|
209
|
+
var import_agent_sdk = require("@robota-sdk/agent-sdk");
|
|
240
210
|
|
|
241
211
|
// src/utils/provider-factory.ts
|
|
242
212
|
function readProviderSettings(cwd, options = {}) {
|
|
@@ -252,14 +222,23 @@ function readProviderSettings(cwd, options = {}) {
|
|
|
252
222
|
throw new Error("No provider configuration found. Run `robota` to set up.");
|
|
253
223
|
}
|
|
254
224
|
function readMergedProviderSettings(cwd) {
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
225
|
+
return readMergedProviderSettingsFromPaths(getProviderSettingsPaths(cwd));
|
|
226
|
+
}
|
|
227
|
+
function getProviderSettingsPaths(cwd) {
|
|
228
|
+
const userHome = getUserHome();
|
|
229
|
+
return [
|
|
230
|
+
(0, import_node_path2.join)(userHome, ".robota", "settings.json"),
|
|
231
|
+
(0, import_node_path2.join)(userHome, ".claude", "settings.json"),
|
|
258
232
|
(0, import_node_path2.join)(cwd, ".robota", "settings.json"),
|
|
259
233
|
(0, import_node_path2.join)(cwd, ".robota", "settings.local.json"),
|
|
260
234
|
(0, import_node_path2.join)(cwd, ".claude", "settings.json"),
|
|
261
235
|
(0, import_node_path2.join)(cwd, ".claude", "settings.local.json")
|
|
262
236
|
];
|
|
237
|
+
}
|
|
238
|
+
function getUserHome() {
|
|
239
|
+
return process.env.HOME ?? process.env.USERPROFILE ?? "/";
|
|
240
|
+
}
|
|
241
|
+
function readMergedProviderSettingsFromPaths(paths) {
|
|
263
242
|
return paths.reduce((settings, filePath) => {
|
|
264
243
|
const parsed = readSettingsFile(filePath);
|
|
265
244
|
if (parsed === void 0) {
|
|
@@ -343,7 +322,7 @@ function normalizeProviderConfig(settings, providerDefinitions) {
|
|
|
343
322
|
return {
|
|
344
323
|
name: settings.name,
|
|
345
324
|
model,
|
|
346
|
-
apiKey: apiKeyReference !== void 0 ? resolveEnvReference(apiKeyReference) : void 0,
|
|
325
|
+
apiKey: apiKeyReference !== void 0 ? (0, import_agent_sdk.resolveEnvReference)(apiKeyReference) : void 0,
|
|
347
326
|
baseURL: settings.baseURL ?? defaults.baseURL,
|
|
348
327
|
timeout: settings.timeout,
|
|
349
328
|
...options !== void 0 && { options }
|
|
@@ -373,37 +352,27 @@ function getProviderDefinitions(options) {
|
|
|
373
352
|
|
|
374
353
|
// src/utils/provider-setup.ts
|
|
375
354
|
var import_node_path3 = require("path");
|
|
376
|
-
var import_node_os2 = require("os");
|
|
377
355
|
|
|
378
356
|
// src/utils/settings-check.ts
|
|
379
357
|
var import_node_fs3 = require("fs");
|
|
380
|
-
function
|
|
381
|
-
|
|
382
|
-
try {
|
|
383
|
-
const raw = (0, import_node_fs3.readFileSync)(filePath, "utf8").trim();
|
|
384
|
-
if (raw.length === 0) return "incomplete";
|
|
385
|
-
const parsed = JSON.parse(raw);
|
|
386
|
-
if (!hasUsableProviderConfig(parsed, providerDefinitions)) return "incomplete";
|
|
387
|
-
return "valid";
|
|
388
|
-
} catch {
|
|
389
|
-
return "corrupt";
|
|
390
|
-
}
|
|
358
|
+
function checkSettingsDocument(settings, providerDefinitions = []) {
|
|
359
|
+
return hasUsableProviderConfig(settings, providerDefinitions) ? "valid" : "incomplete";
|
|
391
360
|
}
|
|
392
361
|
function hasUsableProviderConfig(settings, providerDefinitions) {
|
|
362
|
+
if (typeof settings.currentProvider === "string") {
|
|
363
|
+
const profile = settings.providers?.[settings.currentProvider];
|
|
364
|
+
return isUsableProviderProfile(profile?.type, profile, providerDefinitions);
|
|
365
|
+
}
|
|
393
366
|
if (settings.provider && isUsableProviderProfile(settings.provider.name, settings.provider, providerDefinitions)) {
|
|
394
367
|
return true;
|
|
395
368
|
}
|
|
396
|
-
|
|
397
|
-
return false;
|
|
398
|
-
}
|
|
399
|
-
const profile = settings.providers?.[settings.currentProvider];
|
|
400
|
-
return isUsableProviderProfile(profile?.type, profile, providerDefinitions);
|
|
369
|
+
return false;
|
|
401
370
|
}
|
|
402
371
|
function isUsableProviderProfile(type, profile, providerDefinitions) {
|
|
403
372
|
if (!profile) {
|
|
404
373
|
return false;
|
|
405
374
|
}
|
|
406
|
-
if (hasUsableSecretReference(profile.apiKey)) {
|
|
375
|
+
if ((0, import_agent_sdk.hasUsableSecretReference)(profile.apiKey)) {
|
|
407
376
|
return true;
|
|
408
377
|
}
|
|
409
378
|
if (!type) {
|
|
@@ -413,73 +382,11 @@ function isUsableProviderProfile(type, profile, providerDefinitions) {
|
|
|
413
382
|
if (definition === void 0) {
|
|
414
383
|
return false;
|
|
415
384
|
}
|
|
416
|
-
return definition.requiresApiKey !== true || hasUsableSecretReference(definition.defaults?.apiKey);
|
|
385
|
+
return definition.requiresApiKey !== true || (0, import_agent_sdk.hasUsableSecretReference)(definition.defaults?.apiKey);
|
|
417
386
|
}
|
|
418
387
|
|
|
419
388
|
// src/utils/provider-settings.ts
|
|
420
|
-
|
|
421
|
-
return {
|
|
422
|
-
...settings,
|
|
423
|
-
providers: {
|
|
424
|
-
...settings.providers ?? {},
|
|
425
|
-
[profileName]: profile
|
|
426
|
-
}
|
|
427
|
-
};
|
|
428
|
-
}
|
|
429
|
-
function setCurrentProvider(settings, profileName) {
|
|
430
|
-
if (!settings.providers?.[profileName]) {
|
|
431
|
-
throw new Error(`Provider profile "${profileName}" was not found`);
|
|
432
|
-
}
|
|
433
|
-
return {
|
|
434
|
-
...settings,
|
|
435
|
-
currentProvider: profileName
|
|
436
|
-
};
|
|
437
|
-
}
|
|
438
|
-
function validateProviderProfile(profileName, profile, options = {}) {
|
|
439
|
-
if (!profile.type) {
|
|
440
|
-
throw new Error(`Provider profile "${profileName}" is missing type`);
|
|
441
|
-
}
|
|
442
|
-
if (!profile.model) {
|
|
443
|
-
throw new Error(`Provider profile "${profileName}" is missing model`);
|
|
444
|
-
}
|
|
445
|
-
const definition = (0, import_agent_core.findProviderDefinition)(options.providerDefinitions ?? [], profile.type);
|
|
446
|
-
if (definition?.requiresApiKey === true && !hasUsableSecretReference(profile.apiKey ?? definition.defaults?.apiKey)) {
|
|
447
|
-
throw new Error(`Provider profile "${profileName}" is missing apiKey`);
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
function buildProviderSetupPatch(input, options = {}) {
|
|
451
|
-
const profile = buildProviderProfile(input, options);
|
|
452
|
-
validateProviderProfile(input.profile, profile, options);
|
|
453
|
-
return {
|
|
454
|
-
...input.setCurrent && { currentProvider: input.profile },
|
|
455
|
-
providers: {
|
|
456
|
-
[input.profile]: profile
|
|
457
|
-
}
|
|
458
|
-
};
|
|
459
|
-
}
|
|
460
|
-
function buildProviderProfile(input, options = {}) {
|
|
461
|
-
const defaults = getProviderDefaults(input.type, options.providerDefinitions ?? []);
|
|
462
|
-
const apiKey = input.apiKeyEnv !== void 0 ? `$ENV:${input.apiKeyEnv}` : input.apiKey ?? defaults.apiKey;
|
|
463
|
-
const baseURL = input.baseURL ?? defaults.baseURL;
|
|
464
|
-
return {
|
|
465
|
-
type: input.type,
|
|
466
|
-
model: input.model ?? defaults.model,
|
|
467
|
-
...apiKey !== void 0 && { apiKey },
|
|
468
|
-
...baseURL !== void 0 && { baseURL },
|
|
469
|
-
...input.timeout !== void 0 && { timeout: input.timeout }
|
|
470
|
-
};
|
|
471
|
-
}
|
|
472
|
-
function getProviderDefaults(type, providerDefinitions) {
|
|
473
|
-
return (0, import_agent_core.findProviderDefinition)(providerDefinitions, type)?.defaults ?? {};
|
|
474
|
-
}
|
|
475
|
-
function mergeProviderPatch(settings, patch) {
|
|
476
|
-
const [profileName, profile] = Object.entries(patch.providers)[0] ?? [];
|
|
477
|
-
if (!profileName || !profile) {
|
|
478
|
-
return settings;
|
|
479
|
-
}
|
|
480
|
-
const withProfile = upsertProviderProfile(settings, profileName, profile);
|
|
481
|
-
return patch.currentProvider ? setCurrentProvider(withProfile, patch.currentProvider) : withProfile;
|
|
482
|
-
}
|
|
389
|
+
var import_agent_sdk2 = require("@robota-sdk/agent-sdk");
|
|
483
390
|
|
|
484
391
|
// src/utils/provider-configuration.ts
|
|
485
392
|
function readProviderDocument(settingsPath) {
|
|
@@ -487,8 +394,8 @@ function readProviderDocument(settingsPath) {
|
|
|
487
394
|
}
|
|
488
395
|
function applyProviderConfiguration(settingsPath, input, options = {}) {
|
|
489
396
|
const settings = readProviderDocument(settingsPath);
|
|
490
|
-
const patch = buildProviderSetupPatch(input, options);
|
|
491
|
-
const next = mergeProviderPatch(settings, patch);
|
|
397
|
+
const patch = (0, import_agent_sdk2.buildProviderSetupPatch)(input, options);
|
|
398
|
+
const next = (0, import_agent_sdk2.mergeProviderPatch)(settings, patch);
|
|
492
399
|
writeSettings(settingsPath, next);
|
|
493
400
|
return next;
|
|
494
401
|
}
|
|
@@ -496,162 +403,78 @@ function applyProviderSwitch(settingsPath, profileName, options = {}) {
|
|
|
496
403
|
const settings = readProviderDocument(settingsPath);
|
|
497
404
|
const hasLocalProfile = settings.providers?.[profileName] !== void 0;
|
|
498
405
|
const hasKnownProfile = options.knownProviders?.[profileName] !== void 0;
|
|
499
|
-
const next = hasLocalProfile || hasKnownProfile ? { ...settings, currentProvider: profileName } : setCurrentProvider(settings, profileName);
|
|
406
|
+
const next = hasLocalProfile || hasKnownProfile ? { ...settings, currentProvider: profileName } : (0, import_agent_sdk2.setCurrentProvider)(settings, profileName);
|
|
500
407
|
writeSettings(settingsPath, next);
|
|
501
408
|
return next;
|
|
502
409
|
}
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
stepIndex: 0,
|
|
510
|
-
values: {}
|
|
511
|
-
};
|
|
512
|
-
}
|
|
513
|
-
function formatProviderSetupSelectionPrompt(providerDefinitions) {
|
|
514
|
-
if (providerDefinitions.length === 0) {
|
|
515
|
-
return " No providers are available.";
|
|
516
|
-
}
|
|
517
|
-
const lines = [
|
|
518
|
-
" Select provider:",
|
|
519
|
-
...providerDefinitions.map(
|
|
520
|
-
(definition, index) => ` ${index + 1}. ${formatProviderSetupChoiceLabel(definition)}`
|
|
521
|
-
),
|
|
522
|
-
` Provider [1-${providerDefinitions.length}] (default: 1): `
|
|
523
|
-
];
|
|
524
|
-
return lines.join("\n");
|
|
525
|
-
}
|
|
526
|
-
function resolveProviderSetupSelection(rawValue, providerDefinitions) {
|
|
527
|
-
const value = rawValue.trim();
|
|
528
|
-
const selectedValue = value.length > 0 ? value : "1";
|
|
529
|
-
const index = parseProviderSelectionIndex(selectedValue);
|
|
530
|
-
if (index !== void 0) {
|
|
531
|
-
const definition2 = providerDefinitions[index];
|
|
532
|
-
if (definition2 !== void 0) {
|
|
533
|
-
return definition2.type;
|
|
534
|
-
}
|
|
535
|
-
throw new Error(
|
|
536
|
-
`Provider selection ${selectedValue} is out of range. Currently supported: ${(0, import_agent_core.formatSupportedProviderTypes)(providerDefinitions)}`
|
|
537
|
-
);
|
|
538
|
-
}
|
|
539
|
-
const definition = (0, import_agent_core.findProviderDefinition)(providerDefinitions, selectedValue);
|
|
540
|
-
if (definition === void 0) {
|
|
541
|
-
throw new Error(
|
|
542
|
-
`Unknown provider: ${selectedValue}. Currently supported: ${(0, import_agent_core.formatSupportedProviderTypes)(providerDefinitions)}`
|
|
543
|
-
);
|
|
544
|
-
}
|
|
545
|
-
return definition.type;
|
|
546
|
-
}
|
|
547
|
-
function getProviderSetupStep(state) {
|
|
548
|
-
const step = state.steps[state.stepIndex];
|
|
549
|
-
if (step === void 0) {
|
|
550
|
-
throw new Error(`Provider setup step ${state.stepIndex} is out of range`);
|
|
410
|
+
function applyActiveModelChange(cwd, modelId, options = {}) {
|
|
411
|
+
const settingsPaths = options.settingsPaths ?? getProviderSettingsPaths(cwd);
|
|
412
|
+
const merged = readMergedProviderSettingsFromPaths(settingsPaths);
|
|
413
|
+
const activeProfileName = options.providerOverride ?? merged.currentProvider;
|
|
414
|
+
if (typeof activeProfileName === "string") {
|
|
415
|
+
return updateActiveProviderProfileModel(settingsPaths, activeProfileName, modelId);
|
|
551
416
|
}
|
|
552
|
-
return
|
|
417
|
+
return updateLegacyProviderModel(settingsPaths, modelId);
|
|
553
418
|
}
|
|
554
|
-
function
|
|
555
|
-
const
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
if (validationMessage !== void 0) {
|
|
559
|
-
return { status: "error", state, message: validationMessage };
|
|
419
|
+
function updateActiveProviderProfileModel(settingsPaths, profileName, modelId) {
|
|
420
|
+
const settingsPath = findLastPathWithProviderProfile(settingsPaths, profileName) ?? settingsPaths[0];
|
|
421
|
+
if (settingsPath === void 0) {
|
|
422
|
+
throw new Error("No settings path available for model update");
|
|
560
423
|
}
|
|
561
|
-
const
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
let state = createProviderSetupFlow(type, providerDefinitions);
|
|
573
|
-
const stepCount = state.steps.length;
|
|
574
|
-
while (state.stepIndex < stepCount) {
|
|
575
|
-
const step = getProviderSetupStep(state);
|
|
576
|
-
const value = await promptInput2(formatProviderSetupPromptLabel(step), step.masked === true);
|
|
577
|
-
const result = submitProviderSetupValue(state, value);
|
|
578
|
-
if (result.status === "complete") {
|
|
579
|
-
return result.input;
|
|
580
|
-
}
|
|
581
|
-
if (result.status === "error") {
|
|
582
|
-
throw new Error(result.message);
|
|
424
|
+
const settings = readProviderDocument(settingsPath);
|
|
425
|
+
const providers = settings.providers ?? {};
|
|
426
|
+
const existing = providers[profileName] ?? {};
|
|
427
|
+
const next = {
|
|
428
|
+
...settings,
|
|
429
|
+
providers: {
|
|
430
|
+
...providers,
|
|
431
|
+
[profileName]: {
|
|
432
|
+
...existing,
|
|
433
|
+
model: modelId
|
|
434
|
+
}
|
|
583
435
|
}
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
}
|
|
588
|
-
function formatProviderSetupPromptLabel(step) {
|
|
589
|
-
const suffix = step.defaultValue !== void 0 ? ` (default: ${step.defaultValue})` : "";
|
|
590
|
-
return ` ${step.title}${suffix}: `;
|
|
591
|
-
}
|
|
592
|
-
function formatProviderSetupChoiceLabel(definition) {
|
|
593
|
-
const label = definition.displayName !== void 0 ? `${definition.displayName} (${definition.type})` : definition.type;
|
|
594
|
-
return definition.description !== void 0 ? `${label} - ${definition.description}` : label;
|
|
436
|
+
};
|
|
437
|
+
writeSettings(settingsPath, next);
|
|
438
|
+
return { settingsPath, settings: next, profileName };
|
|
595
439
|
}
|
|
596
|
-
function
|
|
597
|
-
|
|
598
|
-
|
|
440
|
+
function updateLegacyProviderModel(settingsPaths, modelId) {
|
|
441
|
+
const settingsPath = findLastPathWithLegacyProvider(settingsPaths) ?? settingsPaths[0];
|
|
442
|
+
if (settingsPath === void 0) {
|
|
443
|
+
throw new Error("No settings path available for model update");
|
|
599
444
|
}
|
|
600
|
-
|
|
445
|
+
const settings = readProviderDocument(settingsPath);
|
|
446
|
+
const next = {
|
|
447
|
+
...settings,
|
|
448
|
+
provider: {
|
|
449
|
+
...settings.provider ?? {},
|
|
450
|
+
model: modelId
|
|
451
|
+
}
|
|
452
|
+
};
|
|
453
|
+
writeSettings(settingsPath, next);
|
|
454
|
+
return { settingsPath, settings: next, legacyProvider: true };
|
|
601
455
|
}
|
|
602
|
-
function
|
|
603
|
-
|
|
604
|
-
|
|
456
|
+
function findLastPathWithProviderProfile(settingsPaths, profileName) {
|
|
457
|
+
for (let index = settingsPaths.length - 1; index >= 0; index -= 1) {
|
|
458
|
+
const settingsPath = settingsPaths[index];
|
|
459
|
+
if (settingsPath === void 0) continue;
|
|
460
|
+
const settings = readProviderDocument(settingsPath);
|
|
461
|
+
if (settings.providers?.[profileName] !== void 0) return settingsPath;
|
|
605
462
|
}
|
|
606
463
|
return void 0;
|
|
607
464
|
}
|
|
608
|
-
function
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
);
|
|
614
|
-
}
|
|
615
|
-
if (definition.setupSteps !== void 0) {
|
|
616
|
-
return [...definition.setupSteps];
|
|
617
|
-
}
|
|
618
|
-
const steps = [
|
|
619
|
-
{
|
|
620
|
-
key: "model",
|
|
621
|
-
title: `${definition.type} model`,
|
|
622
|
-
defaultValue: definition.defaults?.model,
|
|
623
|
-
required: definition.defaults?.model === void 0
|
|
624
|
-
}
|
|
625
|
-
];
|
|
626
|
-
if (definition.defaults?.baseURL !== void 0) {
|
|
627
|
-
steps.unshift({
|
|
628
|
-
key: "baseURL",
|
|
629
|
-
title: `${definition.type} base URL`,
|
|
630
|
-
defaultValue: definition.defaults.baseURL
|
|
631
|
-
});
|
|
632
|
-
}
|
|
633
|
-
if (definition.requiresApiKey === true) {
|
|
634
|
-
steps.push({
|
|
635
|
-
key: "apiKey",
|
|
636
|
-
title: `${definition.type} API key`,
|
|
637
|
-
defaultValue: definition.defaults?.apiKey,
|
|
638
|
-
required: definition.defaults?.apiKey === void 0,
|
|
639
|
-
masked: true
|
|
640
|
-
});
|
|
465
|
+
function findLastPathWithLegacyProvider(settingsPaths) {
|
|
466
|
+
for (let index = settingsPaths.length - 1; index >= 0; index -= 1) {
|
|
467
|
+
const settingsPath = settingsPaths[index];
|
|
468
|
+
if (settingsPath === void 0) continue;
|
|
469
|
+
const settings = readProviderDocument(settingsPath);
|
|
470
|
+
if (settings.provider !== void 0) return settingsPath;
|
|
641
471
|
}
|
|
642
|
-
return
|
|
643
|
-
}
|
|
644
|
-
function buildProviderSetupInput(state) {
|
|
645
|
-
return {
|
|
646
|
-
profile: state.type,
|
|
647
|
-
type: state.type,
|
|
648
|
-
model: state.values.model,
|
|
649
|
-
apiKey: state.values.apiKey,
|
|
650
|
-
...state.values.baseURL !== void 0 && { baseURL: state.values.baseURL },
|
|
651
|
-
setCurrent: true
|
|
652
|
-
};
|
|
472
|
+
return void 0;
|
|
653
473
|
}
|
|
654
474
|
|
|
475
|
+
// src/utils/provider-setup-flow.ts
|
|
476
|
+
var import_agent_sdk3 = require("@robota-sdk/agent-sdk");
|
|
477
|
+
|
|
655
478
|
// src/utils/provider-setup.ts
|
|
656
479
|
function getSettingsPathForScope(cwd, scope) {
|
|
657
480
|
if (scope === void 0 || scope === "user") {
|
|
@@ -683,23 +506,31 @@ function handleProviderConfigurationArgs(cwd, args, providerDefinitions = DEFAUL
|
|
|
683
506
|
return false;
|
|
684
507
|
}
|
|
685
508
|
async function ensureConfig(cwd, args, promptInput2, providerDefinitions = DEFAULT_PROVIDER_DEFINITIONS) {
|
|
686
|
-
const
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
}));
|
|
690
|
-
if (checks.some((check) => check.status === "valid")) {
|
|
509
|
+
const merged = readMergedProviderSettings(cwd);
|
|
510
|
+
const selectedSettings = args.provider !== void 0 ? { ...merged, currentProvider: args.provider } : merged;
|
|
511
|
+
if (checkSettingsDocument(selectedSettings, providerDefinitions) === "valid") {
|
|
691
512
|
return;
|
|
692
513
|
}
|
|
693
514
|
if (!isInteractiveTerminal()) {
|
|
694
515
|
throw new Error(formatMissingProviderConfigMessage(providerDefinitions));
|
|
695
516
|
}
|
|
696
|
-
await runInteractiveProviderSetup(
|
|
517
|
+
await runInteractiveProviderSetup(
|
|
518
|
+
cwd,
|
|
519
|
+
selectStartupSetupArgs(cwd, args),
|
|
520
|
+
promptInput2,
|
|
521
|
+
providerDefinitions
|
|
522
|
+
);
|
|
523
|
+
const updated = readMergedProviderSettings(cwd);
|
|
524
|
+
const updatedSettings = args.provider !== void 0 ? { ...updated, currentProvider: args.provider } : updated;
|
|
525
|
+
if (checkSettingsDocument(updatedSettings, providerDefinitions) !== "valid") {
|
|
526
|
+
throw new Error(formatMissingProviderConfigMessage(providerDefinitions));
|
|
527
|
+
}
|
|
697
528
|
}
|
|
698
529
|
async function runInteractiveProviderSetup(cwd, args, promptInput2, providerDefinitions = DEFAULT_PROVIDER_DEFINITIONS) {
|
|
699
|
-
const providerChoice = await promptInput2(formatProviderSetupSelectionPrompt(providerDefinitions));
|
|
700
|
-
const type = resolveProviderSetupSelection(providerChoice, providerDefinitions);
|
|
530
|
+
const providerChoice = await promptInput2((0, import_agent_sdk3.formatProviderSetupSelectionPrompt)(providerDefinitions));
|
|
531
|
+
const type = (0, import_agent_sdk3.resolveProviderSetupSelection)(providerChoice, providerDefinitions);
|
|
701
532
|
const settingsPath = getSettingsPathForScope(cwd, args.settingsScope);
|
|
702
|
-
const input = await runProviderSetupPromptFlow(type, promptInput2, providerDefinitions);
|
|
533
|
+
const input = await (0, import_agent_sdk3.runProviderSetupPromptFlow)(type, promptInput2, providerDefinitions);
|
|
703
534
|
applyProviderConfiguration(settingsPath, input, {
|
|
704
535
|
providerDefinitions
|
|
705
536
|
});
|
|
@@ -729,15 +560,31 @@ function buildSetupInputFromArgs(args) {
|
|
|
729
560
|
setCurrent: args.setCurrent
|
|
730
561
|
};
|
|
731
562
|
}
|
|
732
|
-
function
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
563
|
+
function selectStartupSetupArgs(cwd, args) {
|
|
564
|
+
if (args.settingsScope !== void 0 || args.provider !== void 0) {
|
|
565
|
+
return args;
|
|
566
|
+
}
|
|
567
|
+
const currentProviderPath = findHighestPriorityCurrentProviderPath(getProviderSettingsPaths(cwd));
|
|
568
|
+
if (currentProviderPath === void 0) {
|
|
569
|
+
return args;
|
|
570
|
+
}
|
|
571
|
+
const projectSettingsPath = (0, import_node_path3.join)(cwd, ".robota", "settings.json");
|
|
572
|
+
const projectLocalSettingsPath = (0, import_node_path3.join)(cwd, ".robota", "settings.local.json");
|
|
573
|
+
if (currentProviderPath === projectSettingsPath || currentProviderPath === projectLocalSettingsPath) {
|
|
574
|
+
return { ...args, settingsScope: "project-local" };
|
|
575
|
+
}
|
|
576
|
+
return args;
|
|
577
|
+
}
|
|
578
|
+
function findHighestPriorityCurrentProviderPath(settingsPaths) {
|
|
579
|
+
for (let index = settingsPaths.length - 1; index >= 0; index -= 1) {
|
|
580
|
+
const settingsPath = settingsPaths[index];
|
|
581
|
+
if (settingsPath === void 0) continue;
|
|
582
|
+
const settings = readSettings(settingsPath);
|
|
583
|
+
if (typeof settings.currentProvider === "string") {
|
|
584
|
+
return settingsPath;
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
return void 0;
|
|
741
588
|
}
|
|
742
589
|
function isInteractiveTerminal() {
|
|
743
590
|
return process.stdin.isTTY === true && process.stdout.isTTY === true;
|
|
@@ -771,13 +618,11 @@ var import_ink22 = require("ink");
|
|
|
771
618
|
// src/ui/App.tsx
|
|
772
619
|
var import_react19 = require("react");
|
|
773
620
|
var import_ink21 = require("ink");
|
|
774
|
-
var
|
|
621
|
+
var import_agent_core11 = require("@robota-sdk/agent-core");
|
|
775
622
|
|
|
776
623
|
// src/ui/hooks/useInteractiveSession.ts
|
|
777
624
|
var import_react2 = require("react");
|
|
778
|
-
var
|
|
779
|
-
var import_node_path4 = require("path");
|
|
780
|
-
var import_agent_sdk = require("@robota-sdk/agent-sdk");
|
|
625
|
+
var import_agent_sdk5 = require("@robota-sdk/agent-sdk");
|
|
781
626
|
var import_agent_core3 = require("@robota-sdk/agent-core");
|
|
782
627
|
|
|
783
628
|
// src/ui/background-task-view-model.ts
|
|
@@ -802,7 +647,11 @@ function toBackgroundTaskViewModel(state, partialText) {
|
|
|
802
647
|
lastActivityAt: state.lastActivityAt,
|
|
803
648
|
timeoutReason: state.timeoutReason,
|
|
804
649
|
exitCode: state.result?.exitCode,
|
|
805
|
-
signalCode: state.result?.signalCode
|
|
650
|
+
signalCode: state.result?.signalCode,
|
|
651
|
+
worktreePath: state.worktreePath,
|
|
652
|
+
branchName: state.branchName,
|
|
653
|
+
worktreeStatus: state.worktreeStatus,
|
|
654
|
+
worktreeNextAction: state.worktreeNextAction
|
|
806
655
|
};
|
|
807
656
|
}
|
|
808
657
|
function getBackgroundTaskStatusLabel(state) {
|
|
@@ -967,6 +816,14 @@ var TuiStateManager = class {
|
|
|
967
816
|
this.history = updated.length > MAX_RENDERED_MESSAGES ? updated.slice(-MAX_RENDERED_MESSAGES) : updated;
|
|
968
817
|
this.notify();
|
|
969
818
|
}
|
|
819
|
+
clearHistory() {
|
|
820
|
+
this.history = [];
|
|
821
|
+
this.debouncedStreamNotify.flush();
|
|
822
|
+
this.streamBuf = "";
|
|
823
|
+
this.streamingText = "";
|
|
824
|
+
this.activeTools = [];
|
|
825
|
+
this.notify();
|
|
826
|
+
}
|
|
970
827
|
/** Update pending prompt state */
|
|
971
828
|
setPendingPrompt(prompt) {
|
|
972
829
|
this.pendingPrompt = prompt;
|
|
@@ -1034,128 +891,33 @@ var import_react = require("react");
|
|
|
1034
891
|
var import_node_crypto = require("crypto");
|
|
1035
892
|
var import_agent_core2 = require("@robota-sdk/agent-core");
|
|
1036
893
|
|
|
1037
|
-
// src/
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
message: formatProviderList(settings.currentProvider, settings.providers),
|
|
1045
|
-
success: true
|
|
1046
|
-
};
|
|
1047
|
-
}
|
|
1048
|
-
if (subcommand === "current" || subcommand === "") {
|
|
1049
|
-
return {
|
|
1050
|
-
message: formatCurrentProvider(settings.currentProvider, settings.providers),
|
|
1051
|
-
success: true
|
|
1052
|
-
};
|
|
1053
|
-
}
|
|
1054
|
-
if (subcommand === "use") {
|
|
1055
|
-
return buildProviderSwitch(settings.providers, profileArg);
|
|
1056
|
-
}
|
|
1057
|
-
if (subcommand === "test") {
|
|
1058
|
-
return await testProvider(settings.currentProvider, settings.providers, profileArg, deps);
|
|
1059
|
-
}
|
|
1060
|
-
if (subcommand === "add") {
|
|
1061
|
-
return buildProviderSetup(profileArg, providerDefinitions);
|
|
1062
|
-
}
|
|
1063
|
-
return {
|
|
1064
|
-
message: "Usage: provider [current|list|use <profile>|add <type>|test [profile]]",
|
|
1065
|
-
success: false
|
|
1066
|
-
};
|
|
1067
|
-
}
|
|
1068
|
-
function formatProviderList(currentProvider, providers) {
|
|
1069
|
-
const entries = Object.entries(providers ?? {});
|
|
1070
|
-
if (entries.length === 0) {
|
|
1071
|
-
return "No provider profiles configured.";
|
|
1072
|
-
}
|
|
1073
|
-
return entries.map(([name, profile]) => {
|
|
1074
|
-
const marker = name === currentProvider ? "*" : "-";
|
|
1075
|
-
return `${marker} ${name}: ${profile.type ?? "unknown"} ${profile.model ?? "(no model)"}`;
|
|
1076
|
-
}).join("\n");
|
|
1077
|
-
}
|
|
1078
|
-
function formatCurrentProvider(currentProvider, providers) {
|
|
1079
|
-
if (!currentProvider) {
|
|
1080
|
-
return "No current provider configured.";
|
|
1081
|
-
}
|
|
1082
|
-
const profile = providers?.[currentProvider];
|
|
1083
|
-
if (!profile) {
|
|
1084
|
-
return `Current provider "${currentProvider}" was not found in providers.`;
|
|
1085
|
-
}
|
|
1086
|
-
return [
|
|
1087
|
-
`Current provider: ${currentProvider}`,
|
|
1088
|
-
`Type: ${profile.type ?? "unknown"}`,
|
|
1089
|
-
`Model: ${profile.model ?? "(no model)"}`,
|
|
1090
|
-
...profile.baseURL ? [`Base URL: ${profile.baseURL}`] : []
|
|
1091
|
-
].join("\n");
|
|
1092
|
-
}
|
|
1093
|
-
function buildProviderSwitch(providers, profileName) {
|
|
1094
|
-
if (!profileName) {
|
|
1095
|
-
return { message: "Usage: provider use <profile>", success: false };
|
|
1096
|
-
}
|
|
1097
|
-
if (!providers?.[profileName]) {
|
|
1098
|
-
return { message: `Provider profile "${profileName}" was not found.`, success: false };
|
|
1099
|
-
}
|
|
1100
|
-
return {
|
|
1101
|
-
message: `Provider change requested: ${profileName}`,
|
|
1102
|
-
success: true,
|
|
1103
|
-
data: { providerSwitch: { profile: profileName } }
|
|
1104
|
-
};
|
|
1105
|
-
}
|
|
1106
|
-
function buildProviderSetup(type, providerDefinitions) {
|
|
1107
|
-
if (!type) {
|
|
1108
|
-
return {
|
|
1109
|
-
message: "Provider setup requested. Select a provider to continue.",
|
|
1110
|
-
success: true,
|
|
1111
|
-
data: { providerSetup: {} }
|
|
1112
|
-
};
|
|
1113
|
-
}
|
|
1114
|
-
if ((0, import_agent_core.findProviderDefinition)(providerDefinitions, type) === void 0) {
|
|
1115
|
-
return {
|
|
1116
|
-
message: `Usage: provider add <type>. Supported: ${(0, import_agent_core.formatSupportedProviderTypes)(providerDefinitions)}`,
|
|
1117
|
-
success: false
|
|
1118
|
-
};
|
|
1119
|
-
}
|
|
1120
|
-
return {
|
|
1121
|
-
message: `Provider setup requested: ${type}`,
|
|
1122
|
-
success: true,
|
|
1123
|
-
data: { providerSetup: { type } }
|
|
1124
|
-
};
|
|
894
|
+
// src/plugins/plugin-command-source-loader.ts
|
|
895
|
+
var import_node_os = require("os");
|
|
896
|
+
var import_node_path4 = require("path");
|
|
897
|
+
var import_agent_sdk4 = require("@robota-sdk/agent-sdk");
|
|
898
|
+
var PLUGIN_SOURCE_NAME = "plugin";
|
|
899
|
+
function getHomeDir() {
|
|
900
|
+
return process.env.HOME ?? (0, import_node_os.homedir)();
|
|
1125
901
|
}
|
|
1126
|
-
|
|
1127
|
-
const
|
|
1128
|
-
|
|
1129
|
-
return { message: "No provider profile selected.", success: false };
|
|
1130
|
-
}
|
|
1131
|
-
const profile = providers?.[profileName];
|
|
1132
|
-
if (!profile) {
|
|
1133
|
-
return { message: `Provider profile "${profileName}" was not found.`, success: false };
|
|
1134
|
-
}
|
|
902
|
+
function reloadPluginCommandSource(registry) {
|
|
903
|
+
const pluginsDir = (0, import_node_path4.join)(getHomeDir(), ".robota", "plugins");
|
|
904
|
+
const loader = new import_agent_sdk4.BundlePluginLoader(pluginsDir);
|
|
1135
905
|
try {
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
906
|
+
const plugins = loader.loadPluginsSync();
|
|
907
|
+
if (plugins.length === 0) {
|
|
908
|
+
registry.replaceSource(PLUGIN_SOURCE_NAME);
|
|
909
|
+
return 0;
|
|
910
|
+
}
|
|
911
|
+
registry.replaceSource(PLUGIN_SOURCE_NAME, new import_agent_sdk4.PluginCommandSource(plugins));
|
|
912
|
+
return plugins.length;
|
|
913
|
+
} catch {
|
|
914
|
+
registry.replaceSource(PLUGIN_SOURCE_NAME);
|
|
915
|
+
return 0;
|
|
1141
916
|
}
|
|
1142
|
-
const providerDefinitions = deps.providerDefinitions ?? DEFAULT_PROVIDER_DEFINITIONS;
|
|
1143
|
-
const definition = profile.type ? (0, import_agent_core.findProviderDefinition)(providerDefinitions, profile.type) : void 0;
|
|
1144
|
-
const probe = deps.probe ?? definition?.probeProfile ?? probeProviderProfile;
|
|
1145
|
-
const result = await probe(profile);
|
|
1146
|
-
return {
|
|
1147
|
-
message: result.ok ? `Provider "${profileName}" test passed: ${result.message}` : `Provider "${profileName}" test failed: ${result.message}; manual configuration can continue.`,
|
|
1148
|
-
success: true,
|
|
1149
|
-
data: { providerTest: { profile: profileName } }
|
|
1150
|
-
};
|
|
1151
|
-
}
|
|
1152
|
-
async function probeProviderProfile(profile) {
|
|
1153
|
-
void profile;
|
|
1154
|
-
return { ok: true, message: "Profile fields are valid; no endpoint probe configured." };
|
|
1155
917
|
}
|
|
1156
918
|
|
|
1157
919
|
// src/ui/hooks/useSlashRouting.ts
|
|
1158
|
-
function useSlashRouting(
|
|
920
|
+
function useSlashRouting(interactiveSession, registry, manager) {
|
|
1159
921
|
return (0, import_react.useCallback)(
|
|
1160
922
|
async (input) => {
|
|
1161
923
|
manager.onUserTurnAccepted();
|
|
@@ -1167,70 +929,32 @@ function useSlashRouting(cwd, interactiveSession, registry, manager, providerDef
|
|
|
1167
929
|
const parts = input.slice(1).split(/\s+/);
|
|
1168
930
|
const cmd = parts[0]?.toLowerCase() ?? "";
|
|
1169
931
|
const args = parts.slice(1).join(" ");
|
|
1170
|
-
if (cmd === "provider") {
|
|
1171
|
-
await routeProviderCommand(cwd, args, interactiveSession, manager, providerDefinitions);
|
|
1172
|
-
return;
|
|
1173
|
-
}
|
|
1174
932
|
const result = await interactiveSession.executeCommand(cmd, args);
|
|
1175
933
|
if (result) {
|
|
1176
|
-
applySystemCommandResult(result, interactiveSession, manager);
|
|
934
|
+
applySystemCommandResult(result, interactiveSession, registry, manager);
|
|
1177
935
|
return;
|
|
1178
936
|
}
|
|
1179
937
|
if (await routeSkillCommand(input, cmd, registry, interactiveSession, manager)) {
|
|
1180
938
|
return;
|
|
1181
939
|
}
|
|
1182
|
-
if (routeTuiCommand(cmd, interactiveSession)) {
|
|
1183
|
-
return;
|
|
1184
|
-
}
|
|
1185
940
|
manager.addEntry(
|
|
1186
941
|
(0, import_agent_core2.messageToHistoryEntry)(
|
|
1187
942
|
(0, import_agent_core2.createSystemMessage)(`Unknown command "/${cmd}". Type /help for help.`)
|
|
1188
943
|
)
|
|
1189
944
|
);
|
|
1190
945
|
},
|
|
1191
|
-
[
|
|
946
|
+
[interactiveSession, registry, manager]
|
|
1192
947
|
);
|
|
1193
948
|
}
|
|
1194
|
-
|
|
1195
|
-
const
|
|
949
|
+
function applySystemCommandResult(result, interactiveSession, registry, manager) {
|
|
950
|
+
const pendingEffects = applyImmediateCommandEffects(result.effects, registry, manager);
|
|
1196
951
|
manager.addEntry((0, import_agent_core2.messageToHistoryEntry)((0, import_agent_core2.createSystemMessage)(result.message)));
|
|
1197
|
-
const providerSwitch = result.data?.providerSwitch;
|
|
1198
|
-
if (providerSwitch?.profile) {
|
|
1199
|
-
getEffects(interactiveSession)._pendingProviderProfile = providerSwitch.profile;
|
|
1200
|
-
}
|
|
1201
|
-
const providerSetup = result.data?.providerSetup;
|
|
1202
|
-
if (providerSetup !== void 0) {
|
|
1203
|
-
getEffects(interactiveSession)._pendingProviderSetup = providerSetup;
|
|
1204
|
-
}
|
|
1205
|
-
}
|
|
1206
|
-
function applySystemCommandResult(result, interactiveSession, manager) {
|
|
1207
|
-
manager.addEntry((0, import_agent_core2.messageToHistoryEntry)((0, import_agent_core2.createSystemMessage)(result.message)));
|
|
1208
|
-
const data = result.data;
|
|
1209
952
|
const effects = getEffects(interactiveSession);
|
|
1210
|
-
if (
|
|
1211
|
-
effects.
|
|
1212
|
-
return;
|
|
953
|
+
if (result.interaction !== void 0) {
|
|
954
|
+
effects._pendingCommandInteraction = result.interaction;
|
|
1213
955
|
}
|
|
1214
|
-
if (
|
|
1215
|
-
effects.
|
|
1216
|
-
return;
|
|
1217
|
-
}
|
|
1218
|
-
if (data?.resetRequested === true) {
|
|
1219
|
-
effects._resetRequested = true;
|
|
1220
|
-
return;
|
|
1221
|
-
}
|
|
1222
|
-
if (data?.triggerResumePicker === true) {
|
|
1223
|
-
effects._triggerResumePicker = true;
|
|
1224
|
-
return;
|
|
1225
|
-
}
|
|
1226
|
-
if (typeof data?.name === "string") {
|
|
1227
|
-
effects._sessionName = data.name;
|
|
1228
|
-
return;
|
|
1229
|
-
}
|
|
1230
|
-
const statusLinePatch = data?.statuslinePatch;
|
|
1231
|
-
if (isStatusLineSettingsPatch(statusLinePatch)) {
|
|
1232
|
-
effects._statusLinePatch = statusLinePatch;
|
|
1233
|
-
return;
|
|
956
|
+
if (pendingEffects.length > 0) {
|
|
957
|
+
effects._pendingCommandEffects = pendingEffects;
|
|
1234
958
|
}
|
|
1235
959
|
const ctx = interactiveSession.getContextState();
|
|
1236
960
|
manager.setContextState({
|
|
@@ -1239,6 +963,22 @@ function applySystemCommandResult(result, interactiveSession, manager) {
|
|
|
1239
963
|
maxTokens: ctx.maxTokens
|
|
1240
964
|
});
|
|
1241
965
|
}
|
|
966
|
+
function applyImmediateCommandEffects(effects, registry, manager) {
|
|
967
|
+
if (effects === void 0 || effects.length === 0) return [];
|
|
968
|
+
const pendingEffects = [];
|
|
969
|
+
for (const effect of effects) {
|
|
970
|
+
if (effect.type === "conversation-history-cleared") {
|
|
971
|
+
manager.clearHistory();
|
|
972
|
+
continue;
|
|
973
|
+
}
|
|
974
|
+
if (effect.type === "plugin-registry-reload-requested") {
|
|
975
|
+
reloadPluginCommandSource(registry);
|
|
976
|
+
continue;
|
|
977
|
+
}
|
|
978
|
+
pendingEffects.push(effect);
|
|
979
|
+
}
|
|
980
|
+
return pendingEffects;
|
|
981
|
+
}
|
|
1242
982
|
async function routeSkillCommand(input, cmd, registry, interactiveSession, manager) {
|
|
1243
983
|
const skillCmd = registry.getCommands().find((c) => c.name === cmd && (c.source === "skill" || c.source === "plugin"));
|
|
1244
984
|
if (!skillCmd) {
|
|
@@ -1262,31 +1002,16 @@ async function routeSkillCommand(input, cmd, registry, interactiveSession, manag
|
|
|
1262
1002
|
manager.setPendingPrompt(interactiveSession.getPendingPrompt());
|
|
1263
1003
|
return true;
|
|
1264
1004
|
}
|
|
1265
|
-
function routeTuiCommand(cmd, interactiveSession) {
|
|
1266
|
-
if (cmd === "exit") {
|
|
1267
|
-
getEffects(interactiveSession)._exitRequested = true;
|
|
1268
|
-
return true;
|
|
1269
|
-
}
|
|
1270
|
-
if (cmd === "plugin") {
|
|
1271
|
-
getEffects(interactiveSession)._triggerPluginTUI = true;
|
|
1272
|
-
return true;
|
|
1273
|
-
}
|
|
1274
|
-
return false;
|
|
1275
|
-
}
|
|
1276
1005
|
function getEffects(interactiveSession) {
|
|
1277
1006
|
return interactiveSession;
|
|
1278
1007
|
}
|
|
1279
|
-
function isStatusLineSettingsPatch(value) {
|
|
1280
|
-
if (value === null || typeof value !== "object" || Array.isArray(value) || value instanceof Date) {
|
|
1281
|
-
return false;
|
|
1282
|
-
}
|
|
1283
|
-
const candidate = value;
|
|
1284
|
-
return (candidate.enabled === void 0 || typeof candidate.enabled === "boolean") && (candidate.gitBranch === void 0 || typeof candidate.gitBranch === "boolean");
|
|
1285
|
-
}
|
|
1286
1008
|
|
|
1287
1009
|
// src/ui/hooks/useInteractiveSession.ts
|
|
1010
|
+
function applyCompactEventToManager(interactiveSession, manager) {
|
|
1011
|
+
manager.syncHistory(interactiveSession.getFullHistory());
|
|
1012
|
+
}
|
|
1288
1013
|
function initializeSession(props, permissionHandler) {
|
|
1289
|
-
const interactiveSession = new
|
|
1014
|
+
const interactiveSession = new import_agent_sdk5.InteractiveSession({
|
|
1290
1015
|
cwd: props.cwd,
|
|
1291
1016
|
provider: props.provider,
|
|
1292
1017
|
permissionMode: props.permissionMode,
|
|
@@ -1298,23 +1023,16 @@ function initializeSession(props, permissionHandler) {
|
|
|
1298
1023
|
sessionName: props.sessionName,
|
|
1299
1024
|
backgroundTaskRunners: props.backgroundTaskRunners,
|
|
1300
1025
|
subagentRunnerFactory: props.subagentRunnerFactory,
|
|
1301
|
-
commandModules: props.commandModules
|
|
1026
|
+
commandModules: props.commandModules,
|
|
1027
|
+
commandHostAdapters: props.commandHostAdapters
|
|
1302
1028
|
});
|
|
1303
|
-
const registry = new
|
|
1304
|
-
registry.
|
|
1029
|
+
const registry = new import_agent_sdk5.CommandRegistry();
|
|
1030
|
+
registry.addModule((0, import_agent_sdk5.createBuiltinCommandModule)());
|
|
1305
1031
|
for (const module2 of props.commandModules ?? []) {
|
|
1306
1032
|
registry.addModule(module2);
|
|
1307
1033
|
}
|
|
1308
|
-
registry.addSource(new
|
|
1309
|
-
|
|
1310
|
-
const loader = new import_agent_sdk.BundlePluginLoader(pluginsDir);
|
|
1311
|
-
try {
|
|
1312
|
-
const plugins = loader.loadPluginsSync();
|
|
1313
|
-
if (plugins.length > 0) {
|
|
1314
|
-
registry.addSource(new import_agent_sdk.PluginCommandSource(plugins));
|
|
1315
|
-
}
|
|
1316
|
-
} catch {
|
|
1317
|
-
}
|
|
1034
|
+
registry.addSource(new import_agent_sdk5.SkillCommandSource(props.cwd));
|
|
1035
|
+
reloadPluginCommandSource(registry);
|
|
1318
1036
|
const manager = new TuiStateManager();
|
|
1319
1037
|
return { interactiveSession, registry, manager };
|
|
1320
1038
|
}
|
|
@@ -1364,6 +1082,7 @@ function useInteractiveSession(props) {
|
|
|
1364
1082
|
}
|
|
1365
1083
|
}
|
|
1366
1084
|
(0, import_react2.useEffect)(() => {
|
|
1085
|
+
const onCompact = () => applyCompactEventToManager(interactiveSession, manager);
|
|
1367
1086
|
interactiveSession.on("text_delta", manager.onTextDelta);
|
|
1368
1087
|
interactiveSession.on("tool_start", manager.onToolStart);
|
|
1369
1088
|
interactiveSession.on("tool_end", manager.onToolEnd);
|
|
@@ -1372,6 +1091,7 @@ function useInteractiveSession(props) {
|
|
|
1372
1091
|
interactiveSession.on("interrupted", manager.onInterrupted);
|
|
1373
1092
|
interactiveSession.on("error", manager.onError);
|
|
1374
1093
|
interactiveSession.on("context_update", manager.onContextUpdate);
|
|
1094
|
+
interactiveSession.on("compact", onCompact);
|
|
1375
1095
|
interactiveSession.on("background_task_event", manager.onBackgroundTaskEvent);
|
|
1376
1096
|
const initCheck = setInterval(() => {
|
|
1377
1097
|
try {
|
|
@@ -1399,6 +1119,7 @@ function useInteractiveSession(props) {
|
|
|
1399
1119
|
interactiveSession.off("interrupted", manager.onInterrupted);
|
|
1400
1120
|
interactiveSession.off("error", manager.onError);
|
|
1401
1121
|
interactiveSession.off("context_update", manager.onContextUpdate);
|
|
1122
|
+
interactiveSession.off("compact", onCompact);
|
|
1402
1123
|
interactiveSession.off("background_task_event", manager.onBackgroundTaskEvent);
|
|
1403
1124
|
};
|
|
1404
1125
|
}, [interactiveSession, manager]);
|
|
@@ -1408,13 +1129,7 @@ function useInteractiveSession(props) {
|
|
|
1408
1129
|
manager.setPendingPrompt(interactiveSession.getPendingPrompt());
|
|
1409
1130
|
}
|
|
1410
1131
|
}, [manager.isThinking, interactiveSession, manager]);
|
|
1411
|
-
const handleSubmit = useSlashRouting(
|
|
1412
|
-
props.cwd,
|
|
1413
|
-
interactiveSession,
|
|
1414
|
-
registry,
|
|
1415
|
-
manager,
|
|
1416
|
-
props.providerDefinitions ?? []
|
|
1417
|
-
);
|
|
1132
|
+
const handleSubmit = useSlashRouting(interactiveSession, registry, manager);
|
|
1418
1133
|
const handleAbort = (0, import_react2.useCallback)(() => {
|
|
1419
1134
|
manager.setAborting(true);
|
|
1420
1135
|
interactiveSession.abort();
|
|
@@ -1442,192 +1157,142 @@ function useInteractiveSession(props) {
|
|
|
1442
1157
|
isThinking: manager.isThinking,
|
|
1443
1158
|
isAborting: manager.isAborting,
|
|
1444
1159
|
isShuttingDown,
|
|
1445
|
-
pendingPrompt: manager.pendingPrompt,
|
|
1446
|
-
backgroundTasks: manager.backgroundTasks,
|
|
1447
|
-
permissionRequest,
|
|
1448
|
-
contextState: manager.contextState,
|
|
1449
|
-
handleSubmit,
|
|
1450
|
-
handleAbort,
|
|
1451
|
-
handleCancelQueue,
|
|
1452
|
-
handleShutdown
|
|
1453
|
-
};
|
|
1454
|
-
}
|
|
1455
|
-
|
|
1456
|
-
// src/ui/hooks/usePluginCallbacks.ts
|
|
1457
|
-
var import_react3 = require("react");
|
|
1458
|
-
var import_node_os4 = require("os");
|
|
1459
|
-
var import_node_path5 = require("path");
|
|
1460
|
-
var import_agent_sdk2 = require("@robota-sdk/agent-sdk");
|
|
1461
|
-
function usePluginCallbacks(cwd) {
|
|
1462
|
-
return (0, import_react3.useMemo)(() => {
|
|
1463
|
-
const home = (0, import_node_os4.homedir)();
|
|
1464
|
-
const pluginsDir = (0, import_node_path5.join)(home, ".robota", "plugins");
|
|
1465
|
-
const userSettingsPath = (0, import_node_path5.join)(home, ".robota", "settings.json");
|
|
1466
|
-
const settingsStore = new import_agent_sdk2.PluginSettingsStore(userSettingsPath);
|
|
1467
|
-
const marketplace = new import_agent_sdk2.MarketplaceClient({ pluginsDir });
|
|
1468
|
-
const installer = new import_agent_sdk2.BundlePluginInstaller({
|
|
1469
|
-
pluginsDir,
|
|
1470
|
-
settingsStore,
|
|
1471
|
-
marketplaceClient: marketplace
|
|
1472
|
-
});
|
|
1473
|
-
const loader = new import_agent_sdk2.BundlePluginLoader(pluginsDir);
|
|
1474
|
-
return {
|
|
1475
|
-
listInstalled: async () => {
|
|
1476
|
-
const plugins = await loader.loadAll();
|
|
1477
|
-
const enabledMap = settingsStore.getEnabledPlugins();
|
|
1478
|
-
return plugins.map((p) => {
|
|
1479
|
-
const parts = p.pluginDir.split("/");
|
|
1480
|
-
const cacheIdx = parts.indexOf("cache");
|
|
1481
|
-
const marketplaceName = cacheIdx >= 0 ? parts[cacheIdx + 1] : "";
|
|
1482
|
-
const fullId = marketplaceName ? `${p.manifest.name}@${marketplaceName}` : p.manifest.name;
|
|
1483
|
-
return {
|
|
1484
|
-
name: fullId,
|
|
1485
|
-
description: p.manifest.description,
|
|
1486
|
-
enabled: enabledMap[fullId] !== false && enabledMap[p.manifest.name] !== false
|
|
1487
|
-
};
|
|
1488
|
-
});
|
|
1489
|
-
},
|
|
1490
|
-
listAvailablePlugins: async (marketplaceName) => {
|
|
1491
|
-
let manifest;
|
|
1492
|
-
try {
|
|
1493
|
-
manifest = marketplace.fetchManifest(marketplaceName);
|
|
1494
|
-
} catch {
|
|
1495
|
-
return [];
|
|
1496
|
-
}
|
|
1497
|
-
const installed = installer.getInstalledPlugins();
|
|
1498
|
-
const installedNames = new Set(Object.values(installed).map((r) => r.pluginName));
|
|
1499
|
-
return manifest.plugins.map((p) => ({
|
|
1500
|
-
name: p.name,
|
|
1501
|
-
description: p.description,
|
|
1502
|
-
installed: installedNames.has(p.name)
|
|
1503
|
-
}));
|
|
1504
|
-
},
|
|
1505
|
-
install: async (pluginId, scope) => {
|
|
1506
|
-
const [name, marketplaceName] = pluginId.split("@");
|
|
1507
|
-
if (!name || !marketplaceName) {
|
|
1508
|
-
throw new Error("Plugin ID must be in format: name@marketplace");
|
|
1509
|
-
}
|
|
1510
|
-
if (scope === "project") {
|
|
1511
|
-
const projectPluginsDir = (0, import_node_path5.join)(cwd, ".robota", "plugins");
|
|
1512
|
-
const projectInstaller = new import_agent_sdk2.BundlePluginInstaller({
|
|
1513
|
-
pluginsDir: projectPluginsDir,
|
|
1514
|
-
settingsStore,
|
|
1515
|
-
marketplaceClient: marketplace
|
|
1516
|
-
});
|
|
1517
|
-
await projectInstaller.install(name, marketplaceName);
|
|
1518
|
-
} else {
|
|
1519
|
-
await installer.install(name, marketplaceName);
|
|
1520
|
-
}
|
|
1521
|
-
},
|
|
1522
|
-
uninstall: async (pluginId) => {
|
|
1523
|
-
await installer.uninstall(pluginId);
|
|
1524
|
-
},
|
|
1525
|
-
enable: async (pluginId) => {
|
|
1526
|
-
await installer.enable(pluginId);
|
|
1527
|
-
},
|
|
1528
|
-
disable: async (pluginId) => {
|
|
1529
|
-
await installer.disable(pluginId);
|
|
1530
|
-
},
|
|
1531
|
-
marketplaceAdd: async (source) => {
|
|
1532
|
-
if (source.includes("/") && !source.includes(":")) {
|
|
1533
|
-
return marketplace.addMarketplace({ type: "github", repo: source });
|
|
1534
|
-
} else {
|
|
1535
|
-
return marketplace.addMarketplace({ type: "git", url: source });
|
|
1536
|
-
}
|
|
1537
|
-
},
|
|
1538
|
-
marketplaceRemove: async (name) => {
|
|
1539
|
-
const installedFromMarketplace = installer.getPluginsByMarketplace(name);
|
|
1540
|
-
for (const record of installedFromMarketplace) {
|
|
1541
|
-
await installer.uninstall(`${record.pluginName}@${record.marketplace}`);
|
|
1542
|
-
}
|
|
1543
|
-
marketplace.removeMarketplace(name);
|
|
1544
|
-
},
|
|
1545
|
-
marketplaceUpdate: async (name) => {
|
|
1546
|
-
marketplace.updateMarketplace(name);
|
|
1547
|
-
},
|
|
1548
|
-
marketplaceList: async () => {
|
|
1549
|
-
return marketplace.listMarketplaces().map((m) => ({
|
|
1550
|
-
name: m.name,
|
|
1551
|
-
type: m.source.type
|
|
1552
|
-
}));
|
|
1553
|
-
},
|
|
1554
|
-
reloadPlugins: async () => {
|
|
1555
|
-
}
|
|
1556
|
-
};
|
|
1557
|
-
}, [cwd]);
|
|
1160
|
+
pendingPrompt: manager.pendingPrompt,
|
|
1161
|
+
backgroundTasks: manager.backgroundTasks,
|
|
1162
|
+
permissionRequest,
|
|
1163
|
+
contextState: manager.contextState,
|
|
1164
|
+
handleSubmit,
|
|
1165
|
+
handleAbort,
|
|
1166
|
+
handleCancelQueue,
|
|
1167
|
+
handleShutdown
|
|
1168
|
+
};
|
|
1558
1169
|
}
|
|
1559
1170
|
|
|
1560
|
-
// src/ui/hooks/
|
|
1561
|
-
var
|
|
1562
|
-
var import_ink = require("ink");
|
|
1563
|
-
var import_agent_core4 = require("@robota-sdk/agent-core");
|
|
1171
|
+
// src/ui/hooks/usePluginCallbacks.ts
|
|
1172
|
+
var import_react3 = require("react");
|
|
1564
1173
|
|
|
1565
|
-
// src/
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
const
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1174
|
+
// src/plugins/plugin-command-adapter.ts
|
|
1175
|
+
var import_node_os2 = require("os");
|
|
1176
|
+
var import_node_path5 = require("path");
|
|
1177
|
+
var import_agent_sdk6 = require("@robota-sdk/agent-sdk");
|
|
1178
|
+
function createCliPluginServices(cwd) {
|
|
1179
|
+
const home = (0, import_node_os2.homedir)();
|
|
1180
|
+
const pluginsDir = (0, import_node_path5.join)(home, ".robota", "plugins");
|
|
1181
|
+
const userSettingsPath = (0, import_node_path5.join)(home, ".robota", "settings.json");
|
|
1182
|
+
const settingsStore = new import_agent_sdk6.PluginSettingsStore(userSettingsPath);
|
|
1183
|
+
const marketplace = new import_agent_sdk6.MarketplaceClient({ pluginsDir });
|
|
1184
|
+
const installer = new import_agent_sdk6.BundlePluginInstaller({
|
|
1185
|
+
pluginsDir,
|
|
1186
|
+
settingsStore,
|
|
1187
|
+
marketplaceClient: marketplace
|
|
1188
|
+
});
|
|
1189
|
+
const loader = new import_agent_sdk6.BundlePluginLoader(pluginsDir);
|
|
1190
|
+
return {
|
|
1191
|
+
cwd,
|
|
1192
|
+
marketplace,
|
|
1193
|
+
installer,
|
|
1194
|
+
loader,
|
|
1195
|
+
settingsStore
|
|
1578
1196
|
};
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
};
|
|
1197
|
+
}
|
|
1198
|
+
async function listInstalledPlugins(services) {
|
|
1199
|
+
const plugins = await services.loader.loadAll();
|
|
1200
|
+
const enabledMap = services.settingsStore.getEnabledPlugins();
|
|
1201
|
+
return plugins.map((plugin) => {
|
|
1202
|
+
const parts = plugin.pluginDir.split("/");
|
|
1203
|
+
const cacheIdx = parts.indexOf("cache");
|
|
1204
|
+
const marketplaceName = cacheIdx >= 0 ? parts[cacheIdx + 1] ?? "" : "";
|
|
1205
|
+
const fullId = marketplaceName ? `${plugin.manifest.name}@${marketplaceName}` : plugin.manifest.name;
|
|
1588
1206
|
return {
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1207
|
+
name: fullId,
|
|
1208
|
+
description: plugin.manifest.description,
|
|
1209
|
+
enabled: enabledMap[fullId] !== false && enabledMap[plugin.manifest.name] !== false
|
|
1592
1210
|
};
|
|
1211
|
+
});
|
|
1212
|
+
}
|
|
1213
|
+
async function listAvailablePlugins(services, marketplaceName) {
|
|
1214
|
+
let manifest;
|
|
1215
|
+
try {
|
|
1216
|
+
manifest = services.marketplace.fetchManifest(marketplaceName);
|
|
1217
|
+
} catch {
|
|
1218
|
+
return [];
|
|
1219
|
+
}
|
|
1220
|
+
const installed = services.installer.getInstalledPlugins();
|
|
1221
|
+
const installedNames = new Set(Object.values(installed).map((record) => record.pluginName));
|
|
1222
|
+
return manifest.plugins.map((plugin) => ({
|
|
1223
|
+
name: plugin.name,
|
|
1224
|
+
description: plugin.description,
|
|
1225
|
+
installed: installedNames.has(plugin.name)
|
|
1226
|
+
}));
|
|
1227
|
+
}
|
|
1228
|
+
async function installPlugin(services, pluginId, scope) {
|
|
1229
|
+
const [name, marketplaceName] = pluginId.split("@");
|
|
1230
|
+
if (!name || !marketplaceName) {
|
|
1231
|
+
throw new Error("Plugin ID must be in format: name@marketplace");
|
|
1232
|
+
}
|
|
1233
|
+
if (scope === "project") {
|
|
1234
|
+
const projectPluginsDir = (0, import_node_path5.join)(services.cwd, ".robota", "plugins");
|
|
1235
|
+
const projectInstaller = new import_agent_sdk6.BundlePluginInstaller({
|
|
1236
|
+
pluginsDir: projectPluginsDir,
|
|
1237
|
+
settingsStore: services.settingsStore,
|
|
1238
|
+
marketplaceClient: services.marketplace
|
|
1239
|
+
});
|
|
1240
|
+
await projectInstaller.install(name, marketplaceName);
|
|
1241
|
+
return;
|
|
1593
1242
|
}
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1243
|
+
await services.installer.install(name, marketplaceName);
|
|
1244
|
+
}
|
|
1245
|
+
async function removeMarketplace(services, name) {
|
|
1246
|
+
const installedFromMarketplace = services.installer.getPluginsByMarketplace(name);
|
|
1247
|
+
for (const record of installedFromMarketplace) {
|
|
1248
|
+
await services.installer.uninstall(`${record.pluginName}@${record.marketplace}`);
|
|
1597
1249
|
}
|
|
1598
|
-
|
|
1599
|
-
...state,
|
|
1600
|
-
flow: result.state
|
|
1601
|
-
};
|
|
1602
|
-
return { status: "prompt", state: nextState, prompt: toProviderSetupStepPrompt(result.state) };
|
|
1250
|
+
services.marketplace.removeMarketplace(name);
|
|
1603
1251
|
}
|
|
1604
|
-
function
|
|
1605
|
-
return {
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
value: definition.type,
|
|
1610
|
-
label: formatProviderSetupChoiceLabel(definition)
|
|
1611
|
-
})),
|
|
1612
|
-
maxVisible: 6
|
|
1613
|
-
};
|
|
1252
|
+
function listMarketplaces(services) {
|
|
1253
|
+
return services.marketplace.listMarketplaces().map((marketplaceEntry) => ({
|
|
1254
|
+
name: marketplaceEntry.name,
|
|
1255
|
+
type: marketplaceEntry.source.type
|
|
1256
|
+
}));
|
|
1614
1257
|
}
|
|
1615
|
-
function
|
|
1616
|
-
const
|
|
1258
|
+
function createCliPluginCommandAdapter(cwd) {
|
|
1259
|
+
const services = createCliPluginServices(cwd);
|
|
1617
1260
|
return {
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1261
|
+
listInstalled: () => listInstalledPlugins(services),
|
|
1262
|
+
listAvailablePlugins: (marketplaceName) => listAvailablePlugins(services, marketplaceName),
|
|
1263
|
+
install: (pluginId, scope) => installPlugin(services, pluginId, scope),
|
|
1264
|
+
uninstall: async (pluginId) => services.installer.uninstall(pluginId),
|
|
1265
|
+
enable: async (pluginId) => services.installer.enable(pluginId),
|
|
1266
|
+
disable: async (pluginId) => services.installer.disable(pluginId),
|
|
1267
|
+
marketplaceAdd: async (source) => {
|
|
1268
|
+
if (source.includes("/") && !source.includes(":")) {
|
|
1269
|
+
return services.marketplace.addMarketplace({ type: "github", repo: source });
|
|
1270
|
+
}
|
|
1271
|
+
return services.marketplace.addMarketplace({ type: "git", url: source });
|
|
1272
|
+
},
|
|
1273
|
+
marketplaceRemove: (name) => removeMarketplace(services, name),
|
|
1274
|
+
marketplaceUpdate: async (name) => services.marketplace.updateMarketplace(name),
|
|
1275
|
+
marketplaceList: async () => listMarketplaces(services),
|
|
1276
|
+
reloadPlugins: async () => ({
|
|
1277
|
+
loadedPluginCount: (await services.loader.loadAll()).length
|
|
1278
|
+
})
|
|
1624
1279
|
};
|
|
1625
1280
|
}
|
|
1626
1281
|
|
|
1282
|
+
// src/ui/hooks/usePluginCallbacks.ts
|
|
1283
|
+
function usePluginCallbacks(cwd) {
|
|
1284
|
+
return (0, import_react3.useMemo)(() => createCliPluginCommandAdapter(cwd), [cwd]);
|
|
1285
|
+
}
|
|
1286
|
+
|
|
1287
|
+
// src/ui/hooks/useSideEffects.ts
|
|
1288
|
+
var import_react4 = require("react");
|
|
1289
|
+
var import_ink = require("ink");
|
|
1290
|
+
var import_agent_core6 = require("@robota-sdk/agent-core");
|
|
1291
|
+
|
|
1627
1292
|
// src/utils/statusline-settings.ts
|
|
1293
|
+
var import_agent_sdk7 = require("@robota-sdk/agent-sdk");
|
|
1628
1294
|
var DEFAULT_STATUS_LINE_SETTINGS = {
|
|
1629
|
-
|
|
1630
|
-
gitBranch: true
|
|
1295
|
+
...import_agent_sdk7.DEFAULT_STATUS_LINE_COMMAND_SETTINGS
|
|
1631
1296
|
};
|
|
1632
1297
|
function readStatusLineSettings(settings) {
|
|
1633
1298
|
const raw = settings.statusline;
|
|
@@ -1662,39 +1327,192 @@ function applyPendingStatusLinePatch(sideEffects, setStatusLineSettings) {
|
|
|
1662
1327
|
return true;
|
|
1663
1328
|
}
|
|
1664
1329
|
|
|
1330
|
+
// src/ui/hooks/command-effect-handler.ts
|
|
1331
|
+
var import_agent_sdk8 = require("@robota-sdk/agent-sdk");
|
|
1332
|
+
var import_agent_core4 = require("@robota-sdk/agent-core");
|
|
1333
|
+
function applyCommandEffects(effects, sideEffects, deps) {
|
|
1334
|
+
for (const effect of effects) {
|
|
1335
|
+
if (effect.type === "model-change-requested") {
|
|
1336
|
+
deps.requestModelChange(effect.modelId);
|
|
1337
|
+
return true;
|
|
1338
|
+
}
|
|
1339
|
+
if (effect.type === "language-change-requested") {
|
|
1340
|
+
applyLanguageEffect(effect.language, deps);
|
|
1341
|
+
return true;
|
|
1342
|
+
}
|
|
1343
|
+
if (effect.type === "settings-reset-requested") {
|
|
1344
|
+
applySettingsResetEffect(deps);
|
|
1345
|
+
return true;
|
|
1346
|
+
}
|
|
1347
|
+
if (effect.type === "session-exit-requested") {
|
|
1348
|
+
deps.requestShutdown(
|
|
1349
|
+
effect.reason ?? "prompt_input_exit",
|
|
1350
|
+
effect.message ?? "User requested exit"
|
|
1351
|
+
);
|
|
1352
|
+
return true;
|
|
1353
|
+
}
|
|
1354
|
+
if (effect.type === "session-restart-requested") {
|
|
1355
|
+
deps.requestShutdown(effect.reason, effect.message);
|
|
1356
|
+
return true;
|
|
1357
|
+
}
|
|
1358
|
+
if (effect.type === "plugin-tui-requested") {
|
|
1359
|
+
deps.openPluginTUI();
|
|
1360
|
+
return true;
|
|
1361
|
+
}
|
|
1362
|
+
if (effect.type === "session-picker-requested") {
|
|
1363
|
+
deps.openSessionPicker();
|
|
1364
|
+
return true;
|
|
1365
|
+
}
|
|
1366
|
+
if (effect.type === "session-renamed") {
|
|
1367
|
+
deps.renameSession(effect.name);
|
|
1368
|
+
return true;
|
|
1369
|
+
}
|
|
1370
|
+
if (effect.type === "statusline-settings-patch") {
|
|
1371
|
+
if ((0, import_agent_sdk8.isStatusLineCommandSettingsPatch)(effect.patch)) {
|
|
1372
|
+
sideEffects._statusLinePatch = effect.patch;
|
|
1373
|
+
if (deps.applyStatusLinePatch(effect.patch)) return true;
|
|
1374
|
+
}
|
|
1375
|
+
}
|
|
1376
|
+
}
|
|
1377
|
+
return false;
|
|
1378
|
+
}
|
|
1379
|
+
function applyLanguageEffect(language, deps) {
|
|
1380
|
+
const settingsPath = getUserSettingsPath();
|
|
1381
|
+
const settings = readSettings(settingsPath);
|
|
1382
|
+
settings.language = language;
|
|
1383
|
+
writeSettings(settingsPath, settings);
|
|
1384
|
+
deps.addEntry(
|
|
1385
|
+
(0, import_agent_core4.messageToHistoryEntry)((0, import_agent_core4.createSystemMessage)(`Language set to "${language}". Restarting...`))
|
|
1386
|
+
);
|
|
1387
|
+
deps.requestShutdown("other", "Language change restart");
|
|
1388
|
+
}
|
|
1389
|
+
function applySettingsResetEffect(deps) {
|
|
1390
|
+
const settingsPath = getUserSettingsPath();
|
|
1391
|
+
if (deleteSettings(settingsPath)) {
|
|
1392
|
+
deps.addEntry(
|
|
1393
|
+
(0, import_agent_core4.messageToHistoryEntry)((0, import_agent_core4.createSystemMessage)(`Deleted ${settingsPath}. Exiting...`))
|
|
1394
|
+
);
|
|
1395
|
+
} else {
|
|
1396
|
+
deps.addEntry((0, import_agent_core4.messageToHistoryEntry)((0, import_agent_core4.createSystemMessage)("No user settings found.")));
|
|
1397
|
+
}
|
|
1398
|
+
deps.requestShutdown("other", "Reset settings restart");
|
|
1399
|
+
}
|
|
1400
|
+
|
|
1401
|
+
// src/ui/hooks/model-change-side-effect.ts
|
|
1402
|
+
var import_agent_core5 = require("@robota-sdk/agent-core");
|
|
1403
|
+
function formatModelChangeConfirmationMessage(modelId) {
|
|
1404
|
+
return `Change model to ${(0, import_agent_core5.getModelName)(modelId)}? This will exit the current session so the next session uses it.`;
|
|
1405
|
+
}
|
|
1406
|
+
function formatModelChangeExitMessage(modelId) {
|
|
1407
|
+
return `Model changed to ${(0, import_agent_core5.getModelName)(modelId)}. Exiting so the next session uses it.`;
|
|
1408
|
+
}
|
|
1409
|
+
function applyConfirmedModelChange(deps) {
|
|
1410
|
+
const applyModelChange = deps.applyModelChange ?? applyActiveModelChange;
|
|
1411
|
+
const options = deps.providerOverride !== void 0 ? { providerOverride: deps.providerOverride } : void 0;
|
|
1412
|
+
try {
|
|
1413
|
+
applyModelChange(deps.cwd, deps.modelId, options);
|
|
1414
|
+
deps.addEntry(
|
|
1415
|
+
(0, import_agent_core5.messageToHistoryEntry)((0, import_agent_core5.createSystemMessage)(formatModelChangeExitMessage(deps.modelId)))
|
|
1416
|
+
);
|
|
1417
|
+
deps.requestShutdown("other", "Model change applied");
|
|
1418
|
+
} catch (error) {
|
|
1419
|
+
deps.addEntry(
|
|
1420
|
+
(0, import_agent_core5.messageToHistoryEntry)(
|
|
1421
|
+
(0, import_agent_core5.createSystemMessage)(`Failed: ${error instanceof Error ? error.message : String(error)}`)
|
|
1422
|
+
)
|
|
1423
|
+
);
|
|
1424
|
+
}
|
|
1425
|
+
}
|
|
1426
|
+
function addModelChangeCancelledMessage(addEntry) {
|
|
1427
|
+
addEntry((0, import_agent_core5.messageToHistoryEntry)((0, import_agent_core5.createSystemMessage)("Model change cancelled.")));
|
|
1428
|
+
}
|
|
1429
|
+
|
|
1665
1430
|
// src/ui/hooks/useSideEffects.ts
|
|
1666
1431
|
var EXIT_DELAY_MS = 500;
|
|
1667
1432
|
function useSideEffects({
|
|
1668
1433
|
cwd,
|
|
1434
|
+
providerOverride,
|
|
1669
1435
|
interactiveSession,
|
|
1670
1436
|
addEntry,
|
|
1671
1437
|
baseHandleSubmit,
|
|
1672
1438
|
setSessionName,
|
|
1673
|
-
setStatusLineSettings
|
|
1674
|
-
providerDefinitions
|
|
1439
|
+
setStatusLineSettings
|
|
1675
1440
|
}) {
|
|
1676
1441
|
const { exit } = (0, import_ink.useApp)();
|
|
1677
1442
|
const [pendingModelId, setPendingModelId] = (0, import_react4.useState)(null);
|
|
1678
1443
|
const pendingModelChangeRef = (0, import_react4.useRef)(null);
|
|
1679
|
-
const [pendingProviderProfile, setPendingProviderProfile] = (0, import_react4.useState)(null);
|
|
1680
|
-
const pendingProviderProfileRef = (0, import_react4.useRef)(null);
|
|
1681
1444
|
const [pendingInteractionPrompt, setPendingInteractionPrompt] = (0, import_react4.useState)(null);
|
|
1682
|
-
const
|
|
1445
|
+
const commandInteractionRef = (0, import_react4.useRef)(null);
|
|
1683
1446
|
const [showPluginTUI, setShowPluginTUI] = (0, import_react4.useState)(false);
|
|
1684
1447
|
const [showSessionPicker, setShowSessionPicker] = (0, import_react4.useState)(false);
|
|
1685
1448
|
const requestShutdown = (0, import_react4.useCallback)(
|
|
1686
1449
|
(reason, message) => {
|
|
1687
|
-
addEntry((0,
|
|
1450
|
+
addEntry((0, import_agent_core6.messageToHistoryEntry)((0, import_agent_core6.createSystemMessage)("Shutting down...")));
|
|
1688
1451
|
setTimeout(() => {
|
|
1689
1452
|
void interactiveSession.shutdown({ reason, message }).finally(() => exit());
|
|
1690
1453
|
}, EXIT_DELAY_MS);
|
|
1691
1454
|
},
|
|
1692
1455
|
[interactiveSession, addEntry, exit]
|
|
1693
1456
|
);
|
|
1457
|
+
const applyEffects = (0, import_react4.useCallback)(
|
|
1458
|
+
(effects, sideEffects) => applyCommandEffects(effects, sideEffects, {
|
|
1459
|
+
addEntry,
|
|
1460
|
+
requestShutdown,
|
|
1461
|
+
requestModelChange: (modelId) => {
|
|
1462
|
+
pendingModelChangeRef.current = modelId;
|
|
1463
|
+
setPendingModelId(modelId);
|
|
1464
|
+
},
|
|
1465
|
+
openPluginTUI: () => setShowPluginTUI(true),
|
|
1466
|
+
openSessionPicker: () => setShowSessionPicker(true),
|
|
1467
|
+
renameSession: (name) => {
|
|
1468
|
+
interactiveSession.setName(name);
|
|
1469
|
+
setSessionName(name);
|
|
1470
|
+
},
|
|
1471
|
+
applyStatusLinePatch: () => applyPendingStatusLinePatch(sideEffects, setStatusLineSettings)
|
|
1472
|
+
}),
|
|
1473
|
+
[addEntry, interactiveSession, requestShutdown, setSessionName, setStatusLineSettings]
|
|
1474
|
+
);
|
|
1475
|
+
const applyCommandResult = (0, import_react4.useCallback)(
|
|
1476
|
+
(result) => {
|
|
1477
|
+
if (result.message.length > 0) {
|
|
1478
|
+
addEntry((0, import_agent_core6.messageToHistoryEntry)((0, import_agent_core6.createSystemMessage)(result.message)));
|
|
1479
|
+
}
|
|
1480
|
+
if (result.interaction !== void 0) {
|
|
1481
|
+
commandInteractionRef.current = result.interaction;
|
|
1482
|
+
setPendingInteractionPrompt(result.interaction.prompt);
|
|
1483
|
+
return;
|
|
1484
|
+
}
|
|
1485
|
+
commandInteractionRef.current = null;
|
|
1486
|
+
setPendingInteractionPrompt(null);
|
|
1487
|
+
if (result.effects !== void 0 && result.effects.length > 0) {
|
|
1488
|
+
applyEffects(result.effects, interactiveSession);
|
|
1489
|
+
}
|
|
1490
|
+
},
|
|
1491
|
+
[addEntry, applyEffects, interactiveSession]
|
|
1492
|
+
);
|
|
1493
|
+
const applyQueuedCommandState = (0, import_react4.useCallback)(
|
|
1494
|
+
(sideEffects) => {
|
|
1495
|
+
if (sideEffects._pendingCommandInteraction !== void 0) {
|
|
1496
|
+
const interaction = sideEffects._pendingCommandInteraction;
|
|
1497
|
+
delete sideEffects._pendingCommandInteraction;
|
|
1498
|
+
commandInteractionRef.current = interaction;
|
|
1499
|
+
setPendingInteractionPrompt(interaction.prompt);
|
|
1500
|
+
return true;
|
|
1501
|
+
}
|
|
1502
|
+
if (sideEffects._pendingCommandEffects !== void 0) {
|
|
1503
|
+
const effects = sideEffects._pendingCommandEffects;
|
|
1504
|
+
delete sideEffects._pendingCommandEffects;
|
|
1505
|
+
return applyEffects(effects, sideEffects);
|
|
1506
|
+
}
|
|
1507
|
+
return false;
|
|
1508
|
+
},
|
|
1509
|
+
[applyEffects]
|
|
1510
|
+
);
|
|
1694
1511
|
const handleSubmit = (0, import_react4.useCallback)(
|
|
1695
1512
|
async (input) => {
|
|
1696
1513
|
await baseHandleSubmit(input);
|
|
1697
1514
|
const sideEffects = interactiveSession;
|
|
1515
|
+
if (applyQueuedCommandState(sideEffects)) return;
|
|
1698
1516
|
if (sideEffects._pendingModelId) {
|
|
1699
1517
|
const modelId = sideEffects._pendingModelId;
|
|
1700
1518
|
delete sideEffects._pendingModelId;
|
|
@@ -1702,69 +1520,25 @@ function useSideEffects({
|
|
|
1702
1520
|
setPendingModelId(modelId);
|
|
1703
1521
|
return;
|
|
1704
1522
|
}
|
|
1705
|
-
if (sideEffects._pendingLanguage) {
|
|
1706
|
-
const lang = sideEffects._pendingLanguage;
|
|
1707
|
-
delete sideEffects._pendingLanguage;
|
|
1708
|
-
const settingsPath = getUserSettingsPath();
|
|
1709
|
-
const settings = readSettings(settingsPath);
|
|
1710
|
-
settings.language = lang;
|
|
1711
|
-
writeSettings(settingsPath, settings);
|
|
1712
|
-
addEntry(
|
|
1713
|
-
(0, import_agent_core4.messageToHistoryEntry)((0, import_agent_core4.createSystemMessage)(`Language set to "${lang}". Restarting...`))
|
|
1714
|
-
);
|
|
1715
|
-
requestShutdown("other", "Language change restart");
|
|
1716
|
-
return;
|
|
1717
|
-
}
|
|
1718
|
-
if (sideEffects._pendingProviderProfile) {
|
|
1719
|
-
const profile = sideEffects._pendingProviderProfile;
|
|
1720
|
-
delete sideEffects._pendingProviderProfile;
|
|
1721
|
-
pendingProviderProfileRef.current = profile;
|
|
1722
|
-
setPendingProviderProfile(profile);
|
|
1723
|
-
return;
|
|
1724
|
-
}
|
|
1725
|
-
if (sideEffects._pendingProviderSetup !== void 0) {
|
|
1726
|
-
const setup = sideEffects._pendingProviderSetup;
|
|
1727
|
-
delete sideEffects._pendingProviderSetup;
|
|
1728
|
-
const result = startProviderSetupInteraction(providerDefinitions, setup.type);
|
|
1729
|
-
if (result.status === "prompt") {
|
|
1730
|
-
providerSetupInteractionRef.current = result.state;
|
|
1731
|
-
setPendingInteractionPrompt(result.prompt);
|
|
1732
|
-
}
|
|
1733
|
-
return;
|
|
1734
|
-
}
|
|
1735
1523
|
if (sideEffects._resetRequested) {
|
|
1736
1524
|
delete sideEffects._resetRequested;
|
|
1737
|
-
|
|
1738
|
-
if (deleteSettings(settingsPath)) {
|
|
1739
|
-
addEntry(
|
|
1740
|
-
(0, import_agent_core4.messageToHistoryEntry)((0, import_agent_core4.createSystemMessage)(`Deleted ${settingsPath}. Exiting...`))
|
|
1741
|
-
);
|
|
1742
|
-
} else {
|
|
1743
|
-
addEntry((0, import_agent_core4.messageToHistoryEntry)((0, import_agent_core4.createSystemMessage)("No user settings found.")));
|
|
1744
|
-
}
|
|
1745
|
-
requestShutdown("other", "Reset settings restart");
|
|
1525
|
+
applyEffects([{ type: "settings-reset-requested" }], sideEffects);
|
|
1746
1526
|
return;
|
|
1747
1527
|
}
|
|
1748
1528
|
if (sideEffects._exitRequested) {
|
|
1749
1529
|
delete sideEffects._exitRequested;
|
|
1750
|
-
|
|
1751
|
-
return;
|
|
1752
|
-
}
|
|
1753
|
-
if (sideEffects._triggerPluginTUI) {
|
|
1754
|
-
delete sideEffects._triggerPluginTUI;
|
|
1755
|
-
setShowPluginTUI(true);
|
|
1530
|
+
applyEffects([{ type: "session-exit-requested" }], sideEffects);
|
|
1756
1531
|
return;
|
|
1757
1532
|
}
|
|
1758
1533
|
if (sideEffects._triggerResumePicker) {
|
|
1759
1534
|
delete sideEffects._triggerResumePicker;
|
|
1760
|
-
|
|
1535
|
+
applyEffects([{ type: "session-picker-requested" }], sideEffects);
|
|
1761
1536
|
return;
|
|
1762
1537
|
}
|
|
1763
1538
|
if (sideEffects._sessionName) {
|
|
1764
1539
|
const name = sideEffects._sessionName;
|
|
1765
1540
|
delete sideEffects._sessionName;
|
|
1766
|
-
|
|
1767
|
-
setSessionName(name);
|
|
1541
|
+
applyEffects([{ type: "session-renamed", name }], sideEffects);
|
|
1768
1542
|
return;
|
|
1769
1543
|
}
|
|
1770
1544
|
if (applyPendingStatusLinePatch(sideEffects, setStatusLineSettings)) return;
|
|
@@ -1772,11 +1546,9 @@ function useSideEffects({
|
|
|
1772
1546
|
[
|
|
1773
1547
|
interactiveSession,
|
|
1774
1548
|
baseHandleSubmit,
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
setStatusLineSettings,
|
|
1779
|
-
providerDefinitions
|
|
1549
|
+
applyQueuedCommandState,
|
|
1550
|
+
applyEffects,
|
|
1551
|
+
setStatusLineSettings
|
|
1780
1552
|
]
|
|
1781
1553
|
);
|
|
1782
1554
|
const handleModelConfirm = (0, import_react4.useCallback)(
|
|
@@ -1785,117 +1557,60 @@ function useSideEffects({
|
|
|
1785
1557
|
setPendingModelId(null);
|
|
1786
1558
|
pendingModelChangeRef.current = null;
|
|
1787
1559
|
if (index === 0 && modelId) {
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
);
|
|
1796
|
-
requestShutdown("other", "Model change restart");
|
|
1797
|
-
} catch (err) {
|
|
1798
|
-
addEntry(
|
|
1799
|
-
(0, import_agent_core4.messageToHistoryEntry)(
|
|
1800
|
-
(0, import_agent_core4.createSystemMessage)(`Failed: ${err instanceof Error ? err.message : String(err)}`)
|
|
1801
|
-
)
|
|
1802
|
-
);
|
|
1803
|
-
}
|
|
1804
|
-
} else {
|
|
1805
|
-
addEntry((0, import_agent_core4.messageToHistoryEntry)((0, import_agent_core4.createSystemMessage)("Model change cancelled.")));
|
|
1806
|
-
}
|
|
1807
|
-
},
|
|
1808
|
-
[addEntry, requestShutdown]
|
|
1809
|
-
);
|
|
1810
|
-
const handleProviderConfirm = (0, import_react4.useCallback)(
|
|
1811
|
-
(index) => {
|
|
1812
|
-
const profile = pendingProviderProfileRef.current;
|
|
1813
|
-
setPendingProviderProfile(null);
|
|
1814
|
-
pendingProviderProfileRef.current = null;
|
|
1815
|
-
if (index === 0 && profile) {
|
|
1816
|
-
try {
|
|
1817
|
-
const settingsPath = getUserSettingsPath();
|
|
1818
|
-
applyProviderSwitch(settingsPath, profile, {
|
|
1819
|
-
knownProviders: readMergedProviderSettings(cwd).providers
|
|
1820
|
-
});
|
|
1821
|
-
addEntry(
|
|
1822
|
-
(0, import_agent_core4.messageToHistoryEntry)(
|
|
1823
|
-
(0, import_agent_core4.createSystemMessage)(`Provider changed to ${profile}. Restarting...`)
|
|
1824
|
-
)
|
|
1825
|
-
);
|
|
1826
|
-
requestShutdown("other", "Provider change restart");
|
|
1827
|
-
} catch (err) {
|
|
1828
|
-
addEntry(
|
|
1829
|
-
(0, import_agent_core4.messageToHistoryEntry)(
|
|
1830
|
-
(0, import_agent_core4.createSystemMessage)(`Failed: ${err instanceof Error ? err.message : String(err)}`)
|
|
1831
|
-
)
|
|
1832
|
-
);
|
|
1833
|
-
}
|
|
1560
|
+
applyConfirmedModelChange({
|
|
1561
|
+
cwd,
|
|
1562
|
+
modelId,
|
|
1563
|
+
providerOverride,
|
|
1564
|
+
addEntry,
|
|
1565
|
+
requestShutdown
|
|
1566
|
+
});
|
|
1834
1567
|
} else {
|
|
1835
|
-
addEntry
|
|
1836
|
-
}
|
|
1837
|
-
},
|
|
1838
|
-
[cwd, addEntry, requestShutdown]
|
|
1839
|
-
);
|
|
1840
|
-
const completeProviderSetup = (0, import_react4.useCallback)(
|
|
1841
|
-
(input) => {
|
|
1842
|
-
providerSetupInteractionRef.current = null;
|
|
1843
|
-
setPendingInteractionPrompt(null);
|
|
1844
|
-
try {
|
|
1845
|
-
const settingsPath = getUserSettingsPath();
|
|
1846
|
-
applyProviderConfiguration(settingsPath, input, { providerDefinitions });
|
|
1847
|
-
addEntry(
|
|
1848
|
-
(0, import_agent_core4.messageToHistoryEntry)(
|
|
1849
|
-
(0, import_agent_core4.createSystemMessage)(`Provider ${input.profile} configured. Restarting...`)
|
|
1850
|
-
)
|
|
1851
|
-
);
|
|
1852
|
-
requestShutdown("other", "Provider setup restart");
|
|
1853
|
-
} catch (err) {
|
|
1854
|
-
addEntry(
|
|
1855
|
-
(0, import_agent_core4.messageToHistoryEntry)(
|
|
1856
|
-
(0, import_agent_core4.createSystemMessage)(`Failed: ${err instanceof Error ? err.message : String(err)}`)
|
|
1857
|
-
)
|
|
1858
|
-
);
|
|
1568
|
+
addModelChangeCancelledMessage(addEntry);
|
|
1859
1569
|
}
|
|
1860
1570
|
},
|
|
1861
|
-
[addEntry, requestShutdown
|
|
1571
|
+
[cwd, providerOverride, addEntry, requestShutdown]
|
|
1862
1572
|
);
|
|
1863
1573
|
const handleInteractionSubmit = (0, import_react4.useCallback)(
|
|
1864
|
-
(value) => {
|
|
1865
|
-
const
|
|
1866
|
-
if (
|
|
1574
|
+
async (value) => {
|
|
1575
|
+
const interaction = commandInteractionRef.current;
|
|
1576
|
+
if (interaction === null) {
|
|
1867
1577
|
setPendingInteractionPrompt(null);
|
|
1868
1578
|
return;
|
|
1869
1579
|
}
|
|
1870
1580
|
try {
|
|
1871
|
-
const result =
|
|
1872
|
-
|
|
1873
|
-
completeProviderSetup(result.input);
|
|
1874
|
-
return;
|
|
1875
|
-
}
|
|
1876
|
-
providerSetupInteractionRef.current = result.state;
|
|
1877
|
-
setPendingInteractionPrompt(result.prompt);
|
|
1581
|
+
const result = await interaction.submit(value);
|
|
1582
|
+
applyCommandResult(result);
|
|
1878
1583
|
} catch (err) {
|
|
1879
|
-
|
|
1584
|
+
commandInteractionRef.current = null;
|
|
1880
1585
|
setPendingInteractionPrompt(null);
|
|
1881
1586
|
addEntry(
|
|
1882
|
-
(0,
|
|
1883
|
-
(0,
|
|
1587
|
+
(0, import_agent_core6.messageToHistoryEntry)(
|
|
1588
|
+
(0, import_agent_core6.createSystemMessage)(`Failed: ${err instanceof Error ? err.message : String(err)}`)
|
|
1884
1589
|
)
|
|
1885
1590
|
);
|
|
1886
1591
|
}
|
|
1887
1592
|
},
|
|
1888
|
-
[addEntry,
|
|
1593
|
+
[addEntry, applyCommandResult]
|
|
1889
1594
|
);
|
|
1890
1595
|
const handleInteractionCancel = (0, import_react4.useCallback)(() => {
|
|
1891
|
-
|
|
1596
|
+
const interaction = commandInteractionRef.current;
|
|
1597
|
+
commandInteractionRef.current = null;
|
|
1892
1598
|
setPendingInteractionPrompt(null);
|
|
1893
|
-
|
|
1894
|
-
|
|
1599
|
+
if (interaction?.cancel === void 0) {
|
|
1600
|
+
addEntry((0, import_agent_core6.messageToHistoryEntry)((0, import_agent_core6.createSystemMessage)("Command interaction cancelled.")));
|
|
1601
|
+
return;
|
|
1602
|
+
}
|
|
1603
|
+
Promise.resolve(interaction.cancel()).then((result) => applyCommandResult(result)).catch((err) => {
|
|
1604
|
+
addEntry(
|
|
1605
|
+
(0, import_agent_core6.messageToHistoryEntry)(
|
|
1606
|
+
(0, import_agent_core6.createSystemMessage)(`Failed: ${err instanceof Error ? err.message : String(err)}`)
|
|
1607
|
+
)
|
|
1608
|
+
);
|
|
1609
|
+
});
|
|
1610
|
+
}, [addEntry, applyCommandResult]);
|
|
1895
1611
|
return {
|
|
1896
1612
|
handleSubmit,
|
|
1897
1613
|
pendingModelId,
|
|
1898
|
-
pendingProviderProfile,
|
|
1899
1614
|
pendingInteractionPrompt,
|
|
1900
1615
|
showPluginTUI,
|
|
1901
1616
|
showSessionPicker,
|
|
@@ -1903,7 +1618,6 @@ function useSideEffects({
|
|
|
1903
1618
|
setShowPluginTUI,
|
|
1904
1619
|
setShowSessionPicker,
|
|
1905
1620
|
handleModelConfirm,
|
|
1906
|
-
handleProviderConfirm,
|
|
1907
1621
|
handleInteractionSubmit,
|
|
1908
1622
|
handleInteractionCancel
|
|
1909
1623
|
};
|
|
@@ -1920,7 +1634,7 @@ function useStatusLineSettings() {
|
|
|
1920
1634
|
// src/ui/MessageList.tsx
|
|
1921
1635
|
var import_react6 = __toESM(require("react"), 1);
|
|
1922
1636
|
var import_ink5 = require("ink");
|
|
1923
|
-
var
|
|
1637
|
+
var import_agent_core8 = require("@robota-sdk/agent-core");
|
|
1924
1638
|
|
|
1925
1639
|
// src/ui/render-markdown.ts
|
|
1926
1640
|
var import_marked = require("marked");
|
|
@@ -2064,7 +1778,7 @@ function ToolDiffBlock({ file, lines }) {
|
|
|
2064
1778
|
|
|
2065
1779
|
// src/ui/UsageSummaryEntry.tsx
|
|
2066
1780
|
var import_ink3 = require("ink");
|
|
2067
|
-
var
|
|
1781
|
+
var import_agent_core7 = require("@robota-sdk/agent-core");
|
|
2068
1782
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
2069
1783
|
var TOKEN_COMPACT_THRESHOLD = 1e3;
|
|
2070
1784
|
function UsageSummaryEntry({ entry }) {
|
|
@@ -2073,9 +1787,9 @@ function UsageSummaryEntry({ entry }) {
|
|
|
2073
1787
|
const prompt = usage.promptTokens !== void 0 ? formatUsageTokenCount(usage.promptTokens) : "?";
|
|
2074
1788
|
const completion = usage.completionTokens !== void 0 ? formatUsageTokenCount(usage.completionTokens) : "?";
|
|
2075
1789
|
const total = formatUsageTokenCount(usage.totalTokens);
|
|
2076
|
-
const context = `${Math.round(usage.contextUsedPercentage)}% (${(0,
|
|
1790
|
+
const context = `${Math.round(usage.contextUsedPercentage)}% (${(0, import_agent_core7.formatTokenCount)(
|
|
2077
1791
|
usage.contextUsedTokens
|
|
2078
|
-
)}/${(0,
|
|
1792
|
+
)}/${(0, import_agent_core7.formatTokenCount)(usage.contextMaxTokens)})`;
|
|
2079
1793
|
const costLabel = usage.costStatus === "unknown" ? "cost unknown" : `cost ${usage.costStatus}`;
|
|
2080
1794
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_ink3.Box, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ink3.Box, { children: [
|
|
2081
1795
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_ink3.Text, { color: "white", bold: true, children: [
|
|
@@ -2099,7 +1813,7 @@ function UsageSummaryEntry({ entry }) {
|
|
|
2099
1813
|
] }) });
|
|
2100
1814
|
}
|
|
2101
1815
|
function formatUsageTokenCount(tokens) {
|
|
2102
|
-
return tokens < TOKEN_COMPACT_THRESHOLD ? tokens.toLocaleString() : (0,
|
|
1816
|
+
return tokens < TOKEN_COMPACT_THRESHOLD ? tokens.toLocaleString() : (0, import_agent_core7.formatTokenCount)(tokens);
|
|
2103
1817
|
}
|
|
2104
1818
|
|
|
2105
1819
|
// src/ui/command-output-summary.ts
|
|
@@ -2240,7 +1954,7 @@ function RoleLabel({ role }) {
|
|
|
2240
1954
|
}
|
|
2241
1955
|
}
|
|
2242
1956
|
function ToolMessage({ message }) {
|
|
2243
|
-
if (!(0,
|
|
1957
|
+
if (!(0, import_agent_core8.isToolMessage)(message)) {
|
|
2244
1958
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_jsx_runtime4.Fragment, {});
|
|
2245
1959
|
}
|
|
2246
1960
|
const toolName = message.name;
|
|
@@ -2303,7 +2017,7 @@ function ToolMessage({ message }) {
|
|
|
2303
2017
|
var MessageItem = import_react6.default.memo(function MessageItem2({
|
|
2304
2018
|
message
|
|
2305
2019
|
}) {
|
|
2306
|
-
if ((0,
|
|
2020
|
+
if ((0, import_agent_core8.isToolMessage)(message)) {
|
|
2307
2021
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ToolMessage, { message });
|
|
2308
2022
|
}
|
|
2309
2023
|
const content = message.content ?? "";
|
|
@@ -2311,7 +2025,7 @@ var MessageItem = import_react6.default.memo(function MessageItem2({
|
|
|
2311
2025
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_ink5.Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
2312
2026
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ink5.Box, { children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(RoleLabel, { role: message.role }) }),
|
|
2313
2027
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ink5.Text, { children: " " }),
|
|
2314
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ink5.Box, { marginLeft: 2, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ink5.Text, { wrap: "wrap", children: (0,
|
|
2028
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ink5.Box, { marginLeft: 2, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_ink5.Text, { wrap: "wrap", children: (0, import_agent_core8.isAssistantMessage)(message) ? renderMarkdown(content + (isInterrupted ? "\n\n_(interrupted)_" : "")) : content }) })
|
|
2315
2029
|
] });
|
|
2316
2030
|
});
|
|
2317
2031
|
function ToolSummaryEntry({ entry }) {
|
|
@@ -2381,7 +2095,7 @@ function MessageList({ history }) {
|
|
|
2381
2095
|
|
|
2382
2096
|
// src/ui/SessionStatusBar.tsx
|
|
2383
2097
|
var import_react7 = require("react");
|
|
2384
|
-
var
|
|
2098
|
+
var import_agent_core10 = require("@robota-sdk/agent-core");
|
|
2385
2099
|
|
|
2386
2100
|
// src/utils/git-branch.ts
|
|
2387
2101
|
var import_node_fs4 = require("fs");
|
|
@@ -2430,7 +2144,7 @@ function resolveGitMetadata(candidate, repoDir) {
|
|
|
2430
2144
|
|
|
2431
2145
|
// src/ui/StatusBar.tsx
|
|
2432
2146
|
var import_ink6 = require("ink");
|
|
2433
|
-
var
|
|
2147
|
+
var import_agent_core9 = require("@robota-sdk/agent-core");
|
|
2434
2148
|
|
|
2435
2149
|
// src/ui/status-activity.ts
|
|
2436
2150
|
var NO_ACTIVE_ITEMS = 0;
|
|
@@ -2512,9 +2226,9 @@ function ContextText({
|
|
|
2512
2226
|
"Context: ",
|
|
2513
2227
|
Math.round(percentage),
|
|
2514
2228
|
"% (",
|
|
2515
|
-
(0,
|
|
2229
|
+
(0, import_agent_core9.formatTokenCount)(usedTokens),
|
|
2516
2230
|
"/",
|
|
2517
|
-
(0,
|
|
2231
|
+
(0, import_agent_core9.formatTokenCount)(maxTokens),
|
|
2518
2232
|
")"
|
|
2519
2233
|
] });
|
|
2520
2234
|
}
|
|
@@ -2576,6 +2290,21 @@ function StatusLeft({
|
|
|
2576
2290
|
)
|
|
2577
2291
|
] });
|
|
2578
2292
|
}
|
|
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
|
+
}
|
|
2579
2308
|
function StatusBar({
|
|
2580
2309
|
permissionMode,
|
|
2581
2310
|
modelName,
|
|
@@ -2618,10 +2347,7 @@ function StatusBar({
|
|
|
2618
2347
|
showGitBranch
|
|
2619
2348
|
}
|
|
2620
2349
|
),
|
|
2621
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2622
|
-
"msgs: ",
|
|
2623
|
-
messageCount
|
|
2624
|
-
] }) })
|
|
2350
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(StatusRight, { isThinking, messageCount })
|
|
2625
2351
|
]
|
|
2626
2352
|
}
|
|
2627
2353
|
);
|
|
@@ -2649,7 +2375,7 @@ function SessionStatusBar({
|
|
|
2649
2375
|
StatusBar,
|
|
2650
2376
|
{
|
|
2651
2377
|
permissionMode,
|
|
2652
|
-
modelName: modelId ? (0,
|
|
2378
|
+
modelName: modelId ? (0, import_agent_core10.getModelName)(modelId) : "",
|
|
2653
2379
|
sessionId,
|
|
2654
2380
|
messageCount,
|
|
2655
2381
|
isThinking,
|
|
@@ -3880,32 +3606,43 @@ function getToolStyle(t) {
|
|
|
3880
3606
|
if (t.result === "denied") return { color: "yellowBright", icon: "\u2298", strikethrough: true };
|
|
3881
3607
|
return { color: "green", icon: "\u2713", strikethrough: false };
|
|
3882
3608
|
}
|
|
3883
|
-
function
|
|
3609
|
+
function renderThinkingFallback(isThinking) {
|
|
3610
|
+
if (!isThinking) return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_jsx_runtime16.Fragment, {});
|
|
3611
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_ink16.Box, { marginBottom: 1, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_ink16.Text, { color: "yellow", children: "Thinking..." }) });
|
|
3612
|
+
}
|
|
3613
|
+
function renderTools(activeTools) {
|
|
3614
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_ink16.Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
3615
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_ink16.Text, { color: "white", bold: true, children: "Tools:" }),
|
|
3616
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_ink16.Text, { children: " " }),
|
|
3617
|
+
activeTools.map((t, i) => {
|
|
3618
|
+
const { color, icon, strikethrough } = getToolStyle(t);
|
|
3619
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_ink16.Box, { flexDirection: "column", children: [
|
|
3620
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_ink16.Text, { color, strikethrough, children: [
|
|
3621
|
+
" ",
|
|
3622
|
+
icon,
|
|
3623
|
+
" ",
|
|
3624
|
+
t.toolName,
|
|
3625
|
+
"(",
|
|
3626
|
+
t.firstArg,
|
|
3627
|
+
")"
|
|
3628
|
+
] }),
|
|
3629
|
+
t.diffLines && t.diffLines.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(ToolDiffBlock, { file: t.diffFile, lines: t.diffLines })
|
|
3630
|
+
] }, `${t.toolName}-${i}`);
|
|
3631
|
+
})
|
|
3632
|
+
] });
|
|
3633
|
+
}
|
|
3634
|
+
function StreamingIndicator({
|
|
3635
|
+
text,
|
|
3636
|
+
activeTools,
|
|
3637
|
+
isThinking = false
|
|
3638
|
+
}) {
|
|
3884
3639
|
const hasTools = activeTools.length > 0;
|
|
3885
3640
|
const hasText = text.length > 0;
|
|
3886
3641
|
if (!hasTools && !hasText) {
|
|
3887
|
-
return
|
|
3642
|
+
return renderThinkingFallback(isThinking);
|
|
3888
3643
|
}
|
|
3889
3644
|
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_ink16.Box, { flexDirection: "column", children: [
|
|
3890
|
-
hasTools &&
|
|
3891
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_ink16.Text, { color: "white", bold: true, children: "Tools:" }),
|
|
3892
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_ink16.Text, { children: " " }),
|
|
3893
|
-
activeTools.map((t, i) => {
|
|
3894
|
-
const { color, icon, strikethrough } = getToolStyle(t);
|
|
3895
|
-
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_ink16.Box, { flexDirection: "column", children: [
|
|
3896
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_ink16.Text, { color, strikethrough, children: [
|
|
3897
|
-
" ",
|
|
3898
|
-
icon,
|
|
3899
|
-
" ",
|
|
3900
|
-
t.toolName,
|
|
3901
|
-
"(",
|
|
3902
|
-
t.firstArg,
|
|
3903
|
-
")"
|
|
3904
|
-
] }),
|
|
3905
|
-
t.diffLines && t.diffLines.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(ToolDiffBlock, { file: t.diffFile, lines: t.diffLines })
|
|
3906
|
-
] }, `${t.toolName}-${i}`);
|
|
3907
|
-
})
|
|
3908
|
-
] }),
|
|
3645
|
+
hasTools && renderTools(activeTools),
|
|
3909
3646
|
hasText && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_ink16.Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
3910
3647
|
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_ink16.Text, { color: "cyan", bold: true, children: "Robota:" }),
|
|
3911
3648
|
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_ink16.Text, { children: " " }),
|
|
@@ -4428,9 +4165,14 @@ function getTaskSegments(task, now) {
|
|
|
4428
4165
|
if (task.signalCode) {
|
|
4429
4166
|
segments.push(`signal ${task.signalCode}`);
|
|
4430
4167
|
}
|
|
4168
|
+
if (task.worktreePath || task.branchName) {
|
|
4169
|
+
segments.push("worktree");
|
|
4170
|
+
}
|
|
4431
4171
|
return segments;
|
|
4432
4172
|
}
|
|
4433
4173
|
function getTaskPreview(task) {
|
|
4174
|
+
if (task.worktreeNextAction) return task.worktreeNextAction;
|
|
4175
|
+
if (task.worktreePath) return task.worktreePath;
|
|
4434
4176
|
const preview = task.errorPreview ?? task.resultPreview ?? task.currentAction ?? task.preview;
|
|
4435
4177
|
return preview || void 0;
|
|
4436
4178
|
}
|
|
@@ -4758,7 +4500,6 @@ function App(props) {
|
|
|
4758
4500
|
}
|
|
4759
4501
|
function AppInner(props) {
|
|
4760
4502
|
const cwd = props.cwd;
|
|
4761
|
-
const providerDefinitions = props.providerDefinitions ?? [];
|
|
4762
4503
|
const {
|
|
4763
4504
|
interactiveSession,
|
|
4764
4505
|
registry,
|
|
@@ -4789,9 +4530,10 @@ function AppInner(props) {
|
|
|
4789
4530
|
backgroundTaskRunners: props.backgroundTaskRunners,
|
|
4790
4531
|
subagentRunnerFactory: props.subagentRunnerFactory,
|
|
4791
4532
|
commandModules: props.commandModules,
|
|
4792
|
-
|
|
4533
|
+
commandHostAdapters: props.commandHostAdapters
|
|
4793
4534
|
});
|
|
4794
|
-
const
|
|
4535
|
+
const fallbackPluginCallbacks = usePluginCallbacks(cwd);
|
|
4536
|
+
const pluginCallbacks = props.commandHostAdapters?.plugin ?? fallbackPluginCallbacks;
|
|
4795
4537
|
const { exit } = (0, import_ink21.useApp)();
|
|
4796
4538
|
const [sessionName, setSessionName] = (0, import_react19.useState)(props.sessionName);
|
|
4797
4539
|
const [updateNotice, setUpdateNotice] = (0, import_react19.useState)();
|
|
@@ -4802,24 +4544,22 @@ function AppInner(props) {
|
|
|
4802
4544
|
const {
|
|
4803
4545
|
handleSubmit,
|
|
4804
4546
|
pendingModelId,
|
|
4805
|
-
pendingProviderProfile,
|
|
4806
4547
|
pendingInteractionPrompt,
|
|
4807
4548
|
showPluginTUI,
|
|
4808
4549
|
showSessionPicker,
|
|
4809
4550
|
setShowPluginTUI,
|
|
4810
4551
|
setShowSessionPicker,
|
|
4811
4552
|
handleModelConfirm,
|
|
4812
|
-
handleProviderConfirm,
|
|
4813
4553
|
handleInteractionSubmit,
|
|
4814
4554
|
handleInteractionCancel
|
|
4815
4555
|
} = useSideEffects({
|
|
4816
4556
|
cwd,
|
|
4557
|
+
providerOverride: props.providerOverride,
|
|
4817
4558
|
interactiveSession,
|
|
4818
4559
|
addEntry,
|
|
4819
4560
|
baseHandleSubmit,
|
|
4820
4561
|
setSessionName,
|
|
4821
|
-
setStatusLineSettings
|
|
4822
|
-
providerDefinitions
|
|
4562
|
+
setStatusLineSettings
|
|
4823
4563
|
});
|
|
4824
4564
|
(0, import_react19.useEffect)(() => {
|
|
4825
4565
|
const name = interactiveSession?.getName?.();
|
|
@@ -4888,24 +4628,24 @@ function AppInner(props) {
|
|
|
4888
4628
|
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_ink21.Box, { flexDirection: "column", paddingX: 1, flexGrow: 1, children: [
|
|
4889
4629
|
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(MessageList, { history }),
|
|
4890
4630
|
isShuttingDown && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_ink21.Box, { marginBottom: 1, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_ink21.Text, { color: "yellow", children: "Shutting down..." }) }),
|
|
4891
|
-
(isThinking || activeTools.length > 0) && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_ink21.Box, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4631
|
+
(isThinking || activeTools.length > 0) && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_ink21.Box, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4632
|
+
StreamingIndicator,
|
|
4633
|
+
{
|
|
4634
|
+
text: streamingText,
|
|
4635
|
+
activeTools,
|
|
4636
|
+
isThinking
|
|
4637
|
+
}
|
|
4638
|
+
) }),
|
|
4892
4639
|
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(BackgroundTaskPanel, { tasks: backgroundTasks })
|
|
4893
4640
|
] }),
|
|
4894
4641
|
permissionRequest && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(PermissionPrompt, { request: permissionRequest }),
|
|
4895
4642
|
pendingModelId && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4896
4643
|
ConfirmPrompt,
|
|
4897
4644
|
{
|
|
4898
|
-
message:
|
|
4645
|
+
message: formatModelChangeConfirmationMessage(pendingModelId),
|
|
4899
4646
|
onSelect: handleModelConfirm
|
|
4900
4647
|
}
|
|
4901
4648
|
),
|
|
4902
|
-
pendingProviderProfile && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4903
|
-
ConfirmPrompt,
|
|
4904
|
-
{
|
|
4905
|
-
message: `Change provider to ${pendingProviderProfile}? This will restart the session.`,
|
|
4906
|
-
onSelect: handleProviderConfirm
|
|
4907
|
-
}
|
|
4908
|
-
),
|
|
4909
4649
|
pendingInteractionPrompt && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4910
4650
|
InteractivePrompt,
|
|
4911
4651
|
{
|
|
@@ -4919,7 +4659,7 @@ function AppInner(props) {
|
|
|
4919
4659
|
{
|
|
4920
4660
|
callbacks: pluginCallbacks,
|
|
4921
4661
|
onClose: () => setShowPluginTUI(false),
|
|
4922
|
-
addMessage: (msg) => addEntry((0,
|
|
4662
|
+
addMessage: (msg) => addEntry((0, import_agent_core11.messageToHistoryEntry)((0, import_agent_core11.createSystemMessage)(msg.content)))
|
|
4923
4663
|
}
|
|
4924
4664
|
),
|
|
4925
4665
|
showSessionPicker && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
@@ -4933,7 +4673,7 @@ function AppInner(props) {
|
|
|
4933
4673
|
},
|
|
4934
4674
|
onCancel: () => {
|
|
4935
4675
|
setShowSessionPicker(false);
|
|
4936
|
-
addEntry((0,
|
|
4676
|
+
addEntry((0, import_agent_core11.messageToHistoryEntry)((0, import_agent_core11.createSystemMessage)("Session resume cancelled.")));
|
|
4937
4677
|
}
|
|
4938
4678
|
}
|
|
4939
4679
|
),
|
|
@@ -5000,7 +4740,7 @@ function renderApp(options) {
|
|
|
5000
4740
|
|
|
5001
4741
|
// src/background/managed-shell-process-runner.ts
|
|
5002
4742
|
var import_node_child_process = require("child_process");
|
|
5003
|
-
var
|
|
4743
|
+
var import_agent_sdk9 = require("@robota-sdk/agent-sdk");
|
|
5004
4744
|
var DEFAULT_OUTPUT_LIMIT_BYTES = 3e4;
|
|
5005
4745
|
var DEFAULT_KILL_GRACE_MS = 2e3;
|
|
5006
4746
|
var LOG_PAGE_SIZE = 200;
|
|
@@ -5054,7 +4794,7 @@ function createManagedShellProcessRunner(options = {}) {
|
|
|
5054
4794
|
kind: "process",
|
|
5055
4795
|
start(task) {
|
|
5056
4796
|
if (task.request.kind !== "process") {
|
|
5057
|
-
throw new
|
|
4797
|
+
throw new import_agent_sdk9.BackgroundTaskError("runner", `Invalid process task kind: ${task.request.kind}`);
|
|
5058
4798
|
}
|
|
5059
4799
|
return startProcessTask(task.taskId, task.request, killGraceMs);
|
|
5060
4800
|
}
|
|
@@ -5083,7 +4823,7 @@ function createProcessResult(runtime) {
|
|
|
5083
4823
|
const timeoutTimer = runtime.request.timeoutMs ? setTimeout(() => {
|
|
5084
4824
|
appendLog(runtime.logs, "system", `timed out after ${runtime.request.timeoutMs}ms`);
|
|
5085
4825
|
runtime.child.kill("SIGTERM");
|
|
5086
|
-
rejectOnceLocal(new
|
|
4826
|
+
rejectOnceLocal(new import_agent_sdk9.BackgroundTaskError("timeout", "Background process timed out"));
|
|
5087
4827
|
}, runtime.request.timeoutMs) : void 0;
|
|
5088
4828
|
function clearTimers() {
|
|
5089
4829
|
if (timeoutTimer) clearTimeout(timeoutTimer);
|
|
@@ -5110,7 +4850,7 @@ function createProcessResult(runtime) {
|
|
|
5110
4850
|
attachOutputListeners(runtime);
|
|
5111
4851
|
runtime.child.on("error", (error) => {
|
|
5112
4852
|
appendLog(runtime.logs, "system", error.message);
|
|
5113
|
-
rejectOnceLocal(new
|
|
4853
|
+
rejectOnceLocal(new import_agent_sdk9.BackgroundTaskError("process", error.message));
|
|
5114
4854
|
});
|
|
5115
4855
|
runtime.child.on("close", (code, signal) => {
|
|
5116
4856
|
resolveOnce(code ?? void 0, signal ?? void 0);
|
|
@@ -5170,10 +4910,10 @@ function readProcessLog(runtime, cursor) {
|
|
|
5170
4910
|
var import_node_child_process3 = require("child_process");
|
|
5171
4911
|
var import_node_fs7 = require("fs");
|
|
5172
4912
|
var import_node_path9 = require("path");
|
|
5173
|
-
var
|
|
4913
|
+
var import_agent_sdk13 = require("@robota-sdk/agent-sdk");
|
|
5174
4914
|
|
|
5175
4915
|
// src/subagents/child-process-subagent-runner-result.ts
|
|
5176
|
-
var
|
|
4916
|
+
var import_agent_sdk11 = require("@robota-sdk/agent-sdk");
|
|
5177
4917
|
|
|
5178
4918
|
// src/subagents/child-process-subagent-ipc.ts
|
|
5179
4919
|
function isRecord2(value) {
|
|
@@ -5205,7 +4945,7 @@ function isSubagentWorkerChildMessage(value) {
|
|
|
5205
4945
|
}
|
|
5206
4946
|
|
|
5207
4947
|
// src/subagents/child-process-subagent-transport.ts
|
|
5208
|
-
var
|
|
4948
|
+
var import_agent_sdk10 = require("@robota-sdk/agent-sdk");
|
|
5209
4949
|
function handleWorkerMessage(message, startWorker, resolveOnce, rejectOnce, emit) {
|
|
5210
4950
|
switch (message.type) {
|
|
5211
4951
|
case "ready":
|
|
@@ -5215,10 +4955,10 @@ function handleWorkerMessage(message, startWorker, resolveOnce, rejectOnce, emit
|
|
|
5215
4955
|
resolveOnce(message.output);
|
|
5216
4956
|
break;
|
|
5217
4957
|
case "error":
|
|
5218
|
-
rejectOnce(new
|
|
4958
|
+
rejectOnce(new import_agent_sdk10.BackgroundTaskError("runner", message.message));
|
|
5219
4959
|
break;
|
|
5220
4960
|
case "cancelled":
|
|
5221
|
-
rejectOnce(new
|
|
4961
|
+
rejectOnce(new import_agent_sdk10.BackgroundTaskError("runner", message.reason ?? "Subagent worker cancelled"));
|
|
5222
4962
|
break;
|
|
5223
4963
|
case "text_delta":
|
|
5224
4964
|
emit?.({ type: "background_task_text_delta", delta: message.delta });
|
|
@@ -5238,7 +4978,7 @@ function handleWorkerMessage(message, startWorker, resolveOnce, rejectOnce, emit
|
|
|
5238
4978
|
});
|
|
5239
4979
|
break;
|
|
5240
4980
|
default:
|
|
5241
|
-
rejectOnce(new
|
|
4981
|
+
rejectOnce(new import_agent_sdk10.BackgroundTaskError("runner", "Unhandled subagent worker message"));
|
|
5242
4982
|
}
|
|
5243
4983
|
}
|
|
5244
4984
|
function extractFirstArg(toolArgs) {
|
|
@@ -5250,7 +4990,7 @@ function extractFirstArg(toolArgs) {
|
|
|
5250
4990
|
function sendWorkerMessage(child, message) {
|
|
5251
4991
|
return new Promise((resolve2, reject) => {
|
|
5252
4992
|
if (!child.connected) {
|
|
5253
|
-
reject(new
|
|
4993
|
+
reject(new import_agent_sdk10.BackgroundTaskError("crash", "Subagent worker IPC channel is closed"));
|
|
5254
4994
|
return;
|
|
5255
4995
|
}
|
|
5256
4996
|
child.send(message, (error) => {
|
|
@@ -5311,7 +5051,7 @@ var ChildProcessSubagentResultController = class {
|
|
|
5311
5051
|
onMessage = (message) => {
|
|
5312
5052
|
if (!isSubagentWorkerChildMessage(message)) {
|
|
5313
5053
|
this.rejectOnce(
|
|
5314
|
-
new
|
|
5054
|
+
new import_agent_sdk11.BackgroundTaskError("runner", "Received malformed subagent worker message")
|
|
5315
5055
|
);
|
|
5316
5056
|
return;
|
|
5317
5057
|
}
|
|
@@ -5319,11 +5059,11 @@ var ChildProcessSubagentResultController = class {
|
|
|
5319
5059
|
handleWorkerMessage(message, this.startWorker, this.resolveOnce, this.rejectOnce, job.emit);
|
|
5320
5060
|
};
|
|
5321
5061
|
onError = (error) => {
|
|
5322
|
-
this.rejectOnce(new
|
|
5062
|
+
this.rejectOnce(new import_agent_sdk11.BackgroundTaskError("crash", error.message));
|
|
5323
5063
|
};
|
|
5324
5064
|
onExit = (code, signal) => {
|
|
5325
5065
|
if (this.settled) return;
|
|
5326
|
-
this.rejectOnce(new
|
|
5066
|
+
this.rejectOnce(new import_agent_sdk11.BackgroundTaskError("crash", formatEarlyExitMessage(code, signal)));
|
|
5327
5067
|
};
|
|
5328
5068
|
resolveOnce = (output) => {
|
|
5329
5069
|
if (this.settled) return;
|
|
@@ -5363,7 +5103,7 @@ function createCancellationResult(jobId) {
|
|
|
5363
5103
|
reject(reason) {
|
|
5364
5104
|
if (settled) return;
|
|
5365
5105
|
settled = true;
|
|
5366
|
-
rejectFn(new
|
|
5106
|
+
rejectFn(new import_agent_sdk11.BackgroundTaskError("runner", reason ?? `Subagent job cancelled: ${jobId}`));
|
|
5367
5107
|
}
|
|
5368
5108
|
};
|
|
5369
5109
|
}
|
|
@@ -5371,7 +5111,7 @@ function createTimeoutTimer(runtime, rejectOnce) {
|
|
|
5371
5111
|
if (!runtime.job.request.timeoutMs) return void 0;
|
|
5372
5112
|
return setTimeout(() => {
|
|
5373
5113
|
void cancelChildProcess(runtime, "Subagent worker timed out");
|
|
5374
|
-
rejectOnce(new
|
|
5114
|
+
rejectOnce(new import_agent_sdk11.BackgroundTaskError("timeout", "Subagent worker timed out"));
|
|
5375
5115
|
}, runtime.job.request.timeoutMs);
|
|
5376
5116
|
}
|
|
5377
5117
|
function toSubagentResult(job, output, resolveTranscriptPath) {
|
|
@@ -5392,33 +5132,60 @@ var import_node_child_process2 = require("child_process");
|
|
|
5392
5132
|
var import_node_crypto2 = require("crypto");
|
|
5393
5133
|
var import_node_fs6 = require("fs");
|
|
5394
5134
|
var import_node_path8 = require("path");
|
|
5395
|
-
var
|
|
5135
|
+
var import_agent_sdk12 = require("@robota-sdk/agent-sdk");
|
|
5396
5136
|
var WORKTREE_DIR = ".robota/worktrees";
|
|
5397
5137
|
var BRANCH_PREFIX = "robota";
|
|
5398
5138
|
var GIT_ENCODING = "utf8";
|
|
5399
5139
|
var SHORT_ID_LENGTH = 8;
|
|
5140
|
+
var DEFAULT_MAX_CREATE_ATTEMPTS = 5;
|
|
5141
|
+
var COLLISION_ERROR_PATTERN = /already exists|is already checked out|missing but already registered/i;
|
|
5400
5142
|
function createGitWorktreeIsolationAdapter(options) {
|
|
5401
5143
|
return new GitWorktreeIsolationAdapter(options);
|
|
5402
5144
|
}
|
|
5403
5145
|
var GitWorktreeIsolationAdapter = class {
|
|
5404
5146
|
worktreeDir;
|
|
5405
5147
|
branchPrefix;
|
|
5148
|
+
idFactory;
|
|
5149
|
+
maxCreateAttempts;
|
|
5406
5150
|
constructor(options = {}) {
|
|
5407
5151
|
this.worktreeDir = options.worktreeDir ?? WORKTREE_DIR;
|
|
5408
5152
|
this.branchPrefix = options.branchPrefix ?? BRANCH_PREFIX;
|
|
5153
|
+
this.idFactory = options.idFactory ?? createShortId;
|
|
5154
|
+
this.maxCreateAttempts = options.maxCreateAttempts ?? DEFAULT_MAX_CREATE_ATTEMPTS;
|
|
5409
5155
|
}
|
|
5410
5156
|
prepare(request) {
|
|
5411
|
-
|
|
5412
|
-
|
|
5413
|
-
|
|
5157
|
+
if (this.maxCreateAttempts < 1) {
|
|
5158
|
+
throw new import_agent_sdk12.BackgroundTaskError("runner", "Git worktree creation attempts must be at least 1");
|
|
5159
|
+
}
|
|
5160
|
+
const repoRoot = resolveRepoRoot(request.cwd);
|
|
5161
|
+
const baseRevision = runGit(repoRoot, ["rev-parse", "HEAD"]).trim();
|
|
5162
|
+
const parentStatus = runGit(repoRoot, ["status", "--porcelain"]).trimEnd();
|
|
5414
5163
|
const worktreeRoot = (0, import_node_path8.join)(repoRoot, this.worktreeDir);
|
|
5415
|
-
const worktreePath = (0, import_node_path8.join)(worktreeRoot, `${request.jobId}-${shortId}`);
|
|
5416
5164
|
(0, import_node_fs6.mkdirSync)(worktreeRoot, { recursive: true });
|
|
5417
|
-
|
|
5418
|
-
|
|
5165
|
+
let lastError;
|
|
5166
|
+
for (let attempt = 0; attempt < this.maxCreateAttempts; attempt += 1) {
|
|
5167
|
+
const shortId = normalizeShortId(this.idFactory());
|
|
5168
|
+
const jobId = sanitizePathSegment(request.jobId);
|
|
5169
|
+
const branchName = `${this.branchPrefix}/${jobId}-${shortId}`;
|
|
5170
|
+
const worktreePath = (0, import_node_path8.join)(worktreeRoot, `${jobId}-${shortId}`);
|
|
5171
|
+
try {
|
|
5172
|
+
runGit(repoRoot, ["worktree", "add", "-b", branchName, worktreePath, "HEAD"]);
|
|
5173
|
+
return { repoRoot, worktreePath, branchName, baseRevision, parentStatus };
|
|
5174
|
+
} catch (error) {
|
|
5175
|
+
lastError = toError(error);
|
|
5176
|
+
if (!isCollisionError(lastError)) throw lastError;
|
|
5177
|
+
}
|
|
5178
|
+
}
|
|
5179
|
+
throw new import_agent_sdk12.BackgroundTaskError(
|
|
5180
|
+
"runner",
|
|
5181
|
+
`Unable to create Git worktree after ${this.maxCreateAttempts} attempts due to branch or path collisions. Last error: ${lastError?.message ?? "unknown error"}`
|
|
5182
|
+
);
|
|
5419
5183
|
}
|
|
5420
5184
|
isClean(worktree) {
|
|
5421
|
-
return
|
|
5185
|
+
return this.getStatus(worktree).trim().length === 0;
|
|
5186
|
+
}
|
|
5187
|
+
getStatus(worktree) {
|
|
5188
|
+
return runGit(worktree.worktreePath, ["status", "--porcelain"]);
|
|
5422
5189
|
}
|
|
5423
5190
|
remove(worktree) {
|
|
5424
5191
|
runGit(worktree.repoRoot, ["worktree", "remove", "--force", worktree.worktreePath]);
|
|
@@ -5430,13 +5197,51 @@ function runGit(cwd, args) {
|
|
|
5430
5197
|
return (0, import_node_child_process2.execFileSync)("git", args, {
|
|
5431
5198
|
cwd,
|
|
5432
5199
|
encoding: GIT_ENCODING,
|
|
5433
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
5200
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
5201
|
+
env: createGitEnvironment()
|
|
5434
5202
|
});
|
|
5435
5203
|
} catch (error) {
|
|
5436
5204
|
const message = error instanceof Error ? error.message : String(error);
|
|
5437
|
-
throw new
|
|
5205
|
+
throw new import_agent_sdk12.BackgroundTaskError("runner", `git ${args.join(" ")} failed: ${message}`);
|
|
5206
|
+
}
|
|
5207
|
+
}
|
|
5208
|
+
function createGitEnvironment() {
|
|
5209
|
+
const env = { ...process.env };
|
|
5210
|
+
for (const key of Object.keys(env)) {
|
|
5211
|
+
if (key.startsWith("GIT_")) {
|
|
5212
|
+
delete env[key];
|
|
5213
|
+
}
|
|
5214
|
+
}
|
|
5215
|
+
return env;
|
|
5216
|
+
}
|
|
5217
|
+
function resolveRepoRoot(cwd) {
|
|
5218
|
+
try {
|
|
5219
|
+
return runGit(cwd, ["rev-parse", "--show-toplevel"]).trim();
|
|
5220
|
+
} catch (error) {
|
|
5221
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
5222
|
+
throw new import_agent_sdk12.BackgroundTaskError(
|
|
5223
|
+
"runner",
|
|
5224
|
+
`Worktree isolation requires a Git repository. Run from a Git worktree or request isolation "none". Details: ${message}`
|
|
5225
|
+
);
|
|
5438
5226
|
}
|
|
5439
5227
|
}
|
|
5228
|
+
function createShortId() {
|
|
5229
|
+
return (0, import_node_crypto2.randomUUID)().slice(0, SHORT_ID_LENGTH);
|
|
5230
|
+
}
|
|
5231
|
+
function normalizeShortId(value) {
|
|
5232
|
+
const sanitized = sanitizePathSegment(value).slice(0, SHORT_ID_LENGTH);
|
|
5233
|
+
return sanitized.length > 0 ? sanitized : createShortId();
|
|
5234
|
+
}
|
|
5235
|
+
function sanitizePathSegment(value) {
|
|
5236
|
+
const sanitized = value.replace(/[^A-Za-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
5237
|
+
return sanitized.length > 0 ? sanitized : "agent";
|
|
5238
|
+
}
|
|
5239
|
+
function toError(error) {
|
|
5240
|
+
return error instanceof Error ? error : new Error(String(error));
|
|
5241
|
+
}
|
|
5242
|
+
function isCollisionError(error) {
|
|
5243
|
+
return COLLISION_ERROR_PATTERN.test(error.message);
|
|
5244
|
+
}
|
|
5440
5245
|
|
|
5441
5246
|
// src/subagents/child-process-subagent-runner.ts
|
|
5442
5247
|
var DEFAULT_KILL_GRACE_MS2 = 2e3;
|
|
@@ -5445,7 +5250,7 @@ function createChildProcessSubagentRunnerFactory(options = {}) {
|
|
|
5445
5250
|
return (deps) => {
|
|
5446
5251
|
const runner = new ChildProcessSubagentRunner(deps, options);
|
|
5447
5252
|
if (options.worktreeIsolation === false) return runner;
|
|
5448
|
-
return (0,
|
|
5253
|
+
return (0, import_agent_sdk13.createWorktreeSubagentRunner)({
|
|
5449
5254
|
runner,
|
|
5450
5255
|
worktreeAdapter: options.worktreeAdapter ?? createGitWorktreeIsolationAdapter(),
|
|
5451
5256
|
hooks: deps.config.hooks,
|
|
@@ -5527,9 +5332,9 @@ var ChildProcessSubagentRunner = class {
|
|
|
5527
5332
|
}
|
|
5528
5333
|
};
|
|
5529
5334
|
function resolveAgentDefinition(agentType, customRegistry) {
|
|
5530
|
-
const definition = customRegistry?.(agentType) ?? (0,
|
|
5335
|
+
const definition = customRegistry?.(agentType) ?? (0, import_agent_sdk13.getBuiltInAgent)(agentType);
|
|
5531
5336
|
if (!definition) {
|
|
5532
|
-
throw new
|
|
5337
|
+
throw new import_agent_sdk13.BackgroundTaskError("validation", `Unknown agent type: ${agentType}`);
|
|
5533
5338
|
}
|
|
5534
5339
|
return definition;
|
|
5535
5340
|
}
|
|
@@ -5596,93 +5401,6 @@ function readTranscriptLog(jobId, transcriptPath, cursor) {
|
|
|
5596
5401
|
};
|
|
5597
5402
|
}
|
|
5598
5403
|
|
|
5599
|
-
// src/commands/statusline-command-module.ts
|
|
5600
|
-
var USAGE = [
|
|
5601
|
-
"Usage: /statusline on | off | reset | git on | git off",
|
|
5602
|
-
"Fields: model, context, permission mode, message count, session name, thinking state, git branch."
|
|
5603
|
-
].join("\n");
|
|
5604
|
-
function createStatusLineEntry() {
|
|
5605
|
-
return {
|
|
5606
|
-
name: "statusline",
|
|
5607
|
-
description: "Configure TUI status-line visibility and fields such as model, context, tokens, session, and git branch.",
|
|
5608
|
-
source: "cli",
|
|
5609
|
-
modelInvocable: false,
|
|
5610
|
-
argumentHint: "on | off | reset | git on | git off",
|
|
5611
|
-
subcommands: [
|
|
5612
|
-
{ name: "on", description: "Show the status line", source: "cli" },
|
|
5613
|
-
{ name: "off", description: "Hide the status line", source: "cli" },
|
|
5614
|
-
{ name: "reset", description: "Restore default status-line fields", source: "cli" },
|
|
5615
|
-
{ name: "git", description: "Show or hide git branch field", source: "cli" }
|
|
5616
|
-
]
|
|
5617
|
-
};
|
|
5618
|
-
}
|
|
5619
|
-
function parseStatusLineArgs(args) {
|
|
5620
|
-
const parts = args.trim().toLowerCase().split(/\s+/).filter((part) => part.length > 0);
|
|
5621
|
-
const [first, second] = parts;
|
|
5622
|
-
if (first === "on" && second === void 0) {
|
|
5623
|
-
return { success: true, message: "Status line enabled.", patch: { enabled: true } };
|
|
5624
|
-
}
|
|
5625
|
-
if (first === "off" && second === void 0) {
|
|
5626
|
-
return { success: true, message: "Status line disabled.", patch: { enabled: false } };
|
|
5627
|
-
}
|
|
5628
|
-
if (first === "reset" && second === void 0) {
|
|
5629
|
-
return {
|
|
5630
|
-
success: true,
|
|
5631
|
-
message: "Status line settings reset.",
|
|
5632
|
-
patch: { enabled: true, gitBranch: true }
|
|
5633
|
-
};
|
|
5634
|
-
}
|
|
5635
|
-
if (first === "git" && second === "on" && parts.length === 2) {
|
|
5636
|
-
return {
|
|
5637
|
-
success: true,
|
|
5638
|
-
message: "Status line git branch shown.",
|
|
5639
|
-
patch: { gitBranch: true }
|
|
5640
|
-
};
|
|
5641
|
-
}
|
|
5642
|
-
if (first === "git" && second === "off" && parts.length === 2) {
|
|
5643
|
-
return {
|
|
5644
|
-
success: true,
|
|
5645
|
-
message: "Status line git branch hidden.",
|
|
5646
|
-
patch: { gitBranch: false }
|
|
5647
|
-
};
|
|
5648
|
-
}
|
|
5649
|
-
return { success: false, message: USAGE };
|
|
5650
|
-
}
|
|
5651
|
-
function createStatusLineSystemCommand() {
|
|
5652
|
-
const entry = createStatusLineEntry();
|
|
5653
|
-
return {
|
|
5654
|
-
name: entry.name,
|
|
5655
|
-
description: entry.description,
|
|
5656
|
-
modelInvocable: false,
|
|
5657
|
-
userInvocable: true,
|
|
5658
|
-
argumentHint: entry.argumentHint,
|
|
5659
|
-
execute: (_session, args) => {
|
|
5660
|
-
const action = parseStatusLineArgs(args);
|
|
5661
|
-
if (!action.success) {
|
|
5662
|
-
return { success: false, message: action.message };
|
|
5663
|
-
}
|
|
5664
|
-
return {
|
|
5665
|
-
success: true,
|
|
5666
|
-
message: action.message,
|
|
5667
|
-
data: { statuslinePatch: action.patch }
|
|
5668
|
-
};
|
|
5669
|
-
}
|
|
5670
|
-
};
|
|
5671
|
-
}
|
|
5672
|
-
var StatusLineCommandSource = class {
|
|
5673
|
-
name = "cli-statusline";
|
|
5674
|
-
getCommands() {
|
|
5675
|
-
return [createStatusLineEntry()];
|
|
5676
|
-
}
|
|
5677
|
-
};
|
|
5678
|
-
function createStatusLineCommandModule() {
|
|
5679
|
-
return {
|
|
5680
|
-
name: "cli-statusline",
|
|
5681
|
-
commandSources: [new StatusLineCommandSource()],
|
|
5682
|
-
systemCommands: [createStatusLineSystemCommand()]
|
|
5683
|
-
};
|
|
5684
|
-
}
|
|
5685
|
-
|
|
5686
5404
|
// src/cli.ts
|
|
5687
5405
|
var import_meta = {};
|
|
5688
5406
|
function readVersion() {
|
|
@@ -5774,9 +5492,39 @@ async function startCli(options = {}) {
|
|
|
5774
5492
|
return;
|
|
5775
5493
|
}
|
|
5776
5494
|
const cwd = process.cwd();
|
|
5495
|
+
const commandHostAdapters = {
|
|
5496
|
+
settings: {
|
|
5497
|
+
read: () => readSettings(getUserSettingsPath()),
|
|
5498
|
+
write: (settings) => writeSettings(getUserSettingsPath(), settings)
|
|
5499
|
+
},
|
|
5500
|
+
plugin: createCliPluginCommandAdapter(cwd)
|
|
5501
|
+
};
|
|
5777
5502
|
const providerDefinitions = options.providerDefinitions ?? DEFAULT_PROVIDER_DEFINITIONS;
|
|
5778
5503
|
const commandModules = [
|
|
5779
|
-
|
|
5504
|
+
(0, import_agent_command_help.createHelpCommandModule)(),
|
|
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
|
+
}),
|
|
5780
5528
|
...options.commandModules ?? []
|
|
5781
5529
|
];
|
|
5782
5530
|
const startupUpdateNoticePromise = shouldRunStartupCliUpdateCheck(args) ? getStartupCliUpdateNotice({ currentVersion: version }) : void 0;
|
|
@@ -5799,7 +5547,7 @@ async function startCli(options = {}) {
|
|
|
5799
5547
|
const modelId = args.model ?? providerSettings.model;
|
|
5800
5548
|
const provider = createProviderFromSettings(cwd, args.model, providerOptions);
|
|
5801
5549
|
const backgroundTaskRunners = [createManagedShellProcessRunner()];
|
|
5802
|
-
const paths = (0,
|
|
5550
|
+
const paths = (0, import_agent_sdk14.projectPaths)(cwd);
|
|
5803
5551
|
const subagentRunnerFactory = createChildProcessSubagentRunnerFactory({
|
|
5804
5552
|
providerConfig: { ...providerSettings, model: modelId },
|
|
5805
5553
|
logsDir: paths.logs
|
|
@@ -5847,7 +5595,7 @@ async function startCli(options = {}) {
|
|
|
5847
5595
|
${args.jsonSchema}`
|
|
5848
5596
|
);
|
|
5849
5597
|
const appendSystemPrompt = appendParts.length > 0 ? appendParts.join("\n\n") : void 0;
|
|
5850
|
-
const session = new
|
|
5598
|
+
const session = new import_agent_sdk14.InteractiveSession({
|
|
5851
5599
|
cwd,
|
|
5852
5600
|
provider,
|
|
5853
5601
|
permissionMode: args.permissionMode ?? "bypassPermissions",
|
|
@@ -5859,7 +5607,8 @@ ${args.jsonSchema}`
|
|
|
5859
5607
|
appendSystemPrompt,
|
|
5860
5608
|
backgroundTaskRunners,
|
|
5861
5609
|
subagentRunnerFactory,
|
|
5862
|
-
commandModules
|
|
5610
|
+
commandModules,
|
|
5611
|
+
commandHostAdapters
|
|
5863
5612
|
});
|
|
5864
5613
|
const transport = (0, import_agent_transport_headless.createHeadlessTransport)({
|
|
5865
5614
|
outputFormat: args.outputFormat ?? "text",
|
|
@@ -5873,6 +5622,7 @@ ${args.jsonSchema}`
|
|
|
5873
5622
|
renderApp({
|
|
5874
5623
|
cwd,
|
|
5875
5624
|
provider,
|
|
5625
|
+
providerOverride: args.provider,
|
|
5876
5626
|
modelId,
|
|
5877
5627
|
language: args.language,
|
|
5878
5628
|
permissionMode: args.permissionMode,
|
|
@@ -5885,7 +5635,7 @@ ${args.jsonSchema}`
|
|
|
5885
5635
|
backgroundTaskRunners,
|
|
5886
5636
|
subagentRunnerFactory,
|
|
5887
5637
|
commandModules,
|
|
5888
|
-
|
|
5638
|
+
commandHostAdapters,
|
|
5889
5639
|
startupUpdateNoticePromise
|
|
5890
5640
|
});
|
|
5891
5641
|
}
|