@actant/core 0.1.2

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.
@@ -0,0 +1,1968 @@
1
+ import { AgentBackendType, SkillDefinition, PromptDefinition, McpServerDefinition, PluginDefinition, WorkflowDefinition, PermissionsInput, Logger, ConfigValidationResult, DomainContextConfig, AgentBackendConfig, ModelProviderConfig, AgentTemplate, AgentInstanceMeta, LaunchMode, WorkspacePolicy, WorkDirConflict, InitializerStep, AgentStatus, ResolveResult, DetachResult, PermissionsConfig, SourceConfig, PackageManifest, PresetDefinition, GitHubSourceConfig, LocalSourceConfig, SourceEntry } from '@actant/shared';
2
+ import { z } from 'zod/v4';
3
+ import { EventEmitter } from 'node:events';
4
+ import { Writable, Readable } from 'node:stream';
5
+
6
+ interface VerifyResult {
7
+ valid: boolean;
8
+ errors: string[];
9
+ warnings: string[];
10
+ }
11
+ interface BackendBuilder {
12
+ readonly backendType: AgentBackendType;
13
+ /** Create the directory scaffold for the workspace */
14
+ scaffold(workspaceDir: string): Promise<void>;
15
+ /** Write skill content files */
16
+ materializeSkills(workspaceDir: string, skills: SkillDefinition[]): Promise<void>;
17
+ /** Write prompt content files */
18
+ materializePrompts(workspaceDir: string, prompts: PromptDefinition[]): Promise<void>;
19
+ /** Write MCP server configuration */
20
+ materializeMcpConfig(workspaceDir: string, servers: McpServerDefinition[]): Promise<void>;
21
+ /** Write plugin configuration */
22
+ materializePlugins(workspaceDir: string, plugins: PluginDefinition[]): Promise<void>;
23
+ /** Write workflow content */
24
+ materializeWorkflow(workspaceDir: string, workflow: WorkflowDefinition): Promise<void>;
25
+ /** Inject tool permissions for autonomous operation */
26
+ injectPermissions(workspaceDir: string, servers: McpServerDefinition[], permissions?: PermissionsInput): Promise<void>;
27
+ /** Verify the workspace integrity after build */
28
+ verify(workspaceDir: string): Promise<VerifyResult>;
29
+ }
30
+
31
+ interface NamedComponent {
32
+ name: string;
33
+ }
34
+ /**
35
+ * Generic base class for Domain Context component managers.
36
+ * Provides CRUD, persist, import/export, search/filter, and load-from-directory.
37
+ */
38
+ declare abstract class BaseComponentManager<T extends NamedComponent> {
39
+ protected readonly components: Map<string, T>;
40
+ protected readonly logger: Logger;
41
+ protected abstract readonly componentType: string;
42
+ protected persistDir?: string;
43
+ constructor(loggerName: string);
44
+ setPersistDir(dir: string): void;
45
+ register(component: T): void;
46
+ unregister(name: string): boolean;
47
+ get(name: string): T | undefined;
48
+ has(name: string): boolean;
49
+ /**
50
+ * Resolve a list of component names to their definitions.
51
+ * @throws {ComponentReferenceError} if any name is not found
52
+ */
53
+ resolve(names: string[]): T[];
54
+ list(): T[];
55
+ get size(): number;
56
+ clear(): void;
57
+ add(component: T, persist?: boolean): Promise<void>;
58
+ update(name: string, patch: Partial<T>, persist?: boolean): Promise<T>;
59
+ remove(name: string, persist?: boolean): Promise<boolean>;
60
+ importFromFile(filePath: string): Promise<T>;
61
+ exportToFile(name: string, filePath: string): Promise<void>;
62
+ search(query: string): T[];
63
+ filter(predicate: (c: T) => boolean): T[];
64
+ /**
65
+ * Resolve a content file reference (e.g. "content.md") to its file contents.
66
+ * Returns null if the ref is inline text (contains newline) or file not found.
67
+ */
68
+ protected resolveContentFile(dirPath: string, contentRef: string): Promise<string | null>;
69
+ /**
70
+ * Load component definitions from JSON files and directory-based components (manifest.json).
71
+ * Invalid files/directories are skipped with a warning.
72
+ * @-prefixed directories are scanned recursively as source namespaces.
73
+ */
74
+ loadFromDirectory(dirPath: string): Promise<number>;
75
+ /**
76
+ * Validate raw data against the component schema.
77
+ * Returns a structured ConfigValidationResult with errors and warnings.
78
+ */
79
+ abstract validate(data: unknown, source: string): ConfigValidationResult<T>;
80
+ /**
81
+ * Validate and unwrap — throws ConfigValidationError on failure.
82
+ * Used internally by CRUD and loading operations.
83
+ */
84
+ protected validateOrThrow(data: unknown, source: string): T;
85
+ protected writeComponent(component: T): Promise<void>;
86
+ protected deleteComponent(name: string): Promise<void>;
87
+ }
88
+
89
+ /**
90
+ * Encapsulates the handling of a single DomainContext component type.
91
+ * Each handler knows how to resolve names and materialize definitions.
92
+ */
93
+ interface ComponentTypeHandler<TDef = unknown> {
94
+ /** The key in DomainContextConfig (e.g. "skills", "prompts") */
95
+ readonly contextKey: string;
96
+ /** Resolve name references to full definitions */
97
+ resolve(refs: unknown, manager?: BaseComponentManager<NamedComponent>): TDef[];
98
+ /** Materialize resolved definitions into the workspace */
99
+ materialize(workspaceDir: string, definitions: TDef[], backendType: AgentBackendType, backendBuilder: unknown): Promise<void>;
100
+ }
101
+
102
+ declare class CursorBuilder implements BackendBuilder {
103
+ readonly backendType: AgentBackendType;
104
+ scaffold(workspaceDir: string): Promise<void>;
105
+ materializeSkills(workspaceDir: string, skills: SkillDefinition[]): Promise<void>;
106
+ materializePrompts(workspaceDir: string, prompts: PromptDefinition[]): Promise<void>;
107
+ materializeMcpConfig(workspaceDir: string, servers: McpServerDefinition[]): Promise<void>;
108
+ materializePlugins(workspaceDir: string, plugins: PluginDefinition[]): Promise<void>;
109
+ materializeWorkflow(workspaceDir: string, workflow: WorkflowDefinition): Promise<void>;
110
+ injectPermissions(workspaceDir: string, servers: McpServerDefinition[], permissions?: PermissionsInput): Promise<void>;
111
+ verify(workspaceDir: string): Promise<VerifyResult>;
112
+ }
113
+
114
+ declare class ClaudeCodeBuilder implements BackendBuilder {
115
+ readonly backendType: "claude-code";
116
+ scaffold(workspaceDir: string): Promise<void>;
117
+ materializeSkills(workspaceDir: string, skills: SkillDefinition[]): Promise<void>;
118
+ materializePrompts(workspaceDir: string, prompts: PromptDefinition[]): Promise<void>;
119
+ materializeMcpConfig(workspaceDir: string, servers: McpServerDefinition[]): Promise<void>;
120
+ materializePlugins(workspaceDir: string, plugins: PluginDefinition[]): Promise<void>;
121
+ materializeWorkflow(workspaceDir: string, workflow: WorkflowDefinition): Promise<void>;
122
+ injectPermissions(workspaceDir: string, servers: McpServerDefinition[], permissions?: PermissionsInput): Promise<void>;
123
+ verify(workspaceDir: string): Promise<VerifyResult>;
124
+ }
125
+
126
+ interface CustomBuilderConfig {
127
+ configDir?: string;
128
+ skillsDir?: string;
129
+ }
130
+ declare class CustomBuilder extends CursorBuilder {
131
+ readonly backendType: AgentBackendType;
132
+ }
133
+
134
+ declare class SkillManager extends BaseComponentManager<SkillDefinition> {
135
+ protected readonly componentType = "Skill";
136
+ constructor();
137
+ /** Render all resolved skills into a single AGENTS.md content block. */
138
+ renderSkills(skills: SkillDefinition[]): string;
139
+ validate(data: unknown, _source: string): ConfigValidationResult<SkillDefinition>;
140
+ }
141
+
142
+ declare class PromptManager extends BaseComponentManager<PromptDefinition> {
143
+ protected readonly componentType = "Prompt";
144
+ constructor();
145
+ /**
146
+ * Render a prompt with variable interpolation.
147
+ * Replaces {{variableName}} placeholders with provided values.
148
+ */
149
+ renderPrompt(prompt: PromptDefinition, variables?: Record<string, string>): string;
150
+ /** Render multiple prompts into a single system.md content block. */
151
+ renderPrompts(prompts: PromptDefinition[], variables?: Record<string, string>): string;
152
+ validate(data: unknown, _source: string): ConfigValidationResult<PromptDefinition>;
153
+ }
154
+
155
+ declare class McpConfigManager extends BaseComponentManager<McpServerDefinition> {
156
+ protected readonly componentType = "McpServer";
157
+ constructor();
158
+ /**
159
+ * Render resolved MCP servers into the .cursor/mcp.json format.
160
+ * Returns the JSON object ready to be serialized.
161
+ */
162
+ renderMcpConfig(servers: McpServerDefinition[]): Record<string, unknown>;
163
+ validate(data: unknown, _source: string): ConfigValidationResult<McpServerDefinition>;
164
+ }
165
+
166
+ declare class WorkflowManager extends BaseComponentManager<WorkflowDefinition> {
167
+ protected readonly componentType = "Workflow";
168
+ constructor();
169
+ /** Get the workflow content ready to write to .trellis/workflow.md */
170
+ renderWorkflow(workflow: WorkflowDefinition): string;
171
+ validate(data: unknown, _source: string): ConfigValidationResult<WorkflowDefinition>;
172
+ }
173
+
174
+ declare class PluginManager extends BaseComponentManager<PluginDefinition> {
175
+ protected readonly componentType = "Plugin";
176
+ constructor();
177
+ /**
178
+ * Render plugins into a Claude Code plugins.json format.
179
+ * Only includes enabled plugins with npm type.
180
+ */
181
+ renderPluginsJson(plugins: PluginDefinition[]): string;
182
+ /**
183
+ * Render plugins as a Cursor extensions.json format.
184
+ */
185
+ renderExtensionsJson(plugins: PluginDefinition[]): string;
186
+ validate(data: unknown, _source: string): ConfigValidationResult<PluginDefinition>;
187
+ }
188
+
189
+ interface DomainManagers$1 {
190
+ skills?: SkillManager;
191
+ prompts?: PromptManager;
192
+ mcp?: McpConfigManager;
193
+ workflows?: WorkflowManager;
194
+ plugins?: PluginManager;
195
+ }
196
+ interface WorkspaceBuildResult {
197
+ verify: VerifyResult;
198
+ backendType: AgentBackendType;
199
+ }
200
+ declare class WorkspaceBuilder {
201
+ private readonly managers?;
202
+ private readonly builders;
203
+ private readonly handlers;
204
+ constructor(managers?: DomainManagers$1 | undefined);
205
+ /** Register a custom BackendBuilder (e.g. for "custom" backend type) */
206
+ registerBuilder(builder: BackendBuilder): void;
207
+ /** Register a component type handler for custom component types or extensions */
208
+ registerHandler(handler: ComponentTypeHandler): void;
209
+ private getManager;
210
+ /**
211
+ * Build workspace using the 6-step pipeline:
212
+ * 1. Resolve — select builder + resolve domain context names to definitions
213
+ * 2. Validate — check that required components exist
214
+ * 3. Scaffold — create directory structure
215
+ * 4. Materialize — write component files
216
+ * 5. Inject — set up permissions
217
+ * 6. Verify — check workspace integrity
218
+ */
219
+ build(workspaceDir: string, domainContext: DomainContextConfig, backendType?: AgentBackendType, permissions?: PermissionsInput): Promise<WorkspaceBuildResult>;
220
+ }
221
+
222
+ type TaskPriority = "low" | "normal" | "high" | "critical";
223
+ type TaskStatus = "queued" | "running" | "completed" | "failed" | "cancelled";
224
+ interface AgentTask {
225
+ id: string;
226
+ agentName: string;
227
+ prompt: string;
228
+ priority: TaskPriority;
229
+ source: string;
230
+ createdAt: string;
231
+ metadata?: Record<string, unknown>;
232
+ }
233
+ interface ExecutionRecord {
234
+ taskId: string;
235
+ agentName: string;
236
+ prompt: string;
237
+ source: string;
238
+ status: TaskStatus;
239
+ startedAt: string;
240
+ completedAt?: string;
241
+ durationMs?: number;
242
+ result?: string;
243
+ error?: string;
244
+ }
245
+
246
+ declare class TaskQueue {
247
+ private queues;
248
+ private processing;
249
+ /** Enqueue a task. Sorts by priority. */
250
+ enqueue(task: AgentTask): void;
251
+ /** Dequeue the highest-priority task for an agent. Returns undefined if empty or agent is processing. */
252
+ dequeue(agentName: string): AgentTask | undefined;
253
+ /** Mark an agent as currently processing (serial execution). */
254
+ markProcessing(agentName: string): void;
255
+ /** Mark an agent as done processing. */
256
+ markDone(agentName: string): void;
257
+ /** Check if an agent has queued tasks. */
258
+ hasTasks(agentName: string): boolean;
259
+ /** Check if an agent is currently processing a task. */
260
+ isProcessing(agentName: string): boolean;
261
+ /** Get the number of queued tasks for an agent. */
262
+ queueSize(agentName: string): number;
263
+ /** Get all queued tasks for an agent. */
264
+ peek(agentName: string): AgentTask[];
265
+ /** Clear all tasks for an agent. */
266
+ clear(agentName: string): void;
267
+ /** Clear all queues. */
268
+ clearAll(): void;
269
+ }
270
+
271
+ declare class ExecutionLog {
272
+ private records;
273
+ private persistDir?;
274
+ private maxInMemory;
275
+ setPersistDir(dir: string): void;
276
+ setMaxInMemory(max: number): void;
277
+ record(entry: ExecutionRecord): Promise<void>;
278
+ /** Get recent execution records, optionally filtered by agent. */
279
+ getRecords(agentName?: string, limit?: number): ExecutionRecord[];
280
+ /** Get the last execution record for an agent. */
281
+ getLastRecord(agentName: string): ExecutionRecord | undefined;
282
+ /** Count records by status for an agent. */
283
+ getStats(agentName?: string): Record<string, number>;
284
+ clear(): void;
285
+ private persistRecord;
286
+ }
287
+
288
+ interface PromptAgentFn {
289
+ (agentName: string, prompt: string): Promise<string>;
290
+ }
291
+ declare class TaskDispatcher {
292
+ private readonly queue;
293
+ private readonly log;
294
+ private readonly promptAgent;
295
+ private readonly pollIntervalMs;
296
+ private running;
297
+ private dispatchInterval;
298
+ private agentNames;
299
+ constructor(queue: TaskQueue, log: ExecutionLog, promptAgent: PromptAgentFn, pollIntervalMs?: number);
300
+ /** Register an agent name to be dispatched. */
301
+ registerAgent(agentName: string): void;
302
+ /** Unregister an agent. */
303
+ unregisterAgent(agentName: string): void;
304
+ /** Start the dispatch loop. */
305
+ start(): void;
306
+ /** Stop the dispatch loop. */
307
+ stop(): void;
308
+ /** Manual dispatch — process one tick immediately. */
309
+ tick(): Promise<void>;
310
+ private executeTask;
311
+ get isRunning(): boolean;
312
+ }
313
+
314
+ declare const HeartbeatConfigSchema: z.ZodObject<{
315
+ intervalMs: z.ZodNumber;
316
+ prompt: z.ZodString;
317
+ priority: z.ZodOptional<z.ZodEnum<{
318
+ low: "low";
319
+ normal: "normal";
320
+ high: "high";
321
+ critical: "critical";
322
+ }>>;
323
+ }, z.core.$strip>;
324
+ declare const CronConfigSchema: z.ZodObject<{
325
+ pattern: z.ZodString;
326
+ prompt: z.ZodString;
327
+ timezone: z.ZodOptional<z.ZodString>;
328
+ priority: z.ZodOptional<z.ZodEnum<{
329
+ low: "low";
330
+ normal: "normal";
331
+ high: "high";
332
+ critical: "critical";
333
+ }>>;
334
+ }, z.core.$strip>;
335
+ declare const HookConfigSchema: z.ZodObject<{
336
+ eventName: z.ZodString;
337
+ prompt: z.ZodString;
338
+ priority: z.ZodOptional<z.ZodEnum<{
339
+ low: "low";
340
+ normal: "normal";
341
+ high: "high";
342
+ critical: "critical";
343
+ }>>;
344
+ }, z.core.$strip>;
345
+ declare const ScheduleConfigSchema: z.ZodObject<{
346
+ heartbeat: z.ZodOptional<z.ZodObject<{
347
+ intervalMs: z.ZodNumber;
348
+ prompt: z.ZodString;
349
+ priority: z.ZodOptional<z.ZodEnum<{
350
+ low: "low";
351
+ normal: "normal";
352
+ high: "high";
353
+ critical: "critical";
354
+ }>>;
355
+ }, z.core.$strip>>;
356
+ cron: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodObject<{
357
+ pattern: z.ZodString;
358
+ prompt: z.ZodString;
359
+ timezone: z.ZodOptional<z.ZodString>;
360
+ priority: z.ZodOptional<z.ZodEnum<{
361
+ low: "low";
362
+ normal: "normal";
363
+ high: "high";
364
+ critical: "critical";
365
+ }>>;
366
+ }, z.core.$strip>>>>;
367
+ hooks: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodObject<{
368
+ eventName: z.ZodString;
369
+ prompt: z.ZodString;
370
+ priority: z.ZodOptional<z.ZodEnum<{
371
+ low: "low";
372
+ normal: "normal";
373
+ high: "high";
374
+ critical: "critical";
375
+ }>>;
376
+ }, z.core.$strip>>>>;
377
+ }, z.core.$strip>;
378
+ type ScheduleConfig = z.infer<typeof ScheduleConfigSchema>;
379
+ type ScheduleConfigInput = z.input<typeof ScheduleConfigSchema>;
380
+
381
+ declare class EmployeeScheduler {
382
+ private readonly agentName;
383
+ private readonly queue;
384
+ private readonly dispatcher;
385
+ private readonly log;
386
+ private readonly router;
387
+ private readonly eventBus;
388
+ private _running;
389
+ constructor(agentName: string, promptAgent: PromptAgentFn, config?: {
390
+ persistDir?: string;
391
+ });
392
+ /** Configure schedule from template config. */
393
+ configure(scheduleConfig: ScheduleConfigInput): void;
394
+ /** Start the scheduler — begins accepting and dispatching tasks. */
395
+ start(): void;
396
+ /** Stop the scheduler. */
397
+ stop(): void;
398
+ /** Manually dispatch a one-off task. */
399
+ dispatch(prompt: string, priority?: "low" | "normal" | "high" | "critical"): void;
400
+ /** Emit an event to trigger HookInput sources. */
401
+ emitEvent(eventName: string, payload?: unknown): void;
402
+ /** Get queued tasks. */
403
+ getTasks(): {
404
+ queued: number;
405
+ processing: boolean;
406
+ tasks: unknown[];
407
+ };
408
+ /** Get execution logs. */
409
+ getLogs(limit?: number): unknown[];
410
+ /** Get execution stats. */
411
+ getStats(): Record<string, number>;
412
+ /** Get input sources info. */
413
+ getSources(): {
414
+ id: string;
415
+ type: string;
416
+ active: boolean;
417
+ }[];
418
+ get running(): boolean;
419
+ get executionLog(): ExecutionLog;
420
+ }
421
+
422
+ type TaskCallback = (task: AgentTask) => void;
423
+ interface InputSource {
424
+ readonly id: string;
425
+ readonly type: string;
426
+ /** Start the input source. Calls onTask when a task should be dispatched. */
427
+ start(agentName: string, onTask: TaskCallback): void;
428
+ /** Stop the input source. */
429
+ stop(): void;
430
+ /** Whether this source is currently active. */
431
+ readonly active: boolean;
432
+ }
433
+
434
+ interface HeartbeatConfig {
435
+ intervalMs: number;
436
+ prompt: string;
437
+ priority?: "low" | "normal" | "high" | "critical";
438
+ }
439
+ declare class HeartbeatInput implements InputSource {
440
+ private readonly config;
441
+ readonly id: string;
442
+ readonly type = "heartbeat";
443
+ private interval;
444
+ private _active;
445
+ constructor(config: HeartbeatConfig, id?: string);
446
+ start(agentName: string, onTask: TaskCallback): void;
447
+ stop(): void;
448
+ get active(): boolean;
449
+ }
450
+
451
+ interface CronConfig {
452
+ pattern: string;
453
+ prompt: string;
454
+ timezone?: string;
455
+ priority?: "low" | "normal" | "high" | "critical";
456
+ }
457
+ declare class CronInput implements InputSource {
458
+ private readonly config;
459
+ readonly id: string;
460
+ readonly type = "cron";
461
+ private job;
462
+ private _active;
463
+ constructor(config: CronConfig, id?: string);
464
+ start(agentName: string, onTask: TaskCallback): void;
465
+ stop(): void;
466
+ get active(): boolean;
467
+ }
468
+
469
+ interface HookConfig {
470
+ eventName: string;
471
+ prompt: string;
472
+ priority?: "low" | "normal" | "high" | "critical";
473
+ }
474
+ declare class HookInput implements InputSource {
475
+ private readonly config;
476
+ private readonly emitter;
477
+ readonly id: string;
478
+ readonly type = "hook";
479
+ private _active;
480
+ private handler;
481
+ constructor(config: HookConfig, emitter: EventEmitter, id?: string);
482
+ start(agentName: string, onTask: TaskCallback): void;
483
+ stop(): void;
484
+ get active(): boolean;
485
+ }
486
+
487
+ declare class InputRouter {
488
+ private readonly queue;
489
+ private sources;
490
+ private agentName?;
491
+ constructor(queue: TaskQueue);
492
+ /** Register an input source. */
493
+ register(source: InputSource): void;
494
+ /** Unregister an input source. */
495
+ unregister(sourceId: string): boolean;
496
+ /** Start all registered input sources. */
497
+ startAll(agentName: string): void;
498
+ /** Stop all registered input sources. */
499
+ stopAll(): void;
500
+ /** Get all registered source IDs. */
501
+ listSources(): {
502
+ id: string;
503
+ type: string;
504
+ active: boolean;
505
+ }[];
506
+ /** Get a specific source by ID. */
507
+ getSource(id: string): InputSource | undefined;
508
+ get sourceCount(): number;
509
+ }
510
+
511
+ declare const McpServerRefSchema: z.ZodObject<{
512
+ name: z.ZodString;
513
+ command: z.ZodString;
514
+ args: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString>>>;
515
+ env: z.ZodDefault<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>>;
516
+ }, z.core.$strip>;
517
+ declare const DomainContextSchema: z.ZodObject<{
518
+ skills: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString>>>;
519
+ prompts: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString>>>;
520
+ mcpServers: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodObject<{
521
+ name: z.ZodString;
522
+ command: z.ZodString;
523
+ args: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString>>>;
524
+ env: z.ZodDefault<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>>;
525
+ }, z.core.$strip>>>>;
526
+ workflow: z.ZodOptional<z.ZodString>;
527
+ subAgents: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString>>>;
528
+ plugins: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString>>>;
529
+ extensions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodArray<z.ZodUnknown>>>;
530
+ }, z.core.$strip>;
531
+ declare const AgentBackendSchema: z.ZodObject<{
532
+ type: z.ZodEnum<{
533
+ cursor: "cursor";
534
+ "claude-code": "claude-code";
535
+ custom: "custom";
536
+ }>;
537
+ config: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
538
+ }, z.core.$strip>;
539
+ declare const ModelProviderSchema: z.ZodObject<{
540
+ type: z.ZodEnum<{
541
+ custom: "custom";
542
+ anthropic: "anthropic";
543
+ openai: "openai";
544
+ }>;
545
+ config: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
546
+ }, z.core.$strip>;
547
+ declare const InitializerStepSchema: z.ZodObject<{
548
+ type: z.ZodString;
549
+ config: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
550
+ }, z.core.$strip>;
551
+ declare const InitializerSchema: z.ZodObject<{
552
+ steps: z.ZodArray<z.ZodObject<{
553
+ type: z.ZodString;
554
+ config: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
555
+ }, z.core.$strip>>;
556
+ }, z.core.$strip>;
557
+ declare const PermissionsObjectSchema: z.ZodObject<{
558
+ allow: z.ZodOptional<z.ZodArray<z.ZodString>>;
559
+ deny: z.ZodOptional<z.ZodArray<z.ZodString>>;
560
+ ask: z.ZodOptional<z.ZodArray<z.ZodString>>;
561
+ defaultMode: z.ZodOptional<z.ZodEnum<{
562
+ bypassPermissions: "bypassPermissions";
563
+ default: "default";
564
+ acceptEdits: "acceptEdits";
565
+ plan: "plan";
566
+ dontAsk: "dontAsk";
567
+ }>>;
568
+ sandbox: z.ZodOptional<z.ZodObject<{
569
+ enabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
570
+ autoAllowBashIfSandboxed: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
571
+ network: z.ZodOptional<z.ZodObject<{
572
+ allowedDomains: z.ZodOptional<z.ZodArray<z.ZodString>>;
573
+ allowLocalBinding: z.ZodOptional<z.ZodBoolean>;
574
+ }, z.core.$strip>>;
575
+ }, z.core.$strip>>;
576
+ additionalDirectories: z.ZodOptional<z.ZodArray<z.ZodString>>;
577
+ }, z.core.$strip>;
578
+ declare const PermissionPresetSchema: z.ZodEnum<{
579
+ permissive: "permissive";
580
+ standard: "standard";
581
+ restricted: "restricted";
582
+ readonly: "readonly";
583
+ }>;
584
+ /** Accepts either a preset string or a full permissions object. */
585
+ declare const PermissionsInputSchema: z.ZodUnion<readonly [z.ZodEnum<{
586
+ permissive: "permissive";
587
+ standard: "standard";
588
+ restricted: "restricted";
589
+ readonly: "readonly";
590
+ }>, z.ZodObject<{
591
+ allow: z.ZodOptional<z.ZodArray<z.ZodString>>;
592
+ deny: z.ZodOptional<z.ZodArray<z.ZodString>>;
593
+ ask: z.ZodOptional<z.ZodArray<z.ZodString>>;
594
+ defaultMode: z.ZodOptional<z.ZodEnum<{
595
+ bypassPermissions: "bypassPermissions";
596
+ default: "default";
597
+ acceptEdits: "acceptEdits";
598
+ plan: "plan";
599
+ dontAsk: "dontAsk";
600
+ }>>;
601
+ sandbox: z.ZodOptional<z.ZodObject<{
602
+ enabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
603
+ autoAllowBashIfSandboxed: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
604
+ network: z.ZodOptional<z.ZodObject<{
605
+ allowedDomains: z.ZodOptional<z.ZodArray<z.ZodString>>;
606
+ allowLocalBinding: z.ZodOptional<z.ZodBoolean>;
607
+ }, z.core.$strip>>;
608
+ }, z.core.$strip>>;
609
+ additionalDirectories: z.ZodOptional<z.ZodArray<z.ZodString>>;
610
+ }, z.core.$strip>]>;
611
+ declare const ComponentOriginSchema: z.ZodObject<{
612
+ type: z.ZodEnum<{
613
+ source: "source";
614
+ builtin: "builtin";
615
+ local: "local";
616
+ }>;
617
+ sourceName: z.ZodOptional<z.ZodString>;
618
+ syncHash: z.ZodOptional<z.ZodString>;
619
+ syncedAt: z.ZodOptional<z.ZodString>;
620
+ modified: z.ZodOptional<z.ZodBoolean>;
621
+ }, z.core.$strip>;
622
+ declare const AgentTemplateSchema: z.ZodObject<{
623
+ name: z.ZodString;
624
+ version: z.ZodString;
625
+ description: z.ZodOptional<z.ZodString>;
626
+ $type: z.ZodOptional<z.ZodString>;
627
+ $version: z.ZodOptional<z.ZodNumber>;
628
+ origin: z.ZodOptional<z.ZodObject<{
629
+ type: z.ZodEnum<{
630
+ source: "source";
631
+ builtin: "builtin";
632
+ local: "local";
633
+ }>;
634
+ sourceName: z.ZodOptional<z.ZodString>;
635
+ syncHash: z.ZodOptional<z.ZodString>;
636
+ syncedAt: z.ZodOptional<z.ZodString>;
637
+ modified: z.ZodOptional<z.ZodBoolean>;
638
+ }, z.core.$strip>>;
639
+ tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
640
+ backend: z.ZodObject<{
641
+ type: z.ZodEnum<{
642
+ cursor: "cursor";
643
+ "claude-code": "claude-code";
644
+ custom: "custom";
645
+ }>;
646
+ config: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
647
+ }, z.core.$strip>;
648
+ provider: z.ZodObject<{
649
+ type: z.ZodEnum<{
650
+ custom: "custom";
651
+ anthropic: "anthropic";
652
+ openai: "openai";
653
+ }>;
654
+ config: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
655
+ }, z.core.$strip>;
656
+ domainContext: z.ZodObject<{
657
+ skills: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString>>>;
658
+ prompts: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString>>>;
659
+ mcpServers: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodObject<{
660
+ name: z.ZodString;
661
+ command: z.ZodString;
662
+ args: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString>>>;
663
+ env: z.ZodDefault<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>>;
664
+ }, z.core.$strip>>>>;
665
+ workflow: z.ZodOptional<z.ZodString>;
666
+ subAgents: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString>>>;
667
+ plugins: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString>>>;
668
+ extensions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodArray<z.ZodUnknown>>>;
669
+ }, z.core.$strip>;
670
+ permissions: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
671
+ permissive: "permissive";
672
+ standard: "standard";
673
+ restricted: "restricted";
674
+ readonly: "readonly";
675
+ }>, z.ZodObject<{
676
+ allow: z.ZodOptional<z.ZodArray<z.ZodString>>;
677
+ deny: z.ZodOptional<z.ZodArray<z.ZodString>>;
678
+ ask: z.ZodOptional<z.ZodArray<z.ZodString>>;
679
+ defaultMode: z.ZodOptional<z.ZodEnum<{
680
+ bypassPermissions: "bypassPermissions";
681
+ default: "default";
682
+ acceptEdits: "acceptEdits";
683
+ plan: "plan";
684
+ dontAsk: "dontAsk";
685
+ }>>;
686
+ sandbox: z.ZodOptional<z.ZodObject<{
687
+ enabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
688
+ autoAllowBashIfSandboxed: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
689
+ network: z.ZodOptional<z.ZodObject<{
690
+ allowedDomains: z.ZodOptional<z.ZodArray<z.ZodString>>;
691
+ allowLocalBinding: z.ZodOptional<z.ZodBoolean>;
692
+ }, z.core.$strip>>;
693
+ }, z.core.$strip>>;
694
+ additionalDirectories: z.ZodOptional<z.ZodArray<z.ZodString>>;
695
+ }, z.core.$strip>]>>;
696
+ initializer: z.ZodOptional<z.ZodObject<{
697
+ steps: z.ZodArray<z.ZodObject<{
698
+ type: z.ZodString;
699
+ config: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
700
+ }, z.core.$strip>>;
701
+ }, z.core.$strip>>;
702
+ schedule: z.ZodOptional<z.ZodObject<{
703
+ heartbeat: z.ZodOptional<z.ZodObject<{
704
+ intervalMs: z.ZodNumber;
705
+ prompt: z.ZodString;
706
+ priority: z.ZodOptional<z.ZodEnum<{
707
+ low: "low";
708
+ normal: "normal";
709
+ high: "high";
710
+ critical: "critical";
711
+ }>>;
712
+ }, z.core.$strip>>;
713
+ cron: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodObject<{
714
+ pattern: z.ZodString;
715
+ prompt: z.ZodString;
716
+ timezone: z.ZodOptional<z.ZodString>;
717
+ priority: z.ZodOptional<z.ZodEnum<{
718
+ low: "low";
719
+ normal: "normal";
720
+ high: "high";
721
+ critical: "critical";
722
+ }>>;
723
+ }, z.core.$strip>>>>;
724
+ hooks: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodObject<{
725
+ eventName: z.ZodString;
726
+ prompt: z.ZodString;
727
+ priority: z.ZodOptional<z.ZodEnum<{
728
+ low: "low";
729
+ normal: "normal";
730
+ high: "high";
731
+ critical: "critical";
732
+ }>>;
733
+ }, z.core.$strip>>>>;
734
+ }, z.core.$strip>>;
735
+ metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
736
+ }, z.core.$strip>;
737
+ type AgentTemplateInput = z.input<typeof AgentTemplateSchema>;
738
+ type AgentTemplateOutput = z.output<typeof AgentTemplateSchema>;
739
+
740
+ /**
741
+ * Standalone config validators (#119).
742
+ * Each function validates a sub-config and returns a ConfigValidationResult
743
+ * with both schema errors and semantic warnings.
744
+ */
745
+
746
+ declare function validateBackendConfig(data: unknown): ConfigValidationResult<AgentBackendConfig>;
747
+ declare function validateProviderConfig(data: unknown): ConfigValidationResult<ModelProviderConfig>;
748
+ declare function validatePermissionsConfig(data: unknown): ConfigValidationResult<PermissionsInput>;
749
+ declare function validateScheduleConfig(data: unknown): ConfigValidationResult<ScheduleConfig>;
750
+ declare function validateDomainContextConfig(data: unknown): ConfigValidationResult<DomainContextConfig>;
751
+ /**
752
+ * Deep-validate an AgentTemplate: schema + cross-field semantic checks.
753
+ * Returns all errors and warnings.
754
+ */
755
+ declare function validateTemplate(data: unknown): ConfigValidationResult<AgentTemplate>;
756
+
757
+ declare class TemplateLoader {
758
+ /**
759
+ * Load and validate an Agent Template from a JSON file.
760
+ * @throws {ConfigNotFoundError} if file does not exist
761
+ * @throws {ConfigValidationError} if JSON is malformed or fails schema validation
762
+ */
763
+ loadFromFile(filePath: string): Promise<AgentTemplate>;
764
+ /**
765
+ * Parse and validate an Agent Template from a JSON string.
766
+ * @throws {ConfigValidationError} if JSON is malformed or fails schema validation
767
+ */
768
+ loadFromString(content: string, source?: string): Promise<AgentTemplate>;
769
+ /**
770
+ * Load all valid Agent Templates from a directory (non-recursive).
771
+ * Only `.json` files are considered; non-template files are skipped.
772
+ * @throws {ConfigNotFoundError} if directory does not exist
773
+ */
774
+ loadFromDirectory(dirPath: string): Promise<AgentTemplate[]>;
775
+ private parseAndValidate;
776
+ }
777
+ /**
778
+ * Map Zod's output (with defaults applied) to the shared AgentTemplate type.
779
+ * This ensures the return type satisfies the interface contract exactly.
780
+ */
781
+ declare function toAgentTemplate(output: AgentTemplateOutput): AgentTemplate;
782
+
783
+ interface RegistryOptions {
784
+ /** If true, re-registering the same name overwrites the existing entry. Default: false */
785
+ allowOverwrite?: boolean;
786
+ }
787
+ /**
788
+ * Template registry that extends BaseComponentManager (#119).
789
+ * Inherits CRUD, search/filter, import/export from the base class.
790
+ * Adds template-specific overrides: duplicate checking, TemplateLoader-based directory loading.
791
+ */
792
+ declare class TemplateRegistry extends BaseComponentManager<AgentTemplate> {
793
+ protected readonly componentType = "template";
794
+ private readonly loader;
795
+ private readonly allowOverwrite;
796
+ constructor(options?: RegistryOptions);
797
+ /**
798
+ * Register a template. Throws if a template with the same name already exists
799
+ * (unless allowOverwrite is enabled).
800
+ */
801
+ register(template: AgentTemplate): void;
802
+ /**
803
+ * Get a template by name.
804
+ * @throws {TemplateNotFoundError} if not found
805
+ */
806
+ getOrThrow(name: string): AgentTemplate;
807
+ /**
808
+ * Load templates from a directory using TemplateLoader (JSON + Zod validation).
809
+ * Invalid files are skipped with a warning log.
810
+ */
811
+ loadFromDirectory(dirPath: string): Promise<number>;
812
+ /** @deprecated Use loadFromDirectory instead. */
813
+ loadBuiltins(configDir: string): Promise<number>;
814
+ /**
815
+ * Validate raw data as an AgentTemplate using the Zod schema.
816
+ * Returns structured ConfigValidationResult (#119).
817
+ */
818
+ validate(data: unknown, _source: string): ConfigValidationResult<AgentTemplate>;
819
+ persist(template: AgentTemplate): Promise<void>;
820
+ }
821
+
822
+ interface TemplateFileWatcherOptions {
823
+ debounceMs?: number;
824
+ }
825
+ /**
826
+ * Watches the templates directory for file changes and auto-reloads
827
+ * the TemplateRegistry. Handles create, modify, and delete events.
828
+ *
829
+ * Tracks file→templateName mapping so deletions can correctly unregister
830
+ * templates whose name differs from the filename.
831
+ */
832
+ declare class TemplateFileWatcher {
833
+ private readonly templatesDir;
834
+ private readonly registry;
835
+ private watcher;
836
+ private readonly debounceMs;
837
+ private readonly loader;
838
+ private debounceTimers;
839
+ /** Maps relative filename → template name loaded from that file. */
840
+ private fileToName;
841
+ constructor(templatesDir: string, registry: TemplateRegistry, options?: TemplateFileWatcherOptions);
842
+ start(): void;
843
+ stop(): void;
844
+ get isWatching(): boolean;
845
+ private buildFileMap;
846
+ private handleChange;
847
+ private processChange;
848
+ }
849
+
850
+ interface StepContext {
851
+ workspaceDir: string;
852
+ instanceMeta: Partial<AgentInstanceMeta>;
853
+ template: AgentTemplate;
854
+ logger: {
855
+ info: (...args: unknown[]) => void;
856
+ warn: (...args: unknown[]) => void;
857
+ error: (...args: unknown[]) => void;
858
+ debug: (...args: unknown[]) => void;
859
+ };
860
+ /** Shared mutable state between steps. */
861
+ state: Map<string, unknown>;
862
+ }
863
+ interface StepResult {
864
+ success: boolean;
865
+ output?: Record<string, unknown>;
866
+ message?: string;
867
+ }
868
+ interface StepValidationIssue {
869
+ field: string;
870
+ message: string;
871
+ }
872
+ interface StepValidationResult {
873
+ valid: boolean;
874
+ issues: StepValidationIssue[];
875
+ }
876
+ interface PipelineOptions {
877
+ /** Per-step timeout in ms. Default: 60_000 (1 min). */
878
+ defaultStepTimeoutMs?: number;
879
+ /** Total pipeline timeout in ms. Default: 300_000 (5 min). */
880
+ totalTimeoutMs?: number;
881
+ /** Progress callback invoked before each step executes. */
882
+ onProgress?: (stepIndex: number, totalSteps: number, stepType: string) => void;
883
+ }
884
+ interface PipelineResult {
885
+ success: boolean;
886
+ stepsExecuted: number;
887
+ stepsTotal: number;
888
+ errors: PipelineStepError[];
889
+ outputs: Map<string, Record<string, unknown>>;
890
+ }
891
+ interface PipelineStepError {
892
+ stepIndex: number;
893
+ stepType: string;
894
+ error: Error;
895
+ }
896
+
897
+ /**
898
+ * Abstract base class for initializer step executors.
899
+ * Each step type (e.g. "git-clone", "exec") implements this interface.
900
+ */
901
+ declare abstract class InitializerStepExecutor {
902
+ /** Unique identifier matching the `type` field in InitializerStep config. */
903
+ abstract readonly type: string;
904
+ /** Validate step-specific config before execution. */
905
+ abstract validate(config: unknown): StepValidationResult;
906
+ /** Execute the step within the given context. */
907
+ abstract execute(context: StepContext, config: unknown): Promise<StepResult>;
908
+ /** Optional rollback — called in reverse order when a later step fails. */
909
+ rollback?(context: StepContext, config: unknown, error: Error): Promise<void>;
910
+ }
911
+
912
+ /**
913
+ * Registry for initializer step executors.
914
+ * Supports registration of custom step types at runtime.
915
+ */
916
+ declare class StepRegistry {
917
+ private readonly executors;
918
+ register(executor: InitializerStepExecutor): void;
919
+ get(type: string): InitializerStepExecutor | undefined;
920
+ getOrThrow(type: string): InitializerStepExecutor;
921
+ has(type: string): boolean;
922
+ listTypes(): string[];
923
+ }
924
+
925
+ interface InitializerOptions {
926
+ defaultLaunchMode?: LaunchMode;
927
+ domainManagers?: DomainManagers$1;
928
+ /** Step registry for InitializerConfig pipeline execution. When provided, template.initializer.steps will be executed during createInstance(). */
929
+ stepRegistry?: StepRegistry;
930
+ }
931
+ interface InstanceOverrides {
932
+ launchMode: LaunchMode;
933
+ workspacePolicy: WorkspacePolicy;
934
+ /** Absolute path for the agent workspace. When omitted, defaults to {instancesBaseDir}/{name}. */
935
+ workDir: string;
936
+ /** Behavior when workDir already exists. Default: "error". */
937
+ workDirConflict: WorkDirConflict;
938
+ /** Override template permissions at instance level. Completely replaces template.permissions. */
939
+ permissions: PermissionsInput;
940
+ metadata: Record<string, string>;
941
+ }
942
+ declare class AgentInitializer {
943
+ private readonly templateRegistry;
944
+ private readonly instancesBaseDir;
945
+ private readonly options?;
946
+ private readonly builder;
947
+ private readonly pipeline?;
948
+ constructor(templateRegistry: TemplateRegistry, instancesBaseDir: string, options?: InitializerOptions | undefined);
949
+ /**
950
+ * Create a new Agent Instance.
951
+ * 1. Resolve template from registry
952
+ * 2. Create workspace directory {instancesBaseDir}/{name}/
953
+ * 3. Materialize Domain Context files
954
+ * 4. Write .actant.json metadata
955
+ *
956
+ * @throws {TemplateNotFoundError} if template is not in registry
957
+ * @throws {ConfigValidationError} if name conflicts with existing directory
958
+ * @throws {WorkspaceInitError} if directory creation or file writing fails
959
+ */
960
+ createInstance(name: string, templateName: string, overrides?: Partial<InstanceOverrides>): Promise<AgentInstanceMeta>;
961
+ /**
962
+ * Find an existing instance or create a new one (idempotent).
963
+ * - Directory exists + valid .actant.json → return existing
964
+ * - Directory does not exist → create new instance
965
+ * - Directory exists but corrupted → throw InstanceCorruptedError
966
+ */
967
+ findOrCreateInstance(name: string, templateName: string, overrides?: Partial<InstanceOverrides>): Promise<{
968
+ meta: AgentInstanceMeta;
969
+ created: boolean;
970
+ }>;
971
+ /**
972
+ * Destroy an instance by removing its workspace directory.
973
+ * For symlinked instances (custom workDir): removes the symlink and `.actant.json`
974
+ * from the target, but preserves the rest of the user's directory.
975
+ * For normal instances: removes the entire workspace directory.
976
+ */
977
+ destroyInstance(name: string): Promise<void>;
978
+ }
979
+
980
+ /**
981
+ * Optional Domain managers for full component resolution.
982
+ * When provided, names are resolved to real definitions and rendered.
983
+ * When absent, placeholder content is generated.
984
+ */
985
+ interface DomainManagers {
986
+ skills?: SkillManager;
987
+ prompts?: PromptManager;
988
+ mcp?: McpConfigManager;
989
+ workflows?: WorkflowManager;
990
+ }
991
+ /**
992
+ * Materializes Domain Context references into actual files in the instance workspace.
993
+ * Paths for IDE-specific config (MCP, etc.) depend on backendType (e.g. .cursor vs .claude).
994
+ *
995
+ * Materialization rules:
996
+ * skills → AGENTS.md
997
+ * mcpServers → {backendConfigDir}/mcp.json (e.g. .cursor/mcp.json or .claude/mcp.json)
998
+ * workflow → .trellis/workflow.md
999
+ * prompts → prompts/system.md
1000
+ * subAgents → recorded in .actant.json (not materialized as files)
1001
+ *
1002
+ * @deprecated Use WorkspaceBuilder + BackendBuilder instead (Phase 3b).
1003
+ * Kept for backward compatibility; will be removed in a future version.
1004
+ */
1005
+ declare class ContextMaterializer {
1006
+ private readonly managers?;
1007
+ constructor(managers?: DomainManagers | undefined);
1008
+ materialize(workspaceDir: string, domainContext: DomainContextConfig, backendType?: AgentBackendType): Promise<void>;
1009
+ private materializeSkills;
1010
+ /**
1011
+ * MCP Servers → {configDir}/mcp.json (e.g. .cursor/mcp.json or .claude/mcp.json)
1012
+ * Template provides inline McpServerRef configs; no name-based resolution needed.
1013
+ */
1014
+ private materializeMcpServers;
1015
+ /**
1016
+ * Claude Code settings.local.json — pre-approve tools so agents can operate autonomously.
1017
+ * Includes both MCP tools (`mcp__<server>` prefix) and essential built-in tools.
1018
+ */
1019
+ private materializeClaudePermissions;
1020
+ private materializeWorkflow;
1021
+ private materializePrompts;
1022
+ }
1023
+
1024
+ /**
1025
+ * Executes an ordered list of initializer steps with:
1026
+ * - Sequential execution (steps may depend on prior shared state)
1027
+ * - Per-step and total pipeline timeout
1028
+ * - Transactional rollback on failure (reverse order)
1029
+ * - Progress reporting
1030
+ */
1031
+ declare class InitializationPipeline {
1032
+ private readonly registry;
1033
+ private readonly stepTimeoutMs;
1034
+ private readonly totalTimeoutMs;
1035
+ private readonly onProgress?;
1036
+ constructor(registry: StepRegistry, options?: PipelineOptions);
1037
+ /**
1038
+ * Validate all steps without executing them.
1039
+ * Returns per-step validation results.
1040
+ */
1041
+ dryRun(steps: InitializerStep[]): StepValidationResult[];
1042
+ /**
1043
+ * Execute all steps sequentially. On failure, rollback executed steps in reverse order.
1044
+ */
1045
+ run(steps: InitializerStep[], context: StepContext): Promise<PipelineResult>;
1046
+ private executeWithTimeout;
1047
+ private rollback;
1048
+ }
1049
+
1050
+ /**
1051
+ * Creates directories within the workspace.
1052
+ * Paths are relative to workspaceDir (absolute paths are rejected for safety).
1053
+ */
1054
+ declare class MkdirStep extends InitializerStepExecutor {
1055
+ readonly type = "mkdir";
1056
+ validate(config: unknown): StepValidationResult;
1057
+ execute(context: StepContext, config: unknown): Promise<StepResult>;
1058
+ rollback(context: StepContext, config: unknown, _error: Error): Promise<void>;
1059
+ }
1060
+
1061
+ /**
1062
+ * Execute an arbitrary shell command within the workspace.
1063
+ */
1064
+ declare class ExecStep extends InitializerStepExecutor {
1065
+ readonly type = "exec";
1066
+ validate(config: unknown): StepValidationResult;
1067
+ execute(context: StepContext, config: unknown): Promise<StepResult>;
1068
+ }
1069
+
1070
+ /**
1071
+ * Copy files or directories into the workspace.
1072
+ * `from` can be absolute (external source) or relative to workspaceDir.
1073
+ * `to` must be relative to workspaceDir.
1074
+ */
1075
+ declare class FileCopyStep extends InitializerStepExecutor {
1076
+ readonly type = "file-copy";
1077
+ validate(config: unknown): StepValidationResult;
1078
+ execute(context: StepContext, config: unknown): Promise<StepResult>;
1079
+ rollback(context: StepContext, config: unknown, _error: Error): Promise<void>;
1080
+ }
1081
+
1082
+ /**
1083
+ * Clone a git repository into the workspace.
1084
+ */
1085
+ declare class GitCloneStep extends InitializerStepExecutor {
1086
+ readonly type = "git-clone";
1087
+ validate(config: unknown): StepValidationResult;
1088
+ execute(context: StepContext, config: unknown): Promise<StepResult>;
1089
+ rollback(context: StepContext, config: unknown, _error: Error): Promise<void>;
1090
+ }
1091
+
1092
+ /**
1093
+ * Run package installation (npm/pnpm/yarn install) within the workspace.
1094
+ */
1095
+ declare class NpmInstallStep extends InitializerStepExecutor {
1096
+ readonly type = "npm-install";
1097
+ validate(config: unknown): StepValidationResult;
1098
+ execute(context: StepContext, config: unknown): Promise<StepResult>;
1099
+ }
1100
+
1101
+ /**
1102
+ * Create a StepRegistry pre-loaded with all built-in step executors.
1103
+ */
1104
+ declare function createDefaultStepRegistry(): StepRegistry;
1105
+
1106
+ declare const AgentStatusSchema: z.ZodEnum<{
1107
+ error: "error";
1108
+ running: "running";
1109
+ created: "created";
1110
+ starting: "starting";
1111
+ stopping: "stopping";
1112
+ stopped: "stopped";
1113
+ crashed: "crashed";
1114
+ }>;
1115
+ declare const LaunchModeSchema: z.ZodEnum<{
1116
+ direct: "direct";
1117
+ "acp-background": "acp-background";
1118
+ "acp-service": "acp-service";
1119
+ "one-shot": "one-shot";
1120
+ }>;
1121
+ declare const AgentInstanceMetaSchema: z.ZodObject<{
1122
+ id: z.ZodString;
1123
+ name: z.ZodString;
1124
+ templateName: z.ZodString;
1125
+ templateVersion: z.ZodString;
1126
+ backendType: z.ZodDefault<z.ZodEnum<{
1127
+ cursor: "cursor";
1128
+ "claude-code": "claude-code";
1129
+ custom: "custom";
1130
+ }>>;
1131
+ backendConfig: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1132
+ status: z.ZodEnum<{
1133
+ error: "error";
1134
+ running: "running";
1135
+ created: "created";
1136
+ starting: "starting";
1137
+ stopping: "stopping";
1138
+ stopped: "stopped";
1139
+ crashed: "crashed";
1140
+ }>;
1141
+ launchMode: z.ZodEnum<{
1142
+ direct: "direct";
1143
+ "acp-background": "acp-background";
1144
+ "acp-service": "acp-service";
1145
+ "one-shot": "one-shot";
1146
+ }>;
1147
+ workspacePolicy: z.ZodDefault<z.ZodEnum<{
1148
+ persistent: "persistent";
1149
+ ephemeral: "ephemeral";
1150
+ }>>;
1151
+ processOwnership: z.ZodDefault<z.ZodEnum<{
1152
+ managed: "managed";
1153
+ external: "external";
1154
+ }>>;
1155
+ createdAt: z.ZodString;
1156
+ updatedAt: z.ZodString;
1157
+ pid: z.ZodOptional<z.ZodNumber>;
1158
+ effectivePermissions: z.ZodOptional<z.ZodObject<{
1159
+ allow: z.ZodOptional<z.ZodArray<z.ZodString>>;
1160
+ deny: z.ZodOptional<z.ZodArray<z.ZodString>>;
1161
+ ask: z.ZodOptional<z.ZodArray<z.ZodString>>;
1162
+ defaultMode: z.ZodOptional<z.ZodEnum<{
1163
+ bypassPermissions: "bypassPermissions";
1164
+ default: "default";
1165
+ acceptEdits: "acceptEdits";
1166
+ plan: "plan";
1167
+ dontAsk: "dontAsk";
1168
+ }>>;
1169
+ sandbox: z.ZodOptional<z.ZodObject<{
1170
+ enabled: z.ZodOptional<z.ZodBoolean>;
1171
+ autoAllowBashIfSandboxed: z.ZodOptional<z.ZodBoolean>;
1172
+ network: z.ZodOptional<z.ZodObject<{
1173
+ allowedDomains: z.ZodOptional<z.ZodArray<z.ZodString>>;
1174
+ allowLocalBinding: z.ZodOptional<z.ZodBoolean>;
1175
+ }, z.core.$strip>>;
1176
+ }, z.core.$strip>>;
1177
+ additionalDirectories: z.ZodOptional<z.ZodArray<z.ZodString>>;
1178
+ }, z.core.$strip>>;
1179
+ metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
1180
+ }, z.core.$strip>;
1181
+
1182
+ /** Minimal interface for scanInstances to use registry without circular dependency. */
1183
+ interface InstanceRegistryAdapter {
1184
+ list(): Iterable<{
1185
+ name: string;
1186
+ workspacePath: string;
1187
+ status: string;
1188
+ }>;
1189
+ }
1190
+
1191
+ declare function metaFilePath(workspaceDir: string): string;
1192
+ /** Read and validate `.actant.json` from a workspace directory. */
1193
+ declare function readInstanceMeta(workspaceDir: string): Promise<AgentInstanceMeta>;
1194
+ /** Atomic write: write to a temp file then rename (prevents partial writes). */
1195
+ declare function writeInstanceMeta(workspaceDir: string, meta: AgentInstanceMeta): Promise<void>;
1196
+ /** Partially update `.actant.json` — read, merge, write. */
1197
+ declare function updateInstanceMeta(workspaceDir: string, patch: Partial<AgentInstanceMeta>): Promise<AgentInstanceMeta>;
1198
+ /**
1199
+ * Scan `instancesBaseDir` for all valid instance directories.
1200
+ * Directories whose `.actant.json` is missing or invalid are logged and skipped.
1201
+ *
1202
+ * When `registry` is provided, also includes instances from the registry (external workspaces)
1203
+ * and deduplicates by name (registry entries take precedence).
1204
+ */
1205
+ declare function scanInstances(instancesBaseDir: string, registry?: InstanceRegistryAdapter): Promise<{
1206
+ valid: AgentInstanceMeta[];
1207
+ corrupted: string[];
1208
+ }>;
1209
+
1210
+ interface InstanceRegistryEntry {
1211
+ name: string;
1212
+ template: string;
1213
+ workspacePath: string;
1214
+ location: "builtin" | "external";
1215
+ createdAt: string;
1216
+ status: "stopped" | "running" | "orphaned";
1217
+ }
1218
+ interface InstanceRegistryData {
1219
+ version: 1;
1220
+ instances: Record<string, InstanceRegistryEntry>;
1221
+ }
1222
+ declare class InstanceRegistry implements InstanceRegistryAdapter {
1223
+ private readonly registryPath;
1224
+ private readonly builtinInstancesDir;
1225
+ private data;
1226
+ constructor(registryPath: string, builtinInstancesDir: string);
1227
+ load(): Promise<void>;
1228
+ save(): Promise<void>;
1229
+ register(entry: InstanceRegistryEntry): void;
1230
+ unregister(name: string): boolean;
1231
+ get(name: string): InstanceRegistryEntry | undefined;
1232
+ list(): InstanceRegistryEntry[];
1233
+ has(name: string): boolean;
1234
+ updateStatus(name: string, status: InstanceRegistryEntry["status"]): void;
1235
+ adopt(workspacePath: string, renameTo?: string): Promise<InstanceRegistryEntry>;
1236
+ reconcile(): Promise<{
1237
+ orphaned: string[];
1238
+ adopted: string[];
1239
+ }>;
1240
+ }
1241
+
1242
+ interface AgentProcess {
1243
+ pid: number;
1244
+ workspaceDir: string;
1245
+ instanceName: string;
1246
+ /** Present when the process uses ACP stdio protocol. */
1247
+ stdio?: {
1248
+ stdin: Writable;
1249
+ stdout: Readable;
1250
+ stderr: Readable;
1251
+ };
1252
+ }
1253
+ /**
1254
+ * Strategy interface for launching/terminating Agent backend processes.
1255
+ */
1256
+ interface AgentLauncher {
1257
+ launch(workspaceDir: string, meta: AgentInstanceMeta): Promise<AgentProcess>;
1258
+ terminate(process: AgentProcess): Promise<void>;
1259
+ }
1260
+
1261
+ interface RestartPolicy {
1262
+ /** Maximum number of restarts before giving up. Default: 5 */
1263
+ maxRestarts: number;
1264
+ /** Base delay for exponential backoff (ms). Default: 1000 */
1265
+ backoffBaseMs: number;
1266
+ /** Maximum backoff delay cap (ms). Default: 60000 */
1267
+ backoffMaxMs: number;
1268
+ /** Reset restart counter after this many ms of stable running. Default: 300000 (5 min) */
1269
+ resetAfterMs: number;
1270
+ }
1271
+ declare const DEFAULT_RESTART_POLICY: RestartPolicy;
1272
+ interface RestartDecision {
1273
+ allowed: boolean;
1274
+ delayMs: number;
1275
+ attempt: number;
1276
+ }
1277
+ /**
1278
+ * Tracks restart attempts per instance and enforces exponential backoff.
1279
+ *
1280
+ * Usage:
1281
+ * const tracker = new RestartTracker();
1282
+ * // Before restarting:
1283
+ * const decision = tracker.shouldRestart("my-agent");
1284
+ * if (decision.allowed) {
1285
+ * await delay(decision.delayMs);
1286
+ * tracker.recordRestart("my-agent");
1287
+ * // ... do restart ...
1288
+ * }
1289
+ * // After agent successfully starts:
1290
+ * tracker.recordStart("my-agent");
1291
+ */
1292
+ declare class RestartTracker {
1293
+ private states;
1294
+ private readonly policy;
1295
+ constructor(policy?: Partial<RestartPolicy>);
1296
+ shouldRestart(instanceName: string): RestartDecision;
1297
+ recordRestart(instanceName: string): void;
1298
+ recordStart(instanceName: string): void;
1299
+ reset(instanceName: string): void;
1300
+ getRestartCount(instanceName: string): number;
1301
+ dispose(): void;
1302
+ private getOrCreate;
1303
+ }
1304
+
1305
+ interface PromptResult {
1306
+ text: string;
1307
+ sessionId?: string;
1308
+ }
1309
+ interface StreamChunk {
1310
+ type: "text" | "tool_use" | "result" | "error";
1311
+ content: string;
1312
+ }
1313
+ interface AgentCommunicator {
1314
+ /**
1315
+ * Send a prompt and collect the full response.
1316
+ * @param workspaceDir - The agent's workspace directory (cwd for the process)
1317
+ * @param prompt - The user prompt
1318
+ * @param options - Optional configuration
1319
+ */
1320
+ runPrompt(workspaceDir: string, prompt: string, options?: RunPromptOptions): Promise<PromptResult>;
1321
+ /**
1322
+ * Send a prompt and stream the response chunks.
1323
+ * @param workspaceDir - The agent's workspace directory
1324
+ * @param prompt - The user prompt
1325
+ * @param options - Optional configuration
1326
+ */
1327
+ streamPrompt(workspaceDir: string, prompt: string, options?: RunPromptOptions): AsyncIterable<StreamChunk>;
1328
+ }
1329
+ interface RunPromptOptions {
1330
+ systemPromptFile?: string;
1331
+ appendSystemPrompt?: string;
1332
+ sessionId?: string;
1333
+ timeoutMs?: number;
1334
+ maxTurns?: number;
1335
+ model?: string;
1336
+ }
1337
+ type CommunicatorFactory = (backendType: AgentBackendType) => AgentCommunicator;
1338
+
1339
+ /**
1340
+ * Minimal ACP connection manager interface.
1341
+ * The real implementation lives in @actant/acp; this avoids a circular dependency.
1342
+ */
1343
+ interface AcpConnectionManagerLike {
1344
+ connect(name: string, options: {
1345
+ command: string;
1346
+ args: string[];
1347
+ cwd: string;
1348
+ connectionOptions?: {
1349
+ autoApprove?: boolean;
1350
+ env?: Record<string, string>;
1351
+ };
1352
+ }): Promise<{
1353
+ sessionId: string;
1354
+ }>;
1355
+ has(name: string): boolean;
1356
+ getPrimarySessionId(name: string): string | undefined;
1357
+ getConnection(name: string): AcpConnectionLike | undefined;
1358
+ disconnect(name: string): Promise<void>;
1359
+ disposeAll(): Promise<void>;
1360
+ }
1361
+ interface AcpConnectionLike {
1362
+ prompt(sessionId: string, text: string): Promise<{
1363
+ stopReason: string;
1364
+ text: string;
1365
+ }>;
1366
+ streamPrompt(sessionId: string, text: string): AsyncIterable<unknown>;
1367
+ newSession(cwd: string): Promise<{
1368
+ sessionId: string;
1369
+ }>;
1370
+ isConnected: boolean;
1371
+ }
1372
+ interface ManagerOptions {
1373
+ corruptedDir?: string;
1374
+ /** Milliseconds between process alive checks. Default: 5000 */
1375
+ watcherPollIntervalMs?: number;
1376
+ /** Restart policy for acp-service agents. */
1377
+ restartPolicy?: Partial<RestartPolicy>;
1378
+ /** ACP connection manager for ACP-based backends. */
1379
+ acpManager?: AcpConnectionManagerLike;
1380
+ /** Instance registry for discovering external workspaces. */
1381
+ instanceRegistry?: InstanceRegistryAdapter;
1382
+ }
1383
+ declare class AgentManager {
1384
+ private readonly initializer;
1385
+ private readonly launcher;
1386
+ private readonly instancesBaseDir;
1387
+ private cache;
1388
+ private processes;
1389
+ private readonly corruptedDir;
1390
+ private readonly watcher;
1391
+ private readonly restartTracker;
1392
+ private readonly acpManager?;
1393
+ private readonly instanceRegistry?;
1394
+ constructor(initializer: AgentInitializer, launcher: AgentLauncher, instancesBaseDir: string, options?: ManagerOptions);
1395
+ /**
1396
+ * Scan all workspace directories, load metadata into cache,
1397
+ * fix stale running/starting states, and start the process watcher.
1398
+ */
1399
+ initialize(): Promise<void>;
1400
+ /** Create a new agent (delegates to Initializer). */
1401
+ createAgent(name: string, templateName: string, overrides?: Partial<InstanceOverrides>): Promise<AgentInstanceMeta>;
1402
+ /** Find existing or create new agent (idempotent). */
1403
+ getOrCreateAgent(name: string, templateName: string, overrides?: Partial<InstanceOverrides>): Promise<{
1404
+ meta: AgentInstanceMeta;
1405
+ created: boolean;
1406
+ }>;
1407
+ /**
1408
+ * Start an agent — launch the backend process.
1409
+ * For ACP backends, also establishes ACP connection (initialize + session/new).
1410
+ * @throws {AgentNotFoundError} if agent is not in cache
1411
+ * @throws {AgentAlreadyRunningError} if agent is already running
1412
+ */
1413
+ startAgent(name: string): Promise<void>;
1414
+ /**
1415
+ * Stop an agent — disconnect ACP and terminate the backend process.
1416
+ * @throws {AgentNotFoundError} if agent is not in cache
1417
+ */
1418
+ stopAgent(name: string): Promise<void>;
1419
+ /** Destroy an agent — stop it if running, then remove workspace. */
1420
+ destroyAgent(name: string): Promise<void>;
1421
+ /** Get agent metadata by name. */
1422
+ getAgent(name: string): AgentInstanceMeta | undefined;
1423
+ /** Get agent status by name. */
1424
+ getStatus(name: string): AgentStatus | undefined;
1425
+ /** List all known agents. */
1426
+ listAgents(): AgentInstanceMeta[];
1427
+ /** Get count of managed agents. */
1428
+ get size(): number;
1429
+ /**
1430
+ * Resolve spawn info for an agent without starting it.
1431
+ * If the agent doesn't exist but templateName is provided, auto-creates it.
1432
+ */
1433
+ resolveAgent(name: string, templateName?: string, overrides?: Partial<InstanceOverrides>): Promise<ResolveResult>;
1434
+ /**
1435
+ * Register an externally-spawned process with the manager.
1436
+ * Sets processOwnership to "external" and registers ProcessWatcher monitoring.
1437
+ * @throws {AgentNotFoundError} if agent is not in cache
1438
+ * @throws {AgentAlreadyAttachedError} if agent already has an attached process
1439
+ */
1440
+ attachAgent(name: string, pid: number, attachMetadata?: Record<string, string>): Promise<AgentInstanceMeta>;
1441
+ /**
1442
+ * Detach an externally-managed process.
1443
+ * Clears pid and processOwnership. If cleanup is requested and workspace is ephemeral, destroys the instance.
1444
+ * @throws {AgentNotFoundError} if agent is not in cache
1445
+ * @throws {AgentNotAttachedError} if agent has no attached process
1446
+ */
1447
+ detachAgent(name: string, options?: {
1448
+ cleanup?: boolean;
1449
+ }): Promise<DetachResult>;
1450
+ /**
1451
+ * Send a prompt to an agent and collect the full response.
1452
+ * Uses ACP connection if the agent is started with ACP, otherwise falls back to CLI pipe mode.
1453
+ */
1454
+ runPrompt(name: string, prompt: string, options?: RunPromptOptions): Promise<PromptResult>;
1455
+ /**
1456
+ * Send a prompt to an agent and stream the response.
1457
+ * Uses ACP connection if available, otherwise falls back to CLI pipe mode.
1458
+ */
1459
+ streamPrompt(name: string, prompt: string, options?: RunPromptOptions): AsyncIterable<StreamChunk>;
1460
+ /**
1461
+ * Send a message to a running agent via its ACP session.
1462
+ * Unlike runPrompt, this requires the agent to be started with ACP.
1463
+ * @throws {Error} if agent has no ACP connection
1464
+ */
1465
+ promptAgent(name: string, message: string, sessionId?: string): Promise<PromptResult>;
1466
+ /** Check if an agent has an active ACP connection. */
1467
+ hasAcpConnection(name: string): boolean;
1468
+ /** Shut down the process watcher, ACP connections, and release resources. */
1469
+ dispose(): Promise<void>;
1470
+ private handleProcessExit;
1471
+ private requireAgent;
1472
+ private moveToCorrupted;
1473
+ }
1474
+
1475
+ /**
1476
+ * What the manager should do when a watched process exits.
1477
+ * - "mark-stopped": set status to stopped, clear pid (default for most modes)
1478
+ * - "restart": attempt to relaunch the process (acp-service with restart policy)
1479
+ * - "destroy": mark stopped then destroy the instance (one-shot with autoDestroy)
1480
+ */
1481
+ type ProcessExitAction = {
1482
+ type: "mark-stopped";
1483
+ } | {
1484
+ type: "restart";
1485
+ } | {
1486
+ type: "destroy";
1487
+ };
1488
+ /**
1489
+ * What the manager should do for a stale running/starting instance on daemon restart.
1490
+ * - "mark-stopped": reset status to stopped (default)
1491
+ * - "restart": attempt to relaunch (acp-service recovery)
1492
+ */
1493
+ type RecoveryAction = {
1494
+ type: "mark-stopped";
1495
+ } | {
1496
+ type: "restart";
1497
+ };
1498
+ interface LaunchModeHandler {
1499
+ readonly mode: LaunchMode;
1500
+ getProcessExitAction(instanceName: string, meta?: AgentInstanceMeta): ProcessExitAction;
1501
+ getRecoveryAction(instanceName: string): RecoveryAction;
1502
+ }
1503
+ declare function getLaunchModeHandler(mode: LaunchMode): LaunchModeHandler;
1504
+
1505
+ /**
1506
+ * Mock launcher for testing — simulates launching a process
1507
+ * by returning a fake PID without actually spawning anything.
1508
+ */
1509
+ declare class MockLauncher implements AgentLauncher {
1510
+ readonly launched: AgentProcess[];
1511
+ readonly terminated: AgentProcess[];
1512
+ launch(workspaceDir: string, meta: AgentInstanceMeta): Promise<AgentProcess>;
1513
+ terminate(process: AgentProcess): Promise<void>;
1514
+ }
1515
+
1516
+ interface ProcessLogWriterOptions {
1517
+ /** Max file size in bytes before rotation. Default: 10 MB. */
1518
+ maxSizeBytes?: number;
1519
+ /** Number of rotated files to keep. Default: 3. */
1520
+ maxFiles?: number;
1521
+ }
1522
+ /**
1523
+ * Captures stdout/stderr from a child process into log files within
1524
+ * {instanceDir}/logs/. Supports size-based log rotation.
1525
+ */
1526
+ declare class ProcessLogWriter {
1527
+ private readonly logsDir;
1528
+ private readonly maxSize;
1529
+ private readonly maxFiles;
1530
+ private stdoutStream;
1531
+ private stderrStream;
1532
+ private stdoutBytes;
1533
+ private stderrBytes;
1534
+ private closed;
1535
+ constructor(instanceDir: string, options?: ProcessLogWriterOptions);
1536
+ /**
1537
+ * Initialize the log directory and open write streams.
1538
+ * Call this before piping process streams.
1539
+ */
1540
+ initialize(): Promise<void>;
1541
+ /**
1542
+ * Attach to readable streams from a spawned process.
1543
+ */
1544
+ attach(stdout: Readable | null, stderr: Readable | null): void;
1545
+ /**
1546
+ * Close all write streams gracefully.
1547
+ */
1548
+ close(): Promise<void>;
1549
+ /**
1550
+ * Read the last N lines from a log file (stdout or stderr).
1551
+ */
1552
+ readTail(stream: "stdout" | "stderr", lines: number): Promise<string[]>;
1553
+ get logDirectory(): string;
1554
+ private rotateFile;
1555
+ private closeStream;
1556
+ }
1557
+
1558
+ interface ProcessLauncherOptions {
1559
+ /** Milliseconds to wait for graceful shutdown before SIGKILL. Default: 5000 */
1560
+ terminateTimeoutMs?: number;
1561
+ /** Milliseconds to wait after spawn to verify the process is still alive. Default: 500 */
1562
+ spawnVerifyDelayMs?: number;
1563
+ /** Enable process log capture for non-ACP backends. Default: true. */
1564
+ enableProcessLogs?: boolean;
1565
+ /** Options for process log file writer. */
1566
+ logWriterOptions?: ProcessLogWriterOptions;
1567
+ }
1568
+ /**
1569
+ * Real launcher that spawns IDE/CLI backend processes.
1570
+ *
1571
+ * Lifecycle:
1572
+ * launch() → spawn detached child → verify alive → return AgentProcess
1573
+ * terminate() → SIGTERM → wait → SIGKILL if still alive
1574
+ */
1575
+ declare class ProcessLauncher implements AgentLauncher {
1576
+ private readonly terminateTimeoutMs;
1577
+ private readonly spawnVerifyDelayMs;
1578
+ private readonly enableProcessLogs;
1579
+ private readonly logWriterOptions?;
1580
+ private readonly logWriters;
1581
+ constructor(options?: ProcessLauncherOptions);
1582
+ launch(workspaceDir: string, meta: AgentInstanceMeta): Promise<AgentProcess>;
1583
+ getLogWriter(instanceName: string): ProcessLogWriter | undefined;
1584
+ terminate(agentProcess: AgentProcess): Promise<void>;
1585
+ }
1586
+
1587
+ type LauncherMode = "mock" | "real";
1588
+ interface LauncherConfig {
1589
+ mode: LauncherMode;
1590
+ processOptions?: ProcessLauncherOptions;
1591
+ }
1592
+ /**
1593
+ * Factory function to create the appropriate AgentLauncher.
1594
+ *
1595
+ * - "mock": returns MockLauncher (for testing / development without real IDE)
1596
+ * - "real": returns ProcessLauncher (spawns actual processes)
1597
+ *
1598
+ * Default: "real" in production, can be overridden by config or env.
1599
+ */
1600
+ declare function createLauncher(config?: Partial<LauncherConfig>): AgentLauncher;
1601
+
1602
+ interface ResolvedBackend {
1603
+ command: string;
1604
+ args: string[];
1605
+ }
1606
+ /** Whether a backend type uses the ACP stdio protocol for communication. */
1607
+ declare function isAcpBackend(backendType: AgentBackendType): boolean;
1608
+ /**
1609
+ * Resolve the executable command and arguments for a given backend type.
1610
+ * Supports explicit override via `backendConfig.executablePath` and `backendConfig.args`.
1611
+ */
1612
+ declare function resolveBackend(backendType: AgentBackendType, workspaceDir: string, backendConfig?: Record<string, unknown>): ResolvedBackend;
1613
+
1614
+ /**
1615
+ * Check whether a process with the given PID is still alive.
1616
+ * Uses `kill(pid, 0)` which sends no signal but checks existence.
1617
+ */
1618
+ declare function isProcessAlive(pid: number): boolean;
1619
+
1620
+ interface ProcessExitInfo {
1621
+ instanceName: string;
1622
+ pid: number;
1623
+ }
1624
+ type ProcessExitHandler = (info: ProcessExitInfo) => void | Promise<void>;
1625
+ interface ProcessWatcherOptions {
1626
+ /** Milliseconds between alive-checks. Default: 5000 */
1627
+ pollIntervalMs?: number;
1628
+ }
1629
+ /**
1630
+ * Periodically polls tracked PIDs and fires a callback
1631
+ * when a watched process is no longer alive.
1632
+ *
1633
+ * Usage:
1634
+ * const watcher = new ProcessWatcher(onExit, { pollIntervalMs: 3000 });
1635
+ * watcher.start();
1636
+ * watcher.watch("my-agent", 12345);
1637
+ * // ... later ...
1638
+ * watcher.unwatch("my-agent"); // e.g. before intentional stop
1639
+ * watcher.dispose();
1640
+ */
1641
+ declare class ProcessWatcher {
1642
+ private readonly onProcessExit;
1643
+ private readonly watches;
1644
+ private timer;
1645
+ private polling;
1646
+ private readonly pollIntervalMs;
1647
+ constructor(onProcessExit: ProcessExitHandler, options?: ProcessWatcherOptions);
1648
+ watch(instanceName: string, pid: number): void;
1649
+ unwatch(instanceName: string): boolean;
1650
+ isWatching(instanceName: string): boolean;
1651
+ get watchCount(): number;
1652
+ start(): void;
1653
+ stop(): void;
1654
+ dispose(): void;
1655
+ get isRunning(): boolean;
1656
+ private poll;
1657
+ }
1658
+
1659
+ /**
1660
+ * Communicates with an agent via the `claude` CLI in print mode.
1661
+ * Uses `claude -p --output-format stream-json "prompt"` for streaming
1662
+ * and `claude -p --output-format json "prompt"` for one-shot.
1663
+ */
1664
+ declare class ClaudeCodeCommunicator implements AgentCommunicator {
1665
+ private readonly executable;
1666
+ constructor(executable?: string);
1667
+ runPrompt(workspaceDir: string, prompt: string, options?: RunPromptOptions): Promise<PromptResult>;
1668
+ streamPrompt(workspaceDir: string, prompt: string, options?: RunPromptOptions): AsyncIterable<StreamChunk>;
1669
+ private buildArgs;
1670
+ }
1671
+
1672
+ /**
1673
+ * Communicator stub for Cursor backend.
1674
+ * Cursor CLI does not yet support a pipe mode for programmatic communication.
1675
+ * This implementation provides a clear error until Cursor adds this capability.
1676
+ */
1677
+ declare class CursorCommunicator implements AgentCommunicator {
1678
+ runPrompt(_workspaceDir: string, _prompt: string, _options?: RunPromptOptions): Promise<PromptResult>;
1679
+ streamPrompt(_workspaceDir: string, _prompt: string, _options?: RunPromptOptions): AsyncIterable<StreamChunk>;
1680
+ }
1681
+
1682
+ declare function createCommunicator(backendType: AgentBackendType): AgentCommunicator;
1683
+
1684
+ declare function resolvePermissions(input: PermissionsInput | undefined): PermissionsConfig;
1685
+ declare function resolvePermissionsWithMcp(input: PermissionsInput | undefined, mcpServerNames: string[]): PermissionsConfig;
1686
+
1687
+ /**
1688
+ * Minimal tool information extracted from ACP RequestPermissionRequest.toolCall
1689
+ * for pattern matching against PermissionsConfig rules.
1690
+ */
1691
+ interface ToolCallInfo {
1692
+ /** ACP ToolKind: read | edit | delete | move | search | execute | think | fetch | switch_mode | other */
1693
+ kind?: string;
1694
+ /** Human-readable title, e.g. "Bash: npm run build", "Write to /src/foo.ts" */
1695
+ title?: string;
1696
+ /** Tool call ID for audit trail */
1697
+ toolCallId: string;
1698
+ }
1699
+ type PolicyAction = "allow" | "deny" | "ask";
1700
+ interface PolicyDecision {
1701
+ action: PolicyAction;
1702
+ matchedRule?: string;
1703
+ }
1704
+ /**
1705
+ * Permission policy enforcer that evaluates ACP tool calls against
1706
+ * a PermissionsConfig (allow/deny/ask lists with Claude Code glob syntax).
1707
+ *
1708
+ * Evaluation order: deny -> ask -> allow (deny wins).
1709
+ */
1710
+ declare class PermissionPolicyEnforcer {
1711
+ private config;
1712
+ constructor(config: PermissionsConfig);
1713
+ updateConfig(config: PermissionsConfig): void;
1714
+ getConfig(): Readonly<PermissionsConfig>;
1715
+ /**
1716
+ * Evaluate a tool call against the configured permission rules.
1717
+ * Order: deny > ask > allow > defaultMode fallback.
1718
+ */
1719
+ evaluate(toolCall: ToolCallInfo): PolicyDecision;
1720
+ /**
1721
+ * Build an ACP RequestPermissionOutcome from a PolicyDecision.
1722
+ * Returns the appropriate option selection based on the decision.
1723
+ */
1724
+ buildOutcome(decision: PolicyDecision, options: ReadonlyArray<{
1725
+ kind: string;
1726
+ optionId: string;
1727
+ }>): {
1728
+ outcome: "selected";
1729
+ optionId: string;
1730
+ } | {
1731
+ outcome: "cancelled";
1732
+ };
1733
+ private extractToolName;
1734
+ private extractToolArg;
1735
+ /**
1736
+ * Check if toolName+toolArg match any pattern in the list.
1737
+ * Returns the matched pattern string, or undefined.
1738
+ */
1739
+ private matchList;
1740
+ /**
1741
+ * Match a single Claude Code permission pattern against tool name + arg.
1742
+ *
1743
+ * Supported formats:
1744
+ * "*" — matches everything
1745
+ * "ToolName" — matches tool by name (case-insensitive)
1746
+ * "Tool(specifier)" — matches tool with glob specifier
1747
+ * "mcp__server" — matches MCP server prefix
1748
+ * "mcp__server__tool" — matches specific MCP tool
1749
+ */
1750
+ private matchPattern;
1751
+ private toolNameMatches;
1752
+ }
1753
+ /**
1754
+ * Simple glob matcher supporting * (match any sequence) and ** (match across path separators).
1755
+ * Sufficient for Claude Code permission patterns like "npm run *", "./src/**", "domain:*.com".
1756
+ */
1757
+ declare function globMatch(pattern: string, input: string): boolean;
1758
+
1759
+ type PermissionAuditEvent = "permission.resolved" | "permission.injected" | "permission.evaluated" | "permission.updated";
1760
+ interface AuditEntry {
1761
+ event: PermissionAuditEvent;
1762
+ instanceName?: string;
1763
+ templateName?: string;
1764
+ toolCall?: ToolCallInfo;
1765
+ decision?: PolicyDecision;
1766
+ detail?: Record<string, unknown>;
1767
+ timestamp: string;
1768
+ }
1769
+ declare class PermissionAuditLogger {
1770
+ private readonly instanceName;
1771
+ constructor(instanceName?: string);
1772
+ log(event: PermissionAuditEvent, detail?: Omit<AuditEntry, "event" | "timestamp" | "instanceName">): void;
1773
+ logEvaluation(toolCall: ToolCallInfo, decision: PolicyDecision): void;
1774
+ logResolved(templateName: string, preset?: string): void;
1775
+ logInjected(backendType: string): void;
1776
+ logUpdated(source: string): void;
1777
+ }
1778
+
1779
+ type SessionState = "active" | "idle" | "expired";
1780
+ interface SessionLease {
1781
+ sessionId: string;
1782
+ agentName: string;
1783
+ /** Currently-bound client identifier. null when idle (client disconnected). */
1784
+ clientId: string | null;
1785
+ state: SessionState;
1786
+ createdAt: string;
1787
+ lastActivityAt: string;
1788
+ /** Milliseconds of idle time before the session expires. */
1789
+ idleTtlMs: number;
1790
+ }
1791
+ interface CreateSessionOptions {
1792
+ agentName: string;
1793
+ clientId: string;
1794
+ idleTtlMs?: number;
1795
+ }
1796
+ interface SessionRegistryOptions {
1797
+ defaultIdleTtlMs?: number;
1798
+ ttlCheckIntervalMs?: number;
1799
+ }
1800
+ /**
1801
+ * In-memory registry of Session Lease objects.
1802
+ * Tracks which client owns which session, handles idle/expire transitions,
1803
+ * and runs a periodic sweep to expire stale sessions.
1804
+ */
1805
+ declare class SessionRegistry {
1806
+ private sessions;
1807
+ private sweepTimer;
1808
+ private readonly defaultIdleTtlMs;
1809
+ private onExpireCallback?;
1810
+ constructor(options?: SessionRegistryOptions);
1811
+ /** Register a callback invoked when a session expires. */
1812
+ onExpire(callback: (session: SessionLease) => void): void;
1813
+ /** Create a new session for an agent, bound to a client. */
1814
+ create(opts: CreateSessionOptions): SessionLease;
1815
+ /** Get a session by ID, or undefined if not found. */
1816
+ get(sessionId: string): SessionLease | undefined;
1817
+ /** List all sessions, optionally filtered by agent name. */
1818
+ list(agentName?: string): SessionLease[];
1819
+ /**
1820
+ * Record activity on a session, updating lastActivityAt
1821
+ * and ensuring state is "active".
1822
+ */
1823
+ touch(sessionId: string): void;
1824
+ /**
1825
+ * Mark a session as idle (client disconnected but session is kept alive).
1826
+ * The session will expire after its idleTtlMs elapses.
1827
+ */
1828
+ release(sessionId: string): void;
1829
+ /**
1830
+ * Resume an idle session, binding it to a (potentially new) client.
1831
+ * Returns false if the session is not found, expired, or already active.
1832
+ */
1833
+ resume(sessionId: string, clientId: string): boolean;
1834
+ /** Explicitly close and remove a session. */
1835
+ close(sessionId: string): boolean;
1836
+ /** Close all sessions for a given agent. */
1837
+ closeByAgent(agentName: string): number;
1838
+ /** Number of active sessions. */
1839
+ get size(): number;
1840
+ /** Stop the TTL sweep timer and clear all sessions. */
1841
+ dispose(): void;
1842
+ private sweepExpired;
1843
+ }
1844
+
1845
+ interface FetchResult {
1846
+ manifest: PackageManifest;
1847
+ skills: SkillDefinition[];
1848
+ prompts: PromptDefinition[];
1849
+ mcpServers: McpServerDefinition[];
1850
+ workflows: WorkflowDefinition[];
1851
+ presets: PresetDefinition[];
1852
+ templates: AgentTemplate[];
1853
+ }
1854
+ /**
1855
+ * Extensible interface for component sources.
1856
+ * Implement this to add new source types (GitHub, local, HTTP, npm, etc.).
1857
+ */
1858
+ interface ComponentSource {
1859
+ readonly type: string;
1860
+ readonly packageName: string;
1861
+ readonly config: SourceConfig;
1862
+ fetch(): Promise<FetchResult>;
1863
+ sync(): Promise<FetchResult>;
1864
+ dispose(): Promise<void>;
1865
+ }
1866
+
1867
+ /**
1868
+ * Fetches component packages from GitHub repositories via shallow clone.
1869
+ * After cloning, delegates to LocalSource for actual file parsing.
1870
+ */
1871
+ declare class GitHubSource implements ComponentSource {
1872
+ readonly type = "github";
1873
+ readonly packageName: string;
1874
+ readonly config: GitHubSourceConfig;
1875
+ private readonly cacheDir;
1876
+ constructor(packageName: string, config: GitHubSourceConfig, cacheDir: string);
1877
+ fetch(): Promise<FetchResult>;
1878
+ sync(): Promise<FetchResult>;
1879
+ dispose(): Promise<void>;
1880
+ private clone;
1881
+ private pull;
1882
+ private readCached;
1883
+ }
1884
+
1885
+ declare class LocalSource implements ComponentSource {
1886
+ readonly type = "local";
1887
+ readonly packageName: string;
1888
+ readonly config: LocalSourceConfig;
1889
+ constructor(packageName: string, config: LocalSourceConfig);
1890
+ fetch(): Promise<FetchResult>;
1891
+ sync(): Promise<FetchResult>;
1892
+ dispose(): Promise<void>;
1893
+ private loadPackage;
1894
+ private loadManifest;
1895
+ private loadJsonDir;
1896
+ private loadPresets;
1897
+ }
1898
+
1899
+ type ComponentTypeName = "skill" | "prompt" | "workflow" | "mcpServer" | "plugin" | "template" | "preset";
1900
+ interface ComponentVersionDelta {
1901
+ type: ComponentTypeName;
1902
+ name: string;
1903
+ oldVersion?: string;
1904
+ newVersion?: string;
1905
+ }
1906
+ interface SyncReport {
1907
+ added: ComponentVersionDelta[];
1908
+ updated: ComponentVersionDelta[];
1909
+ removed: ComponentVersionDelta[];
1910
+ unchanged: string[];
1911
+ hasBreakingChanges: boolean;
1912
+ }
1913
+
1914
+ declare const DEFAULT_SOURCE_NAME = "actant-hub";
1915
+ declare const DEFAULT_SOURCE_CONFIG: SourceConfig;
1916
+
1917
+ interface SourceManagerDeps {
1918
+ skillManager: BaseComponentManager<SkillDefinition>;
1919
+ promptManager: BaseComponentManager<PromptDefinition>;
1920
+ mcpConfigManager: BaseComponentManager<McpServerDefinition>;
1921
+ workflowManager: BaseComponentManager<WorkflowDefinition>;
1922
+ templateRegistry?: TemplateRegistry;
1923
+ }
1924
+ /**
1925
+ * Manages component sources (GitHub repos, local dirs, etc.).
1926
+ * Syncs remote components into the domain managers with `package@name` namespacing.
1927
+ */
1928
+ declare class SourceManager {
1929
+ private readonly sources;
1930
+ private readonly presets;
1931
+ private readonly managers;
1932
+ private readonly homeDir;
1933
+ private readonly sourcesFilePath;
1934
+ private readonly cacheDir;
1935
+ constructor(homeDir: string, managers: SourceManagerDeps);
1936
+ addSource(name: string, config: SourceConfig): Promise<FetchResult>;
1937
+ syncSource(name: string): Promise<FetchResult>;
1938
+ syncSourceWithReport(name: string): Promise<{
1939
+ fetchResult: FetchResult;
1940
+ report: SyncReport;
1941
+ }>;
1942
+ syncAll(): Promise<void>;
1943
+ syncAllWithReport(): Promise<{
1944
+ report: SyncReport;
1945
+ }>;
1946
+ removeSource(name: string): Promise<boolean>;
1947
+ listSources(): SourceEntry[];
1948
+ hasSource(name: string): boolean;
1949
+ listPresets(packageName?: string): PresetDefinition[];
1950
+ getPreset(qualifiedName: string): PresetDefinition | undefined;
1951
+ /**
1952
+ * Apply a preset to a template — expands preset component refs
1953
+ * into the template's domainContext with `package@name` namespacing.
1954
+ * Returns a new template (does not mutate input).
1955
+ */
1956
+ applyPreset(qualifiedName: string, template: AgentTemplate): AgentTemplate;
1957
+ initialize(): Promise<void>;
1958
+ private createSource;
1959
+ private injectComponents;
1960
+ private removeNamespacedComponents;
1961
+ private removeNamespacedPresets;
1962
+ private persistSources;
1963
+ private getSourceOrThrow;
1964
+ private snapshotComponents;
1965
+ private buildSyncReport;
1966
+ }
1967
+
1968
+ export { AgentBackendSchema, type AgentCommunicator, AgentInitializer, AgentInstanceMetaSchema, type AgentLauncher, AgentManager, type AgentProcess, AgentStatusSchema, type AgentTask, type AgentTemplateInput, type AgentTemplateOutput, AgentTemplateSchema, type AuditEntry, type BackendBuilder, BaseComponentManager, ClaudeCodeBuilder, ClaudeCodeCommunicator, type CommunicatorFactory, ComponentOriginSchema, type ComponentSource, type ComponentTypeHandler, ContextMaterializer, type CreateSessionOptions, type CronConfig, CronConfigSchema, CronInput, CursorBuilder, CursorCommunicator, CustomBuilder, type CustomBuilderConfig, DEFAULT_RESTART_POLICY, DEFAULT_SOURCE_CONFIG, DEFAULT_SOURCE_NAME, DomainContextSchema, type DomainManagers$1 as DomainManagers, EmployeeScheduler, ExecStep, ExecutionLog, type ExecutionRecord, type FetchResult, FileCopyStep, GitCloneStep, GitHubSource, type HeartbeatConfig, HeartbeatConfigSchema, HeartbeatInput, type HookConfig, HookConfigSchema, HookInput, InitializationPipeline, type InitializerOptions, InitializerSchema, InitializerStepExecutor, InitializerStepSchema, InputRouter, type InputSource, type InstanceOverrides, InstanceRegistry, type InstanceRegistryAdapter, type InstanceRegistryData, type InstanceRegistryEntry, type LaunchModeHandler, LaunchModeSchema, type LauncherConfig, type LauncherMode, LocalSource, type ManagerOptions, McpConfigManager, McpServerRefSchema, MkdirStep, MockLauncher, ModelProviderSchema, type NamedComponent, NpmInstallStep, type PermissionAuditEvent, PermissionAuditLogger, PermissionPolicyEnforcer, PermissionPresetSchema, PermissionsInputSchema, PermissionsObjectSchema, type PipelineOptions, type PipelineResult, PluginManager, type PolicyAction, type PolicyDecision, type ProcessExitAction, type ProcessExitHandler, type ProcessExitInfo, ProcessLauncher, type ProcessLauncherOptions, ProcessLogWriter, type ProcessLogWriterOptions, ProcessWatcher, type ProcessWatcherOptions, type PromptAgentFn, PromptManager, type PromptResult, type RecoveryAction, type RegistryOptions, type ResolvedBackend, type RestartDecision, type RestartPolicy, RestartTracker, type RunPromptOptions, type ScheduleConfig, type ScheduleConfigInput, ScheduleConfigSchema, type SessionLease, SessionRegistry, type SessionRegistryOptions, type SessionState, SkillManager, SourceManager, type SourceManagerDeps, type StepContext, StepRegistry, type StepResult, type StepValidationResult, type StreamChunk, type TaskCallback, TaskDispatcher, type TaskPriority, TaskQueue, type TaskStatus, TemplateFileWatcher, type TemplateFileWatcherOptions, TemplateLoader, TemplateRegistry, type ToolCallInfo, type VerifyResult, WorkflowManager, type WorkspaceBuildResult, WorkspaceBuilder, createCommunicator, createDefaultStepRegistry, createLauncher, getLaunchModeHandler, globMatch, isAcpBackend, isProcessAlive, metaFilePath, readInstanceMeta, resolveBackend, resolvePermissions, resolvePermissionsWithMcp, scanInstances, toAgentTemplate, updateInstanceMeta, validateBackendConfig, validateDomainContextConfig, validatePermissionsConfig, validateProviderConfig, validateScheduleConfig, validateTemplate, writeInstanceMeta };