@callstack/apex 0.4.4 → 0.4.5
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 +6 -4
- package/dist/cli.js +26 -15
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -234,10 +234,12 @@ Other launchers: `apex run opencode`, `apex run claude`, `apex run pi`, `apex ru
|
|
|
234
234
|
Launchers pass extra arguments through unchanged (without a shell), can be overridden by explicit
|
|
235
235
|
user arguments, and never run `init`. `apex run claude` sets the gateway URL, token, attribution
|
|
236
236
|
flag and model aliases in the child process only, leaving your default Claude provider alone.
|
|
237
|
-
`apex run opencode`
|
|
238
|
-
|
|
239
|
-
`
|
|
240
|
-
the
|
|
237
|
+
`apex run opencode` asks the installed binary which interface it has (`--standalone` exists only on
|
|
238
|
+
OpenCode 2; its version number says nothing, because dev and beta builds of both generations report
|
|
239
|
+
`0.0.0-*`): OpenCode 1 gets `--model`; OpenCode 2, whose terminal interface has no `--model`, starts
|
|
240
|
+
with `--standalone` and the model in `OPENCODE_CONFIG_CONTENT`, so the private server sees the
|
|
241
|
+
model and, for a config that references the key variable, your key too. A binary that cannot be
|
|
242
|
+
asked launches with neither flag, on your own configuration, and says so.
|
|
241
243
|
|
|
242
244
|
## Safety and recovery
|
|
243
245
|
|
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { isDeepStrictEqual, parseArgs, styleText } from "node:util";
|
|
2
|
+
import { isDeepStrictEqual, parseArgs, promisify, styleText } from "node:util";
|
|
3
3
|
import { execFile, spawn } from "node:child_process";
|
|
4
4
|
import { access, lstat, mkdir, open, readFile, rename, stat, unlink } from "node:fs/promises";
|
|
5
5
|
import { basename, delimiter, dirname, join, parse, resolve } from "node:path";
|
|
@@ -2602,14 +2602,15 @@ async function executable(command, env = process.env, platform = process.platfor
|
|
|
2602
2602
|
}
|
|
2603
2603
|
return null;
|
|
2604
2604
|
}
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2605
|
+
const execFileAsync = promisify(execFile);
|
|
2606
|
+
async function openCodeSupportsStandalone(binary) {
|
|
2607
|
+
if (!binary) return null;
|
|
2608
|
+
try {
|
|
2609
|
+
const { stdout, stderr } = await execFileAsync(binary, ["--help"], { timeout: 5e3 });
|
|
2610
|
+
return `${stdout}${stderr}`.includes("--standalone");
|
|
2611
|
+
} catch (error) {
|
|
2612
|
+
return `${error.stdout}${error.stderr}`.includes("--standalone") ? true : null;
|
|
2613
|
+
}
|
|
2613
2614
|
}
|
|
2614
2615
|
function locations(home = homedir(), env = process.env, platform = process.platform) {
|
|
2615
2616
|
const config = env.XDG_CONFIG_HOME || join(home, ".config");
|
|
@@ -2851,14 +2852,20 @@ function launchToken(env, provider) {
|
|
|
2851
2852
|
if (!token?.trim()) throw new Error(`Set ${provider.envVar} in your environment before launching with ${provider.name}.`);
|
|
2852
2853
|
return token;
|
|
2853
2854
|
}
|
|
2854
|
-
function launchOptions(id, env = process.env, provider = defaultProvider(env), {
|
|
2855
|
+
function launchOptions(id, env = process.env, provider = defaultProvider(env), { openCodeStandalone = false } = {}) {
|
|
2855
2856
|
const { model } = provider;
|
|
2856
2857
|
const token = launchToken(env, provider);
|
|
2857
2858
|
const childEnv = { ...env };
|
|
2858
2859
|
switch (id) {
|
|
2859
2860
|
case "opencode": {
|
|
2860
2861
|
const selected = `${provider.opencode}/${model}`;
|
|
2861
|
-
if (
|
|
2862
|
+
if (openCodeStandalone === null) return {
|
|
2863
|
+
args: [],
|
|
2864
|
+
env: childEnv,
|
|
2865
|
+
note: "(OpenCode interface unknown: no model flag added)",
|
|
2866
|
+
warning: "Apex CLI: Could not ask which OpenCode interface is installed, so it launches without a model flag. OpenCode 1 takes --model, OpenCode 2 takes --standalone; opencode --help says which you have."
|
|
2867
|
+
};
|
|
2868
|
+
if (!openCodeStandalone) return {
|
|
2862
2869
|
args: ["--model", selected],
|
|
2863
2870
|
env: childEnv
|
|
2864
2871
|
};
|
|
@@ -2919,7 +2926,7 @@ function launchOptions(id, env = process.env, provider = defaultProvider(env), {
|
|
|
2919
2926
|
}
|
|
2920
2927
|
function runExpansion(id, provider, installed = {}) {
|
|
2921
2928
|
const { args, note } = launchOptions(id, { [provider.envVar]: "placeholder" }, provider, installed);
|
|
2922
|
-
return [
|
|
2929
|
+
return [[id, ...args].join(" "), note].filter(Boolean).join(" ");
|
|
2923
2930
|
}
|
|
2924
2931
|
const copilotModel = (provider) => JSON.stringify({
|
|
2925
2932
|
id: provider.model,
|
|
@@ -4998,10 +5005,12 @@ async function commandInit(rest) {
|
|
|
4998
5005
|
dim("Apex CLI never reads, stores or logs the key itself.")
|
|
4999
5006
|
]);
|
|
5000
5007
|
const runnable = active.map((entry) => entry.id).filter((id) => RUNNABLE.includes(id));
|
|
5001
|
-
const
|
|
5008
|
+
const opencodeBinary = active.find((entry) => entry.id === "opencode")?.binary;
|
|
5009
|
+
const probed = opencodeBinary ? await openCodeSupportsStandalone(opencodeBinary) : void 0;
|
|
5010
|
+
const installed = { openCodeStandalone: probed };
|
|
5002
5011
|
const rows = runnable.map((id) => ({
|
|
5003
5012
|
command: `${apex} run ${id}`,
|
|
5004
|
-
expansion: runExpansion(id, provider, installed)
|
|
5013
|
+
expansion: id === "opencode" && probed === void 0 ? id : runExpansion(id, provider, installed)
|
|
5005
5014
|
}));
|
|
5006
5015
|
const commandWidth = columnWidth(rows.map((row) => row.command));
|
|
5007
5016
|
section(runnable.length ? `Use these commands to run ${provider.model} with your selected harnesses:` : `Use ${provider.model} with your assistant:`, [
|
|
@@ -5195,7 +5204,9 @@ async function commandRun(rest) {
|
|
|
5195
5204
|
const binary = await executable(id);
|
|
5196
5205
|
if (!binary) throw new Error(`${id} was not found on PATH. Install it first, then run ${APEX} init.`);
|
|
5197
5206
|
if (process.platform === "win32" && /\.(cmd|bat)$/i.test(binary)) throw new Error("Windows .cmd/.bat launchers are not executed through a shell. Use WSL or launch the configured assistant directly.");
|
|
5198
|
-
const
|
|
5207
|
+
const standalone = id === "opencode" ? await openCodeSupportsStandalone(binary) : false;
|
|
5208
|
+
const options = launchOptions(id, process.env, provider, { openCodeStandalone: standalone });
|
|
5209
|
+
if (options.warning) console.error(styleText("yellow", options.warning));
|
|
5199
5210
|
const args = passed[0] === "--" ? passed.slice(1) : passed;
|
|
5200
5211
|
const child = spawn(binary, await launchArgs(options, args), {
|
|
5201
5212
|
env: options.env,
|