@robota-sdk/agent-sdk 3.0.0-beta.31 → 3.0.0-beta.33

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.
@@ -109,7 +109,7 @@ Respond with JSON: { "ok": boolean, "reason"?: string }`;
109
109
  };
110
110
 
111
111
  // src/assembly/create-session.ts
112
- import { Session } from "@robota-sdk/agent-sessions";
112
+ import { Session as Session2 } from "@robota-sdk/agent-sessions";
113
113
 
114
114
  // src/context/system-prompt-builder.ts
115
115
  var TRUST_LEVEL_DESCRIPTIONS = {
@@ -251,11 +251,379 @@ function createProvider(config) {
251
251
  return new AnthropicProvider({ apiKey });
252
252
  }
253
253
 
254
+ // src/tools/agent-tool.ts
255
+ import { z } from "zod";
256
+ import { createZodFunctionTool } from "@robota-sdk/agent-tools";
257
+
258
+ // src/agents/built-in-agents.ts
259
+ 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.
260
+
261
+ Your role is to complete the assigned task thoroughly and accurately. Follow these guidelines:
262
+
263
+ - Execute the task as described in the prompt. Do not expand scope beyond what is requested.
264
+ - Use the most appropriate tools for each step. Prefer precise tools (Read, Grep, Glob) over broad ones (Bash) when possible.
265
+ - Report your findings clearly and concisely when the task is complete.
266
+ - If a task cannot be completed, explain why and what information is missing.
267
+ - Maintain the same code quality standards as the parent session (strict types, no fallbacks, proper error handling).`;
268
+ 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.
269
+
270
+ 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.
271
+
272
+ Your role is to answer questions about the codebase by:
273
+
274
+ - Searching for relevant files, symbols, and patterns using Glob and Grep.
275
+ - Reading source files, configuration, and documentation to understand structure and behavior.
276
+ - Tracing code paths across modules to understand how components interact.
277
+ - Summarizing findings in a clear, structured format with file paths and line references.
278
+ - Identifying architectural patterns, dependencies, and potential issues.
279
+
280
+ 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.`;
281
+ 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.
282
+
283
+ You operate in read-only mode. You must NEVER attempt to write or edit files. Your tools are restricted to read-only operations.
284
+
285
+ Your role is to:
286
+
287
+ - Analyze the current codebase state relevant to the task by reading specs, source code, and tests.
288
+ - Research implementation approaches by examining existing patterns and architectural conventions in the repository.
289
+ - Identify affected files, modules, and interfaces that a proposed change would touch.
290
+ - Assess risks, dependencies, and potential breaking changes.
291
+ - Produce a structured implementation plan with clear steps, file lists, and ordering.
292
+ - Consider edge cases, error handling, and test coverage requirements.
293
+
294
+ 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.`;
295
+ var BUILT_IN_AGENTS = [
296
+ {
297
+ name: "general-purpose",
298
+ description: "General-purpose task execution agent with full tool access.",
299
+ systemPrompt: GENERAL_PURPOSE_SYSTEM_PROMPT
300
+ },
301
+ {
302
+ name: "Explore",
303
+ description: "Read-only codebase exploration and analysis agent.",
304
+ systemPrompt: EXPLORE_SYSTEM_PROMPT,
305
+ model: "claude-haiku-4-5",
306
+ disallowedTools: ["Write", "Edit"]
307
+ },
308
+ {
309
+ name: "Plan",
310
+ description: "Read-only planning, research, and architecture agent.",
311
+ systemPrompt: PLAN_SYSTEM_PROMPT,
312
+ disallowedTools: ["Write", "Edit"]
313
+ }
314
+ ];
315
+ function getBuiltInAgent(name) {
316
+ return BUILT_IN_AGENTS.find((agent) => agent.name === name);
317
+ }
318
+
319
+ // src/assembly/create-subagent-session.ts
320
+ import { Session } from "@robota-sdk/agent-sessions";
321
+
322
+ // src/assembly/subagent-prompts.ts
323
+ function getSubagentSuffix() {
324
+ 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.
325
+
326
+ 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.
327
+
328
+ Do not use emojis.`;
329
+ }
330
+ function getForkWorkerSuffix() {
331
+ 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:
332
+ - Scope: What was requested
333
+ - Result: What was done
334
+ - Key files: Relevant file paths (absolute)
335
+ - Files changed: List of modifications
336
+ - Issues: Any problems encountered`;
337
+ }
338
+ function assembleSubagentPrompt(options) {
339
+ const parts = [options.agentBody];
340
+ if (options.claudeMd) {
341
+ parts.push(options.claudeMd);
342
+ }
343
+ if (options.agentsMd) {
344
+ parts.push(options.agentsMd);
345
+ }
346
+ const suffix = options.isForkWorker ? getForkWorkerSuffix() : getSubagentSuffix();
347
+ parts.push(suffix);
348
+ return parts.join("\n\n");
349
+ }
350
+
351
+ // src/assembly/create-subagent-session.ts
352
+ var MODEL_SHORTCUTS = {
353
+ sonnet: "claude-sonnet-4-6",
354
+ haiku: "claude-haiku-4-5",
355
+ opus: "claude-opus-4-6"
356
+ };
357
+ function resolveModelId(shortName, _parentModel) {
358
+ return MODEL_SHORTCUTS[shortName] ?? shortName;
359
+ }
360
+ function filterTools(parentTools, agentDefinition) {
361
+ let tools = [...parentTools];
362
+ if (agentDefinition.disallowedTools) {
363
+ const denySet = new Set(agentDefinition.disallowedTools);
364
+ tools = tools.filter((t) => !denySet.has(t.getName()));
365
+ }
366
+ if (agentDefinition.tools) {
367
+ const allowSet = new Set(agentDefinition.tools);
368
+ tools = tools.filter((t) => allowSet.has(t.getName()));
369
+ }
370
+ tools = tools.filter((t) => t.getName() !== "Agent");
371
+ return tools;
372
+ }
373
+ function createSubagentSession(options) {
374
+ const { agentDefinition, parentConfig, parentContext, parentTools, terminal } = options;
375
+ const tools = filterTools(parentTools, agentDefinition);
376
+ const model = agentDefinition.model ? resolveModelId(agentDefinition.model, parentConfig.provider.model) : parentConfig.provider.model;
377
+ const systemMessage = assembleSubagentPrompt({
378
+ agentBody: agentDefinition.systemPrompt,
379
+ claudeMd: parentContext.claudeMd,
380
+ agentsMd: parentContext.agentsMd,
381
+ isForkWorker: options.isForkWorker ?? false
382
+ });
383
+ const provider = createProvider(parentConfig);
384
+ return new Session({
385
+ tools,
386
+ provider,
387
+ systemMessage,
388
+ terminal,
389
+ model,
390
+ maxTurns: agentDefinition.maxTurns,
391
+ permissions: parentConfig.permissions,
392
+ permissionMode: options.permissionMode,
393
+ defaultTrustLevel: parentConfig.defaultTrustLevel,
394
+ permissionHandler: options.permissionHandler,
395
+ hooks: options.hooks,
396
+ hookTypeExecutors: options.hookTypeExecutors,
397
+ onTextDelta: options.onTextDelta,
398
+ onToolExecution: options.onToolExecution
399
+ });
400
+ }
401
+
402
+ // src/tools/agent-tool.ts
403
+ function asZodSchema(schema) {
404
+ return schema;
405
+ }
406
+ var AgentSchema = z.object({
407
+ prompt: z.string().describe("The task for the subagent to perform"),
408
+ subagent_type: z.string().optional().describe('Agent type: "general-purpose", "Explore", "Plan", or a custom agent name'),
409
+ model: z.string().optional().describe("Optional model override")
410
+ });
411
+ var sessionDepsStore = /* @__PURE__ */ new WeakMap();
412
+ function storeAgentToolDeps(key, deps) {
413
+ sessionDepsStore.set(key, deps);
414
+ }
415
+ function retrieveAgentToolDeps(key) {
416
+ return sessionDepsStore.get(key);
417
+ }
418
+ function resolveAgentDefinition(agentType, customRegistry) {
419
+ const builtIn = getBuiltInAgent(agentType);
420
+ if (builtIn) return builtIn;
421
+ if (customRegistry) return customRegistry(agentType);
422
+ return void 0;
423
+ }
424
+ function generateAgentId() {
425
+ return `agent_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
426
+ }
427
+ function createAgentTool(deps) {
428
+ async function runAgent(args) {
429
+ const agentType = args.subagent_type ?? "general-purpose";
430
+ const agentDef = resolveAgentDefinition(agentType, deps.customAgentRegistry);
431
+ if (!agentDef) {
432
+ return JSON.stringify({
433
+ success: false,
434
+ output: "",
435
+ error: `Unknown agent type: ${agentType}`
436
+ });
437
+ }
438
+ const effectiveDef = args.model ? { ...agentDef, model: args.model } : agentDef;
439
+ const session = createSubagentSession({
440
+ agentDefinition: effectiveDef,
441
+ parentConfig: deps.config,
442
+ parentContext: deps.context,
443
+ parentTools: deps.tools,
444
+ terminal: deps.terminal,
445
+ permissionMode: deps.permissionMode,
446
+ permissionHandler: deps.permissionHandler,
447
+ hooks: deps.hooks,
448
+ hookTypeExecutors: deps.hookTypeExecutors,
449
+ onTextDelta: deps.onTextDelta,
450
+ onToolExecution: deps.onToolExecution
451
+ });
452
+ const agentId = generateAgentId();
453
+ try {
454
+ const response = await session.run(args.prompt);
455
+ return JSON.stringify({
456
+ success: true,
457
+ output: response,
458
+ agentId
459
+ });
460
+ } catch (err) {
461
+ const message = err instanceof Error ? err.message : String(err);
462
+ return JSON.stringify({
463
+ success: false,
464
+ output: "",
465
+ error: `Sub-agent error: ${message}`,
466
+ agentId
467
+ });
468
+ }
469
+ }
470
+ return createZodFunctionTool(
471
+ "Agent",
472
+ "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.",
473
+ asZodSchema(AgentSchema),
474
+ async (params) => {
475
+ return runAgent(params);
476
+ }
477
+ );
478
+ }
479
+
480
+ // src/agents/agent-definition-loader.ts
481
+ import { readdirSync, readFileSync, existsSync } from "fs";
482
+ import { join, basename } from "path";
483
+ import { homedir } from "os";
484
+ var LIST_KEYS = /* @__PURE__ */ new Set(["tools", "disallowedTools"]);
485
+ var NUMBER_KEYS = /* @__PURE__ */ new Set(["maxTurns"]);
486
+ function parseFrontmatter(content) {
487
+ const lines = content.split("\n");
488
+ if (lines[0]?.trim() !== "---") {
489
+ return { frontmatter: null, body: content };
490
+ }
491
+ let endIndex = -1;
492
+ for (let i = 1; i < lines.length; i++) {
493
+ if (lines[i]?.trim() === "---") {
494
+ endIndex = i;
495
+ break;
496
+ }
497
+ }
498
+ if (endIndex === -1) {
499
+ return { frontmatter: null, body: content };
500
+ }
501
+ const result = {};
502
+ for (let i = 1; i < endIndex; i++) {
503
+ const line = lines[i];
504
+ const match = line.match(/^([a-zA-Z][a-zA-Z0-9]*(?:[A-Z][a-z]*)*):\s*(.+)/);
505
+ if (!match) continue;
506
+ const key = match[1];
507
+ const rawValue = match[2].trim();
508
+ if (LIST_KEYS.has(key)) {
509
+ result[key] = rawValue.split(",").map((s) => s.trim());
510
+ } else if (NUMBER_KEYS.has(key)) {
511
+ result[key] = parseInt(rawValue, 10);
512
+ } else {
513
+ result[key] = rawValue;
514
+ }
515
+ }
516
+ const body = lines.slice(endIndex + 1).join("\n").trim();
517
+ return {
518
+ frontmatter: Object.keys(result).length > 0 ? result : null,
519
+ body
520
+ };
521
+ }
522
+ function scanAgentsDir(dir) {
523
+ if (!existsSync(dir)) return [];
524
+ const agents = [];
525
+ let entries;
526
+ try {
527
+ entries = readdirSync(dir, { withFileTypes: true });
528
+ } catch {
529
+ return [];
530
+ }
531
+ for (const entry of entries) {
532
+ if (!entry.isFile() || !entry.name.endsWith(".md")) continue;
533
+ const filePath = join(dir, entry.name);
534
+ const content = readFileSync(filePath, "utf-8");
535
+ const { frontmatter, body } = parseFrontmatter(content);
536
+ const fallbackName = basename(entry.name, ".md");
537
+ const agent = {
538
+ name: frontmatter?.name ?? fallbackName,
539
+ description: frontmatter?.description ?? "",
540
+ systemPrompt: body
541
+ };
542
+ if (frontmatter?.model !== void 0) agent.model = frontmatter.model;
543
+ if (frontmatter?.maxTurns !== void 0) agent.maxTurns = frontmatter.maxTurns;
544
+ if (frontmatter?.tools !== void 0) agent.tools = frontmatter.tools;
545
+ if (frontmatter?.disallowedTools !== void 0)
546
+ agent.disallowedTools = frontmatter.disallowedTools;
547
+ agents.push(agent);
548
+ }
549
+ return agents;
550
+ }
551
+ var AgentDefinitionLoader = class {
552
+ cwd;
553
+ home;
554
+ constructor(cwd, home) {
555
+ this.cwd = cwd;
556
+ this.home = home ?? homedir();
557
+ }
558
+ /** Load all agent definitions, merged with built-in agents. Custom overrides built-in on name collision. */
559
+ loadAll() {
560
+ const sources = [
561
+ scanAgentsDir(join(this.cwd, ".claude", "agents")),
562
+ scanAgentsDir(join(this.home, ".robota", "agents"))
563
+ ];
564
+ const seen = /* @__PURE__ */ new Set();
565
+ const customAgents = [];
566
+ for (const agents of sources) {
567
+ for (const agent of agents) {
568
+ if (!seen.has(agent.name)) {
569
+ seen.add(agent.name);
570
+ customAgents.push(agent);
571
+ }
572
+ }
573
+ }
574
+ const result = [...customAgents];
575
+ for (const builtIn of BUILT_IN_AGENTS) {
576
+ if (!seen.has(builtIn.name)) {
577
+ result.push(builtIn);
578
+ }
579
+ }
580
+ return result;
581
+ }
582
+ /** Get a specific agent by name (custom or built-in). */
583
+ getAgent(name) {
584
+ return this.loadAll().find((agent) => agent.name === name);
585
+ }
586
+ };
587
+
254
588
  // src/assembly/create-session.ts
255
589
  function createSession(options) {
256
590
  const provider = options.provider ?? createProvider(options.config);
257
591
  const defaultTools = createDefaultTools();
258
592
  const tools = [...defaultTools, ...options.additionalTools ?? []];
593
+ const agentLoader = new AgentDefinitionLoader(process.cwd());
594
+ const hookTypeExecutors = [];
595
+ if (options.providerFactory) {
596
+ hookTypeExecutors.push(
597
+ new PromptExecutor({
598
+ providerFactory: options.providerFactory,
599
+ defaultModel: options.config.provider.model
600
+ })
601
+ );
602
+ }
603
+ if (options.sessionFactory) {
604
+ hookTypeExecutors.push(
605
+ new AgentExecutor({
606
+ sessionFactory: options.sessionFactory
607
+ })
608
+ );
609
+ }
610
+ if (options.additionalHookExecutors) {
611
+ hookTypeExecutors.push(...options.additionalHookExecutors);
612
+ }
613
+ const agentToolDeps = {
614
+ config: options.config,
615
+ context: options.context,
616
+ tools,
617
+ terminal: options.terminal,
618
+ permissionMode: options.permissionMode,
619
+ permissionHandler: options.permissionHandler,
620
+ hooks: options.config.hooks,
621
+ hookTypeExecutors: hookTypeExecutors.length > 0 ? hookTypeExecutors : void 0,
622
+ onTextDelta: options.onTextDelta,
623
+ onToolExecution: options.onToolExecution,
624
+ customAgentRegistry: (name) => agentLoader.getAgent(name)
625
+ };
626
+ tools.push(createAgentTool(agentToolDeps));
259
627
  const buildPrompt = options.systemPromptBuilder ?? buildSystemPrompt;
260
628
  const systemMessage = buildPrompt({
261
629
  agentsMd: options.context.agentsMd,
@@ -278,26 +646,7 @@ function createSession(options) {
278
646
  allow: [...defaultAllow, ...options.config.permissions.allow ?? []],
279
647
  deny: options.config.permissions.deny ?? []
280
648
  };
281
- const hookTypeExecutors = [];
282
- if (options.providerFactory) {
283
- hookTypeExecutors.push(
284
- new PromptExecutor({
285
- providerFactory: options.providerFactory,
286
- defaultModel: options.config.provider.model
287
- })
288
- );
289
- }
290
- if (options.sessionFactory) {
291
- hookTypeExecutors.push(
292
- new AgentExecutor({
293
- sessionFactory: options.sessionFactory
294
- })
295
- );
296
- }
297
- if (options.additionalHookExecutors) {
298
- hookTypeExecutors.push(...options.additionalHookExecutors);
299
- }
300
- return new Session({
649
+ const session = new Session2({
301
650
  tools,
302
651
  provider,
303
652
  systemMessage,
@@ -318,89 +667,104 @@ function createSession(options) {
318
667
  sessionLogger: options.sessionLogger,
319
668
  hookTypeExecutors: hookTypeExecutors.length > 0 ? hookTypeExecutors : void 0
320
669
  });
670
+ storeAgentToolDeps(session, agentToolDeps);
671
+ return session;
672
+ }
673
+
674
+ // src/assembly/subagent-logger.ts
675
+ import { mkdirSync } from "fs";
676
+ import { join as join2 } from "path";
677
+ import { FileSessionLogger } from "@robota-sdk/agent-sessions";
678
+ function createSubagentLogger(parentSessionId, _agentId, baseLogsDir) {
679
+ const subagentDir = join2(baseLogsDir, parentSessionId, "subagents");
680
+ mkdirSync(subagentDir, { recursive: true });
681
+ return new FileSessionLogger(subagentDir);
682
+ }
683
+ function resolveSubagentLogDir(parentSessionId, baseLogsDir) {
684
+ return join2(baseLogsDir, parentSessionId, "subagents");
321
685
  }
322
686
 
323
687
  // src/index.ts
324
- import { Session as Session2 } from "@robota-sdk/agent-sessions";
325
- import { FileSessionLogger, SilentSessionLogger } from "@robota-sdk/agent-sessions";
688
+ import { Session as Session3 } from "@robota-sdk/agent-sessions";
689
+ import { FileSessionLogger as FileSessionLogger2, SilentSessionLogger } from "@robota-sdk/agent-sessions";
326
690
  import { SessionStore } from "@robota-sdk/agent-sessions";
327
691
 
328
692
  // src/config/config-loader.ts
329
- import { readFileSync, existsSync } from "fs";
330
- import { join } from "path";
693
+ import { readFileSync as readFileSync2, existsSync as existsSync2 } from "fs";
694
+ import { join as join3 } from "path";
331
695
 
332
696
  // src/config/config-types.ts
333
- import { z } from "zod";
334
- var ProviderSchema = z.object({
335
- name: z.string().optional(),
336
- model: z.string().optional(),
337
- apiKey: z.string().optional()
697
+ import { z as z2 } from "zod";
698
+ var ProviderSchema = z2.object({
699
+ name: z2.string().optional(),
700
+ model: z2.string().optional(),
701
+ apiKey: z2.string().optional()
338
702
  });
339
- var PermissionsSchema = z.object({
703
+ var PermissionsSchema = z2.object({
340
704
  /** Patterns that are always approved without prompting */
341
- allow: z.array(z.string()).optional(),
705
+ allow: z2.array(z2.string()).optional(),
342
706
  /** Patterns that are always denied */
343
- deny: z.array(z.string()).optional()
707
+ deny: z2.array(z2.string()).optional()
344
708
  });
345
- var EnvSchema = z.record(z.string()).optional();
346
- var CommandHookDefinitionSchema = z.object({
347
- type: z.literal("command"),
348
- command: z.string(),
349
- timeout: z.number().optional()
709
+ var EnvSchema = z2.record(z2.string()).optional();
710
+ var CommandHookDefinitionSchema = z2.object({
711
+ type: z2.literal("command"),
712
+ command: z2.string(),
713
+ timeout: z2.number().optional()
350
714
  });
351
- var HttpHookDefinitionSchema = z.object({
352
- type: z.literal("http"),
353
- url: z.string(),
354
- headers: z.record(z.string()).optional(),
355
- timeout: z.number().optional()
715
+ var HttpHookDefinitionSchema = z2.object({
716
+ type: z2.literal("http"),
717
+ url: z2.string(),
718
+ headers: z2.record(z2.string()).optional(),
719
+ timeout: z2.number().optional()
356
720
  });
357
- var PromptHookDefinitionSchema = z.object({
358
- type: z.literal("prompt"),
359
- prompt: z.string(),
360
- model: z.string().optional()
721
+ var PromptHookDefinitionSchema = z2.object({
722
+ type: z2.literal("prompt"),
723
+ prompt: z2.string(),
724
+ model: z2.string().optional()
361
725
  });
362
- var AgentHookDefinitionSchema = z.object({
363
- type: z.literal("agent"),
364
- agent: z.string(),
365
- maxTurns: z.number().optional(),
366
- timeout: z.number().optional()
726
+ var AgentHookDefinitionSchema = z2.object({
727
+ type: z2.literal("agent"),
728
+ agent: z2.string(),
729
+ maxTurns: z2.number().optional(),
730
+ timeout: z2.number().optional()
367
731
  });
368
- var HookDefinitionSchema = z.discriminatedUnion("type", [
732
+ var HookDefinitionSchema = z2.discriminatedUnion("type", [
369
733
  CommandHookDefinitionSchema,
370
734
  HttpHookDefinitionSchema,
371
735
  PromptHookDefinitionSchema,
372
736
  AgentHookDefinitionSchema
373
737
  ]);
374
- var HookGroupSchema = z.object({
375
- matcher: z.string(),
376
- hooks: z.array(HookDefinitionSchema)
738
+ var HookGroupSchema = z2.object({
739
+ matcher: z2.string(),
740
+ hooks: z2.array(HookDefinitionSchema)
377
741
  });
378
- var HooksSchema = z.object({
379
- PreToolUse: z.array(HookGroupSchema).optional(),
380
- PostToolUse: z.array(HookGroupSchema).optional(),
381
- SessionStart: z.array(HookGroupSchema).optional(),
382
- Stop: z.array(HookGroupSchema).optional(),
383
- PreCompact: z.array(HookGroupSchema).optional(),
384
- PostCompact: z.array(HookGroupSchema).optional(),
385
- UserPromptSubmit: z.array(HookGroupSchema).optional(),
386
- Notification: z.array(HookGroupSchema).optional()
742
+ var HooksSchema = z2.object({
743
+ PreToolUse: z2.array(HookGroupSchema).optional(),
744
+ PostToolUse: z2.array(HookGroupSchema).optional(),
745
+ SessionStart: z2.array(HookGroupSchema).optional(),
746
+ Stop: z2.array(HookGroupSchema).optional(),
747
+ PreCompact: z2.array(HookGroupSchema).optional(),
748
+ PostCompact: z2.array(HookGroupSchema).optional(),
749
+ UserPromptSubmit: z2.array(HookGroupSchema).optional(),
750
+ Notification: z2.array(HookGroupSchema).optional()
387
751
  }).optional();
388
- var EnabledPluginsSchema = z.record(z.boolean()).optional();
389
- var MarketplaceSourceSchema = z.object({
390
- source: z.object({
391
- type: z.enum(["github", "git", "local", "url"]),
392
- repo: z.string().optional(),
393
- url: z.string().optional(),
394
- path: z.string().optional(),
395
- ref: z.string().optional()
752
+ var EnabledPluginsSchema = z2.record(z2.boolean()).optional();
753
+ var MarketplaceSourceSchema = z2.object({
754
+ source: z2.object({
755
+ type: z2.enum(["github", "git", "local", "url"]),
756
+ repo: z2.string().optional(),
757
+ url: z2.string().optional(),
758
+ path: z2.string().optional(),
759
+ ref: z2.string().optional()
396
760
  })
397
761
  });
398
- var ExtraKnownMarketplacesSchema = z.record(MarketplaceSourceSchema).optional();
399
- var SettingsSchema = z.object({
762
+ var ExtraKnownMarketplacesSchema = z2.record(MarketplaceSourceSchema).optional();
763
+ var SettingsSchema = z2.object({
400
764
  /** Trust level used when no --permission-mode flag is given */
401
- defaultTrustLevel: z.enum(["safe", "moderate", "full"]).optional(),
765
+ defaultTrustLevel: z2.enum(["safe", "moderate", "full"]).optional(),
402
766
  /** Response language (e.g., "ko", "en", "ja"). Injected into system prompt. */
403
- language: z.string().optional(),
767
+ language: z2.string().optional(),
404
768
  provider: ProviderSchema.optional(),
405
769
  permissions: PermissionsSchema.optional(),
406
770
  env: EnvSchema,
@@ -429,10 +793,10 @@ var DEFAULTS = {
429
793
  env: {}
430
794
  };
431
795
  function readJsonFile(filePath) {
432
- if (!existsSync(filePath)) {
796
+ if (!existsSync2(filePath)) {
433
797
  return void 0;
434
798
  }
435
- const raw = readFileSync(filePath, "utf-8").trim();
799
+ const raw = readFileSync2(filePath, "utf-8").trim();
436
800
  if (raw.length === 0) {
437
801
  return void 0;
438
802
  }
@@ -503,15 +867,15 @@ function toResolvedConfig(merged) {
503
867
  function getSettingsPaths(cwd) {
504
868
  const home = getHomeDir();
505
869
  return [
506
- join(home, ".robota", "settings.json"),
870
+ join3(home, ".robota", "settings.json"),
507
871
  // 1. user (lowest)
508
- join(cwd, ".robota", "settings.json"),
872
+ join3(cwd, ".robota", "settings.json"),
509
873
  // 2. project
510
- join(cwd, ".robota", "settings.local.json"),
874
+ join3(cwd, ".robota", "settings.local.json"),
511
875
  // 3. project-local
512
- join(cwd, ".claude", "settings.json"),
876
+ join3(cwd, ".claude", "settings.json"),
513
877
  // 4. project, Claude Code compat
514
- join(cwd, ".claude", "settings.local.json")
878
+ join3(cwd, ".claude", "settings.local.json")
515
879
  // 5. project-local (highest)
516
880
  ];
517
881
  }
@@ -536,8 +900,8 @@ async function loadConfig(cwd) {
536
900
  }
537
901
 
538
902
  // src/context/context-loader.ts
539
- import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
540
- import { join as join2, dirname, resolve } from "path";
903
+ import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
904
+ import { join as join4, dirname, resolve } from "path";
541
905
  var AGENTS_FILENAME = "AGENTS.md";
542
906
  var CLAUDE_FILENAME = "CLAUDE.md";
543
907
  function collectFilesWalkingUp(startDir, filename) {
@@ -545,8 +909,8 @@ function collectFilesWalkingUp(startDir, filename) {
545
909
  let current = resolve(startDir);
546
910
  let atRoot = false;
547
911
  while (!atRoot) {
548
- const candidate = join2(current, filename);
549
- if (existsSync2(candidate)) {
912
+ const candidate = join4(current, filename);
913
+ if (existsSync3(candidate)) {
550
914
  found.push(candidate);
551
915
  }
552
916
  const parent = dirname(current);
@@ -584,47 +948,47 @@ function extractCompactInstructions(content) {
584
948
  async function loadContext(cwd) {
585
949
  const agentsPaths = collectFilesWalkingUp(cwd, AGENTS_FILENAME);
586
950
  const claudePaths = collectFilesWalkingUp(cwd, CLAUDE_FILENAME);
587
- const agentsMd = agentsPaths.map((p) => readFileSync2(p, "utf-8")).join("\n\n");
588
- const claudeMd = claudePaths.map((p) => readFileSync2(p, "utf-8")).join("\n\n");
951
+ const agentsMd = agentsPaths.map((p) => readFileSync3(p, "utf-8")).join("\n\n");
952
+ const claudeMd = claudePaths.map((p) => readFileSync3(p, "utf-8")).join("\n\n");
589
953
  const compactInstructions = extractCompactInstructions(claudeMd);
590
954
  return { agentsMd, claudeMd, compactInstructions };
591
955
  }
592
956
 
593
957
  // src/context/project-detector.ts
594
- import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
595
- import { join as join3 } from "path";
958
+ import { existsSync as existsSync4, readFileSync as readFileSync4 } from "fs";
959
+ import { join as join5 } from "path";
596
960
  function tryReadJson(filePath) {
597
- if (!existsSync3(filePath)) return void 0;
961
+ if (!existsSync4(filePath)) return void 0;
598
962
  try {
599
- return JSON.parse(readFileSync3(filePath, "utf-8"));
963
+ return JSON.parse(readFileSync4(filePath, "utf-8"));
600
964
  } catch {
601
965
  return void 0;
602
966
  }
603
967
  }
604
968
  function detectPackageManager(cwd) {
605
- if (existsSync3(join3(cwd, "pnpm-workspace.yaml")) || existsSync3(join3(cwd, "pnpm-lock.yaml"))) {
969
+ if (existsSync4(join5(cwd, "pnpm-workspace.yaml")) || existsSync4(join5(cwd, "pnpm-lock.yaml"))) {
606
970
  return "pnpm";
607
971
  }
608
- if (existsSync3(join3(cwd, "yarn.lock"))) {
972
+ if (existsSync4(join5(cwd, "yarn.lock"))) {
609
973
  return "yarn";
610
974
  }
611
- if (existsSync3(join3(cwd, "bun.lockb"))) {
975
+ if (existsSync4(join5(cwd, "bun.lockb"))) {
612
976
  return "bun";
613
977
  }
614
- if (existsSync3(join3(cwd, "package-lock.json"))) {
978
+ if (existsSync4(join5(cwd, "package-lock.json"))) {
615
979
  return "npm";
616
980
  }
617
981
  return void 0;
618
982
  }
619
983
  async function detectProject(cwd) {
620
- const pkgJsonPath = join3(cwd, "package.json");
621
- const tsconfigPath = join3(cwd, "tsconfig.json");
622
- const pyprojectPath = join3(cwd, "pyproject.toml");
623
- const cargoPath = join3(cwd, "Cargo.toml");
624
- const goModPath = join3(cwd, "go.mod");
625
- if (existsSync3(pkgJsonPath)) {
984
+ const pkgJsonPath = join5(cwd, "package.json");
985
+ const tsconfigPath = join5(cwd, "tsconfig.json");
986
+ const pyprojectPath = join5(cwd, "pyproject.toml");
987
+ const cargoPath = join5(cwd, "Cargo.toml");
988
+ const goModPath = join5(cwd, "go.mod");
989
+ if (existsSync4(pkgJsonPath)) {
626
990
  const pkgJson = tryReadJson(pkgJsonPath);
627
- const language = existsSync3(tsconfigPath) ? "typescript" : "javascript";
991
+ const language = existsSync4(tsconfigPath) ? "typescript" : "javascript";
628
992
  const packageManager = detectPackageManager(cwd);
629
993
  return {
630
994
  type: "node",
@@ -633,19 +997,19 @@ async function detectProject(cwd) {
633
997
  language
634
998
  };
635
999
  }
636
- if (existsSync3(pyprojectPath) || existsSync3(join3(cwd, "setup.py"))) {
1000
+ if (existsSync4(pyprojectPath) || existsSync4(join5(cwd, "setup.py"))) {
637
1001
  return {
638
1002
  type: "python",
639
1003
  language: "python"
640
1004
  };
641
1005
  }
642
- if (existsSync3(cargoPath)) {
1006
+ if (existsSync4(cargoPath)) {
643
1007
  return {
644
1008
  type: "rust",
645
1009
  language: "rust"
646
1010
  };
647
1011
  }
648
- if (existsSync3(goModPath)) {
1012
+ if (existsSync4(goModPath)) {
649
1013
  return {
650
1014
  type: "go",
651
1015
  language: "go"
@@ -722,27 +1086,27 @@ import { evaluatePermission } from "@robota-sdk/agent-core";
722
1086
  import { runHooks } from "@robota-sdk/agent-core";
723
1087
 
724
1088
  // src/paths.ts
725
- import { join as join4 } from "path";
726
- import { homedir } from "os";
1089
+ import { join as join6 } from "path";
1090
+ import { homedir as homedir2 } from "os";
727
1091
  function projectPaths(cwd) {
728
- const base = join4(cwd, ".robota");
1092
+ const base = join6(cwd, ".robota");
729
1093
  return {
730
- settings: join4(base, "settings.json"),
731
- settingsLocal: join4(base, "settings.local.json"),
732
- logs: join4(base, "logs"),
733
- sessions: join4(base, "sessions")
1094
+ settings: join6(base, "settings.json"),
1095
+ settingsLocal: join6(base, "settings.local.json"),
1096
+ logs: join6(base, "logs"),
1097
+ sessions: join6(base, "sessions")
734
1098
  };
735
1099
  }
736
1100
  function userPaths() {
737
- const base = join4(homedir(), ".robota");
1101
+ const base = join6(homedir2(), ".robota");
738
1102
  return {
739
- settings: join4(base, "settings.json"),
740
- sessions: join4(base, "sessions")
1103
+ settings: join6(base, "settings.json"),
1104
+ sessions: join6(base, "sessions")
741
1105
  };
742
1106
  }
743
1107
 
744
1108
  // src/plugins/plugin-settings-store.ts
745
- import { existsSync as existsSync4, readFileSync as readFileSync4, writeFileSync, mkdirSync } from "fs";
1109
+ import { existsSync as existsSync5, readFileSync as readFileSync5, writeFileSync, mkdirSync as mkdirSync2 } from "fs";
746
1110
  import { dirname as dirname2 } from "path";
747
1111
  var PluginSettingsStore = class {
748
1112
  settingsPath;
@@ -751,11 +1115,11 @@ var PluginSettingsStore = class {
751
1115
  }
752
1116
  /** Read the full settings file from disk. */
753
1117
  readAll() {
754
- if (!existsSync4(this.settingsPath)) {
1118
+ if (!existsSync5(this.settingsPath)) {
755
1119
  return {};
756
1120
  }
757
1121
  try {
758
- const raw = readFileSync4(this.settingsPath, "utf-8");
1122
+ const raw = readFileSync5(this.settingsPath, "utf-8");
759
1123
  const data = JSON.parse(raw);
760
1124
  if (typeof data === "object" && data !== null) {
761
1125
  return data;
@@ -768,8 +1132,8 @@ var PluginSettingsStore = class {
768
1132
  /** Write the full settings file to disk. */
769
1133
  writeAll(settings) {
770
1134
  const dir = dirname2(this.settingsPath);
771
- if (!existsSync4(dir)) {
772
- mkdirSync(dir, { recursive: true });
1135
+ if (!existsSync5(dir)) {
1136
+ mkdirSync2(dir, { recursive: true });
773
1137
  }
774
1138
  writeFileSync(this.settingsPath, JSON.stringify(settings, null, 2), "utf-8");
775
1139
  }
@@ -843,8 +1207,8 @@ var PluginSettingsStore = class {
843
1207
  };
844
1208
 
845
1209
  // src/plugins/bundle-plugin-loader.ts
846
- import { existsSync as existsSync5, readdirSync, readFileSync as readFileSync5 } from "fs";
847
- import { join as join5 } from "path";
1210
+ import { existsSync as existsSync6, readdirSync as readdirSync2, readFileSync as readFileSync6 } from "fs";
1211
+ import { join as join7 } from "path";
848
1212
  function parseSkillFrontmatter(raw) {
849
1213
  const trimmed = raw.trimStart();
850
1214
  if (!trimmed.startsWith("---")) {
@@ -893,9 +1257,9 @@ function validateManifest(data) {
893
1257
  };
894
1258
  }
895
1259
  function getSortedSubdirs(dirPath) {
896
- if (!existsSync5(dirPath)) return [];
1260
+ if (!existsSync6(dirPath)) return [];
897
1261
  try {
898
- const entries = readdirSync(dirPath, { withFileTypes: true });
1262
+ const entries = readdirSync2(dirPath, { withFileTypes: true });
899
1263
  return entries.filter((e) => e.isDirectory()).map((e) => e.name).sort();
900
1264
  } catch {
901
1265
  return [];
@@ -923,23 +1287,23 @@ var BundlePluginLoader = class {
923
1287
  * For each marketplace/plugin pair, the latest version (lexicographically last) is loaded.
924
1288
  */
925
1289
  discoverAndLoad() {
926
- const cacheDir = join5(this.pluginsDir, "cache");
927
- if (!existsSync5(cacheDir)) {
1290
+ const cacheDir = join7(this.pluginsDir, "cache");
1291
+ if (!existsSync6(cacheDir)) {
928
1292
  return [];
929
1293
  }
930
1294
  const results = [];
931
1295
  const marketplaces = getSortedSubdirs(cacheDir);
932
1296
  for (const marketplace of marketplaces) {
933
- const marketplaceDir = join5(cacheDir, marketplace);
1297
+ const marketplaceDir = join7(cacheDir, marketplace);
934
1298
  const plugins = getSortedSubdirs(marketplaceDir);
935
1299
  for (const pluginName of plugins) {
936
- const pluginDir = join5(marketplaceDir, pluginName);
1300
+ const pluginDir = join7(marketplaceDir, pluginName);
937
1301
  const versions = getSortedSubdirs(pluginDir);
938
1302
  if (versions.length === 0) continue;
939
1303
  const latestVersion = versions[versions.length - 1];
940
- const versionDir = join5(pluginDir, latestVersion);
941
- const manifestPath = join5(versionDir, ".claude-plugin", "plugin.json");
942
- if (!existsSync5(manifestPath)) continue;
1304
+ const versionDir = join7(pluginDir, latestVersion);
1305
+ const manifestPath = join7(versionDir, ".claude-plugin", "plugin.json");
1306
+ if (!existsSync6(manifestPath)) continue;
943
1307
  const manifest = this.readManifest(manifestPath);
944
1308
  if (!manifest) continue;
945
1309
  const pluginId = `${manifest.name}@${marketplace}`;
@@ -953,7 +1317,7 @@ var BundlePluginLoader = class {
953
1317
  /** Read and validate a plugin.json manifest. Returns null on failure. */
954
1318
  readManifest(path) {
955
1319
  try {
956
- const raw = readFileSync5(path, "utf-8");
1320
+ const raw = readFileSync6(path, "utf-8");
957
1321
  const data = JSON.parse(raw);
958
1322
  return validateManifest(data);
959
1323
  } catch {
@@ -988,15 +1352,15 @@ var BundlePluginLoader = class {
988
1352
  }
989
1353
  /** Load skills from the plugin's skills/ directory. */
990
1354
  loadSkills(pluginDir, pluginName) {
991
- const skillsDir = join5(pluginDir, "skills");
992
- if (!existsSync5(skillsDir)) return [];
993
- const entries = readdirSync(skillsDir, { withFileTypes: true });
1355
+ const skillsDir = join7(pluginDir, "skills");
1356
+ if (!existsSync6(skillsDir)) return [];
1357
+ const entries = readdirSync2(skillsDir, { withFileTypes: true });
994
1358
  const skills = [];
995
1359
  for (const entry of entries) {
996
1360
  if (!entry.isDirectory()) continue;
997
- const skillFile = join5(skillsDir, entry.name, "SKILL.md");
998
- if (!existsSync5(skillFile)) continue;
999
- const raw = readFileSync5(skillFile, "utf-8");
1361
+ const skillFile = join7(skillsDir, entry.name, "SKILL.md");
1362
+ if (!existsSync6(skillFile)) continue;
1363
+ const raw = readFileSync6(skillFile, "utf-8");
1000
1364
  const { metadata, content } = parseSkillFrontmatter(raw);
1001
1365
  const description = typeof metadata.description === "string" ? metadata.description : "";
1002
1366
  const skill = {
@@ -1011,13 +1375,13 @@ var BundlePluginLoader = class {
1011
1375
  }
1012
1376
  /** Load commands from the plugin's commands/ directory (flat .md files). */
1013
1377
  loadCommands(pluginDir, pluginName) {
1014
- const commandsDir = join5(pluginDir, "commands");
1015
- if (!existsSync5(commandsDir)) return [];
1016
- const entries = readdirSync(commandsDir, { withFileTypes: true });
1378
+ const commandsDir = join7(pluginDir, "commands");
1379
+ if (!existsSync6(commandsDir)) return [];
1380
+ const entries = readdirSync2(commandsDir, { withFileTypes: true });
1017
1381
  const commands = [];
1018
1382
  for (const entry of entries) {
1019
1383
  if (!entry.isFile() || !entry.name.endsWith(".md")) continue;
1020
- const raw = readFileSync5(join5(commandsDir, entry.name), "utf-8");
1384
+ const raw = readFileSync6(join7(commandsDir, entry.name), "utf-8");
1021
1385
  const { metadata, content } = parseSkillFrontmatter(raw);
1022
1386
  const name = typeof metadata.name === "string" ? metadata.name : entry.name.replace(/\.md$/, "");
1023
1387
  const description = typeof metadata.description === "string" ? metadata.description : "";
@@ -1032,10 +1396,10 @@ var BundlePluginLoader = class {
1032
1396
  }
1033
1397
  /** Load hooks from hooks/hooks.json if present. */
1034
1398
  loadHooks(pluginDir) {
1035
- const hooksPath = join5(pluginDir, "hooks", "hooks.json");
1036
- if (!existsSync5(hooksPath)) return {};
1399
+ const hooksPath = join7(pluginDir, "hooks", "hooks.json");
1400
+ if (!existsSync6(hooksPath)) return {};
1037
1401
  try {
1038
- const raw = readFileSync5(hooksPath, "utf-8");
1402
+ const raw = readFileSync6(hooksPath, "utf-8");
1039
1403
  const data = JSON.parse(raw);
1040
1404
  if (typeof data === "object" && data !== null) {
1041
1405
  return data;
@@ -1047,12 +1411,12 @@ var BundlePluginLoader = class {
1047
1411
  }
1048
1412
  /** Load MCP server configuration if present. Checks `.mcp.json` at plugin root first. */
1049
1413
  loadMcpConfig(pluginDir) {
1050
- const primaryPath = join5(pluginDir, ".mcp.json");
1051
- const fallbackPath = join5(pluginDir, ".claude-plugin", "mcp.json");
1052
- const mcpPath = existsSync5(primaryPath) ? primaryPath : fallbackPath;
1053
- if (!existsSync5(mcpPath)) return void 0;
1414
+ const primaryPath = join7(pluginDir, ".mcp.json");
1415
+ const fallbackPath = join7(pluginDir, ".claude-plugin", "mcp.json");
1416
+ const mcpPath = existsSync6(primaryPath) ? primaryPath : fallbackPath;
1417
+ if (!existsSync6(mcpPath)) return void 0;
1054
1418
  try {
1055
- const raw = readFileSync5(mcpPath, "utf-8");
1419
+ const raw = readFileSync6(mcpPath, "utf-8");
1056
1420
  return JSON.parse(raw);
1057
1421
  } catch {
1058
1422
  return void 0;
@@ -1060,10 +1424,10 @@ var BundlePluginLoader = class {
1060
1424
  }
1061
1425
  /** Load agent definitions from agents/ directory if present. */
1062
1426
  loadAgents(pluginDir) {
1063
- const agentsDir = join5(pluginDir, "agents");
1064
- if (!existsSync5(agentsDir)) return [];
1427
+ const agentsDir = join7(pluginDir, "agents");
1428
+ if (!existsSync6(agentsDir)) return [];
1065
1429
  try {
1066
- const entries = readdirSync(agentsDir, { withFileTypes: true });
1430
+ const entries = readdirSync2(agentsDir, { withFileTypes: true });
1067
1431
  return entries.filter((e) => e.isDirectory() || e.name.endsWith(".md")).map((e) => e.name.replace(/\.md$/, ""));
1068
1432
  } catch {
1069
1433
  return [];
@@ -1073,8 +1437,8 @@ var BundlePluginLoader = class {
1073
1437
 
1074
1438
  // src/plugins/bundle-plugin-installer.ts
1075
1439
  import { execSync } from "child_process";
1076
- import { cpSync, existsSync as existsSync6, mkdirSync as mkdirSync2, readFileSync as readFileSync6, rmSync, writeFileSync as writeFileSync2 } from "fs";
1077
- import { join as join6, dirname as dirname3 } from "path";
1440
+ import { cpSync, existsSync as existsSync7, mkdirSync as mkdirSync3, readFileSync as readFileSync7, rmSync, writeFileSync as writeFileSync2 } from "fs";
1441
+ import { join as join8, dirname as dirname3 } from "path";
1078
1442
  var GIT_CLONE_TIMEOUT_MS = 6e4;
1079
1443
  var BundlePluginInstaller = class {
1080
1444
  pluginsDir;
@@ -1085,8 +1449,8 @@ var BundlePluginInstaller = class {
1085
1449
  exec;
1086
1450
  constructor(options) {
1087
1451
  this.pluginsDir = options.pluginsDir;
1088
- this.cacheDir = join6(this.pluginsDir, "cache");
1089
- this.registryPath = join6(this.pluginsDir, "installed_plugins.json");
1452
+ this.cacheDir = join8(this.pluginsDir, "cache");
1453
+ this.registryPath = join8(this.pluginsDir, "installed_plugins.json");
1090
1454
  this.settingsStore = options.settingsStore;
1091
1455
  this.marketplaceClient = options.marketplaceClient;
1092
1456
  this.exec = options.exec ?? this.defaultExec;
@@ -1106,8 +1470,8 @@ var BundlePluginInstaller = class {
1106
1470
  throw new Error(`Plugin "${pluginName}" not found in marketplace "${marketplaceName}"`);
1107
1471
  }
1108
1472
  const version = this.resolveVersion(entry, marketplaceName);
1109
- const targetDir = join6(this.cacheDir, marketplaceName, pluginName, version);
1110
- if (existsSync6(targetDir)) {
1473
+ const targetDir = join8(this.cacheDir, marketplaceName, pluginName, version);
1474
+ if (existsSync7(targetDir)) {
1111
1475
  throw new Error(
1112
1476
  `Plugin "${pluginName}" version "${version}" is already installed from "${marketplaceName}"`
1113
1477
  );
@@ -1134,7 +1498,7 @@ var BundlePluginInstaller = class {
1134
1498
  if (!record) {
1135
1499
  throw new Error(`Plugin "${pluginId}" is not installed`);
1136
1500
  }
1137
- if (existsSync6(record.installPath)) {
1501
+ if (existsSync7(record.installPath)) {
1138
1502
  rmSync(record.installPath, { recursive: true, force: true });
1139
1503
  }
1140
1504
  delete registry[pluginId];
@@ -1181,13 +1545,13 @@ var BundlePluginInstaller = class {
1181
1545
  }
1182
1546
  /** Resolve the source and install the plugin. */
1183
1547
  resolveAndInstall(rawSource, marketplaceName, pluginName, targetDir) {
1184
- mkdirSync2(targetDir, { recursive: true });
1548
+ mkdirSync3(targetDir, { recursive: true });
1185
1549
  const source = this.normalizeSource(rawSource);
1186
1550
  try {
1187
1551
  if (typeof source === "string") {
1188
1552
  const marketplaceDir = this.marketplaceClient.getMarketplaceDir(marketplaceName);
1189
- const sourcePath = join6(marketplaceDir, source);
1190
- if (!existsSync6(sourcePath)) {
1553
+ const sourcePath = join8(marketplaceDir, source);
1554
+ if (!existsSync7(sourcePath)) {
1191
1555
  throw new Error(
1192
1556
  `Plugin source path "${source}" not found in marketplace "${marketplaceName}"`
1193
1557
  );
@@ -1204,7 +1568,7 @@ var BundlePluginInstaller = class {
1204
1568
  throw new Error(`Unknown source type: ${JSON.stringify(source)}`);
1205
1569
  }
1206
1570
  } catch (err) {
1207
- if (existsSync6(targetDir)) {
1571
+ if (existsSync7(targetDir)) {
1208
1572
  rmSync(targetDir, { recursive: true, force: true });
1209
1573
  }
1210
1574
  throw err;
@@ -1223,11 +1587,11 @@ var BundlePluginInstaller = class {
1223
1587
  }
1224
1588
  /** Read the installed_plugins.json registry. */
1225
1589
  readRegistry() {
1226
- if (!existsSync6(this.registryPath)) {
1590
+ if (!existsSync7(this.registryPath)) {
1227
1591
  return {};
1228
1592
  }
1229
1593
  try {
1230
- const raw = readFileSync6(this.registryPath, "utf-8");
1594
+ const raw = readFileSync7(this.registryPath, "utf-8");
1231
1595
  const data = JSON.parse(raw);
1232
1596
  if (typeof data === "object" && data !== null) {
1233
1597
  return data;
@@ -1240,8 +1604,8 @@ var BundlePluginInstaller = class {
1240
1604
  /** Write the installed_plugins.json registry. */
1241
1605
  writeRegistry(registry) {
1242
1606
  const dir = dirname3(this.registryPath);
1243
- if (!existsSync6(dir)) {
1244
- mkdirSync2(dir, { recursive: true });
1607
+ if (!existsSync7(dir)) {
1608
+ mkdirSync3(dir, { recursive: true });
1245
1609
  }
1246
1610
  writeFileSync2(this.registryPath, JSON.stringify(registry, null, 2), "utf-8");
1247
1611
  }
@@ -1255,14 +1619,14 @@ var BundlePluginInstaller = class {
1255
1619
  import { execSync as execSync2 } from "child_process";
1256
1620
  import {
1257
1621
  cpSync as cpSync2,
1258
- existsSync as existsSync7,
1259
- mkdirSync as mkdirSync3,
1260
- readFileSync as readFileSync7,
1622
+ existsSync as existsSync8,
1623
+ mkdirSync as mkdirSync4,
1624
+ readFileSync as readFileSync8,
1261
1625
  renameSync,
1262
1626
  rmSync as rmSync2,
1263
1627
  writeFileSync as writeFileSync3
1264
1628
  } from "fs";
1265
- import { join as join7, dirname as dirname4 } from "path";
1629
+ import { join as join9, dirname as dirname4 } from "path";
1266
1630
  var GIT_TIMEOUT_MS = 6e4;
1267
1631
  var MarketplaceClient = class {
1268
1632
  pluginsDir;
@@ -1272,8 +1636,8 @@ var MarketplaceClient = class {
1272
1636
  constructor(options) {
1273
1637
  this.pluginsDir = options.pluginsDir;
1274
1638
  this.exec = options.exec ?? this.defaultExec;
1275
- this.marketplacesDir = join7(this.pluginsDir, "marketplaces");
1276
- this.registryPath = join7(this.pluginsDir, "known_marketplaces.json");
1639
+ this.marketplacesDir = join9(this.pluginsDir, "marketplaces");
1640
+ this.registryPath = join9(this.pluginsDir, "known_marketplaces.json");
1277
1641
  }
1278
1642
  /**
1279
1643
  * Add a marketplace by cloning its repository.
@@ -1287,10 +1651,10 @@ var MarketplaceClient = class {
1287
1651
  */
1288
1652
  addMarketplace(source) {
1289
1653
  const tempName = "temp-" + Date.now().toString(36);
1290
- const tempDir = join7(this.marketplacesDir, tempName);
1291
- mkdirSync3(this.marketplacesDir, { recursive: true });
1654
+ const tempDir = join9(this.marketplacesDir, tempName);
1655
+ mkdirSync4(this.marketplacesDir, { recursive: true });
1292
1656
  if (source.type === "local") {
1293
- if (!existsSync7(source.path)) {
1657
+ if (!existsSync8(source.path)) {
1294
1658
  throw new Error(`Local marketplace path does not exist: ${source.path}`);
1295
1659
  }
1296
1660
  cpSync2(source.path, tempDir, { recursive: true });
@@ -1304,8 +1668,8 @@ var MarketplaceClient = class {
1304
1668
  throw new Error(`Failed to clone marketplace: ${message}`);
1305
1669
  }
1306
1670
  }
1307
- const manifestPath = join7(tempDir, ".claude-plugin", "marketplace.json");
1308
- if (!existsSync7(manifestPath)) {
1671
+ const manifestPath = join9(tempDir, ".claude-plugin", "marketplace.json");
1672
+ if (!existsSync8(manifestPath)) {
1309
1673
  rmSync2(tempDir, { recursive: true, force: true });
1310
1674
  throw new Error(
1311
1675
  source.type === "local" ? "Local directory does not contain .claude-plugin/marketplace.json" : "Cloned repository does not contain .claude-plugin/marketplace.json"
@@ -1322,7 +1686,7 @@ var MarketplaceClient = class {
1322
1686
  rmSync2(tempDir, { recursive: true, force: true });
1323
1687
  throw new Error(`Marketplace "${name}" already exists`);
1324
1688
  }
1325
- const finalDir = join7(this.marketplacesDir, name);
1689
+ const finalDir = join9(this.marketplacesDir, name);
1326
1690
  renameSync(tempDir, finalDir);
1327
1691
  registry[name] = {
1328
1692
  source,
@@ -1344,7 +1708,7 @@ var MarketplaceClient = class {
1344
1708
  throw new Error(`Marketplace "${name}" not found`);
1345
1709
  }
1346
1710
  this.removeInstalledPluginsForMarketplace(name);
1347
- if (existsSync7(entry.installLocation)) {
1711
+ if (existsSync8(entry.installLocation)) {
1348
1712
  rmSync2(entry.installLocation, { recursive: true, force: true });
1349
1713
  }
1350
1714
  delete registry[name];
@@ -1364,12 +1728,12 @@ var MarketplaceClient = class {
1364
1728
  if (!entry) {
1365
1729
  throw new Error(`Marketplace "${name}" not found`);
1366
1730
  }
1367
- if (!existsSync7(entry.installLocation)) {
1731
+ if (!existsSync8(entry.installLocation)) {
1368
1732
  throw new Error(`Marketplace directory for "${name}" does not exist`);
1369
1733
  }
1370
1734
  if (entry.source.type === "local") {
1371
1735
  const localSource = entry.source;
1372
- if (!existsSync7(localSource.path)) {
1736
+ if (!existsSync8(localSource.path)) {
1373
1737
  throw new Error(`Local marketplace path does not exist: ${localSource.path}`);
1374
1738
  }
1375
1739
  rmSync2(entry.installLocation, { recursive: true, force: true });
@@ -1404,8 +1768,8 @@ var MarketplaceClient = class {
1404
1768
  if (!entry) {
1405
1769
  throw new Error(`Marketplace "${marketplaceName}" not found`);
1406
1770
  }
1407
- const manifestPath = join7(entry.installLocation, ".claude-plugin", "marketplace.json");
1408
- if (!existsSync7(manifestPath)) {
1771
+ const manifestPath = join9(entry.installLocation, ".claude-plugin", "marketplace.json");
1772
+ if (!existsSync8(manifestPath)) {
1409
1773
  throw new Error(
1410
1774
  `Marketplace "${marketplaceName}" does not contain .claude-plugin/marketplace.json`
1411
1775
  );
@@ -1472,11 +1836,11 @@ var MarketplaceClient = class {
1472
1836
  * and updates the registry.
1473
1837
  */
1474
1838
  removeInstalledPluginsForMarketplace(marketplaceName) {
1475
- const installedPath = join7(this.pluginsDir, "installed_plugins.json");
1476
- if (!existsSync7(installedPath)) return;
1839
+ const installedPath = join9(this.pluginsDir, "installed_plugins.json");
1840
+ if (!existsSync8(installedPath)) return;
1477
1841
  let registry;
1478
1842
  try {
1479
- const raw = readFileSync7(installedPath, "utf-8");
1843
+ const raw = readFileSync8(installedPath, "utf-8");
1480
1844
  const data = JSON.parse(raw);
1481
1845
  if (typeof data !== "object" || data === null) return;
1482
1846
  registry = data;
@@ -1486,7 +1850,7 @@ var MarketplaceClient = class {
1486
1850
  let changed = false;
1487
1851
  for (const [pluginId, record] of Object.entries(registry)) {
1488
1852
  if (record.marketplace === marketplaceName) {
1489
- if (record.installPath && existsSync7(record.installPath)) {
1853
+ if (record.installPath && existsSync8(record.installPath)) {
1490
1854
  rmSync2(record.installPath, { recursive: true, force: true });
1491
1855
  }
1492
1856
  delete registry[pluginId];
@@ -1495,15 +1859,15 @@ var MarketplaceClient = class {
1495
1859
  }
1496
1860
  if (changed) {
1497
1861
  const dir = dirname4(installedPath);
1498
- if (!existsSync7(dir)) {
1499
- mkdirSync3(dir, { recursive: true });
1862
+ if (!existsSync8(dir)) {
1863
+ mkdirSync4(dir, { recursive: true });
1500
1864
  }
1501
1865
  writeFileSync3(installedPath, JSON.stringify(registry, null, 2), "utf-8");
1502
1866
  }
1503
1867
  }
1504
1868
  /** Read and parse a marketplace.json from a file path. */
1505
1869
  readManifestFromPath(path) {
1506
- const raw = readFileSync7(path, "utf-8");
1870
+ const raw = readFileSync8(path, "utf-8");
1507
1871
  const data = JSON.parse(raw);
1508
1872
  if (typeof data !== "object" || data === null) {
1509
1873
  throw new Error("Invalid marketplace manifest: not an object");
@@ -1516,11 +1880,11 @@ var MarketplaceClient = class {
1516
1880
  }
1517
1881
  /** Read the known_marketplaces.json registry. */
1518
1882
  readRegistry() {
1519
- if (!existsSync7(this.registryPath)) {
1883
+ if (!existsSync8(this.registryPath)) {
1520
1884
  return {};
1521
1885
  }
1522
1886
  try {
1523
- const raw = readFileSync7(this.registryPath, "utf-8");
1887
+ const raw = readFileSync8(this.registryPath, "utf-8");
1524
1888
  const data = JSON.parse(raw);
1525
1889
  if (typeof data === "object" && data !== null) {
1526
1890
  return data;
@@ -1533,8 +1897,8 @@ var MarketplaceClient = class {
1533
1897
  /** Write the known_marketplaces.json registry. */
1534
1898
  writeRegistry(registry) {
1535
1899
  const dir = dirname4(this.registryPath);
1536
- if (!existsSync7(dir)) {
1537
- mkdirSync3(dir, { recursive: true });
1900
+ if (!existsSync8(dir)) {
1901
+ mkdirSync4(dir, { recursive: true });
1538
1902
  }
1539
1903
  writeFileSync3(this.registryPath, JSON.stringify(registry, null, 2), "utf-8");
1540
1904
  }
@@ -1544,78 +1908,6 @@ var MarketplaceClient = class {
1544
1908
  }
1545
1909
  };
1546
1910
 
1547
- // src/tools/agent-tool.ts
1548
- import { z as z2 } from "zod";
1549
- import { createZodFunctionTool } from "@robota-sdk/agent-tools";
1550
- function asZodSchema(schema) {
1551
- return schema;
1552
- }
1553
- var AgentSchema = z2.object({
1554
- prompt: z2.string().describe("Task description for the sub-agent"),
1555
- description: z2.string().optional().describe("Short description of what the sub-agent will do (3-5 words)")
1556
- });
1557
- var agentToolDeps;
1558
- function setAgentToolDeps(deps) {
1559
- agentToolDeps = deps;
1560
- }
1561
- async function runAgent(args) {
1562
- if (!agentToolDeps) {
1563
- const result = {
1564
- success: false,
1565
- output: "",
1566
- error: "Agent tool not initialized \u2014 missing dependencies"
1567
- };
1568
- return JSON.stringify(result);
1569
- }
1570
- const noopTerminal = {
1571
- write: () => {
1572
- },
1573
- writeLine: () => {
1574
- },
1575
- writeMarkdown: () => {
1576
- },
1577
- writeError: () => {
1578
- },
1579
- prompt: () => Promise.resolve(""),
1580
- select: () => Promise.resolve(0),
1581
- spinner: () => ({ stop: () => {
1582
- }, update: () => {
1583
- } })
1584
- };
1585
- const subSession = createSession({
1586
- config: agentToolDeps.config,
1587
- context: agentToolDeps.context,
1588
- projectInfo: agentToolDeps.projectInfo,
1589
- terminal: noopTerminal,
1590
- // Sub-agents bypass permissions — they inherit parent's trust
1591
- permissionMode: "bypassPermissions"
1592
- });
1593
- try {
1594
- const response = await subSession.run(args.prompt);
1595
- const result = {
1596
- success: true,
1597
- output: response
1598
- };
1599
- return JSON.stringify(result);
1600
- } catch (err) {
1601
- const message = err instanceof Error ? err.message : String(err);
1602
- const result = {
1603
- success: false,
1604
- output: "",
1605
- error: `Sub-agent error: ${message}`
1606
- };
1607
- return JSON.stringify(result);
1608
- }
1609
- }
1610
- var agentTool = createZodFunctionTool(
1611
- "Agent",
1612
- "Spawn a sub-agent with isolated context to handle a task. The sub-agent has its own conversation history and can use all tools.",
1613
- asZodSchema(AgentSchema),
1614
- async (params) => {
1615
- return runAgent(params);
1616
- }
1617
- );
1618
-
1619
1911
  // src/index.ts
1620
1912
  import { bashTool as bashTool2 } from "@robota-sdk/agent-tools";
1621
1913
  import { readTool as readTool2 } from "@robota-sdk/agent-tools";
@@ -1625,26 +1917,33 @@ import { globTool as globTool2 } from "@robota-sdk/agent-tools";
1625
1917
  import { grepTool as grepTool2 } from "@robota-sdk/agent-tools";
1626
1918
  export {
1627
1919
  AgentExecutor,
1920
+ BUILT_IN_AGENTS,
1628
1921
  BundlePluginInstaller,
1629
1922
  BundlePluginLoader,
1630
1923
  DEFAULT_TOOL_DESCRIPTIONS,
1631
- FileSessionLogger,
1924
+ FileSessionLogger2 as FileSessionLogger,
1632
1925
  MarketplaceClient,
1633
1926
  PluginSettingsStore,
1634
1927
  PromptExecutor,
1635
- Session2 as Session,
1928
+ Session3 as Session,
1636
1929
  SessionStore,
1637
1930
  SilentSessionLogger,
1638
1931
  TRUST_TO_MODE,
1639
- agentTool,
1932
+ assembleSubagentPrompt,
1640
1933
  bashTool2 as bashTool,
1641
1934
  buildSystemPrompt,
1935
+ createAgentTool,
1642
1936
  createDefaultTools,
1643
1937
  createProvider,
1644
1938
  createSession,
1939
+ createSubagentLogger,
1940
+ createSubagentSession,
1645
1941
  detectProject,
1646
1942
  editTool2 as editTool,
1647
1943
  evaluatePermission,
1944
+ getBuiltInAgent,
1945
+ getForkWorkerSuffix,
1946
+ getSubagentSuffix,
1648
1947
  globTool2 as globTool,
1649
1948
  grepTool2 as grepTool,
1650
1949
  loadConfig,
@@ -1653,8 +1952,10 @@ export {
1653
1952
  promptForApproval,
1654
1953
  query,
1655
1954
  readTool2 as readTool,
1955
+ resolveSubagentLogDir,
1956
+ retrieveAgentToolDeps,
1656
1957
  runHooks,
1657
- setAgentToolDeps,
1958
+ storeAgentToolDeps,
1658
1959
  userPaths,
1659
1960
  writeTool2 as writeTool
1660
1961
  };