ai-whisper 0.5.0 → 0.5.1

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.
@@ -6894,11 +6894,387 @@ function createCodexLiveSession(input) {
6894
6894
  };
6895
6895
  }
6896
6896
 
6897
- // ../adapter-ai-ezio/dist/create-ai-ezio-provider.js
6898
- import { TurnError, EngineExitedError } from "@ai-ezio/harness";
6897
+ // ../../node_modules/.pnpm/@ai-ezio+harness@file+..+ai-ezio+packages+harness/node_modules/@ai-ezio/harness/dist/resolve-hax.js
6898
+ import { existsSync as existsSync5 } from "node:fs";
6899
+ import { createRequire as createRequire3 } from "node:module";
6900
+ import { dirname as dirname2, join as join7 } from "node:path";
6901
+ import { fileURLToPath } from "node:url";
6902
+ var HaxBinaryNotFoundError = class extends Error {
6903
+ constructor(message) {
6904
+ super(message);
6905
+ this.name = "HaxBinaryNotFoundError";
6906
+ }
6907
+ };
6908
+ function platformPackageName(platform, arch) {
6909
+ return `@ai-ezio/hax-${platform}-${arch}`;
6910
+ }
6911
+ function defaultResolvePackageJson(specifier) {
6912
+ const require4 = createRequire3(import.meta.url);
6913
+ return require4.resolve(specifier);
6914
+ }
6915
+ function findDevRoot() {
6916
+ let dir = dirname2(fileURLToPath(import.meta.url));
6917
+ for (let i = 0; i < 12; i++) {
6918
+ if (existsSync5(join7(dir, "vendor", "hax", "build", "hax"))) {
6919
+ return dir;
6920
+ }
6921
+ const parent = dirname2(dir);
6922
+ if (parent === dir)
6923
+ break;
6924
+ dir = parent;
6925
+ }
6926
+ return void 0;
6927
+ }
6928
+ function describeHaxBinary(options = {}) {
6929
+ const env = options.env ?? process.env;
6930
+ const platform = options.platform ?? process.platform;
6931
+ const arch = options.arch ?? process.arch;
6932
+ const fileExists = options.fileExists ?? existsSync5;
6933
+ const resolvePackageJson = options.resolvePackageJson ?? defaultResolvePackageJson;
6934
+ const attempts = [];
6935
+ const override = env.AI_EZIO_HAX_BIN;
6936
+ if (override !== void 0 && override !== "") {
6937
+ if (fileExists(override)) {
6938
+ attempts.push(`AI_EZIO_HAX_BIN=${override} (exists)`);
6939
+ return { ok: true, path: override, source: "env-override", attempts };
6940
+ }
6941
+ attempts.push(`AI_EZIO_HAX_BIN=${override} (missing)`);
6942
+ return {
6943
+ ok: false,
6944
+ attempts,
6945
+ error: `AI_EZIO_HAX_BIN is set to "${override}" but no file exists there.`
6946
+ };
6947
+ }
6948
+ attempts.push("AI_EZIO_HAX_BIN (unset)");
6949
+ const pkg = platformPackageName(platform, arch);
6950
+ try {
6951
+ const pkgJson = resolvePackageJson(`${pkg}/package.json`);
6952
+ const bin = join7(dirname2(pkgJson), "bin", "hax");
6953
+ if (fileExists(bin)) {
6954
+ attempts.push(`${pkg} (found ${bin})`);
6955
+ return { ok: true, path: bin, source: "platform-package", attempts };
6956
+ }
6957
+ attempts.push(`${pkg} (resolved, but ${bin} missing)`);
6958
+ } catch {
6959
+ attempts.push(`${pkg} (not installed)`);
6960
+ }
6961
+ const devRoot = "devRoot" in options ? options.devRoot : findDevRoot();
6962
+ if (devRoot !== void 0) {
6963
+ const devBin = join7(devRoot, "vendor", "hax", "build", "hax");
6964
+ if (fileExists(devBin)) {
6965
+ attempts.push(`${devBin} (dev fallback)`);
6966
+ return { ok: true, path: devBin, source: "dev-fallback", attempts };
6967
+ }
6968
+ attempts.push(`${devBin} (dev fallback missing)`);
6969
+ } else {
6970
+ attempts.push("vendor/hax/build/hax (no dev root)");
6971
+ }
6972
+ return {
6973
+ ok: false,
6974
+ attempts,
6975
+ error: `Could not locate the hax binary. Tried: ${attempts.join("; ")}.`
6976
+ };
6977
+ }
6978
+ function resolveHaxBinary(options = {}) {
6979
+ const result = describeHaxBinary(options);
6980
+ if (result.ok && result.path !== void 0)
6981
+ return result.path;
6982
+ throw new HaxBinaryNotFoundError(`${result.error} Run "ai-ezio doctor" for help.`);
6983
+ }
6984
+
6985
+ // ../../node_modules/.pnpm/@ai-ezio+harness@file+..+ai-ezio+packages+harness/node_modules/@ai-ezio/harness/dist/spawn.js
6986
+ import { spawn as spawn5 } from "node:child_process";
6987
+
6988
+ // ../../node_modules/.pnpm/@ai-ezio+harness@file+..+ai-ezio+packages+harness/node_modules/@ai-ezio/harness/dist/skills-dir.js
6989
+ import { homedir } from "node:os";
6990
+ import { join as join8 } from "node:path";
6991
+ function aiEzioGlobalSkillsDir(env = process.env) {
6992
+ const base = env.XDG_CONFIG_HOME && env.XDG_CONFIG_HOME !== "" ? env.XDG_CONFIG_HOME : join8(homedir(), ".config");
6993
+ return join8(base, "ai-ezio", "skills");
6994
+ }
6995
+
6996
+ // ../../node_modules/.pnpm/@ai-ezio+harness@file+..+ai-ezio+packages+harness/node_modules/@ai-ezio/harness/dist/spawn.js
6997
+ function haxSpawnArgs(extra = []) {
6998
+ return ["--protocol-fd=3", "--control-fd=4", "--mount-mode", ...extra];
6999
+ }
7000
+ function haxSpawnEnv(base = process.env) {
7001
+ return { ...base, HAX_EXTRA_SKILLS_DIR: aiEzioGlobalSkillsDir(base) };
7002
+ }
7003
+ function spawnHax(options = {}) {
7004
+ const binary = options.binary ?? resolveHaxBinary();
7005
+ const child = spawn5(binary, haxSpawnArgs(options.args), {
7006
+ // 0,1,2 ignored; 3 = events (hax writes), 4 = controls (hax reads).
7007
+ stdio: ["ignore", "ignore", "ignore", "pipe", "pipe"],
7008
+ env: haxSpawnEnv(options.env ?? process.env)
7009
+ });
7010
+ const eventStream = child.stdio[3];
7011
+ const controlStream = child.stdio[4];
7012
+ return { child, eventStream, controlStream };
7013
+ }
7014
+
7015
+ // ../../node_modules/.pnpm/@ai-ezio+protocol@file+..+ai-ezio+packages+protocol/node_modules/@ai-ezio/protocol/dist/codec.js
7016
+ import { StringDecoder } from "node:string_decoder";
7017
+ var MalformedLineError = class extends Error {
7018
+ line;
7019
+ constructor(line) {
7020
+ super(`malformed JSONL line: ${JSON.stringify(line)}`);
7021
+ this.line = line;
7022
+ this.name = "MalformedLineError";
7023
+ }
7024
+ };
7025
+ function encodeControl(control) {
7026
+ return `${JSON.stringify(control)}
7027
+ `;
7028
+ }
7029
+ var JsonlDecoder = class {
7030
+ buffer = "";
7031
+ // fd-3 yields raw Buffer chunks at arbitrary boundaries. StringDecoder holds
7032
+ // back the trailing bytes of a multibyte UTF-8 codepoint until the rest
7033
+ // arrives, so a char split across reads (em-dash, bullet, smart quote, box
7034
+ // chars) never decodes to `�`. Decoding a chunk in isolation does NOT.
7035
+ utf8 = new StringDecoder("utf8");
7036
+ /**
7037
+ * Append a chunk and return every complete event it produced. A trailing
7038
+ * partial line — or a partial multibyte char — is retained until the rest
7039
+ * arrives. Throws MalformedLineError on a complete-but-unparseable line (the
7040
+ * buffer past it is preserved so decoding can continue after the caller
7041
+ * handles it).
7042
+ */
7043
+ push(chunk) {
7044
+ this.buffer += typeof chunk === "string" ? chunk : this.utf8.write(Buffer.from(chunk));
7045
+ const events = [];
7046
+ let nl = this.buffer.indexOf("\n");
7047
+ while (nl >= 0) {
7048
+ const line = this.buffer.slice(0, nl);
7049
+ this.buffer = this.buffer.slice(nl + 1);
7050
+ const trimmed = line.trim();
7051
+ if (trimmed.length > 0) {
7052
+ let parsed;
7053
+ try {
7054
+ parsed = JSON.parse(trimmed);
7055
+ } catch {
7056
+ throw new MalformedLineError(line);
7057
+ }
7058
+ events.push(parsed);
7059
+ }
7060
+ nl = this.buffer.indexOf("\n");
7061
+ }
7062
+ return events;
7063
+ }
7064
+ /** Bytes buffered but not yet terminated by a newline. */
7065
+ get pending() {
7066
+ return this.buffer;
7067
+ }
7068
+ };
7069
+
7070
+ // ../../node_modules/.pnpm/@ai-ezio+protocol@file+..+ai-ezio+packages+protocol/node_modules/@ai-ezio/protocol/dist/transport-fd.js
7071
+ var FdTransport = class {
7072
+ eventStream;
7073
+ controlStream;
7074
+ decoder = new JsonlDecoder();
7075
+ constructor(eventStream, controlStream) {
7076
+ this.eventStream = eventStream;
7077
+ this.controlStream = controlStream;
7078
+ }
7079
+ async *events() {
7080
+ for await (const chunk of this.eventStream) {
7081
+ for (const event of this.decoder.push(chunk)) {
7082
+ yield event;
7083
+ }
7084
+ }
7085
+ }
7086
+ send(control) {
7087
+ this.controlStream.write(encodeControl(control));
7088
+ }
7089
+ close() {
7090
+ this.controlStream.end();
7091
+ }
7092
+ };
7093
+
7094
+ // ../../node_modules/.pnpm/@ai-ezio+protocol@file+..+ai-ezio+packages+protocol/node_modules/@ai-ezio/protocol/dist/index.js
7095
+ var PROTOCOL_VERSION = "0.1.0";
7096
+ function semverMajor(version) {
7097
+ const major = Number.parseInt(version.split(".", 1)[0] ?? "", 10);
7098
+ if (Number.isNaN(major)) {
7099
+ throw new Error(`Invalid semver version string: "${version}"`);
7100
+ }
7101
+ return major;
7102
+ }
7103
+ function isProtocolCompatible(theirs, ours = PROTOCOL_VERSION) {
7104
+ return semverMajor(theirs) === semverMajor(ours);
7105
+ }
7106
+
7107
+ // ../../node_modules/.pnpm/@ai-ezio+harness@file+..+ai-ezio+packages+harness/node_modules/@ai-ezio/harness/dist/session.js
7108
+ var ProtocolVersionError = class extends Error {
7109
+ constructor(theirs, ours) {
7110
+ super(`unsupported engine protocol ${theirs} (harness speaks ${ours})`);
7111
+ this.name = "ProtocolVersionError";
7112
+ }
7113
+ };
7114
+ var TurnError = class extends Error {
7115
+ turnId;
7116
+ constructor(message, turnId) {
7117
+ super(message);
7118
+ this.turnId = turnId;
7119
+ this.name = "TurnError";
7120
+ }
7121
+ };
7122
+ var EngineExitedError = class extends Error {
7123
+ constructor(message = "engine exited (fd-3 EOF)") {
7124
+ super(message);
7125
+ this.name = "EngineExitedError";
7126
+ }
7127
+ };
7128
+ var Session = class {
7129
+ options;
7130
+ spawned;
7131
+ transport;
7132
+ queue = [];
7133
+ waiters = [];
7134
+ ended = false;
7135
+ closed = false;
7136
+ exitHandlers = [];
7137
+ ready;
7138
+ constructor(options = {}) {
7139
+ this.options = options;
7140
+ }
7141
+ /** Subscribe to engine child-exit (workflow-agnostic lifecycle signal for
7142
+ * adapters that surface provider exit). Fires once per child exit. */
7143
+ onExit(handler) {
7144
+ this.exitHandlers.push(handler);
7145
+ }
7146
+ deliver(event) {
7147
+ if (event && this.options.onEvent)
7148
+ this.options.onEvent(event);
7149
+ const w = this.waiters.shift();
7150
+ if (w)
7151
+ w(event);
7152
+ else if (event)
7153
+ this.queue.push(event);
7154
+ }
7155
+ next() {
7156
+ const queued = this.queue.shift();
7157
+ if (queued)
7158
+ return Promise.resolve(queued);
7159
+ if (this.ended)
7160
+ return Promise.resolve(null);
7161
+ return new Promise((resolve2) => this.waiters.push(resolve2));
7162
+ }
7163
+ /** Consume events until one of the given type arrives. Fatal EOF →
7164
+ * EngineExitedError; a turn-scoped `error` → TurnError. */
7165
+ async waitForEvent(type) {
7166
+ for (; ; ) {
7167
+ const e = await this.next();
7168
+ if (e === null)
7169
+ throw new EngineExitedError(`engine exited before "${type}"`);
7170
+ if (e.type === "error" && type !== "error") {
7171
+ throw new TurnError(e.message, e.turnId);
7172
+ }
7173
+ if (e.type === type)
7174
+ return e;
7175
+ }
7176
+ }
7177
+ /** Spawn hax, pump events, and gate on the `ready` protocol version. */
7178
+ async start(options = {}) {
7179
+ const spawned = spawnHax(options);
7180
+ this.spawned = spawned;
7181
+ spawned.child.on("exit", (code, signal) => {
7182
+ for (const handler of this.exitHandlers)
7183
+ handler({ code, signal });
7184
+ });
7185
+ const transport = new FdTransport(spawned.eventStream, spawned.controlStream);
7186
+ this.transport = transport;
7187
+ void (async () => {
7188
+ try {
7189
+ for await (const event of transport.events())
7190
+ this.deliver(event);
7191
+ } finally {
7192
+ this.ended = true;
7193
+ while (this.waiters.length)
7194
+ this.deliver(null);
7195
+ }
7196
+ })();
7197
+ const ready = await this.waitForEvent("ready");
7198
+ if (!isProtocolCompatible(ready.protocol, PROTOCOL_VERSION)) {
7199
+ this.close();
7200
+ throw new ProtocolVersionError(ready.protocol, PROTOCOL_VERSION);
7201
+ }
7202
+ this.ready = ready;
7203
+ return ready;
7204
+ }
7205
+ control(control) {
7206
+ if (!this.transport)
7207
+ throw new Error("session not started");
7208
+ this.transport.send(control);
7209
+ }
7210
+ /** Send a user turn without waiting (pair with waitForEvent/interrupt). */
7211
+ submit(text) {
7212
+ this.control({ type: "submit", text });
7213
+ }
7214
+ /**
7215
+ * Submit a user turn and resolve with its authoritative content at idle.
7216
+ * A turn-scoped `error` is captured and the loop **drains to `idle`** (so the
7217
+ * session settles at a clean boundary and a later submit works), then rejects
7218
+ * with TurnError. A fatal fd-3 EOF mid-turn rejects with EngineExitedError.
7219
+ */
7220
+ async submitAndWait(text) {
7221
+ this.control({ type: "submit", text });
7222
+ let result;
7223
+ let turnError;
7224
+ for (; ; ) {
7225
+ const e = await this.next();
7226
+ if (e === null)
7227
+ throw new EngineExitedError("engine exited mid-turn");
7228
+ if (e.type === "assistant_turn_finished") {
7229
+ result = { turnId: e.turnId, content: e.content };
7230
+ } else if (e.type === "error") {
7231
+ turnError = new TurnError(e.message, e.turnId);
7232
+ } else if (e.type === "idle") {
7233
+ if (turnError)
7234
+ throw turnError;
7235
+ return result ?? { turnId: "", content: "" };
7236
+ }
7237
+ }
7238
+ }
7239
+ /** Cancel the in-flight turn. */
7240
+ interrupt() {
7241
+ this.control({ type: "interrupt" });
7242
+ }
7243
+ /** Re-fetch the last handback without re-running a turn (no clipboard).
7244
+ * Resolves the re-emitted content; rejects TurnError if no prior response. */
7245
+ async copyLastResponse() {
7246
+ this.control({ type: "copy_last_response" });
7247
+ const e = await this.waitForEvent("assistant_turn_finished");
7248
+ if (e.type !== "assistant_turn_finished")
7249
+ throw new Error("unexpected event");
7250
+ return { turnId: e.turnId, content: e.content };
7251
+ }
7252
+ /** Start a fresh conversation; resolves once the engine is idle again. */
7253
+ async newConversation() {
7254
+ this.control({ type: "new_conversation" });
7255
+ await this.waitForEvent("idle");
7256
+ }
7257
+ /** Request an engine/session status event. */
7258
+ async status() {
7259
+ this.control({ type: "status" });
7260
+ return await this.waitForEvent("status");
7261
+ }
7262
+ /** Close the control channel (shuts the engine down) and stop the child.
7263
+ * Idempotent — safe to call from both the version-gate teardown and the
7264
+ * caller. */
7265
+ close() {
7266
+ if (this.closed)
7267
+ return;
7268
+ this.closed = true;
7269
+ try {
7270
+ this.transport?.close();
7271
+ } catch {
7272
+ }
7273
+ this.spawned?.child.kill();
7274
+ }
7275
+ };
6899
7276
 
