brainclaw 0.19.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.
Files changed (128) hide show
  1. package/LICENSE +74 -0
  2. package/README.md +226 -0
  3. package/dist/cli.js +1037 -0
  4. package/dist/commands/accept.js +149 -0
  5. package/dist/commands/adapter-openclaw-import.js +75 -0
  6. package/dist/commands/add-step.js +35 -0
  7. package/dist/commands/agent-board.js +106 -0
  8. package/dist/commands/audit.js +35 -0
  9. package/dist/commands/bootstrap.js +34 -0
  10. package/dist/commands/capability.js +104 -0
  11. package/dist/commands/changes.js +112 -0
  12. package/dist/commands/check-constraints.js +63 -0
  13. package/dist/commands/claim-resource.js +54 -0
  14. package/dist/commands/claim.js +92 -0
  15. package/dist/commands/complete-step.js +34 -0
  16. package/dist/commands/constraint.js +44 -0
  17. package/dist/commands/context-diff.js +32 -0
  18. package/dist/commands/context.js +63 -0
  19. package/dist/commands/decision.js +45 -0
  20. package/dist/commands/delete-plan.js +20 -0
  21. package/dist/commands/diff.js +99 -0
  22. package/dist/commands/doctor.js +1275 -0
  23. package/dist/commands/enable-agent.js +63 -0
  24. package/dist/commands/env.js +46 -0
  25. package/dist/commands/estimation-report.js +167 -0
  26. package/dist/commands/explore.js +47 -0
  27. package/dist/commands/export.js +381 -0
  28. package/dist/commands/handoff.js +63 -0
  29. package/dist/commands/history.js +22 -0
  30. package/dist/commands/hooks.js +123 -0
  31. package/dist/commands/init.js +356 -0
  32. package/dist/commands/install-hooks.js +115 -0
  33. package/dist/commands/instruction.js +56 -0
  34. package/dist/commands/list-agents.js +44 -0
  35. package/dist/commands/list-claims.js +45 -0
  36. package/dist/commands/list-instructions.js +50 -0
  37. package/dist/commands/list-plans.js +48 -0
  38. package/dist/commands/mcp-worker.js +12 -0
  39. package/dist/commands/mcp.js +2272 -0
  40. package/dist/commands/memory.js +283 -0
  41. package/dist/commands/metrics.js +175 -0
  42. package/dist/commands/plan-resource.js +62 -0
  43. package/dist/commands/plan.js +76 -0
  44. package/dist/commands/prune-candidates.js +36 -0
  45. package/dist/commands/prune.js +48 -0
  46. package/dist/commands/pull.js +25 -0
  47. package/dist/commands/push.js +28 -0
  48. package/dist/commands/rebuild.js +14 -0
  49. package/dist/commands/reflect-runtime-note.js +74 -0
  50. package/dist/commands/reflect.js +286 -0
  51. package/dist/commands/register-agent.js +29 -0
  52. package/dist/commands/reject.js +52 -0
  53. package/dist/commands/release-claim.js +41 -0
  54. package/dist/commands/release-claims.js +67 -0
  55. package/dist/commands/review.js +242 -0
  56. package/dist/commands/rollback.js +156 -0
  57. package/dist/commands/runtime-note.js +144 -0
  58. package/dist/commands/runtime-status.js +49 -0
  59. package/dist/commands/search.js +36 -0
  60. package/dist/commands/session-end.js +187 -0
  61. package/dist/commands/session-start.js +147 -0
  62. package/dist/commands/set-trust.js +92 -0
  63. package/dist/commands/setup.js +446 -0
  64. package/dist/commands/show-candidate.js +31 -0
  65. package/dist/commands/star-candidate.js +28 -0
  66. package/dist/commands/status.js +133 -0
  67. package/dist/commands/sync.js +159 -0
  68. package/dist/commands/tool.js +126 -0
  69. package/dist/commands/trap.js +74 -0
  70. package/dist/commands/update-handoff.js +23 -0
  71. package/dist/commands/update-plan.js +37 -0
  72. package/dist/commands/upgrade.js +382 -0
  73. package/dist/commands/use-candidate.js +35 -0
  74. package/dist/commands/version.js +96 -0
  75. package/dist/commands/watch.js +215 -0
  76. package/dist/commands/whoami.js +104 -0
  77. package/dist/core/agent-context.js +340 -0
  78. package/dist/core/agent-files.js +874 -0
  79. package/dist/core/agent-integrations.js +135 -0
  80. package/dist/core/agent-inventory.js +401 -0
  81. package/dist/core/agent-registry.js +420 -0
  82. package/dist/core/ai-agent-detection.js +140 -0
  83. package/dist/core/audit.js +85 -0
  84. package/dist/core/bootstrap.js +658 -0
  85. package/dist/core/brainclaw-version.js +433 -0
  86. package/dist/core/candidates.js +137 -0
  87. package/dist/core/circuit-breaker.js +118 -0
  88. package/dist/core/claims.js +72 -0
  89. package/dist/core/config.js +86 -0
  90. package/dist/core/context-diff.js +122 -0
  91. package/dist/core/context.js +1212 -0
  92. package/dist/core/contradictions.js +270 -0
  93. package/dist/core/coordination.js +86 -0
  94. package/dist/core/cross-project.js +99 -0
  95. package/dist/core/duplicates.js +72 -0
  96. package/dist/core/event-log.js +152 -0
  97. package/dist/core/events.js +56 -0
  98. package/dist/core/execution-context.js +204 -0
  99. package/dist/core/freshness.js +87 -0
  100. package/dist/core/global-registry.js +182 -0
  101. package/dist/core/host.js +10 -0
  102. package/dist/core/identity.js +151 -0
  103. package/dist/core/ids.js +56 -0
  104. package/dist/core/input-validation.js +81 -0
  105. package/dist/core/instructions.js +117 -0
  106. package/dist/core/io.js +191 -0
  107. package/dist/core/json-store.js +63 -0
  108. package/dist/core/lifecycle.js +45 -0
  109. package/dist/core/lock.js +129 -0
  110. package/dist/core/logger.js +49 -0
  111. package/dist/core/machine-profile.js +332 -0
  112. package/dist/core/markdown.js +120 -0
  113. package/dist/core/memory-git.js +133 -0
  114. package/dist/core/migration.js +247 -0
  115. package/dist/core/project-registry.js +64 -0
  116. package/dist/core/reflection-safety.js +21 -0
  117. package/dist/core/repo-analysis.js +133 -0
  118. package/dist/core/reputation.js +409 -0
  119. package/dist/core/runtime.js +134 -0
  120. package/dist/core/schema.js +580 -0
  121. package/dist/core/search.js +115 -0
  122. package/dist/core/security.js +66 -0
  123. package/dist/core/setup-state.js +50 -0
  124. package/dist/core/state.js +83 -0
  125. package/dist/core/store-resolution.js +119 -0
  126. package/dist/core/sync-remote.js +83 -0
  127. package/dist/core/traps.js +86 -0
  128. package/package.json +60 -0
