@rynfar/meridian 1.34.1 → 1.37.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.
Files changed (46) hide show
  1. package/README.md +144 -27
  2. package/dist/cli-p9swy5t3.js +67 -0
  3. package/dist/{cli-g9ypdz51.js → cli-pr79d7nw.js} +9 -5
  4. package/dist/{cli-bwchvbfb.js → cli-ygx1djsx.js} +1838 -147
  5. package/dist/cli.js +9 -9
  6. package/dist/{profileCli-5e3p99k0.js → profileCli-5f15dx7k.js} +1 -1
  7. package/dist/{profilePage-9nkbct3w.js → profilePage-g5t5t6av.js} +4 -2
  8. package/dist/{profiles-ntgacztq.js → profiles-edzz1ffd.js} +1 -1
  9. package/dist/proxy/adapter.d.ts +17 -0
  10. package/dist/proxy/adapter.d.ts.map +1 -1
  11. package/dist/proxy/adapters/crush.d.ts.map +1 -1
  12. package/dist/proxy/auth.d.ts +27 -0
  13. package/dist/proxy/auth.d.ts.map +1 -0
  14. package/dist/proxy/errors.d.ts +1 -1
  15. package/dist/proxy/errors.d.ts.map +1 -1
  16. package/dist/proxy/query.d.ts +21 -1
  17. package/dist/proxy/query.d.ts.map +1 -1
  18. package/dist/proxy/sdkFeatures.d.ts +56 -0
  19. package/dist/proxy/sdkFeatures.d.ts.map +1 -0
  20. package/dist/proxy/server.d.ts.map +1 -1
  21. package/dist/proxy/types.d.ts +2 -0
  22. package/dist/proxy/types.d.ts.map +1 -1
  23. package/dist/server.js +3 -3
  24. package/dist/{setup-5x116vbs.js → setup-v5pnqe04.js} +1 -1
  25. package/dist/telemetry/index.d.ts +9 -4
  26. package/dist/telemetry/index.d.ts.map +1 -1
  27. package/dist/telemetry/logStore.d.ts +4 -25
  28. package/dist/telemetry/logStore.d.ts.map +1 -1
  29. package/dist/telemetry/percentiles.d.ts +12 -0
  30. package/dist/telemetry/percentiles.d.ts.map +1 -0
  31. package/dist/telemetry/profileBar.d.ts +1 -1
  32. package/dist/telemetry/profileBar.d.ts.map +1 -1
  33. package/dist/telemetry/prometheus.d.ts +10 -0
  34. package/dist/telemetry/prometheus.d.ts.map +1 -0
  35. package/dist/telemetry/routes.d.ts.map +1 -1
  36. package/dist/telemetry/settingsPage.d.ts +6 -0
  37. package/dist/telemetry/settingsPage.d.ts.map +1 -0
  38. package/dist/telemetry/sqlite.d.ts +7 -0
  39. package/dist/telemetry/sqlite.d.ts.map +1 -0
  40. package/dist/telemetry/store.d.ts +3 -3
  41. package/dist/telemetry/store.d.ts.map +1 -1
  42. package/dist/telemetry/types.d.ts +51 -0
  43. package/dist/telemetry/types.d.ts.map +1 -1
  44. package/dist/{tokenRefresh-ywwpe8k2.js → tokenRefresh-y7d1qvb3.js} +1 -1
  45. package/package.json +4 -3
  46. package/dist/cli-a05ws7rb.js +0 -18
package/dist/cli.js CHANGED
@@ -1,15 +1,15 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  startProxyServer
4
- } from "./cli-bwchvbfb.js";
5
- import"./cli-g9ypdz51.js";
4
+ } from "./cli-ygx1djsx.js";
5
+ import"./cli-pr79d7nw.js";
6
6
  import"./cli-rtab0qa6.js";
7
7
  import"./cli-m9pfb7h9.js";
8
8
  import"./cli-vdp9s10c.js";
9
9
  import"./cli-340h1chz.js";
10
10
  import {
11
11
  __require
12
- } from "./cli-a05ws7rb.js";
12
+ } from "./cli-p9swy5t3.js";
13
13
 
14
14
  // bin/cli.ts
15
15
  import { createRequire } from "module";
@@ -49,7 +49,7 @@ See https://github.com/rynfar/meridian for full documentation.`);
49
49
  process.exit(0);
50
50
  }
