@robota-sdk/agent-sdk 3.0.0-beta.30 → 3.0.0-beta.32

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.
@@ -31,26 +31,33 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
33
  AgentExecutor: () => AgentExecutor,
34
+ BUILT_IN_AGENTS: () => BUILT_IN_AGENTS,
34
35
  BundlePluginInstaller: () => BundlePluginInstaller,
35
36
  BundlePluginLoader: () => BundlePluginLoader,
36
37
  DEFAULT_TOOL_DESCRIPTIONS: () => DEFAULT_TOOL_DESCRIPTIONS,
37
- FileSessionLogger: () => import_agent_sessions3.FileSessionLogger,
38
+ FileSessionLogger: () => import_agent_sessions5.FileSessionLogger,
38
39
  MarketplaceClient: () => MarketplaceClient,
39
40
  PluginSettingsStore: () => PluginSettingsStore,
40
41
  PromptExecutor: () => PromptExecutor,
41
- Session: () => import_agent_sessions2.Session,
42
- SessionStore: () => import_agent_sessions4.SessionStore,
43
- SilentSessionLogger: () => import_agent_sessions3.SilentSessionLogger,
42
+ Session: () => import_agent_sessions4.Session,
43
+ SessionStore: () => import_agent_sessions6.SessionStore,
44
+ SilentSessionLogger: () => import_agent_sessions5.SilentSessionLogger,
44
45
  TRUST_TO_MODE: () => import_agent_core.TRUST_TO_MODE,
45
- agentTool: () => agentTool,
46
+ assembleSubagentPrompt: () => assembleSubagentPrompt,
46
47
  bashTool: () => import_agent_tools3.bashTool,
47
48
  buildSystemPrompt: () => buildSystemPrompt,
49
+ createAgentTool: () => createAgentTool,
48
50
  createDefaultTools: () => createDefaultTools,
49
51
  createProvider: () => createProvider,
50
52
  createSession: () => createSession,
53
+ createSubagentLogger: () => createSubagentLogger,
54
+ createSubagentSession: () => createSubagentSession,
51
55
  detectProject: () => detectProject,
52
56
  editTool: () => import_agent_tools6.editTool,
53
57
  evaluatePermission: () => import_agent_core2.evaluatePermission,
58
+ getBuiltInAgent: () => getBuiltInAgent,
59
+ getForkWorkerSuffix: () => getForkWorkerSuffix,
60
+ getSubagentSuffix: () => getSubagentSuffix,
54
61
  globTool: () => import_agent_tools7.globTool,
55
62
  grepTool: () => import_agent_tools8.grepTool,
56
63
  loadConfig: () => loadConfig,
@@ -59,8 +66,10 @@ __export(index_exports, {
59
66
  promptForApproval: () => promptForApproval,
60
67
  query: () => query,
61
68
  readTool: () => import_agent_tools4.readTool,
69
+ resolveSubagentLogDir: () => resolveSubagentLogDir,
70
+ retrieveAgentToolDeps: () => retrieveAgentToolDeps,
62
71
  runHooks: () => import_agent_core3.runHooks,
63
- setAgentToolDeps: () => setAgentToolDeps,
72
+ storeAgentToolDeps: () => storeAgentToolDeps,
64
73
  userPaths: () => userPaths,
65
74
  writeTool: () => import_agent_tools5.writeTool
66
75
  });
