@callstack/apex 0.3.0 → 0.3.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 +39 -9
- package/dist/cli.js +172 -37
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -148,15 +148,43 @@ their own backup first, so an undo is itself reversible. Apex CLI records each b
|
|
|
148
148
|
| OpenCode | `~/.config/opencode/opencode.json` or `.jsonc` | Adds `provider.callstack.ai`, OpenAI-compatible transport, model and environment-key reference; preserves the default model. A config already in OpenCode 2's `providers` format gets the v2 entry instead, and you add the key with `/connect`. |
|
|
149
149
|
| Codex 0.134.0+ | `~/.codex/callstack_ai.config.toml` | Adds a self-contained Responses API provider/profile; leaves base config and default model untouched. |
|
|
150
150
|
| Claude Code | `~/.claude/settings.json` | Merges attribution flag only; use `apex run claude` for gateway credentials and model selection. |
|
|
151
|
-
| Pi | `~/.pi/agent/models.json` | Adds `providers.callstack` with Chat Completions, Apex and `$CALLSTACK_AUTH_TOKEN`;
|
|
151
|
+
| Pi | `~/.pi/agent/models.json` and `settings.json` | Adds `providers.callstack` with Chat Completions, Apex and `$CALLSTACK_AUTH_TOKEN`; saves `medium` as Apex's per-model thinking default for direct launches. Preserves other models and their defaults. Requires a Pi version supporting `$VAR` key interpolation and `modelThinkingLevels`. |
|
|
152
152
|
| Cursor | Guided setup | Prints endpoint, API-key and custom-model steps; does not modify private editor storage. |
|
|
153
153
|
| VS Code / Copilot | Guided setup | Detects VS Code, not whether Copilot is installed; prints custom-endpoint steps and model JSON, retaining the editor-generated secret reference. |
|
|
154
|
-
| Vercel AI SDK / Eve | Guided setup | Detected from the `package.json` in the directory you run Apex CLI from (`ai`, `@ai-sdk/openai` or `eve`); prints the connector snippet, which reads the key from `CALLSTACK_AUTH_TOKEN
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
154
|
+
| Vercel AI SDK / Eve | Guided setup | Detected from the `package.json` in the directory you run Apex CLI from (`ai`, `@ai-sdk/openai` or `eve`); prints the connector snippet, which reads the key from `CALLSTACK_AUTH_TOKEN`. Nothing is written into the project. |
|
|
155
|
+
|
|
156
|
+
Apex configs declare tool calling, image input, and the supported
|
|
157
|
+
`none`/`low`/`medium`/`xhigh` reasoning efforts (default `medium`) where supported.
|
|
158
|
+
OpenCode, Pi, Copilot, Claude's launcher, and the AI SDK guidance retain a 32,768-token output
|
|
159
|
+
budget. OpenCode, Pi, Codex, Copilot, and Claude's launcher declare the model's native
|
|
160
|
+
262,144-token context window using each app's documented fields. Input limits and compaction
|
|
161
|
+
thresholds use the harness defaults; Apex CLI does not set a separate input budget or compaction
|
|
162
|
+
reserve.
|
|
163
|
+
Pi's per-model default applies to fresh direct launches and model selection; `apex run pi` also
|
|
164
|
+
selects `medium` explicitly. Resumed Pi sessions retain their saved thinking level.
|
|
165
|
+
|
|
166
|
+
The gateway model ID, authentication, `medium` default, and `off` → `none` translation remain
|
|
167
|
+
Callstack-specific.
|
|
168
|
+
|
|
169
|
+
| Harness | Context field | Output field | Official reference |
|
|
170
|
+
| --- | --- | --- | --- |
|
|
171
|
+
| OpenCode | `limit.context` | `limit.output` | [Custom providers](https://opencode.ai/docs/providers/) |
|
|
172
|
+
| Pi | `contextWindow` | `maxTokens` | [Custom models](https://pi.dev/docs/latest/models) |
|
|
173
|
+
| Codex | `model_context_window` | No output-limit config key | [OpenAI configuration reference](https://developers.openai.com/codex/config-reference/) |
|
|
174
|
+
| Claude Code launcher | `CLAUDE_CODE_MAX_CONTEXT_TOKENS` | `CLAUDE_CODE_MAX_OUTPUT_TOKENS` | [Environment variables](https://code.claude.com/docs/en/env-vars) |
|
|
175
|
+
| VS Code / Copilot | `contextWindow` | `maxOutputTokens` | [Custom endpoint models](https://code.visualstudio.com/docs/agent-customization/language-models) |
|
|
176
|
+
|
|
177
|
+
The Claude launcher sets context/output limits only in the child process and does not set compaction
|
|
178
|
+
window or percentage controls. Pi retains its native compaction settings. The AI SDK
|
|
179
|
+
snippet sets the output budget without inventing a context-window option.
|
|
180
|
+
|
|
181
|
+
Run `apex init` again after updating the CLI to preview upgrades to an existing Apex setup; pass
|
|
182
|
+
`--apply` to save them. Apex context/output metadata and reasoning mappings are updated in place. Older OpenCode input
|
|
183
|
+
limits and Codex compaction overrides are removed so each harness uses its own compaction defaults.
|
|
184
|
+
Codex's obsolete `model_max_output_tokens` key from older Apex versions is removed, and its dedicated
|
|
185
|
+
profile becomes self-contained. Unrelated settings, models, credentials and comments are preserved;
|
|
186
|
+
the ordinary backups and `apex undo` also cover upgrades. `none` remains supported: the gateway
|
|
187
|
+
translates it to thinking off.
|
|
160
188
|
|
|
161
189
|
Respects `XDG_CONFIG_HOME`, `CODEX_HOME`, `CLAUDE_CONFIG_DIR`, `PI_CODING_AGENT_DIR`,
|
|
162
190
|
`XDG_STATE_HOME`/`APEX_STATE_DIR`, and Windows `APPDATA`. Project-specific settings and custom
|
|
@@ -201,9 +229,11 @@ Apex CLI will not break what you already have.
|
|
|
201
229
|
How that works underneath:
|
|
202
230
|
|
|
203
231
|
- Previews print paths and key/value changes, never secrets.
|
|
204
|
-
- All selected configurations are parsed before any write. Malformed files
|
|
205
|
-
|
|
232
|
+
- All selected configurations are parsed before any write. Malformed files and symlinked files or
|
|
233
|
+
directories are refused, and one bad assistant blocks the
|
|
206
234
|
whole batch instead of half-applying it.
|
|
235
|
+
- The dedicated Codex Apex profile's owned keys are upgraded rather than rejected as conflicts;
|
|
236
|
+
the base `config.toml` and other profiles remain untouched.
|
|
207
237
|
- JSON/JSONC edits preserve comments and unrelated keys. The Callstack endpoint is set to the
|
|
208
238
|
documented one. A key the assistant already has (in OpenCode's own key store, or in Pi's
|
|
209
239
|
`models.json`, where Apex CLI 0.2 put them) is kept, so upgrading never leaves an assistant
|
package/dist/cli.js
CHANGED
|
@@ -2212,26 +2212,123 @@ function editJson(text, changes, path) {
|
|
|
2212
2212
|
parseJson(next, path);
|
|
2213
2213
|
return next;
|
|
2214
2214
|
}
|
|
2215
|
-
function
|
|
2216
|
-
|
|
2215
|
+
function updateToml(text, desired, path, obsolete = []) {
|
|
2216
|
+
const before = text ?? "";
|
|
2217
2217
|
try {
|
|
2218
|
-
|
|
2218
|
+
parse$1(before);
|
|
2219
2219
|
} catch {
|
|
2220
2220
|
throw new Error(`Invalid TOML in ${path}; nothing overwritten.`);
|
|
2221
2221
|
}
|
|
2222
|
-
const
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
const
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2222
|
+
const eol = before.includes("\r\n") ? "\r\n" : "\n";
|
|
2223
|
+
const keyText = (key) => /^[\w-]+$/.test(key) ? key : JSON.stringify(key);
|
|
2224
|
+
const lines = before.split(/\r?\n/);
|
|
2225
|
+
const valueAt = (value, keys) => keys.reduce((parent, key) => parent?.[key], value);
|
|
2226
|
+
const merge = (old, next) => object(next) ? Object.fromEntries(Object.entries({
|
|
2227
|
+
...object(old) ? old : {},
|
|
2228
|
+
...next
|
|
2229
|
+
}).map(([key, value]) => [key, Object.hasOwn(next, key) ? merge(old?.[key], next[key]) : value])) : next;
|
|
2230
|
+
const inline = (value) => value instanceof Date ? stringify({ value }).trim().replace(/^value\s*=\s*/, "") : object(value) ? `{ ${Object.entries(value).map(([key, item]) => `${JSON.stringify(key)} = ${inline(item)}`).join(", ")} }` : Array.isArray(value) ? `[${value.map(inline).join(", ")}]` : stringify({ value }).trim().replace(/^value\s*=\s*/, "");
|
|
2231
|
+
const statements = [];
|
|
2232
|
+
let section = [];
|
|
2233
|
+
for (let i = 0; i < lines.length; i++) {
|
|
2234
|
+
if (!lines[i].trim() || lines[i].trimStart().startsWith("#")) {
|
|
2235
|
+
statements.push({
|
|
2236
|
+
text: lines[i],
|
|
2237
|
+
section
|
|
2238
|
+
});
|
|
2239
|
+
continue;
|
|
2240
|
+
}
|
|
2241
|
+
let block = lines[i], parsed;
|
|
2242
|
+
for (;;) try {
|
|
2243
|
+
parsed = parse$1(block);
|
|
2244
|
+
break;
|
|
2245
|
+
} catch {
|
|
2246
|
+
if (++i >= lines.length) throw new Error(`Cannot safely update TOML in ${path}.`);
|
|
2247
|
+
block += eol + lines[i];
|
|
2248
|
+
}
|
|
2249
|
+
if (block.trimStart().startsWith("[")) {
|
|
2250
|
+
section = [];
|
|
2251
|
+
let cursor = parsed;
|
|
2252
|
+
while (object(cursor) && Object.keys(cursor).length === 1) {
|
|
2253
|
+
const key = Object.keys(cursor)[0];
|
|
2254
|
+
section.push(key);
|
|
2255
|
+
cursor = cursor[key];
|
|
2256
|
+
}
|
|
2257
|
+
statements.push({
|
|
2258
|
+
text: block,
|
|
2259
|
+
section,
|
|
2260
|
+
header: true,
|
|
2261
|
+
array: Array.isArray(cursor)
|
|
2262
|
+
});
|
|
2263
|
+
continue;
|
|
2264
|
+
}
|
|
2265
|
+
let equal = 0, keyQuote = null;
|
|
2266
|
+
for (; equal < block.length; equal++) {
|
|
2267
|
+
const char = block[equal];
|
|
2268
|
+
if (keyQuote === "\"" && char === "\\") {
|
|
2269
|
+
equal++;
|
|
2270
|
+
continue;
|
|
2271
|
+
}
|
|
2272
|
+
if (keyQuote) {
|
|
2273
|
+
if (char === keyQuote) keyQuote = null;
|
|
2274
|
+
} else if (char === "\"" || char === "'") keyQuote = char;
|
|
2275
|
+
else if (char === "=") break;
|
|
2276
|
+
}
|
|
2277
|
+
const rawKey = block.slice(0, equal).trim();
|
|
2278
|
+
let cursor = parse$1(`${rawKey} = 0`), keys = [];
|
|
2279
|
+
while (object(cursor)) {
|
|
2280
|
+
const key = Object.keys(cursor)[0];
|
|
2281
|
+
keys.push(key);
|
|
2282
|
+
cursor = cursor[key];
|
|
2283
|
+
}
|
|
2284
|
+
const full = [...section, ...keys];
|
|
2285
|
+
if (obsolete.includes(full.join("."))) continue;
|
|
2286
|
+
const next = valueAt(desired, full);
|
|
2287
|
+
if (next !== void 0 && !isDeepStrictEqual(valueAt(parsed, keys), merge(valueAt(parsed, keys), next))) {
|
|
2288
|
+
let comment = "", quote = null;
|
|
2289
|
+
if (!block.includes(eol)) for (let j = equal + 1; j < block.length; j++) {
|
|
2290
|
+
const char = block[j];
|
|
2291
|
+
if (quote === "\"" && char === "\\") {
|
|
2292
|
+
j++;
|
|
2293
|
+
continue;
|
|
2294
|
+
}
|
|
2295
|
+
if (quote) {
|
|
2296
|
+
if (char === quote) quote = null;
|
|
2297
|
+
} else if (char === "\"" || char === "'") quote = char;
|
|
2298
|
+
else if (char === "#") {
|
|
2299
|
+
comment = ` ${block.slice(j)}`;
|
|
2300
|
+
break;
|
|
2301
|
+
}
|
|
2302
|
+
}
|
|
2303
|
+
block = `${block.slice(0, equal + 1)} ${inline(merge(valueAt(parsed, keys), next))}${comment}`;
|
|
2304
|
+
}
|
|
2305
|
+
statements.push({
|
|
2306
|
+
text: block,
|
|
2307
|
+
section
|
|
2308
|
+
});
|
|
2309
|
+
}
|
|
2310
|
+
const leaves = (value, prefix = []) => Object.entries(value).flatMap(([key, item]) => object(item) ? leaves(item, [...prefix, key]) : [[[...prefix, key], item]]);
|
|
2311
|
+
for (const [keys, value] of leaves(desired)) {
|
|
2312
|
+
const current = parse$1(statements.map((item) => item.text).join(eol));
|
|
2313
|
+
if (isDeepStrictEqual(valueAt(current, keys), value)) continue;
|
|
2314
|
+
let header = -1, prefix = [];
|
|
2315
|
+
statements.forEach((item, index) => {
|
|
2316
|
+
if (item.header && !item.array && item.section.length < keys.length && item.section.every((key, i) => key === keys[i]) && item.section.length > prefix.length) {
|
|
2317
|
+
header = index;
|
|
2318
|
+
prefix = item.section;
|
|
2319
|
+
}
|
|
2320
|
+
});
|
|
2321
|
+
let end = statements.findIndex((item, index) => index > header && item.header);
|
|
2322
|
+
if (end === -1) end = statements.length;
|
|
2323
|
+
statements.splice(end, 0, {
|
|
2324
|
+
text: `${keys.slice(prefix.length).map(keyText).join(".")} = ${inline(value)}`,
|
|
2325
|
+
section: prefix
|
|
2326
|
+
});
|
|
2327
|
+
}
|
|
2328
|
+
const after = statements.map((item) => item.text).join(eol);
|
|
2329
|
+
const result = parse$1(after);
|
|
2330
|
+
for (const [keys, value] of leaves(desired)) if (!isDeepStrictEqual(valueAt(result, keys), value)) throw new Error(`Cannot safely update ${keys.join(".")} in ${path}.`);
|
|
2331
|
+
return after === before ? before : `${after.replace(/\s+$/, "")}${eol}`;
|
|
2235
2332
|
}
|
|
2236
2333
|
function sha256(text) {
|
|
2237
2334
|
return createHash("sha256").update(text, "utf8").digest("hex");
|
|
@@ -2311,8 +2408,7 @@ const RUNNABLE = [
|
|
|
2311
2408
|
"pi"
|
|
2312
2409
|
];
|
|
2313
2410
|
const CONTEXT_WINDOW = 262144;
|
|
2314
|
-
const
|
|
2315
|
-
const MAX_OUTPUT = 16384;
|
|
2411
|
+
const MAX_OUTPUT = 32768;
|
|
2316
2412
|
const EFFORTS = [
|
|
2317
2413
|
"none",
|
|
2318
2414
|
"low",
|
|
@@ -2330,7 +2426,6 @@ const OPENCODE_MODEL = {
|
|
|
2330
2426
|
},
|
|
2331
2427
|
limit: {
|
|
2332
2428
|
context: CONTEXT_WINDOW,
|
|
2333
|
-
input: MAX_INPUT,
|
|
2334
2429
|
output: MAX_OUTPUT
|
|
2335
2430
|
},
|
|
2336
2431
|
options: { reasoningEffort: "medium" },
|
|
@@ -2349,7 +2444,6 @@ const OPENCODE_V2_PROVIDER = {
|
|
|
2349
2444
|
},
|
|
2350
2445
|
limit: {
|
|
2351
2446
|
context: CONTEXT_WINDOW,
|
|
2352
|
-
input: MAX_INPUT,
|
|
2353
2447
|
output: MAX_OUTPUT
|
|
2354
2448
|
},
|
|
2355
2449
|
settings: { reasoningEffort: "medium" },
|
|
@@ -2372,7 +2466,8 @@ const PI_MODEL = {
|
|
|
2372
2466
|
xhigh: "xhigh",
|
|
2373
2467
|
max: null
|
|
2374
2468
|
},
|
|
2375
|
-
contextWindow: CONTEXT_WINDOW
|
|
2469
|
+
contextWindow: CONTEXT_WINDOW,
|
|
2470
|
+
maxTokens: MAX_OUTPUT
|
|
2376
2471
|
};
|
|
2377
2472
|
async function exists(path) {
|
|
2378
2473
|
try {
|
|
@@ -2497,7 +2592,34 @@ async function planAssistant(assistant) {
|
|
|
2497
2592
|
const storedKey = await openCodeHasKey(assistant.authFile);
|
|
2498
2593
|
await json(hasJsonc ? "opencode.jsonc" : "opencode.json", (existing) => {
|
|
2499
2594
|
v2 = Object.hasOwn(existing, "providers");
|
|
2500
|
-
if (v2) return [
|
|
2595
|
+
if (v2) return [
|
|
2596
|
+
[[
|
|
2597
|
+
"providers",
|
|
2598
|
+
"callstack.ai",
|
|
2599
|
+
"name"
|
|
2600
|
+
], OPENCODE_V2_PROVIDER.name],
|
|
2601
|
+
[[
|
|
2602
|
+
"providers",
|
|
2603
|
+
"callstack.ai",
|
|
2604
|
+
"package"
|
|
2605
|
+
], OPENCODE_V2_PROVIDER.package],
|
|
2606
|
+
[[
|
|
2607
|
+
"providers",
|
|
2608
|
+
"callstack.ai",
|
|
2609
|
+
"settings",
|
|
2610
|
+
"baseURL"
|
|
2611
|
+
], BASE_URL],
|
|
2612
|
+
...Object.entries(OPENCODE_V2_PROVIDER.models[MODEL]).map(([key, value]) => [[
|
|
2613
|
+
"providers",
|
|
2614
|
+
"callstack.ai",
|
|
2615
|
+
"models",
|
|
2616
|
+
MODEL,
|
|
2617
|
+
key
|
|
2618
|
+
], key === "settings" ? {
|
|
2619
|
+
...existing.providers?.["callstack.ai"]?.models?.[MODEL]?.settings,
|
|
2620
|
+
...value
|
|
2621
|
+
} : value])
|
|
2622
|
+
];
|
|
2501
2623
|
return [
|
|
2502
2624
|
[[
|
|
2503
2625
|
"provider",
|
|
@@ -2515,18 +2637,22 @@ async function planAssistant(assistant) {
|
|
|
2515
2637
|
"options",
|
|
2516
2638
|
"baseURL"
|
|
2517
2639
|
], BASE_URL],
|
|
2518
|
-
...storedKey ? [] : [[[
|
|
2640
|
+
...storedKey || existing.provider?.["callstack.ai"]?.options?.apiKey ? [] : [[[
|
|
2519
2641
|
"provider",
|
|
2520
2642
|
"callstack.ai",
|
|
2521
2643
|
"options",
|
|
2522
2644
|
"apiKey"
|
|
2523
2645
|
], "{env:CALLSTACK_AUTH_TOKEN}"]],
|
|
2524
|
-
[[
|
|
2646
|
+
...Object.entries(OPENCODE_MODEL).map(([key, value]) => [[
|
|
2525
2647
|
"provider",
|
|
2526
2648
|
"callstack.ai",
|
|
2527
2649
|
"models",
|
|
2528
|
-
MODEL
|
|
2529
|
-
|
|
2650
|
+
MODEL,
|
|
2651
|
+
key
|
|
2652
|
+
], key === "options" ? {
|
|
2653
|
+
...existing.provider?.["callstack.ai"]?.models?.[MODEL]?.options,
|
|
2654
|
+
...value
|
|
2655
|
+
} : value])
|
|
2530
2656
|
];
|
|
2531
2657
|
});
|
|
2532
2658
|
if (v2) changes[0].steps = ["OpenCode 2 stores provider keys itself: run /connect in OpenCode, pick callstack.ai → \"Manually enter API Key\", and paste your Callstack key."];
|
|
@@ -2557,9 +2683,14 @@ async function planAssistant(assistant) {
|
|
|
2557
2683
|
"providers",
|
|
2558
2684
|
"callstack",
|
|
2559
2685
|
"models"
|
|
2560
|
-
], models.some((model) => model.id === "callstack/Apex") ? models.map((model) => model.id === "callstack/Apex" ?
|
|
2686
|
+
], models.some((model) => model.id === "callstack/Apex") ? models.map((model) => model.id === "callstack/Apex" ? {
|
|
2687
|
+
...model,
|
|
2688
|
+
...PI_MODEL,
|
|
2689
|
+
...model.compat ? { compat: Object.fromEntries(Object.entries(model.compat).filter(([key]) => key !== "reasoningEffortMap")) } : {}
|
|
2690
|
+
} : model) : [...models, PI_MODEL]]
|
|
2561
2691
|
];
|
|
2562
2692
|
});
|
|
2693
|
+
await json("settings.json", [[["modelThinkingLevels", `callstack/${MODEL}`], "medium"]]);
|
|
2563
2694
|
break;
|
|
2564
2695
|
case "claude":
|
|
2565
2696
|
await json("settings.json", [[["env", "CLAUDE_CODE_ATTRIBUTION_HEADER"], "0"]]);
|
|
@@ -2567,7 +2698,7 @@ async function planAssistant(assistant) {
|
|
|
2567
2698
|
case "codex": {
|
|
2568
2699
|
const path = join(assistant.directory, "callstack_ai.config.toml");
|
|
2569
2700
|
const before = await readConfig(path);
|
|
2570
|
-
const after =
|
|
2701
|
+
const after = updateToml(before, {
|
|
2571
2702
|
model_provider: "callstack_ai",
|
|
2572
2703
|
model: MODEL,
|
|
2573
2704
|
model_context_window: CONTEXT_WINDOW,
|
|
@@ -2579,7 +2710,7 @@ async function planAssistant(assistant) {
|
|
|
2579
2710
|
wire_api: "responses",
|
|
2580
2711
|
requires_openai_auth: false
|
|
2581
2712
|
} }
|
|
2582
|
-
}, path);
|
|
2713
|
+
}, path, ["model_max_output_tokens", "model_auto_compact_token_limit"]);
|
|
2583
2714
|
changes.push({
|
|
2584
2715
|
path,
|
|
2585
2716
|
before,
|
|
@@ -2609,7 +2740,9 @@ function launchOptions(id, env = process.env) {
|
|
|
2609
2740
|
"--provider",
|
|
2610
2741
|
"callstack",
|
|
2611
2742
|
"--model",
|
|
2612
|
-
MODEL
|
|
2743
|
+
MODEL,
|
|
2744
|
+
"--thinking",
|
|
2745
|
+
"medium"
|
|
2613
2746
|
],
|
|
2614
2747
|
env: childEnv
|
|
2615
2748
|
};
|
|
@@ -2629,7 +2762,9 @@ function launchOptions(id, env = process.env) {
|
|
|
2629
2762
|
ANTHROPIC_DEFAULT_OPUS_MODEL: MODEL,
|
|
2630
2763
|
ANTHROPIC_DEFAULT_SONNET_MODEL: MODEL,
|
|
2631
2764
|
ANTHROPIC_DEFAULT_HAIKU_MODEL: MODEL,
|
|
2632
|
-
CLAUDE_CODE_SUBAGENT_MODEL: MODEL
|
|
2765
|
+
CLAUDE_CODE_SUBAGENT_MODEL: MODEL,
|
|
2766
|
+
CLAUDE_CODE_MAX_CONTEXT_TOKENS: String(CONTEXT_WINDOW),
|
|
2767
|
+
CLAUDE_CODE_MAX_OUTPUT_TOKENS: String(MAX_OUTPUT)
|
|
2633
2768
|
});
|
|
2634
2769
|
return {
|
|
2635
2770
|
args: ["--model", MODEL],
|
|
@@ -2663,7 +2798,11 @@ const AI_SDK_SNIPPET = [
|
|
|
2663
2798
|
` baseURL: '${BASE_URL}',`,
|
|
2664
2799
|
" apiKey: process.env.CALLSTACK_AUTH_TOKEN,",
|
|
2665
2800
|
"});",
|
|
2666
|
-
|
|
2801
|
+
"const requestOptions = {",
|
|
2802
|
+
` model: apex('${MODEL}'),`,
|
|
2803
|
+
` maxOutputTokens: ${MAX_OUTPUT},`,
|
|
2804
|
+
"};",
|
|
2805
|
+
"// Pass requestOptions with your prompt to generateText / streamText.",
|
|
2667
2806
|
`// Reasoning effort (${EFFORTS.join(", ")}):`,
|
|
2668
2807
|
"// providerOptions: { callstack: { reasoningEffort: 'medium' } }"
|
|
2669
2808
|
];
|
|
@@ -2674,11 +2813,7 @@ const MANUAL = {
|
|
|
2674
2813
|
"Keep the generated apiKey secret reference; add this object to its models array:",
|
|
2675
2814
|
...COPILOT_MODEL.split("\n")
|
|
2676
2815
|
],
|
|
2677
|
-
"ai-sdk": [
|
|
2678
|
-
"Apex CLI never writes your key into a project. Keep it in CALLSTACK_AUTH_TOKEN (for example in a .env that git ignores) and create the provider with:",
|
|
2679
|
-
...AI_SDK_SNIPPET,
|
|
2680
|
-
`Eve: set modelContextWindowTokens: ${CONTEXT_WINDOW} on defineAgent, or compaction will fail to compile.`
|
|
2681
|
-
]
|
|
2816
|
+
"ai-sdk": ["Apex CLI never writes your key into a project. Keep it in CALLSTACK_AUTH_TOKEN (for example in a .env that git ignores) and create the provider with:", ...AI_SDK_SNIPPET]
|
|
2682
2817
|
};
|
|
2683
2818
|
const MANUAL_IDS = Object.keys(MANUAL);
|
|
2684
2819
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@callstack/apex",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "Detects the AI coding assistants installed on your machine and configures them to use Callstack Apex.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"keywords": [
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
"build": "tsdown",
|
|
25
25
|
"pretest": "npm run build",
|
|
26
26
|
"prepack": "npm run build",
|
|
27
|
+
"prepublishOnly": "npm test",
|
|
27
28
|
"test": "node --test",
|
|
28
29
|
"check": "for f in src/*.js bin/apex.js; do node --check \"$f\" || exit 1; done && npm run build"
|
|
29
30
|
},
|