ai-whisper 0.4.1 → 0.4.3
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/dist/bin/whisper.js +63 -23
- package/package.json +3 -3
package/dist/bin/whisper.js
CHANGED
|
@@ -4758,7 +4758,7 @@ function acquireCaptureLease(db, collabId, pid, options = {}) {
|
|
|
4758
4758
|
acquired_at = excluded.acquired_at`).run(LEASE_ID, collabId, pid, acquiredAt);
|
|
4759
4759
|
return true;
|
|
4760
4760
|
});
|
|
4761
|
-
return tx();
|
|
4761
|
+
return tx.immediate();
|
|
4762
4762
|
}
|
|
4763
4763
|
function releaseCaptureLease(db, collabId) {
|
|
4764
4764
|
const tx = db.transaction(() => {
|
|
@@ -10183,12 +10183,16 @@ async function captureHandbackText(input) {
|
|
|
10183
10183
|
let acquired = false;
|
|
10184
10184
|
const deadline = Date.now() + acquireMaxWaitMs;
|
|
10185
10185
|
for (; ; ) {
|
|
10186
|
-
|
|
10187
|
-
|
|
10188
|
-
|
|
10189
|
-
|
|
10190
|
-
|
|
10191
|
-
|
|
10186
|
+
try {
|
|
10187
|
+
acquired = acquireCaptureLease(
|
|
10188
|
+
input.db,
|
|
10189
|
+
input.collabId,
|
|
10190
|
+
input.pid,
|
|
10191
|
+
input.leaseOptions
|
|
10192
|
+
);
|
|
10193
|
+
} catch {
|
|
10194
|
+
acquired = false;
|
|
10195
|
+
}
|
|
10192
10196
|
if (acquired) break;
|
|
10193
10197
|
if (Date.now() >= deadline) break;
|
|
10194
10198
|
await sleep3(acquireBackoffMs);
|
|
@@ -10265,22 +10269,56 @@ function makeChangeCountReader(deps) {
|
|
|
10265
10269
|
}
|
|
10266
10270
|
|
|
10267
10271
|
// src/runtime/provider-submit-strategy.ts
|
|
10272
|
+
var PASTE_START = "\x1B[200~";
|
|
10273
|
+
var PASTE_END = "\x1B[201~";
|
|
10268
10274
|
async function submitInjectedProviderInput(input) {
|
|
10269
10275
|
const sleep3 = input.sleep ?? ((ms) => new Promise((resolve5) => setTimeout(resolve5, ms)));
|
|
10270
|
-
if (input.target === "
|
|
10271
|
-
|
|
10272
|
-
|
|
10273
|
-
|
|
10274
|
-
|
|
10276
|
+
if (input.target === "claude") {
|
|
10277
|
+
input.writeUserInput(input.text);
|
|
10278
|
+
await sleep3(75);
|
|
10279
|
+
input.writeUserInput("\r");
|
|
10280
|
+
return;
|
|
10281
|
+
}
|
|
10282
|
+
const strategy = input.strategyOverride ?? (input.bracketedPasteEnabled ? "bracketed" : "keystream");
|
|
10283
|
+
if (strategy === "bracketed") {
|
|
10284
|
+
const safe = input.text.split(PASTE_END).join("");
|
|
10285
|
+
input.writeUserInput(PASTE_START + safe + PASTE_END);
|
|
10275
10286
|
await sleep3(100);
|
|
10276
10287
|
input.writeUserInput("\r");
|
|
10277
10288
|
return;
|
|
10278
10289
|
}
|
|
10279
|
-
|
|
10280
|
-
|
|
10290
|
+
if (strategy === "chunk") {
|
|
10291
|
+
input.writeUserInput(input.text);
|
|
10292
|
+
await sleep3(75);
|
|
10293
|
+
input.writeUserInput("\r");
|
|
10294
|
+
return;
|
|
10295
|
+
}
|
|
10296
|
+
for (const char of input.text) {
|
|
10297
|
+
input.writeUserInput(char);
|
|
10298
|
+
await sleep3(5);
|
|
10299
|
+
}
|
|
10300
|
+
await sleep3(100);
|
|
10281
10301
|
input.writeUserInput("\r");
|
|
10282
10302
|
}
|
|
10283
10303
|
|
|
10304
|
+
// src/runtime/bracketed-paste-detector.ts
|
|
10305
|
+
var ENABLE = "\x1B[?2004h";
|
|
10306
|
+
var RESET2 = "\x1B[?2004l";
|
|
10307
|
+
function createBracketedPasteDetector() {
|
|
10308
|
+
let enabled = false;
|
|
10309
|
+
return {
|
|
10310
|
+
observe(data) {
|
|
10311
|
+
const hi = data.lastIndexOf(ENABLE);
|
|
10312
|
+
const lo = data.lastIndexOf(RESET2);
|
|
10313
|
+
if (hi > lo) enabled = true;
|
|
10314
|
+
else if (lo > hi) enabled = false;
|
|
10315
|
+
},
|
|
10316
|
+
get enabled() {
|
|
10317
|
+
return enabled;
|
|
10318
|
+
}
|
|
10319
|
+
};
|
|
10320
|
+
}
|
|
10321
|
+
|
|
10284
10322
|
// src/runtime/runtime-debug-log.ts
|
|
10285
10323
|
import { appendFileSync as appendFileSync4 } from "node:fs";
|
|
10286
10324
|
function toHex2(text) {
|
|
@@ -10308,6 +10346,11 @@ function createRuntimeDebugLogger(input) {
|
|
|
10308
10346
|
}
|
|
10309
10347
|
|
|
10310
10348
|
// src/runtime/mount-session-main.ts
|
|
10349
|
+
function resolveCodexSubmitStrategyOverride() {
|
|
10350
|
+
const raw = process.env.AI_WHISPER_CODEX_SUBMIT_STRATEGY;
|
|
10351
|
+
if (raw === "bracketed" || raw === "keystream" || raw === "chunk") return raw;
|
|
10352
|
+
return void 0;
|
|
10353
|
+
}
|
|
10311
10354
|
var readChangeCount = makeChangeCountReader();
|
|
10312
10355
|
function safeReapSessions(input) {
|
|
10313
10356
|
const reap = input.reap ?? ((collabId, agentType, keepSessionId) => {
|
|
@@ -10412,6 +10455,8 @@ function createMountSessionRuntime(input) {
|
|
|
10412
10455
|
let lastActivityAt = Date.now();
|
|
10413
10456
|
try {
|
|
10414
10457
|
const turnCapture = createAssistantTurnCapture();
|
|
10458
|
+
const bracketedPaste = createBracketedPasteDetector();
|
|
10459
|
+
const codexStrategyOverride = resolveCodexSubmitStrategyOverride();
|
|
10415
10460
|
const debugLog = createRuntimeDebugLogger({
|
|
10416
10461
|
logPath: process.env.AI_WHISPER_DEBUG_INPUT_LOG ?? null,
|
|
10417
10462
|
sessionId: process.env.AI_WHISPER_SESSION_ID ?? null
|
|
@@ -10433,12 +10478,15 @@ function createMountSessionRuntime(input) {
|
|
|
10433
10478
|
await submitInjectedProviderInput({
|
|
10434
10479
|
target: input.target,
|
|
10435
10480
|
text,
|
|
10436
|
-
writeUserInput: (value) => writeInjectedInput("mounted-submit", value)
|
|
10481
|
+
writeUserInput: (value) => writeInjectedInput("mounted-submit", value),
|
|
10482
|
+
bracketedPasteEnabled: bracketedPaste.enabled,
|
|
10483
|
+
strategyOverride: codexStrategyOverride
|
|
10437
10484
|
});
|
|
10438
10485
|
};
|
|
10439
10486
|
interactiveSession.onProviderOutput?.((data) => {
|
|
10440
10487
|
lastActivityAt = Date.now();
|
|
10441
10488
|
turnCapture.recordProviderOutput(data);
|
|
10489
|
+
bracketedPaste.observe(data);
|
|
10442
10490
|
});
|
|
10443
10491
|
const onRelay = (directive, sendNow) => {
|
|
10444
10492
|
if (!resolvedClaim) {
|
|
@@ -10563,14 +10611,6 @@ function createMountSessionRuntime(input) {
|
|
|
10563
10611
|
pid: process.pid,
|
|
10564
10612
|
turnText,
|
|
10565
10613
|
readChangeCount,
|
|
10566
|
-
// TEMP 2026-05-29: bump lease poll-acquire from default 4s to 30s
|
|
10567
|
-
// to absorb concurrent-collab contention while we land the proper
|
|
10568
|
-
// fix (per-provider capture strategies, design doc Phase 2). The
|
|
10569
|
-
// auto-handback already waits ≥30s grace + however long the
|
|
10570
|
-
// provider takes to idle, so an extra 0–30s of lease wait is
|
|
10571
|
-
// invisible. Revert once mount restart / per-provider strategy
|
|
10572
|
-
// removes the host-global single-lease bottleneck.
|
|
10573
|
-
acquireMaxWaitMs: 3e4,
|
|
10574
10614
|
runCapture: () => captureClipboardHandback({
|
|
10575
10615
|
triggerCopy: () => submitInjectedInput2("/copy"),
|
|
10576
10616
|
// Some provider versions show a picker after /copy (e.g. Claude
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai-whisper",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.3",
|
|
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": {
|
|
@@ -47,9 +47,9 @@
|
|
|
47
47
|
"ink-testing-library": "^4.0.0",
|
|
48
48
|
"@ai-whisper/adapter-claude": "0.0.0",
|
|
49
49
|
"@ai-whisper/adapter-codex": "0.0.0",
|
|
50
|
-
"@ai-whisper/
|
|
50
|
+
"@ai-whisper/broker": "0.0.0",
|
|
51
51
|
"@ai-whisper/shared": "0.0.0",
|
|
52
|
-
"@ai-whisper/
|
|
52
|
+
"@ai-whisper/companion-core": "0.0.0"
|
|
53
53
|
},
|
|
54
54
|
"files": [
|
|
55
55
|
"dist",
|