@robota-sdk/agent-cli 3.0.0-beta.24 → 3.0.0-beta.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/node/bin.cjs CHANGED
@@ -25,10 +25,10 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
25
25
 
26
26
  // src/cli.ts
27
27
  var import_node_fs3 = require("fs");
28
- var import_node_path3 = require("path");
28
+ var import_node_path5 = require("path");
29
29
  var import_node_url = require("url");
30
- var import_agent_sdk2 = require("@robota-sdk/agent-sdk");
31
- var import_agent_sdk3 = require("@robota-sdk/agent-sdk");
30
+ var import_agent_sdk4 = require("@robota-sdk/agent-sdk");
31
+ var import_agent_sdk5 = require("@robota-sdk/agent-sdk");
32
32
 
33
33
  // src/utils/cli-args.ts
34
34
  var import_node_util = require("util");
@@ -166,7 +166,7 @@ var PrintTerminal = class {
166
166
  var import_ink11 = require("ink");
167
167
 
168
168
  // src/ui/App.tsx
169
- var import_react11 = require("react");
169
+ var import_react12 = require("react");
170
170
  var import_ink10 = require("ink");
171
171
  var import_agent_core3 = require("@robota-sdk/agent-core");
172
172
 
@@ -386,7 +386,122 @@ function handleReset(addMessage) {
386
386
  }
387
387
  return { handled: true, exitRequested: true };
388
388
  }
