pi-codebuddy-sdk 0.4.36 → 0.4.37
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 +39 -2
- package/package.json +5 -2
- package/src/config.ts +27 -6
- package/src/index.ts +44 -24
- package/src/models.ts +7 -0
package/README.md
CHANGED
|
@@ -103,6 +103,8 @@ File: `~/.pi/agent/codebuddy-sdk.json` or `.pi/codebuddy-sdk.json` in a project.
|
|
|
103
103
|
| `provider.strictMcpConfig` | `true` | Use only Pi-bridged MCP tools |
|
|
104
104
|
| `provider.pathToCodebuddyCode` | auto | Path to the `codebuddy` **CLI entry point** when it is **not** on `PATH`; does not change the JS runtime |
|
|
105
105
|
| `provider.executable` | host runtime | Runtime used to spawn the CLI (e.g. `"node"`). Set it when the host is Bun-compiled (no `bun` on `PATH`); auto-detected otherwise |
|
|
106
|
+
| `provider.isolatedEnv` | `false` | Opt in to a private CodeBuddy config dir with user, auto, and team memory disabled |
|
|
107
|
+
| `provider.codebuddyConfigDir` | `~/.codebuddy-cli-isolated` | Config dir used when `isolatedEnv` is enabled |
|
|
106
108
|
| `provider.contextWindow` | estimated | Override context window (tokens) for **all** models (e.g. `300000`) |
|
|
107
109
|
| `provider.maxTokens` | estimated | Override max output tokens for **all** models (e.g. `32768`) |
|
|
108
110
|
| `provider.modelOverrides` | — | Per-model overrides, keyed by model id or substring (see below) |
|
|
@@ -121,7 +123,42 @@ key wins and beats the global `contextWindow` / `maxTokens`:
|
|
|
121
123
|
}
|
|
122
124
|
```
|
|
123
125
|
|
|
124
|
-
Supported per-model keys: `contextWindow`, `maxTokens`, `reasoning`, `images
|
|
126
|
+
Supported per-model keys: `contextWindow`, `maxTokens`, `reasoning`, `images`,
|
|
127
|
+
`thinkingLevelMap`.
|
|
128
|
+
|
|
129
|
+
`thinkingLevelMap` maps a pi thinking level to the effort string sent to the
|
|
130
|
+
CodeBuddy CLI. pi only offers `xhigh` and `max` when a model declares them here
|
|
131
|
+
(pi-ai `getSupportedThinkingLevels`), so a model that supports `max` upstream
|
|
132
|
+
stays unreachable until the map names it:
|
|
133
|
+
|
|
134
|
+
```json
|
|
135
|
+
{
|
|
136
|
+
"provider": {
|
|
137
|
+
"modelOverrides": {
|
|
138
|
+
"deepseek-v4.1-flash": { "thinkingLevelMap": { "max": "max" } },
|
|
139
|
+
"space-bunny": { "thinkingLevelMap": { "xhigh": "xhigh", "max": "max" } }
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Declare only the habits the model actually serves — an effort the backend
|
|
146
|
+
rejects fails the turn.
|
|
147
|
+
|
|
148
|
+
Set `provider.isolatedEnv` to keep Pi turns away from the CodeBuddy IDE's rules,
|
|
149
|
+
projects, and memory. The extension sends both the CLI subprocess and its own
|
|
150
|
+
session files to one config dir:
|
|
151
|
+
|
|
152
|
+
```json
|
|
153
|
+
{
|
|
154
|
+
"provider": {
|
|
155
|
+
"isolatedEnv": true,
|
|
156
|
+
"codebuddyConfigDir": "/path/to/private-codebuddy-config"
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
The first run against a new dir needs the CodeBuddy CLI login for that dir.
|
|
125
162
|
|
|
126
163
|
Window values the backend reports for a model are remembered per model id in
|
|
127
164
|
`~/.pi/agent/codebuddy-sdk-learned-windows.json`, so the next start registers the
|
|
@@ -134,7 +171,7 @@ again (ids the backend no longer serves are dropped automatically).
|
|
|
134
171
|
- The extension does **not** send conversation data to this repository or any third-party telemetry endpoint.
|
|
135
172
|
- Credentials are handled entirely by the CodeBuddy CLI on your machine.
|
|
136
173
|
- Optional debug mode (`CODEBUDDY_SDK_DEBUG=1`) writes **local** logs under `~/.pi/agent/`; paths are redacted, prompts and tool payloads are not logged. Delete logs when finished.
|
|
137
|
-
- CodeBuddy loads project instructions,
|
|
174
|
+
- CodeBuddy loads project instructions, rules, and project memory independently of `--setting-sources`; those files can add context that is not part of the Pi session. Set `provider.isolatedEnv` to use a private config dir with memory disabled.
|
|
138
175
|
|
|
139
176
|
## Troubleshooting
|
|
140
177
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-codebuddy-sdk",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.37",
|
|
4
4
|
"description": "Pi extension that uses CodeBuddy (via Agent SDK) as a model provider and adds an AskCodebuddy tool.",
|
|
5
5
|
"author": "RealAlexandreAI",
|
|
6
6
|
"license": "MIT",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"typecheck": "tsc --noEmit"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@tencent-ai/agent-sdk": "^0.3.
|
|
37
|
+
"@tencent-ai/agent-sdk": "^0.3.291",
|
|
38
38
|
"change-case": "^5.4.4"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
@@ -52,6 +52,9 @@
|
|
|
52
52
|
"typebox": "1.4.3",
|
|
53
53
|
"typescript": "^7.0.2"
|
|
54
54
|
},
|
|
55
|
+
"overrides": {
|
|
56
|
+
"undici": "^8.12.3"
|
|
57
|
+
},
|
|
55
58
|
"pi": {
|
|
56
59
|
"extensions": [
|
|
57
60
|
"./src/index.ts"
|
package/src/config.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { SettingSource } from "./index-types.js";
|
|
2
|
+
import type { ModelOverrides } from "./models.js";
|
|
2
3
|
import { CONFIG_DIR_NAME } from "@earendil-works/pi-coding-agent";
|
|
3
4
|
import { existsSync, readFileSync } from "fs";
|
|
4
5
|
import { homedir } from "os";
|
|
@@ -32,17 +33,37 @@ export interface Config {
|
|
|
32
33
|
* host runtime; set this when a Bun-compiled host has no `bun` on `PATH`.
|
|
33
34
|
*/
|
|
34
35
|
executable?: string;
|
|
36
|
+
/** Run the CLI against a private CodeBuddy config dir and disable its memory. */
|
|
37
|
+
isolatedEnv?: boolean;
|
|
38
|
+
/** Config dir used when `isolatedEnv` is on. Defaults to `~/.codebuddy-cli-isolated`. */
|
|
39
|
+
codebuddyConfigDir?: string;
|
|
35
40
|
/** Override the estimated context window (tokens) for ALL models. */
|
|
36
41
|
contextWindow?: number;
|
|
37
42
|
/** Override the estimated max output tokens for ALL models. */
|
|
38
43
|
maxTokens?: number;
|
|
39
44
|
/** Per-model overrides keyed by model id (or id substring). */
|
|
40
|
-
modelOverrides?: Record<string,
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
45
|
+
modelOverrides?: Record<string, ModelOverrides>;
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function resolveCodebuddyConfigDir(provider?: Config["provider"]): string | undefined {
|
|
50
|
+
if (provider?.isolatedEnv !== true) return undefined;
|
|
51
|
+
return provider.codebuddyConfigDir ?? join(homedir(), ".codebuddy-cli-isolated");
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function buildCodebuddyEnv(
|
|
55
|
+
provider?: Config["provider"],
|
|
56
|
+
base: NodeJS.ProcessEnv = process.env,
|
|
57
|
+
): NodeJS.ProcessEnv {
|
|
58
|
+
const env = { ...base, DISABLE_AUTO_COMPACT: "1" };
|
|
59
|
+
const dir = resolveCodebuddyConfigDir(provider);
|
|
60
|
+
if (!dir) return env;
|
|
61
|
+
return {
|
|
62
|
+
...env,
|
|
63
|
+
CODEBUDDY_CONFIG_DIR: dir,
|
|
64
|
+
CODEBUDDY_MEMORY_ENABLED: "0",
|
|
65
|
+
CODEBUDDY_DISABLE_AUTO_MEMORY: "1",
|
|
66
|
+
CODEBUDDY_TEAM_MEMORY_ENABLED: "0",
|
|
46
67
|
};
|
|
47
68
|
}
|
|
48
69
|
|
package/src/index.ts
CHANGED
|
@@ -20,7 +20,7 @@ import { MCP_SERVER_NAME, MCP_TOOL_PREFIX, buildCodebuddySystemPrompt } from "./
|
|
|
20
20
|
import { verifyWrittenSession as _verifyWrittenSession } from "./session-verify.js";
|
|
21
21
|
import { extractAllToolResults as _extractAllToolResults, type McpResult } from "./extract-tool-results.js";
|
|
22
22
|
import { QueryContext, ctx } from "./query-state.js";
|
|
23
|
-
import { loadConfig, type Config } from "./config.js";
|
|
23
|
+
import { buildCodebuddyEnv, loadConfig, resolveCodebuddyConfigDir, type Config } from "./config.js";
|
|
24
24
|
import { jsonSchemaToZodShape } from "./typebox-to-zod.js";
|
|
25
25
|
import { buildActionSummary, type ToolCallState } from "./askcodebuddy-ui.js";
|
|
26
26
|
import { withSdkGate } from "./sdk-gate.js";
|
|
@@ -207,10 +207,6 @@ type ContentBlockParam =
|
|
|
207
207
|
| { type: "image"; source: { type: "base64"; media_type: string; data: string } };
|
|
208
208
|
type SettingSource = "user" | "project" | "local";
|
|
209
209
|
|
|
210
|
-
function resolveModel(input: string) {
|
|
211
|
-
return _resolveModel(MODELS, input);
|
|
212
|
-
}
|
|
213
|
-
|
|
214
210
|
function registerCodebuddyProvider(pi: ExtensionAPI, globals: Record<symbol, any> = globalThis as Record<symbol, any>): void {
|
|
215
211
|
const { streamFn, claimStream } = providerRegistration(globals, streamCodebuddySdk, boundRuntime);
|
|
216
212
|
pi.registerProvider(PROVIDER_ID, {
|
|
@@ -447,7 +443,7 @@ async function runIsolatedSummary(
|
|
|
447
443
|
prompt: promptText,
|
|
448
444
|
options: {
|
|
449
445
|
cwd,
|
|
450
|
-
env:
|
|
446
|
+
env: buildCodebuddyEnv(loadConfig(cwd).provider),
|
|
451
447
|
tools: [],
|
|
452
448
|
strictMcpConfig: true,
|
|
453
449
|
settingSources: [] as SettingSource[],
|
|
@@ -562,7 +558,7 @@ function verifyWrittenSession(
|
|
|
562
558
|
`. Report: ${ISSUES_URL}`,
|
|
563
559
|
"warning",
|
|
564
560
|
);
|
|
565
|
-
diagDump("session_verify_fail", { msg, jsonlPath, cwd, realpath: safeRealpath(cwd), codebuddyConfigDir:
|
|
561
|
+
diagDump("session_verify_fail", { msg, jsonlPath, cwd, realpath: safeRealpath(cwd), codebuddyConfigDir: resolveCodebuddyConfigDir(providerSettings) ?? null });
|
|
566
562
|
}
|
|
567
563
|
}
|
|
568
564
|
|
|
@@ -691,11 +687,11 @@ function syncSharedSession(
|
|
|
691
687
|
const preserveId = previousSessionId !== undefined && !sharedSession?.forceRotate;
|
|
692
688
|
if (preserveId) {
|
|
693
689
|
// Wipe prior jsonl + companion dir (no-op if nothing to wipe).
|
|
694
|
-
deleteSession(previousSessionId!, cwd,
|
|
690
|
+
deleteSession(previousSessionId!, cwd, resolveCodebuddyConfigDir(providerSettings));
|
|
695
691
|
}
|
|
696
692
|
const session = createSession({
|
|
697
693
|
projectPath: cwd,
|
|
698
|
-
codebuddyDir:
|
|
694
|
+
codebuddyDir: resolveCodebuddyConfigDir(providerSettings),
|
|
699
695
|
...(preserveId ? { sessionId: previousSessionId } : {}),
|
|
700
696
|
...(modelId ? { model: modelId } : {}),
|
|
701
697
|
});
|
|
@@ -727,7 +723,11 @@ export const __test = {
|
|
|
727
723
|
getSharedSession() {
|
|
728
724
|
return sharedSession;
|
|
729
725
|
},
|
|
726
|
+
setProviderSettings(settings: NonNullable<Config["provider"]>) {
|
|
727
|
+
providerSettings = settings;
|
|
728
|
+
},
|
|
730
729
|
syncSharedSession,
|
|
730
|
+
promptAndWait,
|
|
731
731
|
};
|
|
732
732
|
|
|
733
733
|
// --- Provider helpers: tool name mapping ---
|
|
@@ -910,7 +910,7 @@ function syncServedContextWindow(label: string, message: CbMessage, model: Model
|
|
|
910
910
|
// Pi reasoning levels → CC SDK effort levels
|
|
911
911
|
|
|
912
912
|
const REASONING_TO_EFFORT: Record<string, Effort> = {
|
|
913
|
-
minimal: "low", low: "low", medium: "medium", high: "high", xhigh: "xhigh",
|
|
913
|
+
minimal: "low", low: "low", medium: "medium", high: "high", xhigh: "xhigh", max: "max",
|
|
914
914
|
};
|
|
915
915
|
|
|
916
916
|
// --- Provider helpers: misc ---
|
|
@@ -1399,7 +1399,7 @@ function streamCodebuddySdk(model: Model<any>, context: Context, options?: Simpl
|
|
|
1399
1399
|
const extraArgs: Record<string, string | null> = { model: cliModel };
|
|
1400
1400
|
if (strictMcpConfigEnabled) extraArgs["strict-mcp-config"] = null;
|
|
1401
1401
|
|
|
1402
|
-
const childEnv =
|
|
1402
|
+
const childEnv = buildCodebuddyEnv(providerSettings);
|
|
1403
1403
|
const queryOptions: NonNullable<Parameters<typeof query>[0]["options"]> = {
|
|
1404
1404
|
cwd,
|
|
1405
1405
|
env: childEnv,
|
|
@@ -1472,7 +1472,7 @@ function streamCodebuddySdk(model: Model<any>, context: Context, options?: Simpl
|
|
|
1472
1472
|
const sessionId = capturedSessionId ?? sharedSession?.sessionId;
|
|
1473
1473
|
if (syncResult.preserveSharedSession) {
|
|
1474
1474
|
if (capturedSessionId && capturedSessionId !== sharedSession?.sessionId) {
|
|
1475
|
-
deleteSession(capturedSessionId, cwd,
|
|
1475
|
+
deleteSession(capturedSessionId, cwd, resolveCodebuddyConfigDir(providerSettings));
|
|
1476
1476
|
debug(`provider: query done, deleted ephemeral session ${capturedSessionId.slice(0, 8)} to preserve shared session`);
|
|
1477
1477
|
}
|
|
1478
1478
|
debug(`provider: query done, ignoring captured session ${capturedSessionId?.slice(0, 8) ?? "none"} to preserve shared session`);
|
|
@@ -1571,12 +1571,12 @@ async function promptAndWait(
|
|
|
1571
1571
|
isolated?: boolean;
|
|
1572
1572
|
context?: Context["messages"];
|
|
1573
1573
|
},
|
|
1574
|
+
runQuery: typeof startQuery = startQuery,
|
|
1574
1575
|
): Promise<{ responseText: string; stopReason: string }> {
|
|
1575
1576
|
const cwd = process.cwd();
|
|
1576
|
-
const requestedModel = options?.model
|
|
1577
|
-
const model =
|
|
1577
|
+
const requestedModel = options?.model;
|
|
1578
|
+
const model = requestedModel === undefined ? undefined : _resolveModel(MODELS, requestedModel);
|
|
1578
1579
|
const modelId = model?.id ?? requestedModel;
|
|
1579
|
-
const cliModel = model ? codebuddyModelId(model) : modelId;
|
|
1580
1580
|
|
|
1581
1581
|
// Session resume for shared mode — reuse provider's session if it exists,
|
|
1582
1582
|
// otherwise create one from pi's context.
|
|
@@ -1613,19 +1613,19 @@ async function promptAndWait(
|
|
|
1613
1613
|
|
|
1614
1614
|
const extraArgs: Record<string, string | null> = {
|
|
1615
1615
|
"strict-mcp-config": null,
|
|
1616
|
-
model:
|
|
1616
|
+
...(modelId !== undefined ? { model: modelId } : {}),
|
|
1617
1617
|
};
|
|
1618
1618
|
|
|
1619
1619
|
debug("askCodebuddy:",
|
|
1620
|
-
`mode=${mode} model=${modelId
|
|
1620
|
+
`mode=${mode} model=${modelId ?? "CLI default"} effort=${effort ?? "default"}`,
|
|
1621
1621
|
`isolated=${options?.isolated ?? false} resume=${resumeSessionId?.slice(0, 8) ?? "none"}`,
|
|
1622
1622
|
`sysPrompt=${Boolean(askSystemPrompt)} promptLen=${prompt.length}`);
|
|
1623
1623
|
|
|
1624
|
-
const sdkQuery =
|
|
1624
|
+
const sdkQuery = runQuery({
|
|
1625
1625
|
prompt,
|
|
1626
1626
|
options: {
|
|
1627
1627
|
cwd,
|
|
1628
|
-
env:
|
|
1628
|
+
env: buildCodebuddyEnv(providerSettings),
|
|
1629
1629
|
permissionMode: "bypassPermissions",
|
|
1630
1630
|
...(disallowedTools.length ? { disallowedTools } : {}),
|
|
1631
1631
|
...(effort ? { effort } : {}),
|
|
@@ -1699,6 +1699,10 @@ async function promptAndWait(
|
|
|
1699
1699
|
if (!responseText && message.subtype === "success" && message.result) {
|
|
1700
1700
|
responseText = message.result;
|
|
1701
1701
|
}
|
|
1702
|
+
if (r.is_error || message.subtype !== "success") {
|
|
1703
|
+
const failure = [responseText, r.result, ...(r.errors ?? [])].filter(Boolean).join("\n");
|
|
1704
|
+
throw new Error(failure || `CodeBuddy query failed (${message.subtype}).`);
|
|
1705
|
+
}
|
|
1702
1706
|
break;
|
|
1703
1707
|
}
|
|
1704
1708
|
}
|
|
@@ -1710,6 +1714,13 @@ async function promptAndWait(
|
|
|
1710
1714
|
`sdkMessages=${sdkMessageCount} textDeltas=${textDeltaCount} responseLen=${responseText.length}`,
|
|
1711
1715
|
`toolCalls=${toolCalls.size}`);
|
|
1712
1716
|
return { responseText, stopReason };
|
|
1717
|
+
} catch (err) {
|
|
1718
|
+
const message = errorMessage(err);
|
|
1719
|
+
const unavailableModel = /model\s*\[([^\]]+)\]\s*service info not found/i.exec(message);
|
|
1720
|
+
if (unavailableModel) {
|
|
1721
|
+
throw new Error(`CodeBuddy model "${unavailableModel[1]}" is unavailable for this account. Choose a model ID supported by your CodeBuddy account, or omit model to use the CLI's account default.\n${message}`);
|
|
1722
|
+
}
|
|
1723
|
+
throw err;
|
|
1713
1724
|
} finally {
|
|
1714
1725
|
signal?.removeEventListener("abort", onAbort);
|
|
1715
1726
|
endQuery(sdkQuery, "askCodebuddy", { log: debug });
|
|
@@ -1734,7 +1745,16 @@ async function discoverModels(pi: ExtensionAPI): Promise<void> {
|
|
|
1734
1745
|
await withSdkGate(async () => {
|
|
1735
1746
|
let q: ReturnType<typeof startQuery> | undefined;
|
|
1736
1747
|
try {
|
|
1737
|
-
q = startQuery({
|
|
1748
|
+
q = startQuery({
|
|
1749
|
+
prompt: " ",
|
|
1750
|
+
options: {
|
|
1751
|
+
maxTurns: 0,
|
|
1752
|
+
permissionMode: "bypassPermissions",
|
|
1753
|
+
tools: [],
|
|
1754
|
+
env: buildCodebuddyEnv(providerSettings),
|
|
1755
|
+
...(providerSettings.pathToCodebuddyCode ? { pathToCodebuddyCode: providerSettings.pathToCodebuddyCode } : {}),
|
|
1756
|
+
},
|
|
1757
|
+
});
|
|
1738
1758
|
const supported = await q.supportedModels();
|
|
1739
1759
|
await q.return().catch(() => {});
|
|
1740
1760
|
if (!supported.length) return;
|
|
@@ -1903,11 +1923,11 @@ export default async function (pi: ExtensionAPI) {
|
|
|
1903
1923
|
|
|
1904
1924
|
if (askConf?.enabled !== false) {
|
|
1905
1925
|
const askCodebuddyParams = Type.Object({
|
|
1906
|
-
prompt: Type.String({ description: "The question or task for CodeBuddy. By default
|
|
1926
|
+
prompt: Type.String({ description: "The question or task for CodeBuddy. By default CodeBuddy sees the full conversation history. Don't research up front, let CodeBuddy explore." }),
|
|
1907
1927
|
mode: Type.Optional(StringEnum(modeValues, { description: modeDesc })),
|
|
1908
|
-
model: Type.Optional(Type.String({ description:
|
|
1909
|
-
thinking: Type.Optional(StringEnum(["off", "minimal", "low", "medium", "high", "xhigh"] as const, { description: "Thinking effort level. Omit to use CodeBuddy's default." })),
|
|
1910
|
-
isolated: Type.Optional(Type.Boolean({ description: "When true,
|
|
1928
|
+
model: Type.Optional(Type.String({ description: "CodeBuddy model ID supported by your account. Omit to use the CLI's account default." })),
|
|
1929
|
+
thinking: Type.Optional(StringEnum(["off", "minimal", "low", "medium", "high", "xhigh", "max"] as const, { description: "Thinking effort level. Omit to use CodeBuddy's default." })),
|
|
1930
|
+
isolated: Type.Optional(Type.Boolean({ description: "When true, CodeBuddy sees only this prompt (clean session). When false (default), CodeBuddy sees the full conversation history." })),
|
|
1911
1931
|
});
|
|
1912
1932
|
pi.registerTool<typeof askCodebuddyParams>({
|
|
1913
1933
|
name: askConf?.name ?? "AskCodebuddy",
|
package/src/models.ts
CHANGED
|
@@ -95,6 +95,9 @@ export type ModelOverrides = {
|
|
|
95
95
|
maxTokens?: number;
|
|
96
96
|
reasoning?: boolean;
|
|
97
97
|
images?: boolean;
|
|
98
|
+
// Pi thinking level -> provider-native effort. Pi only offers `xhigh`/`max`
|
|
99
|
+
// when the key is present here (pi-ai `getSupportedThinkingLevels`).
|
|
100
|
+
thinkingLevelMap?: Record<string, string>;
|
|
98
101
|
};
|
|
99
102
|
|
|
100
103
|
/**
|
|
@@ -137,12 +140,16 @@ export function buildModels(
|
|
|
137
140
|
const input: ("text" | "image")[] = o.images === undefined
|
|
138
141
|
? m.input
|
|
139
142
|
: (o.images ? ["text", "image"] as const : ["text"] as const);
|
|
143
|
+
const thinkingLevelMap = o.thinkingLevelMap
|
|
144
|
+
? { ...(m.thinkingLevelMap ?? {}), ...o.thinkingLevelMap }
|
|
145
|
+
: m.thinkingLevelMap;
|
|
140
146
|
return {
|
|
141
147
|
...m,
|
|
142
148
|
contextWindow,
|
|
143
149
|
maxTokens,
|
|
144
150
|
reasoning: o.reasoning ?? m.reasoning,
|
|
145
151
|
input,
|
|
152
|
+
...(thinkingLevelMap ? { thinkingLevelMap } : {}),
|
|
146
153
|
cost: m.cost ?? { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
147
154
|
};
|
|
148
155
|
});
|