crosscheck-mcp 0.2.24 → 0.2.26

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.
@@ -0,0 +1,205 @@
1
+ /** Default model per provider — matches Python's `build_providers()`. */
2
+ declare const DEFAULT_MODELS: Readonly<Record<string, string>>;
3
+ /**
4
+ * Built-in fallbacks for the DEFAULT models, used when a seat hasn't set its
5
+ * own `<PROVIDER>_MODEL_FALLBACKS`.
6
+ *
7
+ * This exists because of a concrete hazard the previous default was written
8
+ * to dodge: a newer model is not enabled on every account or project, so
9
+ * pinning one as the default breaks calls for anyone who lacks access. The
10
+ * old code solved that by defaulting to an older model everyone could reach,
11
+ * which cost everyone else the better one.
12
+ *
13
+ * A chain solves it properly — ask for the current model, and degrade to the
14
+ * broadly-available one ONLY on a model-access failure (never on a bad key, a
15
+ * rate limit, or a 500; see core/model-fallback.ts). Same mechanism the super
16
+ * lineup uses.
17
+ */
18
+ declare const DEFAULT_FALLBACKS: Readonly<Record<string, readonly string[]>>;
19
+ /** Build the active provider registry. Returns a `Record<name, Provider>`
20
+ * with only the providers whose API key is present in `opts.env`.
21
+ *
22
+ * Provider iteration order in the returned dict matches Python: anthropic,
23
+ * openai, xai, mistral, groq, deepseek, gemini. */
24
+ /**
25
+ * Providers kept OUT of the panel even when a key is present.
26
+ *
27
+ * A panel's cost and latency scale with its width, and every seat has to earn
28
+ * its place by contributing a view the others don't. mistral and groq were
29
+ * standing in the panel on the strength of having a key configured, not on
30
+ * the strength of what they added — so they are excluded at the registry,
31
+ * which is the one place every tool, the router and list_providers all read.
32
+ * Excluding here rather than in each tool's own resolveProviders (there are
33
+ * four separate copies) means they cannot reappear through a path someone
34
+ * forgot to update.
35
+ *
36
+ * Reversible without a rebuild:
37
+ * CROSSCHECK_ENABLE_PROVIDERS=mistral,groq puts them back
38
+ * CROSSCHECK_EXCLUDE_PROVIDERS=kimi,qwen excludes others
39
+ */
40
+ declare const DEFAULT_EXCLUDED_PROVIDERS: readonly string[];
41
+
42
+ /**
43
+ * Embedded host entrypoint — the API Crosscheck Desktop runs panels through.
44
+ *
45
+ * WHY NOT JUST SPEAK MCP OVER STDIO?
46
+ * ----------------------------------
47
+ * Because MCP's `tools/call` is request/response: one JSON envelope at the
48
+ * end. A `confer super` panel runs for minutes. A desktop app that shows a
49
+ * spinner for three minutes and then dumps five answers at once is not a
50
+ * working screen, it's a progress bar with extra steps.
51
+ *
52
+ * `runConfer` and `runDebate` already accept per-panelist hooks (added for
53
+ * the browser extension). This entrypoint turns those hooks into ONE typed,
54
+ * JSON-serializable event stream that survives an Electron IPC boundary, so
55
+ * the host can render the panel as it happens.
56
+ *
57
+ * WHAT THIS IS NOT
58
+ * ----------------
59
+ * Not token-level streaming. `Provider.send()` returns finished text — no
60
+ * adapter in this engine speaks SSE today. These events are panel LIFECYCLE:
61
+ * dispatched → resolved, with usage and cost attached. That is the honest
62
+ * granularity, and a host that renders it as "per-provider status + elapsed"
63
+ * is telling the truth. A host that renders a fake typewriter off these
64
+ * events is lying to its user.
65
+ *
66
+ * THE ENV RULE
67
+ * ------------
68
+ * Provider keys go into a PRIVATE env object that is handed to
69
+ * `buildProviders` and then dropped. They are never written to `process.env`.
70
+ * That is not tidiness — the desktop app spawns a terminal, and a child shell
71
+ * inherits `process.env`. Keeping keys out of it is what stops a user's own
72
+ * `env | grep KEY` from printing their Anthropic key inside our app.
73
+ */
74
+ /**
75
+ * Vault provider id → engine env var.
76
+ *
77
+ * The two sides disagree on one name and always have: the vault (and the
78
+ * user) call it `grok`, the engine registry calls it `xai`. That split is
79
+ * load-bearing in both repos, so this table is the single place it is
80
+ * reconciled — mirroring `KEY_BINDINGS` in crosscheck-cli's mcp.ts. If you
81
+ * add a provider, it goes in both.
82
+ */
83
+ declare const KEY_ENV: Readonly<Record<string, string>>;
84
+ /** Vault provider id → engine model-pin env var. Same split, same reason. */
85
+ declare const MODEL_ENV: Readonly<Record<string, string>>;
86
+ declare function vaultId(engineName: string): string;
87
+ /** Usage as a host should render it. Cost is what the engine computed from
88
+ * pricing.json; `null` means we could not price the call, which a UI must
89
+ * show as "unavailable" rather than as $0.00. */
90
+ interface EventUsage {
91
+ promptTokens: number;
92
+ completionTokens: number;
93
+ totalTokens: number;
94
+ costUsd: number | null;
95
+ }
96
+ type EngineEvent =
97
+ /** The panel has been selected and dispatch is about to begin. Carries the
98
+ * full roster so a host can paint every provider's column up front. */
99
+ {
100
+ type: "run.start";
101
+ runId: string;
102
+ tool: string;
103
+ at: number;
104
+ panel: Array<{
105
+ provider: string;
106
+ model: string;
107
+ }>;
108
+ }
109
+ /** One panelist's request just went out. `round` is present for debate. */
110
+ | {
111
+ type: "panelist.start";
112
+ runId: string;
113
+ at: number;
114
+ provider: string;
115
+ model: string;
116
+ round?: number;
117
+ }
118
+ /** One panelist resolved. `ok: false` means that provider failed and the
119
+ * others carried on — never a reason to fail the run. */
120
+ | {
121
+ type: "panelist.done";
122
+ runId: string;
123
+ at: number;
124
+ provider: string;
125
+ model: string;
126
+ round?: number;
127
+ ok: boolean;
128
+ text: string;
129
+ error: string | null;
130
+ usage: EventUsage | null;
131
+ }
132
+ /** The moderator's synthesis landed (debate only). */
133
+ | {
134
+ type: "synthesis.done";
135
+ runId: string;
136
+ at: number;
137
+ text: string;
138
+ usage: EventUsage | null;
139
+ }
140
+ /** The run finished. `envelope` is byte-identical to what `call()` returns. */
141
+ | {
142
+ type: "run.done";
143
+ runId: string;
144
+ at: number;
145
+ durationMs: number;
146
+ envelope: unknown;
147
+ }
148
+ /** The run itself failed — not a panelist. Rare: a config or budget gate. */
149
+ | {
150
+ type: "run.error";
151
+ runId: string;
152
+ at: number;
153
+ message: string;
154
+ };
155
+ type EngineEventSink = (event: EngineEvent) => void;
156
+ interface EmbeddedEngineOptions {
157
+ /** Vault provider id → raw API key. Only providers present here are built.
158
+ * Held in a private env object; never written to `process.env`. */
159
+ keys: Readonly<Record<string, string>>;
160
+ /** Vault provider id → pinned model. Omit a provider to take the engine
161
+ * default. Mirrors what `/account/models` and `crosscheck models set` do. */
162
+ models?: Readonly<Record<string, string>>;
163
+ /** Default moderator/synthesis provider. */
164
+ moderator?: string;
165
+ /** Explicit pricing.json path. Defaults to the copy bundled in `dist/`. */
166
+ pricingPath?: string;
167
+ /** Directory to archive run transcripts into. Omit to write none. */
168
+ transcriptsDir?: string;
169
+ }
170
+ interface EmbeddedEngine {
171
+ readonly version: string;
172
+ /** Providers actually built, by vault id — i.e. the ones with a usable key
173
+ * that are not excluded from the panel. Sorted. */
174
+ readonly providers: readonly string[];
175
+ /** Effective model per built provider, by vault id. */
176
+ readonly models: Readonly<Record<string, string>>;
177
+ /** Every registered tool name. */
178
+ listTools(): string[];
179
+ /** Invoke any tool and wait for the final envelope. No events. */
180
+ call(name: string, args: Record<string, unknown>): Promise<unknown>;
181
+ /** Invoke a tool, emitting lifecycle events as the panel progresses.
182
+ * `confer` and `debate` stream; every other tool emits `run.start` and
183
+ * `run.done` around a plain `call`, so a host can use one code path. */
184
+ run(name: string, args: Record<string, unknown>, onEvent: EngineEventSink): Promise<unknown>;
185
+ /** Flush queued telemetry. Call before the host process exits. */
186
+ close(): Promise<void>;
187
+ }
188
+ /** Pull the host-facing usage numbers out of an askOne envelope. Returns null
189
+ * when the provider reported nothing — which a UI must render as unknown,
190
+ * not as zero. */
191
+ declare function usageOf(answer: Record<string, unknown>): EventUsage | null;
192
+ declare function textOf(answer: Record<string, unknown>): string;
193
+ declare function errorOf(answer: Record<string, unknown>): string | null;
194
+ declare function createEmbeddedEngine(opts: EmbeddedEngineOptions): EmbeddedEngine;
195
+
196
+ /** Test seam. `usageOf` encodes the "unknown is not zero" rule that the cost
197
+ * column depends on, and it is not otherwise reachable without live keys. */
198
+ declare const __test_internals: {
199
+ usageOf: typeof usageOf;
200
+ textOf: typeof textOf;
201
+ errorOf: typeof errorOf;
202
+ vaultId: typeof vaultId;
203
+ };
204
+
205
+ export { DEFAULT_EXCLUDED_PROVIDERS, DEFAULT_FALLBACKS, DEFAULT_MODELS, type EmbeddedEngine, type EmbeddedEngineOptions, type EngineEvent, type EngineEventSink, type EventUsage, KEY_ENV as __KEY_ENV, MODEL_ENV as __MODEL_ENV, __test_internals, createEmbeddedEngine };
@@ -0,0 +1,205 @@
1
+ /** Default model per provider — matches Python's `build_providers()`. */
2
+ declare const DEFAULT_MODELS: Readonly<Record<string, string>>;
3
+ /**
4
+ * Built-in fallbacks for the DEFAULT models, used when a seat hasn't set its
5
+ * own `<PROVIDER>_MODEL_FALLBACKS`.
6
+ *
7
+ * This exists because of a concrete hazard the previous default was written
8
+ * to dodge: a newer model is not enabled on every account or project, so
9
+ * pinning one as the default breaks calls for anyone who lacks access. The
10
+ * old code solved that by defaulting to an older model everyone could reach,
11
+ * which cost everyone else the better one.
12
+ *
13
+ * A chain solves it properly — ask for the current model, and degrade to the
14
+ * broadly-available one ONLY on a model-access failure (never on a bad key, a
15
+ * rate limit, or a 500; see core/model-fallback.ts). Same mechanism the super
16
+ * lineup uses.
17
+ */
18
+ declare const DEFAULT_FALLBACKS: Readonly<Record<string, readonly string[]>>;
19
+ /** Build the active provider registry. Returns a `Record<name, Provider>`
20
+ * with only the providers whose API key is present in `opts.env`.
21
+ *
22
+ * Provider iteration order in the returned dict matches Python: anthropic,
23
+ * openai, xai, mistral, groq, deepseek, gemini. */
24
+ /**
25
+ * Providers kept OUT of the panel even when a key is present.
26
+ *
27
+ * A panel's cost and latency scale with its width, and every seat has to earn
28
+ * its place by contributing a view the others don't. mistral and groq were
29
+ * standing in the panel on the strength of having a key configured, not on
30
+ * the strength of what they added — so they are excluded at the registry,
31
+ * which is the one place every tool, the router and list_providers all read.
32
+ * Excluding here rather than in each tool's own resolveProviders (there are
33
+ * four separate copies) means they cannot reappear through a path someone
34
+ * forgot to update.
35
+ *
36
+ * Reversible without a rebuild:
37
+ * CROSSCHECK_ENABLE_PROVIDERS=mistral,groq puts them back
38
+ * CROSSCHECK_EXCLUDE_PROVIDERS=kimi,qwen excludes others
39
+ */
40
+ declare const DEFAULT_EXCLUDED_PROVIDERS: readonly string[];
41
+
42
+ /**
43
+ * Embedded host entrypoint — the API Crosscheck Desktop runs panels through.
44
+ *
45
+ * WHY NOT JUST SPEAK MCP OVER STDIO?
46
+ * ----------------------------------
47
+ * Because MCP's `tools/call` is request/response: one JSON envelope at the
48
+ * end. A `confer super` panel runs for minutes. A desktop app that shows a
49
+ * spinner for three minutes and then dumps five answers at once is not a
50
+ * working screen, it's a progress bar with extra steps.
51
+ *
52
+ * `runConfer` and `runDebate` already accept per-panelist hooks (added for
53
+ * the browser extension). This entrypoint turns those hooks into ONE typed,
54
+ * JSON-serializable event stream that survives an Electron IPC boundary, so
55
+ * the host can render the panel as it happens.
56
+ *
57
+ * WHAT THIS IS NOT
58
+ * ----------------
59
+ * Not token-level streaming. `Provider.send()` returns finished text — no
60
+ * adapter in this engine speaks SSE today. These events are panel LIFECYCLE:
61
+ * dispatched → resolved, with usage and cost attached. That is the honest
62
+ * granularity, and a host that renders it as "per-provider status + elapsed"
63
+ * is telling the truth. A host that renders a fake typewriter off these
64
+ * events is lying to its user.
65
+ *
66
+ * THE ENV RULE
67
+ * ------------
68
+ * Provider keys go into a PRIVATE env object that is handed to
69
+ * `buildProviders` and then dropped. They are never written to `process.env`.
70
+ * That is not tidiness — the desktop app spawns a terminal, and a child shell
71
+ * inherits `process.env`. Keeping keys out of it is what stops a user's own
72
+ * `env | grep KEY` from printing their Anthropic key inside our app.
73
+ */
74
+ /**
75
+ * Vault provider id → engine env var.
76
+ *
77
+ * The two sides disagree on one name and always have: the vault (and the
78
+ * user) call it `grok`, the engine registry calls it `xai`. That split is
79
+ * load-bearing in both repos, so this table is the single place it is
80
+ * reconciled — mirroring `KEY_BINDINGS` in crosscheck-cli's mcp.ts. If you
81
+ * add a provider, it goes in both.
82
+ */
83
+ declare const KEY_ENV: Readonly<Record<string, string>>;
84
+ /** Vault provider id → engine model-pin env var. Same split, same reason. */
85
+ declare const MODEL_ENV: Readonly<Record<string, string>>;
86
+ declare function vaultId(engineName: string): string;
87
+ /** Usage as a host should render it. Cost is what the engine computed from
88
+ * pricing.json; `null` means we could not price the call, which a UI must
89
+ * show as "unavailable" rather than as $0.00. */
90
+ interface EventUsage {
91
+ promptTokens: number;
92
+ completionTokens: number;
93
+ totalTokens: number;
94
+ costUsd: number | null;
95
+ }
96
+ type EngineEvent =
97
+ /** The panel has been selected and dispatch is about to begin. Carries the
98
+ * full roster so a host can paint every provider's column up front. */
99
+ {
100
+ type: "run.start";
101
+ runId: string;
102
+ tool: string;
103
+ at: number;
104
+ panel: Array<{
105
+ provider: string;
106
+ model: string;
107
+ }>;
108
+ }
109
+ /** One panelist's request just went out. `round` is present for debate. */
110
+ | {
111
+ type: "panelist.start";
112
+ runId: string;
113
+ at: number;
114
+ provider: string;
115
+ model: string;
116
+ round?: number;
117
+ }
118
+ /** One panelist resolved. `ok: false` means that provider failed and the
119
+ * others carried on — never a reason to fail the run. */
120
+ | {
121
+ type: "panelist.done";
122
+ runId: string;
123
+ at: number;
124
+ provider: string;
125
+ model: string;
126
+ round?: number;
127
+ ok: boolean;
128
+ text: string;
129
+ error: string | null;
130
+ usage: EventUsage | null;
131
+ }
132
+ /** The moderator's synthesis landed (debate only). */
133
+ | {
134
+ type: "synthesis.done";
135
+ runId: string;
136
+ at: number;
137
+ text: string;
138
+ usage: EventUsage | null;
139
+ }
140
+ /** The run finished. `envelope` is byte-identical to what `call()` returns. */
141
+ | {
142
+ type: "run.done";
143
+ runId: string;
144
+ at: number;
145
+ durationMs: number;
146
+ envelope: unknown;
147
+ }
148
+ /** The run itself failed — not a panelist. Rare: a config or budget gate. */
149
+ | {
150
+ type: "run.error";
151
+ runId: string;
152
+ at: number;
153
+ message: string;
154
+ };
155
+ type EngineEventSink = (event: EngineEvent) => void;
156
+ interface EmbeddedEngineOptions {
157
+ /** Vault provider id → raw API key. Only providers present here are built.
158
+ * Held in a private env object; never written to `process.env`. */
159
+ keys: Readonly<Record<string, string>>;
160
+ /** Vault provider id → pinned model. Omit a provider to take the engine
161
+ * default. Mirrors what `/account/models` and `crosscheck models set` do. */
162
+ models?: Readonly<Record<string, string>>;
163
+ /** Default moderator/synthesis provider. */
164
+ moderator?: string;
165
+ /** Explicit pricing.json path. Defaults to the copy bundled in `dist/`. */
166
+ pricingPath?: string;
167
+ /** Directory to archive run transcripts into. Omit to write none. */
168
+ transcriptsDir?: string;
169
+ }
170
+ interface EmbeddedEngine {
171
+ readonly version: string;
172
+ /** Providers actually built, by vault id — i.e. the ones with a usable key
173
+ * that are not excluded from the panel. Sorted. */
174
+ readonly providers: readonly string[];
175
+ /** Effective model per built provider, by vault id. */
176
+ readonly models: Readonly<Record<string, string>>;
177
+ /** Every registered tool name. */
178
+ listTools(): string[];
179
+ /** Invoke any tool and wait for the final envelope. No events. */
180
+ call(name: string, args: Record<string, unknown>): Promise<unknown>;
181
+ /** Invoke a tool, emitting lifecycle events as the panel progresses.
182
+ * `confer` and `debate` stream; every other tool emits `run.start` and
183
+ * `run.done` around a plain `call`, so a host can use one code path. */
184
+ run(name: string, args: Record<string, unknown>, onEvent: EngineEventSink): Promise<unknown>;
185
+ /** Flush queued telemetry. Call before the host process exits. */
186
+ close(): Promise<void>;
187
+ }
188
+ /** Pull the host-facing usage numbers out of an askOne envelope. Returns null
189
+ * when the provider reported nothing — which a UI must render as unknown,
190
+ * not as zero. */
191
+ declare function usageOf(answer: Record<string, unknown>): EventUsage | null;
192
+ declare function textOf(answer: Record<string, unknown>): string;
193
+ declare function errorOf(answer: Record<string, unknown>): string | null;
194
+ declare function createEmbeddedEngine(opts: EmbeddedEngineOptions): EmbeddedEngine;
195
+
196
+ /** Test seam. `usageOf` encodes the "unknown is not zero" rule that the cost
197
+ * column depends on, and it is not otherwise reachable without live keys. */
198
+ declare const __test_internals: {
199
+ usageOf: typeof usageOf;
200
+ textOf: typeof textOf;
201
+ errorOf: typeof errorOf;
202
+ vaultId: typeof vaultId;
203
+ };
204
+
205
+ export { DEFAULT_EXCLUDED_PROVIDERS, DEFAULT_FALLBACKS, DEFAULT_MODELS, type EmbeddedEngine, type EmbeddedEngineOptions, type EngineEvent, type EngineEventSink, type EventUsage, KEY_ENV as __KEY_ENV, MODEL_ENV as __MODEL_ENV, __test_internals, createEmbeddedEngine };