@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.
@@ -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 import_agent_sdk8 = require("@robota-sdk/agent-sdk");
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 ENV_REFERENCE_PREFIX = "$ENV:";
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
- const paths = [
256
- (0, import_node_path2.join)((0, import_node_os.homedir)(), ".robota", "settings.json"),
257
- (0, import_node_path2.join)((0, import_node_os.homedir)(), ".claude", "settings.json"),
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 checkSettingsFile(filePath, providerDefinitions = []) {
381
- if (!(0, import_node_fs3.existsSync)(filePath)) return "missing";
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
- if (typeof settings.currentProvider !== "string") {
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
- function upsertProviderProfile(settings, profileName, profile) {
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
- // src/utils/provider-setup-flow.ts
505
- function createProviderSetupFlow(type, providerDefinitions) {
506
- return {
507
- type,
508
- steps: getProviderSetupSteps(type, providerDefinitions),
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 step;
417
+ return updateLegacyProviderModel(settingsPaths, modelId);
553
418
  }
554
- function submitProviderSetupValue(state, rawValue) {
555
- const step = getProviderSetupStep(state);
556
- const value = rawValue.trim() || step.defaultValue || "";
557
- const validationMessage = validateProviderSetupValue(step, value);
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 nextState = {
562
- ...state,
563
- stepIndex: state.stepIndex + 1,
564
- values: { ...state.values, [step.key]: value }
565
- };
566
- if (nextState.stepIndex < state.steps.length) {
567
- return { status: "next", state: nextState };
568
- }
569
- return { status: "complete", input: buildProviderSetupInput(nextState) };
570
- }
571
- async function runProviderSetupPromptFlow(type, promptInput2, providerDefinitions) {
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
- state = result.state;
585
- }
586
- throw new Error("Provider setup flow ended without completion");
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 parseProviderSelectionIndex(value) {
597
- if (!/^\d+$/.test(value)) {
598
- return void 0;
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
- return Number(value) - 1;
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 validateProviderSetupValue(step, value) {
603
- if (step.required === true && value.length === 0) {
604
- return "Required";
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 getProviderSetupSteps(type, providerDefinitions) {
609
- const definition = (0, import_agent_core.findProviderDefinition)(providerDefinitions, type);
610
- if (definition === void 0) {
611
- throw new Error(
612
- `Unknown provider: ${type}. Currently supported: ${(0, import_agent_core.formatSupportedProviderTypes)(providerDefinitions)}`
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 steps;
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 checks = getSettingsCheckPaths(cwd).map((path) => ({
687
- path,
688
- status: checkSettingsFile(path, providerDefinitions)
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(cwd, args, promptInput2, providerDefinitions);
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 getSettingsCheckPaths(cwd) {
733
- return [
734
- getUserSettingsPath(),
735
- (0, import_node_path3.join)((0, import_node_os2.homedir)(), ".claude", "settings.json"),
736
- (0, import_node_path3.join)(cwd, ".robota", "settings.json"),
737
- (0, import_node_path3.join)(cwd, ".robota", "settings.local.json"),
738
- (0, import_node_path3.join)(cwd, ".claude", "settings.json"),
739
- (0, import_node_path3.join)(cwd, ".claude", "settings.local.json")
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 import_agent_core9 = require("@robota-sdk/agent-core");
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 import_node_os3 = require("os");
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/utils/provider-command.ts
1038
- async function handleProviderCommand(cwd, args, deps = {}) {
1039
- const settings = readMergedProviderSettings(cwd);
1040
- const providerDefinitions = deps.providerDefinitions ?? DEFAULT_PROVIDER_DEFINITIONS;
1041
- const [subcommand = "current", profileArg] = args.trim().split(/\s+/);
1042
- if (subcommand === "list") {
1043
- return {
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
- async function testProvider(currentProvider, providers, profileArg, deps) {
1127
- const profileName = profileArg ?? currentProvider;
1128
- if (!profileName) {
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
- validateProviderProfile(profileName, profile, {
1137
- providerDefinitions: deps.providerDefinitions ?? DEFAULT_PROVIDER_DEFINITIONS
1138
- });
1139
- } catch (error) {
1140
- return { message: error instanceof Error ? error.message : String(error), success: false };
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(cwd, interactiveSession, registry, manager, providerDefinitions) {
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
- [cwd, interactiveSession, registry, manager, providerDefinitions]
946
+ [interactiveSession, registry, manager]
1192
947
  );
1193
948
  }
1194
- async function routeProviderCommand(cwd, args, interactiveSession, manager, providerDefinitions) {
1195
- const result = await handleProviderCommand(cwd, args, { providerDefinitions });
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 (typeof data?.modelId === "string") {
1211
- effects._pendingModelId = data.modelId;
1212
- return;
953
+ if (result.interaction !== void 0) {
954
+ effects._pendingCommandInteraction = result.interaction;
1213
955
  }
1214
- if (typeof data?.language === "string") {
1215
- effects._pendingLanguage = data.language;
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 import_agent_sdk.InteractiveSession({
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 import_agent_sdk.CommandRegistry();
1304
- registry.addSource(new import_agent_sdk.BuiltinCommandSource());
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 import_agent_sdk.SkillCommandSource(props.cwd));
1309
- const pluginsDir = (0, import_node_path4.join)((0, import_node_os3.homedir)(), ".robota", "plugins");
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/useSideEffects.ts
1561
- var import_react4 = require("react");
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/utils/provider-setup-interaction.ts
1566
- function startProviderSetupInteraction(providerDefinitions, type) {
1567
- if (type === void 0) {
1568
- const state2 = {
1569
- mode: "select-provider",
1570
- providerDefinitions
1571
- };
1572
- return { status: "prompt", state: state2, prompt: toProviderSelectionPrompt(providerDefinitions) };
1573
- }
1574
- const state = {
1575
- mode: "setup-fields",
1576
- providerDefinitions,
1577
- flow: createProviderSetupFlow(type, providerDefinitions)
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
- return { status: "prompt", state, prompt: toProviderSetupStepPrompt(state.flow) };
1580
- }
1581
- function submitProviderSetupInteractionValue(state, value) {
1582
- if (state.mode === "select-provider") {
1583
- const nextState2 = {
1584
- mode: "setup-fields",
1585
- providerDefinitions: state.providerDefinitions,
1586
- flow: createProviderSetupFlow(value, state.providerDefinitions)
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
- status: "prompt",
1590
- state: nextState2,
1591
- prompt: toProviderSetupStepPrompt(nextState2.flow)
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
- const result = submitProviderSetupValue(state.flow, value);
1595
- if (result.status === "complete") {
1596
- return { status: "complete", input: result.input };
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
- const nextState = {
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 toProviderSelectionPrompt(providerDefinitions) {
1605
- return {
1606
- kind: "choice",
1607
- title: "Select provider",
1608
- options: providerDefinitions.map((definition) => ({
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 toProviderSetupStepPrompt(flow) {
1616
- const step = getProviderSetupStep(flow);
1258
+ function createCliPluginCommandAdapter(cwd) {
1259
+ const services = createCliPluginServices(cwd);
1617
1260
  return {
1618
- kind: "text",
1619
- title: step.title,
1620
- ...step.defaultValue !== void 0 ? { placeholder: step.defaultValue } : {},
1621
- ...step.defaultValue !== void 0 ? { allowEmpty: true } : {},
1622
- ...step.masked !== void 0 ? { masked: step.masked } : {},
1623
- validate: (value) => validateProviderSetupValue(step, value)
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
- enabled: true,
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 providerSetupInteractionRef = (0, import_react4.useRef)(null);
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, import_agent_core4.messageToHistoryEntry)((0, import_agent_core4.createSystemMessage)("Shutting down...")));
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
- const settingsPath = getUserSettingsPath();
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
- requestShutdown("prompt_input_exit", "User requested exit");
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
- setShowSessionPicker(true);
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
- interactiveSession.setName(name);
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
- addEntry,
1776
- requestShutdown,
1777
- setSessionName,
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
- try {
1789
- const settingsPath = getUserSettingsPath();
1790
- updateModelInSettings(settingsPath, modelId);
1791
- addEntry(
1792
- (0, import_agent_core4.messageToHistoryEntry)(
1793
- (0, import_agent_core4.createSystemMessage)(`Model changed to ${(0, import_agent_core4.getModelName)(modelId)}. Restarting...`)
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((0, import_agent_core4.messageToHistoryEntry)((0, import_agent_core4.createSystemMessage)("Provider change cancelled.")));
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, providerDefinitions]
1571
+ [cwd, providerOverride, addEntry, requestShutdown]
1862
1572
  );
1863
1573
  const handleInteractionSubmit = (0, import_react4.useCallback)(
1864
- (value) => {
1865
- const state = providerSetupInteractionRef.current;
1866
- if (state === null) {
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 = submitProviderSetupInteractionValue(state, value);
1872
- if (result.status === "complete") {
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
- providerSetupInteractionRef.current = null;
1584
+ commandInteractionRef.current = null;
1880
1585
  setPendingInteractionPrompt(null);
1881
1586
  addEntry(
1882
- (0, import_agent_core4.messageToHistoryEntry)(
1883
- (0, import_agent_core4.createSystemMessage)(`Failed: ${err instanceof Error ? err.message : String(err)}`)
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, completeProviderSetup]
1593
+ [addEntry, applyCommandResult]
1889
1594
  );
1890
1595
  const handleInteractionCancel = (0, import_react4.useCallback)(() => {
1891
- providerSetupInteractionRef.current = null;
1596
+ const interaction = commandInteractionRef.current;
1597
+ commandInteractionRef.current = null;
1892
1598
  setPendingInteractionPrompt(null);
1893
- addEntry((0, import_agent_core4.messageToHistoryEntry)((0, import_agent_core4.createSystemMessage)("Provider setup cancelled.")));
1894
- }, [addEntry]);
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 import_agent_core6 = require("@robota-sdk/agent-core");
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 import_agent_core5 = require("@robota-sdk/agent-core");
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, import_agent_core5.formatTokenCount)(
1790
+ const context = `${Math.round(usage.contextUsedPercentage)}% (${(0, import_agent_core7.formatTokenCount)(
2077
1791
  usage.contextUsedTokens
2078
- )}/${(0, import_agent_core5.formatTokenCount)(usage.contextMaxTokens)})`;
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, import_agent_core5.formatTokenCount)(tokens);
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, import_agent_core6.isToolMessage)(message)) {
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, import_agent_core6.isToolMessage)(message)) {
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, import_agent_core6.isAssistantMessage)(message) ? renderMarkdown(content + (isInterrupted ? "\n\n_(interrupted)_" : "")) : content }) })
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 import_agent_core8 = require("@robota-sdk/agent-core");
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 import_agent_core7 = require("@robota-sdk/agent-core");
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, import_agent_core7.formatTokenCount)(usedTokens),
2229
+ (0, import_agent_core9.formatTokenCount)(usedTokens),
2516
2230
  "/",
2517
- (0, import_agent_core7.formatTokenCount)(maxTokens),
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)(import_ink6.Text, { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_ink6.Text, { dimColor: true, children: [
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, import_agent_core8.getModelName)(modelId) : "",
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 StreamingIndicator({ text, activeTools }) {
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 /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_jsx_runtime16.Fragment, {});
3642
+ return renderThinkingFallback(isThinking);
3888
3643
  }
3889
3644
  return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_ink16.Box, { flexDirection: "column", children: [
3890
- hasTools && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_ink16.Box, { flexDirection: "column", marginBottom: 1, children: [
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
- providerDefinitions
4533
+ commandHostAdapters: props.commandHostAdapters
4793
4534
  });
4794
- const pluginCallbacks = usePluginCallbacks(cwd);
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)(StreamingIndicator, { text: streamingText, activeTools }) }),
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: `Change model to ${(0, import_agent_core9.getModelName)(pendingModelId)}? This will restart the session.`,
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, import_agent_core9.messageToHistoryEntry)((0, import_agent_core9.createSystemMessage)(msg.content)))
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, import_agent_core9.messageToHistoryEntry)((0, import_agent_core9.createSystemMessage)("Session resume cancelled.")));
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 import_agent_sdk3 = require("@robota-sdk/agent-sdk");
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 import_agent_sdk3.BackgroundTaskError("runner", `Invalid process task kind: ${task.request.kind}`);
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 import_agent_sdk3.BackgroundTaskError("timeout", "Background process timed out"));
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 import_agent_sdk3.BackgroundTaskError("process", error.message));
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 import_agent_sdk7 = require("@robota-sdk/agent-sdk");
4913
+ var import_agent_sdk13 = require("@robota-sdk/agent-sdk");
5174
4914
 
5175
4915
  // src/subagents/child-process-subagent-runner-result.ts
5176
- var import_agent_sdk5 = require("@robota-sdk/agent-sdk");
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 import_agent_sdk4 = require("@robota-sdk/agent-sdk");
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 import_agent_sdk4.BackgroundTaskError("runner", message.message));
4958
+ rejectOnce(new import_agent_sdk10.BackgroundTaskError("runner", message.message));
5219
4959
  break;
5220
4960
  case "cancelled":
5221
- rejectOnce(new import_agent_sdk4.BackgroundTaskError("runner", message.reason ?? "Subagent worker cancelled"));
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 import_agent_sdk4.BackgroundTaskError("runner", "Unhandled subagent worker message"));
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 import_agent_sdk4.BackgroundTaskError("crash", "Subagent worker IPC channel is closed"));
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 import_agent_sdk5.BackgroundTaskError("runner", "Received malformed subagent worker message")
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 import_agent_sdk5.BackgroundTaskError("crash", error.message));
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 import_agent_sdk5.BackgroundTaskError("crash", formatEarlyExitMessage(code, signal)));
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 import_agent_sdk5.BackgroundTaskError("runner", reason ?? `Subagent job cancelled: ${jobId}`));
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 import_agent_sdk5.BackgroundTaskError("timeout", "Subagent worker timed out"));
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 import_agent_sdk6 = require("@robota-sdk/agent-sdk");
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
- const repoRoot = runGit(request.cwd, ["rev-parse", "--show-toplevel"]).trim();
5412
- const shortId = (0, import_node_crypto2.randomUUID)().slice(0, SHORT_ID_LENGTH);
5413
- const branchName = `${this.branchPrefix}/${request.jobId}-${shortId}`;
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
- runGit(repoRoot, ["worktree", "add", "-b", branchName, worktreePath, "HEAD"]);
5418
- return { repoRoot, worktreePath, branchName };
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 runGit(worktree.worktreePath, ["status", "--porcelain"]).trim().length === 0;
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 import_agent_sdk6.BackgroundTaskError("runner", `git ${args.join(" ")} failed: ${message}`);
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, import_agent_sdk7.createWorktreeSubagentRunner)({
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, import_agent_sdk7.getBuiltInAgent)(agentType);
5335
+ const definition = customRegistry?.(agentType) ?? (0, import_agent_sdk13.getBuiltInAgent)(agentType);
5531
5336
  if (!definition) {
5532
- throw new import_agent_sdk7.BackgroundTaskError("validation", `Unknown agent type: ${agentType}`);
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
- createStatusLineCommandModule(),
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, import_agent_sdk8.projectPaths)(cwd);
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 import_agent_sdk8.InteractiveSession({
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
- providerDefinitions,
5638
+ commandHostAdapters,
5889
5639
  startupUpdateNoticePromise
5890
5640
  });
5891
5641
  }