memorix 1.2.0 → 1.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/CHANGELOG.md +30 -1
- package/README.md +18 -4
- package/README.zh-CN.md +18 -4
- package/TEAM.md +86 -86
- package/dist/cli/index.js +15919 -14055
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +1997 -1021
- package/dist/index.js.map +1 -1
- package/dist/maintenance-runner.d.ts +1 -1
- package/dist/maintenance-runner.js +8481 -8005
- package/dist/maintenance-runner.js.map +1 -1
- package/dist/memcode-runtime/CHANGELOG.md +30 -1
- package/dist/sdk.d.ts +7 -2
- package/dist/sdk.js +2022 -1024
- package/dist/sdk.js.map +1 -1
- package/dist/types.d.ts +49 -1
- package/dist/types.js.map +1 -1
- package/docs/1.2.2-MEMORY-CONTROL-PLANE.md +434 -0
- package/docs/AGENT_OPERATOR_PLAYBOOK.md +4 -0
- package/docs/API_REFERENCE.md +27 -5
- package/docs/DESIGN_DECISIONS.md +357 -357
- package/docs/DEVELOPMENT.md +4 -0
- package/docs/README.md +1 -1
- package/docs/SETUP.md +7 -1
- package/docs/dev-log/progress.txt +91 -11
- package/docs/knowledge/workflows/memorix-release.md +57 -0
- package/package.json +1 -1
- package/plugins/codex/memorix/.codex-plugin/plugin.json +1 -1
- package/src/audit/index.ts +156 -156
- package/src/cli/command-guide.ts +192 -0
- package/src/cli/commands/audit-list.ts +89 -89
- package/src/cli/commands/audit.ts +9 -4
- package/src/cli/commands/background.ts +659 -659
- package/src/cli/commands/cleanup.ts +5 -1
- package/src/cli/commands/codegraph.ts +17 -8
- package/src/cli/commands/context.ts +3 -2
- package/src/cli/commands/doctor.ts +4 -2
- package/src/cli/commands/explain.ts +9 -3
- package/src/cli/commands/formation.ts +48 -48
- package/src/cli/commands/git-hook-install.ts +111 -111
- package/src/cli/commands/handoff.ts +75 -61
- package/src/cli/commands/hooks-status.ts +63 -63
- package/src/cli/commands/identity.ts +116 -0
- package/src/cli/commands/ingest-commit.ts +153 -153
- package/src/cli/commands/ingest-image.ts +71 -69
- package/src/cli/commands/ingest-log.ts +180 -180
- package/src/cli/commands/ingest.ts +44 -44
- package/src/cli/commands/integrate-shared.ts +15 -15
- package/src/cli/commands/knowledge.ts +40 -0
- package/src/cli/commands/lock.ts +93 -92
- package/src/cli/commands/memory.ts +58 -21
- package/src/cli/commands/message.ts +123 -118
- package/src/cli/commands/operator-shared.ts +98 -3
- package/src/cli/commands/poll.ts +74 -64
- package/src/cli/commands/purge-all-memory.ts +85 -85
- package/src/cli/commands/purge-project-memory.ts +83 -83
- package/src/cli/commands/reasoning.ts +135 -121
- package/src/cli/commands/retention.ts +9 -4
- package/src/cli/commands/serve-http.ts +22 -43
- package/src/cli/commands/serve-shared.ts +118 -118
- package/src/cli/commands/session.ts +29 -3
- package/src/cli/commands/setup.ts +9 -3
- package/src/cli/commands/skills.ts +124 -119
- package/src/cli/commands/status.ts +4 -3
- package/src/cli/commands/task.ts +193 -184
- package/src/cli/commands/team.ts +14 -10
- package/src/cli/commands/transfer.ts +108 -55
- package/src/cli/commands/uninstall-project-artifacts.ts +85 -85
- package/src/cli/identity.ts +89 -0
- package/src/cli/index.ts +96 -19
- package/src/cli/invocation.ts +115 -0
- package/src/cli/tui/ChatView.tsx +234 -234
- package/src/cli/tui/CommandBar.tsx +312 -312
- package/src/cli/tui/ContextRail.tsx +118 -118
- package/src/cli/tui/HeaderBar.tsx +72 -72
- package/src/cli/tui/LogoBanner.tsx +51 -51
- package/src/cli/tui/Sidebar.tsx +179 -179
- package/src/cli/tui/chat-service.ts +41 -18
- package/src/cli/tui/data.ts +23 -44
- package/src/cli/tui/index.ts +41 -41
- package/src/cli/tui/markdown-render.tsx +371 -371
- package/src/cli/tui/operator-context.ts +60 -0
- package/src/cli/tui/use-mouse.ts +157 -157
- package/src/cli/tui/useNavigation.ts +56 -56
- package/src/cli/tui/views/MemoryView.tsx +10 -8
- package/src/cli/update-checker.ts +211 -211
- package/src/cli/version.ts +7 -7
- package/src/cli/workbench.ts +1 -1
- package/src/codegraph/auto-context.ts +34 -17
- package/src/codegraph/context-pack.ts +1 -0
- package/src/codegraph/current-facts.ts +19 -1
- package/src/codegraph/project-context.ts +2 -0
- package/src/codegraph/task-lens.ts +49 -5
- package/src/compact/engine.ts +26 -10
- package/src/compact/index-format.ts +25 -2
- package/src/compact/token-budget.ts +74 -74
- package/src/dashboard/project-classification.ts +64 -64
- package/src/dashboard/server.ts +58 -52
- package/src/embedding/fastembed-provider.ts +142 -142
- package/src/embedding/transformers-provider.ts +111 -111
- package/src/git/extractor.ts +209 -209
- package/src/git/hooks-path.ts +85 -85
- package/src/hooks/admission.ts +117 -0
- package/src/hooks/handler.ts +98 -91
- package/src/hooks/pattern-detector.ts +173 -173
- package/src/hooks/significance-filter.ts +250 -250
- package/src/knowledge/claims.ts +51 -1
- package/src/knowledge/context-assembly.ts +97 -0
- package/src/knowledge/types.ts +1 -0
- package/src/knowledge/workflows.ts +34 -3
- package/src/knowledge/workset.ts +179 -10
- package/src/llm/memory-manager.ts +328 -328
- package/src/llm/provider.ts +885 -885
- package/src/llm/quality.ts +248 -248
- package/src/memory/admission.ts +57 -0
- package/src/memory/attribution-guard.ts +249 -249
- package/src/memory/auto-relations.ts +21 -0
- package/src/memory/consolidation.ts +13 -2
- package/src/memory/disclosure-policy.ts +140 -135
- package/src/memory/entity-extractor.ts +197 -197
- package/src/memory/export-import.ts +11 -3
- package/src/memory/formation/evaluate.ts +217 -217
- package/src/memory/formation/extract.ts +361 -361
- package/src/memory/formation/index.ts +417 -417
- package/src/memory/formation/resolve.ts +344 -344
- package/src/memory/formation/types.ts +315 -315
- package/src/memory/freshness.ts +122 -122
- package/src/memory/graph-context.ts +8 -2
- package/src/memory/graph-scope.ts +46 -0
- package/src/memory/graph.ts +197 -197
- package/src/memory/observations.ts +162 -4
- package/src/memory/quality-audit.ts +2 -0
- package/src/memory/refs.ts +94 -94
- package/src/memory/retention.ts +22 -2
- package/src/memory/secret-filter.ts +79 -79
- package/src/memory/session.ts +5 -2
- package/src/memory/visibility.ts +80 -0
- package/src/multimodal/image-loader.ts +143 -143
- package/src/orchestrate/adapters/claude-stream.ts +192 -192
- package/src/orchestrate/adapters/claude.ts +111 -111
- package/src/orchestrate/adapters/codex-stream.ts +134 -134
- package/src/orchestrate/adapters/codex.ts +41 -41
- package/src/orchestrate/adapters/gemini-stream.ts +166 -166
- package/src/orchestrate/adapters/gemini.ts +42 -42
- package/src/orchestrate/adapters/index.ts +73 -73
- package/src/orchestrate/adapters/opencode-stream.ts +143 -143
- package/src/orchestrate/adapters/opencode.ts +47 -47
- package/src/orchestrate/adapters/spawn-helper.ts +286 -286
- package/src/orchestrate/adapters/types.ts +77 -77
- package/src/orchestrate/capability-router.ts +284 -284
- package/src/orchestrate/context-compact.ts +188 -188
- package/src/orchestrate/cost-tracker.ts +219 -219
- package/src/orchestrate/error-recovery.ts +191 -191
- package/src/orchestrate/evidence.ts +140 -140
- package/src/orchestrate/ledger.ts +110 -110
- package/src/orchestrate/memorix-bridge.ts +378 -340
- package/src/orchestrate/output-budget.ts +80 -80
- package/src/orchestrate/permission.ts +152 -152
- package/src/orchestrate/pipeline-trace.ts +131 -131
- package/src/orchestrate/prompt-builder.ts +155 -155
- package/src/orchestrate/ring-buffer.ts +37 -37
- package/src/orchestrate/task-graph.ts +389 -389
- package/src/orchestrate/verify-gate.ts +33 -10
- package/src/orchestrate/worktree.ts +232 -232
- package/src/project/aliases.ts +374 -374
- package/src/project/detector.ts +268 -268
- package/src/rules/adapters/claude-code.ts +99 -99
- package/src/rules/adapters/codex.ts +97 -97
- package/src/rules/adapters/copilot.ts +124 -124
- package/src/rules/adapters/cursor.ts +114 -114
- package/src/rules/adapters/kiro.ts +126 -126
- package/src/rules/adapters/trae.ts +56 -56
- package/src/rules/adapters/windsurf.ts +83 -83
- package/src/rules/syncer.ts +235 -235
- package/src/runtime/control-plane-maintenance.ts +1 -0
- package/src/runtime/isolated-maintenance.ts +1 -0
- package/src/runtime/lifecycle.ts +18 -0
- package/src/runtime/maintenance-jobs.ts +1 -0
- package/src/runtime/maintenance-runner.ts +2 -0
- package/src/runtime/project-maintenance.ts +89 -0
- package/src/sdk.ts +334 -304
- package/src/search/intent-detector.ts +289 -289
- package/src/search/query-expansion.ts +52 -52
- package/src/server/formation-timeout.ts +27 -27
- package/src/server.ts +334 -93
- package/src/skills/mini-skills.ts +386 -386
- package/src/store/chat-store.ts +119 -119
- package/src/store/graph-store.ts +249 -249
- package/src/store/mini-skill-store.ts +349 -349
- package/src/store/orama-store.ts +61 -6
- package/src/store/persistence-json.ts +212 -212
- package/src/store/persistence.ts +291 -291
- package/src/store/project-affinity.ts +195 -195
- package/src/store/sqlite-db.ts +23 -1
- package/src/store/sqlite-store.ts +12 -2
- package/src/team/event-bus.ts +76 -76
- package/src/team/file-locks.ts +173 -173
- package/src/team/handoff.ts +168 -161
- package/src/team/messages.ts +203 -203
- package/src/team/poll.ts +132 -132
- package/src/team/tasks.ts +211 -211
- package/src/types.ts +51 -0
- package/src/wiki/generator.ts +2 -0
- package/src/workspace/mcp-adapters/codex.ts +191 -191
- package/src/workspace/mcp-adapters/copilot.ts +105 -105
- package/src/workspace/mcp-adapters/cursor.ts +53 -53
- package/src/workspace/mcp-adapters/kiro.ts +64 -64
- package/src/workspace/mcp-adapters/opencode.ts +123 -123
- package/src/workspace/mcp-adapters/trae.ts +134 -134
- package/src/workspace/mcp-adapters/windsurf.ts +91 -91
- package/src/workspace/sanitizer.ts +60 -60
- package/src/workspace/workflow-sync.ts +131 -131
|
@@ -1,53 +1,53 @@
|
|
|
1
|
-
import type { MCPConfigAdapter, MCPServerEntry } from '../../types.js';
|
|
2
|
-
import { homedir } from 'node:os';
|
|
3
|
-
import { join } from 'node:path';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Cursor MCP config adapter.
|
|
7
|
-
* Format: JSON file at ~/.cursor/mcp.json or .cursor/mcp.json (project-level)
|
|
8
|
-
* Structure: { mcpServers: { [name]: { command, args, env?, url? } } }
|
|
9
|
-
*/
|
|
10
|
-
export class CursorMCPAdapter implements MCPConfigAdapter {
|
|
11
|
-
readonly source = 'cursor' as const;
|
|
12
|
-
|
|
13
|
-
parse(content: string): MCPServerEntry[] {
|
|
14
|
-
try {
|
|
15
|
-
const config = JSON.parse(content);
|
|
16
|
-
const servers = config.mcpServers ?? {};
|
|
17
|
-
return Object.entries(servers).map(([name, entry]: [string, any]) => ({
|
|
18
|
-
name,
|
|
19
|
-
command: entry.command ?? '',
|
|
20
|
-
args: entry.args ?? [],
|
|
21
|
-
...(entry.env && Object.keys(entry.env).length > 0 ? { env: entry.env } : {}),
|
|
22
|
-
...(entry.url ? { url: entry.url } : {}),
|
|
23
|
-
}));
|
|
24
|
-
} catch {
|
|
25
|
-
return [];
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
generate(servers: MCPServerEntry[]): string {
|
|
30
|
-
const mcpServers: Record<string, any> = {};
|
|
31
|
-
for (const s of servers) {
|
|
32
|
-
const entry: Record<string, any> = {};
|
|
33
|
-
if (s.url) {
|
|
34
|
-
entry.url = s.url;
|
|
35
|
-
} else {
|
|
36
|
-
entry.command = s.command;
|
|
37
|
-
entry.args = s.args;
|
|
38
|
-
}
|
|
39
|
-
if (s.env && Object.keys(s.env).length > 0) {
|
|
40
|
-
entry.env = s.env;
|
|
41
|
-
}
|
|
42
|
-
mcpServers[s.name] = entry;
|
|
43
|
-
}
|
|
44
|
-
return JSON.stringify({ mcpServers }, null, 2);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
getConfigPath(projectRoot?: string): string {
|
|
48
|
-
if (projectRoot) {
|
|
49
|
-
return join(projectRoot, '.cursor', 'mcp.json');
|
|
50
|
-
}
|
|
51
|
-
return join(homedir(), '.cursor', 'mcp.json');
|
|
52
|
-
}
|
|
53
|
-
}
|
|
1
|
+
import type { MCPConfigAdapter, MCPServerEntry } from '../../types.js';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Cursor MCP config adapter.
|
|
7
|
+
* Format: JSON file at ~/.cursor/mcp.json or .cursor/mcp.json (project-level)
|
|
8
|
+
* Structure: { mcpServers: { [name]: { command, args, env?, url? } } }
|
|
9
|
+
*/
|
|
10
|
+
export class CursorMCPAdapter implements MCPConfigAdapter {
|
|
11
|
+
readonly source = 'cursor' as const;
|
|
12
|
+
|
|
13
|
+
parse(content: string): MCPServerEntry[] {
|
|
14
|
+
try {
|
|
15
|
+
const config = JSON.parse(content);
|
|
16
|
+
const servers = config.mcpServers ?? {};
|
|
17
|
+
return Object.entries(servers).map(([name, entry]: [string, any]) => ({
|
|
18
|
+
name,
|
|
19
|
+
command: entry.command ?? '',
|
|
20
|
+
args: entry.args ?? [],
|
|
21
|
+
...(entry.env && Object.keys(entry.env).length > 0 ? { env: entry.env } : {}),
|
|
22
|
+
...(entry.url ? { url: entry.url } : {}),
|
|
23
|
+
}));
|
|
24
|
+
} catch {
|
|
25
|
+
return [];
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
generate(servers: MCPServerEntry[]): string {
|
|
30
|
+
const mcpServers: Record<string, any> = {};
|
|
31
|
+
for (const s of servers) {
|
|
32
|
+
const entry: Record<string, any> = {};
|
|
33
|
+
if (s.url) {
|
|
34
|
+
entry.url = s.url;
|
|
35
|
+
} else {
|
|
36
|
+
entry.command = s.command;
|
|
37
|
+
entry.args = s.args;
|
|
38
|
+
}
|
|
39
|
+
if (s.env && Object.keys(s.env).length > 0) {
|
|
40
|
+
entry.env = s.env;
|
|
41
|
+
}
|
|
42
|
+
mcpServers[s.name] = entry;
|
|
43
|
+
}
|
|
44
|
+
return JSON.stringify({ mcpServers }, null, 2);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
getConfigPath(projectRoot?: string): string {
|
|
48
|
+
if (projectRoot) {
|
|
49
|
+
return join(projectRoot, '.cursor', 'mcp.json');
|
|
50
|
+
}
|
|
51
|
+
return join(homedir(), '.cursor', 'mcp.json');
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -1,64 +1,64 @@
|
|
|
1
|
-
import type { MCPConfigAdapter, MCPServerEntry } from '../../types.js';
|
|
2
|
-
import { homedir } from 'node:os';
|
|
3
|
-
import { join } from 'node:path';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Kiro MCP config adapter.
|
|
7
|
-
* Format: JSON file at .kiro/settings/mcp.json (project-level)
|
|
8
|
-
* or ~/.kiro/settings/mcp.json (user-level)
|
|
9
|
-
* Structure: { mcpServers: { ... }, powers?: { mcpServers: { ... } } }
|
|
10
|
-
*
|
|
11
|
-
* Kiro stores user-added servers in `mcpServers` and power-installed
|
|
12
|
-
* servers (context7, figma, postman, supabase etc.) in `powers.mcpServers`.
|
|
13
|
-
* Both sections use the same entry format.
|
|
14
|
-
*
|
|
15
|
-
* Source: Kiro official MCP documentation.
|
|
16
|
-
*/
|
|
17
|
-
export class KiroMCPAdapter implements MCPConfigAdapter {
|
|
18
|
-
readonly source = 'kiro' as const;
|
|
19
|
-
|
|
20
|
-
parse(content: string): MCPServerEntry[] {
|
|
21
|
-
try {
|
|
22
|
-
const config = JSON.parse(content);
|
|
23
|
-
// Merge top-level mcpServers and powers.mcpServers (dedup by name)
|
|
24
|
-
const topLevel = config.mcpServers ?? {};
|
|
25
|
-
const powers = config.powers?.mcpServers ?? {};
|
|
26
|
-
const merged = { ...powers, ...topLevel };
|
|
27
|
-
return Object.entries(merged).map(([name, entry]: [string, any]) => ({
|
|
28
|
-
name,
|
|
29
|
-
command: entry.command ?? '',
|
|
30
|
-
args: entry.args ?? [],
|
|
31
|
-
...(entry.env && Object.keys(entry.env).length > 0 ? { env: entry.env } : {}),
|
|
32
|
-
...(entry.url ? { url: entry.url } : {}),
|
|
33
|
-
...(entry.disabled === true ? { disabled: true } : {}),
|
|
34
|
-
}));
|
|
35
|
-
} catch {
|
|
36
|
-
return [];
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
generate(servers: MCPServerEntry[]): string {
|
|
41
|
-
const mcpServers: Record<string, any> = {};
|
|
42
|
-
for (const s of servers) {
|
|
43
|
-
const entry: Record<string, any> = {};
|
|
44
|
-
if (s.url) {
|
|
45
|
-
entry.url = s.url;
|
|
46
|
-
} else {
|
|
47
|
-
entry.command = s.command;
|
|
48
|
-
entry.args = s.args;
|
|
49
|
-
}
|
|
50
|
-
if (s.env && Object.keys(s.env).length > 0) {
|
|
51
|
-
entry.env = s.env;
|
|
52
|
-
}
|
|
53
|
-
mcpServers[s.name] = entry;
|
|
54
|
-
}
|
|
55
|
-
return JSON.stringify({ mcpServers }, null, 2);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
getConfigPath(projectRoot?: string): string {
|
|
59
|
-
if (projectRoot) {
|
|
60
|
-
return join(projectRoot, '.kiro', 'settings', 'mcp.json');
|
|
61
|
-
}
|
|
62
|
-
return join(homedir(), '.kiro', 'settings', 'mcp.json');
|
|
63
|
-
}
|
|
64
|
-
}
|
|
1
|
+
import type { MCPConfigAdapter, MCPServerEntry } from '../../types.js';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Kiro MCP config adapter.
|
|
7
|
+
* Format: JSON file at .kiro/settings/mcp.json (project-level)
|
|
8
|
+
* or ~/.kiro/settings/mcp.json (user-level)
|
|
9
|
+
* Structure: { mcpServers: { ... }, powers?: { mcpServers: { ... } } }
|
|
10
|
+
*
|
|
11
|
+
* Kiro stores user-added servers in `mcpServers` and power-installed
|
|
12
|
+
* servers (context7, figma, postman, supabase etc.) in `powers.mcpServers`.
|
|
13
|
+
* Both sections use the same entry format.
|
|
14
|
+
*
|
|
15
|
+
* Source: Kiro official MCP documentation.
|
|
16
|
+
*/
|
|
17
|
+
export class KiroMCPAdapter implements MCPConfigAdapter {
|
|
18
|
+
readonly source = 'kiro' as const;
|
|
19
|
+
|
|
20
|
+
parse(content: string): MCPServerEntry[] {
|
|
21
|
+
try {
|
|
22
|
+
const config = JSON.parse(content);
|
|
23
|
+
// Merge top-level mcpServers and powers.mcpServers (dedup by name)
|
|
24
|
+
const topLevel = config.mcpServers ?? {};
|
|
25
|
+
const powers = config.powers?.mcpServers ?? {};
|
|
26
|
+
const merged = { ...powers, ...topLevel };
|
|
27
|
+
return Object.entries(merged).map(([name, entry]: [string, any]) => ({
|
|
28
|
+
name,
|
|
29
|
+
command: entry.command ?? '',
|
|
30
|
+
args: entry.args ?? [],
|
|
31
|
+
...(entry.env && Object.keys(entry.env).length > 0 ? { env: entry.env } : {}),
|
|
32
|
+
...(entry.url ? { url: entry.url } : {}),
|
|
33
|
+
...(entry.disabled === true ? { disabled: true } : {}),
|
|
34
|
+
}));
|
|
35
|
+
} catch {
|
|
36
|
+
return [];
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
generate(servers: MCPServerEntry[]): string {
|
|
41
|
+
const mcpServers: Record<string, any> = {};
|
|
42
|
+
for (const s of servers) {
|
|
43
|
+
const entry: Record<string, any> = {};
|
|
44
|
+
if (s.url) {
|
|
45
|
+
entry.url = s.url;
|
|
46
|
+
} else {
|
|
47
|
+
entry.command = s.command;
|
|
48
|
+
entry.args = s.args;
|
|
49
|
+
}
|
|
50
|
+
if (s.env && Object.keys(s.env).length > 0) {
|
|
51
|
+
entry.env = s.env;
|
|
52
|
+
}
|
|
53
|
+
mcpServers[s.name] = entry;
|
|
54
|
+
}
|
|
55
|
+
return JSON.stringify({ mcpServers }, null, 2);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
getConfigPath(projectRoot?: string): string {
|
|
59
|
+
if (projectRoot) {
|
|
60
|
+
return join(projectRoot, '.kiro', 'settings', 'mcp.json');
|
|
61
|
+
}
|
|
62
|
+
return join(homedir(), '.kiro', 'settings', 'mcp.json');
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -1,123 +1,123 @@
|
|
|
1
|
-
import type { MCPConfigAdapter, MCPServerEntry } from '../../types.js';
|
|
2
|
-
import { homedir } from 'node:os';
|
|
3
|
-
import { join } from 'node:path';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* OpenCode MCP Configuration Adapter.
|
|
7
|
-
*
|
|
8
|
-
* OpenCode uses JSON config files for MCP servers:
|
|
9
|
-
* 1. Project-level: opencode.json in project root
|
|
10
|
-
* 2. Global: ~/.config/opencode/opencode.json
|
|
11
|
-
*
|
|
12
|
-
* Format:
|
|
13
|
-
* {
|
|
14
|
-
* "$schema": "https://opencode.ai/config.json",
|
|
15
|
-
* "mcp": {
|
|
16
|
-
* "name": {
|
|
17
|
-
* "type": "local",
|
|
18
|
-
* "command": ["memorix", "serve"],
|
|
19
|
-
* "environment": { "KEY": "value" },
|
|
20
|
-
* "enabled": true
|
|
21
|
-
* }
|
|
22
|
-
* }
|
|
23
|
-
* }
|
|
24
|
-
*
|
|
25
|
-
* Remote (HTTP) servers:
|
|
26
|
-
* {
|
|
27
|
-
* "mcp": {
|
|
28
|
-
* "name": {
|
|
29
|
-
* "type": "remote",
|
|
30
|
-
* "url": "https://...",
|
|
31
|
-
* "headers": { "Authorization": "Bearer ..." }
|
|
32
|
-
* }
|
|
33
|
-
* }
|
|
34
|
-
* }
|
|
35
|
-
*
|
|
36
|
-
* Source: https://opencode.ai/docs/mcp-servers/
|
|
37
|
-
*/
|
|
38
|
-
export class OpenCodeMCPAdapter implements MCPConfigAdapter {
|
|
39
|
-
readonly source = 'opencode' as const;
|
|
40
|
-
|
|
41
|
-
parse(content: string): MCPServerEntry[] {
|
|
42
|
-
try {
|
|
43
|
-
const config = JSON.parse(content);
|
|
44
|
-
const servers = config.mcp ?? {};
|
|
45
|
-
return Object.entries(servers).map(([name, entry]: [string, any]) => {
|
|
46
|
-
const result: MCPServerEntry = {
|
|
47
|
-
name,
|
|
48
|
-
command: '',
|
|
49
|
-
args: [],
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
if (entry.type === 'remote' && entry.url) {
|
|
53
|
-
// HTTP transport
|
|
54
|
-
result.url = entry.url;
|
|
55
|
-
if (entry.headers && typeof entry.headers === 'object' && Object.keys(entry.headers).length > 0) {
|
|
56
|
-
result.headers = entry.headers;
|
|
57
|
-
}
|
|
58
|
-
} else {
|
|
59
|
-
// Local (stdio) transport — command is an array in OpenCode
|
|
60
|
-
if (Array.isArray(entry.command) && entry.command.length > 0) {
|
|
61
|
-
result.command = entry.command[0];
|
|
62
|
-
result.args = entry.command.slice(1);
|
|
63
|
-
} else if (typeof entry.command === 'string') {
|
|
64
|
-
result.command = entry.command;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// Environment variables (OpenCode uses "environment" not "env")
|
|
69
|
-
const env = entry.environment ?? entry.env;
|
|
70
|
-
if (env && typeof env === 'object' && Object.keys(env).length > 0) {
|
|
71
|
-
result.env = env;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// Disabled flag
|
|
75
|
-
if (entry.enabled === false) {
|
|
76
|
-
result.disabled = true;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
return result;
|
|
80
|
-
});
|
|
81
|
-
} catch {
|
|
82
|
-
return [];
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
generate(servers: MCPServerEntry[]): string {
|
|
87
|
-
const mcp: Record<string, any> = {};
|
|
88
|
-
for (const s of servers) {
|
|
89
|
-
const entry: Record<string, any> = {};
|
|
90
|
-
|
|
91
|
-
if (s.url) {
|
|
92
|
-
// HTTP transport
|
|
93
|
-
entry.type = 'remote';
|
|
94
|
-
entry.url = s.url;
|
|
95
|
-
if (s.headers && Object.keys(s.headers).length > 0) {
|
|
96
|
-
entry.headers = s.headers;
|
|
97
|
-
}
|
|
98
|
-
} else {
|
|
99
|
-
// stdio transport — OpenCode uses command as array
|
|
100
|
-
entry.type = 'local';
|
|
101
|
-
entry.command = [s.command, ...s.args];
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
if (s.env && Object.keys(s.env).length > 0) {
|
|
105
|
-
entry.environment = s.env;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
if (s.disabled === true) {
|
|
109
|
-
entry.enabled = false;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
mcp[s.name] = entry;
|
|
113
|
-
}
|
|
114
|
-
return JSON.stringify({ $schema: 'https://opencode.ai/config.json', mcp }, null, 2);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
getConfigPath(projectRoot?: string): string {
|
|
118
|
-
if (projectRoot) {
|
|
119
|
-
return join(projectRoot, 'opencode.json');
|
|
120
|
-
}
|
|
121
|
-
return join(homedir(), '.config', 'opencode', 'opencode.json');
|
|
122
|
-
}
|
|
123
|
-
}
|
|
1
|
+
import type { MCPConfigAdapter, MCPServerEntry } from '../../types.js';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* OpenCode MCP Configuration Adapter.
|
|
7
|
+
*
|
|
8
|
+
* OpenCode uses JSON config files for MCP servers:
|
|
9
|
+
* 1. Project-level: opencode.json in project root
|
|
10
|
+
* 2. Global: ~/.config/opencode/opencode.json
|
|
11
|
+
*
|
|
12
|
+
* Format:
|
|
13
|
+
* {
|
|
14
|
+
* "$schema": "https://opencode.ai/config.json",
|
|
15
|
+
* "mcp": {
|
|
16
|
+
* "name": {
|
|
17
|
+
* "type": "local",
|
|
18
|
+
* "command": ["memorix", "serve"],
|
|
19
|
+
* "environment": { "KEY": "value" },
|
|
20
|
+
* "enabled": true
|
|
21
|
+
* }
|
|
22
|
+
* }
|
|
23
|
+
* }
|
|
24
|
+
*
|
|
25
|
+
* Remote (HTTP) servers:
|
|
26
|
+
* {
|
|
27
|
+
* "mcp": {
|
|
28
|
+
* "name": {
|
|
29
|
+
* "type": "remote",
|
|
30
|
+
* "url": "https://...",
|
|
31
|
+
* "headers": { "Authorization": "Bearer ..." }
|
|
32
|
+
* }
|
|
33
|
+
* }
|
|
34
|
+
* }
|
|
35
|
+
*
|
|
36
|
+
* Source: https://opencode.ai/docs/mcp-servers/
|
|
37
|
+
*/
|
|
38
|
+
export class OpenCodeMCPAdapter implements MCPConfigAdapter {
|
|
39
|
+
readonly source = 'opencode' as const;
|
|
40
|
+
|
|
41
|
+
parse(content: string): MCPServerEntry[] {
|
|
42
|
+
try {
|
|
43
|
+
const config = JSON.parse(content);
|
|
44
|
+
const servers = config.mcp ?? {};
|
|
45
|
+
return Object.entries(servers).map(([name, entry]: [string, any]) => {
|
|
46
|
+
const result: MCPServerEntry = {
|
|
47
|
+
name,
|
|
48
|
+
command: '',
|
|
49
|
+
args: [],
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
if (entry.type === 'remote' && entry.url) {
|
|
53
|
+
// HTTP transport
|
|
54
|
+
result.url = entry.url;
|
|
55
|
+
if (entry.headers && typeof entry.headers === 'object' && Object.keys(entry.headers).length > 0) {
|
|
56
|
+
result.headers = entry.headers;
|
|
57
|
+
}
|
|
58
|
+
} else {
|
|
59
|
+
// Local (stdio) transport — command is an array in OpenCode
|
|
60
|
+
if (Array.isArray(entry.command) && entry.command.length > 0) {
|
|
61
|
+
result.command = entry.command[0];
|
|
62
|
+
result.args = entry.command.slice(1);
|
|
63
|
+
} else if (typeof entry.command === 'string') {
|
|
64
|
+
result.command = entry.command;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Environment variables (OpenCode uses "environment" not "env")
|
|
69
|
+
const env = entry.environment ?? entry.env;
|
|
70
|
+
if (env && typeof env === 'object' && Object.keys(env).length > 0) {
|
|
71
|
+
result.env = env;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Disabled flag
|
|
75
|
+
if (entry.enabled === false) {
|
|
76
|
+
result.disabled = true;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return result;
|
|
80
|
+
});
|
|
81
|
+
} catch {
|
|
82
|
+
return [];
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
generate(servers: MCPServerEntry[]): string {
|
|
87
|
+
const mcp: Record<string, any> = {};
|
|
88
|
+
for (const s of servers) {
|
|
89
|
+
const entry: Record<string, any> = {};
|
|
90
|
+
|
|
91
|
+
if (s.url) {
|
|
92
|
+
// HTTP transport
|
|
93
|
+
entry.type = 'remote';
|
|
94
|
+
entry.url = s.url;
|
|
95
|
+
if (s.headers && Object.keys(s.headers).length > 0) {
|
|
96
|
+
entry.headers = s.headers;
|
|
97
|
+
}
|
|
98
|
+
} else {
|
|
99
|
+
// stdio transport — OpenCode uses command as array
|
|
100
|
+
entry.type = 'local';
|
|
101
|
+
entry.command = [s.command, ...s.args];
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (s.env && Object.keys(s.env).length > 0) {
|
|
105
|
+
entry.environment = s.env;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (s.disabled === true) {
|
|
109
|
+
entry.enabled = false;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
mcp[s.name] = entry;
|
|
113
|
+
}
|
|
114
|
+
return JSON.stringify({ $schema: 'https://opencode.ai/config.json', mcp }, null, 2);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
getConfigPath(projectRoot?: string): string {
|
|
118
|
+
if (projectRoot) {
|
|
119
|
+
return join(projectRoot, 'opencode.json');
|
|
120
|
+
}
|
|
121
|
+
return join(homedir(), '.config', 'opencode', 'opencode.json');
|
|
122
|
+
}
|
|
123
|
+
}
|