389
- async function executeSlashCommand(cmd, args, session, addMessage, clearMessages, registry) {
389
+ async function handlePluginCommand(args, addMessage, callbacks) {
390
+ const parts = args.trim().split(/\s+/);
391
+ const subcommand = parts[0] ?? "";
392
+ const subArgs = parts.slice(1).join(" ").trim();
393
+ try {
394
+ switch (subcommand) {
395
+ case "":
396
+ case void 0: {
397
+ const plugins = await callbacks.listInstalled();
398
+ if (plugins.length === 0) {
399
+ addMessage({ role: "system", content: "No plugins installed." });
400
+ } else {
401
+ const lines = plugins.map(
402
+ (p) => ` ${p.name} \u2014 ${p.description} [${p.enabled ? "enabled" : "disabled"}]`
403
+ );
404
+ addMessage({ role: "system", content: `Installed plugins:
405
+ ${lines.join("\n")}` });
406
+ }
407
+ return { handled: true };
408
+ }
409
+ case "install": {
410
+ if (!subArgs) {
411
+ addMessage({ role: "system", content: "Usage: /plugin install <name>@<marketplace>" });
412
+ return { handled: true };
413
+ }
414
+ await callbacks.install(subArgs);
415
+ addMessage({ role: "system", content: `Installed plugin: ${subArgs}` });
416
+ return { handled: true };
417
+ }
418
+ case "uninstall": {
419
+ if (!subArgs) {
420
+ addMessage({ role: "system", content: "Usage: /plugin uninstall <name>@<marketplace>" });
421
+ return { handled: true };
422
+ }
423
+ await callbacks.uninstall(subArgs);
424
+ addMessage({ role: "system", content: `Uninstalled plugin: ${subArgs}` });
425
+ return { handled: true };
426
+ }
427
+ case "enable": {
428
+ if (!subArgs) {
429
+ addMessage({ role: "system", content: "Usage: /plugin enable <name>@<marketplace>" });
430
+ return { handled: true };
431
+ }
432
+ await callbacks.enable(subArgs);
433
+ addMessage({ role: "system", content: `Enabled plugin: ${subArgs}` });
434
+ return { handled: true };
435
+ }
436
+ case "disable": {
437
+ if (!subArgs) {
438
+ addMessage({ role: "system", content: "Usage: /plugin disable <name>@<marketplace>" });
439
+ return { handled: true };
440
+ }
441
+ await callbacks.disable(subArgs);
442
+ addMessage({ role: "system", content: `Disabled plugin: ${subArgs}` });
443
+ return { handled: true };
444
+ }
445
+ case "marketplace": {
446
+ const mpParts = subArgs.split(/\s+/);
447
+ const mpSubcommand = mpParts[0] ?? "";
448
+ const mpArgs = mpParts.slice(1).join(" ").trim();
449
+ if (mpSubcommand === "add" && mpArgs) {
450
+ const registeredName = await callbacks.marketplaceAdd(mpArgs);
451
+ addMessage({
452
+ role: "system",
453
+ content: `Added marketplace: "${registeredName}" (from ${mpArgs})
454
+ Install plugins with: /plugin install <name>@${registeredName}`
455
+ });
456
+ return { handled: true };
457
+ } else if (mpSubcommand === "remove" && mpArgs) {
458
+ await callbacks.marketplaceRemove(mpArgs);
459
+ addMessage({
460
+ role: "system",
461
+ content: `Removed marketplace "${mpArgs}" and uninstalled its plugins.`
462
+ });
463
+ return { handled: true };
464
+ } else if (mpSubcommand === "update" && mpArgs) {
465
+ await callbacks.marketplaceUpdate(mpArgs);
466
+ addMessage({
467
+ role: "system",
468
+ content: `Updated marketplace "${mpArgs}".`
469
+ });
470
+ return { handled: true };
471
+ } else if (mpSubcommand === "list") {
472
+ const sources = await callbacks.marketplaceList();
473
+ if (sources.length === 0) {
474
+ addMessage({ role: "system", content: "No marketplace sources configured." });
475
+ } else {
476
+ const lines = sources.map((s) => ` ${s.name} (${s.type})`);
477
+ addMessage({ role: "system", content: `Marketplace sources:
478
+ ${lines.join("\n")}` });
479
+ }
480
+ return { handled: true };
481
+ } else {
482
+ addMessage({
483
+ role: "system",
484
+ content: "Usage: /plugin marketplace add <source> | remove <name> | update <name> | list"
485
+ });
486
+ return { handled: true };
487
+ }
488
+ }
489
+ default:
490
+ addMessage({ role: "system", content: `Unknown plugin subcommand: ${subcommand}` });
491
+ return { handled: true };
492
+ }
493
+ } catch (error) {
494
+ const message = error instanceof Error ? error.message : String(error);
495
+ addMessage({ role: "system", content: `Plugin error: ${message}` });
496
+ return { handled: true };
497
+ }
498
+ }
499
+ async function handleReloadPlugins(addMessage, callbacks) {
500
+ await callbacks.reloadPlugins();
501
+ addMessage({ role: "system", content: "Plugins reload complete." });
502
+ return { handled: true };
503
+ }
504
+ async function executeSlashCommand(cmd, args, session, addMessage, clearMessages, registry, pluginCallbacks) {
390
505
  switch (cmd) {
391
506
  case "help":
392
507
  return handleHelp(addMessage);
@@ -410,10 +525,22 @@ async function executeSlashCommand(cmd, args, session, addMessage, clearMessages
410
525
  return handleReset(addMessage);
411
526
  case "exit":
412
527
  return { handled: true, exitRequested: true };
528
+ case "plugin":
529
+ if (pluginCallbacks) {
530
+ return handlePluginCommand(args, addMessage, pluginCallbacks);
531
+ }
532
+ addMessage({ role: "system", content: "Plugin management is not available." });
533
+ return { handled: true };
534
+ case "reload-plugins":
535
+ if (pluginCallbacks) {
536
+ return handleReloadPlugins(addMessage, pluginCallbacks);
537
+ }
538
+ addMessage({ role: "system", content: "Plugin management is not available." });
539
+ return { handled: true };
413
540
  default: {
414
- const skillCmd = registry.getCommands().find((c) => c.name === cmd && c.source === "skill");
415
- if (skillCmd) {
416
- addMessage({ role: "system", content: `Invoking skill: ${cmd}` });
541
+ const dynamicCmd = registry.getCommands().find((c) => c.name === cmd && (c.source === "skill" || c.source === "plugin"));
542
+ if (dynamicCmd) {
543
+ addMessage({ role: "system", content: `Invoking ${dynamicCmd.source}: ${cmd}` });
417
544
  return { handled: false };
418
545
  }
419
546
  addMessage({ role: "system", content: `Unknown command "/${cmd}". Type /help for help.` });
@@ -424,14 +551,22 @@ async function executeSlashCommand(cmd, args, session, addMessage, clearMessages
424
551
 
425
552
  // src/ui/hooks/useSlashCommands.ts
426
553
  var EXIT_DELAY_MS = 500;
427
- function useSlashCommands(session, addMessage, setMessages, exit, registry, pendingModelChangeRef, setPendingModelId) {
554
+ function useSlashCommands(session, addMessage, setMessages, exit, registry, pendingModelChangeRef, setPendingModelId, pluginCallbacks) {
428
555
  return (0, import_react3.useCallback)(
429
556
  async (input) => {
430
557
  const parts = input.slice(1).split(/\s+/);
431
558
  const cmd = parts[0]?.toLowerCase() ?? "";
432
559
  const args = parts.slice(1).join(" ");
433
560
  const clearMessages = () => setMessages([]);
434
- const result = await executeSlashCommand(cmd, args, session, addMessage, clearMessages, registry);
561
+ const result = await executeSlashCommand(
562
+ cmd,
563
+ args,
564
+ session,
565
+ addMessage,
566
+ clearMessages,
567
+ registry,
568
+ pluginCallbacks
569
+ );
435
570
  if (result.pendingModelId) {
436
571
  pendingModelChangeRef.current = result.pendingModelId;
437
572
  setPendingModelId(result.pendingModelId);
@@ -441,7 +576,16 @@ function useSlashCommands(session, addMessage, setMessages, exit, registry, pend
441
576
  }
442
577
  return result.handled;
443
578
  },
444
- [session, addMessage, setMessages, exit, registry, pendingModelChangeRef, setPendingModelId]
579
+ [
580
+ session,
581
+ addMessage,
582
+ setMessages,
583
+ exit,
584
+ registry,
585
+ pendingModelChangeRef,
586
+ setPendingModelId,
587
+ pluginCallbacks
588
+ ]
445
589
  );
446
590
  }
447
591
 
@@ -476,16 +620,60 @@ function parseFirstArgValue(argsJson) {
476
620
  }
477
621
 
478
622
  // src/utils/skill-prompt.ts
479
- function buildSkillPrompt(input, registry) {
623
+ var import_node_child_process = require("child_process");
624
+ function substituteVariables(content, args, context) {
625
+ const argParts = args ? args.split(/\s+/) : [];
626
+ let result = content;
627
+ result = result.replace(/\$ARGUMENTS\[(\d+)]/g, (_match, index) => {
628
+ return argParts[Number(index)] ?? "";
629
+ });
630
+ result = result.replace(/\$ARGUMENTS/g, args);
631
+ result = result.replace(/\$(\d)(?!\d|\w|\[)/g, (_match, digit) => {
632
+ return argParts[Number(digit)] ?? "";
633
+ });
634
+ result = result.replace(/\$\{CLAUDE_SESSION_ID}/g, context?.sessionId ?? "");
635
+ result = result.replace(/\$\{CLAUDE_SKILL_DIR}/g, context?.skillDir ?? "");
636
+ return result;
637
+ }
638
+ async function preprocessShellCommands(content) {
639
+ const shellPattern = /!`([^`]+)`/g;
640
+ if (!shellPattern.test(content)) {
641
+ return content;
642
+ }
643
+ shellPattern.lastIndex = 0;
644
+ let result = content;
645
+ let match;
646
+ const matches = [];
647
+ while ((match = shellPattern.exec(content)) !== null) {
648
+ matches.push({ full: match[0], command: match[1] });
649
+ }
650
+ for (const { full, command } of matches) {
651
+ let output = "";
652
+ try {
653
+ output = (0, import_node_child_process.execSync)(command, {
654
+ timeout: 5e3,
655
+ encoding: "utf-8",
656
+ stdio: ["pipe", "pipe", "pipe"]
657
+ }).trimEnd();
658
+ } catch {
659
+ output = "";
660
+ }
661
+ result = result.replace(full, output);
662
+ }
663
+ return result;
664
+ }
665
+ async function buildSkillPrompt(input, registry, context) {
480
666
  const parts = input.slice(1).split(/\s+/);
481
667
  const cmd = parts[0]?.toLowerCase() ?? "";
482
- const skillCmd = registry.getCommands().find((c) => c.name === cmd && c.source === "skill");
668
+ const skillCmd = registry.getCommands().find((c) => c.name === cmd && (c.source === "skill" || c.source === "plugin"));
483
669
  if (!skillCmd) return null;
484
670
  const args = parts.slice(1).join(" ").trim();
485
671
  const userInstruction = args || skillCmd.description;
486
672
  if (skillCmd.skillContent) {
673
+ let processed = await preprocessShellCommands(skillCmd.skillContent);
674
+ processed = substituteVariables(processed, args, context);
487
675
  return `<skill name="${cmd}">
488
- ${skillCmd.skillContent}
676
+ ${processed}
489
677
  </skill>
490
678
 
491
679
  Execute the "${cmd}" skill: ${userInstruction}`;
@@ -498,12 +686,12 @@ function syncContextState(session, setter) {
498
686
  const ctx = session.getContextState();
499
687
  setter({ percentage: ctx.usedPercentage, usedTokens: ctx.usedTokens, maxTokens: ctx.maxTokens });
500
688
  }
501
- async function runSessionPrompt(prompt, session, addMessage, clearStreamingText, setIsThinking, setContextState) {
689
+ async function runSessionPrompt(prompt, session, addMessage, clearStreamingText, setIsThinking, setContextState, rawInput) {
502
690
  setIsThinking(true);
503
691
  clearStreamingText();
504
692
  const historyBefore = session.getHistory().length;
505
693
  try {
506
- const response = await session.run(prompt);
694
+ const response = await session.run(prompt, rawInput);
507
695
  clearStreamingText();
508
696
  const history = session.getHistory();
509
697
  const toolLines = extractToolCalls(
@@ -511,7 +699,11 @@ async function runSessionPrompt(prompt, session, addMessage, clearStreamingText,
511
699
  historyBefore
512
700
  );
513
701
  if (toolLines.length > 0) {
514
- addMessage({ role: "tool", content: toolLines.join("\n"), toolName: `${toolLines.length} tools` });
702
+ addMessage({
703
+ role: "tool",
704
+ content: toolLines.join("\n"),
705
+ toolName: `${toolLines.length} tools`
706
+ });
515
707
  }
516
708
  addMessage({ role: "assistant", content: response || "(empty response)" });
517
709
  syncContextState(session, setContextState);
@@ -536,19 +728,45 @@ function useSubmitHandler(session, addMessage, handleSlashCommand, clearStreamin
536
728
  syncContextState(session, setContextState);
537
729
  return;
538
730
  }
539
- const prompt = buildSkillPrompt(input, registry);
731
+ const prompt = await buildSkillPrompt(input, registry);
540
732
  if (!prompt) return;
541
- return runSessionPrompt(prompt, session, addMessage, clearStreamingText, setIsThinking, setContextState);
733
+ return runSessionPrompt(
734
+ prompt,
735
+ session,
736
+ addMessage,
737
+ clearStreamingText,
738
+ setIsThinking,
739
+ setContextState,
740
+ input
741
+ );
542
742
  }
543
743
  addMessage({ role: "user", content: input });
544
- return runSessionPrompt(input, session, addMessage, clearStreamingText, setIsThinking, setContextState);
744
+ return runSessionPrompt(
745
+ input,
746
+ session,
747
+ addMessage,
748
+ clearStreamingText,
749
+ setIsThinking,
750
+ setContextState
751
+ );
545
752
  },
546
- [session, addMessage, handleSlashCommand, clearStreamingText, setIsThinking, setContextState, registry]
753
+ [
754
+ session,
755
+ addMessage,
756
+ handleSlashCommand,
757
+ clearStreamingText,
758
+ setIsThinking,
759
+ setContextState,
760
+ registry
761
+ ]
547
762
  );
548
763
  }
549
764
 
550
765
  // src/ui/hooks/useCommandRegistry.ts
551
766
  var import_react5 = require("react");
767
+ var import_node_os2 = require("os");
768
+ var import_node_path3 = require("path");
769
+ var import_agent_sdk2 = require("@robota-sdk/agent-sdk");
552
770
 
553
771
  // src/commands/command-registry.ts
554
772
  var CommandRegistry = class {
@@ -632,6 +850,23 @@ function createBuiltinCommands() {
632
850
  { name: "cost", description: "Show session info", source: "builtin" },
633
851
  { name: "context", description: "Context window info", source: "builtin" },
634
852
  { name: "permissions", description: "Permission rules", source: "builtin" },
853
+ {
854
+ name: "plugin",
855
+ description: "Manage plugins",
856
+ source: "builtin",
857
+ subcommands: [
858
+ { name: "install", description: "Install a plugin (name@marketplace)", source: "builtin" },
859
+ {
860
+ name: "uninstall",
861
+ description: "Uninstall a plugin (name@marketplace)",
862
+ source: "builtin"
863
+ },
864
+ { name: "enable", description: "Enable a plugin (name@marketplace)", source: "builtin" },
865
+ { name: "disable", description: "Disable a plugin (name@marketplace)", source: "builtin" },
866
+ { name: "marketplace", description: "Manage marketplace sources", source: "builtin" }
867
+ ]
868
+ },
869
+ { name: "reload-plugins", description: "Reload all plugin resources", source: "builtin" },
635
870
  { name: "reset", description: "Delete settings and exit", source: "builtin" },
636
871
  { name: "exit", description: "Exit CLI", source: "builtin" }
637
872
  ];
@@ -651,25 +886,50 @@ var BuiltinCommandSource = class {
651
886
  var import_node_fs2 = require("fs");
652
887
  var import_node_path2 = require("path");
653
888
  var import_node_os = require("os");
889
+ var BOOLEAN_KEYS = /* @__PURE__ */ new Set(["disable-model-invocation", "user-invocable"]);
890
+ var LIST_KEYS = /* @__PURE__ */ new Set(["allowed-tools"]);
891
+ function kebabToCamel(key) {
892
+ return key.replace(/-([a-z])/g, (_match, letter) => letter.toUpperCase());
893
+ }
654
894
  function parseFrontmatter(content) {
655
895
  const lines = content.split("\n");
656
896
  if (lines[0]?.trim() !== "---") return null;
657
- let name = "";
658
- let description = "";
897
+ const result = {};
659
898
  for (let i = 1; i < lines.length; i++) {
660
899
  const line = lines[i];
661
900
  if (line.trim() === "---") break;
662
- const nameMatch = line.match(/^name:\s*(.+)/);
663
- if (nameMatch) {
664
- name = nameMatch[1].trim();
665
- continue;
666
- }
667
- const descMatch = line.match(/^description:\s*(.+)/);
668
- if (descMatch) {
669
- description = descMatch[1].trim();
901
+ const match = line.match(/^([a-z][a-z0-9-]*):\s*(.+)/);
902
+ if (!match) continue;
903
+ const key = match[1];
904
+ const rawValue = match[2].trim();
905
+ const camelKey = kebabToCamel(key);
906
+ if (BOOLEAN_KEYS.has(key)) {
907
+ result[camelKey] = rawValue === "true";
908
+ } else if (LIST_KEYS.has(key)) {
909
+ result[camelKey] = rawValue.split(",").map((s) => s.trim());
910
+ } else {
911
+ result[camelKey] = rawValue;
670
912
  }
671
913
  }
672
- return name ? { name, description } : null;
914
+ return Object.keys(result).length > 0 ? result : null;
915
+ }
916
+ function buildCommand(frontmatter, content, fallbackName) {
917
+ const cmd = {
918
+ name: frontmatter?.name ?? fallbackName,
919
+ description: frontmatter?.description ?? `Skill: ${fallbackName}`,
920
+ source: "skill",
921
+ skillContent: content
922
+ };
923
+ if (frontmatter?.argumentHint !== void 0) cmd.argumentHint = frontmatter.argumentHint;
924
+ if (frontmatter?.disableModelInvocation !== void 0)
925
+ cmd.disableModelInvocation = frontmatter.disableModelInvocation;
926
+ if (frontmatter?.userInvocable !== void 0) cmd.userInvocable = frontmatter.userInvocable;
927
+ if (frontmatter?.allowedTools !== void 0) cmd.allowedTools = frontmatter.allowedTools;
928
+ if (frontmatter?.model !== void 0) cmd.model = frontmatter.model;
929
+ if (frontmatter?.effort !== void 0) cmd.effort = frontmatter.effort;
930
+ if (frontmatter?.context !== void 0) cmd.context = frontmatter.context;
931
+ if (frontmatter?.agent !== void 0) cmd.agent = frontmatter.agent;
932
+ return cmd;
673
933
  }
674
934
  function scanSkillsDir(skillsDir) {
675
935
  if (!(0, import_node_fs2.existsSync)(skillsDir)) return [];
@@ -681,48 +941,246 @@ function scanSkillsDir(skillsDir) {
681
941
  if (!(0, import_node_fs2.existsSync)(skillFile)) continue;
682
942
  const content = (0, import_node_fs2.readFileSync)(skillFile, "utf-8");
683
943
  const frontmatter = parseFrontmatter(content);
684
- commands.push({
685
- name: frontmatter?.name ?? entry.name,
686
- description: frontmatter?.description ?? `Skill: ${entry.name}`,
687
- source: "skill",
688
- skillContent: content
689
- });
944
+ commands.push(buildCommand(frontmatter, content, entry.name));
945
+ }
946
+ return commands;
947
+ }
948
+ function scanCommandsDir(commandsDir) {
949
+ if (!(0, import_node_fs2.existsSync)(commandsDir)) return [];
950
+ const commands = [];
951
+ const entries = (0, import_node_fs2.readdirSync)(commandsDir, { withFileTypes: true });
952
+ for (const entry of entries) {
953
+ if (!entry.isFile() || !entry.name.endsWith(".md")) continue;
954
+ const filePath = (0, import_node_path2.join)(commandsDir, entry.name);
955
+ const content = (0, import_node_fs2.readFileSync)(filePath, "utf-8");
956
+ const frontmatter = parseFrontmatter(content);
957
+ const fallbackName = (0, import_node_path2.basename)(entry.name, ".md");
958
+ commands.push(buildCommand(frontmatter, content, fallbackName));
690
959
  }
691
960
  return commands;
692
961
  }
693
962
  var SkillCommandSource = class {
694
963
  name = "skill";
695
964
  cwd;
965
+ home;
696
966
  cachedCommands = null;
697
- constructor(cwd) {
967
+ constructor(cwd, home) {
698
968
  this.cwd = cwd;
969
+ this.home = home ?? (0, import_node_os.homedir)();
699
970
  }
700
971
  getCommands() {
701
972
  if (this.cachedCommands) return this.cachedCommands;
702
- const projectSkills = scanSkillsDir((0, import_node_path2.join)(this.cwd, ".agents", "skills"));
703
- const userSkills = scanSkillsDir((0, import_node_path2.join)((0, import_node_os.homedir)(), ".claude", "skills"));
704
- const seen = new Set(projectSkills.map((cmd) => cmd.name));
705
- const merged = [...projectSkills];
706
- for (const cmd of userSkills) {
707
- if (!seen.has(cmd.name)) {
708
- merged.push(cmd);
973
+ const sources = [
974
+ scanSkillsDir((0, import_node_path2.join)(this.cwd, ".claude", "skills")),
975
+ // 1. project .claude/skills
976
+ scanCommandsDir((0, import_node_path2.join)(this.cwd, ".claude", "commands")),
977
+ // 2. project .claude/commands (legacy)
978
+ scanSkillsDir((0, import_node_path2.join)(this.home, ".robota", "skills")),
979
+ // 3. user ~/.robota/skills
980
+ scanSkillsDir((0, import_node_path2.join)(this.cwd, ".agents", "skills"))
981
+ // 4. project .agents/skills
982
+ ];
983
+ const seen = /* @__PURE__ */ new Set();
984
+ const merged = [];
985
+ for (const commands of sources) {
986
+ for (const cmd of commands) {
987
+ if (!seen.has(cmd.name)) {
988
+ seen.add(cmd.name);
989
+ merged.push(cmd);
990
+ }
709
991
  }
710
992
  }
711
993
  this.cachedCommands = merged;
712
994
  return this.cachedCommands;
713
995
  }
996
+ /** Get skills that models can invoke (excludes disableModelInvocation: true) */
997
+ getModelInvocableSkills() {
998
+ return this.getCommands().filter((cmd) => cmd.disableModelInvocation !== true);
999
+ }
1000
+ /** Get skills that users can invoke (excludes userInvocable: false) */
1001
+ getUserInvocableSkills() {
1002
+ return this.getCommands().filter((cmd) => cmd.userInvocable !== false);
1003
+ }
1004
+ };
1005
+
1006
+ // src/commands/plugin-source.ts
1007
+ var PluginCommandSource = class {
1008
+ name = "plugin";
1009
+ plugins;
1010
+ constructor(plugins) {
1011
+ this.plugins = plugins;
1012
+ }
1013
+ getCommands() {
1014
+ const commands = [];
1015
+ for (const plugin of this.plugins) {
1016
+ for (const skill of plugin.skills) {
1017
+ const baseName = skill.name.includes("@") ? skill.name.split("@")[0] : skill.name;
1018
+ commands.push({
1019
+ name: baseName,
1020
+ description: `${skill.description} (${plugin.manifest.name})`,
1021
+ source: "plugin",
1022
+ skillContent: skill.skillContent,
1023
+ pluginDir: plugin.pluginDir
1024
+ });
1025
+ }
1026
+ for (const cmd of plugin.commands) {
1027
+ commands.push({
1028
+ name: cmd.name,
1029
+ description: cmd.description,
1030
+ source: "plugin",
1031
+ skillContent: cmd.skillContent,
1032
+ pluginDir: plugin.pluginDir
1033
+ });
1034
+ }
1035
+ }
1036
+ return commands;
1037
+ }
714
1038
  };
715
1039
 
716
1040
  // src/ui/hooks/useCommandRegistry.ts
1041
+ function buildPluginEnv(plugin) {
1042
+ const dataDir = (0, import_node_path3.join)((0, import_node_path3.dirname)((0, import_node_path3.dirname)(plugin.pluginDir)), "data", plugin.manifest.name);
1043
+ return {
1044
+ CLAUDE_PLUGIN_ROOT: plugin.pluginDir,
1045
+ CLAUDE_PLUGIN_PATH: plugin.pluginDir,
1046
+ CLAUDE_PLUGIN_DATA: dataDir
1047
+ };
1048
+ }
1049
+ function mergePluginHooks(plugins) {
1050
+ const merged = {};
1051
+ for (const plugin of plugins) {
1052
+ const hooksObj = plugin.hooks;
1053
+ if (!hooksObj) continue;
1054
+ const pluginEnv = buildPluginEnv(plugin);
1055
+ const innerHooks = hooksObj.hooks ?? hooksObj;
1056
+ for (const [event, groups] of Object.entries(innerHooks)) {
1057
+ if (!Array.isArray(groups)) continue;
1058
+ if (!merged[event]) merged[event] = [];
1059
+ const resolved = groups.map((group) => {
1060
+ const resolved2 = resolvePluginRoot(group, plugin.pluginDir);
1061
+ if (typeof resolved2 === "object" && resolved2 !== null) {
1062
+ resolved2.env = pluginEnv;
1063
+ }
1064
+ return resolved2;
1065
+ });
1066
+ merged[event].push(...resolved);
1067
+ }
1068
+ }
1069
+ return merged;
1070
+ }
1071
+ function resolvePluginRoot(group, pluginDir) {
1072
+ if (typeof group !== "object" || group === null) return group;
1073
+ const obj = group;
1074
+ if (Array.isArray(obj.hooks)) {
1075
+ return {
1076
+ ...obj,
1077
+ hooks: obj.hooks.map((h) => {
1078
+ if (typeof h !== "object" || h === null) return h;
1079
+ const hook = h;
1080
+ if (typeof hook.command === "string") {
1081
+ return {
1082
+ ...hook,
1083
+ command: hook.command.replace(/\$\{CLAUDE_PLUGIN_ROOT\}/g, pluginDir)
1084
+ };
1085
+ }
1086
+ return hook;
1087
+ })
1088
+ };
1089
+ }
1090
+ return group;
1091
+ }
717
1092
  function useCommandRegistry(cwd) {
718
- const registryRef = (0, import_react5.useRef)(null);
719
- if (registryRef.current === null) {
1093
+ const resultRef = (0, import_react5.useRef)(null);
1094
+ if (resultRef.current === null) {
720
1095
  const registry = new CommandRegistry();
721
1096
  registry.addSource(new BuiltinCommandSource());
722
1097
  registry.addSource(new SkillCommandSource(cwd));
723
- registryRef.current = registry;
1098
+ let pluginHooks = {};
1099
+ const pluginsDir = (0, import_node_path3.join)((0, import_node_os2.homedir)(), ".robota", "plugins");
1100
+ const loader = new import_agent_sdk2.BundlePluginLoader(pluginsDir);
1101
+ try {
1102
+ const plugins = loader.loadPluginsSync();
1103
+ if (plugins.length > 0) {
1104
+ registry.addSource(new PluginCommandSource(plugins));
1105
+ pluginHooks = mergePluginHooks(plugins);
1106
+ }
1107
+ } catch {
1108
+ }
1109
+ resultRef.current = { registry, pluginHooks };
724
1110
  }
725
- return registryRef.current;
1111
+ return resultRef.current;
1112
+ }
1113
+
1114
+ // src/ui/hooks/usePluginCallbacks.ts
1115
+ var import_react6 = require("react");
1116
+ var import_node_os3 = require("os");
1117
+ var import_node_path4 = require("path");
1118
+ var import_agent_sdk3 = require("@robota-sdk/agent-sdk");
1119
+ function usePluginCallbacks(cwd) {
1120
+ return (0, import_react6.useMemo)(() => {
1121
+ const home = (0, import_node_os3.homedir)();
1122
+ const pluginsDir = (0, import_node_path4.join)(home, ".robota", "plugins");
1123
+ const userSettingsPath = (0, import_node_path4.join)(home, ".robota", "settings.json");
1124
+ const settingsStore = new import_agent_sdk3.PluginSettingsStore(userSettingsPath);
1125
+ const marketplace = new import_agent_sdk3.MarketplaceClient({ pluginsDir });
1126
+ const installer = new import_agent_sdk3.BundlePluginInstaller({
1127
+ pluginsDir,
1128
+ settingsStore,
1129
+ marketplaceClient: marketplace
1130
+ });
1131
+ const loader = new import_agent_sdk3.BundlePluginLoader(pluginsDir);
1132
+ return {
1133
+ listInstalled: async () => {
1134
+ const plugins = await loader.loadAll();
1135
+ return plugins.map((p) => ({
1136
+ name: p.manifest.name,
1137
+ description: p.manifest.description,
1138
+ enabled: true
1139
+ }));
1140
+ },
1141
+ install: async (pluginId) => {
1142
+ const [name, marketplaceName] = pluginId.split("@");
1143
+ if (!name || !marketplaceName) {
1144
+ throw new Error("Plugin ID must be in format: name@marketplace");
1145
+ }
1146
+ await installer.install(name, marketplaceName);
1147
+ },
1148
+ uninstall: async (pluginId) => {
1149
+ await installer.uninstall(pluginId);
1150
+ },
1151
+ enable: async (pluginId) => {
1152
+ await installer.enable(pluginId);
1153
+ },
1154
+ disable: async (pluginId) => {
1155
+ await installer.disable(pluginId);
1156
+ },
1157
+ marketplaceAdd: async (source) => {
1158
+ if (source.includes("/") && !source.includes(":")) {
1159
+ return marketplace.addMarketplace({ type: "github", repo: source });
1160
+ } else {
1161
+ return marketplace.addMarketplace({ type: "git", url: source });
1162
+ }
1163
+ },
1164
+ marketplaceRemove: async (name) => {
1165
+ const installedFromMarketplace = installer.getPluginsByMarketplace(name);
1166
+ for (const record of installedFromMarketplace) {
1167
+ await installer.uninstall(`${record.pluginName}@${record.marketplace}`);
1168
+ }
1169
+ marketplace.removeMarketplace(name);
1170
+ },
1171
+ marketplaceUpdate: async (name) => {
1172
+ marketplace.updateMarketplace(name);
1173
+ },
1174
+ marketplaceList: async () => {
1175
+ return marketplace.listMarketplaces().map((m) => ({
1176
+ name: m.name,
1177
+ type: m.source.type
1178
+ }));
1179
+ },
1180
+ reloadPlugins: async () => {
1181
+ }
1182
+ };
1183
+ }, [cwd]);
726
1184
  }
727
1185
 
728
1186
  // src/ui/MessageList.tsx
@@ -845,11 +1303,11 @@ function StatusBar({
845
1303
  }
846
1304
 
847
1305
  // src/ui/InputArea.tsx
848
- var import_react8 = __toESM(require("react"), 1);
1306
+ var import_react9 = __toESM(require("react"), 1);
849
1307
  var import_ink6 = require("ink");
850
1308
 
851
1309
  // src/ui/CjkTextInput.tsx
852
- var import_react6 = require("react");
1310
+ var import_react7 = require("react");
853
1311
  var import_ink3 = require("ink");
854
1312
  var import_chalk = __toESM(require("chalk"), 1);
855
1313
  var import_jsx_runtime3 = require("react/jsx-runtime");
@@ -869,9 +1327,9 @@ function CjkTextInput({
869
1327
  focus = true,
870
1328
  showCursor = true
871
1329
  }) {
872
- const valueRef = (0, import_react6.useRef)(value);
873
- const cursorRef = (0, import_react6.useRef)(value.length);
874
- const [, forceRender] = (0, import_react6.useState)(0);
1330
+ const valueRef = (0, import_react7.useRef)(value);
1331
+ const cursorRef = (0, import_react7.useRef)(value.length);
1332
+ const [, forceRender] = (0, import_react7.useState)(0);
875
1333
  if (value !== valueRef.current) {
876
1334
  valueRef.current = value;
877
1335
  if (cursorRef.current > value.length) {
@@ -948,15 +1406,15 @@ function renderWithCursor(value, cursorOffset, placeholder, showCursor) {
948
1406
  }
949
1407
 
950
1408
  // src/ui/WaveText.tsx
951
- var import_react7 = require("react");
1409
+ var import_react8 = require("react");
952
1410
  var import_ink4 = require("ink");
953
1411
  var import_jsx_runtime4 = require("react/jsx-runtime");
954
1412
  var WAVE_COLORS = ["#666666", "#888888", "#aaaaaa", "#888888"];
955
1413
  var INTERVAL_MS = 400;
956
1414
  var CHARS_PER_GROUP = 4;
957
1415
  function WaveText({ text }) {
958
- const [tick, setTick] = (0, import_react7.useState)(0);
959
- (0, import_react7.useEffect)(() => {
1416
+ const [tick, setTick] = (0, import_react8.useState)(0);
1417
+ (0, import_react8.useEffect)(() => {
960
1418
  const timer = setInterval(() => {
961
1419
  setTick((prev) => prev + 1);
962
1420
  }, INTERVAL_MS);
@@ -1022,16 +1480,16 @@ function parseSlashInput(value) {
1022
1480
  return { isSlash: true, parentCommand: parent, filter: rest };
1023
1481
  }
1024
1482
  function useAutocomplete(value, registry) {
1025
- const [selectedIndex, setSelectedIndex] = (0, import_react8.useState)(0);
1026
- const [dismissed, setDismissed] = (0, import_react8.useState)(false);
1027
- const prevValueRef = import_react8.default.useRef(value);
1483
+ const [selectedIndex, setSelectedIndex] = (0, import_react9.useState)(0);
1484
+ const [dismissed, setDismissed] = (0, import_react9.useState)(false);
1485
+ const prevValueRef = import_react9.default.useRef(value);
1028
1486
  if (prevValueRef.current !== value) {
1029
1487
  prevValueRef.current = value;
1030
1488
  if (dismissed) setDismissed(false);
1031
1489
  }
1032
1490
  const parsed = parseSlashInput(value);
1033
1491
  const isSubcommandMode = parsed.isSlash && parsed.parentCommand.length > 0;
1034
- const filteredCommands = (0, import_react8.useMemo)(() => {
1492
+ const filteredCommands = (0, import_react9.useMemo)(() => {
1035
1493
  if (!registry || !parsed.isSlash || dismissed) return [];
1036
1494
  if (isSubcommandMode) {
1037
1495
  const subs = registry.getSubcommands(parsed.parentCommand);
@@ -1065,7 +1523,7 @@ function useAutocomplete(value, registry) {
1065
1523
  };
1066
1524
  }
1067
1525
  function InputArea({ onSubmit, isDisabled, registry }) {
1068
- const [value, setValue] = (0, import_react8.useState)("");
1526
+ const [value, setValue] = (0, import_react9.useState)("");
1069
1527
  const {
1070
1528
  showPopup,
1071
1529
  filteredCommands,
@@ -1074,7 +1532,7 @@ function InputArea({ onSubmit, isDisabled, registry }) {
1074
1532
  isSubcommandMode,
1075
1533
  setShowPopup
1076
1534
  } = useAutocomplete(value, registry);
1077
- const handleSubmit = (0, import_react8.useCallback)(
1535
+ const handleSubmit = (0, import_react9.useCallback)(
1078
1536
  (text) => {
1079
1537
  const trimmed = text.trim();
1080
1538
  if (trimmed.length === 0) return;
@@ -1087,7 +1545,7 @@ function InputArea({ onSubmit, isDisabled, registry }) {
1087
1545
  },
1088
1546
  [showPopup, filteredCommands, selectedIndex, onSubmit]
1089
1547
  );
1090
- const selectCommand = (0, import_react8.useCallback)(
1548
+ const selectCommand = (0, import_react9.useCallback)(
1091
1549
  (cmd) => {
1092
1550
  const parsed = parseSlashInput(value);
1093
1551
  if (parsed.parentCommand) {
@@ -1148,7 +1606,7 @@ function InputArea({ onSubmit, isDisabled, registry }) {
1148
1606
  }
1149
1607
 
1150
1608
  // src/ui/ConfirmPrompt.tsx
1151
- var import_react9 = require("react");
1609
+ var import_react10 = require("react");
1152
1610
  var import_ink7 = require("ink");
1153
1611
  var import_jsx_runtime7 = require("react/jsx-runtime");
1154
1612
  function ConfirmPrompt({
@@ -1156,9 +1614,9 @@ function ConfirmPrompt({
1156
1614
  options = ["Yes", "No"],
1157
1615
  onSelect
1158
1616
  }) {
1159
- const [selected, setSelected] = (0, import_react9.useState)(0);
1160
- const resolvedRef = (0, import_react9.useRef)(false);
1161
- const doSelect = (0, import_react9.useCallback)(
1617
+ const [selected, setSelected] = (0, import_react10.useState)(0);
1618
+ const resolvedRef = (0, import_react10.useRef)(false);
1619
+ const doSelect = (0, import_react10.useCallback)(
1162
1620
  (index) => {
1163
1621
  if (resolvedRef.current) return;
1164
1622
  resolvedRef.current = true;
@@ -1191,7 +1649,7 @@ function ConfirmPrompt({
1191
1649
  }
1192
1650
 
1193
1651
  // src/ui/PermissionPrompt.tsx
1194
- var import_react10 = __toESM(require("react"), 1);
1652
+ var import_react11 = __toESM(require("react"), 1);
1195
1653
  var import_ink8 = require("ink");
1196
1654
  var import_jsx_runtime8 = require("react/jsx-runtime");
1197
1655
  var OPTIONS = ["Allow", "Allow always (this session)", "Deny"];
@@ -1201,15 +1659,15 @@ function formatArgs(args) {
1201
1659
  return entries.map(([k, v]) => `${k}: ${typeof v === "string" ? v : JSON.stringify(v)}`).join(", ");
1202
1660
  }
1203
1661
  function PermissionPrompt({ request }) {
1204
- const [selected, setSelected] = import_react10.default.useState(0);
1205
- const resolvedRef = import_react10.default.useRef(false);
1206
- const prevRequestRef = import_react10.default.useRef(request);
1662
+ const [selected, setSelected] = import_react11.default.useState(0);
1663
+ const resolvedRef = import_react11.default.useRef(false);
1664
+ const prevRequestRef = import_react11.default.useRef(request);
1207
1665
  if (prevRequestRef.current !== request) {
1208
1666
  prevRequestRef.current = request;
1209
1667
  resolvedRef.current = false;
1210
1668
  setSelected(0);
1211
1669
  }
1212
- const doResolve = import_react10.default.useCallback(
1670
+ const doResolve = import_react11.default.useCallback(
1213
1671
  (index) => {
1214
1672
  if (resolvedRef.current) return;
1215
1673
  resolvedRef.current = true;
@@ -1288,20 +1746,46 @@ function StreamingIndicator({ text, activeTools }) {
1288
1746
  // src/ui/App.tsx
1289
1747
  var import_jsx_runtime10 = require("react/jsx-runtime");
1290
1748
  var EXIT_DELAY_MS2 = 500;
1749
+ function mergeHooksIntoConfig(configHooks, pluginHooks) {
1750
+ const pluginKeys = Object.keys(pluginHooks);
1751
+ if (pluginKeys.length === 0) return configHooks;
1752
+ const merged = {};
1753
+ for (const [event, groups] of Object.entries(pluginHooks)) {
1754
+ merged[event] = [...groups];
1755
+ }
1756
+ if (configHooks) {
1757
+ for (const [event, groups] of Object.entries(configHooks)) {
1758
+ if (!Array.isArray(groups)) continue;
1759
+ if (!merged[event]) merged[event] = [];
1760
+ merged[event].push(...groups);
1761
+ }
1762
+ }
1763
+ return merged;
1764
+ }
1291
1765
  function App(props) {
1292
1766
  const { exit } = (0, import_ink10.useApp)();
1293
- const { session, permissionRequest, streamingText, clearStreamingText, activeTools } = useSession(props);
1767
+ const { registry, pluginHooks } = useCommandRegistry(props.cwd ?? process.cwd());
1768
+ const configWithPluginHooks = {
1769
+ ...props.config,
1770
+ hooks: mergeHooksIntoConfig(
1771
+ props.config.hooks,
1772
+ pluginHooks
1773
+ )
1774
+ };
1775
+ const { session, permissionRequest, streamingText, clearStreamingText, activeTools } = useSession(
1776
+ { ...props, config: configWithPluginHooks }
1777
+ );
1294
1778
  const { messages, setMessages, addMessage } = useMessages();
1295
- const [isThinking, setIsThinking] = (0, import_react11.useState)(false);
1779
+ const [isThinking, setIsThinking] = (0, import_react12.useState)(false);
1296
1780
  const initialCtx = session.getContextState();
1297
- const [contextState, setContextState] = (0, import_react11.useState)({
1781
+ const [contextState, setContextState] = (0, import_react12.useState)({
1298
1782
  percentage: initialCtx.usedPercentage,
1299
1783
  usedTokens: initialCtx.usedTokens,
1300
1784
  maxTokens: initialCtx.maxTokens
1301
1785
  });
1302
- const registry = useCommandRegistry(props.cwd ?? process.cwd());
1303
- const pendingModelChangeRef = (0, import_react11.useRef)(null);
1304
- const [pendingModelId, setPendingModelId] = (0, import_react11.useState)(null);
1786
+ const pendingModelChangeRef = (0, import_react12.useRef)(null);
1787
+ const [pendingModelId, setPendingModelId] = (0, import_react12.useState)(null);
1788
+ const pluginCallbacks = usePluginCallbacks(props.cwd ?? process.cwd());
1305
1789
  const handleSlashCommand = useSlashCommands(
1306
1790
  session,
1307
1791
  addMessage,
@@ -1309,7 +1793,8 @@ function App(props) {
1309
1793
  exit,
1310
1794
  registry,
1311
1795
  pendingModelChangeRef,
1312
- setPendingModelId
1796
+ setPendingModelId,
1797
+ pluginCallbacks
1313
1798
  );
1314
1799
  const handleSubmit = useSubmitHandler(
1315
1800
  session,
@@ -1425,23 +1910,24 @@ function renderApp(options) {
1425
1910
 
1426
1911
  // src/cli.ts
1427
1912
  var import_meta = {};
1428
- function hasValidSettingsFile(filePath) {
1429
- if (!(0, import_node_fs3.existsSync)(filePath)) return false;
1913
+ function checkSettingsFile(filePath) {
1914
+ if (!(0, import_node_fs3.existsSync)(filePath)) return "missing";
1430
1915
  try {
1431
1916
  const raw = (0, import_node_fs3.readFileSync)(filePath, "utf8").trim();
1432
- if (raw.length === 0) return false;
1917
+ if (raw.length === 0) return "incomplete";
1433
1918
  const parsed = JSON.parse(raw);
1434
1919
  const provider = parsed.provider;
1435
- return !!provider?.apiKey;
1920
+ if (!provider?.apiKey) return "incomplete";
1921
+ return "valid";
1436
1922
  } catch {
1437
- return false;
1923
+ return "corrupt";
1438
1924
  }
1439
1925
  }
1440
1926
  function readVersion() {
1441
1927
  try {
1442
1928
  const thisFile = (0, import_node_url.fileURLToPath)(import_meta.url);
1443
- const dir = (0, import_node_path3.dirname)(thisFile);
1444
- const candidates = [(0, import_node_path3.join)(dir, "..", "..", "package.json"), (0, import_node_path3.join)(dir, "..", "package.json")];
1929
+ const dir = (0, import_node_path5.dirname)(thisFile);
1930
+ const candidates = [(0, import_node_path5.join)(dir, "..", "..", "package.json"), (0, import_node_path5.join)(dir, "..", "package.json")];
1445
1931
  for (const pkgPath of candidates) {
1446
1932
  try {
1447
1933
  const raw = (0, import_node_fs3.readFileSync)(pkgPath, "utf-8");
@@ -1494,14 +1980,36 @@ function promptInput(label, masked = false) {
1494
1980
  }
1495
1981
  async function ensureConfig(cwd) {
1496
1982
  const userPath = getUserSettingsPath();
1497
- const projectPath = (0, import_node_path3.join)(cwd, ".robota", "settings.json");
1498
- const localPath = (0, import_node_path3.join)(cwd, ".robota", "settings.local.json");
1499
- if (hasValidSettingsFile(userPath) || hasValidSettingsFile(projectPath) || hasValidSettingsFile(localPath)) {
1983
+ const projectPath = (0, import_node_path5.join)(cwd, ".robota", "settings.json");
1984
+ const localPath = (0, import_node_path5.join)(cwd, ".robota", "settings.local.json");
1985
+ const paths = [userPath, projectPath, localPath];
1986
+ const checks = paths.map((p) => ({ path: p, status: checkSettingsFile(p) }));
1987
+ if (checks.some((c) => c.status === "valid")) {
1500
1988
  return;
1501
1989
  }
1990
+ const corrupt = checks.filter((c) => c.status === "corrupt");
1991
+ const incomplete = checks.filter((c) => c.status === "incomplete");
1502
1992
  process.stdout.write("\n");
1503
- process.stdout.write(" Welcome to Robota CLI!\n");
1504
- process.stdout.write(" No configuration found. Let's set up.\n");
1993
+ if (corrupt.length > 0) {
1994
+ for (const c of corrupt) {
1995
+ process.stderr.write(` ERROR: Settings file is corrupt (invalid JSON): ${c.path}
1996
+ `);
1997
+ }
1998
+ process.stdout.write("\n");
1999
+ }
2000
+ if (incomplete.length > 0) {
2001
+ for (const c of incomplete) {
2002
+ process.stderr.write(` WARNING: Settings file is missing provider.apiKey: ${c.path}
2003
+ `);
2004
+ }
2005
+ process.stdout.write("\n");
2006
+ }
2007
+ if (corrupt.length === 0 && incomplete.length === 0) {
2008
+ process.stdout.write(" Welcome to Robota CLI!\n");
2009
+ process.stdout.write(" No configuration found. Let's set up.\n");
2010
+ } else {
2011
+ process.stdout.write(" Reconfiguring...\n");
2012
+ }
1505
2013
  process.stdout.write("\n");
1506
2014
  const apiKey = await promptInput(" Anthropic API key: ", true);
1507
2015
  if (!apiKey) {
@@ -1509,7 +2017,7 @@ async function ensureConfig(cwd) {
1509
2017
  process.exit(1);
1510
2018
  }
1511
2019
  const language = await promptInput(" Response language (ko/en/ja/zh, default: en): ");
1512
- const settingsDir = (0, import_node_path3.dirname)(userPath);
2020
+ const settingsDir = (0, import_node_path5.dirname)(userPath);
1513
2021
  (0, import_node_fs3.mkdirSync)(settingsDir, { recursive: true });
1514
2022
  const settings = {
1515
2023
  provider: {
@@ -1550,9 +2058,9 @@ async function startCli() {
1550
2058
  const cwd = process.cwd();
1551
2059
  await ensureConfig(cwd);
1552
2060
  const [config, context, projectInfo] = await Promise.all([
1553
- (0, import_agent_sdk2.loadConfig)(cwd),
1554
- (0, import_agent_sdk2.loadContext)(cwd),
1555
- (0, import_agent_sdk2.detectProject)(cwd)
2061
+ (0, import_agent_sdk4.loadConfig)(cwd),
2062
+ (0, import_agent_sdk4.loadContext)(cwd),
2063
+ (0, import_agent_sdk4.detectProject)(cwd)
1556
2064
  ]);
1557
2065
  if (args.model !== void 0) {
1558
2066
  config.provider.model = args.model;
@@ -1560,7 +2068,7 @@ async function startCli() {
1560
2068
  if (args.language !== void 0) {
1561
2069
  config.language = args.language;
1562
2070
  }
1563
- const sessionStore = new import_agent_sdk2.SessionStore();
2071
+ const sessionStore = new import_agent_sdk4.SessionStore();
1564
2072
  if (args.printMode) {
1565
2073
  const prompt = args.positional.join(" ").trim();
1566
2074
  if (prompt.length === 0) {
@@ -1568,15 +2076,15 @@ async function startCli() {
1568
2076
  process.exit(1);
1569
2077
  }
1570
2078
  const terminal = new PrintTerminal();
1571
- const paths = (0, import_agent_sdk2.projectPaths)(cwd);
1572
- const session = (0, import_agent_sdk2.createSession)({
2079
+ const paths = (0, import_agent_sdk4.projectPaths)(cwd);
2080
+ const session = (0, import_agent_sdk4.createSession)({
1573
2081
  config,
1574
2082
  context,
1575
2083
  terminal,
1576
- sessionLogger: new import_agent_sdk2.FileSessionLogger(paths.logs),
2084
+ sessionLogger: new import_agent_sdk4.FileSessionLogger(paths.logs),
1577
2085
  projectInfo,
1578
2086
  permissionMode: args.permissionMode,
1579
- promptForApproval: import_agent_sdk3.promptForApproval
2087
+ promptForApproval: import_agent_sdk5.promptForApproval
1580
2088
  });
1581
2089
  const response = await session.run(prompt);
1582
2090
  process.stdout.write(response + "\n");