@vanillagreen/pi-claude-bridge 1.9.0 → 3.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +43 -125
- package/bundle/connector-inventory.js +16 -3
- package/bundle/index.js +3743 -1810
- package/package.json +14 -23
- package/src/account-host.ts +112 -0
- package/src/account-router.ts +272 -0
- package/src/agents-md.ts +54 -10
- package/src/assistant-stream.ts +472 -66
- package/src/auth-presence.ts +6 -50
- package/src/bridge-commands.ts +86 -0
- package/src/bridge-state.ts +200 -15
- package/src/config.ts +170 -20
- package/src/connector-audit.ts +203 -0
- package/src/connector-cache.ts +148 -0
- package/src/connector-inventory.ts +66 -7
- package/src/connector-runtime.ts +158 -0
- package/src/connectors.ts +406 -19
- package/src/consume-query.ts +312 -0
- package/src/convert.ts +20 -10
- package/src/debug.ts +64 -6
- package/src/index.ts +901 -676
- package/src/models.ts +0 -7
- package/src/native-provider.ts +94 -0
- package/src/prompt-context.ts +5 -1
- package/src/query-options.ts +183 -0
- package/src/query-state.ts +490 -25
- package/src/query-teardown.ts +45 -0
- package/src/rate-limit.ts +48 -13
- package/src/request-lane.ts +36 -0
- package/src/sdk-query.ts +16 -0
- package/src/session-persistence.ts +370 -50
- package/src/tool-pairing-audit.ts +117 -0
- package/src/typebox-to-zod.ts +9 -3
package/src/models.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
// Canonical selection + display order for the model picker.
|
|
2
|
-
// `resolveModelId` returns the first partial match, so `opus` resolves to the first-listed opus entry.
|
|
3
2
|
// Extracted from index.ts so tests can import without activating the extension.
|
|
4
3
|
|
|
5
4
|
export const FABLE_MODEL_ID = "claude-fable-5";
|
|
@@ -94,9 +93,3 @@ export function buildModels<T extends { id: string; [key: string]: any }>(piAiMo
|
|
|
94
93
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
95
94
|
}));
|
|
96
95
|
}
|
|
97
|
-
|
|
98
|
-
export function resolveModelId(models: Array<{ id: string }>, input: string): string {
|
|
99
|
-
const lower = input.toLowerCase();
|
|
100
|
-
const match = models.find((m) => m.id === lower || m.id.includes(lower));
|
|
101
|
-
return match ? match.id : input;
|
|
102
|
-
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
// Native pi >=0.81 provider construction (bridge 2.x).
|
|
2
|
+
//
|
|
3
|
+
// Bridge 1.x could not register unconditionally: pi's legacy
|
|
4
|
+
// ModelRegistry.hasConfiguredAuth() treated the dummy `apiKey: "not-used"` as
|
|
5
|
+
// "configured", so the models looked connected while every request failed at
|
|
6
|
+
// spawn. 1.x therefore gated register/unregister on real credential presence
|
|
7
|
+
// (decideRegistration). The native Provider form inverts that: the provider is
|
|
8
|
+
// ALWAYS registered, and `auth.apiKey.check/resolve` report configured-ness
|
|
9
|
+
// from the same existence-only probes, so pi itself hides claude-bridge models
|
|
10
|
+
// while no Claude credentials are present and shows them when they appear.
|
|
11
|
+
//
|
|
12
|
+
// What the native form does NOT change (see DEVELOPMENT.md "Provider
|
|
13
|
+
// registration"): the process-global primary-instance/stream-guard tokens stay
|
|
14
|
+
// (pi's registerNativeProvider is replace-by-id, so an unguarded subagent
|
|
15
|
+
// re-registration would still swap in its own streamSimple), and the pre-spawn
|
|
16
|
+
// credential fail-fast in streamSimple stays (a mid-session logout must fail
|
|
17
|
+
// the turn with an actionable message even if the picker snapshot is stale).
|
|
18
|
+
//
|
|
19
|
+
// SECURITY: like auth-presence.ts, this module only reports credential
|
|
20
|
+
// EXISTENCE. resolve() hands pi the same dummy key the legacy config carried —
|
|
21
|
+
// the Claude Code subprocess does its own authentication; pi never needs a
|
|
22
|
+
// real secret, so none is read or exposed.
|
|
23
|
+
|
|
24
|
+
import { hasClaudeCredentials } from "./auth-presence.js";
|
|
25
|
+
import { PROVIDER_ID } from "./convert.js";
|
|
26
|
+
|
|
27
|
+
export const NATIVE_PROVIDER_UNSUPPORTED_MESSAGE =
|
|
28
|
+
"Claude bridge 2.x requires pi >= 0.81 (native provider API). Upgrade the host pi, or pin @vanillagreen/pi-claude-bridge@1.x.";
|
|
29
|
+
|
|
30
|
+
/** pi-ai gained createProvider in 0.81 alongside the object-form
|
|
31
|
+
* registerProvider; its presence is the capability signal for both. */
|
|
32
|
+
export function supportsNativeProvider(piAi: unknown): boolean {
|
|
33
|
+
return typeof (piAi as { createProvider?: unknown })?.createProvider === "function";
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Auth source label for pi's status UI, chosen by the same existence-only
|
|
37
|
+
* probes hasClaudeCredentials uses. Never reads credential contents. */
|
|
38
|
+
export function claudeAuthSourceLabel(env: NodeJS.ProcessEnv = process.env): string {
|
|
39
|
+
if (env.CLAUDE_CODE_OAUTH_TOKEN?.trim()) return "CLAUDE_CODE_OAUTH_TOKEN";
|
|
40
|
+
if (env.ANTHROPIC_API_KEY?.trim()) return "ANTHROPIC_API_KEY";
|
|
41
|
+
if (env.ANTHROPIC_AUTH_TOKEN?.trim()) return "ANTHROPIC_AUTH_TOKEN";
|
|
42
|
+
return "Claude Code login";
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Build the Provider object for pi.registerProvider(provider).
|
|
47
|
+
*
|
|
48
|
+
* `piAi` is the HOST's pi-ai namespace (the bundle externalizes it), passed in
|
|
49
|
+
* rather than imported so a pre-0.81 host fails the supportsNativeProvider()
|
|
50
|
+
* check with a clear message instead of crashing module load on a missing
|
|
51
|
+
* named export. `env` is bindable for tests; the credential probes themselves
|
|
52
|
+
* run at check/resolve CALL time, so a login/logout between calls is seen.
|
|
53
|
+
*/
|
|
54
|
+
export function buildNativeProvider(
|
|
55
|
+
piAi: unknown,
|
|
56
|
+
models: Array<Record<string, unknown>>,
|
|
57
|
+
streamSimple: (...args: unknown[]) => unknown,
|
|
58
|
+
env: NodeJS.ProcessEnv = process.env,
|
|
59
|
+
// Availability probe. Defaults to direct credential presence; the extension
|
|
60
|
+
// passes a probe that also accepts a companion account-router pool.
|
|
61
|
+
hasCredentials: () => boolean = () => hasClaudeCredentials(env),
|
|
62
|
+
): unknown {
|
|
63
|
+
if (!supportsNativeProvider(piAi)) throw new Error(NATIVE_PROVIDER_UNSUPPORTED_MESSAGE);
|
|
64
|
+
// The legacy config path stamped provider/api/baseUrl onto each model during
|
|
65
|
+
// composition; createProvider passes models through verbatim, so stamp here.
|
|
66
|
+
// Stamps win over any provider field the source model carries — the models
|
|
67
|
+
// come from pi-ai's anthropic registry and must be re-homed under pi-claude.
|
|
68
|
+
const stamped = models.map((model) => ({ ...model, api: "claude-bridge", baseUrl: "claude-bridge", provider: PROVIDER_ID }));
|
|
69
|
+
// The Claude Code subprocess router IS the implementation for both stream
|
|
70
|
+
// entry points — there is no raw-API shape to dispatch to.
|
|
71
|
+
const streams = {
|
|
72
|
+
stream: streamSimple,
|
|
73
|
+
streamSimple,
|
|
74
|
+
};
|
|
75
|
+
return (piAi as { createProvider: (input: unknown) => unknown }).createProvider({
|
|
76
|
+
id: PROVIDER_ID,
|
|
77
|
+
name: "Pi Claude",
|
|
78
|
+
baseUrl: "claude-bridge",
|
|
79
|
+
auth: {
|
|
80
|
+
apiKey: {
|
|
81
|
+
name: "Claude Code credentials",
|
|
82
|
+
// check() exists so pi's availability pass never has to call
|
|
83
|
+
// resolve(): both are existence-only, but check is the documented
|
|
84
|
+
// side-effect-free probe.
|
|
85
|
+
check: async () => (hasCredentials() ? { type: "api_key" as const, source: claudeAuthSourceLabel(env) } : undefined),
|
|
86
|
+
resolve: async () => (hasCredentials()
|
|
87
|
+
? { auth: { apiKey: "not-used" }, source: claudeAuthSourceLabel(env) }
|
|
88
|
+
: undefined),
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
models: stamped,
|
|
92
|
+
api: streams,
|
|
93
|
+
});
|
|
94
|
+
}
|
package/src/prompt-context.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from "fs";
|
|
2
2
|
import { dirname, join, resolve } from "path";
|
|
3
3
|
import { isolatedFromEnv, piUserDir } from "./config.js";
|
|
4
|
+
import { debug } from "./debug.js";
|
|
4
5
|
|
|
5
6
|
export interface PromptContextSettings {
|
|
6
7
|
includeAppendSystemPromptMd?: boolean;
|
|
@@ -19,7 +20,10 @@ function readTrimmed(path: string): string | undefined {
|
|
|
19
20
|
if (!existsSync(path)) return undefined;
|
|
20
21
|
const content = readFileSync(path, "utf8").trim();
|
|
21
22
|
return content.length > 0 ? content : undefined;
|
|
22
|
-
} catch {
|
|
23
|
+
} catch (error) {
|
|
24
|
+
// The file exists but could not be read: the user opted into forwarding
|
|
25
|
+
// it, so a silent drop looks like the setting being ignored.
|
|
26
|
+
debug(`prompt-context: failed to read ${path}:`, error instanceof Error ? error.message : String(error));
|
|
23
27
|
return undefined;
|
|
24
28
|
}
|
|
25
29
|
}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
// Pure assembly of the Claude Agent SDK query options for one bridge query.
|
|
2
|
+
// Extracted from index.ts (pure move): no closures — reads config, env, and
|
|
3
|
+
// the provided context only.
|
|
4
|
+
|
|
5
|
+
import { type Model } from "@earendil-works/pi-ai";
|
|
6
|
+
import { createSdkMcpServer, type query, type EffortLevel, type SettingSource } from "@anthropic-ai/claude-agent-sdk";
|
|
7
|
+
import { accountSessionScope, subscriberProfileEnv, type ClaudeAccountRoute } from "./account-router.js";
|
|
8
|
+
import { extractAgentsAppend } from "./agents-md.js";
|
|
9
|
+
import { spawnClaudeCodeWithDiagnostics } from "./claude-executable.js";
|
|
10
|
+
import { normalizeEffortLevel, type Config } from "./config.js";
|
|
11
|
+
import { connectorQueryOptions, connectorWriteModeFor, connectorsEnabledFor, settingSourcesForQuery } from "./connectors.js";
|
|
12
|
+
import { connectorServersSnapshot } from "./connector-runtime.js";
|
|
13
|
+
import { PROVIDER_ID } from "./convert.js";
|
|
14
|
+
import { makeCliDebugOptions } from "./debug.js";
|
|
15
|
+
import { FABLE_MODEL_ID, fallbackModelForPrimaryModel } from "./models.js";
|
|
16
|
+
import { buildPromptContextAppend } from "./prompt-context.js";
|
|
17
|
+
import { extractSkillsBlock } from "./skills.js";
|
|
18
|
+
|
|
19
|
+
// --- Effort level mapping ---
|
|
20
|
+
// Pi reasoning levels → CC SDK effort levels
|
|
21
|
+
|
|
22
|
+
const REASONING_TO_EFFORT: Record<string, EffortLevel> = {
|
|
23
|
+
minimal: "low", low: "low", medium: "medium", high: "high", xhigh: "max", max: "max",
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
function normalizeEffortOverrideModelKey(value: string): string {
|
|
27
|
+
const key = value.trim().toLowerCase();
|
|
28
|
+
return key.startsWith(`${PROVIDER_ID}/`) ? key.slice(PROVIDER_ID.length + 1) : key;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function resolveConfiguredEffort(
|
|
32
|
+
modelId: string,
|
|
33
|
+
reasoningEffort: EffortLevel | undefined,
|
|
34
|
+
providerConfig?: Config["provider"],
|
|
35
|
+
): EffortLevel | undefined {
|
|
36
|
+
const target = normalizeEffortOverrideModelKey(modelId);
|
|
37
|
+
for (const [key, rawEffort] of Object.entries(providerConfig?.modelEffortOverrides ?? {})) {
|
|
38
|
+
const normalizedKey = normalizeEffortOverrideModelKey(key);
|
|
39
|
+
if (normalizedKey !== "*" && normalizedKey !== target) continue;
|
|
40
|
+
const effort = normalizeEffortLevel(rawEffort) as EffortLevel | undefined;
|
|
41
|
+
if (effort) return effort;
|
|
42
|
+
}
|
|
43
|
+
return (normalizeEffortLevel(providerConfig?.forceEffort) as EffortLevel | undefined) ?? reasoningEffort;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface BuildClaudeQueryOptionsInput {
|
|
47
|
+
cwd: string;
|
|
48
|
+
/** The model Pi requested. */
|
|
49
|
+
requestedModel: Model<any>;
|
|
50
|
+
/** The model this attempt actually runs (router may substitute). */
|
|
51
|
+
queryModel: Model<any>;
|
|
52
|
+
account?: ClaudeAccountRoute;
|
|
53
|
+
bridgeConfig: Config;
|
|
54
|
+
systemPrompt?: string;
|
|
55
|
+
/** Pi reasoning level from the stream options, if any. */
|
|
56
|
+
reasoning?: string;
|
|
57
|
+
resumeSessionId: string | null;
|
|
58
|
+
mcpServers?: Record<string, ReturnType<typeof createSdkMcpServer>>;
|
|
59
|
+
claudeExecutable?: string;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface BuiltClaudeQueryOptions {
|
|
63
|
+
queryOptions: NonNullable<Parameters<typeof query>[0]["options"]>;
|
|
64
|
+
// Diagnostics-ish bits the caller's debug line reports.
|
|
65
|
+
enableCloudMcp: boolean;
|
|
66
|
+
appendSystemPrompt: boolean;
|
|
67
|
+
promptContextLabels: string[];
|
|
68
|
+
strictMcpConfigEnabled: boolean;
|
|
69
|
+
effort?: EffortLevel;
|
|
70
|
+
fallbackModel?: string;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function buildClaudeQueryOptions(input: BuildClaudeQueryOptionsInput): BuiltClaudeQueryOptions {
|
|
74
|
+
const { cwd, requestedModel, queryModel, account, bridgeConfig, systemPrompt, reasoning, resumeSessionId, mcpServers, claudeExecutable } = input;
|
|
75
|
+
const providerSettings = bridgeConfig.provider ?? {};
|
|
76
|
+
const accountScope = accountSessionScope(account);
|
|
77
|
+
// Whether to expose the Claude account's claude.ai cloud MCP connectors
|
|
78
|
+
// (Gmail/Calendar/Drive). Enabled via env or config; drives setting-sources,
|
|
79
|
+
// tool isolation, and the ENABLE_CLAUDEAI_MCP_SERVERS child-env gate below.
|
|
80
|
+
const enableCloudMcp = connectorsEnabledFor(bridgeConfig);
|
|
81
|
+
// Connector WRITE control: read-only by default (writes denied); the one-shot
|
|
82
|
+
// approved-write executor sets CLAUDE_BRIDGE_CONNECTOR_WRITE=allow / config.
|
|
83
|
+
const connectorWriteMode = connectorWriteModeFor(bridgeConfig);
|
|
84
|
+
// Declare the account's connected connectors explicitly so `alwaysLoad` can
|
|
85
|
+
// hold startup until they attach — otherwise the turn-1 manifest is built
|
|
86
|
+
// before the CLI has fetched them (vstack#832).
|
|
87
|
+
const connectorServers = enableCloudMcp ? connectorServersSnapshot(accountScope.claudeConfigDir) : {};
|
|
88
|
+
const appendSystemPrompt = providerSettings.appendSystemPrompt !== false;
|
|
89
|
+
const agentsAppend = appendSystemPrompt ? extractAgentsAppend() : undefined;
|
|
90
|
+
const skillsAppend = appendSystemPrompt ? extractSkillsBlock(systemPrompt) : undefined;
|
|
91
|
+
const promptContextAppend = buildPromptContextAppend(systemPrompt, cwd, bridgeConfig.promptContext ?? {});
|
|
92
|
+
const appendParts = [agentsAppend, skillsAppend, promptContextAppend.text].filter((part): part is string => Boolean(part));
|
|
93
|
+
const systemPromptAppend = appendParts.length > 0 ? appendParts.join("\n\n") : undefined;
|
|
94
|
+
|
|
95
|
+
// MCP auto-loading suppression: with appendSystemPrompt=true (default), the
|
|
96
|
+
// SDK uses isolation mode and avoids filesystem settings. If users turn that
|
|
97
|
+
// off, load user/project settings but pass --strict-mcp-config so Claude Code
|
|
98
|
+
// ignores auto-discovered filesystem MCP servers while Pi owns tool execution.
|
|
99
|
+
// Connectors mode needs settings resolution ON but restricted to USER scope
|
|
100
|
+
// only — project/local settings files can smuggle `env`/`apiKeyHelper` from
|
|
101
|
+
// a hostile checkout (vstack#990). Full rationale on settingSourcesForQuery.
|
|
102
|
+
const settingSources: SettingSource[] | undefined = settingSourcesForQuery(
|
|
103
|
+
enableCloudMcp, appendSystemPrompt, providerSettings.settingSources);
|
|
104
|
+
const strictMcpConfigEnabled = !appendSystemPrompt && providerSettings.strictMcpConfig !== false;
|
|
105
|
+
// Prefer the model's own thinkingLevelMap when present (pi-ai 0.72+ ships
|
|
106
|
+
// per-model overrides — e.g. opus-4-7 wants xhigh→xhigh, not xhigh→max).
|
|
107
|
+
// Fall back to our generic table for older pi-ai or unmapped levels.
|
|
108
|
+
const requestedEffort = reasoning
|
|
109
|
+
? ((queryModel as any).thinkingLevelMap?.[reasoning] as EffortLevel | undefined)
|
|
110
|
+
?? REASONING_TO_EFFORT[reasoning]
|
|
111
|
+
: undefined;
|
|
112
|
+
const effort = resolveConfiguredEffort(queryModel.id, requestedEffort, providerSettings);
|
|
113
|
+
|
|
114
|
+
const extraArgs: Record<string, string | null> = {};
|
|
115
|
+
// Opus 4.7 defaults thinking.display to "omitted" (empty thinking text in stream).
|
|
116
|
+
// Force summarized so thinking_delta events arrive. See anthropics/claude-agent-sdk-python#830.
|
|
117
|
+
// Deliberately the raw flag, NOT the typed `thinking` option: every non-disabled
|
|
118
|
+
// ThinkingConfig also emits `--thinking adaptive` or `--max-thinking-tokens`
|
|
119
|
+
// (verified in sdk.mjs flag mapping), so the typed form cannot set display
|
|
120
|
+
// without overriding the model's thinking mode alongside our `--effort`.
|
|
121
|
+
if (effort) extraArgs["thinking-display"] = "summarized";
|
|
122
|
+
// With a managed Fable pool, let every account's model-scoped allowance run
|
|
123
|
+
// out (rotation) before changing models — the CLI's own Opus fallback would
|
|
124
|
+
// silently skip accounts whose Fable quota is still available. Once the
|
|
125
|
+
// router explicitly selects Opus, its normal Opus→4.8 safety fallback is
|
|
126
|
+
// back on.
|
|
127
|
+
const fallbackModel = account && requestedModel.id === FABLE_MODEL_ID && queryModel.id === requestedModel.id
|
|
128
|
+
? undefined
|
|
129
|
+
: fallbackModelForPrimaryModel(queryModel.id);
|
|
130
|
+
|
|
131
|
+
// Suppress claude.ai cloud MCP servers (Figma/Canva/etc. auto-discovered via OAuth
|
|
132
|
+
// when the user is logged into Anthropic). These are a separate code path from
|
|
133
|
+
// filesystem MCP and are NOT blocked by --strict-mcp-config or settingSources=undefined.
|
|
134
|
+
// The native CC binary gates them on env var ENABLE_CLAUDEAI_MCP_SERVERS: setting it
|
|
135
|
+
// to "0"/"false"/"no"/"off" makes the loader return early before any cloud fetch.
|
|
136
|
+
// DISABLE_AUTO_COMPACT=1: pi owns context-management and propagates its own
|
|
137
|
+
// /compact via session_compact (see handler in the extension entry). Letting CC
|
|
138
|
+
// also autocompact would double-flush the prompt cache and races pi's
|
|
139
|
+
// threshold with CC's, including CC's anti-thrashing guard (issue #8).
|
|
140
|
+
// Manual /compact in CC still works (we never invoke it).
|
|
141
|
+
// When connectors are enabled, allow claude.ai cloud MCP servers so the
|
|
142
|
+
// authenticated account's Gmail/Calendar/Drive tools load. Default stays "0".
|
|
143
|
+
const childEnv = {
|
|
144
|
+
...(account ? subscriberProfileEnv(account) : process.env),
|
|
145
|
+
ENABLE_CLAUDEAI_MCP_SERVERS: enableCloudMcp ? "1" : "0",
|
|
146
|
+
DISABLE_AUTO_COMPACT: "1",
|
|
147
|
+
};
|
|
148
|
+
const queryOptions: NonNullable<Parameters<typeof query>[0]["options"]> = {
|
|
149
|
+
cwd,
|
|
150
|
+
model: queryModel.id,
|
|
151
|
+
env: childEnv,
|
|
152
|
+
...connectorQueryOptions(enableCloudMcp, connectorWriteMode),
|
|
153
|
+
permissionMode: "bypassPermissions",
|
|
154
|
+
includePartialMessages: true,
|
|
155
|
+
...(fallbackModel ? { fallbackModel } : {}),
|
|
156
|
+
...(providerSettings.fastMode ? { settings: { fastMode: true } } : {}),
|
|
157
|
+
systemPrompt: {
|
|
158
|
+
type: "preset", preset: "claude_code",
|
|
159
|
+
append: systemPromptAppend ? systemPromptAppend : undefined,
|
|
160
|
+
},
|
|
161
|
+
extraArgs,
|
|
162
|
+
...(strictMcpConfigEnabled ? { strictMcpConfig: true } : {}),
|
|
163
|
+
...(effort ? { effort } : {}),
|
|
164
|
+
...(settingSources ? { settingSources } : {}),
|
|
165
|
+
...(mcpServers || Object.keys(connectorServers).length > 0
|
|
166
|
+
? { mcpServers: { ...(mcpServers ?? {}), ...connectorServers } as NonNullable<Parameters<typeof query>[0]["options"]>["mcpServers"] }
|
|
167
|
+
: {}),
|
|
168
|
+
...(resumeSessionId ? { resume: resumeSessionId } : {}),
|
|
169
|
+
...(claudeExecutable ? { pathToClaudeCodeExecutable: claudeExecutable } : {}),
|
|
170
|
+
spawnClaudeCodeProcess: spawnClaudeCodeWithDiagnostics,
|
|
171
|
+
...makeCliDebugOptions("provider"),
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
return {
|
|
175
|
+
queryOptions,
|
|
176
|
+
enableCloudMcp,
|
|
177
|
+
appendSystemPrompt,
|
|
178
|
+
promptContextLabels: promptContextAppend.labels,
|
|
179
|
+
strictMcpConfigEnabled,
|
|
180
|
+
...(effort ? { effort } : {}),
|
|
181
|
+
...(fallbackModel ? { fallbackModel } : {}),
|
|
182
|
+
};
|
|
183
|
+
}
|