@rynfar/meridian 1.21.1

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 (67) hide show
  1. package/README.md +410 -0
  2. package/assets/banner.svg +46 -0
  3. package/assets/how-it-works.svg +87 -0
  4. package/assets/icon.svg +16 -0
  5. package/assets/logo.svg +15 -0
  6. package/dist/cli-zyn4cqp2.js +24392 -0
  7. package/dist/cli.js +46 -0
  8. package/dist/logger.d.ts +5 -0
  9. package/dist/logger.d.ts.map +1 -0
  10. package/dist/mcpTools.d.ts +15 -0
  11. package/dist/mcpTools.d.ts.map +1 -0
  12. package/dist/proxy/adapter.d.ts +78 -0
  13. package/dist/proxy/adapter.d.ts.map +1 -0
  14. package/dist/proxy/adapters/crush.d.ts +22 -0
  15. package/dist/proxy/adapters/crush.d.ts.map +1 -0
  16. package/dist/proxy/adapters/detect.d.ts +18 -0
  17. package/dist/proxy/adapters/detect.d.ts.map +1 -0
  18. package/dist/proxy/adapters/droid.d.ts +19 -0
  19. package/dist/proxy/adapters/droid.d.ts.map +1 -0
  20. package/dist/proxy/adapters/opencode.d.ts +9 -0
  21. package/dist/proxy/adapters/opencode.d.ts.map +1 -0
  22. package/dist/proxy/agentDefs.d.ts +51 -0
  23. package/dist/proxy/agentDefs.d.ts.map +1 -0
  24. package/dist/proxy/agentMatch.d.ts +18 -0
  25. package/dist/proxy/agentMatch.d.ts.map +1 -0
  26. package/dist/proxy/errors.d.ts +25 -0
  27. package/dist/proxy/errors.d.ts.map +1 -0
  28. package/dist/proxy/messages.d.ts +24 -0
  29. package/dist/proxy/messages.d.ts.map +1 -0
  30. package/dist/proxy/models.d.ts +46 -0
  31. package/dist/proxy/models.d.ts.map +1 -0
  32. package/dist/proxy/passthroughTools.d.ts +30 -0
  33. package/dist/proxy/passthroughTools.d.ts.map +1 -0
  34. package/dist/proxy/query.d.ts +105 -0
  35. package/dist/proxy/query.d.ts.map +1 -0
  36. package/dist/proxy/server.d.ts +10 -0
  37. package/dist/proxy/server.d.ts.map +1 -0
  38. package/dist/proxy/session/cache.d.ts +32 -0
  39. package/dist/proxy/session/cache.d.ts.map +1 -0
  40. package/dist/proxy/session/fingerprint.d.ts +31 -0
  41. package/dist/proxy/session/fingerprint.d.ts.map +1 -0
  42. package/dist/proxy/session/lineage.d.ts +103 -0
  43. package/dist/proxy/session/lineage.d.ts.map +1 -0
  44. package/dist/proxy/sessionStore.d.ts +36 -0
  45. package/dist/proxy/sessionStore.d.ts.map +1 -0
  46. package/dist/proxy/tools.d.ts +26 -0
  47. package/dist/proxy/tools.d.ts.map +1 -0
  48. package/dist/proxy/types.d.ts +27 -0
  49. package/dist/proxy/types.d.ts.map +1 -0
  50. package/dist/server.js +18 -0
  51. package/dist/telemetry/dashboard.d.ts +6 -0
  52. package/dist/telemetry/dashboard.d.ts.map +1 -0
  53. package/dist/telemetry/index.d.ts +7 -0
  54. package/dist/telemetry/index.d.ts.map +1 -0
  55. package/dist/telemetry/landing.d.ts +7 -0
  56. package/dist/telemetry/landing.d.ts.map +1 -0
  57. package/dist/telemetry/logStore.d.ts +50 -0
  58. package/dist/telemetry/logStore.d.ts.map +1 -0
  59. package/dist/telemetry/routes.d.ts +11 -0
  60. package/dist/telemetry/routes.d.ts.map +1 -0
  61. package/dist/telemetry/store.d.ts +39 -0
  62. package/dist/telemetry/store.d.ts.map +1 -0
  63. package/dist/telemetry/types.d.ts +93 -0
  64. package/dist/telemetry/types.d.ts.map +1 -0
  65. package/dist/utils/lruMap.d.ts +28 -0
  66. package/dist/utils/lruMap.d.ts.map +1 -0
  67. package/package.json +77 -0
