@vzn/vx 0.0.649 → 0.0.650
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/package.json +5 -5
- package/src/cache/cache.ts +24 -27
- package/src/cache/fold-memo.ts +8 -1
- package/src/cache/index.ts +11 -0
- package/src/cache/lockfile-memo.ts +119 -0
- package/src/cache/remote-hits.ts +9 -1
- package/src/cache/run-notes.ts +123 -0
- package/src/cache/schema.ts +43 -0
- package/src/cli/last.ts +12 -21
- package/src/cli/plugin-commands.ts +2 -1
- package/src/cli/why.ts +3 -3
- package/src/graph/scheduler.ts +11 -5
- package/src/history/history.ts +34 -2
- package/src/history/index.ts +3 -0
- package/src/index.ts +9 -2
- package/src/orchestrator/doctor.ts +2 -2
- package/src/orchestrator/hit-restore.ts +3 -0
- package/src/orchestrator/index.ts +0 -1
- package/src/orchestrator/live-usage.ts +93 -0
- package/src/orchestrator/lockfile-claim.ts +74 -79
- package/src/orchestrator/plugin.ts +2 -2
- package/src/orchestrator/prepare.ts +2 -1
- package/src/orchestrator/run-failures.ts +34 -113
- package/src/orchestrator/run.ts +47 -15
- package/src/orchestrator/steps.ts +2 -2
- package/src/report/events.ts +11 -3
- package/src/report/forecast.ts +24 -23
- package/src/report/framed-output.ts +156 -28
- package/src/report/index.ts +2 -1
- package/src/report/logger.ts +44 -15
- package/src/report/plain-output.ts +1 -1
- package/src/report/status-line.ts +38 -14
- package/src/report/summary.ts +4 -0
- package/src/util/colors.ts +3 -0
- package/src/util/hidden-prompt.ts +8 -2
- package/src/util/secrets.ts +3 -0
- package/src/orchestrator/run-steps.ts +0 -93
|
@@ -28,9 +28,15 @@ function askHidden(
|
|
|
28
28
|
output: { write(s: string): unknown },
|
|
29
29
|
interrupt: () => void,
|
|
30
30
|
): Promise<string> {
|
|
31
|
-
output.write(question)
|
|
32
31
|
const wasRaw = input.isRaw === true
|
|
33
|
-
|
|
32
|
+
// A terminal that refuses raw mode (EIO once its session is gone) cannot
|
|
33
|
+
// hide an answer: the rejection reaches the broker before any question.
|
|
34
|
+
try {
|
|
35
|
+
input.setRawMode(true)
|
|
36
|
+
} catch (err) {
|
|
37
|
+
return Promise.reject(err)
|
|
38
|
+
}
|
|
39
|
+
output.write(question)
|
|
34
40
|
input.resume()
|
|
35
41
|
return new Promise((resolve) => {
|
|
36
42
|
let line = ''
|
package/src/util/secrets.ts
CHANGED
|
@@ -146,6 +146,9 @@ export class SecretBroker {
|
|
|
146
146
|
let answer: string
|
|
147
147
|
try {
|
|
148
148
|
answer = (await this.terminal.ask(prompt)).trim()
|
|
149
|
+
} catch {
|
|
150
|
+
// The terminal could not take a hidden answer: nobody can answer.
|
|
151
|
+
throw unavailable(key, 'no-terminal')
|
|
149
152
|
} finally {
|
|
150
153
|
release()
|
|
151
154
|
}
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
// What a run said that its rows do not hold, for `vx last`: the steps it
|
|
2
|
-
// did not wait on (`vx:prefetch`, M 2026-10-16), which never show in a
|
|
3
|
-
// run's output, and its warnings, which scroll past on a terminal and are
|
|
4
|
-
// gone (an agent reading the run afterwards saw only the footer's count,
|
|
5
|
-
// 2026-10-28). One file per run that had any, `<cacheDir>/steps/<runId>.json`
|
|
6
|
-
// and `<cacheDir>/warnings/<runId>.json`, the newest 50 of each kept, as
|
|
7
|
-
// run-failures.ts keeps failed output: files, not cache.db, so the index
|
|
8
|
-
// layout stays as it was. A run with none writes nothing.
|
|
9
|
-
|
|
10
|
-
import { mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs'
|
|
11
|
-
import path from 'node:path'
|
|
12
|
-
import { isFsRefusal } from '../util/index.js'
|
|
13
|
-
import { trimKept } from './run-failures.js'
|
|
14
|
-
|
|
15
|
-
/** Runs whose steps (or warnings) are kept; run ids are UUIDv7, so names sort by age. */
|
|
16
|
-
const KEPT = 50
|
|
17
|
-
|
|
18
|
-
/** One of vx's own steps that ran beside the tasks. */
|
|
19
|
-
export interface RunStep {
|
|
20
|
-
id: string
|
|
21
|
-
durationMs: number
|
|
22
|
-
ok: boolean
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
type Kept = 'steps' | 'warnings'
|
|
26
|
-
|
|
27
|
-
function keep(
|
|
28
|
-
cacheDir: string,
|
|
29
|
-
kind: Kept,
|
|
30
|
-
runId: string,
|
|
31
|
-
value: readonly unknown[],
|
|
32
|
-
warn: (message: string) => void,
|
|
33
|
-
): void {
|
|
34
|
-
if (value.length === 0) return
|
|
35
|
-
try {
|
|
36
|
-
const dir = path.join(cacheDir, kind)
|
|
37
|
-
mkdirSync(dir, { recursive: true })
|
|
38
|
-
const file = path.join(dir, `${runId}.json`)
|
|
39
|
-
const tmp = `${file}.${process.pid}.tmp`
|
|
40
|
-
writeFileSync(tmp, JSON.stringify(value))
|
|
41
|
-
renameSync(tmp, file)
|
|
42
|
-
trimKept(dir, KEPT)
|
|
43
|
-
} catch (err) {
|
|
44
|
-
if (!isFsRefusal(err)) throw err
|
|
45
|
-
warn(
|
|
46
|
-
`[vx] ${kind === 'steps' ? 'background steps' : 'warnings'} not kept: ${err.message} — the verdict above stands`,
|
|
47
|
-
)
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
function kept<T>(cacheDir: string, kind: Kept, runId: string): T[] {
|
|
52
|
-
try {
|
|
53
|
-
return JSON.parse(readFileSync(path.join(cacheDir, kind, `${runId}.json`), 'utf8')) as T[]
|
|
54
|
-
} catch {
|
|
55
|
-
return []
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/** Keep `steps` for `runId`; a refused write costs only them. */
|
|
60
|
-
export function writeRunSteps(
|
|
61
|
-
cacheDir: string,
|
|
62
|
-
runId: string,
|
|
63
|
-
steps: readonly RunStep[],
|
|
64
|
-
warn: (message: string) => void,
|
|
65
|
-
): void {
|
|
66
|
-
keep(cacheDir, 'steps', runId, steps, warn)
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/** The background steps `runId` kept; none when it had none or they are gone. */
|
|
70
|
-
export function runSteps(cacheDir: string, runId: string): RunStep[] {
|
|
71
|
-
return kept<RunStep>(cacheDir, 'steps', runId)
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/** Keep the run's warnings as plain text, colour stripped; a refused write costs only them. */
|
|
75
|
-
export function writeRunWarnings(
|
|
76
|
-
cacheDir: string,
|
|
77
|
-
runId: string,
|
|
78
|
-
warnings: readonly string[],
|
|
79
|
-
warn: (message: string) => void,
|
|
80
|
-
): void {
|
|
81
|
-
keep(
|
|
82
|
-
cacheDir,
|
|
83
|
-
'warnings',
|
|
84
|
-
runId,
|
|
85
|
-
warnings.map((w) => Bun.stripANSI(w)),
|
|
86
|
-
warn,
|
|
87
|
-
)
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/** The warnings `runId` said; none when it said none or they are gone. */
|
|
91
|
-
export function runWarnings(cacheDir: string, runId: string): string[] {
|
|
92
|
-
return kept<string>(cacheDir, 'warnings', runId)
|
|
93
|
-
}
|