@@ -0,0 +1,135 @@
1
+ import fs from 'node:fs';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
4
+ const SUPPORTED_AGENT_INTEGRATION_NAMES = new Set([
5
+ 'github-copilot',
6
+ 'claude-code',
7
+ 'cursor',
8
+ 'windsurf',
9
+ 'cline',
10
+ 'codex',
11
+ 'opencode',
12
+ 'antigravity',
13
+ 'continue',
14
+ 'roo',
15
+ ]);
16
+ const DEFAULT_SURFACES = {
17
+ 'github-copilot': [
18
+ { kind: 'instructions', location: 'workspace', path: '.github/copilot-instructions.md' },
19
+ { kind: 'skill', location: 'workspace', path: '.github/skills/brainclaw-context/SKILL.md' },
20
+ ],
21
+ 'claude-code': [
22
+ { kind: 'instructions', location: 'workspace', path: 'CLAUDE.md' },
23
+ { kind: 'mcp', location: 'workspace', path: '.mcp.json' },
24
+ { kind: 'skill', location: 'workspace', path: '.claude/commands/brainclaw.md' },
25
+ ],
26
+ 'cursor': [
27
+ { kind: 'instructions', location: 'workspace', path: '.cursor/rules/brainclaw.md' },
28
+ { kind: 'rule', location: 'workspace', path: '.cursor/rules/brainclaw-mcp-shim.mdc' },
29
+ { kind: 'mcp', location: 'machine', path: '.cursor/mcp.json' },
30
+ ],
31
+ 'windsurf': [
32
+ { kind: 'instructions', location: 'workspace', path: '.windsurfrules' },
33
+ { kind: 'hook', location: 'workspace', path: '.windsurfrules' },
34
+ { kind: 'mcp', location: 'machine', path: '.codeium/windsurf/mcp_config.json' },
35
+ ],
36
+ 'cline': [
37
+ { kind: 'instructions', location: 'workspace', path: '.clinerules/brainclaw.md' },
38
+ { kind: 'mcp', location: 'workspace', path: '.vscode/cline_mcp_settings.json' },
39
+ ],
40
+ 'codex': [
41
+ { kind: 'instructions', location: 'workspace', path: 'AGENTS.md' },
42
+ { kind: 'mcp', location: 'machine', path: '.codex/config.toml' },
43
+ ],
44
+ 'opencode': [
45
+ { kind: 'instructions', location: 'workspace', path: 'AGENTS.md' },
46
+ { kind: 'mcp', location: 'workspace', path: 'opencode.json' },
47
+ ],
48
+ 'antigravity': [
49
+ { kind: 'instructions', location: 'workspace', path: 'GEMINI.md' },
50
+ { kind: 'mcp', location: 'machine', path: '.gemini/antigravity/mcp_config.json' },
51
+ ],
52
+ 'continue': [
53
+ { kind: 'instructions', location: 'workspace', path: '.continue/rules/brainclaw.md' },
54
+ { kind: 'mcp', location: 'workspace', path: '.continue/config.json' },
55
+ ],
56
+ 'roo': [
57
+ { kind: 'instructions', location: 'workspace', path: '.roo/rules/brainclaw.md' },
58
+ { kind: 'mcp', location: 'workspace', path: '.roo/mcp.json' },
59
+ ],
60
+ };
61
+ function mergeSurfaces(current, next) {
62
+ const merged = [...current];
63
+ for (const candidate of next) {
64
+ const exists = merged.some((surface) => surface.kind === candidate.kind
65
+ && surface.location === candidate.location
66
+ && surface.path === candidate.path);
67
+ if (!exists) {
68
+ merged.push(candidate);
69
+ }
70
+ }
71
+ return merged;
72
+ }
73
+ export function buildAgentIntegrationDeclaration(agentName, declarationSource = 'manual') {
74
+ return {
75
+ agent_name: agentName,
76
+ declaration_source: declarationSource,
77
+ surfaces: DEFAULT_SURFACES[agentName].map((surface) => ({ ...surface })),
78
+ };
79
+ }
80
+ export function isAgentIntegrationName(value) {
81
+ return SUPPORTED_AGENT_INTEGRATION_NAMES.has(value);
82
+ }
83
+ function resolveDeclaredSurfacePath(surface, cwd, env) {
84
+ if (!surface.path) {
85
+ return undefined;
86
+ }
87
+ if (surface.location === 'workspace') {
88
+ return path.join(cwd, surface.path);
89
+ }
90
+ const homeDir = env.HOME?.trim() || env.USERPROFILE?.trim() || os.homedir();
91
+ return path.join(homeDir, surface.path);
92
+ }
93
+ function surfaceExists(surface, cwd, env) {
94
+ const expectedPath = resolveDeclaredSurfacePath(surface, cwd, env);
95
+ return {
96
+ ...surface,
97
+ expected_path: expectedPath,
98
+ exists: expectedPath ? fs.existsSync(expectedPath) : false,
99
+ };
100
+ }
101
+ export function assessAgentIntegrationReadiness(config, cwd, env = process.env) {
102
+ return (config.agent_integrations?.declarations ?? []).map((declaration) => {
103
+ const surfaces = declaration.surfaces.map((surface) => surfaceExists(surface, cwd, env));
104
+ const missingSurfaces = surfaces.filter((surface) => !surface.exists);
105
+ return {
106
+ agent_name: declaration.agent_name,
107
+ declaration_source: declaration.declaration_source,
108
+ ready: missingSurfaces.length === 0,
109
+ missing_surfaces: missingSurfaces,
110
+ surfaces,
111
+ };
112
+ });
113
+ }
114
+ export function upsertAgentIntegrationDeclaration(config, agentName, declarationSource = 'manual') {
115
+ const declarations = config.agent_integrations?.declarations ?? [];
116
+ const existing = declarations.find((item) => item.agent_name === agentName);
117
+ const next = buildAgentIntegrationDeclaration(agentName, declarationSource);
118
+ if (!config.agent_integrations) {
119
+ config.agent_integrations = { declarations: [] };
120
+ }
121
+ if (!existing) {
122
+ config.agent_integrations.declarations.push(next);
123
+ return true;
124
+ }
125
+ const mergedSurfaces = mergeSurfaces(existing.surfaces ?? [], next.surfaces);
126
+ const mergedSource = existing.declaration_source === 'manual' || declarationSource === 'manual'
127
+ ? 'manual'
128
+ : 'detected';
129
+ const changed = mergedSource !== existing.declaration_source
130
+ || mergedSurfaces.length !== (existing.surfaces?.length ?? 0);
131
+ existing.declaration_source = mergedSource;
132
+ existing.surfaces = mergedSurfaces;
133
+ return changed;
134
+ }
135
+ //# sourceMappingURL=agent-integrations.js.map
@@ -0,0 +1,401 @@
1
+ import fs from 'node:fs';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
4
+ import { spawnSync } from 'node:child_process';
5
+ import yaml from 'yaml';
6
+ import { MEMORY_DIR } from './io.js';
7
+ function tryCommand(command, args, timeout = 5000) {
8
+ try {
9
+ const r = spawnSync(command, args, { encoding: 'utf-8', timeout, windowsHide: true });
10
+ return { ok: r.status === 0, stdout: r.stdout ?? '' };
11
+ }
12
+ catch {
13
+ return { ok: false, stdout: '' };
14
+ }
15
+ }
16
+ const AGENT_DEFINITIONS = [
17
+ {
18
+ name: 'claude-code',
19
+ detect: (_home, env) => {
20
+ // Check if claude CLI is available
21
+ const cli = tryCommand('claude', ['--version'], 3000);
22
+ if (cli.ok) {
23
+ const ver = cli.stdout.trim().match(/(\d+\.\d+\.\d+)/)?.[1];
24
+ return { installed: true, method: 'claude CLI', version: ver };
25
+ }
26
+ // Check env var (means it's running)
27
+ if (env.CLAUDE_CODE_VERSION) {
28
+ return { installed: true, method: 'CLAUDE_CODE_VERSION env', version: env.CLAUDE_CODE_VERSION };
29
+ }
30
+ return { installed: false, method: '' };
31
+ },
32
+ models: [
33
+ { name: 'claude-opus-4-6', context_window: 1000000 },
34
+ { name: 'claude-sonnet-4-6', context_window: 200000 },
35
+ { name: 'claude-haiku-4-5', context_window: 200000 },
36
+ ],
37
+ native_tools: ['Read', 'Write', 'Edit', 'Bash', 'Glob', 'Grep', 'Agent', 'WebSearch', 'WebFetch', 'NotebookEdit'],
38
+ mcp_support: true,
39
+ mcp_config_format: '.mcp.json (workspace)',
40
+ skills_support: true,
41
+ skills_path_pattern: '.claude/commands/',
42
+ rules_support: false,
43
+ hooks_support: true,
44
+ instruction_file: 'CLAUDE.md',
45
+ },
46
+ {
47
+ name: 'cursor',
48
+ detect: (home) => {
49
+ // Check for Cursor config directories
50
+ const cursorDir = path.join(home, '.cursor');
51
+ if (fs.existsSync(cursorDir)) {
52
+ return { installed: true, method: '~/.cursor directory' };
53
+ }
54
+ // Check common install paths
55
+ if (process.platform === 'win32') {
56
+ const appData = process.env.LOCALAPPDATA ?? '';
57
+ if (appData && fs.existsSync(path.join(appData, 'Programs', 'cursor'))) {
58
+ return { installed: true, method: 'AppData/Programs/cursor' };
59
+ }
60
+ }
61
+ return { installed: false, method: '' };
62
+ },
63
+ models: [
64
+ { name: 'claude-sonnet-4-6', context_window: 200000 },
65
+ { name: 'gpt-4o', context_window: 128000 },
66
+ { name: 'cursor-small', context_window: 128000 },
67
+ ],
68
+ native_tools: ['edit', 'terminal', 'codebase-search', 'file-search'],
69
+ mcp_support: true,
70
+ mcp_config_format: '.cursor/mcp.json (machine)',
71
+ skills_support: false,
72
+ rules_support: true,
73
+ hooks_support: false,
74
+ instruction_file: '.cursor/rules/',
75
+ },
76
+ {
77
+ name: 'codex',
78
+ detect: (home) => {
79
+ const codexDir = path.join(home, '.codex');
80
+ if (fs.existsSync(codexDir)) {
81
+ return { installed: true, method: '~/.codex directory' };
82
+ }
83
+ const cli = tryCommand('codex', ['--version'], 3000);
84
+ if (cli.ok) {
85
+ const ver = cli.stdout.trim().match(/(\d+\.\d+\.\d+)/)?.[1];
86
+ return { installed: true, method: 'codex CLI', version: ver };
87
+ }
88
+ return { installed: false, method: '' };
89
+ },
90
+ models: [
91
+ { name: 'o4-mini', context_window: 200000 },
92
+ { name: 'o3', context_window: 200000 },
93
+ { name: 'gpt-4.1', context_window: 1000000 },
94
+ ],
95
+ native_tools: ['shell', 'file_read', 'file_write', 'file_edit'],
96
+ mcp_support: true,
97
+ mcp_config_format: '.codex/config.toml (TOML)',
98
+ skills_support: true,
99
+ skills_path_pattern: '.codex/skills/',
100
+ rules_support: false,
101
+ hooks_support: false,
102
+ instruction_file: 'AGENTS.md',
103
+ },
104
+ {
105
+ name: 'windsurf',
106
+ detect: (home) => {
107
+ if (process.platform === 'win32') {
108
+ const appData = process.env.LOCALAPPDATA ?? '';
109
+ if (appData && fs.existsSync(path.join(appData, 'Programs', 'windsurf'))) {
110
+ return { installed: true, method: 'AppData/Programs/windsurf' };
111
+ }
112
+ }
113
+ // Check for Windsurf config
114
+ const wsConfig = path.join(home, '.codeium', 'windsurf');
115
+ if (fs.existsSync(wsConfig)) {
116
+ return { installed: true, method: '~/.codeium/windsurf directory' };
117
+ }
118
+ return { installed: false, method: '' };
119
+ },
120
+ models: [
121
+ { name: 'claude-sonnet-4-6', context_window: 200000 },
122
+ { name: 'gpt-4o', context_window: 128000 },
123
+ ],
124
+ native_tools: ['edit', 'terminal', 'search'],
125
+ mcp_support: true,
126
+ mcp_config_format: '.codeium/windsurf/mcp_config.json',
127
+ skills_support: false,
128
+ rules_support: true,
129
+ hooks_support: true,
130
+ instruction_file: '.windsurfrules',
131
+ },
132
+ {
133
+ name: 'github-copilot',
134
+ detect: (_home, env) => {
135
+ if (env.GITHUB_COPILOT_TOKEN || env.GITHUB_COPILOT_PRODUCT) {
136
+ return { installed: true, method: 'GITHUB_COPILOT_* env' };
137
+ }
138
+ // Check VS Code extensions directory for copilot
139
+ const vscodeExt = path.join(_home, '.vscode', 'extensions');
140
+ if (fs.existsSync(vscodeExt)) {
141
+ try {
142
+ const exts = fs.readdirSync(vscodeExt);
143
+ if (exts.some(e => e.startsWith('github.copilot-'))) {
144
+ return { installed: true, method: 'VS Code extension' };
145
+ }
146
+ }
147
+ catch { /* non-fatal */ }
148
+ }
149
+ return { installed: false, method: '' };
150
+ },
151
+ models: [
152
+ { name: 'gpt-4o', context_window: 128000 },
153
+ { name: 'claude-sonnet-4-6', context_window: 200000 },
154
+ ],
155
+ native_tools: ['code-completion', 'chat', 'inline-edit'],
156
+ mcp_support: false,
157
+ skills_support: true,
158
+ skills_path_pattern: '.github/skills/',
159
+ rules_support: false,
160
+ hooks_support: false,
161
+ instruction_file: '.github/copilot-instructions.md',
162
+ },
163
+ {
164
+ name: 'cline',
165
+ detect: (_home, env) => {
166
+ if (env.CLINE_AGENT || env.CLINE_SESSION_ID) {
167
+ return { installed: true, method: 'CLINE_* env' };
168
+ }
169
+ const vscodeExt = path.join(_home, '.vscode', 'extensions');
170
+ if (fs.existsSync(vscodeExt)) {
171
+ try {
172
+ const exts = fs.readdirSync(vscodeExt);
173
+ if (exts.some(e => e.includes('cline'))) {
174
+ return { installed: true, method: 'VS Code extension' };
175
+ }
176
+ }
177
+ catch { /* non-fatal */ }
178
+ }
179
+ return { installed: false, method: '' };
180
+ },
181
+ models: [
182
+ { name: 'claude-sonnet-4-6', context_window: 200000 },
183
+ { name: 'gpt-4o', context_window: 128000 },
184
+ ],
185
+ native_tools: ['read_file', 'write_file', 'execute_command', 'browser_action', 'search_files'],
186
+ mcp_support: true,
187
+ mcp_config_format: '.vscode/cline_mcp_settings.json',
188
+ skills_support: false,
189
+ rules_support: true,
190
+ hooks_support: false,
191
+ instruction_file: '.clinerules/',
192
+ },
193
+ {
194
+ name: 'roo',
195
+ detect: (_home, env) => {
196
+ if (env.ROO_AGENT || env.ROO_SESSION_ID) {
197
+ return { installed: true, method: 'ROO_* env' };
198
+ }
199
+ const vscodeExt = path.join(_home, '.vscode', 'extensions');
200
+ if (fs.existsSync(vscodeExt)) {
201
+ try {
202
+ const exts = fs.readdirSync(vscodeExt);
203
+ if (exts.some(e => e.includes('roo'))) {
204
+ return { installed: true, method: 'VS Code extension' };
205
+ }
206
+ }
207
+ catch { /* non-fatal */ }
208
+ }
209
+ return { installed: false, method: '' };
210
+ },
211
+ models: [
212
+ { name: 'claude-sonnet-4-6', context_window: 200000 },
213
+ ],
214
+ native_tools: ['read_file', 'write_file', 'execute_command', 'browser_action', 'search_files'],
215
+ mcp_support: true,
216
+ mcp_config_format: '.roo/mcp.json',
217
+ skills_support: false,
218
+ rules_support: true,
219
+ hooks_support: false,
220
+ instruction_file: '.roo/rules/',
221
+ },
222
+ {
223
+ name: 'opencode',
224
+ detect: (home, env) => {
225
+ if (env.OPENCODE_SESSION_ID || env.OPENCODE_AGENT) {
226
+ return { installed: true, method: 'OPENCODE_* env' };
227
+ }
228
+ if (fs.existsSync(path.join(home, '.config', 'opencode'))) {
229
+ return { installed: true, method: '~/.config/opencode directory' };
230
+ }
231
+ return { installed: false, method: '' };
232
+ },
233
+ models: [
234
+ { name: 'claude-sonnet-4-6', context_window: 200000 },
235
+ { name: 'gpt-4o', context_window: 128000 },
236
+ ],
237
+ native_tools: ['file_read', 'file_write', 'shell', 'search'],
238
+ mcp_support: true,
239
+ mcp_config_format: 'opencode.json',
240
+ skills_support: false,
241
+ rules_support: false,
242
+ hooks_support: false,
243
+ instruction_file: 'AGENTS.md',
244
+ },
245
+ {
246
+ name: 'antigravity',
247
+ detect: (home, env) => {
248
+ if (env.ANTIGRAVITY_SESSION_ID || env.ANTIGRAVITY_AGENT) {
249
+ return { installed: true, method: 'ANTIGRAVITY_* env' };
250
+ }
251
+ if (fs.existsSync(path.join(home, '.gemini', 'antigravity'))) {
252
+ return { installed: true, method: '~/.gemini/antigravity directory' };
253
+ }
254
+ const cli = tryCommand('gemini', ['--version'], 3000);
255
+ if (cli.ok) {
256
+ return { installed: true, method: 'gemini CLI', version: cli.stdout.trim() };
257
+ }
258
+ return { installed: false, method: '' };
259
+ },
260
+ models: [
261
+ { name: 'gemini-2.5-pro', context_window: 1000000 },
262
+ { name: 'gemini-2.5-flash', context_window: 1000000 },
263
+ ],
264
+ native_tools: ['shell', 'file_read', 'file_write', 'file_edit', 'web_search'],
265
+ mcp_support: true,
266
+ mcp_config_format: '.gemini/antigravity/mcp_config.json',
267
+ skills_support: false,
268
+ rules_support: false,
269
+ hooks_support: false,
270
+ instruction_file: 'GEMINI.md',
271
+ },
272
+ {
273
+ name: 'continue',
274
+ detect: (_home, env) => {
275
+ if (env.CONTINUE_AGENT || env.CONTINUE_SESSION_ID) {
276
+ return { installed: true, method: 'CONTINUE_* env' };
277
+ }
278
+ const vscodeExt = path.join(_home, '.vscode', 'extensions');
279
+ if (fs.existsSync(vscodeExt)) {
280
+ try {
281
+ const exts = fs.readdirSync(vscodeExt);
282
+ if (exts.some(e => e.includes('continue'))) {
283
+ return { installed: true, method: 'VS Code extension' };
284
+ }
285
+ }
286
+ catch { /* non-fatal */ }
287
+ }
288
+ return { installed: false, method: '' };
289
+ },
290
+ models: [
291
+ { name: 'claude-sonnet-4-6', context_window: 200000 },
292
+ { name: 'gpt-4o', context_window: 128000 },
293
+ ],
294
+ native_tools: ['edit', 'terminal', 'codebase-search'],
295
+ mcp_support: true,
296
+ mcp_config_format: '.continue/config.json',
297
+ skills_support: false,
298
+ rules_support: true,
299
+ hooks_support: false,
300
+ instruction_file: '.continue/rules/',
301
+ },
302
+ ];
303
+ // ── Public API ─────────────────────────────────────────────────────────────────
304
+ /**
305
+ * Detect ALL installed agents on this machine (not just the running one).
306
+ */
307
+ export function buildAgentInventory(homeDir = os.homedir(), env = process.env) {
308
+ const agents = AGENT_DEFINITIONS.map(def => {
309
+ const detection = def.detect(homeDir, env);
310
+ return {
311
+ name: def.name,
312
+ installed: detection.installed,
313
+ detection_method: detection.method,
314
+ version: detection.version,
315
+ models: def.models,
316
+ native_tools: def.native_tools,
317
+ mcp_support: def.mcp_support,
318
+ mcp_config_format: def.mcp_config_format,
319
+ skills_support: def.skills_support,
320
+ skills_path_pattern: def.skills_path_pattern,
321
+ rules_support: def.rules_support,
322
+ hooks_support: def.hooks_support,
323
+ instruction_file: def.instruction_file,
324
+ };
325
+ });
326
+ return {
327
+ schema_version: 1,
328
+ generated_at: new Date().toISOString(),
329
+ agents,
330
+ };
331
+ }
332
+ /**
333
+ * Path to the agent inventory file.
334
+ */
335
+ export function agentInventoryPath() {
336
+ return path.join(os.homedir(), MEMORY_DIR, 'agents-inventory.yaml');
337
+ }
338
+ /**
339
+ * Save agent inventory to ~/.brainclaw/agents-inventory.yaml.
340
+ */
341
+ export function saveAgentInventory(inventory) {
342
+ const filePath = agentInventoryPath();
343
+ const dir = path.dirname(filePath);
344
+ if (!fs.existsSync(dir)) {
345
+ fs.mkdirSync(dir, { recursive: true });
346
+ }
347
+ const content = yaml.stringify(inventory, { lineWidth: 120 });
348
+ fs.writeFileSync(filePath, content, 'utf-8');
349
+ return filePath;
350
+ }
351
+ /**
352
+ * Load agent inventory from ~/.brainclaw/agents-inventory.yaml.
353
+ */
354
+ export function loadAgentInventory() {
355
+ const filePath = agentInventoryPath();
356
+ if (!fs.existsSync(filePath))
357
+ return undefined;
358
+ try {
359
+ const content = fs.readFileSync(filePath, 'utf-8');
360
+ return yaml.parse(content);
361
+ }
362
+ catch {
363
+ return undefined;
364
+ }
365
+ }
366
+ /**
367
+ * Render a human-readable summary of the agent inventory.
368
+ */
369
+ export function renderAgentInventorySummary(inventory) {
370
+ const lines = [];
371
+ const installed = inventory.agents.filter(a => a.installed);
372
+ const notInstalled = inventory.agents.filter(a => !a.installed);
373
+ lines.push(`Agents detected: ${installed.length}/${inventory.agents.length}`);
374
+ lines.push('');
375
+ for (const agent of installed) {
376
+ const ver = agent.version ? ` v${agent.version}` : '';
377
+ lines.push(`✔ ${agent.name}${ver} (${agent.detection_method})`);
378
+ lines.push(` Models: ${agent.models.map(m => m.name).join(', ')}`);
379
+ lines.push(` Tools: ${agent.native_tools.join(', ')}`);
380
+ const features = [];
381
+ if (agent.mcp_support)
382
+ features.push('MCP');
383
+ if (agent.skills_support)
384
+ features.push('Skills');
385
+ if (agent.rules_support)
386
+ features.push('Rules');
387
+ if (agent.hooks_support)
388
+ features.push('Hooks');
389
+ lines.push(` Features: ${features.join(', ') || 'none'}`);
390
+ if (agent.instruction_file) {
391
+ lines.push(` Instructions: ${agent.instruction_file}`);
392
+ }
393
+ lines.push('');
394
+ }
395
+ if (notInstalled.length > 0) {
396
+ lines.push(`Not detected: ${notInstalled.map(a => a.name).join(', ')}`);
397
+ }
398
+ lines.push(`Inventory generated: ${inventory.generated_at}`);
399
+ return lines.join('\n');
400
+ }
401
+ //# sourceMappingURL=agent-inventory.js.map