@wrenai/genbi 0.0.3 → 0.0.4
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
CHANGED
|
@@ -25,7 +25,7 @@ the rest:
|
|
|
25
25
|
|
|
26
26
|
## Developer preview
|
|
27
27
|
|
|
28
|
-
`@wrenai/genbi` is published at `0.0.
|
|
28
|
+
`@wrenai/genbi` is published at `0.0.4`. Nothing here is under a compatibility
|
|
29
29
|
commitment yet — commands, environment variables and interfaces move without
|
|
30
30
|
notice. The Codex runtime is supported in code but has not been exercised end
|
|
31
31
|
to end; Claude is the one that is. See
|
|
@@ -31,6 +31,16 @@ import { isWarbleSiblingCheckoutDevModeEnabled, resolveInstalledPackageBin } fro
|
|
|
31
31
|
*/
|
|
32
32
|
export async function resolveWarbleBinary(explicit) {
|
|
33
33
|
if (explicit !== undefined) {
|
|
34
|
+
// A value with no path separator is a command name, not a file path, and is
|
|
35
|
+
// resolved on PATH — the same reading the native-session preflight gives it.
|
|
36
|
+
// Requiring it to exist relative to the working directory made `"warble"` an
|
|
37
|
+
// explicit value that could never resolve, while the preflight found it and
|
|
38
|
+
// reported the producer healthy: one string, two answers.
|
|
39
|
+
if (!explicit.includes(path.sep) && !path.isAbsolute(explicit)) {
|
|
40
|
+
if (await isExecutableOnPath(explicit))
|
|
41
|
+
return explicit;
|
|
42
|
+
throw new WarbleBinaryNotFoundError([`explicit warbleBin "${explicit}" is not on PATH`]);
|
|
43
|
+
}
|
|
34
44
|
if (!existsSync(explicit)) {
|
|
35
45
|
throw new WarbleBinaryNotFoundError([`explicit warbleBin "${explicit}" does not exist`]);
|
|
36
46
|
}
|
|
@@ -105,6 +105,7 @@ import { createApp } from "./app.js";
|
|
|
105
105
|
import { recoverBootstrapProjectBinding } from "./bootstrap-project-binding.js";
|
|
106
106
|
import { createHarnessProfileSources } from "./harness-profile-sources.js";
|
|
107
107
|
import { compileProfile, compileRawProfile } from "../harness/compile/index.js";
|
|
108
|
+
import { resolveWarbleBinary } from "../harness/compile/resolve-binary.js";
|
|
108
109
|
import { toAuthChoiceFromRuntimeSettings } from "./auth-choice.js";
|
|
109
110
|
import { Store } from "./db.js";
|
|
110
111
|
import { resolveEnrichmentBinding, resolveProjectIdentity } from "./enrichment.js";
|
|
@@ -170,6 +171,22 @@ async function main() {
|
|
|
170
171
|
// (server/turn.ts) and `server/spa.ts`.
|
|
171
172
|
const candidateStaticDir = path.join(packageRoot, "dist");
|
|
172
173
|
const staticDir = existsSync(path.join(candidateStaticDir, "index.html")) ? candidateStaticDir : undefined;
|
|
174
|
+
// Resolve the Warble binary once, here, and hand the resolved path to every
|
|
175
|
+
// consumer. Passing the bare name `"warble"` looked like a harmless default and
|
|
176
|
+
// was not: `resolveWarbleBinary` treats any value it is given as an explicit
|
|
177
|
+
// path and only searches when given nothing, so that default disabled the one
|
|
178
|
+
// lookup that finds the `@warble/cli` an install actually ships. It also made
|
|
179
|
+
// two resolvers disagree about the same string — the native preflight resolves
|
|
180
|
+
// a bare name through PATH and reported the producer healthy, while every
|
|
181
|
+
// compile failed.
|
|
182
|
+
const resolvedWarbleBin = await resolveWarbleBinary(flags.warbleBin).catch((error) => {
|
|
183
|
+
// Not fatal: the app still starts, and readiness reports the reason per
|
|
184
|
+
// vendor rather than the process dying at boot over a feature the user may
|
|
185
|
+
// not reach.
|
|
186
|
+
process.stderr.write(`warning: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
187
|
+
return undefined;
|
|
188
|
+
});
|
|
189
|
+
const warbleBinOption = resolvedWarbleBin !== undefined ? { warbleBin: resolvedWarbleBin } : {};
|
|
173
190
|
const profileSource = flags.profile ?? resolveDefaultProfileSource();
|
|
174
191
|
// Frozen at boot: GET /api/harness accepts only a purpose and must never
|
|
175
192
|
// inherit a caller-supplied RouteOptions.profileSource.
|
|
@@ -459,7 +476,7 @@ async function main() {
|
|
|
459
476
|
binding,
|
|
460
477
|
artifactRoot,
|
|
461
478
|
materializationState: nativeMaterializationState,
|
|
462
|
-
materialize: () => dispatchInteractiveArtifacts({ warbleBin:
|
|
479
|
+
materialize: () => dispatchInteractiveArtifacts({ warbleBin: resolvedWarbleBin ?? "warble", irPath: enrichIrPath, target, cwd: artifactRoot, boundProject: binding.path, materializationState: nativeMaterializationState }),
|
|
463
480
|
}, { getCurrentBinding: currentInteractiveBinding });
|
|
464
481
|
}
|
|
465
482
|
const nativeMcpUrl = `http://127.0.0.1:${port}/api/native-sessions/mcp`;
|
|
@@ -489,11 +506,13 @@ async function main() {
|
|
|
489
506
|
resolveDispatchIr: async (purpose, binding) => {
|
|
490
507
|
const profileSource = harnessProfileSources[purpose];
|
|
491
508
|
const compiled = purpose === "setup" || binding === undefined
|
|
492
|
-
? await compileRawProfile({ profileSource, mode: "native",
|
|
493
|
-
: await compileProfile({ profileSource, userProject: binding.path, mode: "native",
|
|
509
|
+
? await compileRawProfile({ profileSource, mode: "native", ...warbleBinOption })
|
|
510
|
+
: await compileProfile({ profileSource, userProject: binding.path, mode: "native", ...warbleBinOption });
|
|
494
511
|
return compiled.irPath;
|
|
495
512
|
},
|
|
496
|
-
|
|
513
|
+
// The service's option is a required string; when resolution failed the bare
|
|
514
|
+
// name is what the preflight will report as unresolvable, with its reason.
|
|
515
|
+
warbleBin: resolvedWarbleBin ?? "warble",
|
|
497
516
|
...(process.env["WREN_HARNESS_WREN_SHIM"] !== undefined ? { wrenShim: process.env["WREN_HARNESS_WREN_SHIM"] } : {}),
|
|
498
517
|
terminalHostAvailable: async () => {
|
|
499
518
|
try {
|
|
@@ -7,6 +7,7 @@ import { execFileSync, spawn } from "node:child_process";
|
|
|
7
7
|
import { accessSync, chmodSync, constants, existsSync, lstatSync, mkdirSync, mkdtempSync, readFileSync, realpathSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
8
8
|
import os from "node:os";
|
|
9
9
|
import path from "node:path";
|
|
10
|
+
import { WarbleBinaryNotFoundError } from "../harness/compile/errors.js";
|
|
10
11
|
import { InteractiveLaunchError, NO_INTERACTIVE_TERMINAL_LEASES, interactiveExecutableAvailable } from "./interactive-terminal.js";
|
|
11
12
|
import { newId } from "./db.js";
|
|
12
13
|
import { NATIVE_MCP_CREDENTIAL_ENV_VAR } from "./native-artifacts.js";
|
|
@@ -39,11 +40,13 @@ const CODEX_NATIVE_PERMISSION_HEADER = "[permissions.warble_native_wren.filesyst
|
|
|
39
40
|
const PROVIDER_SESSION_UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
40
41
|
const CODEX_RESUME_HANDLE_FILE = path.join(".warble", "codex-thread-id");
|
|
41
42
|
function logNativeLaunchFailure(purpose, vendor, phase, error) {
|
|
42
|
-
const
|
|
43
|
-
//
|
|
44
|
-
//
|
|
45
|
-
//
|
|
46
|
-
|
|
43
|
+
const rejected = error instanceof InteractiveLaunchError;
|
|
44
|
+
// Exception text, paths, credentials and argv stay out of the log for an
|
|
45
|
+
// unexpected error, which may carry any of them. A rejection carries a
|
|
46
|
+
// sentence authored here, and suppressing that turned every diagnosis into a
|
|
47
|
+
// guess: an operator saw a phase and a category and no cause.
|
|
48
|
+
const detail = rejected ? ` reason=${error.message}` : "";
|
|
49
|
+
console.error(`[native-sessions] launch failed purpose=${purpose} vendor=${vendor} phase=${phase} category=${rejected ? "rejected" : "unexpected"}${detail}`);
|
|
47
50
|
}
|
|
48
51
|
/**
|
|
49
52
|
* The producer deliberately sees only a sealed binding identity, never a caller-supplied path.
|
|
@@ -352,6 +355,16 @@ export function nativeSessionLaunchFailure(error) {
|
|
|
352
355
|
return "native session launch artifacts are unavailable";
|
|
353
356
|
if (message === "native session launch paths are unavailable" || message === "native session launch paths are outside its server-owned scope")
|
|
354
357
|
return "native session launch artifacts are unavailable";
|
|
358
|
+
// Every InteractiveLaunchError message is authored in this file: a fixed
|
|
359
|
+
// sentence, a fixed profile name, or a reason readiness already publishes.
|
|
360
|
+
// None is built from a path, argv, or process output. Falling through to the
|
|
361
|
+
// generic string threw away the cause of eighteen distinct failures, which is
|
|
362
|
+
// what left "native session launch failed" as the only thing a user could see.
|
|
363
|
+
if (error instanceof InteractiveLaunchError)
|
|
364
|
+
return message;
|
|
365
|
+
// This one is NOT safe to forward: its text embeds the configured binary path.
|
|
366
|
+
if (error instanceof WarbleBinaryNotFoundError)
|
|
367
|
+
return "the Warble binary could not be resolved";
|
|
355
368
|
return "native session launch failed";
|
|
356
369
|
}
|
|
357
370
|
const NATIVE_PRODUCER_CATEGORY = "native_session_producer_incompatible";
|
|
@@ -1310,9 +1323,20 @@ export class NativeSessionService {
|
|
|
1310
1323
|
// Compile for this binding rather than dispatching the profile's golden.
|
|
1311
1324
|
// Falls back to the configured path only where no resolver is wired (the
|
|
1312
1325
|
// fixture-mode tests), never silently in production — see `bin.ts`.
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1326
|
+
// Compiling for this binding runs before the launch try/catch below, so a
|
|
1327
|
+
// failure here reached the HTTP route unlogged and unclassified — the case
|
|
1328
|
+
// where the server printed nothing at all and the browser said only "native
|
|
1329
|
+
// session launch failed".
|
|
1330
|
+
let irPath;
|
|
1331
|
+
try {
|
|
1332
|
+
irPath = this.options.resolveDispatchIr === undefined
|
|
1333
|
+
? configuredIr
|
|
1334
|
+
: await this.options.resolveDispatchIr(purpose, binding);
|
|
1335
|
+
}
|
|
1336
|
+
catch (error) {
|
|
1337
|
+
logNativeLaunchFailure(purpose, dispatchDefinition.provider, "dispatch_ir", error);
|
|
1338
|
+
throw error;
|
|
1339
|
+
}
|
|
1316
1340
|
const producer = this.legacyFixtureMode() ? undefined : await this.productionProducerPreflight();
|
|
1317
1341
|
const launchProducer = producer ? producer.vendors[dispatchDefinition.provider] : undefined;
|
|
1318
1342
|
if (producer && (!launchProducer?.available || !producer.producer)) {
|