@@ -177,7 +186,7 @@ Respond with JSON: { "ok": boolean, "reason"?: string }`;
177
186
  };
178
187
 
179
188
  // src/assembly/create-session.ts
180
- var import_agent_sessions = require("@robota-sdk/agent-sessions");
189
+ var import_agent_sessions2 = require("@robota-sdk/agent-sessions");
181
190
 
182
191
  // src/context/system-prompt-builder.ts
183
192
  var TRUST_LEVEL_DESCRIPTIONS = {
@@ -310,11 +319,379 @@ function createProvider(config) {
310
319
  return new import_agent_provider_anthropic.AnthropicProvider({ apiKey });
311
320
  }
312
321
 
322
+ // src/tools/agent-tool.ts
323
+ var import_zod = require("zod");
324
+ var import_agent_tools2 = require("@robota-sdk/agent-tools");
325
+
326
+ // src/agents/built-in-agents.ts
327
+ var GENERAL_PURPOSE_SYSTEM_PROMPT = `You are a general-purpose task execution agent. You have access to all tools available in the parent session and can perform any task delegated to you.
328
+
329
+ Your role is to complete the assigned task thoroughly and accurately. Follow these guidelines:
330
+
331
+ - Execute the task as described in the prompt. Do not expand scope beyond what is requested.
332
+ - Use the most appropriate tools for each step. Prefer precise tools (Read, Grep, Glob) over broad ones (Bash) when possible.
333
+ - Report your findings clearly and concisely when the task is complete.
334
+ - If a task cannot be completed, explain why and what information is missing.
335
+ - Maintain the same code quality standards as the parent session (strict types, no fallbacks, proper error handling).`;
336
+ var EXPLORE_SYSTEM_PROMPT = `You are a codebase exploration and analysis agent. Your purpose is to search, read, and understand code without making any modifications.
337
+
338
+ You operate in read-only mode. You must NEVER attempt to write or edit files. Your tools are restricted to read-only operations: reading files, searching with grep and glob, and running non-destructive bash commands.
339
+
340
+ Your role is to answer questions about the codebase by:
341
+
342
+ - Searching for relevant files, symbols, and patterns using Glob and Grep.
343
+ - Reading source files, configuration, and documentation to understand structure and behavior.
344
+ - Tracing code paths across modules to understand how components interact.
345
+ - Summarizing findings in a clear, structured format with file paths and line references.
346
+ - Identifying architectural patterns, dependencies, and potential issues.
347
+
348
+ When exploring, prefer targeted searches over broad scans. Start with the most likely locations and narrow down. Always include absolute file paths in your responses so the caller can navigate directly to relevant code.`;
349
+ var PLAN_SYSTEM_PROMPT = `You are a planning, research, and architecture agent. Your purpose is to analyze requirements, research approaches, and produce structured plans without making any code modifications.
350
+
351
+ You operate in read-only mode. You must NEVER attempt to write or edit files. Your tools are restricted to read-only operations.
352
+
353
+ Your role is to:
354
+
355
+ - Analyze the current codebase state relevant to the task by reading specs, source code, and tests.
356
+ - Research implementation approaches by examining existing patterns and architectural conventions in the repository.
357
+ - Identify affected files, modules, and interfaces that a proposed change would touch.
358
+ - Assess risks, dependencies, and potential breaking changes.
359
+ - Produce a structured implementation plan with clear steps, file lists, and ordering.
360
+ - Consider edge cases, error handling, and test coverage requirements.
361
+
362
+ Output your plan in a structured format with numbered steps. For each step, specify which files are involved and what changes are needed. Flag any decisions that require human judgment or clarification.`;
363
+ var BUILT_IN_AGENTS = [
364
+ {
365
+ name: "general-purpose",
366
+ description: "General-purpose task execution agent with full tool access.",
367
+ systemPrompt: GENERAL_PURPOSE_SYSTEM_PROMPT
368
+ },
369
+ {
370
+ name: "Explore",
371
+ description: "Read-only codebase exploration and analysis agent.",
372
+ systemPrompt: EXPLORE_SYSTEM_PROMPT,
373
+ model: "claude-haiku-4-5",
374
+ disallowedTools: ["Write", "Edit"]
375
+ },
376
+ {
377
+ name: "Plan",
378
+ description: "Read-only planning, research, and architecture agent.",
379
+ systemPrompt: PLAN_SYSTEM_PROMPT,
380
+ disallowedTools: ["Write", "Edit"]
381
+ }
382
+ ];
383
+ function getBuiltInAgent(name) {
384
+ return BUILT_IN_AGENTS.find((agent) => agent.name === name);
385
+ }
386
+
387
+ // src/assembly/create-subagent-session.ts
388
+ var import_agent_sessions = require("@robota-sdk/agent-sessions");
389
+
390
+ // src/assembly/subagent-prompts.ts
391
+ function getSubagentSuffix() {
392
+ return `When you complete the task, respond with a concise report covering what was done and any key findings \u2014 the caller will relay this to the user, so it only needs the essentials.
393
+
394
+ In your final response, share file paths (always absolute, never relative) that are relevant to the task. Include code snippets only when the exact text is load-bearing \u2014 do not recap code you merely read.
395
+
396
+ Do not use emojis.`;
397
+ }
398
+ function getForkWorkerSuffix() {
399
+ return `You are a worker subagent executing a specific task. Do NOT spawn sub-agents; execute directly. Keep your report under 500 words. Use this structure:
400
+ - Scope: What was requested
401
+ - Result: What was done
402
+ - Key files: Relevant file paths (absolute)
403
+ - Files changed: List of modifications
404
+ - Issues: Any problems encountered`;
405
+ }
406
+ function assembleSubagentPrompt(options) {
407
+ const parts = [options.agentBody];
408
+ if (options.claudeMd) {
409
+ parts.push(options.claudeMd);
410
+ }
411
+ if (options.agentsMd) {
412
+ parts.push(options.agentsMd);
413
+ }
414
+ const suffix = options.isForkWorker ? getForkWorkerSuffix() : getSubagentSuffix();
415
+ parts.push(suffix);
416
+ return parts.join("\n\n");
417
+ }
418
+
419
+ // src/assembly/create-subagent-session.ts
420
+ var MODEL_SHORTCUTS = {
421
+ sonnet: "claude-sonnet-4-6",
422
+ haiku: "claude-haiku-4-5",
423
+ opus: "claude-opus-4-6"
424
+ };
425
+ function resolveModelId(shortName, _parentModel) {
426
+ return MODEL_SHORTCUTS[shortName] ?? shortName;
427
+ }
428
+ function filterTools(parentTools, agentDefinition) {
429
+ let tools = [...parentTools];
430
+ if (agentDefinition.disallowedTools) {
431
+ const denySet = new Set(agentDefinition.disallowedTools);
432
+ tools = tools.filter((t) => !denySet.has(t.getName()));
433
+ }
434
+ if (agentDefinition.tools) {
435
+ const allowSet = new Set(agentDefinition.tools);
436
+ tools = tools.filter((t) => allowSet.has(t.getName()));
437
+ }
438
+ tools = tools.filter((t) => t.getName() !== "Agent");
439
+ return tools;
440
+ }
441
+ function createSubagentSession(options) {
442
+ const { agentDefinition, parentConfig, parentContext, parentTools, terminal } = options;
443
+ const tools = filterTools(parentTools, agentDefinition);
444
+ const model = agentDefinition.model ? resolveModelId(agentDefinition.model, parentConfig.provider.model) : parentConfig.provider.model;
445
+ const systemMessage = assembleSubagentPrompt({
446
+ agentBody: agentDefinition.systemPrompt,
447
+ claudeMd: parentContext.claudeMd,
448
+ agentsMd: parentContext.agentsMd,
449
+ isForkWorker: options.isForkWorker ?? false
450
+ });
451
+ const provider = createProvider(parentConfig);
452
+ return new import_agent_sessions.Session({
453
+ tools,
454
+ provider,
455
+ systemMessage,
456
+ terminal,
457
+ model,
458
+ maxTurns: agentDefinition.maxTurns,
459
+ permissions: parentConfig.permissions,
460
+ permissionMode: options.permissionMode,
461
+ defaultTrustLevel: parentConfig.defaultTrustLevel,
462
+ permissionHandler: options.permissionHandler,
463
+ hooks: options.hooks,
464
+ hookTypeExecutors: options.hookTypeExecutors,
465
+ onTextDelta: options.onTextDelta,
466
+ onToolExecution: options.onToolExecution
467
+ });
468
+ }
469
+
470
+ // src/tools/agent-tool.ts
471
+ function asZodSchema(schema) {
472
+ return schema;
473
+ }
474
+ var AgentSchema = import_zod.z.object({
475
+ prompt: import_zod.z.string().describe("The task for the subagent to perform"),
476
+ subagent_type: import_zod.z.string().optional().describe('Agent type: "general-purpose", "Explore", "Plan", or a custom agent name'),
477
+ model: import_zod.z.string().optional().describe("Optional model override")
478
+ });
479
+ var sessionDepsStore = /* @__PURE__ */ new WeakMap();
480
+ function storeAgentToolDeps(key, deps) {
481
+ sessionDepsStore.set(key, deps);
482
+ }
483
+ function retrieveAgentToolDeps(key) {
484
+ return sessionDepsStore.get(key);
485
+ }
486
+ function resolveAgentDefinition(agentType, customRegistry) {
487
+ const builtIn = getBuiltInAgent(agentType);
488
+ if (builtIn) return builtIn;
489
+ if (customRegistry) return customRegistry(agentType);
490
+ return void 0;
491
+ }
492
+ function generateAgentId() {
493
+ return `agent_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
494
+ }
495
+ function createAgentTool(deps) {
496
+ async function runAgent(args) {
497
+ const agentType = args.subagent_type ?? "general-purpose";
498
+ const agentDef = resolveAgentDefinition(agentType, deps.customAgentRegistry);
499
+ if (!agentDef) {
500
+ return JSON.stringify({
501
+ success: false,
502
+ output: "",
503
+ error: `Unknown agent type: ${agentType}`
504
+ });
505
+ }
506
+ const effectiveDef = args.model ? { ...agentDef, model: args.model } : agentDef;
507
+ const session = createSubagentSession({
508
+ agentDefinition: effectiveDef,
509
+ parentConfig: deps.config,
510
+ parentContext: deps.context,
511
+ parentTools: deps.tools,
512
+ terminal: deps.terminal,
513
+ permissionMode: deps.permissionMode,
514
+ permissionHandler: deps.permissionHandler,
515
+ hooks: deps.hooks,
516
+ hookTypeExecutors: deps.hookTypeExecutors,
517
+ onTextDelta: deps.onTextDelta,
518
+ onToolExecution: deps.onToolExecution
519
+ });
520
+ const agentId = generateAgentId();
521
+ try {
522
+ const response = await session.run(args.prompt);
523
+ return JSON.stringify({
524
+ success: true,
525
+ output: response,
526
+ agentId
527
+ });
528
+ } catch (err) {
529
+ const message = err instanceof Error ? err.message : String(err);
530
+ return JSON.stringify({
531
+ success: false,
532
+ output: "",
533
+ error: `Sub-agent error: ${message}`,
534
+ agentId
535
+ });
536
+ }
537
+ }
538
+ return (0, import_agent_tools2.createZodFunctionTool)(
539
+ "Agent",
540
+ "Launch a subagent to handle a task in an isolated context. The subagent gets its own context window and returns a result when done. The result returned by the agent is not visible to the user. To show the user the result, you should send a text message back to the user with a concise summary of the result.",
541
+ asZodSchema(AgentSchema),
542
+ async (params) => {
543
+ return runAgent(params);
544
+ }
545
+ );
546
+ }
547
+
548
+ // src/agents/agent-definition-loader.ts
549
+ var import_node_fs = require("fs");
550
+ var import_node_path = require("path");
551
+ var import_node_os = require("os");
552
+ var LIST_KEYS = /* @__PURE__ */ new Set(["tools", "disallowedTools"]);
553
+ var NUMBER_KEYS = /* @__PURE__ */ new Set(["maxTurns"]);
554
+ function parseFrontmatter(content) {
555
+ const lines = content.split("\n");
556
+ if (lines[0]?.trim() !== "---") {
557
+ return { frontmatter: null, body: content };
558
+ }
559
+ let endIndex = -1;
560
+ for (let i = 1; i < lines.length; i++) {
561
+ if (lines[i]?.trim() === "---") {
562
+ endIndex = i;
563
+ break;
564
+ }
565
+ }
566
+ if (endIndex === -1) {
567
+ return { frontmatter: null, body: content };
568
+ }
569
+ const result = {};
570
+ for (let i = 1; i < endIndex; i++) {
571
+ const line = lines[i];
572
+ const match = line.match(/^([a-zA-Z][a-zA-Z0-9]*(?:[A-Z][a-z]*)*):\s*(.+)/);
573
+ if (!match) continue;
574
+ const key = match[1];
575
+ const rawValue = match[2].trim();
576
+ if (LIST_KEYS.has(key)) {
577
+ result[key] = rawValue.split(",").map((s) => s.trim());
578
+ } else if (NUMBER_KEYS.has(key)) {
579
+ result[key] = parseInt(rawValue, 10);
580
+ } else {
581
+ result[key] = rawValue;
582
+ }
583
+ }
584
+ const body = lines.slice(endIndex + 1).join("\n").trim();
585
+ return {
586
+ frontmatter: Object.keys(result).length > 0 ? result : null,
587
+ body
588
+ };
589
+ }
590
+ function scanAgentsDir(dir) {
591
+ if (!(0, import_node_fs.existsSync)(dir)) return [];
592
+ const agents = [];
593
+ let entries;
594
+ try {
595
+ entries = (0, import_node_fs.readdirSync)(dir, { withFileTypes: true });
596
+ } catch {
597
+ return [];
598
+ }
599
+ for (const entry of entries) {
600
+ if (!entry.isFile() || !entry.name.endsWith(".md")) continue;
601
+ const filePath = (0, import_node_path.join)(dir, entry.name);
602
+ const content = (0, import_node_fs.readFileSync)(filePath, "utf-8");
603
+ const { frontmatter, body } = parseFrontmatter(content);
604
+ const fallbackName = (0, import_node_path.basename)(entry.name, ".md");
605
+ const agent = {
606
+ name: frontmatter?.name ?? fallbackName,
607
+ description: frontmatter?.description ?? "",
608
+ systemPrompt: body
609
+ };
610
+ if (frontmatter?.model !== void 0) agent.model = frontmatter.model;
611
+ if (frontmatter?.maxTurns !== void 0) agent.maxTurns = frontmatter.maxTurns;
612
+ if (frontmatter?.tools !== void 0) agent.tools = frontmatter.tools;
613
+ if (frontmatter?.disallowedTools !== void 0)
614
+ agent.disallowedTools = frontmatter.disallowedTools;
615
+ agents.push(agent);
616
+ }
617
+ return agents;
618
+ }
619
+ var AgentDefinitionLoader = class {
620
+ cwd;
621
+ home;
622
+ constructor(cwd, home) {
623
+ this.cwd = cwd;
624
+ this.home = home ?? (0, import_node_os.homedir)();
625
+ }
626
+ /** Load all agent definitions, merged with built-in agents. Custom overrides built-in on name collision. */
627
+ loadAll() {
628
+ const sources = [
629
+ scanAgentsDir((0, import_node_path.join)(this.cwd, ".claude", "agents")),
630
+ scanAgentsDir((0, import_node_path.join)(this.home, ".robota", "agents"))
631
+ ];
632
+ const seen = /* @__PURE__ */ new Set();
633
+ const customAgents = [];
634
+ for (const agents of sources) {
635
+ for (const agent of agents) {
636
+ if (!seen.has(agent.name)) {
637
+ seen.add(agent.name);
638
+ customAgents.push(agent);
639
+ }
640
+ }
641
+ }
642
+ const result = [...customAgents];
643
+ for (const builtIn of BUILT_IN_AGENTS) {
644
+ if (!seen.has(builtIn.name)) {
645
+ result.push(builtIn);
646
+ }
647
+ }
648
+ return result;
649
+ }
650
+ /** Get a specific agent by name (custom or built-in). */
651
+ getAgent(name) {
652
+ return this.loadAll().find((agent) => agent.name === name);
653
+ }
654
+ };
655
+
313
656
  // src/assembly/create-session.ts
