@evomap/evolver-mcp 2.0.0-beta.4 → 2.0.0-beta.6

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.d.ts CHANGED
@@ -10,4 +10,7 @@ export * from './serviceGuidance.js';
10
10
  export * from './codexInstaller.js';
11
11
  export * from './cursorRulesInstaller.js';
12
12
  export * from './antigravityInstaller.js';
13
+ export * from './jsonMcpInstaller.js';
14
+ export * from './opencodeInstaller.js';
15
+ export * from './kiroInstaller.js';
13
16
  export * from './envFile.js';
package/dist/index.js CHANGED
@@ -10,4 +10,7 @@ export * from './serviceGuidance.js';
10
10
  export * from './codexInstaller.js';
11
11
  export * from './cursorRulesInstaller.js';
12
12
  export * from './antigravityInstaller.js';
13
+ export * from './jsonMcpInstaller.js';
14
+ export * from './opencodeInstaller.js';
15
+ export * from './kiroInstaller.js';
13
16
  export * from './envFile.js';
@@ -4,7 +4,8 @@ export type InjectionMode = 'mcp-hooks' | 'mcp-plugin' | 'mcp-config' | 'cursor-
4
4
  * Setup support contract (#217). A bootstrapper that delegates runtime onboarding to evolver v2 needs a
5
5
  * DETERMINISTIC answer for every runtime it might ask about — not just the ones v2 can write config for.
6
6
  * The three outcomes are the whole contract:
7
- * - `installed` v2 can write the runtime config/hooks and verify it (claude-code, codex, cursor, antigravity).
7
+ * - `installed` v2 can write the runtime config/hooks and verify it (claude-code, codex, cursor, antigravity,
8
+ * opencode, kiro).
8
9
  * - `manual` v2 cannot mutate this runtime's config, but the path is real: it prints precise MCP/HTTP
9
10
  * wiring the operator does by hand (opencode, openclaw, mcp-generic, http-agent, server).
10
11
  * - `unsupported` v2 refuses with a clear reason (an unrecognized runtime id).
package/dist/injection.js CHANGED
@@ -3,12 +3,10 @@ export const SETUP_RUNTIMES = [
3
3
  'claude-code', 'codex', 'cursor', 'antigravity', 'opencode', 'kiro', 'openclaw', 'mcp-generic', 'http-agent', 'server',
4
4
  ];
5
5
  /** Runtimes v2 can write config/hooks for and verify. Antigravity is MCP-config-only (no lifecycle hook). */
6
- const INSTALLED_RUNTIMES = new Set(['claude-code', 'codex', 'cursor', 'antigravity']);
6
+ const INSTALLED_RUNTIMES = new Set(['claude-code', 'codex', 'cursor', 'antigravity', 'opencode', 'kiro']);
7
7
  /** Runtimes with no v2 auto-installer but a real manual path. The reason is the short, honest "do it by hand"
8
8
  * line; the precise wiring text is a separate concern (#217 slice 2), not hard-coded here. */
9
9
  const MANUAL_RUNTIMES = new Map([
10
- ['opencode', 'opencode is consumed passively today; register the evolver MCP server in its config by hand'],
11
- ['kiro', 'kiro is consumed passively today; register the evolver MCP server in its config by hand'],
12
10
  ['openclaw', 'no v2 auto-installer yet; wire the evolver MCP server (or PrivateHub HTTP/A2A) by hand'],
13
11
  ['mcp-generic', 'no config writer for a generic MCP client; register the evolver MCP server by hand'],
14
12
  ['http-agent', 'no config writer for an HTTP/API-only agent; wire it to PrivateHub HTTP/A2A by hand'],
@@ -67,12 +65,17 @@ export function planInjection(runtime, server) {
67
65
  config: { mcpServers: { evolver: { command: server.command, args: server.args ?? [], ...(server.env ? { env: server.env } : {}) } } },
68
66
  note: 'antigravity: write mcpServers.evolver in the user-level MCP config; tool discovery only (no SessionStart hook)',
69
67
  };
70
- case 'kiro':
71
68
  case 'opencode':
72
69
  return {
73
- runtime, mode: 'passive',
74
- config: {},
75
- note: `${runtime}: MVP 仅被动消费会话日志(无工具注入); 接入方式待补`,
70
+ runtime, mode: 'mcp-config',
71
+ config: { mcp: { evolver: { type: 'local', command: [server.command, ...(server.args ?? [])], ...(server.env ? { environment: server.env } : {}), enabled: true } } },
72
+ note: 'OpenCode: write opencode.json local MCP registration; no lifecycle prompt injection.',
73
+ };
74
+ case 'kiro':
75
+ return {
76
+ runtime, mode: 'mcp-config',
77
+ config: { mcpServers: { evolver: { command: server.command, args: server.args ?? [], ...(server.env ? { env: server.env } : {}), disabled: false } } },
78
+ note: 'Kiro: write .kiro/settings/mcp.json MCP registration; no lifecycle prompt injection.',
76
79
  };
77
80
  default: {
78
81
  const _exhaustive = runtime;
@@ -32,6 +32,8 @@ export interface InstallOptions {
32
32
  hookCommand?: string;
33
33
  /** Reinstall even if an evolver install is already present. */
34
34
  force?: boolean;
35
+ /** Plan and validate without writing config or backup files. */
36
+ dryRun?: boolean;
35
37
  /** Cursor only: the top genes to render into .cursor/rules/evolver.mdc. The daemon refreshes these on change;
36
38
  * a one-shot `setup-hooks --runtime=cursor` install seeds the file (empty ⇒ a placeholder the daemon fills). */
37
39
  genes?: readonly CursorGene[];
@@ -40,12 +42,44 @@ export interface InstallOptions {
40
42
  /** Antigravity only: override the user home used to resolve ~/.gemini config roots. Intended for hermetic
41
43
  * embedding/tests; normal callers omit it. configRoot and scope do not affect Antigravity's user config. */
42
44
  homeDir?: string;
45
+ /** Kiro user scope only: direct replacement for ~/.kiro, matching KIRO_HOME semantics. */
46
+ kiroHome?: string;
47
+ /** OpenCode user scope only: explicit XDG_CONFIG_HOME used to resolve the global config. */
48
+ xdgConfigHome?: string;
49
+ /** OpenCode user scope only: explicit OPENCODE_CONFIG file override. */
50
+ opencodeConfig?: string;
51
+ /** OpenCode user scope only: explicit OPENCODE_CONFIG_DIR override. */
52
+ opencodeConfigDir?: string;
53
+ /** OpenCode only: inline config loaded after project/custom-directory config. */
54
+ opencodeConfigContent?: string;
55
+ /** OpenCode only: mirrors truthy OPENCODE_DISABLE_PROJECT_CONFIG handling. */
56
+ opencodeDisableProjectConfig?: boolean;
57
+ /** OpenCode only: injectable managed-config directory for hermetic tests. */
58
+ opencodeManagedConfigDir?: string;
59
+ /** OpenCode only: injectable macOS managed-preference paths for hermetic tests. */
60
+ opencodeManagedPreferencePaths?: readonly string[];
61
+ /** OpenCode only: injectable platform used to resolve system managed paths. */
62
+ opencodePlatform?: NodeJS.Platform;
63
+ /** OpenCode only: injectable ProgramData used to resolve the Windows managed path. */
64
+ opencodeProgramData?: string;
65
+ /** OpenCode only: injectable username used to resolve macOS managed preferences. */
66
+ opencodeUsername?: string;
43
67
  }
44
68
  export interface UninstallOptions {
45
69
  configRoot: string;
46
70
  scope?: InstallScope;
47
71
  /** Antigravity only: override the user home used to resolve ~/.gemini config roots. */
48
72
  homeDir?: string;
73
+ /** Kiro user scope only: direct replacement for ~/.kiro, matching KIRO_HOME semantics. */
74
+ kiroHome?: string;
75
+ /** Validate and report the uninstall without changing config or backup files. */
76
+ dryRun?: boolean;
77
+ /** OpenCode user scope only: explicit XDG_CONFIG_HOME used to resolve the global config. */
78
+ xdgConfigHome?: string;
79
+ /** OpenCode user scope only: explicit OPENCODE_CONFIG file override. */
80
+ opencodeConfig?: string;
81
+ /** OpenCode user scope only: explicit OPENCODE_CONFIG_DIR override. */
82
+ opencodeConfigDir?: string;
49
83
  }
50
84
  export interface InstallResult {
51
85
  ok: boolean;
@@ -54,6 +88,9 @@ export interface InstallResult {
54
88
  /** Absolute paths written (install) or cleaned (uninstall). */
55
89
  files: string[];
56
90
  alreadyInstalled?: boolean;
91
+ dryRun?: boolean;
92
+ verified?: boolean;
93
+ backups?: string[];
57
94
  error?: string;
58
95
  }
59
96
  export declare class SymlinkRefusedError extends Error {
package/dist/installer.js CHANGED
@@ -23,6 +23,8 @@ import { installCodex, uninstallCodex } from './codexInstaller.js';
23
23
  // top genes into .cursor/rules/evolver.mdc. It plugs into the same install/uninstall dispatch below.
24
24
  import { installCursorRules, uninstallCursorRules } from './cursorRulesInstaller.js';
25
25
  import { installAntigravity, uninstallAntigravity } from './antigravityInstaller.js';
26
+ import { installOpenCode, uninstallOpenCode } from './opencodeInstaller.js';
27
+ import { installKiro, uninstallKiro } from './kiroInstaller.js';
26
28
  /** Marks a config file as containing evolver-managed entries, so uninstall only removes what we added. */
27
29
  export const MANAGED_MARKER = '_evolver_managed';
28
30
  /** A hook entry is evolver-owned if any of its commands mention this — used to replace-not-duplicate on reinstall. */
@@ -404,9 +406,14 @@ export function installInjection(plan, opts) {
404
406
  if (plan.runtime === 'antigravity') {
405
407
  return installAntigravity(plan, opts);
406
408
  }
409
+ if (plan.runtime === 'opencode') {
410
+ return installOpenCode(plan, opts);
411
+ }
412
+ if (plan.runtime === 'kiro') {
413
+ return installKiro(plan, opts);
414
+ }
407
415
  if (plan.runtime !== 'claude-code') {
408
- // kiro/opencode are passive (handled above); any other active runtime is not yet ported.
409
- return { ok: false, runtime: plan.runtime, mode: plan.mode, files: [], error: `installer not yet implemented for ${plan.runtime} (supported: claude-code, codex, cursor, antigravity)` };
416
+ return { ok: false, runtime: plan.runtime, mode: plan.mode, files: [], error: `installer not yet implemented for ${plan.runtime} (supported: claude-code, codex, cursor, antigravity, opencode, kiro)` };
410
417
  }
411
418
  const hookCommand = opts.hookCommand ?? DEFAULT_HOOK_COMMAND;
412
419
  const scope = opts.scope ?? 'project';
@@ -487,6 +494,12 @@ export function uninstallInjection(runtime, opts) {
487
494
  if (runtime === 'antigravity') {
488
495
  return uninstallAntigravity(runtime, opts);
489
496
  }
497
+ if (runtime === 'opencode') {
498
+ return uninstallOpenCode(runtime, opts);
499
+ }
500
+ if (runtime === 'kiro') {
501
+ return uninstallKiro(runtime, opts);
502
+ }
490
503
  if (runtime !== 'claude-code') {
491
504
  return { ok: false, runtime, mode: 'n/a', files: [], error: `uninstall not implemented for ${runtime}` };
492
505
  }
@@ -0,0 +1,75 @@
1
+ import type { InjectionPlan, McpServerCmd, RuntimeId } from './injection.js';
2
+ import { type InstallOptions, type InstallResult, type UninstallOptions } from './installer.js';
3
+ type BeforeReplaceHook = (path: string) => void;
4
+ export declare function _setJsonMcpBeforeReplaceHookForTest(hook?: BeforeReplaceHook): void;
5
+ export declare function _setJsonMcpAfterReplaceHookForTest(hook?: BeforeReplaceHook): void;
6
+ export declare function _setJsonMcpBeforeBackupRemoveHookForTest(hook?: BeforeReplaceHook): void;
7
+ export interface JsonMcpRuntimeSpec {
8
+ runtime: 'opencode' | 'kiro';
9
+ configPath(opts: JsonMcpPathOptions): string;
10
+ resolveConfig?(opts: JsonMcpPathOptions): JsonMcpRuntimeResolution;
11
+ safeRoot?(opts: JsonMcpPathOptions): string;
12
+ conflictingPaths?(opts: JsonMcpPathOptions): string[];
13
+ containerKey: 'mcp' | 'mcpServers';
14
+ entry(server: McpServerCmd): Record<string, unknown>;
15
+ installPreflight?(resolution: JsonMcpRuntimeResolution, opts: InstallOptions, expected: Record<string, unknown>): JsonMcpInstallPreflight | undefined;
16
+ }
17
+ export interface JsonMcpInstallPreflight {
18
+ alreadyInstalled?: boolean;
19
+ assertUnchanged(): void;
20
+ }
21
+ type JsonMcpPathOptions = Pick<InstallOptions, 'configRoot' | 'scope' | 'homeDir' | 'kiroHome' | 'xdgConfigHome' | 'opencodeConfig' | 'opencodeConfigDir'>;
22
+ export interface JsonMcpRuntimeResolution {
23
+ configPath: string;
24
+ safeRoot: string;
25
+ conflictingPaths: string[];
26
+ /** An active sibling at the same precedence slot that must remain user-owned and read-only. */
27
+ activePrecedencePath?: string;
28
+ /** The writable target was retargeted to a uniquely managed config discovered outside the active path. */
29
+ managedRetarget?: true;
30
+ /** Runtime config candidates ordered from lowest to highest precedence; the first path is the default target. */
31
+ topologyCandidatePaths?: string[];
32
+ evidencePaths?: string[];
33
+ /** Config locations that may contain a managed backup from an earlier active-precedence decision. */
34
+ uninstallCandidatePaths?: string[];
35
+ /** Broader locations used to reuse a managed target selected from an ancestor project directory. */
36
+ installDiscoveryPaths?: string[];
37
+ /** Safe root for install discovery and a selected managed target; does not affect default install writes. */
38
+ installSafeRoot?: string;
39
+ /** Broader read-only locations used only to discover managed backups during uninstall. */
40
+ uninstallDiscoveryPaths?: string[];
41
+ /** Safe root for uninstall discovery and a selected managed target; does not affect install writes. */
42
+ uninstallSafeRoot?: string;
43
+ /** Candidate-local conflicts that must be re-evaluated after uninstall retargeting. */
44
+ uninstallConflictingPaths?: (configPath: string) => string[];
45
+ }
46
+ export declare class McpConfigConflictError extends Error {
47
+ readonly diff: {
48
+ path: string;
49
+ expected: unknown;
50
+ actual: unknown;
51
+ };
52
+ constructor(runtime: string, path: string, expected: unknown, actual: unknown);
53
+ }
54
+ export declare class McpConfigShapeError extends Error {
55
+ constructor(runtime: string, path: string, detail: string);
56
+ }
57
+ export declare class McpConfigOwnershipError extends Error {
58
+ constructor(runtime: string, detail: string);
59
+ }
60
+ export declare class McpConfigVerificationError extends Error {
61
+ private readonly runtime;
62
+ private readonly path;
63
+ restored: boolean;
64
+ constructor(runtime: string, path: string);
65
+ markRestored(): void;
66
+ }
67
+ export declare class McpConfigChangedError extends Error {
68
+ constructor(runtime: string, path: string);
69
+ }
70
+ export declare class McpServerValidationError extends Error {
71
+ constructor(message: string);
72
+ }
73
+ export declare function installJsonMcpRuntime(spec: JsonMcpRuntimeSpec, plan: InjectionPlan, opts: InstallOptions): InstallResult;
74
+ export declare function uninstallJsonMcpRuntime(spec: JsonMcpRuntimeSpec, runtime: RuntimeId, opts: UninstallOptions): InstallResult;
75
+ export {};