package/dist/cli.js ADDED
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ __require,
4
+ startProxyServer
5
+ } from "./cli-zyn4cqp2.js";
6
+
7
+ // bin/cli.ts
8
+ import { exec as execCallback } from "child_process";
9
+ import { promisify } from "util";
10
+ var exec = promisify(execCallback);
11
+ process.on("uncaughtException", (err) => {
12
+ console.error(`[PROXY] Uncaught exception (recovered): ${err.message}`);
13
+ });
14
+ process.on("unhandledRejection", (reason) => {
15
+ console.error(`[PROXY] Unhandled rejection (recovered): ${reason instanceof Error ? reason.message : reason}`);
16
+ });
17
+ var port = parseInt(process.env.CLAUDE_PROXY_PORT || "3456", 10);
18
+ var host = process.env.CLAUDE_PROXY_HOST || "127.0.0.1";
19
+ var idleTimeoutSeconds = parseInt(process.env.CLAUDE_PROXY_IDLE_TIMEOUT_SECONDS || "120", 10);
20
+ async function runCli(start = startProxyServer, runExec = exec) {
21
+ try {
22
+ const { stdout } = await runExec("claude auth status", { timeout: 5000 });
23
+ const auth = JSON.parse(stdout);
24
+ if (!auth.loggedIn) {
25
+ console.error("\x1B[31m✗ Not logged in to Claude.\x1B[0m Run: claude login");
26
+ process.exit(1);
27
+ }
28
+ if (auth.subscriptionType !== "max") {
29
+ console.error(`\x1B[33m⚠ Claude subscription: ${auth.subscriptionType || "unknown"} (Max recommended)\x1B[0m`);
30
+ }
31
+ } catch {
32
+ console.error("\x1B[33m⚠ Could not verify Claude auth status. If requests fail, run: claude login\x1B[0m");
33
+ }
34
+ const proxy = await start({ port, host, idleTimeoutSeconds });
35
+ proxy.server.on("error", (error) => {
36
+ if (error.code === "EADDRINUSE") {
37
+ process.exit(1);
38
+ }
39
+ });
40
+ }
41
+ if (__require.main == __require.module) {
42
+ await runCli();
43
+ }
44
+ export {
45
+ runCli
46
+ };
@@ -0,0 +1,5 @@
1
+ type LogFields = Record<string, unknown>;
2
+ export declare const withClaudeLogContext: <T>(context: LogFields, fn: () => T) => T;
3
+ export declare const claudeLog: (event: string, extra?: LogFields) => void;
4
+ export {};
5
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAEA,KAAK,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AAyDxC,eAAO,MAAM,oBAAoB,GAAI,CAAC,EAAE,SAAS,SAAS,EAAE,IAAI,MAAM,CAAC,KAAG,CAEzE,CAAA;AAED,eAAO,MAAM,SAAS,GAAI,OAAO,MAAM,EAAE,QAAQ,SAAS,SAQzD,CAAA"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Create a fresh MCP server instance per request.
3
+ *
4
+ * SDK ≥0.2.81 enforces "one Protocol per transport connection". The internal
5
+ * McpServer holds a Protocol whose connect() throws if reused:
6
+ * "Already connected to a transport. Call close() before connecting to a
7
+ * new transport, or use a separate Protocol instance per connection."
8
+ *
9
+ * Each query() call connects its own transport to the MCP server, so sharing
10
+ * a singleton across requests triggers this guard on the second request.
11
+ * Creating a fresh instance avoids the conflict entirely — the same pattern
12
+ * used by createPassthroughMcpServer().
13
+ */
14
+ export declare function createOpencodeMcpServer(): import("@anthropic-ai/claude-agent-sdk").McpSdkServerConfigWithInstance;
15
+ //# sourceMappingURL=mcpTools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcpTools.d.ts","sourceRoot":"","sources":["../src/mcpTools.ts"],"names":[],"mappings":"AAYA;;;;;;;;;;;;GAYG;AACH,wBAAgB,uBAAuB,4EA8KtC"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Agent adapter interface.
3
+ *
4
+ * Abstracts agent-specific behavior so the proxy can work with
5
+ * different calling agents (OpenCode, Claude Code, custom agents).
6
+ */
7
+ import type { Context } from "hono";
8
+ /**
9
+ * An agent adapter provides agent-specific configuration to the proxy.
10
+ * The proxy calls these methods during request handling to determine
11
+ * how to interact with the calling agent.
12
+ */
13
+ export interface AgentAdapter {
14
+ /** Human-readable name for logging */
15
+ readonly name: string;
16
+ /**
17
+ * Extract a session ID from the request.
18
+ * Returns undefined if the agent doesn't provide session tracking.
19
+ */
20
+ getSessionId(c: Context): string | undefined;
21
+ /**
22
+ * Extract the client's working directory from the request body.
23
+ * Returns undefined to fall back to CLAUDE_PROXY_WORKDIR or process.cwd().
24
+ */
25
+ extractWorkingDirectory(body: any): string | undefined;
26
+ /**
27
+ * Content normalization — convert message content to a stable string
28
+ * for hashing. Agents may send content in different formats.
29
+ */
30
+ normalizeContent(content: any): string;
31
+ /**
32
+ * SDK built-in tools to block (replaced by MCP equivalents).
33
+ * These are tools where the agent provides its own implementation.
34
+ */
35
+ getBlockedBuiltinTools(): readonly string[];
36
+ /**
37
+ * Claude Code SDK tools that have no equivalent in this agent.
38
+ * These are blocked to prevent Claude from calling tools the agent
39
+ * can't handle.
40
+ */
41
+ getAgentIncompatibleTools(): readonly string[];
42
+ /**
43
+ * The MCP server name used by this agent.
44
+ * Tools are registered as `mcp__{name}__{tool}`.
45
+ */
46
+ getMcpServerName(): string;
47
+ /**
48
+ * MCP tools that are allowed through the proxy's tool filter.
49
+ */
50
+ getAllowedMcpTools(): readonly string[];
51
+ /**
52
+ * Build SDK agent definitions from the request body.
53
+ * Returns agent name → AgentDefinition map for SDK subagent routing.
54
+ * Return empty object {} if the agent doesn't support subagent routing.
55
+ */
56
+ buildSdkAgents?(body: any, mcpToolNames: readonly string[]): Record<string, any>;
57
+ /**
58
+ * Build SDK hooks (e.g., PreToolUse) for this agent.
59
+ * Return undefined if no hooks are needed.
60
+ */
61
+ buildSdkHooks?(body: any, sdkAgents: Record<string, any>): any;
62
+ /**
63
+ * Build additional system context to append (e.g., agent name hints).
64
+ * Return empty string if nothing to add.
65
+ */
66
+ buildSystemContextAddendum?(body: any, sdkAgents: Record<string, any>): string;
67
+ /**
68
+ * Whether this agent uses passthrough mode for tool execution.
69
+ *
70
+ * In passthrough mode the proxy returns tool_use blocks to the calling
71
+ * agent for it to execute, rather than executing them internally via MCP.
72
+ *
73
+ * When undefined, falls back to the CLAUDE_PROXY_PASSTHROUGH env var.
74
+ * When defined, takes precedence over the env var for this agent.
75
+ */
76
+ usesPassthrough?(): boolean;
77
+ }
78
+ //# sourceMappingURL=adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../src/proxy/adapter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAEnC;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,sCAAsC;IACtC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IAErB;;;OAGG;IACH,YAAY,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAAA;IAE5C;;;OAGG;IACH,uBAAuB,CAAC,IAAI,EAAE,GAAG,GAAG,MAAM,GAAG,SAAS,CAAA;IAEtD;;;OAGG;IACH,gBAAgB,CAAC,OAAO,EAAE,GAAG,GAAG,MAAM,CAAA;IAEtC;;;OAGG;IACH,sBAAsB,IAAI,SAAS,MAAM,EAAE,CAAA;IAE3C;;;;OAIG;IACH,yBAAyB,IAAI,SAAS,MAAM,EAAE,CAAA;IAE9C;;;OAGG;IACH,gBAAgB,IAAI,MAAM,CAAA;IAE1B;;OAEG;IACH,kBAAkB,IAAI,SAAS,MAAM,EAAE,CAAA;IAEvC;;;;OAIG;IACH,cAAc,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,YAAY,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAEhF;;;OAGG;IACH,aAAa,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,CAAA;IAE9D;;;OAGG;IACH,0BAA0B,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAAA;IAE9E;;;;;;;;OAQG;IACH,eAAe,CAAC,IAAI,OAAO,CAAA;CAC5B"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Crush (Charm) agent adapter.
3
+ *
4
+ * Provides Crush-specific behavior for session tracking, content normalization,
5
+ * and tool configuration.
6
+ *
7
+ * Crush connects via a provider entry in ~/.config/crush/crush.json using
8
+ * type "anthropic" with base_url pointing at this proxy. No special auth
9
+ * or BYOK mechanism — just a base_url override.
10
+ *
11
+ * Key characteristics:
12
+ * - User-Agent: Charm-Crush/<version>
13
+ * - Always streams (stream: true)
14
+ * - 19 lowercase tool names (bash, edit, write, grep, ls, etc.)
15
+ * - No session header: relies on fingerprint-based session cache
16
+ * - No CWD in request body: falls back to CLAUDE_PROXY_WORKDIR or process.cwd()
17
+ * - Manages its own tool execution loop: passthrough mode is appropriate
18
+ * - System prompt sent as a list in the `system` field (not embedded in messages)
19
+ */
20
+ import type { AgentAdapter } from "../adapter";
21
+ export declare const crushAdapter: AgentAdapter;
22
+ //# sourceMappingURL=crush.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crush.d.ts","sourceRoot":"","sources":["../../../src/proxy/adapters/crush.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAe9C,eAAO,MAAM,YAAY,EAAE,YAkE1B,CAAA"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Agent adapter detection.
3
+ *
4
+ * Inspects the incoming request to select the appropriate AgentAdapter.
5
+ * Falls back to the OpenCode adapter for backward compatibility.
6
+ */
7
+ import type { Context } from "hono";
8
+ import type { AgentAdapter } from "../adapter";
9
+ /**
10
+ * Detect which agent adapter to use based on request headers.
11
+ *
12
+ * Detection rules (evaluated in order):
13
+ * 1. User-Agent starts with "factory-cli/" → Droid adapter
14
+ * 2. User-Agent starts with "Charm-Crush/" → Crush adapter
15
+ * 3. Default → OpenCode adapter (backward compatible)
16
+ */
17
+ export declare function detectAdapter(c: Context): AgentAdapter;
18
+ //# sourceMappingURL=detect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect.d.ts","sourceRoot":"","sources":["../../../src/proxy/adapters/detect.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AACnC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAK9C;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,OAAO,GAAG,YAAY,CAYtD"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Droid (Factory AI) agent adapter.
3
+ *
4
+ * Provides Droid-specific behavior for session tracking, working directory
5
+ * extraction, content normalization, and tool configuration.
6
+ *
7
+ * Authentication: Droid connects via BYOK (Bring Your Own Key) by setting
8
+ * provider="anthropic" and baseUrl pointing to this proxy in
9
+ * ~/.factory/settings.json customModels.
10
+ *
11
+ * Key differences from OpenCode:
12
+ * - No session header: relies on fingerprint-based session caching
13
+ * - CWD in <system-reminder> blocks inside user messages (not <env> in system)
14
+ * - No subagent routing: Droid manages its own subagents internally
15
+ * - MCP server name: "droid"
16
+ */
17
+ import type { AgentAdapter } from "../adapter";
18
+ export declare const droidAdapter: AgentAdapter;
19
+ //# sourceMappingURL=droid.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"droid.d.ts","sourceRoot":"","sources":["../../../src/proxy/adapters/droid.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAwC9C,eAAO,MAAM,YAAY,EAAE,YAuE1B,CAAA"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * OpenCode agent adapter.
3
+ *
4
+ * Provides OpenCode-specific behavior for session tracking,
5
+ * working directory extraction, content normalization, and tool configuration.
6
+ */
7
+ import type { AgentAdapter } from "../adapter";
8
+ export declare const openCodeAdapter: AgentAdapter;
9
+ //# sourceMappingURL=opencode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opencode.d.ts","sourceRoot":"","sources":["../../../src/proxy/adapters/opencode.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAO9C,eAAO,MAAM,eAAe,EAAE,YA6E7B,CAAA"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Extract SDK AgentDefinition objects from OpenCode's Task tool description.
3
+ *
4
+ * OpenCode (via oh-my-opencode or other frameworks) sends a Task tool with
5
+ * descriptions of each available agent. We parse these and convert them into
6
+ * Claude Agent SDK `AgentDefinition` objects so the SDK's native Task handler
7
+ * routes to properly-configured subagents.
8
+ *
9
+ * This means whatever agents the user configures in their framework
10
+ * automatically become available as SDK subagents — with descriptions,
11
+ * model tiers, and tool access.
12
+ */
13
+ /** SDK-compatible agent definition */
14
+ export interface AgentDefinition {
15
+ description: string;
16
+ prompt: string;
17
+ model?: "sonnet" | "opus" | "haiku" | "inherit";
18
+ tools?: string[];
19
+ disallowedTools?: string[];
20
+ }
21
+ /**
22
+ * Parse agent entries from the Task tool description text.
23
+ *
24
+ * Expected format (from OpenCode):
25
+ * - agent-name: Description of what the agent does
26
+ *
27
+ * @returns Map of agent name → description
28
+ */
29
+ export declare function parseAgentDescriptions(taskDescription: string): Map<string, string>;
30
+ /**
31
+ * Map an OpenCode model string to an SDK model tier.
32
+ *
33
+ * The SDK only accepts 'sonnet' | 'opus' | 'haiku' | 'inherit'.
34
+ * We map based on the model name pattern, defaulting to 'inherit'
35
+ * for non-Anthropic models (they'll use the parent session's model).
36
+ */
37
+ export declare function mapModelTier(model?: string): "sonnet" | "opus" | "opus[1m]" | "haiku" | "inherit";
38
+ /**
39
+ * Build SDK AgentDefinition objects from the Task tool description.
40
+ *
41
+ * Each agent gets:
42
+ * - description: from the Task tool text (user-configured)
43
+ * - prompt: instructional prompt incorporating the description
44
+ * - model: 'inherit' (uses parent session model — all requests go through our proxy)
45
+ * - tools: undefined (inherit all tools from parent)
46
+ *
47
+ * @param taskDescription - The full Task tool description text from OpenCode
48
+ * @param mcpToolNames - Optional list of MCP tool names to make available to agents
49
+ */
50
+ export declare function buildAgentDefinitions(taskDescription: string, mcpToolNames?: string[]): Record<string, AgentDefinition>;
51
+ //# sourceMappingURL=agentDefs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agentDefs.d.ts","sourceRoot":"","sources":["../../src/proxy/agentDefs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,sCAAsC;AACtC,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAA;IAC/C,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;CAC3B;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,eAAe,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAcnF;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,GAAG,OAAO,GAAG,SAAS,CAOjG;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,CACnC,eAAe,EAAE,MAAM,EACvB,YAAY,CAAC,EAAE,MAAM,EAAE,GACtB,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAejC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Fuzzy matching for agent names.
3
+ *
4
+ * When Claude sends an invalid subagent_type, this tries to map it
5
+ * to the closest valid agent name. This is deterministic string matching,
6
+ * not LLM guessing.
7
+ *
8
+ * Matching priority:
9
+ * 1. Exact match (case-insensitive)
10
+ * 2. Known aliases (e.g., "general-purpose" → "general")
11
+ * 3. Prefix match (e.g., "lib" → "librarian")
12
+ * 4. Substring match (e.g., "junior" → "sisyphus-junior")
13
+ * 5. Suffix-stripped match (e.g., "explore-agent" → "explore")
14
+ * 6. Semantic aliases (e.g., "search" → "explore")
15
+ * 7. Fallback: return lowercased original
16
+ */
17
+ export declare function fuzzyMatchAgentName(input: string, validAgents: string[]): string;
18
+ //# sourceMappingURL=agentMatch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agentMatch.d.ts","sourceRoot":"","sources":["../../src/proxy/agentMatch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAwCH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,MAAM,CAqChF"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Error classification for SDK errors.
3
+ * Maps raw error messages to structured HTTP error responses.
4
+ */
5
+ export interface ClassifiedError {
6
+ status: number;
7
+ type: string;
8
+ message: string;
9
+ }
10
+ /**
11
+ * Detect specific SDK errors and return helpful messages to the client.
12
+ */
13
+ export declare function classifyError(errMsg: string): ClassifiedError;
14
+ /**
15
+ * Detect errors caused by stale session/message UUIDs.
16
+ * These happen when the upstream Claude session no longer contains
17
+ * the referenced message (expired, compacted server-side, etc.).
18
+ */
19
+ export declare function isStaleSessionError(error: unknown): boolean;
20
+ /**
21
+ * Quick check whether an error message indicates a rate limit.
22
+ * Used by server.ts to decide whether to retry with a smaller context window.
23
+ */
24
+ export declare function isRateLimitError(errMsg: string): boolean;
25
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/proxy/errors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;CAChB;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,eAAe,CAoF7D;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAG3D;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAGxD"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Message parsing and normalization utilities.
3
+ */
4
+ /**
5
+ * Normalize message content to a string for hashing and comparison.
6
+ * Handles both string content and array content (Anthropic content blocks).
7
+ * Strips cache_control metadata to ensure hash stability across requests.
8
+ *
9
+ * NOTE: OpenCode sends content as a string on the first request but as
10
+ * an array on subsequent ones. This normalizer handles both formats.
11
+ * Other agents may behave differently — this will move to the adapter pattern.
12
+ */
13
+ export declare function normalizeContent(content: any): string;
14
+ /**
15
+ * Extract only the last user message (for session resume — SDK already has history).
16
+ */
17
+ export declare function getLastUserMessage(messages: Array<{
18
+ role: string;
19
+ content: any;
20
+ }>): Array<{
21
+ role: string;
22
+ content: any;
23
+ }>;
24
+ //# sourceMappingURL=messages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/proxy/messages.ts"],"names":[],"mappings":"AAAA;;GAEG;AAcH;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,GAAG,GAAG,MAAM,CAiBrD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,GAAG,CAAA;CAAE,CAAC,GAAG,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,GAAG,CAAA;CAAE,CAAC,CAKzH"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Model mapping and Claude executable resolution.
3
+ */
4
+ export type ClaudeModel = "sonnet" | "sonnet[1m]" | "opus" | "opus[1m]" | "haiku";
5
+ export interface ClaudeAuthStatus {
6
+ loggedIn?: boolean;
7
+ subscriptionType?: string;
8
+ email?: string;
9
+ }
10
+ export declare function mapModelToClaudeModel(model: string, subscriptionType?: string | null): ClaudeModel;
11
+ /**
12
+ * Strip the [1m] suffix from a model, returning the base variant.
13
+ * Used for fallback when the 1M context window is rate-limited.
14
+ */
15
+ export declare function stripExtendedContext(model: ClaudeModel): ClaudeModel;
16
+ /**
17
+ * Check whether a model is using extended (1M) context.
18
+ */
19
+ export declare function hasExtendedContext(model: ClaudeModel): boolean;
20
+ export declare function getClaudeAuthStatusAsync(): Promise<ClaudeAuthStatus | null>;
21
+ /**
22
+ * Resolve the Claude executable path asynchronously (non-blocking).
23
+ *
24
+ * Uses a three-tier cache:
25
+ * 1. cachedClaudePath — resolved path, returned immediately on subsequent calls
26
+ * 2. cachedClaudePathPromise — deduplicates concurrent calls during resolution
27
+ * 3. Falls through to resolution logic (SDK cli.js → system `which claude`)
28
+ *
29
+ * The promise is cleared in `finally` to allow retry on failure while
30
+ * cachedClaudePath prevents re-resolution on success.
31
+ */
32
+ export declare function resolveClaudeExecutableAsync(): Promise<string>;
33
+ /** Reset cached path — for testing only */
34
+ export declare function resetCachedClaudePath(): void;
35
+ /** Reset cached auth status — for testing only */
36
+ export declare function resetCachedClaudeAuthStatus(): void;
37
+ /** Expire the auth status cache without clearing lastKnownGoodAuthStatus — for testing only.
38
+ * This simulates the TTL expiring so the next call re-executes `claude auth status`,
39
+ * while preserving the "last known good" fallback state. */
40
+ export declare function expireAuthStatusCache(): void;
41
+ /**
42
+ * Check if an error is a "Controller is already closed" error.
43
+ * This happens when the client disconnects mid-stream.
44
+ */
45
+ export declare function isClosedControllerError(error: unknown): boolean;
46
+ //# sourceMappingURL=models.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../../src/proxy/models.ts"],"names":[],"mappings":"AAAA;;GAEG;AAUH,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,YAAY,GAAG,MAAM,GAAG,UAAU,GAAG,OAAO,CAAA;AACjF,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AA0BD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,WAAW,CAYlG;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,WAAW,GAAG,WAAW,CAIpE;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAE9D;AAED,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAkCjF;AAOD;;;;;;;;;;GAUG;AACH,wBAAsB,4BAA4B,IAAI,OAAO,CAAC,MAAM,CAAC,CAiCpE;AAED,2CAA2C;AAC3C,wBAAgB,qBAAqB,IAAI,IAAI,CAG5C;AAED,kDAAkD;AAClD,wBAAgB,2BAA2B,IAAI,IAAI,CAMlD;AAED;;6DAE6D;AAC7D,wBAAgB,qBAAqB,IAAI,IAAI,CAG5C;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAG/D"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Dynamic MCP tool registration for passthrough mode.
3
+ *
4
+ * In passthrough mode, OpenCode's tools need to be real callable tools
5
+ * (not just text descriptions in the prompt). We create an MCP server
6
+ * that registers each tool from OpenCode's request with the exact
7
+ * name and schema, so Claude generates proper tool_use blocks.
8
+ *
9
+ * Tool handlers are no-ops — the PreToolUse hook blocks execution.
10
+ * We just need the definitions so Claude can call them.
11
+ */
12
+ export declare const PASSTHROUGH_MCP_NAME = "oc";
13
+ export declare const PASSTHROUGH_MCP_PREFIX = "mcp__oc__";
14
+ /**
15
+ * Create an MCP server with tool definitions matching OpenCode's request.
16
+ */
17
+ export declare function createPassthroughMcpServer(tools: Array<{
18
+ name: string;
19
+ description?: string;
20
+ input_schema?: any;
21
+ }>): {
22
+ server: import("@anthropic-ai/claude-agent-sdk").McpSdkServerConfigWithInstance;
23
+ toolNames: string[];
24
+ };
25
+ /**
26
+ * Strip the MCP prefix from a tool name to get the OpenCode tool name.
27
+ * e.g., "mcp__oc__todowrite" → "todowrite"
28
+ */
29
+ export declare function stripMcpPrefix(toolName: string): string;
30
+ //# sourceMappingURL=passthroughTools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"passthroughTools.d.ts","sourceRoot":"","sources":["../../src/proxy/passthroughTools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,eAAO,MAAM,oBAAoB,OAAO,CAAA;AACxC,eAAO,MAAM,sBAAsB,cAAmC,CAAA;AAsCtE;;GAEG;AACH,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,GAAG,CAAA;CAAE,CAAC;;;EAsCzE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAKvD"}
@@ -0,0 +1,105 @@
1
+ /**
2
+ * SDK query options builder.
3
+ *
4
+ * Centralizes the construction of query() options, eliminating duplication
5
+ * between the streaming and non-streaming paths in server.ts.
6
+ */
7
+ import type { AgentAdapter } from "./adapter";
8
+ import { createPassthroughMcpServer } from "./passthroughTools";
9
+ export interface QueryContext {
10
+ /** The prompt to send (text or async iterable for multimodal) */
11
+ prompt: string | AsyncIterable<any>;
12
+ /** Resolved Claude model name */
13
+ model: string;
14
+ /** Client working directory */
15
+ workingDirectory: string;
16
+ /** System context text (may be empty) */
17
+ systemContext: string;
18
+ /** Path to Claude executable */
19
+ claudeExecutable: string;
20
+ /** Whether passthrough mode is enabled */
21
+ passthrough: boolean;
22
+ /** Whether this is a streaming request */
23
+ stream: boolean;
24
+ /** SDK agent definitions extracted from tool descriptions */
25
+ sdkAgents: Record<string, any>;
26
+ /** Passthrough MCP server (if passthrough mode + tools present) */
27
+ passthroughMcp?: ReturnType<typeof createPassthroughMcpServer>;
28
+ /** Cleaned environment variables (API keys stripped) */
29
+ cleanEnv: Record<string, string | undefined>;
30
+ /** SDK session ID for resume (if continuing a session) */
31
+ resumeSessionId?: string;
32
+ /** Whether this is an undo operation */
33
+ isUndo: boolean;
34
+ /** UUID to rollback to for undo operations */
35
+ undoRollbackUuid?: string;
36
+ /** SDK hooks (PreToolUse etc.) */
37
+ sdkHooks?: any;
38
+ /** The agent adapter providing tool configuration */
39
+ adapter: AgentAdapter;
40
+ }
41
+ /**
42
+ * Build the options object for the Claude Agent SDK query() call.
43
+ * This is called identically from both streaming and non-streaming paths,
44
+ * with the only difference being `includePartialMessages` for streaming.
45
+ */
46
+ export declare function buildQueryOptions(ctx: QueryContext): {
47
+ prompt: string | AsyncIterable<any>;
48
+ options: {
49
+ hooks?: any;
50
+ resumeSessionAt?: string | undefined;
51
+ forkSession?: boolean | undefined;
52
+ resume?: string | undefined;
53
+ agents?: Record<string, any> | undefined;
54
+ plugins: never[];
55
+ env: {
56
+ ENABLE_TOOL_SEARCH: string;
57
+ };
58
+ allowedTools?: string[] | undefined;
59
+ mcpServers?: {
60
+ oc: import("@anthropic-ai/claude-agent-sdk").McpSdkServerConfigWithInstance;
61
+ } | undefined;
62
+ disallowedTools: string[];
63
+ systemPrompt?: {
64
+ type: "preset";
65
+ preset: "claude_code";
66
+ append: string;
67
+ } | undefined;
68
+ permissionMode: "bypassPermissions";
69
+ allowDangerouslySkipPermissions: boolean;
70
+ includePartialMessages?: boolean | undefined;
71
+ maxTurns: number;
72
+ cwd: string;
73
+ model: string;
74
+ pathToClaudeCodeExecutable: string;
75
+ } | {
76
+ hooks?: any;
77
+ resumeSessionAt?: string | undefined;
78
+ forkSession?: boolean | undefined;
79
+ resume?: string | undefined;
80
+ agents?: Record<string, any> | undefined;
81
+ plugins: never[];
82
+ env: {
83
+ ENABLE_TOOL_SEARCH: string;
84
+ };
85
+ disallowedTools: string[];
86
+ allowedTools: string[];
87
+ mcpServers: {
88
+ [x: string]: import("@anthropic-ai/claude-agent-sdk").McpSdkServerConfigWithInstance;
89
+ oc?: undefined;
90
+ };
91
+ systemPrompt?: {
92
+ type: "preset";
93
+ preset: "claude_code";
94
+ append: string;
95
+ } | undefined;
96
+ permissionMode: "bypassPermissions";
97
+ allowDangerouslySkipPermissions: boolean;
98
+ includePartialMessages?: boolean | undefined;
99
+ maxTurns: number;
100
+ cwd: string;
101
+ model: string;
102
+ pathToClaudeCodeExecutable: string;
103
+ };
104
+ };
105
+ //# sourceMappingURL=query.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/proxy/query.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAE7C,OAAO,EAAE,0BAA0B,EAAwB,MAAM,oBAAoB,CAAA;AAErF,MAAM,WAAW,YAAY;IAC3B,iEAAiE;IACjE,MAAM,EAAE,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,CAAA;IACnC,iCAAiC;IACjC,KAAK,EAAE,MAAM,CAAA;IACb,+BAA+B;IAC/B,gBAAgB,EAAE,MAAM,CAAA;IACxB,yCAAyC;IACzC,aAAa,EAAE,MAAM,CAAA;IACrB,gCAAgC;IAChC,gBAAgB,EAAE,MAAM,CAAA;IACxB,0CAA0C;IAC1C,WAAW,EAAE,OAAO,CAAA;IACpB,0CAA0C;IAC1C,MAAM,EAAE,OAAO,CAAA;IACf,6DAA6D;IAC7D,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAC9B,mEAAmE;IACnE,cAAc,CAAC,EAAE,UAAU,CAAC,OAAO,0BAA0B,CAAC,CAAA;IAC9D,wDAAwD;IACxD,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;IAC5C,0DAA0D;IAC1D,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,wCAAwC;IACxC,MAAM,EAAE,OAAO,CAAA;IACf,8CAA8C;IAC9C,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,kCAAkC;IAClC,QAAQ,CAAC,EAAE,GAAG,CAAA;IACd,qDAAqD;IACrD,OAAO,EAAE,YAAY,CAAA;CACtB;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA6ClD"}
@@ -0,0 +1,10 @@
1
+ import type { ProxyConfig, ProxyInstance, ProxyServer } from "./types";
2
+ export type { ProxyConfig, ProxyInstance, ProxyServer };
3
+ import { computeLineageHash, hashMessage, computeMessageHashes, type LineageResult } from "./session/lineage";
4
+ import { clearSessionCache, getMaxSessionsLimit } from "./session/cache";
5
+ export { computeLineageHash, hashMessage, computeMessageHashes };
6
+ export { clearSessionCache, getMaxSessionsLimit };
7
+ export type { LineageResult };
8
+ export declare function createProxyServer(config?: Partial<ProxyConfig>): ProxyServer;
9
+ export declare function startProxyServer(config?: Partial<ProxyConfig>): Promise<ProxyInstance>;
10
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/proxy/server.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AACtE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,CAAA;AAgBvD,OAAO,EACL,kBAAkB,EAClB,WAAW,EACX,oBAAoB,EACpB,KAAK,aAAa,EACnB,MAAM,mBAAmB,CAAA;AAG1B,OAAO,EAA+B,iBAAiB,EAAE,mBAAmB,EAAgB,MAAM,iBAAiB,CAAA;AAEnH,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,oBAAoB,EAAE,CAAA;AAChE,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,CAAA;AACjD,YAAY,EAAE,aAAa,EAAE,CAAA;AAyF7B,wBAAgB,iBAAiB,CAAC,MAAM,GAAE,OAAO,CAAC,WAAW,CAAM,GAAG,WAAW,CAulChF;AAED,wBAAsB,gBAAgB,CAAC,MAAM,GAAE,OAAO,CAAC,WAAW,CAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CA0ChG"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Session cache management.
3
+ *
4
+ * Manages in-memory LRU caches for session and fingerprint lookups,
5
+ * coordinates with the shared file store for cross-proxy session resume.
6
+ */
7
+ import { type LineageResult } from "./lineage";
8
+ export declare function getMaxSessionsLimit(): number;
9
+ /** Clear all session caches (used in tests).
10
+ * Re-reads MERIDIAN_MAX_SESSIONS / CLAUDE_PROXY_MAX_SESSIONS so tests can override the limit. */
11
+ export declare function clearSessionCache(): void;
12
+ /** Evict a stale session from all caches and the shared store.
13
+ * Used when a resume/undo fails because the upstream Claude session is gone. */
14
+ export declare function evictSession(sessionId: string | undefined, workingDirectory?: string, messages?: Array<{
15
+ role: string;
16
+ content: any;
17
+ }>): void;
18
+ /** Look up a cached session by header or fingerprint.
19
+ * Returns a LineageResult that classifies the mutation and includes the
20
+ * session state needed for the correct SDK action. */
21
+ export declare function lookupSession(sessionId: string | undefined, messages: Array<{
22
+ role: string;
23
+ content: any;
24
+ }>, workingDirectory?: string): LineageResult;
25
+ /** Store a session mapping with lineage hash and SDK UUIDs for divergence detection.
26
+ * @param sdkMessageUuids — per-message SDK assistant UUIDs (null for user messages).
27
+ * If provided, merged with any previously stored UUIDs to build a complete map. */
28
+ export declare function storeSession(sessionId: string | undefined, messages: Array<{
29
+ role: string;
30
+ content: any;
31
+ }>, claudeSessionId: string, workingDirectory?: string, sdkMessageUuids?: Array<string | null>): void;
32
+ //# sourceMappingURL=cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../../src/proxy/session/cache.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,EAKL,KAAK,aAAa,EACnB,MAAM,WAAW,CAAA;AAMlB,wBAAgB,mBAAmB,IAAI,MAAM,CAW5C;AAqCD;kGACkG;AAClG,wBAAgB,iBAAiB,SAYhC;AAED;iFACiF;AACjF,wBAAgB,YAAY,CAC1B,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,gBAAgB,CAAC,EAAE,MAAM,EACzB,QAAQ,CAAC,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,GAAG,CAAA;CAAE,CAAC,GAC/C,IAAI,CAoBN;AAUD;;uDAEuD;AACvD,wBAAgB,aAAa,CAC3B,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,QAAQ,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,GAAG,CAAA;CAAE,CAAC,EAC/C,gBAAgB,CAAC,EAAE,MAAM,GACxB,aAAa,CAqDf;AAED;;sFAEsF;AACtF,wBAAgB,YAAY,CAC1B,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,QAAQ,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,GAAG,CAAA;CAAE,CAAC,EAC/C,eAAe,EAAE,MAAM,EACvB,gBAAgB,CAAC,EAAE,MAAM,EACzB,eAAe,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,QAoBvC"}