@actant/core 0.2.1 → 0.2.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.
package/dist/index.js CHANGED
@@ -336,9 +336,9 @@ import { createLogger as createLogger3 } from "@actant/shared";
336
336
  // src/builder/handlers/skills-handler.ts
337
337
  var skillsHandler = {
338
338
  contextKey: "skills",
339
- resolve(refs, manager) {
339
+ resolve(refs, manager2) {
340
340
  if (!refs || !Array.isArray(refs) || refs.length === 0) return [];
341
- return manager?.resolve(refs) ?? refs.map((name) => ({ name, content: `- ${name}` }));
341
+ return manager2?.resolve(refs) ?? refs.map((name) => ({ name, content: `- ${name}` }));
342
342
  },
343
343
  async materialize(workspaceDir, definitions, _backendType, builder) {
344
344
  await builder.materializeSkills(workspaceDir, definitions);
@@ -348,9 +348,9 @@ var skillsHandler = {
348
348
  // src/builder/handlers/prompts-handler.ts
349
349
  var promptsHandler = {
350
350
  contextKey: "prompts",
351
- resolve(refs, manager) {
351
+ resolve(refs, manager2) {
352
352
  if (!refs || !Array.isArray(refs) || refs.length === 0) return [];
353
- return manager?.resolve(refs) ?? refs.map((name) => ({ name, content: `- ${name}` }));
353
+ return manager2?.resolve(refs) ?? refs.map((name) => ({ name, content: `- ${name}` }));
354
354
  },
355
355
  async materialize(workspaceDir, definitions, _backendType, builder) {
356
356
  await builder.materializePrompts(workspaceDir, definitions);
@@ -363,7 +363,7 @@ function isMcpServerRef(obj) {
363
363
  }
364
364
  var mcpServersHandler = {
365
365
  contextKey: "mcpServers",
366
- resolve(refs, manager) {
366
+ resolve(refs, manager2) {
367
367
  if (!refs || !Array.isArray(refs) || refs.length === 0) return [];
368
368
  const arr = refs;
369
369
  if (arr.every(isMcpServerRef)) {
@@ -374,7 +374,7 @@ var mcpServersHandler = {
374
374
  env: ref.env
375
375
  }));
376
376
  }
377
- return manager?.resolve(arr) ?? [];
377
+ return manager2?.resolve(arr) ?? [];
378
378
  },
379
379
  async materialize(workspaceDir, definitions, _backendType, builder) {
380
380
  await builder.materializeMcpConfig(workspaceDir, definitions);
@@ -384,11 +384,11 @@ var mcpServersHandler = {
384
384
  // src/builder/handlers/workflow-handler.ts
385
385
  var workflowHandler = {
386
386
  contextKey: "workflow",
387
- resolve(refs, manager) {
387
+ resolve(refs, manager2) {
388
388
  if (refs === void 0 || refs === null) return [];
389
389
  const name = typeof refs === "string" ? refs : Array.isArray(refs) && typeof refs[0] === "string" ? refs[0] : void 0;
390
390
  if (!name) return [];
391
- const resolved = manager?.resolve([name]);
391
+ const resolved = manager2?.resolve([name]);
392
392
  if (resolved && resolved.length > 0) return resolved;
393
393
  return [
394
394
  {
@@ -411,9 +411,9 @@ var workflowHandler = {
411
411
  // src/builder/handlers/plugins-handler.ts
412
412
  var pluginsHandler = {
413
413
  contextKey: "plugins",
414
- resolve(refs, manager) {
414
+ resolve(refs, manager2) {
415
415
  if (!refs || !Array.isArray(refs) || refs.length === 0) return [];
416
- return manager?.resolve(refs) ?? [];
416
+ return manager2?.resolve(refs) ?? [];
417
417
  },
418
418
  async materialize(workspaceDir, definitions, _backendType, builder) {
419
419
  await builder.materializePlugins(workspaceDir, definitions);
@@ -477,8 +477,8 @@ var WorkspaceBuilder = class {
477
477
  const refs = domainContext[handler.contextKey];
478
478
  if (refs === void 0 || refs === null) continue;
479
479
  if (Array.isArray(refs) && refs.length === 0) continue;
480
- const manager = this.getManager(handler.contextKey);
481
- const definitions = handler.resolve(refs, manager);
480
+ const manager2 = this.getManager(handler.contextKey);
481
+ const definitions = handler.resolve(refs, manager2);
482
482
  if (definitions.length > 0) {
483
483
  await handler.materialize(workspaceDir, definitions, backendType, activeBuilder);
484
484
  if (handler.contextKey === "mcpServers") {
@@ -1810,9 +1810,9 @@ import { createLogger as createLogger13 } from "@actant/shared";
1810
1810
  var logger12 = createLogger13("template-file-watcher");
1811
1811
  var DEFAULT_DEBOUNCE_MS = 300;
1812
1812
  var TemplateFileWatcher = class {
1813
- constructor(templatesDir, registry3, options) {
1813
+ constructor(templatesDir, registry2, options) {
1814
1814
  this.templatesDir = templatesDir;
1815
- this.registry = registry3;
1815
+ this.registry = registry2;
1816
1816
  this.debounceMs = options?.debounceMs ?? DEFAULT_DEBOUNCE_MS;
1817
1817
  }
1818
1818
  watcher = null;
@@ -1935,7 +1935,7 @@ var LaunchModeSchema = z3.enum([
1935
1935
  ]);
1936
1936
  var ProcessOwnershipSchema = z3.enum(["managed", "external"]);
1937
1937
  var WorkspacePolicySchema = z3.enum(["persistent", "ephemeral"]);
1938
- var AgentBackendTypeSchema = z3.enum(["cursor", "cursor-agent", "claude-code", "custom", "pi"]);
1938
+ var AgentBackendTypeSchema = z3.string().min(1);
1939
1939
  var PermissionModeSchema2 = z3.enum([
1940
1940
  "default",
1941
1941
  "acceptEdits",
@@ -2044,12 +2044,12 @@ async function updateInstanceMeta(workspaceDir, patch) {
2044
2044
  await writeInstanceMeta(workspaceDir, updated);
2045
2045
  return updated;
2046
2046
  }
2047
- async function scanInstances(instancesBaseDir, registry3) {
2047
+ async function scanInstances(instancesBaseDir, registry2) {
2048
2048
  const valid = [];
2049
2049
  const corrupted = [];
2050
2050
  const validNames = /* @__PURE__ */ new Set();
2051
- if (registry3) {
2052
- for (const entry of registry3.list()) {
2051
+ if (registry2) {
2052
+ for (const entry of registry2.list()) {
2053
2053
  if (entry.status === "orphaned") continue;
2054
2054
  try {
2055
2055
  const st = await stat5(entry.workspacePath);
@@ -2240,8 +2240,8 @@ var logger14 = createLogger15("initialization-pipeline");
2240
2240
  var DEFAULT_STEP_TIMEOUT_MS = 6e4;
2241
2241
  var DEFAULT_TOTAL_TIMEOUT_MS = 3e5;
2242
2242
  var InitializationPipeline = class {
2243
- constructor(registry3, options) {
2244
- this.registry = registry3;
2243
+ constructor(registry2, options) {
2244
+ this.registry = registry2;
2245
2245
  this.stepTimeoutMs = options?.defaultStepTimeoutMs ?? DEFAULT_STEP_TIMEOUT_MS;
2246
2246
  this.totalTimeoutMs = options?.totalTimeoutMs ?? DEFAULT_TOTAL_TIMEOUT_MS;
2247
2247
  this.onProgress = options?.onProgress;
@@ -2591,7 +2591,7 @@ var ContextMaterializer = class {
2591
2591
  this.managers = managers;
2592
2592
  }
2593
2593
  async materialize(workspaceDir, domainContext, backendType = "cursor") {
2594
- const configDir = BACKEND_CONFIG_DIR[backendType];
2594
+ const configDir = BACKEND_CONFIG_DIR[backendType] ?? ".cursor";
2595
2595
  const tasks = [];
2596
2596
  if (domainContext.skills && domainContext.skills.length > 0) {
2597
2597
  tasks.push(this.materializeSkills(workspaceDir, domainContext.skills));
@@ -2992,10 +2992,10 @@ var NpmInstallStep = class extends InitializerStepExecutor {
2992
2992
  return { valid: issues.length === 0, issues };
2993
2993
  }
2994
2994
  async execute(context, config) {
2995
- const { packageManager = "npm", cwd = ".", args = [], registry: registry3 } = config;
2995
+ const { packageManager = "npm", cwd = ".", args = [], registry: registry2 } = config;
2996
2996
  const workDir = join16(context.workspaceDir, cwd);
2997
2997
  const cmdArgs = ["install", ...args];
2998
- if (registry3) cmdArgs.push("--registry", registry3);
2998
+ if (registry2) cmdArgs.push("--registry", registry2);
2999
2999
  context.logger.debug({ packageManager, cwd: workDir, args: cmdArgs }, "Installing dependencies");
3000
3000
  const result = await runInstall(packageManager, cmdArgs, workDir);
3001
3001
  if (result.exitCode !== 0) {
@@ -3037,13 +3037,13 @@ function runInstall(pm, args, cwd) {
3037
3037
 
3038
3038
  // src/initializer/steps/index.ts
3039
3039
  function createDefaultStepRegistry() {
3040
- const registry3 = new StepRegistry();
3041
- registry3.register(new MkdirStep());
3042
- registry3.register(new ExecStep());
3043
- registry3.register(new FileCopyStep());
3044
- registry3.register(new GitCloneStep());
3045
- registry3.register(new NpmInstallStep());
3046
- return registry3;
3040
+ const registry2 = new StepRegistry();
3041
+ registry2.register(new MkdirStep());
3042
+ registry2.register(new ExecStep());
3043
+ registry2.register(new FileCopyStep());
3044
+ registry2.register(new GitCloneStep());
3045
+ registry2.register(new NpmInstallStep());
3046
+ return registry2;
3047
3047
  }
3048
3048
 
3049
3049
  // src/manager/agent-manager.ts
@@ -3059,69 +3059,272 @@ import {
3059
3059
  createLogger as createLogger24
3060
3060
  } from "@actant/shared";
3061
3061
 
3062
+ // src/domain/backend/backend-manager.ts
3063
+ import { execFile } from "child_process";
3064
+
3065
+ // src/domain/backend/backend-schema.ts
3066
+ import { z as z4 } from "zod/v4";
3067
+ var PlatformCommandSchema = z4.object({
3068
+ win32: z4.string().min(1),
3069
+ default: z4.string().min(1)
3070
+ });
3071
+ var OpenSpawnOptionsSchema = z4.object({
3072
+ stdio: z4.enum(["inherit", "ignore"]).optional(),
3073
+ detached: z4.boolean().optional(),
3074
+ windowsHide: z4.boolean().optional(),
3075
+ shell: z4.boolean().optional()
3076
+ });
3077
+ var ExistenceCheckSchema = z4.object({
3078
+ command: z4.string().min(1),
3079
+ args: z4.array(z4.string()).optional(),
3080
+ expectedExitCode: z4.number().int().optional(),
3081
+ versionPattern: z4.string().optional()
3082
+ });
3083
+ var InstallMethodSchema = z4.object({
3084
+ type: z4.enum(["npm", "brew", "winget", "choco", "url", "manual"]),
3085
+ package: z4.string().optional(),
3086
+ platforms: z4.array(z4.string()).optional(),
3087
+ label: z4.string().optional(),
3088
+ instructions: z4.string().optional()
3089
+ });
3090
+ var BackendDefinitionSchema = z4.object({
3091
+ name: z4.string().min(1),
3092
+ version: z4.string().optional(),
3093
+ description: z4.string().optional(),
3094
+ tags: z4.array(z4.string()).optional(),
3095
+ supportedModes: z4.array(z4.enum(["resolve", "open", "acp"])).min(1),
3096
+ resolveCommand: PlatformCommandSchema.optional(),
3097
+ openCommand: PlatformCommandSchema.optional(),
3098
+ acpCommand: PlatformCommandSchema.optional(),
3099
+ acpOwnsProcess: z4.boolean().optional(),
3100
+ resolvePackage: z4.string().optional(),
3101
+ openWorkspaceDir: z4.enum(["arg", "cwd"]).optional(),
3102
+ openSpawnOptions: OpenSpawnOptionsSchema.optional(),
3103
+ existenceCheck: ExistenceCheckSchema.optional(),
3104
+ install: z4.array(InstallMethodSchema).optional()
3105
+ }).passthrough();
3106
+
3107
+ // src/domain/backend/backend-manager.ts
3108
+ var BackendManager = class extends BaseComponentManager {
3109
+ componentType = "Backend";
3110
+ acpResolvers = /* @__PURE__ */ new Map();
3111
+ constructor() {
3112
+ super("backend-manager");
3113
+ }
3114
+ // ---------------------------------------------------------------------------
3115
+ // ACP resolver (behavioral extension, not serializable)
3116
+ // ---------------------------------------------------------------------------
3117
+ registerAcpResolver(backendName, resolver) {
3118
+ this.acpResolvers.set(backendName, resolver);
3119
+ }
3120
+ getAcpResolver(backendName) {
3121
+ return this.acpResolvers.get(backendName);
3122
+ }
3123
+ // ---------------------------------------------------------------------------
3124
+ // Mode queries
3125
+ // ---------------------------------------------------------------------------
3126
+ supportsMode(backendName, mode) {
3127
+ const def = this.get(backendName);
3128
+ return def != null && def.supportedModes.includes(mode);
3129
+ }
3130
+ requireMode(backendName, mode) {
3131
+ const def = this.get(backendName);
3132
+ if (!def) {
3133
+ throw new Error(
3134
+ `Backend "${backendName}" is not registered. Ensure the backend package is installed and its definition was loaded at startup.`
3135
+ );
3136
+ }
3137
+ if (!def.supportedModes.includes(mode)) {
3138
+ const supported = def.supportedModes.join(", ");
3139
+ throw new Error(
3140
+ `Backend "${backendName}" does not support "${mode}" mode. Supported modes: [${supported}]. ` + (mode === "resolve" ? `Use \`agent start\` or \`agent run\` instead.` : mode === "open" ? `This backend has no native TUI/UI to open.` : `Use \`agent resolve\` or \`agent open\` instead.`)
3141
+ );
3142
+ }
3143
+ }
3144
+ // ---------------------------------------------------------------------------
3145
+ // Platform command helper
3146
+ // ---------------------------------------------------------------------------
3147
+ getPlatformCommand(cmd) {
3148
+ return process.platform === "win32" ? cmd.win32 : cmd.default;
3149
+ }
3150
+ // ---------------------------------------------------------------------------
3151
+ // Availability check
3152
+ // ---------------------------------------------------------------------------
3153
+ /**
3154
+ * Probe whether a backend binary is available on the system.
3155
+ * Uses the `existenceCheck` field. Returns `{ available, version? }`.
3156
+ * If no `existenceCheck` is configured, returns `{ available: true }` (assume ok).
3157
+ */
3158
+ async checkAvailability(backendName) {
3159
+ const def = this.get(backendName);
3160
+ if (!def) return { available: false, error: `Backend "${backendName}" not registered` };
3161
+ if (!def.existenceCheck) return { available: true };
3162
+ const { command, args = ["--version"], expectedExitCode = 0, versionPattern } = def.existenceCheck;
3163
+ try {
3164
+ const { stdout, exitCode } = await execCommand(command, args);
3165
+ if (exitCode !== expectedExitCode) {
3166
+ return { available: false, error: `Exit code ${exitCode} (expected ${expectedExitCode})` };
3167
+ }
3168
+ if (versionPattern) {
3169
+ const match = new RegExp(versionPattern).exec(stdout);
3170
+ if (!match) {
3171
+ return { available: false, error: `Version output didn't match pattern: ${versionPattern}` };
3172
+ }
3173
+ return { available: true, version: match[0] };
3174
+ }
3175
+ const version = stdout.trim().split("\n")[0];
3176
+ return { available: true, version: version || void 0 };
3177
+ } catch (err) {
3178
+ return { available: false, error: err.message };
3179
+ }
3180
+ }
3181
+ /**
3182
+ * Get platform-appropriate install methods for a backend.
3183
+ * Filters by `platforms` field; returns all methods if no platform restriction.
3184
+ */
3185
+ getInstallMethods(backendName) {
3186
+ const def = this.get(backendName);
3187
+ if (!def?.install) return [];
3188
+ const plat = process.platform;
3189
+ return def.install.filter((m) => !m.platforms || m.platforms.includes(plat));
3190
+ }
3191
+ // ---------------------------------------------------------------------------
3192
+ // Validation
3193
+ // ---------------------------------------------------------------------------
3194
+ validate(data, _source) {
3195
+ const result = BackendDefinitionSchema.safeParse(data);
3196
+ if (!result.success) {
3197
+ return {
3198
+ valid: false,
3199
+ errors: result.error.issues.map((i) => ({
3200
+ path: i.path.map(String).join("."),
3201
+ message: i.message,
3202
+ severity: "error"
3203
+ })),
3204
+ warnings: []
3205
+ };
3206
+ }
3207
+ return { valid: true, data: result.data, errors: [], warnings: [] };
3208
+ }
3209
+ };
3210
+ function execCommand(command, args) {
3211
+ return new Promise((resolve3) => {
3212
+ execFile(command, args, { timeout: 1e4, windowsHide: true }, (err, stdout) => {
3213
+ if (err && typeof err.code === "string" && err.code === "ENOENT") {
3214
+ resolve3({ stdout: "", exitCode: -1 });
3215
+ return;
3216
+ }
3217
+ const exitCode = err && "code" in err && typeof err.code === "number" ? err.code : err ? 1 : 0;
3218
+ resolve3({ stdout: stdout ?? "", exitCode });
3219
+ });
3220
+ });
3221
+ }
3222
+
3062
3223
  // src/manager/launcher/backend-registry.ts
3063
- var registry = /* @__PURE__ */ new Map();
3224
+ var manager = new BackendManager();
3225
+ function getBackendManager() {
3226
+ return manager;
3227
+ }
3064
3228
  function registerBackend(descriptor) {
3065
- registry.set(descriptor.type, descriptor);
3229
+ const { type, acpResolver, ...rest } = descriptor;
3230
+ const definition = { ...rest, name: type };
3231
+ manager.register(definition);
3232
+ if (acpResolver) {
3233
+ manager.registerAcpResolver(type, acpResolver);
3234
+ }
3235
+ }
3236
+ function registerBackendDefinition(definition) {
3237
+ manager.register(definition);
3066
3238
  }
3067
3239
  function getBackendDescriptor(type) {
3068
- const desc = registry.get(type);
3069
- if (!desc) {
3240
+ const def = manager.get(type);
3241
+ if (!def) {
3070
3242
  throw new Error(
3071
3243
  `Backend "${type}" is not registered. Ensure the backend package is installed and registerBackend() was called at startup.`
3072
3244
  );
3073
3245
  }
3074
- return desc;
3246
+ return def;
3075
3247
  }
3076
3248
  function supportsMode(type, mode) {
3077
- const desc = registry.get(type);
3078
- return desc != null && desc.supportedModes.includes(mode);
3249
+ return manager.supportsMode(type, mode);
3079
3250
  }
3080
3251
  function requireMode(type, mode) {
3081
- const desc = getBackendDescriptor(type);
3082
- if (!desc.supportedModes.includes(mode)) {
3083
- const supported = desc.supportedModes.join(", ");
3084
- throw new Error(
3085
- `Backend "${type}" does not support "${mode}" mode. Supported modes: [${supported}]. ` + (mode === "resolve" ? `Use \`agent start\` or \`agent run\` instead.` : mode === "open" ? `This backend has no native TUI/UI to open.` : `Use \`agent resolve\` or \`agent open\` instead.`)
3086
- );
3087
- }
3252
+ manager.requireMode(type, mode);
3088
3253
  }
3089
3254
  function getPlatformCommand(cmd) {
3090
- return process.platform === "win32" ? cmd.win32 : cmd.default;
3255
+ return manager.getPlatformCommand(cmd);
3091
3256
  }
3092
- var installHints = /* @__PURE__ */ new Map([
3093
- ["claude-code", "npm install -g @zed-industries/claude-agent-acp"],
3094
- ["cursor", "Install Cursor from https://cursor.com"],
3095
- ["cursor-agent", "Install Cursor from https://cursor.com"]
3096
- ]);
3097
3257
  function getInstallHint(type) {
3098
- return installHints.get(type);
3258
+ const methods = manager.getInstallMethods(type);
3259
+ const first = methods[0];
3260
+ return first?.label ?? first?.instructions;
3261
+ }
3262
+ function getAcpResolver(type) {
3263
+ return manager.getAcpResolver(type);
3099
3264
  }
3100
3265
 
3101
3266
  // src/manager/launcher/builtin-backends.ts
3102
- function registerBuiltinBackends() {
3103
- registerBackend({
3104
- type: "cursor",
3267
+ var BUILTIN_BACKENDS = [
3268
+ {
3269
+ name: "cursor",
3270
+ version: "1.0.0",
3271
+ description: "Cursor IDE",
3272
+ origin: { type: "builtin" },
3105
3273
  supportedModes: ["resolve", "open"],
3106
3274
  resolveCommand: { win32: "cursor.cmd", default: "cursor" },
3107
- openCommand: { win32: "cursor.cmd", default: "cursor" }
3108
- });
3109
- registerBackend({
3110
- type: "cursor-agent",
3275
+ openCommand: { win32: "cursor.cmd", default: "cursor" },
3276
+ openSpawnOptions: { shell: process.platform === "win32" },
3277
+ existenceCheck: { command: "cursor", args: ["--version"] },
3278
+ install: [
3279
+ { type: "url", package: "https://cursor.com", label: "Download Cursor", platforms: ["win32", "darwin", "linux"] },
3280
+ { type: "brew", package: "cursor", label: "brew install --cask cursor", platforms: ["darwin"] },
3281
+ { type: "winget", package: "Anysphere.Cursor", label: "winget install Anysphere.Cursor", platforms: ["win32"] }
3282
+ ]
3283
+ },
3284
+ {
3285
+ name: "cursor-agent",
3286
+ version: "1.0.0",
3287
+ description: "Cursor Agent (TUI)",
3288
+ origin: { type: "builtin" },
3111
3289
  supportedModes: ["resolve", "open", "acp"],
3112
- resolveCommand: { win32: "cursor.cmd", default: "cursor" },
3113
- openCommand: { win32: "cursor.cmd", default: "cursor" }
3114
- });
3115
- registerBackend({
3116
- type: "claude-code",
3290
+ resolveCommand: { win32: "agent", default: "agent" },
3291
+ openCommand: { win32: "agent", default: "agent" },
3292
+ openWorkspaceDir: "cwd",
3293
+ openSpawnOptions: { stdio: "inherit", detached: false, windowsHide: false },
3294
+ existenceCheck: { command: "agent", args: ["--version"] },
3295
+ install: [
3296
+ { type: "manual", label: "Included with Cursor", instructions: "Install Cursor from https://cursor.com \u2014 the `agent` CLI is bundled." }
3297
+ ]
3298
+ },
3299
+ {
3300
+ name: "claude-code",
3301
+ version: "1.0.0",
3302
+ description: "Claude Code CLI",
3303
+ origin: { type: "builtin" },
3117
3304
  supportedModes: ["resolve", "open", "acp"],
3118
3305
  resolveCommand: { win32: "claude-agent-acp.cmd", default: "claude-agent-acp" },
3119
- openCommand: { win32: "claude.cmd", default: "claude" }
3120
- });
3121
- registerBackend({
3122
- type: "custom",
3306
+ openCommand: { win32: "claude.exe", default: "claude" },
3307
+ openWorkspaceDir: "cwd",
3308
+ openSpawnOptions: { stdio: "inherit", detached: false, windowsHide: false },
3309
+ resolvePackage: "@zed-industries/claude-agent-acp",
3310
+ existenceCheck: { command: "claude", args: ["--version"] },
3311
+ install: [
3312
+ { type: "npm", package: "@anthropic-ai/claude-code", label: "npm install -g @anthropic-ai/claude-code" }
3313
+ ]
3314
+ },
3315
+ {
3316
+ name: "custom",
3317
+ version: "1.0.0",
3318
+ description: "Custom backend (user-provided executable)",
3319
+ origin: { type: "builtin" },
3123
3320
  supportedModes: ["resolve"]
3124
- });
3321
+ }
3322
+ ];
3323
+ function registerBuiltinBackends() {
3324
+ const mgr = getBackendManager();
3325
+ for (const def of BUILTIN_BACKENDS) {
3326
+ mgr.register(def);
3327
+ }
3125
3328
  }
3126
3329
  registerBuiltinBackends();
3127
3330
 
@@ -3157,25 +3360,36 @@ function resolveBackend(backendType, workspaceDir, backendConfig) {
3157
3360
  })();
3158
3361
  return {
3159
3362
  command,
3160
- args: buildArgs(backendType, workspaceDir, backendConfig)
3363
+ args: buildArgs(backendType, workspaceDir, backendConfig),
3364
+ resolvePackage: desc.resolvePackage
3161
3365
  };
3162
3366
  }
3367
+ var DEFAULT_OPEN_SPAWN = {
3368
+ stdio: "ignore",
3369
+ detached: true,
3370
+ windowsHide: true,
3371
+ shell: false
3372
+ };
3163
3373
  function openBackend(backendType, workspaceDir) {
3164
3374
  requireMode(backendType, "open");
3165
3375
  const desc = getBackendDescriptor(backendType);
3166
3376
  if (!desc.openCommand) {
3167
3377
  throw new Error(`Backend "${backendType}" has no openCommand configured.`);
3168
3378
  }
3379
+ const useCwd = desc.openWorkspaceDir === "cwd";
3169
3380
  return {
3170
3381
  command: getPlatformCommand(desc.openCommand),
3171
- args: [workspaceDir]
3382
+ args: useCwd ? [] : [workspaceDir],
3383
+ cwd: useCwd ? workspaceDir : void 0,
3384
+ openSpawnOptions: { ...DEFAULT_OPEN_SPAWN, ...desc.openSpawnOptions }
3172
3385
  };
3173
3386
  }
3174
3387
  function resolveAcpBackend(backendType, workspaceDir, backendConfig) {
3175
3388
  requireMode(backendType, "acp");
3176
3389
  const desc = getBackendDescriptor(backendType);
3177
- if (desc.acpResolver) {
3178
- return desc.acpResolver(workspaceDir, backendConfig);
3390
+ const resolver = getAcpResolver(backendType);
3391
+ if (resolver) {
3392
+ return resolver(workspaceDir, backendConfig);
3179
3393
  }
3180
3394
  const explicitPath = backendConfig?.executablePath;
3181
3395
  const commandSource = desc.acpCommand ?? desc.resolveCommand;
@@ -3184,7 +3398,8 @@ function resolveAcpBackend(backendType, workspaceDir, backendConfig) {
3184
3398
  })();
3185
3399
  return {
3186
3400
  command,
3187
- args: buildArgs(backendType, workspaceDir, backendConfig)
3401
+ args: buildArgs(backendType, workspaceDir, backendConfig),
3402
+ resolvePackage: desc.resolvePackage
3188
3403
  };
3189
3404
  }
3190
3405
 
@@ -3433,7 +3648,8 @@ var ClaudeCodeCommunicator = class {
3433
3648
  const child = spawn4(this.executable, args, {
3434
3649
  cwd: workspaceDir,
3435
3650
  stdio: ["pipe", "pipe", "pipe"],
3436
- env: { ...process.env }
3651
+ env: { ...process.env },
3652
+ windowsHide: true
3437
3653
  });
3438
3654
  let stdout = "";
3439
3655
  let stderr = "";
@@ -3469,11 +3685,18 @@ var ClaudeCodeCommunicator = class {
3469
3685
  } else if (subtype === "error_max_turns") {
3470
3686
  text = "[max turns reached \u2014 no final result text]";
3471
3687
  } else {
3472
- text = stdout.trim();
3688
+ const costUsd = parsed["cost_usd"];
3689
+ const duration = parsed["duration_ms"];
3690
+ const parts = ["[no result text]"];
3691
+ if (subtype) parts.push(`subtype=${subtype}`);
3692
+ if (costUsd != null) parts.push(`cost=$${costUsd.toFixed(4)}`);
3693
+ if (duration != null) parts.push(`duration=${duration}ms`);
3694
+ text = parts.join(" ");
3473
3695
  }
3474
3696
  resolve3({ text, sessionId });
3475
3697
  } catch {
3476
- resolve3({ text: stdout.trim() });
3698
+ const firstLine = stdout.slice(0, 200).split("\n")[0] ?? "";
3699
+ resolve3({ text: firstLine || "[unparseable response]" });
3477
3700
  }
3478
3701
  });
3479
3702
  child.on("error", (err) => {
@@ -3489,7 +3712,8 @@ var ClaudeCodeCommunicator = class {
3489
3712
  const child = spawn4(this.executable, args, {
3490
3713
  cwd: workspaceDir,
3491
3714
  stdio: ["pipe", "pipe", "pipe"],
3492
- env: { ...process.env }
3715
+ env: { ...process.env },
3716
+ windowsHide: true
3493
3717
  });
3494
3718
  const timeout = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
3495
3719
  const timer = setTimeout(() => {
@@ -3600,12 +3824,12 @@ var CursorCommunicator = class {
3600
3824
  };
3601
3825
 
3602
3826
  // src/communicator/create-communicator.ts
3603
- var registry2 = /* @__PURE__ */ new Map();
3827
+ var registry = /* @__PURE__ */ new Map();
3604
3828
  function registerCommunicator(backendType, factory) {
3605
- registry2.set(backendType, factory);
3829
+ registry.set(backendType, factory);
3606
3830
  }
3607
3831
  function createCommunicator(backendType, backendConfig) {
3608
- const registered = registry2.get(backendType);
3832
+ const registered = registry.get(backendType);
3609
3833
  if (registered) return registered(backendConfig);
3610
3834
  switch (backendType) {
3611
3835
  case "claude-code":
@@ -3613,13 +3837,9 @@ function createCommunicator(backendType, backendConfig) {
3613
3837
  case "cursor":
3614
3838
  case "cursor-agent":
3615
3839
  return new CursorCommunicator();
3616
- case "custom":
3617
- throw new Error(
3618
- "Custom backend communicator not yet supported. Implement AgentCommunicator for your backend."
3619
- );
3620
- case "pi":
3840
+ default:
3621
3841
  throw new Error(
3622
- "Pi backend communicator not registered. Ensure @actant/pi is installed and initialized."
3842
+ `No communicator registered for backend "${backendType}". Register one via registerCommunicator() at startup.`
3623
3843
  );
3624
3844
  }
3625
3845
  }
@@ -3738,12 +3958,13 @@ var AgentManager = class {
3738
3958
  pid = proc.pid;
3739
3959
  }
3740
3960
  if (this.acpManager) {
3741
- const { command, args } = resolveAcpBackend(meta.backendType, dir, meta.backendConfig);
3961
+ const acpResolved = resolveAcpBackend(meta.backendType, dir, meta.backendConfig);
3742
3962
  const providerEnv = buildProviderEnv(meta.providerConfig);
3743
3963
  const connResult = await this.acpManager.connect(name, {
3744
- command,
3745
- args,
3964
+ command: acpResolved.command,
3965
+ args: acpResolved.args,
3746
3966
  cwd: dir,
3967
+ resolvePackage: acpResolved.resolvePackage,
3747
3968
  connectionOptions: {
3748
3969
  autoApprove: true,
3749
3970
  ...Object.keys(providerEnv).length > 0 ? { env: providerEnv } : {}
@@ -3853,14 +4074,15 @@ var AgentManager = class {
3853
4074
  throw new AgentNotFoundError(name);
3854
4075
  }
3855
4076
  const dir = join17(this.instancesBaseDir, name);
3856
- const { command, args } = resolveBackend(meta.backendType, dir, meta.backendConfig);
4077
+ const resolved = resolveBackend(meta.backendType, dir, meta.backendConfig);
3857
4078
  return {
3858
4079
  workspaceDir: dir,
3859
- command,
3860
- args,
4080
+ command: resolved.command,
4081
+ args: resolved.args,
3861
4082
  instanceName: name,
3862
4083
  backendType: meta.backendType,
3863
- created
4084
+ created,
4085
+ resolvePackage: resolved.resolvePackage
3864
4086
  };
3865
4087
  }
3866
4088
  /**
@@ -3871,8 +4093,7 @@ var AgentManager = class {
3871
4093
  async openAgent(name) {
3872
4094
  const meta = this.requireAgent(name);
3873
4095
  const dir = join17(this.instancesBaseDir, name);
3874
- const resolved = openBackend(meta.backendType, dir);
3875
- return resolved;
4096
+ return openBackend(meta.backendType, dir);
3876
4097
  }
3877
4098
  /**
3878
4099
  * Register an externally-spawned process with the manager.
@@ -4444,15 +4665,15 @@ function createLauncher(config) {
4444
4665
  }
4445
4666
 
4446
4667
  // src/domain/skill/skill-manager.ts
4447
- import { z as z4 } from "zod/v4";
4448
- var SkillDefinitionSchema = z4.object({
4449
- name: z4.string().min(1),
4450
- description: z4.string().optional(),
4451
- content: z4.string().min(1),
4452
- tags: z4.array(z4.string()).optional(),
4453
- license: z4.string().optional(),
4454
- compatibility: z4.string().optional(),
4455
- allowedTools: z4.array(z4.string()).optional()
4668
+ import { z as z5 } from "zod/v4";
4669
+ var SkillDefinitionSchema = z5.object({
4670
+ name: z5.string().min(1),
4671
+ description: z5.string().optional(),
4672
+ content: z5.string().min(1),
4673
+ tags: z5.array(z5.string()).optional(),
4674
+ license: z5.string().optional(),
4675
+ compatibility: z5.string().optional(),
4676
+ allowedTools: z5.array(z5.string()).optional()
4456
4677
  }).passthrough();
4457
4678
  var SkillManager = class extends BaseComponentManager {
4458
4679
  componentType = "Skill";
@@ -4492,12 +4713,12 @@ ${sections.join("\n\n---\n\n")}
4492
4713
  };
4493
4714
 
4494
4715
  // src/domain/prompt/prompt-manager.ts
4495
- import { z as z5 } from "zod/v4";
4496
- var PromptDefinitionSchema = z5.object({
4497
- name: z5.string().min(1),
4498
- description: z5.string().optional(),
4499
- content: z5.string().min(1),
4500
- variables: z5.array(z5.string()).optional()
4716
+ import { z as z6 } from "zod/v4";
4717
+ var PromptDefinitionSchema = z6.object({
4718
+ name: z6.string().min(1),
4719
+ description: z6.string().optional(),
4720
+ content: z6.string().min(1),
4721
+ variables: z6.array(z6.string()).optional()
4501
4722
  }).passthrough();
4502
4723
  var PromptManager = class extends BaseComponentManager {
4503
4724
  componentType = "Prompt";
@@ -4549,13 +4770,13 @@ ${sections.join("\n\n---\n\n")}
4549
4770
  };
4550
4771
 
4551
4772
  // src/domain/mcp/mcp-config-manager.ts
4552
- import { z as z6 } from "zod/v4";
4553
- var McpServerDefinitionSchema = z6.object({
4554
- name: z6.string().min(1),
4555
- description: z6.string().optional(),
4556
- command: z6.string().min(1),
4557
- args: z6.array(z6.string()).optional(),
4558
- env: z6.record(z6.string(), z6.string()).optional()
4773
+ import { z as z7 } from "zod/v4";
4774
+ var McpServerDefinitionSchema = z7.object({
4775
+ name: z7.string().min(1),
4776
+ description: z7.string().optional(),
4777
+ command: z7.string().min(1),
4778
+ args: z7.array(z7.string()).optional(),
4779
+ env: z7.record(z7.string(), z7.string()).optional()
4559
4780
  }).passthrough();
4560
4781
  var McpConfigManager = class extends BaseComponentManager {
4561
4782
  componentType = "McpServer";
@@ -4595,11 +4816,11 @@ var McpConfigManager = class extends BaseComponentManager {
4595
4816
  };
4596
4817
 
4597
4818
  // src/domain/workflow/workflow-manager.ts
4598
- import { z as z7 } from "zod/v4";
4599
- var WorkflowDefinitionSchema = z7.object({
4600
- name: z7.string().min(1),
4601
- description: z7.string().optional(),
4602
- content: z7.string().min(1)
4819
+ import { z as z8 } from "zod/v4";
4820
+ var WorkflowDefinitionSchema = z8.object({
4821
+ name: z8.string().min(1),
4822
+ description: z8.string().optional(),
4823
+ content: z8.string().min(1)
4603
4824
  }).passthrough();
4604
4825
  var WorkflowManager = class extends BaseComponentManager {
4605
4826
  componentType = "Workflow";
@@ -4628,14 +4849,14 @@ var WorkflowManager = class extends BaseComponentManager {
4628
4849
  };
4629
4850
 
4630
4851
  // src/domain/plugin/plugin-manager.ts
4631
- import { z as z8 } from "zod/v4";
4632
- var PluginDefinitionSchema = z8.object({
4633
- name: z8.string().min(1),
4634
- description: z8.string().optional(),
4635
- type: z8.enum(["npm", "file", "config"]),
4636
- source: z8.string().optional(),
4637
- config: z8.record(z8.string(), z8.unknown()).optional(),
4638
- enabled: z8.boolean().optional().default(true)
4852
+ import { z as z9 } from "zod/v4";
4853
+ var PluginDefinitionSchema = z9.object({
4854
+ name: z9.string().min(1),
4855
+ description: z9.string().optional(),
4856
+ type: z9.enum(["npm", "file", "config"]),
4857
+ source: z9.string().optional(),
4858
+ config: z9.record(z9.string(), z9.unknown()).optional(),
4859
+ enabled: z9.boolean().optional().default(true)
4639
4860
  }).passthrough();
4640
4861
  var PluginManager = class extends BaseComponentManager {
4641
4862
  componentType = "Plugin";
@@ -5023,7 +5244,7 @@ var SessionRegistry = class {
5023
5244
  // src/source/github-source.ts
5024
5245
  import { join as join20 } from "path";
5025
5246
  import { mkdir as mkdir13, rm as rm5 } from "fs/promises";
5026
- import { execFile } from "child_process";
5247
+ import { execFile as execFile2 } from "child_process";
5027
5248
  import { promisify } from "util";
5028
5249
  import { createLogger as createLogger31 } from "@actant/shared";
5029
5250
 
@@ -5054,16 +5275,17 @@ var LocalSource = class {
5054
5275
  async loadPackage() {
5055
5276
  const rootDir = this.config.path;
5056
5277
  const manifest = await this.loadManifest(rootDir);
5057
- const [skills, prompts, mcpServers, workflows, presets, templates] = await Promise.all([
5278
+ const [skills, prompts, mcpServers, workflows, backends, presets, templates] = await Promise.all([
5058
5279
  this.loadJsonDir(rootDir, manifest.components?.skills, "skills"),
5059
5280
  this.loadJsonDir(rootDir, manifest.components?.prompts, "prompts"),
5060
5281
  this.loadJsonDir(rootDir, manifest.components?.mcp, "mcp"),
5061
5282
  this.loadJsonDir(rootDir, manifest.components?.workflows, "workflows"),
5283
+ this.loadJsonDir(rootDir, manifest.components?.backends, "backends"),
5062
5284
  this.loadPresets(rootDir, manifest.presets),
5063
5285
  this.loadJsonDir(rootDir, manifest.components?.templates, "templates")
5064
5286
  ]);
5065
5287
  logger29.info({ packageName: this.packageName, rootDir }, "Local package loaded");
5066
- return { manifest, skills, prompts, mcpServers, workflows, presets, templates };
5288
+ return { manifest, skills, prompts, mcpServers, workflows, backends, presets, templates };
5067
5289
  }
5068
5290
  async loadManifest(rootDir) {
5069
5291
  const manifestPath = join19(rootDir, "actant.json");
@@ -5155,7 +5377,7 @@ var LocalSource = class {
5155
5377
  };
5156
5378
 
5157
5379
  // src/source/github-source.ts
5158
- var execFileAsync = promisify(execFile);
5380
+ var execFileAsync = promisify(execFile2);
5159
5381
  var logger30 = createLogger31("github-source");
5160
5382
  var GitHubSource = class {
5161
5383
  type = "github";
@@ -5449,6 +5671,11 @@ var SourceManager = class {
5449
5671
  for (const wf of result.workflows) {
5450
5672
  this.managers.workflowManager.register(ns(wf));
5451
5673
  }
5674
+ if (this.managers.backendManager) {
5675
+ for (const backend of result.backends) {
5676
+ this.managers.backendManager.register(ns(backend));
5677
+ }
5678
+ }
5452
5679
  for (const preset of result.presets) {
5453
5680
  this.presets.set(`${packageName}@${preset.name}`, preset);
5454
5681
  }
@@ -5477,6 +5704,7 @@ var SourceManager = class {
5477
5704
  prompts: result.prompts.length,
5478
5705
  mcp: result.mcpServers.length,
5479
5706
  workflows: result.workflows.length,
5707
+ backends: result.backends.length,
5480
5708
  presets: result.presets.length,
5481
5709
  templates: result.templates.length
5482
5710
  },
@@ -5496,6 +5724,9 @@ var SourceManager = class {
5496
5724
  removeFrom(this.managers.promptManager);
5497
5725
  removeFrom(this.managers.mcpConfigManager);
5498
5726
  removeFrom(this.managers.workflowManager);
5727
+ if (this.managers.backendManager) {
5728
+ removeFrom(this.managers.backendManager);
5729
+ }
5499
5730
  if (this.managers.templateRegistry) {
5500
5731
  for (const t of this.managers.templateRegistry.list()) {
5501
5732
  if (t.name.startsWith(prefix)) {
@@ -5609,66 +5840,100 @@ import { readFile as readFile8, readdir as readdir6, stat as stat9, access as ac
5609
5840
  import { join as join22, relative as relative2, extname as extname4 } from "path";
5610
5841
 
5611
5842
  // src/source/source-schemas.ts
5612
- import { z as z9 } from "zod";
5843
+ import { z as z10 } from "zod";
5613
5844
  var VersionedComponentFields = {
5614
- name: z9.string().min(1, "name is required"),
5615
- version: z9.string().optional(),
5616
- description: z9.string().optional(),
5617
- $type: z9.string().optional(),
5618
- $version: z9.number().optional(),
5619
- origin: z9.object({
5620
- type: z9.enum(["builtin", "source", "local"]),
5621
- sourceName: z9.string().optional(),
5622
- syncHash: z9.string().optional(),
5623
- syncedAt: z9.string().optional(),
5624
- modified: z9.boolean().optional()
5845
+ name: z10.string().min(1, "name is required"),
5846
+ version: z10.string().optional(),
5847
+ description: z10.string().optional(),
5848
+ $type: z10.string().optional(),
5849
+ $version: z10.number().optional(),
5850
+ origin: z10.object({
5851
+ type: z10.enum(["builtin", "source", "local"]),
5852
+ sourceName: z10.string().optional(),
5853
+ syncHash: z10.string().optional(),
5854
+ syncedAt: z10.string().optional(),
5855
+ modified: z10.boolean().optional()
5625
5856
  }).optional(),
5626
- tags: z9.array(z9.string()).optional()
5857
+ tags: z10.array(z10.string()).optional()
5627
5858
  };
5628
- var PackageManifestSchema = z9.object({
5629
- name: z9.string().min(1, "name is required"),
5630
- version: z9.string().optional(),
5631
- description: z9.string().optional(),
5632
- components: z9.object({
5633
- skills: z9.array(z9.string()).optional(),
5634
- prompts: z9.array(z9.string()).optional(),
5635
- mcp: z9.array(z9.string()).optional(),
5636
- workflows: z9.array(z9.string()).optional(),
5637
- templates: z9.array(z9.string()).optional()
5859
+ var PackageManifestSchema = z10.object({
5860
+ name: z10.string().min(1, "name is required"),
5861
+ version: z10.string().optional(),
5862
+ description: z10.string().optional(),
5863
+ components: z10.object({
5864
+ skills: z10.array(z10.string()).optional(),
5865
+ prompts: z10.array(z10.string()).optional(),
5866
+ mcp: z10.array(z10.string()).optional(),
5867
+ workflows: z10.array(z10.string()).optional(),
5868
+ templates: z10.array(z10.string()).optional(),
5869
+ backends: z10.array(z10.string()).optional()
5638
5870
  }).optional(),
5639
- presets: z9.array(z9.string()).optional()
5871
+ presets: z10.array(z10.string()).optional()
5640
5872
  });
5641
- var SkillDefinitionSchema2 = z9.object({
5873
+ var SkillDefinitionSchema2 = z10.object({
5642
5874
  ...VersionedComponentFields,
5643
- content: z9.string().min(1, "content is required"),
5644
- license: z9.string().optional(),
5645
- compatibility: z9.string().optional(),
5646
- allowedTools: z9.array(z9.string()).optional()
5875
+ content: z10.string().min(1, "content is required"),
5876
+ license: z10.string().optional(),
5877
+ compatibility: z10.string().optional(),
5878
+ allowedTools: z10.array(z10.string()).optional()
5647
5879
  });
5648
- var PromptDefinitionSchema2 = z9.object({
5880
+ var PromptDefinitionSchema2 = z10.object({
5649
5881
  ...VersionedComponentFields,
5650
- content: z9.string().min(1, "content is required"),
5651
- variables: z9.array(z9.string()).optional()
5882
+ content: z10.string().min(1, "content is required"),
5883
+ variables: z10.array(z10.string()).optional()
5652
5884
  });
5653
- var McpServerDefinitionSchema2 = z9.object({
5885
+ var McpServerDefinitionSchema2 = z10.object({
5654
5886
  ...VersionedComponentFields,
5655
- command: z9.string().min(1, "command is required"),
5656
- args: z9.array(z9.string()).optional(),
5657
- env: z9.record(z9.string(), z9.string()).optional()
5887
+ command: z10.string().min(1, "command is required"),
5888
+ args: z10.array(z10.string()).optional(),
5889
+ env: z10.record(z10.string(), z10.string()).optional()
5658
5890
  });
5659
- var WorkflowDefinitionSchema2 = z9.object({
5891
+ var WorkflowDefinitionSchema2 = z10.object({
5660
5892
  ...VersionedComponentFields,
5661
- content: z9.string().min(1, "content is required")
5893
+ content: z10.string().min(1, "content is required")
5662
5894
  });
5663
- var PresetDefinitionSchema = z9.object({
5664
- name: z9.string().min(1, "name is required"),
5665
- version: z9.string().optional(),
5666
- description: z9.string().optional(),
5667
- skills: z9.array(z9.string()).optional(),
5668
- prompts: z9.array(z9.string()).optional(),
5669
- mcpServers: z9.array(z9.string()).optional(),
5670
- workflows: z9.array(z9.string()).optional(),
5671
- templates: z9.array(z9.string()).optional()
5895
+ var PlatformCommandSchema2 = z10.object({
5896
+ win32: z10.string().min(1),
5897
+ default: z10.string().min(1)
5898
+ });
5899
+ var SourceBackendDefinitionSchema = z10.object({
5900
+ ...VersionedComponentFields,
5901
+ supportedModes: z10.array(z10.enum(["resolve", "open", "acp"])).min(1),
5902
+ resolveCommand: PlatformCommandSchema2.optional(),
5903
+ openCommand: PlatformCommandSchema2.optional(),
5904
+ acpCommand: PlatformCommandSchema2.optional(),
5905
+ acpOwnsProcess: z10.boolean().optional(),
5906
+ resolvePackage: z10.string().optional(),
5907
+ openWorkspaceDir: z10.enum(["arg", "cwd"]).optional(),
5908
+ openSpawnOptions: z10.object({
5909
+ stdio: z10.enum(["inherit", "ignore"]).optional(),
5910
+ detached: z10.boolean().optional(),
5911
+ windowsHide: z10.boolean().optional(),
5912
+ shell: z10.boolean().optional()
5913
+ }).optional(),
5914
+ existenceCheck: z10.object({
5915
+ command: z10.string().min(1),
5916
+ args: z10.array(z10.string()).optional(),
5917
+ expectedExitCode: z10.number().int().optional(),
5918
+ versionPattern: z10.string().optional()
5919
+ }).optional(),
5920
+ install: z10.array(z10.object({
5921
+ type: z10.enum(["npm", "brew", "winget", "choco", "url", "manual"]),
5922
+ package: z10.string().optional(),
5923
+ platforms: z10.array(z10.string()).optional(),
5924
+ label: z10.string().optional(),
5925
+ instructions: z10.string().optional()
5926
+ })).optional()
5927
+ });
5928
+ var PresetDefinitionSchema = z10.object({
5929
+ name: z10.string().min(1, "name is required"),
5930
+ version: z10.string().optional(),
5931
+ description: z10.string().optional(),
5932
+ skills: z10.array(z10.string()).optional(),
5933
+ prompts: z10.array(z10.string()).optional(),
5934
+ mcpServers: z10.array(z10.string()).optional(),
5935
+ workflows: z10.array(z10.string()).optional(),
5936
+ templates: z10.array(z10.string()).optional()
5672
5937
  });
5673
5938
 
5674
5939
  // src/source/source-validator.ts
@@ -6276,6 +6541,7 @@ export {
6276
6541
  AgentStatusSchema,
6277
6542
  AgentTemplateSchema,
6278
6543
  BUILTIN_PROVIDERS,
6544
+ BackendManager,
6279
6545
  BaseComponentManager,
6280
6546
  ClaudeCodeBuilder,
6281
6547
  ClaudeCodeCommunicator,
@@ -6343,6 +6609,8 @@ export {
6343
6609
  createDefaultStepRegistry,
6344
6610
  createLauncher,
6345
6611
  getBackendDescriptor,
6612
+ getBackendManager,
6613
+ getInstallHint,
6346
6614
  getLaunchModeHandler,
6347
6615
  globMatch,
6348
6616
  isAcpBackend,
@@ -6353,6 +6621,7 @@ export {
6353
6621
  openBackend,
6354
6622
  readInstanceMeta,
6355
6623
  registerBackend,
6624
+ registerBackendDefinition,
6356
6625
  registerBuiltinProviders,
6357
6626
  registerCommunicator,
6358
6627
  requireMode,