6900
7277
  // ../adapter-ai-ezio/dist/ai-ezio-engine.js
6901
- import { Session } from "@ai-ezio/harness";
6902
7278
  var defaultCreateEngineSession = ({ onEvent }) => new Session({ onEvent });
6903
7279
 
6904
7280
  // ../adapter-ai-ezio/dist/ai-ezio-prompt.js
@@ -9268,10 +9268,388 @@ function createCodexLiveSession(input) {
9268
9268
 
9269
9269
  // ../adapter-ai-ezio/dist/create-ai-ezio-provider.js
9270
9270
  init_dist();
9271
- import { TurnError, EngineExitedError } from "@ai-ezio/harness";
9271
+
9272
+ // ../../node_modules/.pnpm/@ai-ezio+harness@file+..+ai-ezio+packages+harness/node_modules/@ai-ezio/harness/dist/resolve-hax.js
9273
+ import { existsSync as existsSync7 } from "node:fs";
9274
+ import { createRequire as createRequire3 } from "node:module";
9275
+ import { dirname as dirname3, join as join7 } from "node:path";
9276
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
9277
+ var HaxBinaryNotFoundError = class extends Error {
9278
+ constructor(message) {
9279
+ super(message);
9280
+ this.name = "HaxBinaryNotFoundError";
9281
+ }
9282
+ };
9283
+ function platformPackageName(platform, arch) {
9284
+ return `@ai-ezio/hax-${platform}-${arch}`;
9285
+ }
9286
+ function defaultResolvePackageJson(specifier) {
9287
+ const require4 = createRequire3(import.meta.url);
9288
+ return require4.resolve(specifier);
9289
+ }
9290
+ function findDevRoot() {
9291
+ let dir = dirname3(fileURLToPath2(import.meta.url));
9292
+ for (let i = 0; i < 12; i++) {
9293
+ if (existsSync7(join7(dir, "vendor", "hax", "build", "hax"))) {
9294
+ return dir;
9295
+ }
9296
+ const parent = dirname3(dir);
9297
+ if (parent === dir)
9298
+ break;
9299
+ dir = parent;
9300
+ }
9301
+ return void 0;
9302
+ }
9303
+ function describeHaxBinary(options = {}) {
9304
+ const env = options.env ?? process.env;
9305
+ const platform = options.platform ?? process.platform;
9306
+ const arch = options.arch ?? process.arch;
9307
+ const fileExists = options.fileExists ?? existsSync7;
9308
+ const resolvePackageJson = options.resolvePackageJson ?? defaultResolvePackageJson;
9309
+ const attempts = [];
9310
+ const override = env.AI_EZIO_HAX_BIN;
9311
+ if (override !== void 0 && override !== "") {
9312
+ if (fileExists(override)) {
9313
+ attempts.push(`AI_EZIO_HAX_BIN=${override} (exists)`);
9314
+ return { ok: true, path: override, source: "env-override", attempts };
9315
+ }
9316
+ attempts.push(`AI_EZIO_HAX_BIN=${override} (missing)`);
9317
+ return {
9318
+ ok: false,
9319
+ attempts,
9320
+ error: `AI_EZIO_HAX_BIN is set to "${override}" but no file exists there.`
9321
+ };
9322
+ }
9323
+ attempts.push("AI_EZIO_HAX_BIN (unset)");
9324
+ const pkg = platformPackageName(platform, arch);
9325
+ try {
9326
+ const pkgJson = resolvePackageJson(`${pkg}/package.json`);
9327
+ const bin = join7(dirname3(pkgJson), "bin", "hax");
9328
+ if (fileExists(bin)) {
9329
+ attempts.push(`${pkg} (found ${bin})`);
9330
+ return { ok: true, path: bin, source: "platform-package", attempts };
9331
+ }
9332
+ attempts.push(`${pkg} (resolved, but ${bin} missing)`);
9333
+ } catch {
9334
+ attempts.push(`${pkg} (not installed)`);
9335
+ }
9336
+ const devRoot = "devRoot" in options ? options.devRoot : findDevRoot();
9337
+ if (devRoot !== void 0) {
9338
+ const devBin = join7(devRoot, "vendor", "hax", "build", "hax");
9339
+ if (fileExists(devBin)) {
9340
+ attempts.push(`${devBin} (dev fallback)`);
9341
+ return { ok: true, path: devBin, source: "dev-fallback", attempts };
9342
+ }
9343
+ attempts.push(`${devBin} (dev fallback missing)`);
9344
+ } else {
9345
+ attempts.push("vendor/hax/build/hax (no dev root)");
9346
+ }
9347
+ return {
9348
+ ok: false,
9349
+ attempts,
9350
+ error: `Could not locate the hax binary. Tried: ${attempts.join("; ")}.`
9351
+ };
9352
+ }
9353
+ function resolveHaxBinary(options = {}) {
9354
+ const result = describeHaxBinary(options);
9355
+ if (result.ok && result.path !== void 0)
9356
+ return result.path;
9357
+ throw new HaxBinaryNotFoundError(`${result.error} Run "ai-ezio doctor" for help.`);
9358
+ }
9359
+
9360
+ // ../../node_modules/.pnpm/@ai-ezio+harness@file+..+ai-ezio+packages+harness/node_modules/@ai-ezio/harness/dist/spawn.js
9361
+ import { spawn as spawn6 } from "node:child_process";
9362
+
9363
+ // ../../node_modules/.pnpm/@ai-ezio+harness@file+..+ai-ezio+packages+harness/node_modules/@ai-ezio/harness/dist/skills-dir.js
9364
+ import { homedir } from "node:os";
9365
+ import { join as join8 } from "node:path";
9366
+ function aiEzioGlobalSkillsDir(env = process.env) {
9367
+ const base = env.XDG_CONFIG_HOME && env.XDG_CONFIG_HOME !== "" ? env.XDG_CONFIG_HOME : join8(homedir(), ".config");
9368
+ return join8(base, "ai-ezio", "skills");
9369
+ }
9370
+
9371
+ // ../../node_modules/.pnpm/@ai-ezio+harness@file+..+ai-ezio+packages+harness/node_modules/@ai-ezio/harness/dist/spawn.js
9372
+ function haxSpawnArgs(extra = []) {
9373
+ return ["--protocol-fd=3", "--control-fd=4", "--mount-mode", ...extra];
9374
+ }
9375
+ function haxSpawnEnv(base = process.env) {
9376
+ return { ...base, HAX_EXTRA_SKILLS_DIR: aiEzioGlobalSkillsDir(base) };
9377
+ }
9378
+ function spawnHax(options = {}) {
9379
+ const binary = options.binary ?? resolveHaxBinary();
9380
+ const child = spawn6(binary, haxSpawnArgs(options.args), {
9381
+ // 0,1,2 ignored; 3 = events (hax writes), 4 = controls (hax reads).
9382
+ stdio: ["ignore", "ignore", "ignore", "pipe", "pipe"],
9383
+ env: haxSpawnEnv(options.env ?? process.env)
9384
+ });
9385
+ const eventStream = child.stdio[3];
9386
+ const controlStream = child.stdio[4];
9387
+ return { child, eventStream, controlStream };
9388
+ }
9389
+
9390
+ // ../../node_modules/.pnpm/@ai-ezio+protocol@file+..+ai-ezio+packages+protocol/node_modules/@ai-ezio/protocol/dist/codec.js
9391
+ import { StringDecoder } from "node:string_decoder";
9392
+ var MalformedLineError = class extends Error {
9393
+ line;
9394
+ constructor(line) {
9395
+ super(`malformed JSONL line: ${JSON.stringify(line)}`);
9396
+ this.line = line;
9397
+ this.name = "MalformedLineError";
9398
+ }
9399
+ };
9400
+ function encodeControl(control) {
9401
+ return `${JSON.stringify(control)}
9402
+ `;
9403
+ }
9404
+ var JsonlDecoder = class {
9405
+ buffer = "";
9406
+ // fd-3 yields raw Buffer chunks at arbitrary boundaries. StringDecoder holds
9407
+ // back the trailing bytes of a multibyte UTF-8 codepoint until the rest
9408
+ // arrives, so a char split across reads (em-dash, bullet, smart quote, box
9409
+ // chars) never decodes to `�`. Decoding a chunk in isolation does NOT.
9410
+ utf8 = new StringDecoder("utf8");
9411
+ /**
9412
+ * Append a chunk and return every complete event it produced. A trailing
9413
+ * partial line — or a partial multibyte char — is retained until the rest
9414
+ * arrives. Throws MalformedLineError on a complete-but-unparseable line (the
9415
+ * buffer past it is preserved so decoding can continue after the caller
9416
+ * handles it).
9417
+ */
9418
+ push(chunk) {
9419
+ this.buffer += typeof chunk === "string" ? chunk : this.utf8.write(Buffer.from(chunk));
9420
+ const events = [];
9421
+ let nl = this.buffer.indexOf("\n");
9422
+ while (nl >= 0) {
9423
+ const line = this.buffer.slice(0, nl);
9424
+ this.buffer = this.buffer.slice(nl + 1);
9425
+ const trimmed = line.trim();
9426
+ if (trimmed.length > 0) {
9427
+ let parsed;
9428
+ try {
9429
+ parsed = JSON.parse(trimmed);
9430
+ } catch {
9431
+ throw new MalformedLineError(line);
9432
+ }
9433
+ events.push(parsed);
9434
+ }
9435
+ nl = this.buffer.indexOf("\n");
9436
+ }
9437
+ return events;
9438
+ }
9439
+ /** Bytes buffered but not yet terminated by a newline. */
9440
+ get pending() {
9441
+ return this.buffer;
9442
+ }
9443
+ };
9444
+
9445
+ // ../../node_modules/.pnpm/@ai-ezio+protocol@file+..+ai-ezio+packages+protocol/node_modules/@ai-ezio/protocol/dist/transport-fd.js
9446
+ var FdTransport = class {
9447
+ eventStream;
9448
+ controlStream;
9449
+ decoder = new JsonlDecoder();
9450
+ constructor(eventStream, controlStream) {
9451
+ this.eventStream = eventStream;
9452
+ this.controlStream = controlStream;
9453
+ }
9454
+ async *events() {
9455
+ for await (const chunk of this.eventStream) {
9456
+ for (const event of this.decoder.push(chunk)) {
9457
+ yield event;
9458
+ }
9459
+ }
9460
+ }
9461
+ send(control) {
9462
+ this.controlStream.write(encodeControl(control));
9463
+ }
9464
+ close() {
9465
+ this.controlStream.end();
9466
+ }
9467
+ };
9468
+
9469
+ // ../../node_modules/.pnpm/@ai-ezio+protocol@file+..+ai-ezio+packages+protocol/node_modules/@ai-ezio/protocol/dist/index.js
9470
+ var PROTOCOL_VERSION = "0.1.0";
9471
+ function semverMajor(version) {
9472
+ const major = Number.parseInt(version.split(".", 1)[0] ?? "", 10);
9473
+ if (Number.isNaN(major)) {
9474
+ throw new Error(`Invalid semver version string: "${version}"`);
9475
+ }
9476
+ return major;
9477
+ }
9478
+ function isProtocolCompatible(theirs, ours = PROTOCOL_VERSION) {
9479
+ return semverMajor(theirs) === semverMajor(ours);
9480
+ }
9481
+
9482
+ // ../../node_modules/.pnpm/@ai-ezio+harness@file+..+ai-ezio+packages+harness/node_modules/@ai-ezio/harness/dist/session.js
9483
+ var ProtocolVersionError = class extends Error {
9484
+ constructor(theirs, ours) {
9485
+ super(`unsupported engine protocol ${theirs} (harness speaks ${ours})`);
9486
+ this.name = "ProtocolVersionError";
9487
+ }
9488
+ };
9489
+ var TurnError = class extends Error {
9490
+ turnId;
9491
+ constructor(message, turnId) {
9492
+ super(message);
9493
+ this.turnId = turnId;
9494
+ this.name = "TurnError";
9495
+ }
9496
+ };
9497
+ var EngineExitedError = class extends Error {
9498
+ constructor(message = "engine exited (fd-3 EOF)") {
9499
+ super(message);
9500
+ this.name = "EngineExitedError";
9501
+ }
9502
+ };
9503
+ var Session = class {
9504
+ options;
9505
+ spawned;
9506
+ transport;
9507
+ queue = [];
9508
+ waiters = [];
9509
+ ended = false;
9510
+ closed = false;
9511
+ exitHandlers = [];
9512
+ ready;
9513
+ constructor(options = {}) {
9514
+ this.options = options;
9515
+ }
9516
+ /** Subscribe to engine child-exit (workflow-agnostic lifecycle signal for
9517
+ * adapters that surface provider exit). Fires once per child exit. */
9518
+ onExit(handler) {
9519
+ this.exitHandlers.push(handler);
9520
+ }
9521
+ deliver(event) {
9522
+ if (event && this.options.onEvent)
9523
+ this.options.onEvent(event);
9524
+ const w = this.waiters.shift();
9525
+ if (w)
9526
+ w(event);
9527
+ else if (event)
9528
+ this.queue.push(event);
9529
+ }
9530
+ next() {
9531
+ const queued = this.queue.shift();
9532
+ if (queued)
9533
+ return Promise.resolve(queued);
9534
+ if (this.ended)
9535
+ return Promise.resolve(null);
9536
+ return new Promise((resolve5) => this.waiters.push(resolve5));
9537
+ }
9538
+ /** Consume events until one of the given type arrives. Fatal EOF →
9539
+ * EngineExitedError; a turn-scoped `error` → TurnError. */
9540
+ async waitForEvent(type) {
9541
+ for (; ; ) {
9542
+ const e = await this.next();
9543
+ if (e === null)
9544
+ throw new EngineExitedError(`engine exited before "${type}"`);
9545
+ if (e.type === "error" && type !== "error") {
9546
+ throw new TurnError(e.message, e.turnId);
9547
+ }
9548
+ if (e.type === type)
9549
+ return e;
9550
+ }
9551
+ }
9552
+ /** Spawn hax, pump events, and gate on the `ready` protocol version. */
9553
+ async start(options = {}) {
9554
+ const spawned = spawnHax(options);
9555
+ this.spawned = spawned;
9556
+ spawned.child.on("exit", (code, signal) => {
9557
+ for (const handler of this.exitHandlers)
9558
+ handler({ code, signal });
9559
+ });
9560
+ const transport = new FdTransport(spawned.eventStream, spawned.controlStream);
9561
+ this.transport = transport;
9562
+ void (async () => {
9563
+ try {
9564
+ for await (const event of transport.events())
9565
+ this.deliver(event);
9566
+ } finally {
9567
+ this.ended = true;
9568
+ while (this.waiters.length)
9569
+ this.deliver(null);
9570
+ }
9571
+ })();
9572
+ const ready = await this.waitForEvent("ready");
9573
+ if (!isProtocolCompatible(ready.protocol, PROTOCOL_VERSION)) {
9574
+ this.close();
9575
+ throw new ProtocolVersionError(ready.protocol, PROTOCOL_VERSION);
9576
+ }
9577
+ this.ready = ready;
9578
+ return ready;
9579
+ }
9580
+ control(control) {
9581
+ if (!this.transport)
9582
+ throw new Error("session not started");
9583
+ this.transport.send(control);
9584
+ }
9585
+ /** Send a user turn without waiting (pair with waitForEvent/interrupt). */
9586
+ submit(text) {
9587
+ this.control({ type: "submit", text });
9588
+ }
9589
+ /**
9590
+ * Submit a user turn and resolve with its authoritative content at idle.
9591
+ * A turn-scoped `error` is captured and the loop **drains to `idle`** (so the
9592
+ * session settles at a clean boundary and a later submit works), then rejects
9593
+ * with TurnError. A fatal fd-3 EOF mid-turn rejects with EngineExitedError.
9594
+ */
9595
+ async submitAndWait(text) {
9596
+ this.control({ type: "submit", text });
9597
+ let result;
9598
+ let turnError;
9599
+ for (; ; ) {
9600
+ const e = await this.next();
9601
+ if (e === null)
9602
+ throw new EngineExitedError("engine exited mid-turn");
9603
+ if (e.type === "assistant_turn_finished") {
9604
+ result = { turnId: e.turnId, content: e.content };
9605
+ } else if (e.type === "error") {
9606
+ turnError = new TurnError(e.message, e.turnId);
9607
+ } else if (e.type === "idle") {
9608
+ if (turnError)
9609
+ throw turnError;
9610
+ return result ?? { turnId: "", content: "" };
9611
+ }
9612
+ }
9613
+ }
9614
+ /** Cancel the in-flight turn. */
9615
+ interrupt() {
9616
+ this.control({ type: "interrupt" });
9617
+ }
9618
+ /** Re-fetch the last handback without re-running a turn (no clipboard).
9619
+ * Resolves the re-emitted content; rejects TurnError if no prior response. */
9620
+ async copyLastResponse() {
9621
+ this.control({ type: "copy_last_response" });
9622
+ const e = await this.waitForEvent("assistant_turn_finished");
9623
+ if (e.type !== "assistant_turn_finished")
9624
+ throw new Error("unexpected event");
9625
+ return { turnId: e.turnId, content: e.content };
9626
+ }
9627
+ /** Start a fresh conversation; resolves once the engine is idle again. */
9628
+ async newConversation() {
9629
+ this.control({ type: "new_conversation" });
9630
+ await this.waitForEvent("idle");
9631
+ }
9632
+ /** Request an engine/session status event. */
9633
+ async status() {
9634
+ this.control({ type: "status" });
9635
+ return await this.waitForEvent("status");
9636
+ }
9637
+ /** Close the control channel (shuts the engine down) and stop the child.
9638
+ * Idempotent — safe to call from both the version-gate teardown and the
9639
+ * caller. */
9640
+ close() {
9641
+ if (this.closed)
9642
+ return;
9643
+ this.closed = true;
9644
+ try {
9645
+ this.transport?.close();
9646
+ } catch {
9647
+ }
9648
+ this.spawned?.child.kill();
9649
+ }
9650
+ };
9272
9651
 
9273
9652
  // ../adapter-ai-ezio/dist/ai-ezio-engine.js
9274
- import { Session } from "@ai-ezio/harness";
9275
9653
  var defaultCreateEngineSession = ({ onEvent }) => new Session({ onEvent });
9276
9654
 
9277
9655
  // ../adapter-ai-ezio/dist/ai-ezio-prompt.js
@@ -10763,9 +11141,9 @@ async function captureHandbackText(input) {
10763
11141
 
10764
11142
  // src/runtime/clipboard-change-count.ts
10765
11143
  import { execFile as execFile3 } from "node:child_process";
10766
- import { existsSync as existsSync7 } from "node:fs";
10767
- import { fileURLToPath as fileURLToPath2 } from "node:url";
10768
- import { dirname as dirname3, join as join7 } from "node:path";
11144
+ import { existsSync as existsSync8 } from "node:fs";
11145
+ import { fileURLToPath as fileURLToPath3 } from "node:url";
11146
+ import { dirname as dirname4, join as join9 } from "node:path";
10769
11147
  var HELPER_BIN_NAME = "clipboard-change-count";
10770
11148
  function execFileText2(command, args = []) {
10771
11149
  return new Promise((resolve5, reject) => {
@@ -10781,9 +11159,9 @@ function execFileText2(command, args = []) {
10781
11159
  function makeChangeCountReader(deps) {
10782
11160
  const platform = deps?.platform ?? process.platform;
10783
11161
  const runHelper = deps?.runHelper ?? (async () => {
10784
- const here = dirname3(fileURLToPath2(import.meta.url));
10785
- const bin = join7(here, "..", "native", HELPER_BIN_NAME);
10786
- if (!existsSync7(bin)) throw new Error("changeCount helper not built");
11162
+ const here = dirname4(fileURLToPath3(import.meta.url));
11163
+ const bin = join9(here, "..", "native", HELPER_BIN_NAME);
11164
+ if (!existsSync8(bin)) throw new Error("changeCount helper not built");
10787
11165
  return execFileText2(bin);
10788
11166
  });
10789
11167
  return async () => {
@@ -12750,11 +13128,11 @@ async function runCollabDashboard(input) {
12750
13128
  // src/commands/collab/status.ts
12751
13129
  init_dist2();
12752
13130
  import Database2 from "better-sqlite3";
12753
- import { existsSync as existsSync8 } from "node:fs";
13131
+ import { existsSync as existsSync9 } from "node:fs";
12754
13132
 
12755
13133
  // src/runtime/evaluator-config.ts
12756
13134
  import { readFileSync as readFileSync2, statSync as statSync2 } from "node:fs";
12757
- import { join as join8 } from "node:path";
13135
+ import { join as join10 } from "node:path";
12758
13136
  function isEvaluatorReady(status) {
12759
13137
  return status === "ready" || status === "unknown";
12760
13138
  }
@@ -12766,7 +13144,7 @@ function isEvaluatorPreflightBlocked(status) {
12766
13144
  init_dist();
12767
13145
  function runCollabStatus(input) {
12768
13146
  const sqlitePath = getSharedSqlitePath();
12769
- if (!existsSync8(sqlitePath)) {
13147
+ if (!existsSync9(sqlitePath)) {
12770
13148
  return input.json ? JSON.stringify({ error: "no_collab_for_cwd", cwd: input.cwd }) : `no active collab for ${input.cwd}`;
12771
13149
  }
12772
13150
  const db = new Database2(sqlitePath, { readonly: true });
@@ -13107,9 +13485,9 @@ async function runCollabTell(input) {
13107
13485
 
13108
13486
  // src/runtime/launcher.ts
13109
13487
  import { execSync as execSync3, spawn as nodeSpawn } from "node:child_process";
13110
- import { dirname as dirname4, resolve as resolve4 } from "node:path";
13111
- import { fileURLToPath as fileURLToPath3 } from "node:url";
13112
- var __dirname = dirname4(fileURLToPath3(import.meta.url));
13488
+ import { dirname as dirname5, resolve as resolve4 } from "node:path";
13489
+ import { fileURLToPath as fileURLToPath4 } from "node:url";
13490
+ var __dirname = dirname5(fileURLToPath4(import.meta.url));
13113
13491
  var whisperBinPath = resolve4(__dirname, "../bin/whisper.js");
13114
13492
  var relayMonitorBinPath = resolve4(__dirname, "../bin/relay-monitor.js");
13115
13493
  function shellQuote(value) {
@@ -13375,9 +13753,9 @@ async function runWorkflowTypes() {
13375
13753
  // src/commands/skill/install.ts
13376
13754
  import { cp, mkdir, readdir, stat } from "node:fs/promises";
13377
13755
  import path3 from "node:path";
13378
- import { fileURLToPath as fileURLToPath4 } from "node:url";
13756
+ import { fileURLToPath as fileURLToPath5 } from "node:url";
13379
13757
  function defaultBundledSkillsDir() {
13380
- const here = path3.dirname(fileURLToPath4(import.meta.url));
13758
+ const here = path3.dirname(fileURLToPath5(import.meta.url));
13381
13759
  return path3.resolve(here, "..", "..", "skills");
13382
13760
  }
13383
13761
  function homeForTarget(target, fakeHome) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-whisper",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
4
4
  "description": "Terminal-first relay for paired AI coding agents (Claude + Codex), driven by structured workflows.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -45,11 +45,11 @@
45
45
  "@types/better-sqlite3": "^7.6.12",
46
46
  "@types/react": "^19.2.14",
47
47
  "ink-testing-library": "^4.0.0",
48
- "@ai-whisper/adapter-ai-ezio": "0.0.0",
49
48
  "@ai-whisper/adapter-codex": "0.0.0",
50
- "@ai-whisper/companion-core": "0.0.0",
51
- "@ai-whisper/adapter-claude": "0.0.0",
52
49
  "@ai-whisper/broker": "0.0.0",
50
+ "@ai-whisper/adapter-claude": "0.0.0",
51
+ "@ai-whisper/adapter-ai-ezio": "0.0.0",
52
+ "@ai-whisper/companion-core": "0.0.0",
53
53
  "@ai-whisper/shared": "0.0.0"
54
54
  },
55
55
  "files": [