51
51
  if (args[0] === "profile") {
52
- const { profileAdd, profileList, profileRemove, profileSwitch, profileLogin, profileHelp } = await import("./profileCli-5e3p99k0.js");
52
+ const { profileAdd, profileList, profileRemove, profileSwitch, profileLogin, profileHelp } = await import("./profileCli-5f15dx7k.js");
53
53
  const subcommand = args[1];
54
54
  const profileId = args[2];
55
55
  if (subcommand === "add" && profileId)
@@ -67,7 +67,7 @@ if (args[0] === "profile") {
67
67
  process.exit(0);
68
68
  }
69
69
  if (args[0] === "setup") {
70
- const { findPluginPath, runSetup } = await import("./setup-5x116vbs.js");
70
+ const { findPluginPath, runSetup } = await import("./setup-v5pnqe04.js");
71
71
  const pluginPath = findPluginPath(import.meta.url);
72
72
  const result = runSetup(pluginPath);
73
73
  if (result.alreadyConfigured) {
@@ -88,7 +88,7 @@ Restart OpenCode for the plugin to take effect.`);
88
88
  process.exit(0);
89
89
  }
90
90
  if (args[0] === "refresh-token") {
91
- const { refreshOAuthToken } = await import("./tokenRefresh-ywwpe8k2.js");
91
+ const { refreshOAuthToken } = await import("./tokenRefresh-y7d1qvb3.js");
92
92
  const success = await refreshOAuthToken();
93
93
  if (success) {
94
94
  console.log("Token refreshed successfully");
@@ -121,7 +121,7 @@ try {
121
121
  }
122
122
  async function runCli(start = startProxyServer, runExec = exec) {
123
123
  try {
124
- const { findOpencodeConfigPath, checkPluginConfigured, findPluginPath } = await import("./setup-5x116vbs.js");
124
+ const { findOpencodeConfigPath, checkPluginConfigured, findPluginPath } = await import("./setup-v5pnqe04.js");
125
125
  const configPath = findOpencodeConfigPath();
126
126
  const { existsSync } = await import("fs");
127
127
  if (existsSync(configPath) && !checkPluginConfigured(configPath)) {
@@ -146,10 +146,10 @@ async function runCli(start = startProxyServer, runExec = exec) {
146
146
  console.error("\x1B[33m⚠ Could not verify Claude auth status. If requests fail, run: claude login\x1B[0m");
147
147
  }
148
148
  if (!profiles) {
149
- const { enableDiskProfileDiscovery } = await import("./profiles-ntgacztq.js");
149
+ const { enableDiskProfileDiscovery } = await import("./profiles-edzz1ffd.js");
150
150
  enableDiskProfileDiscovery();
151
151
  }
152
- const proxy = await start({ port, host, idleTimeoutSeconds, profiles, defaultProfile });
152
+ const proxy = await start({ port, host, idleTimeoutSeconds, profiles, defaultProfile, version });
153
153
  proxy.server.on("error", (error) => {
154
154
  if (error.code === "EADDRINUSE") {
155
155
  process.exit(1);
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  setSetting
3
3
  } from "./cli-340h1chz.js";
4
- import"./cli-a05ws7rb.js";
4
+ import"./cli-p9swy5t3.js";
5
5
 
6
6
  // src/proxy/profileCli.ts
7
7
  import { mkdirSync, existsSync, rmSync, readFileSync, writeFileSync } from "node:fs";
@@ -1,11 +1,13 @@
1
1
  import {
2
+ init_profileBar,
2
3
  profileBarCss,
3
4
  profileBarHtml,
4
5
  profileBarJs
5
- } from "./cli-g9ypdz51.js";
6
- import"./cli-a05ws7rb.js";
6
+ } from "./cli-pr79d7nw.js";
7
+ import"./cli-p9swy5t3.js";
7
8
 
8
9
  // src/telemetry/profilePage.ts
10
+ init_profileBar();
9
11
  var profilePageHtml = `<!DOCTYPE html>
10
12
  <html lang="en">
11
13
  <head>
@@ -11,7 +11,7 @@ import {
11
11
  setActiveProfile
12
12
  } from "./cli-vdp9s10c.js";
13
13
  import"./cli-340h1chz.js";
14
- import"./cli-a05ws7rb.js";
14
+ import"./cli-p9swy5t3.js";
15
15
  export {
16
16
  setActiveProfile,
17
17
  restoreActiveProfile,
@@ -5,6 +5,7 @@
5
5
  * different calling agents (OpenCode, Claude Code, custom agents).
6
6
  */
7
7
  import type { Context } from "hono";
8
+ import type { SettingSource } from "@anthropic-ai/claude-agent-sdk";
8
9
  /**
9
10
  * An agent adapter provides agent-specific configuration to the proxy.
10
11
  * The proxy calls these methods during request handling to determine
@@ -91,6 +92,22 @@ export interface AgentAdapter {
91
92
  * Return undefined to disable auto-defer for this agent.
92
93
  */
93
94
  getCoreToolNames?(): readonly string[];
95
+ /**
96
+ * SDK setting sources to load for this agent.
97
+ *
98
+ * Controls whether CLAUDE.md files, user settings, and project settings
99
+ * are loaded by the SDK subprocess. This is what makes Claude "know"
100
+ * about your project instructions and personal preferences.
101
+ *
102
+ * - `['user', 'project']` — load ~/.claude/CLAUDE.md and .claude/CLAUDE.md
103
+ * - `['project']` — load only project-level CLAUDE.md
104
+ * - `[]` or undefined — isolation mode (no filesystem settings loaded)
105
+ *
106
+ * Agents that manage their own context (OpenCode, ForgeCode) should return
107
+ * empty/undefined. Agents that want full Claude Code behavior (Crush, Pi)
108
+ * should return `['user', 'project']`.
109
+ */
110
+ getSettingSources?(): SettingSource[];
94
111
  /**
95
112
  * Whether this agent's client can render thinking blocks.
96
113
  *
@@ -1 +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;;;;;;OAMG;IACH,gBAAgB,CAAC,CAAC,IAAI,EAAE,GAAG,GAAG,OAAO,CAAA;IAErC;;;;;;;;OAQG;IACH,eAAe,CAAC,IAAI,OAAO,CAAA;IAE3B;;;;;;;OAOG;IACH,gBAAgB,CAAC,IAAI,SAAS,MAAM,EAAE,CAAA;IAEtC;;;;;;;OAOG;IACH,gBAAgB,CAAC,IAAI,OAAO,CAAA;IAE5B;;;;;;;;;;;;;;;OAeG;IACH,6BAA6B,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,GAAG,OAAO,eAAe,EAAE,UAAU,EAAE,CAAA;CAC3G"}
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;AACnC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAA;AAEnE;;;;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;;;;;;OAMG;IACH,gBAAgB,CAAC,CAAC,IAAI,EAAE,GAAG,GAAG,OAAO,CAAA;IAErC;;;;;;;;OAQG;IACH,eAAe,CAAC,IAAI,OAAO,CAAA;IAE3B;;;;;;;OAOG;IACH,gBAAgB,CAAC,IAAI,SAAS,MAAM,EAAE,CAAA;IAEtC;;;;;;;;;;;;;;OAcG;IACH,iBAAiB,CAAC,IAAI,aAAa,EAAE,CAAA;IAErC;;;;;;;OAOG;IACH,gBAAgB,CAAC,IAAI,OAAO,CAAA;IAE5B;;;;;;;;;;;;;;;OAeG;IACH,6BAA6B,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,GAAG,OAAO,eAAe,EAAE,UAAU,EAAE,CAAA;CAC3G"}
@@ -1 +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;AAgB9C,eAAO,MAAM,YAAY,EAAE,YAsF1B,CAAA"}
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;AAgB9C,eAAO,MAAM,YAAY,EAAE,YAyF1B,CAAA"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Optional API key authentication middleware.
3
+ *
4
+ * When MERIDIAN_API_KEY is set, requests to protected routes must include
5
+ * a matching key via `x-api-key` header or `Authorization: Bearer` header.
6
+ * When unset, all routes are open (default behavior, backward compatible).
7
+ *
8
+ * Uses constant-time comparison to prevent timing attacks.
9
+ */
10
+ import type { Context, Next } from "hono";
11
+ /**
12
+ * Whether API key authentication is enabled.
13
+ * True when MERIDIAN_API_KEY is set to a non-empty value.
14
+ */
15
+ export declare function authEnabled(): boolean;
16
+ /**
17
+ * Hono middleware that rejects requests without a valid API key.
18
+ * No-op when MERIDIAN_API_KEY is not set.
19
+ */
20
+ export declare function requireAuth(c: Context, next: Next): Promise<void | (Response & import("hono").TypedResponse<{
21
+ type: string;
22
+ error: {
23
+ type: string;
24
+ message: string;
25
+ };
26
+ }, 401, "json">)>;
27
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/proxy/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAMzC;;;GAGG;AACH,wBAAgB,WAAW,IAAI,OAAO,CAErC;AA0BD;;;GAGG;AACH,wBAAsB,WAAW,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI;;;;;;kBAgBvD"}
@@ -24,7 +24,7 @@ export declare function isExpiredTokenError(errMsg: string): boolean;
24
24
  /**
25
25
  * Detect errors caused by stale session/message UUIDs.
26
26
  * These happen when the upstream Claude session no longer contains
27
- * the referenced message (expired, compacted server-side, etc.).
27
+ * the referenced message or conversation (expired, evicted server-side, etc.).
28
28
  */
29
29
  export declare function isStaleSessionError(error: unknown): boolean;
30
30
  /**
@@ -1 +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,CA+G7D;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAG3D;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAG3D;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAGxD;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAGjE"}
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,CA+G7D;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAG3D;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAO3D;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAGxD;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAGjE"}
@@ -5,7 +5,7 @@
5
5
  * between the streaming and non-streaming paths in server.ts.
6
6
  */
7
7
  import type { AgentAdapter } from "./adapter";
8
- import type { Options } from "@anthropic-ai/claude-agent-sdk";
8
+ import type { Options, SettingSource } from "@anthropic-ai/claude-agent-sdk";
9
9
  import { createPassthroughMcpServer } from "./passthroughTools";
10
10
  export interface QueryContext {
11
11
  /** The prompt to send (text or async iterable for multimodal) */
@@ -59,6 +59,26 @@ export interface QueryContext {
59
59
  };
60
60
  /** Beta features to enable */
61
61
  betas?: string[];
62
+ /** SDK setting sources — controls CLAUDE.md and user settings loading */
63
+ settingSources?: SettingSource[];
64
+ /** Use the Claude Code system prompt preset */
65
+ codeSystemPrompt?: boolean;
66
+ /** Include the client agent's system prompt */
67
+ clientSystemPrompt?: boolean;
68
+ /** Enable auto-memory (read + write across sessions) */
69
+ memory?: boolean;
70
+ /** Enable background memory consolidation (dreaming) */
71
+ dreaming?: boolean;
72
+ /** Share memory directory with Claude Code (~/.claude) */
73
+ sharedMemory?: boolean;
74
+ /** Per-request cost cap in USD */
75
+ maxBudgetUsd?: number;
76
+ /** Fallback model when primary fails */
77
+ fallbackModel?: string;
78
+ /** Enable SDK debug logging */
79
+ sdkDebug?: boolean;
80
+ /** Additional directories Claude can access */
81
+ additionalDirectories?: string[];
62
82
  }
63
83
  /**
64
84
  * Build the options object for the Claude Agent SDK query() call.
@@ -1 +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;AAC7C,OAAO,KAAK,EAAE,OAAO,EAAW,MAAM,gCAAgC,CAAA;AAEtE,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,yDAAyD;IACzD,gBAAgB,EAAE,OAAO,CAAA;IACzB,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;IACrB,kEAAkE;IAClE,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IACjC,mEAAmE;IACnE,MAAM,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,CAAA;IAC1C,0EAA0E;IAC1E,QAAQ,CAAC,EAAE;QAAE,IAAI,EAAE,UAAU,CAAA;KAAE,GAAG;QAAE,IAAI,EAAE,SAAS,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,IAAI,EAAE,UAAU,CAAA;KAAE,CAAA;IACnG,8EAA8E;IAC9E,UAAU,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;IAC9B,8BAA8B;IAC9B,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;CACjB;AAED;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAA;IAC9B,OAAO,EAAE,OAAO,CAAA;CACjB;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,YAAY,GAAG,gBAAgB,CA4ErE"}
1
+ {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/proxy/query.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAC7C,OAAO,KAAK,EAAE,OAAO,EAAW,aAAa,EAAE,MAAM,gCAAgC,CAAA;AAErF,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,yDAAyD;IACzD,gBAAgB,EAAE,OAAO,CAAA;IACzB,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;IACrB,kEAAkE;IAClE,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IACjC,mEAAmE;IACnE,MAAM,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,CAAA;IAC1C,0EAA0E;IAC1E,QAAQ,CAAC,EAAE;QAAE,IAAI,EAAE,UAAU,CAAA;KAAE,GAAG;QAAE,IAAI,EAAE,SAAS,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,IAAI,EAAE,UAAU,CAAA;KAAE,CAAA;IACnG,8EAA8E;IAC9E,UAAU,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;IAC9B,8BAA8B;IAC9B,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB,yEAAyE;IACzE,cAAc,CAAC,EAAE,aAAa,EAAE,CAAA;IAChC,+CAA+C;IAC/C,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,+CAA+C;IAC/C,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,wDAAwD;IACxD,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,wDAAwD;IACxD,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,0DAA0D;IAC1D,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,kCAAkC;IAClC,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,wCAAwC;IACxC,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,+BAA+B;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,+CAA+C;IAC/C,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAA;CACjC;AAED;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAA;IAC9B,OAAO,EAAE,OAAO,CAAA;CACjB;AAuBD,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,YAAY,GAAG,gBAAgB,CAsFrE"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * SDK feature toggles — per-adapter configuration for Claude Code features.
3
+ *
4
+ * Persisted to ~/.config/meridian/sdk-features.json.
5
+ * Read at request time (no restart needed to pick up changes).
6
+ */
7
+ export interface AdapterFeatures {
8
+ /** Use the Claude Code system prompt preset (tool instructions, safety rules) */
9
+ codeSystemPrompt: boolean;
10
+ /** Include the client agent's system prompt (e.g. OpenCode/Crush instructions) */
11
+ clientSystemPrompt: boolean;
12
+ /** Load CLAUDE.md instruction files (off, project, full) */
13
+ claudeMd: "off" | "project" | "full";
14
+ /** Enable auto-memory (read + write across sessions) */
15
+ memory: boolean;
16
+ /** Enable background memory consolidation */
17
+ dreaming: boolean;
18
+ /** Default thinking mode (adaptive, enabled, disabled) */
19
+ thinking: "adaptive" | "enabled" | "disabled";
20
+ /** Forward thinking blocks to the client */
21
+ thinkingPassthrough: boolean;
22
+ /** Share memory directory with Claude Code (~/.claude instead of SDK default) */
23
+ sharedMemory: boolean;
24
+ /** Per-request cost cap in USD (0 = disabled) */
25
+ maxBudgetUsd: number;
26
+ /** Fallback model when primary fails (empty = disabled) */
27
+ fallbackModel: string;
28
+ /** Enable SDK debug logging to proxy stderr */
29
+ sdkDebug: boolean;
30
+ /** Comma-separated extra directories Claude can access (beyond CWD) */
31
+ additionalDirectories: string;
32
+ }
33
+ export type FeatureConfig = Record<string, Partial<AdapterFeatures>>;
34
+ /**
35
+ * Get resolved features for an adapter.
36
+ * Priority: user config > adapter defaults > global defaults
37
+ */
38
+ export declare function getFeaturesForAdapter(adapterName: string): AdapterFeatures;
39
+ /**
40
+ * Get the full config for all adapters (for the settings UI).
41
+ */
42
+ export declare function getAllFeatureConfigs(): Record<string, AdapterFeatures>;
43
+ /**
44
+ * Validate and sanitise a partial feature update.
45
+ * Returns only recognised keys with correct types; throws on invalid input.
46
+ */
47
+ export declare function validateFeatureUpdate(raw: unknown): Partial<AdapterFeatures>;
48
+ /**
49
+ * Update features for a specific adapter.
50
+ */
51
+ export declare function updateAdapterFeatures(adapterName: string, features: Partial<AdapterFeatures>): void;
52
+ /**
53
+ * Reset an adapter to its defaults (remove user overrides).
54
+ */
55
+ export declare function resetAdapterFeatures(adapterName: string): void;
56
+ //# sourceMappingURL=sdkFeatures.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sdkFeatures.d.ts","sourceRoot":"","sources":["../../src/proxy/sdkFeatures.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,MAAM,WAAW,eAAe;IAC9B,iFAAiF;IACjF,gBAAgB,EAAE,OAAO,CAAA;IACzB,kFAAkF;IAClF,kBAAkB,EAAE,OAAO,CAAA;IAC3B,4DAA4D;IAC5D,QAAQ,EAAE,KAAK,GAAG,SAAS,GAAG,MAAM,CAAA;IACpC,wDAAwD;IACxD,MAAM,EAAE,OAAO,CAAA;IACf,6CAA6C;IAC7C,QAAQ,EAAE,OAAO,CAAA;IACjB,0DAA0D;IAC1D,QAAQ,EAAE,UAAU,GAAG,SAAS,GAAG,UAAU,CAAA;IAC7C,4CAA4C;IAC5C,mBAAmB,EAAE,OAAO,CAAA;IAC5B,iFAAiF;IACjF,YAAY,EAAE,OAAO,CAAA;IACrB,iDAAiD;IACjD,YAAY,EAAE,MAAM,CAAA;IACpB,2DAA2D;IAC3D,aAAa,EAAE,MAAM,CAAA;IACrB,+CAA+C;IAC/C,QAAQ,EAAE,OAAO,CAAA;IACjB,uEAAuE;IACvE,qBAAqB,EAAE,MAAM,CAAA;CAC9B;AAED,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC,CAAA;AA6DpE;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,eAAe,CAU1E;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAOtE;AAKD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,eAAe,CAAC,CAgC5E;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,IAAI,CAInG;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAI9D"}
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/proxy/server.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AACtE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,CAAA;AAyBvD,OAAO,EACL,kBAAkB,EAClB,WAAW,EACX,oBAAoB,EACpB,KAAK,aAAa,EAEnB,MAAM,mBAAmB,CAAA;AAG1B,OAAO,EAA+B,iBAAiB,EAAE,mBAAmB,EAAsC,MAAM,iBAAiB,CAAA;AAGzI,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,oBAAoB,EAAE,CAAA;AAChE,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,CAAA;AACjD,YAAY,EAAE,aAAa,EAAE,CAAA;AAkJ7B,wBAAgB,iBAAiB,CAAC,MAAM,GAAE,OAAO,CAAC,WAAW,CAAM,GAAG,WAAW,CAwwDhF;AAED,wBAAsB,gBAAgB,CAAC,MAAM,GAAE,OAAO,CAAC,WAAW,CAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAiEhG"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/proxy/server.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AACtE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,CAAA;AAyBvD,OAAO,EACL,kBAAkB,EAClB,WAAW,EACX,oBAAoB,EACpB,KAAK,aAAa,EAEnB,MAAM,mBAAmB,CAAA;AAG1B,OAAO,EAA+B,iBAAiB,EAAE,mBAAmB,EAAsC,MAAM,iBAAiB,CAAA;AAGzI,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,oBAAoB,EAAE,CAAA;AAChE,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,CAAA;AACjD,YAAY,EAAE,aAAa,EAAE,CAAA;AAkJ7B,wBAAgB,iBAAiB,CAAC,MAAM,GAAE,OAAO,CAAC,WAAW,CAAM,GAAG,WAAW,CAk3DhF;AAED,wBAAsB,gBAAgB,CAAC,MAAM,GAAE,OAAO,CAAC,WAAW,CAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAiEhG"}
@@ -10,6 +10,8 @@ export interface ProxyConfig {
10
10
  profiles?: ProfileConfig[];
11
11
  /** Default profile ID when no header is sent */
12
12
  defaultProfile?: string;
13
+ /** Package version, exposed via /health endpoint */
14
+ version?: string;
13
15
  }
14
16
  export interface ProxyInstance {
15
17
  /** The underlying http.Server */
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/proxy/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAA;AACvC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/C,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,OAAO,CAAA;IACd,kBAAkB,EAAE,MAAM,CAAA;IAC1B,MAAM,EAAE,OAAO,CAAA;IACf,oDAAoD;IACpD,QAAQ,CAAC,EAAE,aAAa,EAAE,CAAA;IAC1B,gDAAgD;IAChD,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,iCAAiC;IACjC,MAAM,EAAE,MAAM,CAAA;IACd,uCAAuC;IACvC,MAAM,EAAE,WAAW,CAAA;IACnB,mEAAmE;IACnE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACvB;AAED,oFAAoF;AACpF,MAAM,WAAW,WAAW;IAC1B,+DAA+D;IAC/D,GAAG,EAAE;QAAE,KAAK,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;KAAE,CAAA;IAClF,uCAAuC;IACvC,MAAM,EAAE,WAAW,CAAA;CACpB;AAED,eAAO,MAAM,oBAAoB,EAAE,WAQlC,CAAA"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/proxy/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAA;AACvC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/C,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,OAAO,CAAA;IACd,kBAAkB,EAAE,MAAM,CAAA;IAC1B,MAAM,EAAE,OAAO,CAAA;IACf,oDAAoD;IACpD,QAAQ,CAAC,EAAE,aAAa,EAAE,CAAA;IAC1B,gDAAgD;IAChD,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,oDAAoD;IACpD,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,iCAAiC;IACjC,MAAM,EAAE,MAAM,CAAA;IACd,uCAAuC;IACvC,MAAM,EAAE,WAAW,CAAA;IACnB,mEAAmE;IACnE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACvB;AAED,oFAAoF;AACpF,MAAM,WAAW,WAAW;IAC1B,+DAA+D;IAC/D,GAAG,EAAE;QAAE,KAAK,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;KAAE,CAAA;IAClF,uCAAuC;IACvC,MAAM,EAAE,WAAW,CAAA;CACpB;AAED,eAAO,MAAM,oBAAoB,EAAE,WASlC,CAAA"}
package/dist/server.js CHANGED
@@ -6,13 +6,13 @@ import {
6
6
  getMaxSessionsLimit,
7
7
  hashMessage,
8
8
  startProxyServer
9
- } from "./cli-bwchvbfb.js";
10
- import"./cli-g9ypdz51.js";
9
+ } from "./cli-ygx1djsx.js";
10
+ import"./cli-pr79d7nw.js";
11
11
  import"./cli-rtab0qa6.js";
12
12
  import"./cli-m9pfb7h9.js";
13
13
  import"./cli-vdp9s10c.js";
14
14
  import"./cli-340h1chz.js";
15
- import"./cli-a05ws7rb.js";
15
+ import"./cli-p9swy5t3.js";
16
16
  export {
17
17
  startProxyServer,
18
18
  hashMessage,
@@ -4,7 +4,7 @@ import {
4
4
  findPluginPath,
5
5
  runSetup
6
6
  } from "./cli-rtab0qa6.js";
7
- import"./cli-a05ws7rb.js";
7
+ import"./cli-p9swy5t3.js";
8
8
  export {
9
9
  runSetup,
10
10
  findPluginPath,
@@ -1,7 +1,12 @@
1
- export { telemetryStore, TelemetryStore } from "./store";
2
- export { diagnosticLog, DiagnosticLogStore } from "./logStore";
1
+ import type { ITelemetryStore, IDiagnosticLogStore } from "./types";
2
+ export declare const telemetryStore: ITelemetryStore;
3
+ export declare const diagnosticLog: IDiagnosticLogStore;
4
+ export { MemoryTelemetryStore } from "./store";
5
+ export { MemoryDiagnosticLogStore } from "./logStore";
3
6
  export { createTelemetryRoutes } from "./routes";
4
7
  export { landingHtml } from "./landing";
5
- export type { RequestMetric, TelemetrySummary, PhaseTiming } from "./types";
6
- export type { DiagnosticLog } from "./logStore";
8
+ export { computePercentiles, computeSummary } from "./percentiles";
9
+ export { renderPrometheusMetrics } from "./prometheus";
10
+ export { createSqliteStores } from "./sqlite";
11
+ export type { RequestMetric, TelemetrySummary, PhaseTiming, ITelemetryStore, IDiagnosticLogStore, DiagnosticLog, } from "./types";
7
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/telemetry/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AACxD,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAC9D,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAA;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AACvC,YAAY,EAAE,aAAa,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAC3E,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/telemetry/index.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAA;AAgCnE,eAAO,MAAM,cAAc,EAAE,eAAkC,CAAA;AAC/D,eAAO,MAAM,aAAa,EAAE,mBAAwC,CAAA;AAEpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;AAC9C,OAAO,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAA;AACrD,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAA;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AACvC,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAClE,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAA;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAA;AAC7C,YAAY,EACV,aAAa,EACb,gBAAgB,EAChB,WAAW,EACX,eAAe,EACf,mBAAmB,EACnB,aAAa,GACd,MAAM,SAAS,CAAA"}
@@ -5,46 +5,25 @@
5
5
  * and surfaces them via the telemetry API and dashboard. Replaces the need
6
6
  * for users to dig through stderr to report issues.
7
7
  */
8
- export interface DiagnosticLog {
9
- /** Unix timestamp */
10
- timestamp: number;
11
- /** Log level */
12
- level: "info" | "warn" | "error";
13
- /** Log category for filtering */
14
- category: "session" | "lineage" | "error" | "lifecycle" | "token";
15
- /** Request ID (if associated with a request) */
16
- requestId?: string;
17
- /** Human-readable message */
18
- message: string;
19
- }
20
- export declare class DiagnosticLogStore {
8
+ import type { DiagnosticLog, IDiagnosticLogStore } from "./types";
9
+ export type { DiagnosticLog } from "./types";
10
+ export declare class MemoryDiagnosticLogStore implements IDiagnosticLogStore {
21
11
  private buffer;
22
12
  private head;
23
13
  private count;
24
14
  private readonly capacity;
25
15
  constructor(capacity?: number);
26
- /** Append a log entry. */
27
16
  log(entry: Omit<DiagnosticLog, "timestamp">): void;
28
- /** Convenience: log a session event. */
29
17
  session(message: string, requestId?: string): void;
30
- /** Convenience: log a lineage event (compaction, undo, diverged). */
31
18
  lineage(message: string, requestId?: string): void;
32
- /** Convenience: log an error. */
33
19
  error(message: string, requestId?: string): void;
34
- /**
35
- * Retrieve recent logs, newest first.
36
- * @param options.limit - Max entries (default: 100)
37
- * @param options.since - Only entries after this timestamp
38
- * @param options.category - Filter by category
39
- */
40
20
  getRecent(options?: {
41
21
  limit?: number;
42
22
  since?: number;
43
23
  category?: string;
44
24
  }): DiagnosticLog[];
45
- /** Clear all stored logs. */
46
25
  clear(): void;
47
26
  }
48
27
  /** Singleton instance used by the proxy. */
49
- export declare const diagnosticLog: DiagnosticLogStore;
28
+ export declare const diagnosticLog: MemoryDiagnosticLogStore;
50
29
  //# sourceMappingURL=logStore.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"logStore.d.ts","sourceRoot":"","sources":["../../src/telemetry/logStore.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,WAAW,aAAa;IAC5B,qBAAqB;IACrB,SAAS,EAAE,MAAM,CAAA;IACjB,gBAAgB;IAChB,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAA;IAChC,iCAAiC;IACjC,QAAQ,EAAE,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,WAAW,GAAG,OAAO,CAAA;IACjE,gDAAgD;IAChD,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,6BAA6B;IAC7B,OAAO,EAAE,MAAM,CAAA;CAChB;AAID,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,IAAI,CAAI;IAChB,OAAO,CAAC,KAAK,CAAI;IACjB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAQ;gBAErB,QAAQ,CAAC,EAAE,MAAM;IAK7B,0BAA0B;IAC1B,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,aAAa,EAAE,WAAW,CAAC,GAAG,IAAI;IAMlD,wCAAwC;IACxC,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI;IAIlD,qEAAqE;IACrE,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI;IAIlD,iCAAiC;IACjC,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI;IAIhD;;;;;OAKG;IACH,SAAS,CAAC,OAAO,GAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,aAAa,EAAE;IAgB/F,6BAA6B;IAC7B,KAAK,IAAI,IAAI;CAKd;AAED,4CAA4C;AAC5C,eAAO,MAAM,aAAa,oBAA2B,CAAA"}
1
+ {"version":3,"file":"logStore.d.ts","sourceRoot":"","sources":["../../src/telemetry/logStore.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAA;AACjE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAI5C,qBAAa,wBAAyB,YAAW,mBAAmB;IAClE,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,IAAI,CAAI;IAChB,OAAO,CAAC,KAAK,CAAI;IACjB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAQ;gBAErB,QAAQ,CAAC,EAAE,MAAM;IAK7B,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,aAAa,EAAE,WAAW,CAAC,GAAG,IAAI;IAMlD,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI;IAIlD,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI;IAIlD,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI;IAIhD,SAAS,CAAC,OAAO,GAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,aAAa,EAAE;IAgB/F,KAAK,IAAI,IAAI;CAKd;AAED,4CAA4C;AAC5C,eAAO,MAAM,aAAa,0BAAiC,CAAA"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Shared percentile computation used by all telemetry store implementations.
3
+ */
4
+ import type { RequestMetric, PhaseTiming, TelemetrySummary } from "./types";
5
+ export declare function computePercentiles(values: number[]): PhaseTiming;
6
+ /**
7
+ * Compute a TelemetrySummary from an array of RequestMetric.
8
+ * Both MemoryTelemetryStore and SqliteTelemetryStore use this
9
+ * to guarantee identical output.
10
+ */
11
+ export declare function computeSummary(metrics: RequestMetric[], windowMs: number): TelemetrySummary;
12
+ //# sourceMappingURL=percentiles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"percentiles.d.ts","sourceRoot":"","sources":["../../src/telemetry/percentiles.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAE3E,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,WAAW,CAchE;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,aAAa,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,gBAAgB,CAuG3F"}
@@ -6,6 +6,6 @@
6
6
  * POST /profiles/active — no page reload needed.
7
7
  */
8
8
  export declare const profileBarCss = "\n .meridian-profile-bar {\n position: sticky; top: 0; z-index: 100;\n display: none; align-items: center; gap: 12px;\n padding: 8px 24px;\n background: rgba(13, 17, 23, 0.92);\n backdrop-filter: blur(12px);\n border-bottom: 1px solid var(--border, #30363d);\n font-size: 12px;\n color: var(--muted, #8b949e);\n }\n .meridian-profile-bar.visible { display: flex; }\n .meridian-profile-bar .profile-label {\n font-weight: 500; text-transform: uppercase; letter-spacing: 0.5px;\n font-size: 10px; color: var(--muted, #8b949e);\n }\n .meridian-profile-bar select {\n background: var(--surface, #161b22); color: var(--text, #e6edf3);\n border: 1px solid var(--border, #30363d); border-radius: 6px;\n padding: 4px 24px 4px 10px; font-size: 12px; cursor: pointer;\n appearance: none;\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath d='M3 5l3 3 3-3' fill='none' stroke='%238b949e' stroke-width='1.5'/%3E%3C/svg%3E\");\n background-repeat: no-repeat; background-position: right 6px center;\n }\n .meridian-profile-bar select:hover { border-color: var(--accent, #58a6ff); }\n .meridian-profile-bar select:focus { outline: none; border-color: var(--accent, #58a6ff); box-shadow: 0 0 0 1px var(--accent, #58a6ff); }\n .meridian-profile-bar .profile-status {\n font-size: 11px; color: var(--green, #3fb950); opacity: 0;\n transition: opacity 0.3s;\n }\n .meridian-profile-bar .profile-status.show { opacity: 1; }\n .meridian-profile-bar .profile-type {\n font-size: 10px; padding: 2px 8px; border-radius: 4px;\n background: var(--surface, #161b22); border: 1px solid var(--border, #30363d);\n }\n .meridian-profile-bar .spacer { flex: 1; }\n .meridian-profile-bar .profile-nav a {\n color: var(--muted, #8b949e); text-decoration: none; font-size: 11px;\n padding: 4px 8px; border-radius: 4px; transition: color 0.15s;\n }\n .meridian-profile-bar .profile-nav a:hover { color: var(--text, #e6edf3); }\n .meridian-profile-bar .profile-nav a.active { color: var(--accent, #58a6ff); }\n";
9
- export declare const profileBarHtml = "\n<div class=\"meridian-profile-bar\" id=\"meridianProfileBar\">\n <span class=\"profile-label\">Profile</span>\n <select id=\"meridianProfileSelect\"></select>\n <span class=\"profile-type\" id=\"meridianProfileType\"></span>\n <span class=\"profile-status\" id=\"meridianProfileStatus\">\u2713 Switched</span>\n <div class=\"spacer\"></div>\n <div class=\"profile-nav\">\n <a href=\"/\" id=\"nav-home\">Home</a>\n <a href=\"/profiles\" id=\"nav-profiles\">Profiles</a>\n <a href=\"/telemetry\" id=\"nav-telemetry\">Telemetry</a>\n </div>\n</div>\n";
9
+ export declare const profileBarHtml = "\n<div class=\"meridian-profile-bar\" id=\"meridianProfileBar\">\n <span class=\"profile-label\">Profile</span>\n <select id=\"meridianProfileSelect\"></select>\n <span class=\"profile-type\" id=\"meridianProfileType\"></span>\n <span class=\"profile-status\" id=\"meridianProfileStatus\">\u2713 Switched</span>\n <div class=\"spacer\"></div>\n <div class=\"profile-nav\">\n <a href=\"/\" id=\"nav-home\">Home</a>\n <a href=\"/settings\" id=\"nav-settings\">Settings</a>\n <a href=\"/profiles\" id=\"nav-profiles\">Profiles</a>\n <a href=\"/telemetry\" id=\"nav-telemetry\">Telemetry</a>\n </div>\n</div>\n";
10
10
  export declare const profileBarJs = "\n(function() {\n var profileBar = document.getElementById('meridianProfileBar');\n var profileSelect = document.getElementById('meridianProfileSelect');\n var profileType = document.getElementById('meridianProfileType');\n var profileStatus = document.getElementById('meridianProfileStatus');\n var statusTimeout;\n\n // Highlight active nav link\n var path = location.pathname;\n var navLinks = document.querySelectorAll('.profile-nav a');\n navLinks.forEach(function(a) {\n if (a.getAttribute('href') === path || (path === '/telemetry' && a.id === 'nav-telemetry') || (path === '/' && a.id === 'nav-home')) {\n a.classList.add('active');\n }\n });\n\n function esc(s) { var d = document.createElement('div'); d.textContent = s; return d.innerHTML; }\n\n function loadProfiles() {\n fetch('/profiles/list').then(function(r) { return r.json(); }).then(function(data) {\n if (!data.profiles || data.profiles.length === 0) {\n profileBar.classList.remove('visible');\n return;\n }\n profileBar.classList.add('visible');\n var current = data.profiles.find(function(p) { return p.isActive; });\n profileSelect.innerHTML = data.profiles.map(function(p) {\n return '<option value=\"' + esc(p.id) + '\"' + (p.isActive ? ' selected' : '') + '>' + esc(p.id) + '</option>';\n }).join('');\n if (current) profileType.textContent = current.type;\n }).catch(function() {});\n }\n\n profileSelect.onchange = function() {\n fetch('/profiles/active', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ profile: profileSelect.value })\n }).then(function(r) { return r.json(); }).then(function(data) {\n if (data.success) {\n profileStatus.classList.add('show');\n clearTimeout(statusTimeout);\n statusTimeout = setTimeout(function() { profileStatus.classList.remove('show'); }, 2000);\n loadProfiles();\n }\n }).catch(function() {});\n };\n\n loadProfiles();\n setInterval(loadProfiles, 10000);\n})();\n";
11
11
  //# sourceMappingURL=profileBar.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"profileBar.d.ts","sourceRoot":"","sources":["../../src/telemetry/profileBar.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,eAAO,MAAM,aAAa,wmEA0CzB,CAAA;AAED,eAAO,MAAM,cAAc,0jBAa1B,CAAA;AAED,eAAO,MAAM,YAAY,yiEAoDxB,CAAA"}
1
+ {"version":3,"file":"profileBar.d.ts","sourceRoot":"","sources":["../../src/telemetry/profileBar.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,eAAO,MAAM,aAAa,wmEA0CzB,CAAA;AAED,eAAO,MAAM,cAAc,snBAc1B,CAAA;AAED,eAAO,MAAM,YAAY,yiEAoDxB,CAAA"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Prometheus exposition format renderer.
3
+ *
4
+ * Generates text/plain output from ITelemetryStore data.
5
+ * No dependencies — hand-rolled per the exposition format spec:
6
+ * https://prometheus.io/docs/instrumenting/exposition_formats/
7
+ */
8
+ import type { ITelemetryStore } from "./types";
9
+ export declare function renderPrometheusMetrics(store: ITelemetryStore): string;
10
+ //# sourceMappingURL=prometheus.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prometheus.d.ts","sourceRoot":"","sources":["../../src/telemetry/prometheus.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAiB,MAAM,SAAS,CAAA;AAsB7D,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,eAAe,GAAG,MAAM,CA+CtE"}
@@ -1 +1 @@
1
- {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/telemetry/routes.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAS3B,wBAAgB,qBAAqB,+EAwDpC"}
1
+ {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/telemetry/routes.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAQ3B,wBAAgB,qBAAqB,+EAwDpC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * SDK Features settings page — per-adapter toggle UI.
3
+ * Same dark theme as the telemetry dashboard. No framework, no CDN.
4
+ */
5
+ export declare const settingsPageHtml = "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<title>Meridian \u2014 SDK Features</title>\n<link rel=\"icon\" type=\"image/svg+xml\" href=\"/telemetry/icon.svg\">\n<style>\n :root {\n --bg: #0d1117; --surface: #161b22; --border: #30363d;\n --text: #e6edf3; --muted: #8b949e; --accent: #58a6ff;\n --green: #3fb950; --yellow: #d29922; --red: #f85149;\n --purple: #bc8cff;\n }\n * { box-sizing: border-box; margin: 0; padding: 0; }\n body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;\n background: var(--bg); color: var(--text); padding: 0; line-height: 1.5; }\n \n .meridian-profile-bar {\n position: sticky; top: 0; z-index: 100;\n display: none; align-items: center; gap: 12px;\n padding: 8px 24px;\n background: rgba(13, 17, 23, 0.92);\n backdrop-filter: blur(12px);\n border-bottom: 1px solid var(--border, #30363d);\n font-size: 12px;\n color: var(--muted, #8b949e);\n }\n .meridian-profile-bar.visible { display: flex; }\n .meridian-profile-bar .profile-label {\n font-weight: 500; text-transform: uppercase; letter-spacing: 0.5px;\n font-size: 10px; color: var(--muted, #8b949e);\n }\n .meridian-profile-bar select {\n background: var(--surface, #161b22); color: var(--text, #e6edf3);\n border: 1px solid var(--border, #30363d); border-radius: 6px;\n padding: 4px 24px 4px 10px; font-size: 12px; cursor: pointer;\n appearance: none;\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath d='M3 5l3 3 3-3' fill='none' stroke='%238b949e' stroke-width='1.5'/%3E%3C/svg%3E\");\n background-repeat: no-repeat; background-position: right 6px center;\n }\n .meridian-profile-bar select:hover { border-color: var(--accent, #58a6ff); }\n .meridian-profile-bar select:focus { outline: none; border-color: var(--accent, #58a6ff); box-shadow: 0 0 0 1px var(--accent, #58a6ff); }\n .meridian-profile-bar .profile-status {\n font-size: 11px; color: var(--green, #3fb950); opacity: 0;\n transition: opacity 0.3s;\n }\n .meridian-profile-bar .profile-status.show { opacity: 1; }\n .meridian-profile-bar .profile-type {\n font-size: 10px; padding: 2px 8px; border-radius: 4px;\n background: var(--surface, #161b22); border: 1px solid var(--border, #30363d);\n }\n .meridian-profile-bar .spacer { flex: 1; }\n .meridian-profile-bar .profile-nav a {\n color: var(--muted, #8b949e); text-decoration: none; font-size: 11px;\n padding: 4px 8px; border-radius: 4px; transition: color 0.15s;\n }\n .meridian-profile-bar .profile-nav a:hover { color: var(--text, #e6edf3); }\n .meridian-profile-bar .profile-nav a.active { color: var(--accent, #58a6ff); }\n\n .content { max-width: 900px; margin: 0 auto; padding: 24px; }\n h1 { font-size: 20px; font-weight: 600; margin-bottom: 4px; }\n .subtitle { color: var(--muted); font-size: 13px; margin-bottom: 24px; }\n .nav { display: flex; gap: 16px; margin-bottom: 24px; font-size: 13px; }\n .nav a { color: var(--muted); text-decoration: none; }\n .nav a:hover { color: var(--accent); }\n .nav a.active { color: var(--accent); }\n\n .adapter-card {\n background: var(--surface); border: 1px solid var(--border); border-radius: 8px;\n padding: 20px; margin-bottom: 16px;\n }\n .adapter-header {\n display: flex; align-items: center; justify-content: space-between;\n margin-bottom: 16px;\n }\n .adapter-name { font-size: 16px; font-weight: 600; }\n .adapter-badge {\n font-size: 10px; padding: 2px 8px; border-radius: 10px;\n text-transform: uppercase; letter-spacing: 0.5px;\n }\n .badge-active { background: rgba(63, 185, 80, 0.15); color: var(--green); }\n .badge-inactive { background: rgba(139, 148, 158, 0.15); color: var(--muted); }\n\n .feature-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }\n @media (max-width: 600px) { .feature-grid { grid-template-columns: 1fr; } }\n\n .feature-row {\n display: flex; align-items: center; justify-content: space-between;\n padding: 10px 14px; border-radius: 6px;\n background: var(--bg); border: 1px solid var(--border);\n }\n .feature-info { display: flex; flex-direction: column; }\n .feature-label { font-size: 13px; font-weight: 500; }\n .feature-desc { font-size: 11px; color: var(--muted); margin-top: 2px; }\n\n /* Toggle switch */\n .toggle { position: relative; width: 36px; height: 20px; flex-shrink: 0; }\n .toggle input { opacity: 0; width: 0; height: 0; }\n .toggle-track {\n position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0;\n background: var(--border); border-radius: 10px; transition: background 0.2s;\n }\n .toggle-track::after {\n content: \"\"; position: absolute; height: 14px; width: 14px;\n left: 3px; bottom: 3px; background: var(--muted); border-radius: 50%;\n transition: transform 0.2s, background 0.2s;\n }\n .toggle input:checked + .toggle-track { background: var(--accent); }\n .toggle input:checked + .toggle-track::after {\n transform: translateX(16px); background: var(--text);\n }\n\n /* Select dropdown */\n .feature-select {\n background: var(--surface); color: var(--text); border: 1px solid var(--border);\n border-radius: 6px; padding: 4px 8px; font-size: 12px; cursor: pointer;\n }\n\n .save-indicator {\n position: fixed; bottom: 24px; right: 24px;\n background: var(--green); color: #000; padding: 8px 16px;\n border-radius: 6px; font-size: 13px; font-weight: 500;\n opacity: 0; transition: opacity 0.3s; pointer-events: none;\n }\n .save-indicator.visible { opacity: 1; }\n\n .reset-btn {\n background: none; border: 1px solid var(--border); color: var(--muted);\n border-radius: 6px; padding: 4px 12px; font-size: 11px; cursor: pointer;\n }\n .reset-btn:hover { border-color: var(--red); color: var(--red); }\n</style>\n</head>\n<body>\n\n<div class=\"meridian-profile-bar\" id=\"meridianProfileBar\">\n <span class=\"profile-label\">Profile</span>\n <select id=\"meridianProfileSelect\"></select>\n <span class=\"profile-type\" id=\"meridianProfileType\"></span>\n <span class=\"profile-status\" id=\"meridianProfileStatus\">\u2713 Switched</span>\n <div class=\"spacer\"></div>\n <div class=\"profile-nav\">\n <a href=\"/\" id=\"nav-home\">Home</a>\n <a href=\"/settings\" id=\"nav-settings\">Settings</a>\n <a href=\"/profiles\" id=\"nav-profiles\">Profiles</a>\n <a href=\"/telemetry\" id=\"nav-telemetry\">Telemetry</a>\n </div>\n</div>\n\n<div class=\"content\">\n <h1>SDK Features <span style=\"font-size:11px;padding:2px 8px;border-radius:10px;background:rgba(210,153,34,0.15);color:var(--yellow);vertical-align:middle;margin-left:8px\">Experimental</span></h1>\n <p class=\"subtitle\" style=\"max-width:720px;line-height:1.6\">\n Unlock Claude Code features for any connected agent. Capabilities like auto-memory, dreaming, and CLAUDE.md \u2014 normally\n exclusive to Claude Code \u2014 become available to OpenCode, Crush, Droid, and any other harness routed through Meridian.\n Each agent keeps its own toolchain while gaining access to these additional features.<br><br>\n <strong style=\"color:var(--text)\">System prompts:</strong> For these features to work correctly, both the Claude Code prompt and your client prompt\n should be enabled. When both are active, they are appended together \u2014 Claude Code's base instructions come first,\n followed by your agent's specific instructions.\n </p>\n\n <div id=\"adapters\"></div>\n</div>\n\n<div class=\"save-indicator\" id=\"saveIndicator\">Saved</div>\n\n<script>\nconst FEATURES = [\n { key: 'codeSystemPrompt', label: 'Claude Code Prompt', desc: 'Include the built-in Claude Code system prompt (tool usage rules, safety guidelines, coding best practices)', type: 'toggle' },\n { key: 'clientSystemPrompt', label: 'Client Prompt', desc: 'Include the system prompt sent by the connecting agent (e.g. OpenCode or Crush instructions)', type: 'toggle' },\n { key: 'claudeMd', label: 'CLAUDE.md', desc: 'Load CLAUDE.md instruction files \u2014 Off: none, Project: ./CLAUDE.md only, Full: ~/.claude/CLAUDE.md + ./CLAUDE.md', type: 'select', options: ['off', 'project', 'full'] },\n { key: 'memory', label: 'Memory', desc: 'Read and write memories across sessions', type: 'toggle' },\n { key: 'dreaming', label: 'Auto-Dream', desc: 'Background memory consolidation', type: 'toggle' },\n { key: 'thinking', label: 'Thinking', desc: 'Extended thinking mode', type: 'select', options: ['disabled', 'adaptive', 'enabled'] },\n { key: 'thinkingPassthrough', label: 'Thinking Passthrough', desc: 'Forward thinking blocks to the client', type: 'toggle' },\n { key: 'sharedMemory', label: 'Shared Memory', desc: 'Share memory with Claude Code (~/.claude) instead of isolated storage', type: 'toggle' },\n { key: 'maxBudgetUsd', label: 'Max Budget (USD)', desc: 'Per-request cost cap \u2014 query aborts if exceeded (0 = disabled)', type: 'number' },\n { key: 'fallbackModel', label: 'Fallback Model', desc: 'Auto-fallback model if primary fails', type: 'select', options: ['', 'sonnet', 'opus', 'haiku', 'sonnet[1m]', 'opus[1m]'] },\n { key: 'sdkDebug', label: 'SDK Debug Logging', desc: 'Enable verbose SDK debug output to proxy stderr', type: 'toggle' },\n { key: 'additionalDirectories', label: 'Additional Directories', desc: 'Comma-separated extra paths Claude can access (monorepo libs, etc.)', type: 'text' },\n];\n\nconst ADAPTER_LABELS = {\n opencode: 'OpenCode',\n crush: 'Crush',\n forgecode: 'ForgeCode',\n pi: 'Pi',\n droid: 'Droid',\n passthrough: 'LiteLLM / Passthrough',\n};\n\nlet currentConfig = {};\n\nasync function loadConfig() {\n const res = await fetch('/settings/api/features');\n currentConfig = await res.json();\n render();\n}\n\nasync function saveFeature(adapter, key, value) {\n const patch = {};\n patch[key] = value;\n await fetch('/settings/api/features/' + adapter, {\n method: 'PATCH',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(patch),\n });\n currentConfig[adapter][key] = value;\n showSaved();\n}\n\nasync function resetAdapter(adapter) {\n await fetch('/settings/api/features/' + adapter, { method: 'DELETE' });\n await loadConfig();\n showSaved();\n}\n\nfunction showSaved() {\n const el = document.getElementById('saveIndicator');\n el.classList.add('visible');\n setTimeout(() => el.classList.remove('visible'), 1500);\n}\n\nfunction hasAnyEnabled(features) {\n return features.codeSystemPrompt || !features.clientSystemPrompt || features.claudeMd !== 'off' || features.memory || features.dreaming ||\n features.thinking !== 'disabled' || features.thinkingPassthrough ||\n features.sharedMemory || features.maxBudgetUsd > 0 ||\n features.fallbackModel || features.sdkDebug ||\n features.additionalDirectories;\n}\n\nfunction render() {\n const container = document.getElementById('adapters');\n container.innerHTML = '';\n\n for (const [adapter, label] of Object.entries(ADAPTER_LABELS)) {\n const features = currentConfig[adapter] || {};\n const active = hasAnyEnabled(features);\n\n const card = document.createElement('div');\n card.className = 'adapter-card';\n card.innerHTML = '<div class=\"adapter-header\">' +\n '<span class=\"adapter-name\">' + label + '</span>' +\n '<div style=\"display:flex;gap:8px;align-items:center\">' +\n '<span class=\"adapter-badge ' + (active ? 'badge-active' : 'badge-inactive') + '\">' +\n (active ? 'Active' : 'Default') +\n '</span>' +\n '<button class=\"reset-btn\" onclick=\"resetAdapter(\\''+adapter+'\\')\">Reset</button>' +\n '</div>' +\n '</div>';\n\n const grid = document.createElement('div');\n grid.className = 'feature-grid';\n\n for (const feat of FEATURES) {\n const row = document.createElement('div');\n row.className = 'feature-row';\n\n const info = '<div class=\"feature-info\"><span class=\"feature-label\">' +\n feat.label + '</span><span class=\"feature-desc\">' + feat.desc + '</span></div>';\n\n if (feat.type === 'toggle') {\n const checked = features[feat.key] ? 'checked' : '';\n row.innerHTML = info +\n '<label class=\"toggle\"><input type=\"checkbox\" ' + checked +\n ' onchange=\"saveFeature(\\''+adapter+'\\', \\''+feat.key+'\\', this.checked)\">' +\n '<span class=\"toggle-track\"></span></label>';\n } else if (feat.type === 'select') {\n const options = feat.options.map(o => {\n const label = o === '' ? '(None)' : o.charAt(0).toUpperCase()+o.slice(1);\n return '<option value=\"'+o+'\"'+(features[feat.key]===o?' selected':'')+'>'+label+'</option>';\n }).join('');\n row.innerHTML = info +\n '<select class=\"feature-select\" onchange=\"saveFeature(\\''+adapter+'\\', \\''+feat.key+'\\', this.value)\">' +\n options + '</select>';\n } else if (feat.type === 'number') {\n const value = features[feat.key] ?? 0;\n row.innerHTML = info +\n '<input type=\"number\" class=\"feature-select\" style=\"width:80px;text-align:right\" min=\"0\" step=\"0.01\" value=\"'+value+'\"' +\n ' onchange=\"saveFeature(\\''+adapter+'\\', \\''+feat.key+'\\', parseFloat(this.value)||0)\">';\n } else if (feat.type === 'text') {\n const value = (features[feat.key] ?? '').toString().replace(/\"/g, '&quot;');\n row.innerHTML = info +\n '<input type=\"text\" class=\"feature-select\" style=\"width:180px\" value=\"'+value+'\"' +\n ' onchange=\"saveFeature(\\''+adapter+'\\', \\''+feat.key+'\\', this.value)\">';\n }\n\n grid.appendChild(row);\n }\n\n card.appendChild(grid);\n container.appendChild(card);\n }\n}\n\nloadConfig();\n\n(function() {\n var profileBar = document.getElementById('meridianProfileBar');\n var profileSelect = document.getElementById('meridianProfileSelect');\n var profileType = document.getElementById('meridianProfileType');\n var profileStatus = document.getElementById('meridianProfileStatus');\n var statusTimeout;\n\n // Highlight active nav link\n var path = location.pathname;\n var navLinks = document.querySelectorAll('.profile-nav a');\n navLinks.forEach(function(a) {\n if (a.getAttribute('href') === path || (path === '/telemetry' && a.id === 'nav-telemetry') || (path === '/' && a.id === 'nav-home')) {\n a.classList.add('active');\n }\n });\n\n function esc(s) { var d = document.createElement('div'); d.textContent = s; return d.innerHTML; }\n\n function loadProfiles() {\n fetch('/profiles/list').then(function(r) { return r.json(); }).then(function(data) {\n if (!data.profiles || data.profiles.length === 0) {\n profileBar.classList.remove('visible');\n return;\n }\n profileBar.classList.add('visible');\n var current = data.profiles.find(function(p) { return p.isActive; });\n profileSelect.innerHTML = data.profiles.map(function(p) {\n return '<option value=\"' + esc(p.id) + '\"' + (p.isActive ? ' selected' : '') + '>' + esc(p.id) + '</option>';\n }).join('');\n if (current) profileType.textContent = current.type;\n }).catch(function() {});\n }\n\n profileSelect.onchange = function() {\n fetch('/profiles/active', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ profile: profileSelect.value })\n }).then(function(r) { return r.json(); }).then(function(data) {\n if (data.success) {\n profileStatus.classList.add('show');\n clearTimeout(statusTimeout);\n statusTimeout = setTimeout(function() { profileStatus.classList.remove('show'); }, 2000);\n loadProfiles();\n }\n }).catch(function() {});\n };\n\n loadProfiles();\n setInterval(loadProfiles, 10000);\n})();\n\n</script>\n</body>\n</html>";
6
+ //# sourceMappingURL=settingsPage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settingsPage.d.ts","sourceRoot":"","sources":["../../src/telemetry/settingsPage.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,eAAO,MAAM,gBAAgB,6xfAmPrB,CAAA"}
@@ -0,0 +1,7 @@
1
+ import type { ITelemetryStore, IDiagnosticLogStore } from "./types";
2
+ export declare function createSqliteStores(dbPath: string, retentionDays: number): {
3
+ telemetry: ITelemetryStore;
4
+ diagnostics: IDiagnosticLogStore;
5
+ close: () => void;
6
+ };
7
+ //# sourceMappingURL=sqlite.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../../src/telemetry/sqlite.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAmC,eAAe,EAAE,mBAAmB,EAAiB,MAAM,SAAS,CAAA;AAoUnH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM;eAGV,eAAe;iBACxB,mBAAmB;;EAGvE"}
@@ -4,8 +4,8 @@
4
4
  * Append-only, fixed capacity, oldest entries overwritten.
5
5
  * No disk I/O in the hot path. Data resets on proxy restart.
6
6
  */
7
- import type { RequestMetric, TelemetrySummary } from "./types";
8
- export declare class TelemetryStore {
7
+ import type { RequestMetric, TelemetrySummary, ITelemetryStore } from "./types";
8
+ export declare class MemoryTelemetryStore implements ITelemetryStore {
9
9
  private buffer;
10
10
  private head;
11
11
  private count;
@@ -38,5 +38,5 @@ export declare class TelemetryStore {
38
38
  clear(): void;
39
39
  }
40
40
  /** Singleton store instance used by the proxy. */
41
- export declare const telemetryStore: TelemetryStore;
41
+ export declare const telemetryStore: MemoryTelemetryStore;
42
42
  //# sourceMappingURL=store.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/telemetry/store.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAe,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAY3E,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,IAAI,CAAI;IAChB,OAAO,CAAC,KAAK,CAAI;IACjB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAQ;gBAErB,QAAQ,CAAC,EAAE,MAAM;IAK7B,yCAAyC;IACzC,MAAM,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI;IAMnC,8CAA8C;IAC9C,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;;;;OAKG;IACH,SAAS,CAAC,OAAO,GAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,aAAa,EAAE;IAiB5F;kEAC8D;IAC9D,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAWlE;;;OAGG;IACH,SAAS,CAAC,QAAQ,GAAE,MAAuB,GAAG,gBAAgB;IAiH9D,gCAAgC;IAChC,KAAK,IAAI,IAAI;CAKd;AAkBD,kDAAkD;AAClD,eAAO,MAAM,cAAc,gBAAuB,CAAA"}
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/telemetry/store.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAa/E,qBAAa,oBAAqB,YAAW,eAAe;IAC1D,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,IAAI,CAAI;IAChB,OAAO,CAAC,KAAK,CAAI;IACjB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAQ;gBAErB,QAAQ,CAAC,EAAE,MAAM;IAK7B,yCAAyC;IACzC,MAAM,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI;IAMnC,8CAA8C;IAC9C,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;;;;OAKG;IACH,SAAS,CAAC,OAAO,GAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,aAAa,EAAE;IAiB5F;kEAC8D;IAC9D,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAWlE;;;OAGG;IACH,SAAS,CAAC,QAAQ,GAAE,MAAuB,GAAG,gBAAgB;IAM9D,gCAAgC;IAChC,KAAK,IAAI,IAAI;CAKd;AAED,kDAAkD;AAClD,eAAO,MAAM,cAAc,sBAA6B,CAAA"}