@openparachute/vault 0.6.5-rc.9 → 0.6.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/.parachute/module.json +1 -0
- package/core/src/core.test.ts +7 -7
- package/core/src/mcp.ts +1 -1
- package/core/src/schema.ts +5 -5
- package/core/src/seed-packs.test.ts +222 -56
- package/core/src/seed-packs.ts +334 -70
- package/core/src/tag-hierarchy.ts +1 -1
- package/core/src/tag-schemas.ts +2 -2
- package/core/src/types.ts +1 -1
- package/package.json +1 -1
- package/src/admin-spa.ts +2 -1
- package/src/auth.ts +1 -1
- package/src/cli.ts +317 -53
- package/src/export-watch.ts +1 -1
- package/src/live-frame-parity.test.ts +201 -0
- package/src/module-manifest.ts +8 -0
- package/src/onboarding-seed.test.ts +82 -20
- package/src/onboarding-seed.ts +2 -2
- package/src/routes.ts +3 -3
- package/src/routing.test.ts +2 -2
- package/src/routing.ts +18 -6
- package/src/self-register.test.ts +19 -0
- package/src/self-register.ts +6 -1
- package/src/server.ts +56 -0
- package/src/services-manifest.ts +8 -0
- package/src/subscriptions.ts +100 -42
- package/src/tag-scope.ts +3 -3
- package/src/test-support/live-frame-corpus.ts +72 -0
- package/src/token-store.ts +2 -2
- package/src/transcription/build.test.ts +86 -5
- package/src/transcription/build.ts +87 -7
- package/src/transcription/capability.test.ts +25 -0
- package/src/transcription/capability.ts +27 -2
- package/src/transcription/download.test.ts +101 -0
- package/src/transcription/download.ts +71 -0
- package/src/transcription/install-python.test.ts +366 -0
- package/src/transcription/install-python.ts +471 -0
- package/src/transcription/providers/onnx-asr.test.ts +229 -0
- package/src/transcription/providers/onnx-asr.ts +239 -0
- package/src/transcription/providers/parakeet-mlx.test.ts +290 -0
- package/src/transcription/providers/parakeet-mlx.ts +242 -0
- package/src/transcription/select.test.ts +166 -1
- package/src/transcription/select.ts +234 -1
- package/src/transcription/tiers.test.ts +197 -0
- package/src/transcription/tiers.ts +184 -0
- package/src/vault-create.test.ts +19 -14
- package/src/vault.test.ts +1 -1
- package/src/ws-server.ts +408 -0
- package/src/ws-subscribe.test.ts +474 -0
- package/src/ws-subscribe.ts +242 -0
- package/src/subscribe.test.ts +0 -609
- package/src/subscribe.ts +0 -248
package/src/cli.ts
CHANGED
|
@@ -152,8 +152,20 @@ import {
|
|
|
152
152
|
resolveTranscribeCppPaths,
|
|
153
153
|
resolveTranscriptionProviderName,
|
|
154
154
|
transcribeCppInstalled,
|
|
155
|
+
probeTranscribeCliRunnable,
|
|
155
156
|
readManifest,
|
|
157
|
+
transcriptionHomeDir,
|
|
158
|
+
pythonVenvDir,
|
|
159
|
+
pythonManifestPath,
|
|
160
|
+
readPythonManifest,
|
|
161
|
+
resolveParakeetMlxBin,
|
|
162
|
+
resolveParakeetMlxModel,
|
|
163
|
+
resolveOnnxAsrBin,
|
|
164
|
+
resolveOnnxAsrModel,
|
|
165
|
+
parakeetMlxInstalled,
|
|
166
|
+
onnxAsrInstalled,
|
|
156
167
|
type TranscribeCppManifest,
|
|
168
|
+
type PythonInstallManifest,
|
|
157
169
|
} from "./transcription/select.ts";
|
|
158
170
|
import {
|
|
159
171
|
buildTranscribeCli,
|
|
@@ -162,6 +174,14 @@ import {
|
|
|
162
174
|
TRANSCRIBE_CPP_SOURCE_REF,
|
|
163
175
|
type CliBuildResult,
|
|
164
176
|
} from "./transcription/build.ts";
|
|
177
|
+
import { downloadTo } from "./transcription/download.ts";
|
|
178
|
+
import { selectDefaultProvider, NOMINAL_SLACK_GB, type TierPlan } from "./transcription/tiers.ts";
|
|
179
|
+
import {
|
|
180
|
+
PYTHON_PROVIDERS,
|
|
181
|
+
buildDefaultPythonDeps,
|
|
182
|
+
installPythonBackend,
|
|
183
|
+
type PythonProviderName,
|
|
184
|
+
} from "./transcription/install-python.ts";
|
|
165
185
|
|
|
166
186
|
// ---------------------------------------------------------------------------
|
|
167
187
|
// Argument parsing
|
|
@@ -3529,17 +3549,23 @@ function printHistoryUsage(): void {
|
|
|
3529
3549
|
// ---------------------------------------------------------------------------
|
|
3530
3550
|
|
|
3531
3551
|
/**
|
|
3532
|
-
* `parachute-vault transcription install` — set up
|
|
3533
|
-
* provider
|
|
3534
|
-
* (scribe
|
|
3535
|
-
*
|
|
3536
|
-
*
|
|
3537
|
-
*
|
|
3538
|
-
*
|
|
3539
|
-
*
|
|
3552
|
+
* `parachute-vault transcription install` — set up a LOCAL transcription
|
|
3553
|
+
* provider. With no `--provider`, the ratified RAM/arch/OS tier table
|
|
3554
|
+
* (scribe-fold Phase 2b, `tiers.ts`) picks the host's default:
|
|
3555
|
+
*
|
|
3556
|
+
* - macOS Apple Silicon 8GB+ → parakeet-mlx (Python venv, MLX)
|
|
3557
|
+
* - Linux 4GB+ → onnx-asr (Python venv, int8 ONNX)
|
|
3558
|
+
* - Linux ~2GB → transcribe-cpp + small whisper GGUF
|
|
3559
|
+
* - ~1GB / below floor → remote steer (scribe-http), never forced
|
|
3560
|
+
*
|
|
3561
|
+
* The pick + footprint is printed and the operator confirms (or overrides
|
|
3562
|
+
* with `--provider`/`--model`). Every path is idempotent + non-fatal, and
|
|
3563
|
+
* activation is HONEST: `TRANSCRIPTION_PROVIDER` flips only when a runnable
|
|
3564
|
+
* binary actually exists (PRs #532/#533 precedent). `--dry-run`/`--plan`
|
|
3565
|
+
* prints the selection without downloading.
|
|
3540
3566
|
*
|
|
3541
3567
|
* `parachute-vault transcription status` — show the configured provider +
|
|
3542
|
-
* install state.
|
|
3568
|
+
* per-provider install state.
|
|
3543
3569
|
*/
|
|
3544
3570
|
async function cmdTranscription(args: string[]) {
|
|
3545
3571
|
const sub = args[0];
|
|
@@ -3548,11 +3574,13 @@ async function cmdTranscription(args: string[]) {
|
|
|
3548
3574
|
return;
|
|
3549
3575
|
}
|
|
3550
3576
|
if (sub === "status" || sub === undefined) {
|
|
3551
|
-
cmdTranscriptionStatus();
|
|
3577
|
+
await cmdTranscriptionStatus();
|
|
3552
3578
|
return;
|
|
3553
3579
|
}
|
|
3554
3580
|
console.error(`Unknown transcription subcommand: ${sub}`);
|
|
3555
|
-
console.error(
|
|
3581
|
+
console.error(
|
|
3582
|
+
"Usage: parachute-vault transcription install [--dry-run] [--model <id>] [--provider <transcribe-cpp|parakeet-mlx|onnx-asr|scribe-http>]",
|
|
3583
|
+
);
|
|
3556
3584
|
console.error(" parachute-vault transcription status");
|
|
3557
3585
|
process.exit(1);
|
|
3558
3586
|
}
|
|
@@ -3576,9 +3604,9 @@ async function cmdTranscriptionInstall(args: string[]) {
|
|
|
3576
3604
|
const force = args.includes("--force");
|
|
3577
3605
|
const yes = args.includes("--yes") || args.includes("-y");
|
|
3578
3606
|
const overrideModel = takeArgValue(args, "--model").value;
|
|
3579
|
-
const
|
|
3607
|
+
const providerArg = takeArgValue(args, "--provider").value;
|
|
3580
3608
|
|
|
3581
|
-
if (
|
|
3609
|
+
if (providerArg === "scribe-http") {
|
|
3582
3610
|
// Just flip config back to the remote provider — no download.
|
|
3583
3611
|
if (dryRun) {
|
|
3584
3612
|
console.log("Would set TRANSCRIPTION_PROVIDER=scribe-http in the vault .env (remote provider; no download).");
|
|
@@ -3588,11 +3616,162 @@ async function cmdTranscriptionInstall(args: string[]) {
|
|
|
3588
3616
|
console.log("Set TRANSCRIPTION_PROVIDER=scribe-http. Restart vault to apply. (Remote provider — no local binary/model needed.)");
|
|
3589
3617
|
return;
|
|
3590
3618
|
}
|
|
3591
|
-
|
|
3592
|
-
|
|
3619
|
+
|
|
3620
|
+
let provider: string;
|
|
3621
|
+
let tierModel: string | undefined;
|
|
3622
|
+
if (providerArg) {
|
|
3623
|
+
if (!["transcribe-cpp", "parakeet-mlx", "onnx-asr"].includes(providerArg)) {
|
|
3624
|
+
console.error(
|
|
3625
|
+
`Unknown --provider "${providerArg}". Valid: transcribe-cpp, parakeet-mlx, onnx-asr, scribe-http.`,
|
|
3626
|
+
);
|
|
3627
|
+
process.exit(1);
|
|
3628
|
+
}
|
|
3629
|
+
provider = providerArg;
|
|
3630
|
+
} else {
|
|
3631
|
+
// Auto-default: the ratified RAM/arch/OS tier table (tiers.ts). Probe the
|
|
3632
|
+
// host, print the pick + footprint; the operator confirms below (or
|
|
3633
|
+
// re-runs with --provider/--model to override).
|
|
3634
|
+
const tier = selectDefaultProvider({
|
|
3635
|
+
platform: process.platform,
|
|
3636
|
+
arch: process.arch,
|
|
3637
|
+
totalRamBytes: detectTotalRamBytes(),
|
|
3638
|
+
});
|
|
3639
|
+
printTierPick(tier);
|
|
3640
|
+
if (tier.provider === "scribe-http") {
|
|
3641
|
+
// Remote steer — never force a local install on a below-tier box.
|
|
3642
|
+
console.log("\nNo local install performed. To point at a remote provider now:");
|
|
3643
|
+
console.log(" parachute-vault transcription install --provider scribe-http");
|
|
3644
|
+
if (tier.localOptIn) {
|
|
3645
|
+
console.log(`\nLocal opt-in (explicit only — not auto-installed): ${tier.localOptIn.note}`);
|
|
3646
|
+
}
|
|
3647
|
+
process.exit(dryRun ? 0 : 1);
|
|
3648
|
+
}
|
|
3649
|
+
provider = tier.provider;
|
|
3650
|
+
tierModel = tier.model;
|
|
3651
|
+
console.log("");
|
|
3652
|
+
}
|
|
3653
|
+
|
|
3654
|
+
if (provider === "transcribe-cpp") {
|
|
3655
|
+
// The tier's model pick (e.g. the Linux ~2GB whisper-small tier) seeds the
|
|
3656
|
+
// transcribe-cpp flow; an explicit --model always wins.
|
|
3657
|
+
await runTranscribeCppInstall({ dryRun, force, yes, overrideModel: overrideModel ?? tierModel });
|
|
3658
|
+
return;
|
|
3659
|
+
}
|
|
3660
|
+
await runPythonProviderInstall(provider as PythonProviderName, {
|
|
3661
|
+
dryRun,
|
|
3662
|
+
force,
|
|
3663
|
+
yes,
|
|
3664
|
+
overrideModel,
|
|
3665
|
+
});
|
|
3666
|
+
}
|
|
3667
|
+
|
|
3668
|
+
/** Print the tier-table pick for this host (the install auto-default). */
|
|
3669
|
+
function printTierPick(tier: TierPlan): void {
|
|
3670
|
+
console.log(`Host: ${tier.platform}/${tier.arch}, ${tier.totalRamGb}GB RAM`);
|
|
3671
|
+
console.log(`Tier default: ${tier.provider}${tier.model ? ` (${tier.model})` : ""}`);
|
|
3672
|
+
console.log(` ${tier.reason}`);
|
|
3673
|
+
if (tier.approxDiskMb) {
|
|
3674
|
+
console.log(` ~${tier.approxDiskMb}MB download${tier.peakRamNote ? `, ${tier.peakRamNote}` : ""}`);
|
|
3675
|
+
}
|
|
3676
|
+
console.log(" (override with --provider <transcribe-cpp|parakeet-mlx|onnx-asr|scribe-http>)");
|
|
3677
|
+
}
|
|
3678
|
+
|
|
3679
|
+
/**
|
|
3680
|
+
* Install a Python-based local provider (parakeet-mlx / onnx-asr) into the
|
|
3681
|
+
* managed venv under `~/.parachute/transcription/venv/` and — honestly —
|
|
3682
|
+
* activate it only when a runnable binary verified (`install-python.ts` owns
|
|
3683
|
+
* the apt/venv/warm-pull steps; activation + manifest stay here, mirroring
|
|
3684
|
+
* the transcribe-cpp flow).
|
|
3685
|
+
*/
|
|
3686
|
+
async function runPythonProviderInstall(
|
|
3687
|
+
provider: PythonProviderName,
|
|
3688
|
+
opts: { dryRun: boolean; force: boolean; yes: boolean; overrideModel?: string },
|
|
3689
|
+
): Promise<void> {
|
|
3690
|
+
const spec = PYTHON_PROVIDERS[provider];
|
|
3691
|
+
const venv = pythonVenvDir();
|
|
3692
|
+
// `--model` wins; else env/manifest/ratified default. The pick lands in the
|
|
3693
|
+
// install manifest, which the runtime model resolution reads back.
|
|
3694
|
+
const model =
|
|
3695
|
+
opts.overrideModel ??
|
|
3696
|
+
(provider === "parakeet-mlx" ? resolveParakeetMlxModel() : resolveOnnxAsrModel());
|
|
3697
|
+
const totalRamGb = Math.round((detectTotalRamBytes() / 2 ** 30) * 10) / 10;
|
|
3698
|
+
|
|
3699
|
+
console.log(`Transcription install plan (${provider} — local, Python venv):\n`);
|
|
3700
|
+
console.log(`Host: ${process.platform}/${process.arch}, ${totalRamGb}GB RAM`);
|
|
3701
|
+
console.log(`Package: ${spec.pipTarget} → ${venv}`);
|
|
3702
|
+
console.log(`Model: ${model}`);
|
|
3703
|
+
console.log(` ~${spec.approxDiskMb}MB model download, ${spec.peakRamNote}`);
|
|
3704
|
+
|
|
3705
|
+
if (opts.dryRun) {
|
|
3706
|
+
// Preview the guards the real run would hit — pure, no side effects.
|
|
3707
|
+
if (spec.platform && spec.platform !== process.platform) {
|
|
3708
|
+
console.log(`\n Refused: ${provider} only runs on ${spec.platform}; this host is ${process.platform}.`);
|
|
3709
|
+
} else if (spec.arch && spec.arch !== process.arch) {
|
|
3710
|
+
console.log(`\n Refused: ${provider} needs ${spec.arch} (Apple Silicon); this host is ${process.arch}.`);
|
|
3711
|
+
} else if (totalRamGb < spec.minRamGb - NOMINAL_SLACK_GB && !opts.force) {
|
|
3712
|
+
console.log(`\n Refused: ${totalRamGb}GB RAM < the ~${spec.minRamGb}GB ${provider} floor. ${spec.ramFloorRationale}`);
|
|
3713
|
+
}
|
|
3714
|
+
console.log("\n(--dry-run) Nothing installed.");
|
|
3715
|
+
return;
|
|
3716
|
+
}
|
|
3717
|
+
|
|
3718
|
+
if (!opts.yes) {
|
|
3719
|
+
const ok = await confirm(
|
|
3720
|
+
`Install ${spec.pipTarget} into ${venv} (model ~${spec.approxDiskMb}MB ${provider === "parakeet-mlx" ? "downloads on first use" : "warm-pulled now"})?`,
|
|
3721
|
+
true,
|
|
3722
|
+
);
|
|
3723
|
+
if (!ok) {
|
|
3724
|
+
console.log("Aborted.");
|
|
3725
|
+
return;
|
|
3726
|
+
}
|
|
3727
|
+
}
|
|
3728
|
+
|
|
3729
|
+
const outcome = await installPythonBackend(buildDefaultPythonDeps(), {
|
|
3730
|
+
provider,
|
|
3731
|
+
force: opts.force,
|
|
3732
|
+
model,
|
|
3733
|
+
});
|
|
3734
|
+
|
|
3735
|
+
if (!outcome.ok || !outcome.binPath) {
|
|
3736
|
+
console.error(`\n✗ ${outcome.summary}`);
|
|
3737
|
+
console.error(
|
|
3738
|
+
"Your current provider is unchanged — the verb is idempotent; fix the issue and re-run. Or use the remote provider: parachute-vault transcription install --provider scribe-http",
|
|
3739
|
+
);
|
|
3593
3740
|
process.exit(1);
|
|
3594
3741
|
}
|
|
3595
3742
|
|
|
3743
|
+
// Manifest + honest activation (a runnable binary exists — verified above).
|
|
3744
|
+
const manifest: PythonInstallManifest = {
|
|
3745
|
+
provider,
|
|
3746
|
+
pipTarget: spec.pipTarget,
|
|
3747
|
+
bin: outcome.binPath,
|
|
3748
|
+
venv: outcome.venv ?? "",
|
|
3749
|
+
model,
|
|
3750
|
+
os: process.platform,
|
|
3751
|
+
arch: process.arch,
|
|
3752
|
+
ram_gb: totalRamGb,
|
|
3753
|
+
installedAt: new Date().toISOString(),
|
|
3754
|
+
};
|
|
3755
|
+
mkdirSync(transcriptionHomeDir(), { recursive: true });
|
|
3756
|
+
writeFileSync(pythonManifestPath(), JSON.stringify(manifest, null, 2));
|
|
3757
|
+
|
|
3758
|
+
setEnvVar("TRANSCRIPTION_PROVIDER", provider);
|
|
3759
|
+
console.log(`\n✓ Installed and activated → TRANSCRIPTION_PROVIDER=${provider} set in the vault .env.`);
|
|
3760
|
+
console.log(` Binary: ${outcome.binPath}`);
|
|
3761
|
+
console.log(` Model: ${model}`);
|
|
3762
|
+
if (provider === "parakeet-mlx") {
|
|
3763
|
+
console.log(` NOTE: the model (~${spec.approxDiskMb}MB) downloads into the HuggingFace cache on the first transcription.`);
|
|
3764
|
+
}
|
|
3765
|
+
console.log(` Restart vault to activate: parachute restart vault`);
|
|
3766
|
+
}
|
|
3767
|
+
|
|
3768
|
+
async function runTranscribeCppInstall(opts: {
|
|
3769
|
+
dryRun: boolean;
|
|
3770
|
+
force: boolean;
|
|
3771
|
+
yes: boolean;
|
|
3772
|
+
overrideModel?: string;
|
|
3773
|
+
}) {
|
|
3774
|
+
const { dryRun, force, yes, overrideModel } = opts;
|
|
3596
3775
|
const plan = planInstall({
|
|
3597
3776
|
platform: process.platform,
|
|
3598
3777
|
arch: process.arch,
|
|
@@ -3690,14 +3869,25 @@ async function cmdTranscriptionInstall(args: string[]) {
|
|
|
3690
3869
|
|
|
3691
3870
|
// 5) CLI resolution + provider switch — honest, no silent success. `binPath`
|
|
3692
3871
|
// resolves to TRANSCRIBE_CPP_BIN or the built binary; we activate
|
|
3693
|
-
// transcribe-cpp only when one actually
|
|
3694
|
-
//
|
|
3695
|
-
//
|
|
3872
|
+
// transcribe-cpp only when one actually EXECUTES (`--help` exits 0 —
|
|
3873
|
+
// vault#534: an existsSync-only check activated Linux installs whose CLI
|
|
3874
|
+
// exited 1 on every run). Otherwise we keep the current provider and
|
|
3875
|
+
// report the gap rather than taking transcription offline behind a
|
|
3876
|
+
// provider that can't run.
|
|
3696
3877
|
if (existsSync(paths.binPath)) {
|
|
3697
|
-
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
|
|
3878
|
+
const probe = await probeTranscribeCliRunnable(paths.binPath);
|
|
3879
|
+
if (probe.ok) {
|
|
3880
|
+
setEnvVar("TRANSCRIPTION_PROVIDER", "transcribe-cpp");
|
|
3881
|
+
console.log(`\n✓ Installed and activated → TRANSCRIPTION_PROVIDER=transcribe-cpp set in the vault .env.`);
|
|
3882
|
+
console.log(` CLI: ${paths.binPath} (verified runnable)`);
|
|
3883
|
+
console.log(` Restart vault to activate: parachute restart vault`);
|
|
3884
|
+
} else {
|
|
3885
|
+
console.log(
|
|
3886
|
+
`\n⚠ transcribe-cli exists at ${paths.binPath} but is NOT runnable (${probe.reason}).`,
|
|
3887
|
+
);
|
|
3888
|
+
console.log(" NOT activating transcribe-cpp — your current provider is unchanged.");
|
|
3889
|
+
console.log(noRunnableCliGuidance(paths, buildResult));
|
|
3890
|
+
}
|
|
3701
3891
|
} else {
|
|
3702
3892
|
console.log(`\n✓ Libraries + model installed to ${paths.dir} — transcription is NOT yet activated.`);
|
|
3703
3893
|
console.log(noRunnableCliGuidance(paths, buildResult));
|
|
@@ -3709,13 +3899,6 @@ async function cmdTranscriptionInstall(args: string[]) {
|
|
|
3709
3899
|
}
|
|
3710
3900
|
}
|
|
3711
3901
|
|
|
3712
|
-
/** Download a URL to a destination file (streamed via fetch → Bun.write). */
|
|
3713
|
-
async function downloadTo(url: string, dest: string): Promise<void> {
|
|
3714
|
-
const resp = await fetch(url, { redirect: "follow" });
|
|
3715
|
-
if (!resp.ok) throw new Error(`download failed (${resp.status}) for ${url}`);
|
|
3716
|
-
await Bun.write(dest, resp);
|
|
3717
|
-
}
|
|
3718
|
-
|
|
3719
3902
|
/**
|
|
3720
3903
|
* Download the release tarball, extract it, and place its runtime shared
|
|
3721
3904
|
* libraries (libtranscribe + libggml `.dylib`/`.so`) into `paths.libsDir`,
|
|
@@ -3807,6 +3990,8 @@ async function maybeBuildTranscribeCli(
|
|
|
3807
3990
|
await downloadTo(cliSourceUrl(rel), dest);
|
|
3808
3991
|
}
|
|
3809
3992
|
},
|
|
3993
|
+
readFile: (p) => readFileSync(p, "utf8"),
|
|
3994
|
+
writeFile: (p, content) => writeFileSync(p, content),
|
|
3810
3995
|
compile: (cmd) => {
|
|
3811
3996
|
const p = Bun.spawnSync(cmd);
|
|
3812
3997
|
return { exitCode: p.exitCode ?? 1, stderr: new TextDecoder().decode(p.stderr) };
|
|
@@ -3855,6 +4040,14 @@ function noRunnableCliGuidance(
|
|
|
3855
4040
|
" • build transcribe-cli yourself, point TRANSCRIBE_CPP_BIN at it, and re-run; OR",
|
|
3856
4041
|
" • use the remote provider: parachute-vault transcription install --provider scribe-http",
|
|
3857
4042
|
);
|
|
4043
|
+
} else if (build && !build.ok && build.stage === "patch") {
|
|
4044
|
+
lines.push(
|
|
4045
|
+
`\n⚠ Could not apply the vault#534 backend-init source patch — ${build.message}`,
|
|
4046
|
+
" The pinned upstream source no longer matches the patch anchor. This needs a code fix",
|
|
4047
|
+
" (re-anchor or drop the patch), not a toolchain fix. Until then, either:",
|
|
4048
|
+
" • build a transcribe-cli yourself, point TRANSCRIBE_CPP_BIN at it, and re-run; OR",
|
|
4049
|
+
" • use the remote provider: parachute-vault transcription install --provider scribe-http",
|
|
4050
|
+
);
|
|
3858
4051
|
} else if (build && !build.ok) {
|
|
3859
4052
|
lines.push(
|
|
3860
4053
|
`\n⚠ transcribe-cli build failed (${build.stage}). The libraries + model are installed;`,
|
|
@@ -3877,15 +4070,39 @@ function noRunnableCliGuidance(
|
|
|
3877
4070
|
return lines.join("\n");
|
|
3878
4071
|
}
|
|
3879
4072
|
|
|
3880
|
-
/** `parachute-vault transcription status` — provider + install state. */
|
|
3881
|
-
function cmdTranscriptionStatus(): void {
|
|
4073
|
+
/** `parachute-vault transcription status` — provider + per-provider install state. */
|
|
4074
|
+
async function cmdTranscriptionStatus(): Promise<void> {
|
|
3882
4075
|
const active = resolveTranscriptionProviderName();
|
|
3883
4076
|
console.log(`Configured provider: ${active}`);
|
|
4077
|
+
|
|
4078
|
+
// What the ratified tier table would pick for this host (install default).
|
|
4079
|
+
const tier = selectDefaultProvider({
|
|
4080
|
+
platform: process.platform,
|
|
4081
|
+
arch: process.arch,
|
|
4082
|
+
totalRamBytes: detectTotalRamBytes(),
|
|
4083
|
+
});
|
|
4084
|
+
console.log(
|
|
4085
|
+
`Tier default for this host (${tier.platform}/${tier.arch}, ${tier.totalRamGb}GB): ${tier.provider}${tier.model ? ` (${tier.model})` : ""}`,
|
|
4086
|
+
);
|
|
4087
|
+
|
|
4088
|
+
// transcribe-cpp — prebuilt libs + GGUF model + built CLI. "runnable" is an
|
|
4089
|
+
// EXECUTED verdict, not a stat: `--help` must actually exit 0 (vault#534 —
|
|
4090
|
+
// an existsSync-only check said "yes" on Linux while the CLI exited 1 on
|
|
4091
|
+
// every real transcription because its dlopen'd CPU backends never loaded).
|
|
3884
4092
|
const paths = resolveTranscribeCppPaths();
|
|
3885
4093
|
const manifest = readManifest(paths.manifestPath);
|
|
3886
4094
|
const cliPresent = existsSync(paths.binPath);
|
|
3887
|
-
const
|
|
3888
|
-
|
|
4095
|
+
const filesPresent = transcribeCppInstalled(paths); // CLI + model both on disk
|
|
4096
|
+
let installed = false;
|
|
4097
|
+
let notRunnableReason: string | undefined;
|
|
4098
|
+
if (!filesPresent) {
|
|
4099
|
+
notRunnableReason = !cliPresent ? "no transcribe-cli binary" : "no GGUF model on disk";
|
|
4100
|
+
} else {
|
|
4101
|
+
const probe = await probeTranscribeCliRunnable(paths.binPath);
|
|
4102
|
+
installed = probe.ok;
|
|
4103
|
+
notRunnableReason = probe.reason;
|
|
4104
|
+
}
|
|
4105
|
+
console.log(`\ntranscribe-cpp runnable: ${installed ? "yes" : `no (${notRunnableReason})`}`);
|
|
3889
4106
|
if (manifest) {
|
|
3890
4107
|
console.log(` model: ${manifest.model} (${manifest.modelFile})`);
|
|
3891
4108
|
console.log(
|
|
@@ -3898,14 +4115,56 @@ function cmdTranscriptionStatus(): void {
|
|
|
3898
4115
|
);
|
|
3899
4116
|
console.log(` ram: ${manifest.ram_gb}GB at install (${manifest.os}/${manifest.arch})`);
|
|
3900
4117
|
} else {
|
|
3901
|
-
console.log(` (
|
|
4118
|
+
console.log(` (not installed — run: parachute-vault transcription install --provider transcribe-cpp)`);
|
|
3902
4119
|
}
|
|
3903
|
-
|
|
4120
|
+
|
|
4121
|
+
// parakeet-mlx / onnx-asr — Python venv providers (scribe-fold Phase 2b).
|
|
4122
|
+
const pyManifest = readPythonManifest(pythonManifestPath());
|
|
4123
|
+
const pkBin = resolveParakeetMlxBin();
|
|
4124
|
+
const pkRunnable = parakeetMlxInstalled();
|
|
4125
|
+
console.log(`\nparakeet-mlx runnable: ${pkRunnable ? "yes" : "no"}`);
|
|
4126
|
+
if (pkRunnable) {
|
|
4127
|
+
console.log(` bin: ${pkBin}`);
|
|
4128
|
+
console.log(` model: ${resolveParakeetMlxModel()} (HF cache; downloads on first use)`);
|
|
4129
|
+
} else {
|
|
3904
4130
|
console.log(
|
|
3905
|
-
|
|
4131
|
+
process.platform === "darwin" && process.arch === "arm64"
|
|
4132
|
+
? ` (not installed — run: parachute-vault transcription install${tier.provider === "parakeet-mlx" ? "" : " --provider parakeet-mlx"})`
|
|
4133
|
+
: " (macOS Apple Silicon only)",
|
|
3906
4134
|
);
|
|
3907
4135
|
}
|
|
3908
|
-
|
|
4136
|
+
|
|
4137
|
+
const oxBin = resolveOnnxAsrBin();
|
|
4138
|
+
const oxRunnable = onnxAsrInstalled();
|
|
4139
|
+
console.log(`onnx-asr runnable: ${oxRunnable ? "yes" : "no"}`);
|
|
4140
|
+
if (oxRunnable) {
|
|
4141
|
+
console.log(` bin: ${oxBin}`);
|
|
4142
|
+
console.log(` model: ${resolveOnnxAsrModel()} (HF cache)`);
|
|
4143
|
+
} else {
|
|
4144
|
+
console.log(
|
|
4145
|
+
` (not installed — run: parachute-vault transcription install${tier.provider === "onnx-asr" ? "" : " --provider onnx-asr"})`,
|
|
4146
|
+
);
|
|
4147
|
+
}
|
|
4148
|
+
if (pyManifest) {
|
|
4149
|
+
console.log(
|
|
4150
|
+
` python install: ${pyManifest.provider} (${pyManifest.pipTarget}) @ ${pyManifest.installedAt}${pyManifest.venv ? ` — venv ${pyManifest.venv}` : ""}`,
|
|
4151
|
+
);
|
|
4152
|
+
}
|
|
4153
|
+
|
|
4154
|
+
// Offline warning when the ACTIVE provider isn't runnable.
|
|
4155
|
+
const activeRunnable =
|
|
4156
|
+
active === "scribe-http" ||
|
|
4157
|
+
(active === "transcribe-cpp" && installed) ||
|
|
4158
|
+
(active === "parakeet-mlx" && pkRunnable) ||
|
|
4159
|
+
(active === "onnx-asr" && oxRunnable);
|
|
4160
|
+
if (!activeRunnable) {
|
|
4161
|
+
console.log(
|
|
4162
|
+
`\n⚠ provider is ${active} but no runnable ${active} install was found — transcription is offline until one is available (\`parachute-vault transcription install\`).`,
|
|
4163
|
+
);
|
|
4164
|
+
}
|
|
4165
|
+
console.log(
|
|
4166
|
+
`\nAvailable transcribe-cpp models (override with --model): ${Object.values(MODELS).map((m: ModelChoice) => m.name).join(", ")}`,
|
|
4167
|
+
);
|
|
3909
4168
|
}
|
|
3910
4169
|
|
|
3911
4170
|
// ---------------------------------------------------------------------------
|
|
@@ -4816,22 +5075,27 @@ Schema maintenance:
|
|
|
4816
5075
|
|
|
4817
5076
|
Transcription (scribe-fold):
|
|
4818
5077
|
parachute-vault transcription install [--dry-run] [--model <id>] [--force] [--yes]
|
|
4819
|
-
Install
|
|
4820
|
-
OS/arch + RAM,
|
|
4821
|
-
|
|
4822
|
-
|
|
4823
|
-
|
|
4824
|
-
|
|
4825
|
-
|
|
4826
|
-
|
|
4827
|
-
pick
|
|
4828
|
-
RAM
|
|
4829
|
-
|
|
4830
|
-
|
|
4831
|
-
|
|
4832
|
-
|
|
4833
|
-
|
|
4834
|
-
|
|
5078
|
+
Install this host's tier-default LOCAL provider (probes
|
|
5079
|
+
OS/arch + RAM, prints the pick + footprint, confirms):
|
|
5080
|
+
macOS Apple Silicon 8GB+ → parakeet-mlx (Python venv, MLX)
|
|
5081
|
+
Linux 4GB+ → onnx-asr (Python venv, int8 ONNX)
|
|
5082
|
+
Linux ~2GB → transcribe-cpp + small whisper GGUF
|
|
5083
|
+
~1GB / below floor → remote steer (never forced)
|
|
5084
|
+
Activation is honest: TRANSCRIPTION_PROVIDER flips only when
|
|
5085
|
+
a runnable binary exists. Idempotent; --dry-run prints the
|
|
5086
|
+
pick without downloading; --force re-downloads / bypasses the
|
|
5087
|
+
RAM floor on an explicit --provider; --yes skips the confirm.
|
|
5088
|
+
parachute-vault transcription install --provider <name>
|
|
5089
|
+
Override the tier default. transcribe-cpp downloads the
|
|
5090
|
+
runtime libs + a GGUF (--model overrides the RAM-tier pick:
|
|
5091
|
+
whisper-tiny.en | whisper-small.en | parakeet-tdt-0.6b-v3;
|
|
5092
|
+
builds transcribe-cli from source — needs a C++ compiler).
|
|
5093
|
+
parakeet-mlx / onnx-asr install a Python venv under
|
|
5094
|
+
~/.parachute/transcription/venv (needs python3; apt-installs
|
|
5095
|
+
python3/ffmpeg on Linux). scribe-http switches back to the
|
|
5096
|
+
remote provider (no download).
|
|
5097
|
+
parachute-vault transcription status Show the configured provider, this host's tier default, and
|
|
5098
|
+
per-provider install state.
|
|
4835
5099
|
|
|
4836
5100
|
── Advanced / standalone ──────────────────────────────────────────────
|
|
4837
5101
|
|
package/src/export-watch.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* cursor captured at the *start* of the previous cycle. Vault writes are
|
|
11
11
|
* HTTP-mediated and don't surface to filesystem watchers (the bun:sqlite DB
|
|
12
12
|
* is opaque), so polling on `updated_at >= cursor` is the simplest robust
|
|
13
|
-
* detection. See `
|
|
13
|
+
* detection. See `docs/contracts/vault-portable-export.md`.
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
16
|
import { ensureGitAvailable } from "./git-preflight.ts";
|