314
657
  function createSession(options) {
315
658
  const provider = options.provider ?? createProvider(options.config);
316
659
  const defaultTools = createDefaultTools();
317
660
  const tools = [...defaultTools, ...options.additionalTools ?? []];
661
+ const agentLoader = new AgentDefinitionLoader(process.cwd());
662
+ const hookTypeExecutors = [];
663
+ if (options.providerFactory) {
664
+ hookTypeExecutors.push(
665
+ new PromptExecutor({
666
+ providerFactory: options.providerFactory,
667
+ defaultModel: options.config.provider.model
668
+ })
669
+ );
670
+ }
671
+ if (options.sessionFactory) {
672
+ hookTypeExecutors.push(
673
+ new AgentExecutor({
674
+ sessionFactory: options.sessionFactory
675
+ })
676
+ );
677
+ }
678
+ if (options.additionalHookExecutors) {
679
+ hookTypeExecutors.push(...options.additionalHookExecutors);
680
+ }
681
+ const agentToolDeps = {
682
+ config: options.config,
683
+ context: options.context,
684
+ tools,
685
+ terminal: options.terminal,
686
+ permissionMode: options.permissionMode,
687
+ permissionHandler: options.permissionHandler,
688
+ hooks: options.config.hooks,
689
+ hookTypeExecutors: hookTypeExecutors.length > 0 ? hookTypeExecutors : void 0,
690
+ onTextDelta: options.onTextDelta,
691
+ onToolExecution: options.onToolExecution,
692
+ customAgentRegistry: (name) => agentLoader.getAgent(name)
693
+ };
694
+ tools.push(createAgentTool(agentToolDeps));
318
695
  const buildPrompt = options.systemPromptBuilder ?? buildSystemPrompt;
319
696
  const systemMessage = buildPrompt({
320
697
  agentsMd: options.context.agentsMd,
@@ -337,26 +714,7 @@ function createSession(options) {
337
714
  allow: [...defaultAllow, ...options.config.permissions.allow ?? []],
338
715
  deny: options.config.permissions.deny ?? []
339
716
  };
340
- const hookTypeExecutors = [];
341
- if (options.providerFactory) {
342
- hookTypeExecutors.push(
343
- new PromptExecutor({
344
- providerFactory: options.providerFactory,
345
- defaultModel: options.config.provider.model
346
- })
347
- );
348
- }
349
- if (options.sessionFactory) {
350
- hookTypeExecutors.push(
351
- new AgentExecutor({
352
- sessionFactory: options.sessionFactory
353
- })
354
- );
355
- }
356
- if (options.additionalHookExecutors) {
357
- hookTypeExecutors.push(...options.additionalHookExecutors);
358
- }
359
- return new import_agent_sessions.Session({
717
+ const session = new import_agent_sessions2.Session({
360
718
  tools,
361
719
  provider,
362
720
  systemMessage,
@@ -377,89 +735,104 @@ function createSession(options) {
377
735
  sessionLogger: options.sessionLogger,
378
736
  hookTypeExecutors: hookTypeExecutors.length > 0 ? hookTypeExecutors : void 0
379
737
  });
738
+ storeAgentToolDeps(session, agentToolDeps);
739
+ return session;
380
740
  }
381
741
 
382
- // src/index.ts
383
- var import_agent_sessions2 = require("@robota-sdk/agent-sessions");
742
+ // src/assembly/subagent-logger.ts
743
+ var import_node_fs2 = require("fs");
744
+ var import_node_path2 = require("path");
384
745
  var import_agent_sessions3 = require("@robota-sdk/agent-sessions");
746
+ function createSubagentLogger(parentSessionId, _agentId, baseLogsDir) {
747
+ const subagentDir = (0, import_node_path2.join)(baseLogsDir, parentSessionId, "subagents");
748
+ (0, import_node_fs2.mkdirSync)(subagentDir, { recursive: true });
749
+ return new import_agent_sessions3.FileSessionLogger(subagentDir);
750
+ }
751
+ function resolveSubagentLogDir(parentSessionId, baseLogsDir) {
752
+ return (0, import_node_path2.join)(baseLogsDir, parentSessionId, "subagents");
753
+ }
754
+
755
+ // src/index.ts
385
756
  var import_agent_sessions4 = require("@robota-sdk/agent-sessions");
757
+ var import_agent_sessions5 = require("@robota-sdk/agent-sessions");
758
+ var import_agent_sessions6 = require("@robota-sdk/agent-sessions");
386
759
 
387
760
  // src/config/config-loader.ts
388
761
  var import_fs = require("fs");
389
762
  var import_path = require("path");
390
763
 
391
764
  // src/config/config-types.ts
392
- var import_zod = require("zod");
393
- var ProviderSchema = import_zod.z.object({
394
- name: import_zod.z.string().optional(),
395
- model: import_zod.z.string().optional(),
396
- apiKey: import_zod.z.string().optional()
765
+ var import_zod2 = require("zod");
766
+ var ProviderSchema = import_zod2.z.object({
767
+ name: import_zod2.z.string().optional(),
768
+ model: import_zod2.z.string().optional(),
769
+ apiKey: import_zod2.z.string().optional()
397
770
  });
398
- var PermissionsSchema = import_zod.z.object({
771
+ var PermissionsSchema = import_zod2.z.object({
399
772
  /** Patterns that are always approved without prompting */
400
- allow: import_zod.z.array(import_zod.z.string()).optional(),
773
+ allow: import_zod2.z.array(import_zod2.z.string()).optional(),
401
774
  /** Patterns that are always denied */
402
- deny: import_zod.z.array(import_zod.z.string()).optional()
775
+ deny: import_zod2.z.array(import_zod2.z.string()).optional()
403
776
  });
404
- var EnvSchema = import_zod.z.record(import_zod.z.string()).optional();
405
- var CommandHookDefinitionSchema = import_zod.z.object({
406
- type: import_zod.z.literal("command"),
407
- command: import_zod.z.string(),
408
- timeout: import_zod.z.number().optional()
777
+ var EnvSchema = import_zod2.z.record(import_zod2.z.string()).optional();
778
+ var CommandHookDefinitionSchema = import_zod2.z.object({
779
+ type: import_zod2.z.literal("command"),
780
+ command: import_zod2.z.string(),
781
+ timeout: import_zod2.z.number().optional()
409
782
  });
410
- var HttpHookDefinitionSchema = import_zod.z.object({
411
- type: import_zod.z.literal("http"),
412
- url: import_zod.z.string(),
413
- headers: import_zod.z.record(import_zod.z.string()).optional(),
414
- timeout: import_zod.z.number().optional()
783
+ var HttpHookDefinitionSchema = import_zod2.z.object({
784
+ type: import_zod2.z.literal("http"),
785
+ url: import_zod2.z.string(),
786
+ headers: import_zod2.z.record(import_zod2.z.string()).optional(),
787
+ timeout: import_zod2.z.number().optional()
415
788
  });
416
- var PromptHookDefinitionSchema = import_zod.z.object({
417
- type: import_zod.z.literal("prompt"),
418
- prompt: import_zod.z.string(),
419
- model: import_zod.z.string().optional()
789
+ var PromptHookDefinitionSchema = import_zod2.z.object({
790
+ type: import_zod2.z.literal("prompt"),
791
+ prompt: import_zod2.z.string(),
792
+ model: import_zod2.z.string().optional()
420
793
  });
421
- var AgentHookDefinitionSchema = import_zod.z.object({
422
- type: import_zod.z.literal("agent"),
423
- agent: import_zod.z.string(),
424
- maxTurns: import_zod.z.number().optional(),
425
- timeout: import_zod.z.number().optional()
794
+ var AgentHookDefinitionSchema = import_zod2.z.object({
795
+ type: import_zod2.z.literal("agent"),
796
+ agent: import_zod2.z.string(),
797
+ maxTurns: import_zod2.z.number().optional(),
798
+ timeout: import_zod2.z.number().optional()
426
799
  });
427
- var HookDefinitionSchema = import_zod.z.discriminatedUnion("type", [
800
+ var HookDefinitionSchema = import_zod2.z.discriminatedUnion("type", [
428
801
  CommandHookDefinitionSchema,
429
802
  HttpHookDefinitionSchema,
430
803
  PromptHookDefinitionSchema,
431
804
  AgentHookDefinitionSchema
432
805
  ]);
433
- var HookGroupSchema = import_zod.z.object({
434
- matcher: import_zod.z.string(),
435
- hooks: import_zod.z.array(HookDefinitionSchema)
806
+ var HookGroupSchema = import_zod2.z.object({
807
+ matcher: import_zod2.z.string(),
808
+ hooks: import_zod2.z.array(HookDefinitionSchema)
436
809
  });
437
- var HooksSchema = import_zod.z.object({
438
- PreToolUse: import_zod.z.array(HookGroupSchema).optional(),
439
- PostToolUse: import_zod.z.array(HookGroupSchema).optional(),
440
- SessionStart: import_zod.z.array(HookGroupSchema).optional(),
441
- Stop: import_zod.z.array(HookGroupSchema).optional(),
442
- PreCompact: import_zod.z.array(HookGroupSchema).optional(),
443
- PostCompact: import_zod.z.array(HookGroupSchema).optional(),
444
- UserPromptSubmit: import_zod.z.array(HookGroupSchema).optional(),
445
- Notification: import_zod.z.array(HookGroupSchema).optional()
810
+ var HooksSchema = import_zod2.z.object({
811
+ PreToolUse: import_zod2.z.array(HookGroupSchema).optional(),
812
+ PostToolUse: import_zod2.z.array(HookGroupSchema).optional(),
813
+ SessionStart: import_zod2.z.array(HookGroupSchema).optional(),
814
+ Stop: import_zod2.z.array(HookGroupSchema).optional(),
815
+ PreCompact: import_zod2.z.array(HookGroupSchema).optional(),
816
+ PostCompact: import_zod2.z.array(HookGroupSchema).optional(),
817
+ UserPromptSubmit: import_zod2.z.array(HookGroupSchema).optional(),
818
+ Notification: import_zod2.z.array(HookGroupSchema).optional()
446
819
  }).optional();
447
- var EnabledPluginsSchema = import_zod.z.record(import_zod.z.boolean()).optional();
448
- var MarketplaceSourceSchema = import_zod.z.object({
449
- source: import_zod.z.object({
450
- type: import_zod.z.enum(["github", "git", "local", "url"]),
451
- repo: import_zod.z.string().optional(),
452
- url: import_zod.z.string().optional(),
453
- path: import_zod.z.string().optional(),
454
- ref: import_zod.z.string().optional()
820
+ var EnabledPluginsSchema = import_zod2.z.record(import_zod2.z.boolean()).optional();
821
+ var MarketplaceSourceSchema = import_zod2.z.object({
822
+ source: import_zod2.z.object({
823
+ type: import_zod2.z.enum(["github", "git", "local", "url"]),
824
+ repo: import_zod2.z.string().optional(),
825
+ url: import_zod2.z.string().optional(),
826
+ path: import_zod2.z.string().optional(),
827
+ ref: import_zod2.z.string().optional()
455
828
  })
456
829
  });
457
- var ExtraKnownMarketplacesSchema = import_zod.z.record(MarketplaceSourceSchema).optional();
458
- var SettingsSchema = import_zod.z.object({
830
+ var ExtraKnownMarketplacesSchema = import_zod2.z.record(MarketplaceSourceSchema).optional();
831
+ var SettingsSchema = import_zod2.z.object({
459
832
  /** Trust level used when no --permission-mode flag is given */
460
- defaultTrustLevel: import_zod.z.enum(["safe", "moderate", "full"]).optional(),
833
+ defaultTrustLevel: import_zod2.z.enum(["safe", "moderate", "full"]).optional(),
461
834
  /** Response language (e.g., "ko", "en", "ja"). Injected into system prompt. */
462
- language: import_zod.z.string().optional(),
835
+ language: import_zod2.z.string().optional(),
463
836
  provider: ProviderSchema.optional(),
464
837
  permissions: PermissionsSchema.optional(),
465
838
  env: EnvSchema,
@@ -781,28 +1154,28 @@ var import_agent_core2 = require("@robota-sdk/agent-core");
781
1154
  var import_agent_core3 = require("@robota-sdk/agent-core");
782
1155
 
783
1156
  // src/paths.ts
784
- var import_node_path = require("path");
785
- var import_node_os = require("os");
1157
+ var import_node_path3 = require("path");
1158
+ var import_node_os2 = require("os");
786
1159
  function projectPaths(cwd) {
787
- const base = (0, import_node_path.join)(cwd, ".robota");
1160
+ const base = (0, import_node_path3.join)(cwd, ".robota");
788
1161
  return {
789
- settings: (0, import_node_path.join)(base, "settings.json"),
790
- settingsLocal: (0, import_node_path.join)(base, "settings.local.json"),
791
- logs: (0, import_node_path.join)(base, "logs"),
792
- sessions: (0, import_node_path.join)(base, "sessions")
1162
+ settings: (0, import_node_path3.join)(base, "settings.json"),
1163
+ settingsLocal: (0, import_node_path3.join)(base, "settings.local.json"),
1164
+ logs: (0, import_node_path3.join)(base, "logs"),
1165
+ sessions: (0, import_node_path3.join)(base, "sessions")
793
1166
  };
794
1167
  }
795
1168
  function userPaths() {
796
- const base = (0, import_node_path.join)((0, import_node_os.homedir)(), ".robota");
1169
+ const base = (0, import_node_path3.join)((0, import_node_os2.homedir)(), ".robota");
797
1170
  return {
798
- settings: (0, import_node_path.join)(base, "settings.json"),
799
- sessions: (0, import_node_path.join)(base, "sessions")
1171
+ settings: (0, import_node_path3.join)(base, "settings.json"),
1172
+ sessions: (0, import_node_path3.join)(base, "sessions")
800
1173
  };
801
1174
  }
802
1175
 
803
1176
  // src/plugins/plugin-settings-store.ts
804
- var import_node_fs = require("fs");
805
- var import_node_path2 = require("path");
1177
+ var import_node_fs3 = require("fs");
1178
+ var import_node_path4 = require("path");
806
1179
  var PluginSettingsStore = class {
807
1180
  settingsPath;
808
1181
  constructor(settingsPath) {
@@ -810,11 +1183,11 @@ var PluginSettingsStore = class {
810
1183
  }
811
1184
  /** Read the full settings file from disk. */
812
1185
  readAll() {
813
- if (!(0, import_node_fs.existsSync)(this.settingsPath)) {
1186
+ if (!(0, import_node_fs3.existsSync)(this.settingsPath)) {
814
1187
  return {};
815
1188
  }
816
1189
  try {
817
- const raw = (0, import_node_fs.readFileSync)(this.settingsPath, "utf-8");
1190
+ const raw = (0, import_node_fs3.readFileSync)(this.settingsPath, "utf-8");
818
1191
  const data = JSON.parse(raw);
819
1192
  if (typeof data === "object" && data !== null) {
820
1193
  return data;
@@ -826,11 +1199,11 @@ var PluginSettingsStore = class {
826
1199
  }
827
1200
  /** Write the full settings file to disk. */
828
1201
  writeAll(settings) {
829
- const dir = (0, import_node_path2.dirname)(this.settingsPath);
830
- if (!(0, import_node_fs.existsSync)(dir)) {
831
- (0, import_node_fs.mkdirSync)(dir, { recursive: true });
1202
+ const dir = (0, import_node_path4.dirname)(this.settingsPath);
1203
+ if (!(0, import_node_fs3.existsSync)(dir)) {
1204
+ (0, import_node_fs3.mkdirSync)(dir, { recursive: true });
832
1205
  }
833
- (0, import_node_fs.writeFileSync)(this.settingsPath, JSON.stringify(settings, null, 2), "utf-8");
1206
+ (0, import_node_fs3.writeFileSync)(this.settingsPath, JSON.stringify(settings, null, 2), "utf-8");
834
1207
  }
835
1208
  // --- enabledPlugins ---
836
1209
  /** Get the enabledPlugins map. */
@@ -902,8 +1275,8 @@ var PluginSettingsStore = class {
902
1275
  };
903
1276
 
904
1277
  // src/plugins/bundle-plugin-loader.ts
905
- var import_node_fs2 = require("fs");
906
- var import_node_path3 = require("path");
1278
+ var import_node_fs4 = require("fs");
1279
+ var import_node_path5 = require("path");
907
1280
  function parseSkillFrontmatter(raw) {
908
1281
  const trimmed = raw.trimStart();
909
1282
  if (!trimmed.startsWith("---")) {
@@ -952,9 +1325,9 @@ function validateManifest(data) {
952
1325
  };
953
1326
  }
954
1327
  function getSortedSubdirs(dirPath) {
955
- if (!(0, import_node_fs2.existsSync)(dirPath)) return [];
1328
+ if (!(0, import_node_fs4.existsSync)(dirPath)) return [];
956
1329
  try {
957
- const entries = (0, import_node_fs2.readdirSync)(dirPath, { withFileTypes: true });
1330
+ const entries = (0, import_node_fs4.readdirSync)(dirPath, { withFileTypes: true });
958
1331
  return entries.filter((e) => e.isDirectory()).map((e) => e.name).sort();
959
1332
  } catch {
960
1333
  return [];
@@ -982,23 +1355,23 @@ var BundlePluginLoader = class {
982
1355
  * For each marketplace/plugin pair, the latest version (lexicographically last) is loaded.
983
1356
  */
984
1357
  discoverAndLoad() {
985
- const cacheDir = (0, import_node_path3.join)(this.pluginsDir, "cache");
986
- if (!(0, import_node_fs2.existsSync)(cacheDir)) {
1358
+ const cacheDir = (0, import_node_path5.join)(this.pluginsDir, "cache");
1359
+ if (!(0, import_node_fs4.existsSync)(cacheDir)) {
987
1360
  return [];
988
1361
  }
989
1362
  const results = [];
990
1363
  const marketplaces = getSortedSubdirs(cacheDir);
991
1364
  for (const marketplace of marketplaces) {
992
- const marketplaceDir = (0, import_node_path3.join)(cacheDir, marketplace);
1365
+ const marketplaceDir = (0, import_node_path5.join)(cacheDir, marketplace);
993
1366
  const plugins = getSortedSubdirs(marketplaceDir);
994
1367
  for (const pluginName of plugins) {
995
- const pluginDir = (0, import_node_path3.join)(marketplaceDir, pluginName);
1368
+ const pluginDir = (0, import_node_path5.join)(marketplaceDir, pluginName);
996
1369
  const versions = getSortedSubdirs(pluginDir);
997
1370
  if (versions.length === 0) continue;
998
1371
  const latestVersion = versions[versions.length - 1];
999
- const versionDir = (0, import_node_path3.join)(pluginDir, latestVersion);
1000
- const manifestPath = (0, import_node_path3.join)(versionDir, ".claude-plugin", "plugin.json");
1001
- if (!(0, import_node_fs2.existsSync)(manifestPath)) continue;
1372
+ const versionDir = (0, import_node_path5.join)(pluginDir, latestVersion);
1373
+ const manifestPath = (0, import_node_path5.join)(versionDir, ".claude-plugin", "plugin.json");
1374
+ if (!(0, import_node_fs4.existsSync)(manifestPath)) continue;
1002
1375
  const manifest = this.readManifest(manifestPath);
1003
1376
  if (!manifest) continue;
1004
1377
  const pluginId = `${manifest.name}@${marketplace}`;
@@ -1012,7 +1385,7 @@ var BundlePluginLoader = class {
1012
1385
  /** Read and validate a plugin.json manifest. Returns null on failure. */
1013
1386
  readManifest(path) {
1014
1387
  try {
1015
- const raw = (0, import_node_fs2.readFileSync)(path, "utf-8");
1388
+ const raw = (0, import_node_fs4.readFileSync)(path, "utf-8");
1016
1389
  const data = JSON.parse(raw);
1017
1390
  return validateManifest(data);
1018
1391
  } catch {
@@ -1047,15 +1420,15 @@ var BundlePluginLoader = class {
1047
1420
  }
1048
1421
  /** Load skills from the plugin's skills/ directory. */
1049
1422
  loadSkills(pluginDir, pluginName) {
1050
- const skillsDir = (0, import_node_path3.join)(pluginDir, "skills");
1051
- if (!(0, import_node_fs2.existsSync)(skillsDir)) return [];
1052
- const entries = (0, import_node_fs2.readdirSync)(skillsDir, { withFileTypes: true });
1423
+ const skillsDir = (0, import_node_path5.join)(pluginDir, "skills");
1424
+ if (!(0, import_node_fs4.existsSync)(skillsDir)) return [];
1425
+ const entries = (0, import_node_fs4.readdirSync)(skillsDir, { withFileTypes: true });
1053
1426
  const skills = [];
1054
1427
  for (const entry of entries) {
1055
1428
  if (!entry.isDirectory()) continue;
1056
- const skillFile = (0, import_node_path3.join)(skillsDir, entry.name, "SKILL.md");
1057
- if (!(0, import_node_fs2.existsSync)(skillFile)) continue;
1058
- const raw = (0, import_node_fs2.readFileSync)(skillFile, "utf-8");
1429
+ const skillFile = (0, import_node_path5.join)(skillsDir, entry.name, "SKILL.md");
1430
+ if (!(0, import_node_fs4.existsSync)(skillFile)) continue;
1431
+ const raw = (0, import_node_fs4.readFileSync)(skillFile, "utf-8");
1059
1432
  const { metadata, content } = parseSkillFrontmatter(raw);
1060
1433
  const description = typeof metadata.description === "string" ? metadata.description : "";
1061
1434
  const skill = {
@@ -1070,13 +1443,13 @@ var BundlePluginLoader = class {
1070
1443
  }
1071
1444
  /** Load commands from the plugin's commands/ directory (flat .md files). */
1072
1445
  loadCommands(pluginDir, pluginName) {
1073
- const commandsDir = (0, import_node_path3.join)(pluginDir, "commands");
1074
- if (!(0, import_node_fs2.existsSync)(commandsDir)) return [];
1075
- const entries = (0, import_node_fs2.readdirSync)(commandsDir, { withFileTypes: true });
1446
+ const commandsDir = (0, import_node_path5.join)(pluginDir, "commands");
1447
+ if (!(0, import_node_fs4.existsSync)(commandsDir)) return [];
1448
+ const entries = (0, import_node_fs4.readdirSync)(commandsDir, { withFileTypes: true });
1076
1449
  const commands = [];
1077
1450
  for (const entry of entries) {
1078
1451
  if (!entry.isFile() || !entry.name.endsWith(".md")) continue;
1079
- const raw = (0, import_node_fs2.readFileSync)((0, import_node_path3.join)(commandsDir, entry.name), "utf-8");
1452
+ const raw = (0, import_node_fs4.readFileSync)((0, import_node_path5.join)(commandsDir, entry.name), "utf-8");
1080
1453
  const { metadata, content } = parseSkillFrontmatter(raw);
1081
1454
  const name = typeof metadata.name === "string" ? metadata.name : entry.name.replace(/\.md$/, "");
1082
1455
  const description = typeof metadata.description === "string" ? metadata.description : "";
@@ -1091,10 +1464,10 @@ var BundlePluginLoader = class {
1091
1464
  }
1092
1465
  /** Load hooks from hooks/hooks.json if present. */
1093
1466
  loadHooks(pluginDir) {
1094
- const hooksPath = (0, import_node_path3.join)(pluginDir, "hooks", "hooks.json");
1095
- if (!(0, import_node_fs2.existsSync)(hooksPath)) return {};
1467
+ const hooksPath = (0, import_node_path5.join)(pluginDir, "hooks", "hooks.json");
1468
+ if (!(0, import_node_fs4.existsSync)(hooksPath)) return {};
1096
1469
  try {
1097
- const raw = (0, import_node_fs2.readFileSync)(hooksPath, "utf-8");
1470
+ const raw = (0, import_node_fs4.readFileSync)(hooksPath, "utf-8");
1098
1471
  const data = JSON.parse(raw);
1099
1472
  if (typeof data === "object" && data !== null) {
1100
1473
  return data;
@@ -1106,12 +1479,12 @@ var BundlePluginLoader = class {
1106
1479
  }
1107
1480
  /** Load MCP server configuration if present. Checks `.mcp.json` at plugin root first. */
1108
1481
  loadMcpConfig(pluginDir) {
1109
- const primaryPath = (0, import_node_path3.join)(pluginDir, ".mcp.json");
1110
- const fallbackPath = (0, import_node_path3.join)(pluginDir, ".claude-plugin", "mcp.json");
1111
- const mcpPath = (0, import_node_fs2.existsSync)(primaryPath) ? primaryPath : fallbackPath;
1112
- if (!(0, import_node_fs2.existsSync)(mcpPath)) return void 0;
1482
+ const primaryPath = (0, import_node_path5.join)(pluginDir, ".mcp.json");
1483
+ const fallbackPath = (0, import_node_path5.join)(pluginDir, ".claude-plugin", "mcp.json");
1484
+ const mcpPath = (0, import_node_fs4.existsSync)(primaryPath) ? primaryPath : fallbackPath;
1485
+ if (!(0, import_node_fs4.existsSync)(mcpPath)) return void 0;
1113
1486
  try {
1114
- const raw = (0, import_node_fs2.readFileSync)(mcpPath, "utf-8");
1487
+ const raw = (0, import_node_fs4.readFileSync)(mcpPath, "utf-8");
1115
1488
  return JSON.parse(raw);
1116
1489
  } catch {
1117
1490
  return void 0;
@@ -1119,10 +1492,10 @@ var BundlePluginLoader = class {
1119
1492
  }
1120
1493
  /** Load agent definitions from agents/ directory if present. */
1121
1494
  loadAgents(pluginDir) {
1122
- const agentsDir = (0, import_node_path3.join)(pluginDir, "agents");
1123
- if (!(0, import_node_fs2.existsSync)(agentsDir)) return [];
1495
+ const agentsDir = (0, import_node_path5.join)(pluginDir, "agents");
1496
+ if (!(0, import_node_fs4.existsSync)(agentsDir)) return [];
1124
1497
  try {
1125
- const entries = (0, import_node_fs2.readdirSync)(agentsDir, { withFileTypes: true });
1498
+ const entries = (0, import_node_fs4.readdirSync)(agentsDir, { withFileTypes: true });
1126
1499
  return entries.filter((e) => e.isDirectory() || e.name.endsWith(".md")).map((e) => e.name.replace(/\.md$/, ""));
1127
1500
  } catch {
1128
1501
  return [];
@@ -1132,8 +1505,8 @@ var BundlePluginLoader = class {
1132
1505
 
1133
1506
  // src/plugins/bundle-plugin-installer.ts
1134
1507
  var import_node_child_process = require("child_process");
1135
- var import_node_fs3 = require("fs");
1136
- var import_node_path4 = require("path");
1508
+ var import_node_fs5 = require("fs");
1509
+ var import_node_path6 = require("path");
1137
1510
  var GIT_CLONE_TIMEOUT_MS = 6e4;
1138
1511
  var BundlePluginInstaller = class {
1139
1512
  pluginsDir;
@@ -1144,8 +1517,8 @@ var BundlePluginInstaller = class {
1144
1517
  exec;
1145
1518
  constructor(options) {
1146
1519
  this.pluginsDir = options.pluginsDir;
1147
- this.cacheDir = (0, import_node_path4.join)(this.pluginsDir, "cache");
1148
- this.registryPath = (0, import_node_path4.join)(this.pluginsDir, "installed_plugins.json");
1520
+ this.cacheDir = (0, import_node_path6.join)(this.pluginsDir, "cache");
1521
+ this.registryPath = (0, import_node_path6.join)(this.pluginsDir, "installed_plugins.json");
1149
1522
  this.settingsStore = options.settingsStore;
1150
1523
  this.marketplaceClient = options.marketplaceClient;
1151
1524
  this.exec = options.exec ?? this.defaultExec;
@@ -1165,8 +1538,8 @@ var BundlePluginInstaller = class {
1165
1538
  throw new Error(`Plugin "${pluginName}" not found in marketplace "${marketplaceName}"`);
1166
1539
  }
1167
1540
  const version = this.resolveVersion(entry, marketplaceName);
1168
- const targetDir = (0, import_node_path4.join)(this.cacheDir, marketplaceName, pluginName, version);
1169
- if ((0, import_node_fs3.existsSync)(targetDir)) {
1541
+ const targetDir = (0, import_node_path6.join)(this.cacheDir, marketplaceName, pluginName, version);
1542
+ if ((0, import_node_fs5.existsSync)(targetDir)) {
1170
1543
  throw new Error(
1171
1544
  `Plugin "${pluginName}" version "${version}" is already installed from "${marketplaceName}"`
1172
1545
  );
@@ -1193,8 +1566,8 @@ var BundlePluginInstaller = class {
1193
1566
  if (!record) {
1194
1567
  throw new Error(`Plugin "${pluginId}" is not installed`);
1195
1568
  }
1196
- if ((0, import_node_fs3.existsSync)(record.installPath)) {
1197
- (0, import_node_fs3.rmSync)(record.installPath, { recursive: true, force: true });
1569
+ if ((0, import_node_fs5.existsSync)(record.installPath)) {
1570
+ (0, import_node_fs5.rmSync)(record.installPath, { recursive: true, force: true });
1198
1571
  }
1199
1572
  delete registry[pluginId];
1200
1573
  this.writeRegistry(registry);
@@ -1226,30 +1599,52 @@ var BundlePluginInstaller = class {
1226
1599
  }
1227
1600
  return this.marketplaceClient.getMarketplaceSha(marketplaceName);
1228
1601
  }
1602
+ /**
1603
+ * Normalize source object — Claude Code manifests use `source` key instead of `type`.
1604
+ * e.g., { source: "url", url: "..." } → { type: "url", url: "..." }
1605
+ */
1606
+ normalizeSource(source) {
1607
+ if (typeof source === "string") return source;
1608
+ const obj = source;
1609
+ if (!obj.type && typeof obj.source === "string") {
1610
+ return { ...obj, type: obj.source };
1611
+ }
1612
+ return source;
1613
+ }
1229
1614
  /** Resolve the source and install the plugin. */
1230
- resolveAndInstall(source, marketplaceName, pluginName, targetDir) {
1231
- (0, import_node_fs3.mkdirSync)(targetDir, { recursive: true });
1232
- if (typeof source === "string") {
1233
- const marketplaceDir = this.marketplaceClient.getMarketplaceDir(marketplaceName);
1234
- const sourcePath = (0, import_node_path4.join)(marketplaceDir, source);
1235
- if (!(0, import_node_fs3.existsSync)(sourcePath)) {
1236
- (0, import_node_fs3.rmSync)(targetDir, { recursive: true, force: true });
1237
- throw new Error(
1238
- `Plugin source path "${source}" not found in marketplace "${marketplaceName}"`
1239
- );
1615
+ resolveAndInstall(rawSource, marketplaceName, pluginName, targetDir) {
1616
+ (0, import_node_fs5.mkdirSync)(targetDir, { recursive: true });
1617
+ const source = this.normalizeSource(rawSource);
1618
+ try {
1619
+ if (typeof source === "string") {
1620
+ const marketplaceDir = this.marketplaceClient.getMarketplaceDir(marketplaceName);
1621
+ const sourcePath = (0, import_node_path6.join)(marketplaceDir, source);
1622
+ if (!(0, import_node_fs5.existsSync)(sourcePath)) {
1623
+ throw new Error(
1624
+ `Plugin source path "${source}" not found in marketplace "${marketplaceName}"`
1625
+ );
1626
+ }
1627
+ (0, import_node_fs5.cpSync)(sourcePath, targetDir, { recursive: true });
1628
+ } else if (source.type === "github") {
1629
+ const repoUrl = `https://github.com/${source.repo}.git`;
1630
+ this.cloneToDir(repoUrl, targetDir, pluginName);
1631
+ } else if (source.type === "url" && typeof source.url === "string" && source.url.endsWith(".git")) {
1632
+ this.cloneToDir(source.url, targetDir, pluginName);
1633
+ } else if (source.type === "url") {
1634
+ throw new Error(`URL source "${source.url}" is not a git repository (must end with .git)`);
1635
+ } else {
1636
+ throw new Error(`Unknown source type: ${JSON.stringify(source)}`);
1240
1637
  }
1241
- (0, import_node_fs3.cpSync)(sourcePath, targetDir, { recursive: true });
1242
- } else if (source.type === "github") {
1243
- const repoUrl = `https://github.com/${source.repo}.git`;
1244
- this.cloneToDir(repoUrl, targetDir, pluginName);
1245
- } else if (source.type === "url") {
1246
- (0, import_node_fs3.rmSync)(targetDir, { recursive: true, force: true });
1247
- throw new Error("URL source installation is not yet supported");
1638
+ } catch (err) {
1639
+ if ((0, import_node_fs5.existsSync)(targetDir)) {
1640
+ (0, import_node_fs5.rmSync)(targetDir, { recursive: true, force: true });
1641
+ }
1642
+ throw err;
1248
1643
  }
1249
1644
  }
1250
1645
  /** Clone a git repository to the target directory. */
1251
1646
  cloneToDir(repoUrl, targetDir, pluginName) {
1252
- (0, import_node_fs3.rmSync)(targetDir, { recursive: true, force: true });
1647
+ (0, import_node_fs5.rmSync)(targetDir, { recursive: true, force: true });
1253
1648
  const command = `git clone --depth 1 ${repoUrl} ${targetDir}`;
1254
1649
  try {
1255
1650
  this.exec(command, { timeout: GIT_CLONE_TIMEOUT_MS, stdio: "pipe" });
@@ -1260,11 +1655,11 @@ var BundlePluginInstaller = class {
1260
1655
  }
1261
1656
  /** Read the installed_plugins.json registry. */
1262
1657
  readRegistry() {
1263
- if (!(0, import_node_fs3.existsSync)(this.registryPath)) {
1658
+ if (!(0, import_node_fs5.existsSync)(this.registryPath)) {
1264
1659
  return {};
1265
1660
  }
1266
1661
  try {
1267
- const raw = (0, import_node_fs3.readFileSync)(this.registryPath, "utf-8");
1662
+ const raw = (0, import_node_fs5.readFileSync)(this.registryPath, "utf-8");
1268
1663
  const data = JSON.parse(raw);
1269
1664
  if (typeof data === "object" && data !== null) {
1270
1665
  return data;
@@ -1276,11 +1671,11 @@ var BundlePluginInstaller = class {
1276
1671
  }
1277
1672
  /** Write the installed_plugins.json registry. */
1278
1673
  writeRegistry(registry) {
1279
- const dir = (0, import_node_path4.dirname)(this.registryPath);
1280
- if (!(0, import_node_fs3.existsSync)(dir)) {
1281
- (0, import_node_fs3.mkdirSync)(dir, { recursive: true });
1674
+ const dir = (0, import_node_path6.dirname)(this.registryPath);
1675
+ if (!(0, import_node_fs5.existsSync)(dir)) {
1676
+ (0, import_node_fs5.mkdirSync)(dir, { recursive: true });
1282
1677
  }
1283
- (0, import_node_fs3.writeFileSync)(this.registryPath, JSON.stringify(registry, null, 2), "utf-8");
1678
+ (0, import_node_fs5.writeFileSync)(this.registryPath, JSON.stringify(registry, null, 2), "utf-8");
1284
1679
  }
1285
1680
  /** Default exec implementation using child_process. */
1286
1681
  defaultExec(command, options) {
@@ -1290,8 +1685,8 @@ var BundlePluginInstaller = class {
1290
1685
 
1291
1686
  // src/plugins/marketplace-client.ts
1292
1687
  var import_node_child_process2 = require("child_process");
1293
- var import_node_fs4 = require("fs");
1294
- var import_node_path5 = require("path");
1688
+ var import_node_fs6 = require("fs");
1689
+ var import_node_path7 = require("path");
1295
1690
  var GIT_TIMEOUT_MS = 6e4;
1296
1691
  var MarketplaceClient = class {
1297
1692
  pluginsDir;
@@ -1301,8 +1696,8 @@ var MarketplaceClient = class {
1301
1696
  constructor(options) {
1302
1697
  this.pluginsDir = options.pluginsDir;
1303
1698
  this.exec = options.exec ?? this.defaultExec;
1304
- this.marketplacesDir = (0, import_node_path5.join)(this.pluginsDir, "marketplaces");
1305
- this.registryPath = (0, import_node_path5.join)(this.pluginsDir, "known_marketplaces.json");
1699
+ this.marketplacesDir = (0, import_node_path7.join)(this.pluginsDir, "marketplaces");
1700
+ this.registryPath = (0, import_node_path7.join)(this.pluginsDir, "known_marketplaces.json");
1306
1701
  }
1307
1702
  /**
1308
1703
  * Add a marketplace by cloning its repository.
@@ -1316,13 +1711,13 @@ var MarketplaceClient = class {
1316
1711
  */
1317
1712
  addMarketplace(source) {
1318
1713
  const tempName = "temp-" + Date.now().toString(36);
1319
- const tempDir = (0, import_node_path5.join)(this.marketplacesDir, tempName);
1320
- (0, import_node_fs4.mkdirSync)(this.marketplacesDir, { recursive: true });
1714
+ const tempDir = (0, import_node_path7.join)(this.marketplacesDir, tempName);
1715
+ (0, import_node_fs6.mkdirSync)(this.marketplacesDir, { recursive: true });
1321
1716
  if (source.type === "local") {
1322
- if (!(0, import_node_fs4.existsSync)(source.path)) {
1717
+ if (!(0, import_node_fs6.existsSync)(source.path)) {
1323
1718
  throw new Error(`Local marketplace path does not exist: ${source.path}`);
1324
1719
  }
1325
- (0, import_node_fs4.cpSync)(source.path, tempDir, { recursive: true });
1720
+ (0, import_node_fs6.cpSync)(source.path, tempDir, { recursive: true });
1326
1721
  } else {
1327
1722
  const cloneUrl = this.resolveCloneUrl(source);
1328
1723
  const command = `git clone --depth 1 ${cloneUrl} ${tempDir}`;
@@ -1333,9 +1728,9 @@ var MarketplaceClient = class {
1333
1728
  throw new Error(`Failed to clone marketplace: ${message}`);
1334
1729
  }
1335
1730
  }
1336
- const manifestPath = (0, import_node_path5.join)(tempDir, ".claude-plugin", "marketplace.json");
1337
- if (!(0, import_node_fs4.existsSync)(manifestPath)) {
1338
- (0, import_node_fs4.rmSync)(tempDir, { recursive: true, force: true });
1731
+ const manifestPath = (0, import_node_path7.join)(tempDir, ".claude-plugin", "marketplace.json");
1732
+ if (!(0, import_node_fs6.existsSync)(manifestPath)) {
1733
+ (0, import_node_fs6.rmSync)(tempDir, { recursive: true, force: true });
1339
1734
  throw new Error(
1340
1735
  source.type === "local" ? "Local directory does not contain .claude-plugin/marketplace.json" : "Cloned repository does not contain .claude-plugin/marketplace.json"
1341
1736
  );
@@ -1343,16 +1738,16 @@ var MarketplaceClient = class {
1343
1738
  const manifest = this.readManifestFromPath(manifestPath);
1344
1739
  const name = manifest.name;
1345
1740
  if (!name) {
1346
- (0, import_node_fs4.rmSync)(tempDir, { recursive: true, force: true });
1741
+ (0, import_node_fs6.rmSync)(tempDir, { recursive: true, force: true });
1347
1742
  throw new Error('Marketplace manifest does not contain a "name" field');
1348
1743
  }
1349
1744
  const registry = this.readRegistry();
1350
1745
  if (registry[name]) {
1351
- (0, import_node_fs4.rmSync)(tempDir, { recursive: true, force: true });
1746
+ (0, import_node_fs6.rmSync)(tempDir, { recursive: true, force: true });
1352
1747
  throw new Error(`Marketplace "${name}" already exists`);
1353
1748
  }
1354
- const finalDir = (0, import_node_path5.join)(this.marketplacesDir, name);
1355
- (0, import_node_fs4.renameSync)(tempDir, finalDir);
1749
+ const finalDir = (0, import_node_path7.join)(this.marketplacesDir, name);
1750
+ (0, import_node_fs6.renameSync)(tempDir, finalDir);
1356
1751
  registry[name] = {
1357
1752
  source,
1358
1753
  installLocation: finalDir,
@@ -1373,8 +1768,8 @@ var MarketplaceClient = class {
1373
1768
  throw new Error(`Marketplace "${name}" not found`);
1374
1769
  }
1375
1770
  this.removeInstalledPluginsForMarketplace(name);
1376
- if ((0, import_node_fs4.existsSync)(entry.installLocation)) {
1377
- (0, import_node_fs4.rmSync)(entry.installLocation, { recursive: true, force: true });
1771
+ if ((0, import_node_fs6.existsSync)(entry.installLocation)) {
1772
+ (0, import_node_fs6.rmSync)(entry.installLocation, { recursive: true, force: true });
1378
1773
  }
1379
1774
  delete registry[name];
1380
1775
  this.writeRegistry(registry);
@@ -1393,16 +1788,16 @@ var MarketplaceClient = class {
1393
1788
  if (!entry) {
1394
1789
  throw new Error(`Marketplace "${name}" not found`);
1395
1790
  }
1396
- if (!(0, import_node_fs4.existsSync)(entry.installLocation)) {
1791
+ if (!(0, import_node_fs6.existsSync)(entry.installLocation)) {
1397
1792
  throw new Error(`Marketplace directory for "${name}" does not exist`);
1398
1793
  }
1399
1794
  if (entry.source.type === "local") {
1400
1795
  const localSource = entry.source;
1401
- if (!(0, import_node_fs4.existsSync)(localSource.path)) {
1796
+ if (!(0, import_node_fs6.existsSync)(localSource.path)) {
1402
1797
  throw new Error(`Local marketplace path does not exist: ${localSource.path}`);
1403
1798
  }
1404
- (0, import_node_fs4.rmSync)(entry.installLocation, { recursive: true, force: true });
1405
- (0, import_node_fs4.cpSync)(localSource.path, entry.installLocation, { recursive: true });
1799
+ (0, import_node_fs6.rmSync)(entry.installLocation, { recursive: true, force: true });
1800
+ (0, import_node_fs6.cpSync)(localSource.path, entry.installLocation, { recursive: true });
1406
1801
  } else {
1407
1802
  const command = `git -C ${entry.installLocation} pull`;
1408
1803
  try {
@@ -1433,8 +1828,8 @@ var MarketplaceClient = class {
1433
1828
  if (!entry) {
1434
1829
  throw new Error(`Marketplace "${marketplaceName}" not found`);
1435
1830
  }
1436
- const manifestPath = (0, import_node_path5.join)(entry.installLocation, ".claude-plugin", "marketplace.json");
1437
- if (!(0, import_node_fs4.existsSync)(manifestPath)) {
1831
+ const manifestPath = (0, import_node_path7.join)(entry.installLocation, ".claude-plugin", "marketplace.json");
1832
+ if (!(0, import_node_fs6.existsSync)(manifestPath)) {
1438
1833
  throw new Error(
1439
1834
  `Marketplace "${marketplaceName}" does not contain .claude-plugin/marketplace.json`
1440
1835
  );
@@ -1501,11 +1896,11 @@ var MarketplaceClient = class {
1501
1896
  * and updates the registry.
1502
1897
  */
1503
1898
  removeInstalledPluginsForMarketplace(marketplaceName) {
1504
- const installedPath = (0, import_node_path5.join)(this.pluginsDir, "installed_plugins.json");
1505
- if (!(0, import_node_fs4.existsSync)(installedPath)) return;
1899
+ const installedPath = (0, import_node_path7.join)(this.pluginsDir, "installed_plugins.json");
1900
+ if (!(0, import_node_fs6.existsSync)(installedPath)) return;
1506
1901
  let registry;
1507
1902
  try {
1508
- const raw = (0, import_node_fs4.readFileSync)(installedPath, "utf-8");
1903
+ const raw = (0, import_node_fs6.readFileSync)(installedPath, "utf-8");
1509
1904
  const data = JSON.parse(raw);
1510
1905
  if (typeof data !== "object" || data === null) return;
1511
1906
  registry = data;
@@ -1515,24 +1910,24 @@ var MarketplaceClient = class {
1515
1910
  let changed = false;
1516
1911
  for (const [pluginId, record] of Object.entries(registry)) {
1517
1912
  if (record.marketplace === marketplaceName) {
1518
- if (record.installPath && (0, import_node_fs4.existsSync)(record.installPath)) {
1519
- (0, import_node_fs4.rmSync)(record.installPath, { recursive: true, force: true });
1913
+ if (record.installPath && (0, import_node_fs6.existsSync)(record.installPath)) {
1914
+ (0, import_node_fs6.rmSync)(record.installPath, { recursive: true, force: true });
1520
1915
  }
1521
1916
  delete registry[pluginId];
1522
1917
  changed = true;
1523
1918
  }
1524
1919
  }
1525
1920
  if (changed) {
1526
- const dir = (0, import_node_path5.dirname)(installedPath);
1527
- if (!(0, import_node_fs4.existsSync)(dir)) {
1528
- (0, import_node_fs4.mkdirSync)(dir, { recursive: true });
1921
+ const dir = (0, import_node_path7.dirname)(installedPath);
1922
+ if (!(0, import_node_fs6.existsSync)(dir)) {
1923
+ (0, import_node_fs6.mkdirSync)(dir, { recursive: true });
1529
1924
  }
1530
- (0, import_node_fs4.writeFileSync)(installedPath, JSON.stringify(registry, null, 2), "utf-8");
1925
+ (0, import_node_fs6.writeFileSync)(installedPath, JSON.stringify(registry, null, 2), "utf-8");
1531
1926
  }
1532
1927
  }
1533
1928
  /** Read and parse a marketplace.json from a file path. */
1534
1929
  readManifestFromPath(path) {
1535
- const raw = (0, import_node_fs4.readFileSync)(path, "utf-8");
1930
+ const raw = (0, import_node_fs6.readFileSync)(path, "utf-8");
1536
1931
  const data = JSON.parse(raw);
1537
1932
  if (typeof data !== "object" || data === null) {
1538
1933
  throw new Error("Invalid marketplace manifest: not an object");
@@ -1545,11 +1940,11 @@ var MarketplaceClient = class {
1545
1940
  }
1546
1941
  /** Read the known_marketplaces.json registry. */
1547
1942
  readRegistry() {
1548
- if (!(0, import_node_fs4.existsSync)(this.registryPath)) {
1943
+ if (!(0, import_node_fs6.existsSync)(this.registryPath)) {
1549
1944
  return {};
1550
1945
  }
1551
1946
  try {
1552
- const raw = (0, import_node_fs4.readFileSync)(this.registryPath, "utf-8");
1947
+ const raw = (0, import_node_fs6.readFileSync)(this.registryPath, "utf-8");
1553
1948
  const data = JSON.parse(raw);
1554
1949
  if (typeof data === "object" && data !== null) {
1555
1950
  return data;
@@ -1561,11 +1956,11 @@ var MarketplaceClient = class {
1561
1956
  }
1562
1957
  /** Write the known_marketplaces.json registry. */
1563
1958
  writeRegistry(registry) {
1564
- const dir = (0, import_node_path5.dirname)(this.registryPath);
1565
- if (!(0, import_node_fs4.existsSync)(dir)) {
1566
- (0, import_node_fs4.mkdirSync)(dir, { recursive: true });
1959
+ const dir = (0, import_node_path7.dirname)(this.registryPath);
1960
+ if (!(0, import_node_fs6.existsSync)(dir)) {
1961
+ (0, import_node_fs6.mkdirSync)(dir, { recursive: true });
1567
1962
  }
1568
- (0, import_node_fs4.writeFileSync)(this.registryPath, JSON.stringify(registry, null, 2), "utf-8");
1963
+ (0, import_node_fs6.writeFileSync)(this.registryPath, JSON.stringify(registry, null, 2), "utf-8");
1569
1964
  }
1570
1965
  /** Default exec implementation using child_process. */
1571
1966
  defaultExec(command, options) {
@@ -1573,78 +1968,6 @@ var MarketplaceClient = class {
1573
1968
  }
1574
1969
  };
1575
1970
 
1576
- // src/tools/agent-tool.ts
1577
- var import_zod2 = require("zod");
1578
- var import_agent_tools2 = require("@robota-sdk/agent-tools");
1579
- function asZodSchema(schema) {
1580
- return schema;
1581
- }
1582
- var AgentSchema = import_zod2.z.object({
1583
- prompt: import_zod2.z.string().describe("Task description for the sub-agent"),
1584
- description: import_zod2.z.string().optional().describe("Short description of what the sub-agent will do (3-5 words)")
1585
- });
1586
- var agentToolDeps;
1587
- function setAgentToolDeps(deps) {
1588
- agentToolDeps = deps;
1589
- }
1590
- async function runAgent(args) {
1591
- if (!agentToolDeps) {
1592
- const result = {
1593
- success: false,
1594
- output: "",
1595
- error: "Agent tool not initialized \u2014 missing dependencies"
1596
- };
1597
- return JSON.stringify(result);
1598
- }
1599
- const noopTerminal = {
1600
- write: () => {
1601
- },
1602
- writeLine: () => {
1603
- },
1604
- writeMarkdown: () => {
1605
- },
1606
- writeError: () => {
1607
- },
1608
- prompt: () => Promise.resolve(""),
1609
- select: () => Promise.resolve(0),
1610
- spinner: () => ({ stop: () => {
1611
- }, update: () => {
1612
- } })
1613
- };
1614
- const subSession = createSession({
1615
- config: agentToolDeps.config,
1616
- context: agentToolDeps.context,
1617
- projectInfo: agentToolDeps.projectInfo,
1618
- terminal: noopTerminal,
1619
- // Sub-agents bypass permissions — they inherit parent's trust
1620
- permissionMode: "bypassPermissions"
1621
- });
1622
- try {
1623
- const response = await subSession.run(args.prompt);
1624
- const result = {
1625
- success: true,
1626
- output: response
1627
- };
1628
- return JSON.stringify(result);
1629
- } catch (err) {
1630
- const message = err instanceof Error ? err.message : String(err);
1631
- const result = {
1632
- success: false,
1633
- output: "",
1634
- error: `Sub-agent error: ${message}`
1635
- };
1636
- return JSON.stringify(result);
1637
- }
1638
- }
1639
- var agentTool = (0, import_agent_tools2.createZodFunctionTool)(
1640
- "Agent",
1641
- "Spawn a sub-agent with isolated context to handle a task. The sub-agent has its own conversation history and can use all tools.",
1642
- asZodSchema(AgentSchema),
1643
- async (params) => {
1644
- return runAgent(params);
1645
- }
1646
- );
1647
-
1648
1971
  // src/index.ts
1649
1972
  var import_agent_tools3 = require("@robota-sdk/agent-tools");
1650
1973
  var import_agent_tools4 = require("@robota-sdk/agent-tools");
@@ -1655,6 +1978,7 @@ var import_agent_tools8 = require("@robota-sdk/agent-tools");
1655
1978
  // Annotate the CommonJS export names for ESM import in node:
1656
1979
  0 && (module.exports = {
1657
1980
  AgentExecutor,
1981
+ BUILT_IN_AGENTS,
1658
1982
  BundlePluginInstaller,
1659
1983
  BundlePluginLoader,
1660
1984
  DEFAULT_TOOL_DESCRIPTIONS,
@@ -1666,15 +1990,21 @@ var import_agent_tools8 = require("@robota-sdk/agent-tools");
1666
1990
  SessionStore,
1667
1991
  SilentSessionLogger,
1668
1992
  TRUST_TO_MODE,
1669
- agentTool,
1993
+ assembleSubagentPrompt,
1670
1994
  bashTool,
1671
1995
  buildSystemPrompt,
1996
+ createAgentTool,
1672
1997
  createDefaultTools,
1673
1998
  createProvider,
1674
1999
  createSession,
2000
+ createSubagentLogger,
2001
+ createSubagentSession,
1675
2002
  detectProject,
1676
2003
  editTool,
1677
2004
  evaluatePermission,
2005
+ getBuiltInAgent,
2006
+ getForkWorkerSuffix,
2007
+ getSubagentSuffix,
1678
2008
  globTool,
1679
2009
  grepTool,
1680
2010
  loadConfig,
@@ -1683,8 +2013,10 @@ var import_agent_tools8 = require("@robota-sdk/agent-tools");
1683
2013
  promptForApproval,
1684
2014
  query,
1685
2015
  readTool,
2016
+ resolveSubagentLogDir,
2017
+ retrieveAgentToolDeps,
1686
2018
  runHooks,
1687
- setAgentToolDeps,
2019
+ storeAgentToolDeps,
1688
2020
  userPaths,
1689
2021
  writeTool
1690
2022
  });