fixo-cli 1.0.0
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/LICENSE +201 -0
- package/README.md +530 -0
- package/dist/agent/agent-client.d.ts +108 -0
- package/dist/agent/agent-client.d.ts.map +1 -0
- package/dist/agent/agent-client.js +1247 -0
- package/dist/agent/agent-client.js.map +1 -0
- package/dist/agent/agent-pool.d.ts +20 -0
- package/dist/agent/agent-pool.d.ts.map +1 -0
- package/dist/agent/agent-pool.js +217 -0
- package/dist/agent/agent-pool.js.map +1 -0
- package/dist/agent/background-awareness.d.ts +55 -0
- package/dist/agent/background-awareness.d.ts.map +1 -0
- package/dist/agent/background-awareness.js +104 -0
- package/dist/agent/background-awareness.js.map +1 -0
- package/dist/agent/command-parser.d.ts +33 -0
- package/dist/agent/command-parser.d.ts.map +1 -0
- package/dist/agent/command-parser.js +120 -0
- package/dist/agent/command-parser.js.map +1 -0
- package/dist/agent/context-budget.d.ts +91 -0
- package/dist/agent/context-budget.d.ts.map +1 -0
- package/dist/agent/context-budget.js +219 -0
- package/dist/agent/context-budget.js.map +1 -0
- package/dist/agent/conversation.d.ts +190 -0
- package/dist/agent/conversation.d.ts.map +1 -0
- package/dist/agent/conversation.js +547 -0
- package/dist/agent/conversation.js.map +1 -0
- package/dist/agent/hooks.d.ts +72 -0
- package/dist/agent/hooks.d.ts.map +1 -0
- package/dist/agent/hooks.js +214 -0
- package/dist/agent/hooks.js.map +1 -0
- package/dist/agent/mcp-bridge.d.ts +13 -0
- package/dist/agent/mcp-bridge.d.ts.map +1 -0
- package/dist/agent/mcp-bridge.js +86 -0
- package/dist/agent/mcp-bridge.js.map +1 -0
- package/dist/agent/mcp-client.d.ts +24 -0
- package/dist/agent/mcp-client.d.ts.map +1 -0
- package/dist/agent/mcp-client.js +146 -0
- package/dist/agent/mcp-client.js.map +1 -0
- package/dist/agent/mcp-manager.d.ts +13 -0
- package/dist/agent/mcp-manager.d.ts.map +1 -0
- package/dist/agent/mcp-manager.js +84 -0
- package/dist/agent/mcp-manager.js.map +1 -0
- package/dist/agent/mcp-registry.d.ts +45 -0
- package/dist/agent/mcp-registry.d.ts.map +1 -0
- package/dist/agent/mcp-registry.js +98 -0
- package/dist/agent/mcp-registry.js.map +1 -0
- package/dist/agent/orchestrator.d.ts +14 -0
- package/dist/agent/orchestrator.d.ts.map +1 -0
- package/dist/agent/orchestrator.js +118 -0
- package/dist/agent/orchestrator.js.map +1 -0
- package/dist/agent/parser-adapter.d.ts +120 -0
- package/dist/agent/parser-adapter.d.ts.map +1 -0
- package/dist/agent/parser-adapter.js +265 -0
- package/dist/agent/parser-adapter.js.map +1 -0
- package/dist/agent/parsers/imports.d.ts +11 -0
- package/dist/agent/parsers/imports.d.ts.map +1 -0
- package/dist/agent/parsers/imports.js +94 -0
- package/dist/agent/parsers/imports.js.map +1 -0
- package/dist/agent/parsers/shell.d.ts +23 -0
- package/dist/agent/parsers/shell.d.ts.map +1 -0
- package/dist/agent/parsers/shell.js +200 -0
- package/dist/agent/parsers/shell.js.map +1 -0
- package/dist/agent/parsers/symbols.d.ts +17 -0
- package/dist/agent/parsers/symbols.d.ts.map +1 -0
- package/dist/agent/parsers/symbols.js +103 -0
- package/dist/agent/parsers/symbols.js.map +1 -0
- package/dist/agent/permissions.d.ts +65 -0
- package/dist/agent/permissions.d.ts.map +1 -0
- package/dist/agent/permissions.js +219 -0
- package/dist/agent/permissions.js.map +1 -0
- package/dist/agent/predictive-gate.d.ts +69 -0
- package/dist/agent/predictive-gate.d.ts.map +1 -0
- package/dist/agent/predictive-gate.js +128 -0
- package/dist/agent/predictive-gate.js.map +1 -0
- package/dist/agent/provider-cooldown.d.ts +144 -0
- package/dist/agent/provider-cooldown.d.ts.map +1 -0
- package/dist/agent/provider-cooldown.js +300 -0
- package/dist/agent/provider-cooldown.js.map +1 -0
- package/dist/agent/providers-manager.d.ts +109 -0
- package/dist/agent/providers-manager.d.ts.map +1 -0
- package/dist/agent/providers-manager.js +464 -0
- package/dist/agent/providers-manager.js.map +1 -0
- package/dist/agent/repo-map.d.ts +6 -0
- package/dist/agent/repo-map.d.ts.map +1 -0
- package/dist/agent/repo-map.js +221 -0
- package/dist/agent/repo-map.js.map +1 -0
- package/dist/agent/retry.d.ts +103 -0
- package/dist/agent/retry.d.ts.map +1 -0
- package/dist/agent/retry.js +276 -0
- package/dist/agent/retry.js.map +1 -0
- package/dist/agent/search/index.d.ts +61 -0
- package/dist/agent/search/index.d.ts.map +1 -0
- package/dist/agent/search/index.js +314 -0
- package/dist/agent/search/index.js.map +1 -0
- package/dist/agent/single-agent.d.ts +76 -0
- package/dist/agent/single-agent.d.ts.map +1 -0
- package/dist/agent/single-agent.js +697 -0
- package/dist/agent/single-agent.js.map +1 -0
- package/dist/agent/skills.d.ts +22 -0
- package/dist/agent/skills.d.ts.map +1 -0
- package/dist/agent/skills.js +139 -0
- package/dist/agent/skills.js.map +1 -0
- package/dist/agent/stream-glue.d.ts +85 -0
- package/dist/agent/stream-glue.d.ts.map +1 -0
- package/dist/agent/stream-glue.js +120 -0
- package/dist/agent/stream-glue.js.map +1 -0
- package/dist/agent/subagent.d.ts +72 -0
- package/dist/agent/subagent.d.ts.map +1 -0
- package/dist/agent/subagent.js +193 -0
- package/dist/agent/subagent.js.map +1 -0
- package/dist/agent/telemetry.d.ts +192 -0
- package/dist/agent/telemetry.d.ts.map +1 -0
- package/dist/agent/telemetry.js +400 -0
- package/dist/agent/telemetry.js.map +1 -0
- package/dist/agent/tokenizer.d.ts +42 -0
- package/dist/agent/tokenizer.d.ts.map +1 -0
- package/dist/agent/tokenizer.js +107 -0
- package/dist/agent/tokenizer.js.map +1 -0
- package/dist/agent/tool-executor.d.ts +289 -0
- package/dist/agent/tool-executor.d.ts.map +1 -0
- package/dist/agent/tool-executor.js +2519 -0
- package/dist/agent/tool-executor.js.map +1 -0
- package/dist/agent/web-impl.d.ts +2 -0
- package/dist/agent/web-impl.d.ts.map +1 -0
- package/dist/agent/web-impl.js +34 -0
- package/dist/agent/web-impl.js.map +1 -0
- package/dist/agent/web.d.ts +8 -0
- package/dist/agent/web.d.ts.map +1 -0
- package/dist/agent/web.js +8 -0
- package/dist/agent/web.js.map +1 -0
- package/dist/agent/worker-agent.d.ts +27 -0
- package/dist/agent/worker-agent.d.ts.map +1 -0
- package/dist/agent/worker-agent.js +503 -0
- package/dist/agent/worker-agent.js.map +1 -0
- package/dist/config.d.ts +162 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +138 -0
- package/dist/config.js.map +1 -0
- package/dist/context/fixo-md-watcher.d.ts +42 -0
- package/dist/context/fixo-md-watcher.d.ts.map +1 -0
- package/dist/context/fixo-md-watcher.js +126 -0
- package/dist/context/fixo-md-watcher.js.map +1 -0
- package/dist/context/fixo-md.d.ts +50 -0
- package/dist/context/fixo-md.d.ts.map +1 -0
- package/dist/context/fixo-md.js +118 -0
- package/dist/context/fixo-md.js.map +1 -0
- package/dist/context/todo.d.ts +65 -0
- package/dist/context/todo.d.ts.map +1 -0
- package/dist/context/todo.js +194 -0
- package/dist/context/todo.js.map +1 -0
- package/dist/git/git-manager.d.ts +33 -0
- package/dist/git/git-manager.d.ts.map +1 -0
- package/dist/git/git-manager.js +293 -0
- package/dist/git/git-manager.js.map +1 -0
- package/dist/git/git-ops.d.ts +10 -0
- package/dist/git/git-ops.d.ts.map +1 -0
- package/dist/git/git-ops.js +131 -0
- package/dist/git/git-ops.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +352 -0
- package/dist/index.js.map +1 -0
- package/dist/indexer.d.ts +30 -0
- package/dist/indexer.d.ts.map +1 -0
- package/dist/indexer.js +273 -0
- package/dist/indexer.js.map +1 -0
- package/dist/lsp/lsp-client.d.ts +24 -0
- package/dist/lsp/lsp-client.d.ts.map +1 -0
- package/dist/lsp/lsp-client.js +205 -0
- package/dist/lsp/lsp-client.js.map +1 -0
- package/dist/lsp/lsp-manager.d.ts +17 -0
- package/dist/lsp/lsp-manager.d.ts.map +1 -0
- package/dist/lsp/lsp-manager.js +154 -0
- package/dist/lsp/lsp-manager.js.map +1 -0
- package/dist/lsp/lsp-pre-save.d.ts +137 -0
- package/dist/lsp/lsp-pre-save.d.ts.map +1 -0
- package/dist/lsp/lsp-pre-save.js +245 -0
- package/dist/lsp/lsp-pre-save.js.map +1 -0
- package/dist/lsp/syntax-fallback.d.ts +83 -0
- package/dist/lsp/syntax-fallback.d.ts.map +1 -0
- package/dist/lsp/syntax-fallback.js +275 -0
- package/dist/lsp/syntax-fallback.js.map +1 -0
- package/dist/model-outcomes.d.ts +12 -0
- package/dist/model-outcomes.d.ts.map +1 -0
- package/dist/model-outcomes.js +46 -0
- package/dist/model-outcomes.js.map +1 -0
- package/dist/planner.d.ts +32 -0
- package/dist/planner.d.ts.map +1 -0
- package/dist/planner.js +163 -0
- package/dist/planner.js.map +1 -0
- package/dist/project-memory.d.ts +29 -0
- package/dist/project-memory.d.ts.map +1 -0
- package/dist/project-memory.js +349 -0
- package/dist/project-memory.js.map +1 -0
- package/dist/review.d.ts +2 -0
- package/dist/review.d.ts.map +1 -0
- package/dist/review.js +61 -0
- package/dist/review.js.map +1 -0
- package/dist/runtime/background-jobs.d.ts +97 -0
- package/dist/runtime/background-jobs.d.ts.map +1 -0
- package/dist/runtime/background-jobs.js +331 -0
- package/dist/runtime/background-jobs.js.map +1 -0
- package/dist/runtime/credential-vault.d.ts +124 -0
- package/dist/runtime/credential-vault.d.ts.map +1 -0
- package/dist/runtime/credential-vault.js +184 -0
- package/dist/runtime/credential-vault.js.map +1 -0
- package/dist/runtime/loop-trap.d.ts +197 -0
- package/dist/runtime/loop-trap.d.ts.map +1 -0
- package/dist/runtime/loop-trap.js +420 -0
- package/dist/runtime/loop-trap.js.map +1 -0
- package/dist/runtime/policy.d.ts +15 -0
- package/dist/runtime/policy.d.ts.map +1 -0
- package/dist/runtime/policy.js +60 -0
- package/dist/runtime/policy.js.map +1 -0
- package/dist/runtime/redaction.d.ts +66 -0
- package/dist/runtime/redaction.d.ts.map +1 -0
- package/dist/runtime/redaction.js +155 -0
- package/dist/runtime/redaction.js.map +1 -0
- package/dist/runtime/session-snapshots.d.ts +76 -0
- package/dist/runtime/session-snapshots.d.ts.map +1 -0
- package/dist/runtime/session-snapshots.js +166 -0
- package/dist/runtime/session-snapshots.js.map +1 -0
- package/dist/runtime/staging.d.ts +205 -0
- package/dist/runtime/staging.d.ts.map +1 -0
- package/dist/runtime/staging.js +526 -0
- package/dist/runtime/staging.js.map +1 -0
- package/dist/runtime/task-session.d.ts +95 -0
- package/dist/runtime/task-session.d.ts.map +1 -0
- package/dist/runtime/task-session.js +263 -0
- package/dist/runtime/task-session.js.map +1 -0
- package/dist/runtime/worktree.d.ts +55 -0
- package/dist/runtime/worktree.d.ts.map +1 -0
- package/dist/runtime/worktree.js +175 -0
- package/dist/runtime/worktree.js.map +1 -0
- package/dist/setup-wizard.d.ts +8 -0
- package/dist/setup-wizard.d.ts.map +1 -0
- package/dist/setup-wizard.js +73 -0
- package/dist/setup-wizard.js.map +1 -0
- package/dist/shared/content.d.ts +43 -0
- package/dist/shared/content.d.ts.map +1 -0
- package/dist/shared/content.js +61 -0
- package/dist/shared/content.js.map +1 -0
- package/dist/shared/types.d.ts +217 -0
- package/dist/shared/types.d.ts.map +1 -0
- package/dist/shared/types.js +3 -0
- package/dist/shared/types.js.map +1 -0
- package/dist/test-runner.d.ts +5 -0
- package/dist/test-runner.d.ts.map +1 -0
- package/dist/test-runner.js +42 -0
- package/dist/test-runner.js.map +1 -0
- package/dist/types.d.ts +85 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/ui/ascii.d.ts +23 -0
- package/dist/ui/ascii.d.ts.map +1 -0
- package/dist/ui/ascii.js +45 -0
- package/dist/ui/ascii.js.map +1 -0
- package/dist/ui/colors.d.ts +111 -0
- package/dist/ui/colors.d.ts.map +1 -0
- package/dist/ui/colors.js +166 -0
- package/dist/ui/colors.js.map +1 -0
- package/dist/ui/image-attach.d.ts +27 -0
- package/dist/ui/image-attach.d.ts.map +1 -0
- package/dist/ui/image-attach.js +100 -0
- package/dist/ui/image-attach.js.map +1 -0
- package/dist/ui/index.d.ts +18 -0
- package/dist/ui/index.d.ts.map +1 -0
- package/dist/ui/index.js +18 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/ui/markdown-stream.d.ts +91 -0
- package/dist/ui/markdown-stream.d.ts.map +1 -0
- package/dist/ui/markdown-stream.js +524 -0
- package/dist/ui/markdown-stream.js.map +1 -0
- package/dist/ui/plan-renderer.d.ts +36 -0
- package/dist/ui/plan-renderer.d.ts.map +1 -0
- package/dist/ui/plan-renderer.js +79 -0
- package/dist/ui/plan-renderer.js.map +1 -0
- package/dist/ui/prompt.d.ts +11 -0
- package/dist/ui/prompt.d.ts.map +1 -0
- package/dist/ui/prompt.js +1960 -0
- package/dist/ui/prompt.js.map +1 -0
- package/dist/ui/render-primitives.d.ts +117 -0
- package/dist/ui/render-primitives.d.ts.map +1 -0
- package/dist/ui/render-primitives.js +322 -0
- package/dist/ui/render-primitives.js.map +1 -0
- package/dist/ui/render.d.ts +133 -0
- package/dist/ui/render.d.ts.map +1 -0
- package/dist/ui/render.js +547 -0
- package/dist/ui/render.js.map +1 -0
- package/dist/ui/session-header.d.ts +30 -0
- package/dist/ui/session-header.d.ts.map +1 -0
- package/dist/ui/session-header.js +74 -0
- package/dist/ui/session-header.js.map +1 -0
- package/dist/workspace-guard.d.ts +68 -0
- package/dist/workspace-guard.d.ts.map +1 -0
- package/dist/workspace-guard.js +168 -0
- package/dist/workspace-guard.js.map +1 -0
- package/dist/workspace-lock.d.ts +27 -0
- package/dist/workspace-lock.d.ts.map +1 -0
- package/dist/workspace-lock.js +95 -0
- package/dist/workspace-lock.js.map +1 -0
- package/package.json +63 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/** Shape of a single MCP server config entry (matches MCP spec). */
|
|
2
|
+
export interface McpServerConfig {
|
|
3
|
+
command?: string;
|
|
4
|
+
args?: string[];
|
|
5
|
+
env?: Record<string, string>;
|
|
6
|
+
url?: string;
|
|
7
|
+
type?: 'stdio' | 'sse';
|
|
8
|
+
[key: string]: unknown;
|
|
9
|
+
}
|
|
10
|
+
/** A single source of MCP servers. */
|
|
11
|
+
export interface McpSourceView {
|
|
12
|
+
name: 'global' | 'project' | 'local';
|
|
13
|
+
configPath: string | null;
|
|
14
|
+
servers: Record<string, McpServerConfig>;
|
|
15
|
+
}
|
|
16
|
+
export interface McpRegistryView {
|
|
17
|
+
global: McpSourceView;
|
|
18
|
+
project: McpSourceView;
|
|
19
|
+
local: McpSourceView;
|
|
20
|
+
}
|
|
21
|
+
/** Read the global MCP config from `~/.freellmapi/mcp.json`. */
|
|
22
|
+
export declare function readGlobalMcpConfig(): {
|
|
23
|
+
configPath: string | null;
|
|
24
|
+
servers: Record<string, McpServerConfig>;
|
|
25
|
+
};
|
|
26
|
+
/** Read the project MCP config from `<cwd>/.fixo.yml` or `.fixo.yaml`. */
|
|
27
|
+
export declare function readProjectMcpConfig(cwd: string): {
|
|
28
|
+
configPath: string | null;
|
|
29
|
+
servers: Record<string, McpServerConfig>;
|
|
30
|
+
};
|
|
31
|
+
/** Build a unified view of all MCP sources for `cwd`. */
|
|
32
|
+
export declare function listAllMcpSources(cwd: string): McpRegistryView;
|
|
33
|
+
/** Add a server to the in-memory local layer for `cwd`. */
|
|
34
|
+
export declare function addLocalMcpServer(cwd: string, name: string, config: McpServerConfig): void;
|
|
35
|
+
/** Remove a server from the in-memory local layer. */
|
|
36
|
+
export declare function removeLocalMcpServer(cwd: string, name: string): boolean;
|
|
37
|
+
/** Clear all local entries (test-only). */
|
|
38
|
+
export declare function _resetLocalMcpServers(): void;
|
|
39
|
+
/**
|
|
40
|
+
* Build a merged server map for runtime use. Precedence
|
|
41
|
+
* (highest → lowest): local > project > global. Project
|
|
42
|
+
* shadows global on name conflict; local shadows both.
|
|
43
|
+
*/
|
|
44
|
+
export declare function mergedMcpServers(cwd: string): Record<string, McpServerConfig>;
|
|
45
|
+
//# sourceMappingURL=mcp-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-registry.d.ts","sourceRoot":"","sources":["../../src/agent/mcp-registry.ts"],"names":[],"mappings":"AAmBA,oEAAoE;AACpE,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,OAAO,GAAG,KAAK,CAAC;IACvB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,sCAAsC;AACtC,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAC;IACrC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;CAC1C;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,aAAa,CAAC;IACtB,OAAO,EAAE,aAAa,CAAC;IACvB,KAAK,EAAE,aAAa,CAAC;CACtB;AAcD,gEAAgE;AAChE,wBAAgB,mBAAmB,IAAI;IAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;CAAE,CAW7G;AAED,0EAA0E;AAC1E,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;CAAE,CAazH;AAED,yDAAyD;AACzD,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAQ9D;AAED,2DAA2D;AAC3D,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CAE1F;AAED,sDAAsD;AACtD,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAKvE;AAED,2CAA2C;AAC3C,wBAAgB,qBAAqB,IAAI,IAAI,CAE5C;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAO7E"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* mcp-registry.ts — Unified view of MCP server config across
|
|
3
|
+
* 3 sources: global (~/.freellmapi/mcp.json), project
|
|
4
|
+
* (.fixo.yml / .fixo.yaml), and local (in-memory runtime
|
|
5
|
+
* additions made via /mcp add).
|
|
6
|
+
*
|
|
7
|
+
* Phase 3.3 invariant: when the same server name appears in
|
|
8
|
+
* both global and project, the project definition wins.
|
|
9
|
+
* Local entries shadow both.
|
|
10
|
+
*
|
|
11
|
+
* The registry is read-only on disk; mutating actions
|
|
12
|
+
* (add/remove) are kept in an in-memory layer that is
|
|
13
|
+
* consumed by /mcp add and /mcp remove.
|
|
14
|
+
*/
|
|
15
|
+
import fs from 'node:fs';
|
|
16
|
+
import os from 'node:os';
|
|
17
|
+
import path from 'node:path';
|
|
18
|
+
import yaml from 'js-yaml';
|
|
19
|
+
/** In-memory local additions, keyed by cwd. */
|
|
20
|
+
const localByCwd = new Map();
|
|
21
|
+
function getLocal(cwd) {
|
|
22
|
+
let m = localByCwd.get(cwd);
|
|
23
|
+
if (!m) {
|
|
24
|
+
m = {};
|
|
25
|
+
localByCwd.set(cwd, m);
|
|
26
|
+
}
|
|
27
|
+
return m;
|
|
28
|
+
}
|
|
29
|
+
/** Read the global MCP config from `~/.freellmapi/mcp.json`. */
|
|
30
|
+
export function readGlobalMcpConfig() {
|
|
31
|
+
const configPath = path.join(os.homedir(), '.freellmapi', 'mcp.json');
|
|
32
|
+
if (!fs.existsSync(configPath)) {
|
|
33
|
+
return { configPath: null, servers: {} };
|
|
34
|
+
}
|
|
35
|
+
try {
|
|
36
|
+
const raw = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
37
|
+
return { configPath, servers: raw.mcpServers ?? {} };
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return { configPath, servers: {} };
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/** Read the project MCP config from `<cwd>/.fixo.yml` or `.fixo.yaml`. */
|
|
44
|
+
export function readProjectMcpConfig(cwd) {
|
|
45
|
+
const yml = path.join(cwd, '.fixo.yml');
|
|
46
|
+
const yamlAlt = path.join(cwd, '.fixo.yaml');
|
|
47
|
+
const configPath = fs.existsSync(yml) ? yml : fs.existsSync(yamlAlt) ? yamlAlt : null;
|
|
48
|
+
if (!configPath) {
|
|
49
|
+
return { configPath: null, servers: {} };
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
const raw = yaml.load(fs.readFileSync(configPath, 'utf-8'));
|
|
53
|
+
return { configPath, servers: raw?.mcpServers ?? {} };
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return { configPath, servers: {} };
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/** Build a unified view of all MCP sources for `cwd`. */
|
|
60
|
+
export function listAllMcpSources(cwd) {
|
|
61
|
+
const g = readGlobalMcpConfig();
|
|
62
|
+
const p = readProjectMcpConfig(cwd);
|
|
63
|
+
return {
|
|
64
|
+
global: { name: 'global', configPath: g.configPath, servers: g.servers },
|
|
65
|
+
project: { name: 'project', configPath: p.configPath, servers: p.servers },
|
|
66
|
+
local: { name: 'local', configPath: null, servers: { ...getLocal(cwd) } },
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/** Add a server to the in-memory local layer for `cwd`. */
|
|
70
|
+
export function addLocalMcpServer(cwd, name, config) {
|
|
71
|
+
getLocal(cwd)[name] = config;
|
|
72
|
+
}
|
|
73
|
+
/** Remove a server from the in-memory local layer. */
|
|
74
|
+
export function removeLocalMcpServer(cwd, name) {
|
|
75
|
+
const local = getLocal(cwd);
|
|
76
|
+
if (!(name in local))
|
|
77
|
+
return false;
|
|
78
|
+
delete local[name];
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
/** Clear all local entries (test-only). */
|
|
82
|
+
export function _resetLocalMcpServers() {
|
|
83
|
+
localByCwd.clear();
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Build a merged server map for runtime use. Precedence
|
|
87
|
+
* (highest → lowest): local > project > global. Project
|
|
88
|
+
* shadows global on name conflict; local shadows both.
|
|
89
|
+
*/
|
|
90
|
+
export function mergedMcpServers(cwd) {
|
|
91
|
+
const view = listAllMcpSources(cwd);
|
|
92
|
+
return {
|
|
93
|
+
...view.global.servers,
|
|
94
|
+
...view.project.servers,
|
|
95
|
+
...view.local.servers,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=mcp-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-registry.js","sourceRoot":"","sources":["../../src/agent/mcp-registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { AgentContext, Subtask, TaskDAG } from '../types.js';
|
|
2
|
+
export declare class Orchestrator {
|
|
3
|
+
private client;
|
|
4
|
+
private verbose;
|
|
5
|
+
tokensUsed: {
|
|
6
|
+
prompt_tokens: number;
|
|
7
|
+
completion_tokens: number;
|
|
8
|
+
total_tokens: number;
|
|
9
|
+
};
|
|
10
|
+
constructor(verbose?: boolean);
|
|
11
|
+
plan(context: AgentContext): Promise<TaskDAG>;
|
|
12
|
+
validateAndSortDAG(subtasks: Subtask[]): Subtask[];
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=orchestrator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../../src/agent/orchestrator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAKlE,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,OAAO,CAAU;IAClB,UAAU;;;;MAA+D;gBAEpE,OAAO,UAAQ;IAMrB,IAAI,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC;IAmFnD,kBAAkB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,OAAO,EAAE;CAmCnD"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { AgentClient } from './agent-client.js';
|
|
2
|
+
import { loadConfig } from '../config.js';
|
|
3
|
+
import { C } from '../ui/colors.js';
|
|
4
|
+
export class Orchestrator {
|
|
5
|
+
client;
|
|
6
|
+
verbose;
|
|
7
|
+
tokensUsed = { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 };
|
|
8
|
+
constructor(verbose = false) {
|
|
9
|
+
const config = loadConfig();
|
|
10
|
+
this.client = new AgentClient(config.freellmapi_api_key || '', config.apiUrl, verbose);
|
|
11
|
+
this.verbose = verbose;
|
|
12
|
+
}
|
|
13
|
+
async plan(context) {
|
|
14
|
+
const systemPrompt = `You are the FixO Orchestrator. Your job is to analyze a complex software engineering task and decompose it into a Directed Acyclic Graph (DAG) of subtasks.
|
|
15
|
+
Each subtask will be assigned to a specialist worker agent:
|
|
16
|
+
- 'code': Writes or modifies code files.
|
|
17
|
+
- 'test': Creates, updates, or executes test suites.
|
|
18
|
+
- 'doc': Updates documentation, READMEs, JSDocs, etc.
|
|
19
|
+
- 'reviewer': Reviews changes, audits code modifications.
|
|
20
|
+
|
|
21
|
+
You must output a single valid JSON object containing a "subtasks" array. NO markdown formatting, NO backticks, and NO conversational text.
|
|
22
|
+
|
|
23
|
+
JSON Schema:
|
|
24
|
+
{
|
|
25
|
+
"subtasks": [
|
|
26
|
+
{
|
|
27
|
+
"id": "string",
|
|
28
|
+
"title": "string",
|
|
29
|
+
"description": "string",
|
|
30
|
+
"persona": "code" | "test" | "doc" | "reviewer",
|
|
31
|
+
"dependencies": ["string"],
|
|
32
|
+
"files": ["string"]
|
|
33
|
+
}
|
|
34
|
+
]
|
|
35
|
+
}`;
|
|
36
|
+
const maxRetries = 3;
|
|
37
|
+
let attempt = 0;
|
|
38
|
+
let feedback = '';
|
|
39
|
+
while (attempt < maxRetries) {
|
|
40
|
+
if (attempt > 0) {
|
|
41
|
+
const delayMs = Math.pow(2, attempt) * 1000;
|
|
42
|
+
if (this.verbose) {
|
|
43
|
+
console.log(`[Orchestrator] Retrying plan generation in ${(delayMs / 1000).toFixed(1)}s...`);
|
|
44
|
+
}
|
|
45
|
+
await new Promise(resolve => setTimeout(resolve, delayMs));
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
const response = await this.client.chat([
|
|
49
|
+
{ role: 'system', content: systemPrompt },
|
|
50
|
+
{ role: 'user', content: context.task + (feedback ? `\n\nPrevious attempt failed validation: ${feedback}. Please output only valid JSON matching the schema.` : '') }
|
|
51
|
+
], context.model, { agent_task_type: 'investigation', required_capabilities: ['fast'] });
|
|
52
|
+
if (response.usage) {
|
|
53
|
+
this.tokensUsed.prompt_tokens += response.usage.prompt_tokens;
|
|
54
|
+
this.tokensUsed.completion_tokens += response.usage.completion_tokens;
|
|
55
|
+
this.tokensUsed.total_tokens += response.usage.total_tokens;
|
|
56
|
+
}
|
|
57
|
+
const content = response.content?.trim() || '';
|
|
58
|
+
const jsonMatch = content.match(/\{[\s\S]*\}/);
|
|
59
|
+
const parsed = JSON.parse(jsonMatch ? jsonMatch[0] : content);
|
|
60
|
+
if (parsed && Array.isArray(parsed.subtasks)) {
|
|
61
|
+
this.validateAndSortDAG(parsed.subtasks);
|
|
62
|
+
return parsed;
|
|
63
|
+
}
|
|
64
|
+
feedback = 'Missing subtasks array';
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
feedback = err.message || String(err);
|
|
68
|
+
}
|
|
69
|
+
attempt++;
|
|
70
|
+
}
|
|
71
|
+
console.warn(`${C.YELLOW}[Orchestrator] Warning: Failed to generate plan. Falling back to SingleAgent execution...${C.RESET}`);
|
|
72
|
+
return {
|
|
73
|
+
subtasks: [
|
|
74
|
+
{
|
|
75
|
+
id: 'fallback-task',
|
|
76
|
+
title: 'Execute coding task',
|
|
77
|
+
description: context.task,
|
|
78
|
+
persona: 'code',
|
|
79
|
+
dependencies: [],
|
|
80
|
+
files: [],
|
|
81
|
+
status: 'pending'
|
|
82
|
+
}
|
|
83
|
+
]
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
validateAndSortDAG(subtasks) {
|
|
87
|
+
const sorted = [];
|
|
88
|
+
const visited = new Set();
|
|
89
|
+
const temp = new Set();
|
|
90
|
+
const subtaskMap = new Map();
|
|
91
|
+
for (const s of subtasks) {
|
|
92
|
+
subtaskMap.set(s.id, s);
|
|
93
|
+
}
|
|
94
|
+
function visit(id) {
|
|
95
|
+
if (temp.has(id)) {
|
|
96
|
+
throw new Error(`Circular dependency detected at subtask: ${id}`);
|
|
97
|
+
}
|
|
98
|
+
if (!visited.has(id)) {
|
|
99
|
+
temp.add(id);
|
|
100
|
+
const subtask = subtaskMap.get(id);
|
|
101
|
+
if (!subtask) {
|
|
102
|
+
throw new Error(`Dependency subtask not found: ${id}`);
|
|
103
|
+
}
|
|
104
|
+
for (const depId of subtask.dependencies) {
|
|
105
|
+
visit(depId);
|
|
106
|
+
}
|
|
107
|
+
temp.delete(id);
|
|
108
|
+
visited.add(id);
|
|
109
|
+
sorted.push(subtask);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
for (const s of subtasks) {
|
|
113
|
+
visit(s.id);
|
|
114
|
+
}
|
|
115
|
+
return sorted;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=orchestrator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["../../src/agent/orchestrator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* parser-adapter.ts — Unified code-parsing interface for the FixO CLI.
|
|
3
|
+
*
|
|
4
|
+
* Decouples every consumer (indexer, command-parser, repo-map, future
|
|
5
|
+
* callers) from a single concrete parser. Two implementations exist:
|
|
6
|
+
*
|
|
7
|
+
* - `TreeSitterAdapter` — uses the vendored WebAssembly tree-sitter
|
|
8
|
+
* engine. Supports shell command parsing via the bundled bash
|
|
9
|
+
* grammar, and a generic regex fallback for any other language.
|
|
10
|
+
* If `Parser.init()` throws (WASM architecture mismatch, missing
|
|
11
|
+
* file, etc.) the adapter catches the error, logs a console
|
|
12
|
+
* warning, and reports `supported = false`.
|
|
13
|
+
*
|
|
14
|
+
* - `RegexParserAdapter` — a pure-JS, zero-dependency fallback that
|
|
15
|
+
* works on every platform. It uses curated per-language regexes
|
|
16
|
+
* for symbol and import extraction, and a tokeniser-style splitter
|
|
17
|
+
* for shell commands. Slightly less accurate than tree-sitter but
|
|
18
|
+
* always available.
|
|
19
|
+
*
|
|
20
|
+
* A double-checked async singleton (`ParserFactory`) ensures only one
|
|
21
|
+
* adapter is ever instantiated per process and that concurrent callers
|
|
22
|
+
* share the same in-flight `init()` promise.
|
|
23
|
+
*/
|
|
24
|
+
export type LanguageId = 'typescript' | 'javascript' | 'python' | 'go' | 'rust' | 'bash' | 'json' | 'markdown' | 'generic';
|
|
25
|
+
export interface SymbolInfo {
|
|
26
|
+
name: string;
|
|
27
|
+
kind: 'class' | 'function' | 'interface' | 'type' | 'const' | 'let' | 'var' | 'enum' | 'method' | 'variable' | 'field' | 'module' | 'unknown';
|
|
28
|
+
line: number;
|
|
29
|
+
endLine: number;
|
|
30
|
+
exported: boolean;
|
|
31
|
+
}
|
|
32
|
+
export interface ImportInfo {
|
|
33
|
+
source: string;
|
|
34
|
+
symbols: string[];
|
|
35
|
+
line: number;
|
|
36
|
+
isTypeOnly: boolean;
|
|
37
|
+
}
|
|
38
|
+
export interface ParsedCommand {
|
|
39
|
+
binary: string;
|
|
40
|
+
arguments: string[];
|
|
41
|
+
raw: string;
|
|
42
|
+
}
|
|
43
|
+
export interface ParserInitResult {
|
|
44
|
+
ok: boolean;
|
|
45
|
+
reason?: string;
|
|
46
|
+
}
|
|
47
|
+
export interface ParserAdapter {
|
|
48
|
+
readonly name: 'tree-sitter' | 'regex';
|
|
49
|
+
readonly supported: boolean;
|
|
50
|
+
/** Performs any one-time async work (e.g. loading WASM grammars). */
|
|
51
|
+
init(): Promise<ParserInitResult>;
|
|
52
|
+
/**
|
|
53
|
+
* Extracts symbol declarations from `source` for the given language.
|
|
54
|
+
* Synchronous: callers may invoke this from inside a tight loop.
|
|
55
|
+
*/
|
|
56
|
+
extractSymbols(source: string, language: LanguageId): SymbolInfo[];
|
|
57
|
+
/**
|
|
58
|
+
* Extracts import statements from `source` for the given language.
|
|
59
|
+
* Synchronous: callers may invoke this from inside a tight loop.
|
|
60
|
+
*/
|
|
61
|
+
extractImports(source: string, language: LanguageId): ImportInfo[];
|
|
62
|
+
/**
|
|
63
|
+
* Parses a shell command string into individual `binary`/`arguments`
|
|
64
|
+
* tuples. Optional — adapters that do not understand shell may omit it.
|
|
65
|
+
*/
|
|
66
|
+
parseShellCommand?(command: string): ParsedCommand[];
|
|
67
|
+
/** Frees any held resources. */
|
|
68
|
+
dispose(): void;
|
|
69
|
+
}
|
|
70
|
+
/** Maps a file extension (including the leading dot) to a `LanguageId`. */
|
|
71
|
+
export declare function languageIdFromExtension(ext: string): LanguageId;
|
|
72
|
+
export declare class TreeSitterAdapter implements ParserAdapter {
|
|
73
|
+
readonly name: "tree-sitter";
|
|
74
|
+
supported: boolean;
|
|
75
|
+
private parser;
|
|
76
|
+
private initialised;
|
|
77
|
+
init(): Promise<ParserInitResult>;
|
|
78
|
+
extractSymbols(source: string, language: LanguageId): SymbolInfo[];
|
|
79
|
+
extractImports(source: string, language: LanguageId): ImportInfo[];
|
|
80
|
+
parseShellCommand(command: string): ParsedCommand[];
|
|
81
|
+
private parseShellWithTreeSitter;
|
|
82
|
+
dispose(): void;
|
|
83
|
+
}
|
|
84
|
+
export declare class RegexParserAdapter implements ParserAdapter {
|
|
85
|
+
readonly name: "regex";
|
|
86
|
+
supported: boolean;
|
|
87
|
+
init(): Promise<ParserInitResult>;
|
|
88
|
+
extractSymbols(source: string, language: LanguageId): SymbolInfo[];
|
|
89
|
+
extractImports(source: string, language: LanguageId): ImportInfo[];
|
|
90
|
+
parseShellCommand(command: string): ParsedCommand[];
|
|
91
|
+
/** Convenience: re-uses the safety heuristic so callers can stay pure. */
|
|
92
|
+
isCommandSafeShell(command: string, workspaceRoot: string): boolean;
|
|
93
|
+
dispose(): void;
|
|
94
|
+
}
|
|
95
|
+
export declare class ParserFactory {
|
|
96
|
+
/**
|
|
97
|
+
* Returns a fully-initialised parser adapter. The first caller pays
|
|
98
|
+
* the (potential) WASM-init cost; subsequent callers share the same
|
|
99
|
+
* adapter instance.
|
|
100
|
+
*
|
|
101
|
+
* `force = 'tree-sitter'` rejects the call with the underlying
|
|
102
|
+
* error if WASM init fails (use this when WASM is required by the
|
|
103
|
+
* caller). `force = 'regex'` skips tree-sitter entirely.
|
|
104
|
+
*/
|
|
105
|
+
static getParser(force?: 'tree-sitter' | 'regex' | 'auto'): Promise<ParserAdapter>;
|
|
106
|
+
/**
|
|
107
|
+
* Returns the currently cached parser synchronously, or `null` if
|
|
108
|
+
* the factory has not been initialised yet. Use this only when you
|
|
109
|
+
* cannot await — e.g. inside a sync extraction loop on a hot path.
|
|
110
|
+
*/
|
|
111
|
+
static getCachedParser(): ParserAdapter | null;
|
|
112
|
+
/** Resets the factory. Intended for tests only. */
|
|
113
|
+
static reset(): void;
|
|
114
|
+
/**
|
|
115
|
+
* Configures the factory's force policy. The next `getParser()` call
|
|
116
|
+
* after this method will re-initialise with the new policy.
|
|
117
|
+
*/
|
|
118
|
+
static setForce(force: 'tree-sitter' | 'regex' | 'auto'): void;
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=parser-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser-adapter.d.ts","sourceRoot":"","sources":["../../src/agent/parser-adapter.ts"],"names":[],"mappings":"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"}
|