ai-whisper 0.1.3 → 0.1.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 +18 -0
- package/dist/bin/whisper.js +75 -1
- package/package.json +18 -2
package/README.md
CHANGED
|
@@ -50,6 +50,20 @@ It is **not** for:
|
|
|
50
50
|
- invisible background automation you never watch.
|
|
51
51
|
- people new to coding agents looking for a guided, hand-holding experience.
|
|
52
52
|
|
|
53
|
+
## Prerequisites
|
|
54
|
+
|
|
55
|
+
ai-whisper drives the *real* Claude and Codex CLIs, so you need both installed and authenticated first:
|
|
56
|
+
|
|
57
|
+
- **[Claude Code CLI](https://claude.com/claude-code)** — the `claude` command, signed in.
|
|
58
|
+
- **[Codex CLI](https://github.com/openai/codex)** — the `codex` command, signed in.
|
|
59
|
+
- **Node.js 22+**.
|
|
60
|
+
- **An LLM evaluator with credentials** — workflows are gated by it and refuse to start without it. See [Evaluator configuration](docs/evaluator-configuration.md).
|
|
61
|
+
- **tmux** *(optional)* — only for `whisper collab start`, which auto-arranges both agents into panes. The mount flow below does not need it.
|
|
62
|
+
|
|
63
|
+
## Safety & permissions
|
|
64
|
+
|
|
65
|
+
ai-whisper launches each agent in **full-autonomy mode** so the relay can drive it unattended — `claude --dangerously-skip-permissions` and `codex --dangerously-bypass-approvals-and-sandbox`. Inside the mounted workspace the agents read, write, and run commands without prompting. Point it at code you're willing to let two agents change autonomously, watch the run on the dashboard, and remember you are the final gatekeeper — review the result before you ship it. The deeper rationale is in [Concepts](docs/concepts.md).
|
|
66
|
+
|
|
53
67
|
## Quickstart
|
|
54
68
|
|
|
55
69
|
Install from npm:
|
|
@@ -90,6 +104,10 @@ whisper collab dashboard
|
|
|
90
104
|
|
|
91
105
|
> Running from a repo checkout instead of a packaged install? Build first (`pnpm build`) and invoke the CLI as `node packages/cli/dist/bin/whisper.js ...` wherever these examples say `whisper ...`.
|
|
92
106
|
|
|
107
|
+
## What happens if it fails?
|
|
108
|
+
|
|
109
|
+
A run that stops short usually **escalates** — it does not crash. When the evaluator can't resolve a phase (the round budget is spent, an agent reports it's blocked, or confidence stays too low), the loop halts and turn ownership returns to you. That's a designed exit, not a failure: run state is durable, so you read the dashboard, fix the spec or unblock the agent, and `whisper workflow resume <id>` to pick up where it left off. Escalation is the system asking for a human exactly when it should — seeing it is normal, not a sign something broke.
|
|
110
|
+
|
|
93
111
|
## Core concepts
|
|
94
112
|
|
|
95
113
|
ai-whisper is **not a swarm**. The agents never type at once — work moves by a single baton, one owner at a time. Mounted sessions are *real* Claude and Codex sessions in your terminal, and those sessions are the source of truth. Autonomy is supervised: every handoff, verdict, and round is inspectable, and runs are resumable rather than fire-and-forget. Work is organized as structured workflows — explicit loops and state transitions, not a free-form chat.
|
package/dist/bin/whisper.js
CHANGED
|
@@ -14,6 +14,7 @@ function loadDotEnv() {
|
|
|
14
14
|
|
|
15
15
|
// src/create-cli.ts
|
|
16
16
|
import { execSync as execSync4 } from "node:child_process";
|
|
17
|
+
import { readFileSync as readFileSync3 } from "node:fs";
|
|
17
18
|
import { Command, Option } from "commander";
|
|
18
19
|
|
|
19
20
|
// ../broker/dist/config.js
|
|
@@ -11040,8 +11041,18 @@ async function connectToWorkspaceBroker(input) {
|
|
|
11040
11041
|
function collectArtifact(value, previous = []) {
|
|
11041
11042
|
return [...previous, value];
|
|
11042
11043
|
}
|
|
11044
|
+
function resolveCliVersion() {
|
|
11045
|
+
for (const rel of ["../../package.json", "../package.json"]) {
|
|
11046
|
+
try {
|
|
11047
|
+
const pkg = JSON.parse(readFileSync3(new URL(rel, import.meta.url), "utf8"));
|
|
11048
|
+
if (pkg.name === "ai-whisper" && typeof pkg.version === "string") return pkg.version;
|
|
11049
|
+
} catch {
|
|
11050
|
+
}
|
|
11051
|
+
}
|
|
11052
|
+
return "0.0.0-dev";
|
|
11053
|
+
}
|
|
11043
11054
|
function createCli() {
|
|
11044
|
-
const cli = new Command().name("whisper").description("ai-whisper CLI");
|
|
11055
|
+
const cli = new Command().name("whisper").description("ai-whisper CLI").version(resolveCliVersion(), "-v, --version", "output the version number");
|
|
11045
11056
|
const collab = cli.command("collab").description("Manage AI agent collaboration sessions");
|
|
11046
11057
|
collab.command("start").description("Start a new collaboration session").option("--workspace <path>", "Workspace root", process.cwd()).option("--no-tmux", "Disable tmux even if available").option("--no-launch", "Start broker only, do not launch agent terminals").option(
|
|
11047
11058
|
"--port <port>",
|
|
@@ -11344,6 +11355,69 @@ Not attached (stdin/stdout is not a TTY). To view the tmux session, run:
|
|
|
11344
11355
|
return cli;
|
|
11345
11356
|
}
|
|
11346
11357
|
|
|
11358
|
+
// src/runtime/version-check.ts
|
|
11359
|
+
var PKG = "ai-whisper";
|
|
11360
|
+
var REGISTRY_LATEST = `https://registry.npmjs.org/${PKG}/latest`;
|
|
11361
|
+
var DEFAULT_TIMEOUT_MS = 1500;
|
|
11362
|
+
function coreParts(v) {
|
|
11363
|
+
const core = v.split("-")[0] ?? "";
|
|
11364
|
+
const [a, b, c] = core.split(".").map((n) => Number.parseInt(n, 10) || 0);
|
|
11365
|
+
return [a ?? 0, b ?? 0, c ?? 0];
|
|
11366
|
+
}
|
|
11367
|
+
function isNewerVersion(candidate, current) {
|
|
11368
|
+
const cand = coreParts(candidate);
|
|
11369
|
+
const cur = coreParts(current);
|
|
11370
|
+
for (let i = 0; i < 3; i++) {
|
|
11371
|
+
if (cand[i] > cur[i]) return true;
|
|
11372
|
+
if (cand[i] < cur[i]) return false;
|
|
11373
|
+
}
|
|
11374
|
+
const candPre = candidate.includes("-");
|
|
11375
|
+
const curPre = current.includes("-");
|
|
11376
|
+
if (candPre !== curPre) return !candPre;
|
|
11377
|
+
return false;
|
|
11378
|
+
}
|
|
11379
|
+
function formatVersionReport(current, latest) {
|
|
11380
|
+
if (latest && isNewerVersion(latest, current)) {
|
|
11381
|
+
return `${current}
|
|
11382
|
+
A newer version is available: ${current} \u2192 ${latest} \xB7 update: npm install -g ${PKG}@latest`;
|
|
11383
|
+
}
|
|
11384
|
+
return current;
|
|
11385
|
+
}
|
|
11386
|
+
async function fetchLatestVersion(opts) {
|
|
11387
|
+
const timeoutMs = opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
11388
|
+
const f = opts?.fetchImpl ?? fetch;
|
|
11389
|
+
const ac = new AbortController();
|
|
11390
|
+
const timer = setTimeout(() => ac.abort(), timeoutMs);
|
|
11391
|
+
try {
|
|
11392
|
+
const res = await f(REGISTRY_LATEST, { signal: ac.signal });
|
|
11393
|
+
if (!res.ok) return null;
|
|
11394
|
+
const body = await res.json();
|
|
11395
|
+
return typeof body.version === "string" ? body.version : null;
|
|
11396
|
+
} catch {
|
|
11397
|
+
return null;
|
|
11398
|
+
} finally {
|
|
11399
|
+
clearTimeout(timer);
|
|
11400
|
+
}
|
|
11401
|
+
}
|
|
11402
|
+
async function reportVersion(input) {
|
|
11403
|
+
const write = input.write ?? ((line) => process.stdout.write(`${line}
|
|
11404
|
+
`));
|
|
11405
|
+
if (input.disabled) {
|
|
11406
|
+
write(input.current);
|
|
11407
|
+
return;
|
|
11408
|
+
}
|
|
11409
|
+
const latest = await (input.fetchLatest ? input.fetchLatest() : fetchLatestVersion());
|
|
11410
|
+
write(formatVersionReport(input.current, latest));
|
|
11411
|
+
}
|
|
11412
|
+
|
|
11347
11413
|
// src/bin/whisper.ts
|
|
11348
11414
|
loadDotEnv();
|
|
11415
|
+
var argv = process.argv.slice(2);
|
|
11416
|
+
if (argv.includes("-v") || argv.includes("--version")) {
|
|
11417
|
+
await reportVersion({
|
|
11418
|
+
current: resolveCliVersion(),
|
|
11419
|
+
disabled: process.env.AI_WHISPER_NO_UPDATE_CHECK === "1"
|
|
11420
|
+
});
|
|
11421
|
+
process.exit(0);
|
|
11422
|
+
}
|
|
11349
11423
|
await createCli().parseAsync(process.argv);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai-whisper",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
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": {
|
|
@@ -8,6 +8,22 @@
|
|
|
8
8
|
"url": "https://github.com/ai-creed/ai-whisper.git"
|
|
9
9
|
},
|
|
10
10
|
"homepage": "https://ai-creed.dev/projects/ai-whisper/",
|
|
11
|
+
"keywords": [
|
|
12
|
+
"ai-agents",
|
|
13
|
+
"claude",
|
|
14
|
+
"codex",
|
|
15
|
+
"coding-agent",
|
|
16
|
+
"cli",
|
|
17
|
+
"developer-tools",
|
|
18
|
+
"tmux",
|
|
19
|
+
"spec-driven-development",
|
|
20
|
+
"agent-orchestration",
|
|
21
|
+
"pair-programming",
|
|
22
|
+
"typescript"
|
|
23
|
+
],
|
|
24
|
+
"engines": {
|
|
25
|
+
"node": ">=22"
|
|
26
|
+
},
|
|
11
27
|
"type": "module",
|
|
12
28
|
"bin": {
|
|
13
29
|
"whisper": "./dist/bin/whisper.js",
|
|
@@ -30,8 +46,8 @@
|
|
|
30
46
|
"@types/react": "^19.2.14",
|
|
31
47
|
"ink-testing-library": "^4.0.0",
|
|
32
48
|
"@ai-whisper/adapter-claude": "0.0.0",
|
|
33
|
-
"@ai-whisper/shared": "0.0.0",
|
|
34
49
|
"@ai-whisper/adapter-codex": "0.0.0",
|
|
50
|
+
"@ai-whisper/shared": "0.0.0",
|
|
35
51
|
"@ai-whisper/companion-core": "0.0.0",
|
|
36
52
|
"@ai-whisper/broker": "0.0.0"
|
|
37
53
|
},
|