myshell-tools 1.0.0 → 2.0.0
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/CHANGELOG.md +44 -69
- package/LICENSE +21 -21
- package/README.md +178 -318
- package/dist/cli.d.ts +8 -0
- package/dist/cli.js +130 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/cost.d.ts +36 -0
- package/dist/commands/cost.js +103 -0
- package/dist/commands/cost.js.map +1 -0
- package/dist/commands/doctor.d.ts +36 -0
- package/dist/commands/doctor.js +115 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/login.d.ts +20 -0
- package/dist/commands/login.js +60 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/core/assess.d.ts +25 -0
- package/dist/core/assess.js +142 -0
- package/dist/core/assess.js.map +1 -0
- package/dist/core/classify.d.ts +19 -0
- package/dist/core/classify.js +80 -0
- package/dist/core/classify.js.map +1 -0
- package/dist/core/escalate.d.ts +32 -0
- package/dist/core/escalate.js +57 -0
- package/dist/core/escalate.js.map +1 -0
- package/dist/core/index.d.ts +13 -0
- package/dist/core/index.js +12 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/orchestrate.d.ts +42 -0
- package/dist/core/orchestrate.js +439 -0
- package/dist/core/orchestrate.js.map +1 -0
- package/dist/core/policy.d.ts +9 -0
- package/dist/core/policy.js +27 -0
- package/dist/core/policy.js.map +1 -0
- package/dist/core/prompt.d.ts +26 -0
- package/dist/core/prompt.js +125 -0
- package/dist/core/prompt.js.map +1 -0
- package/dist/core/review.d.ts +46 -0
- package/dist/core/review.js +148 -0
- package/dist/core/review.js.map +1 -0
- package/dist/core/route.d.ts +28 -0
- package/dist/core/route.js +52 -0
- package/dist/core/route.js.map +1 -0
- package/dist/core/types.d.ts +141 -0
- package/dist/core/types.js +14 -0
- package/dist/core/types.js.map +1 -0
- package/dist/infra/atomic.d.ts +53 -0
- package/dist/infra/atomic.js +171 -0
- package/dist/infra/atomic.js.map +1 -0
- package/dist/infra/clock.d.ts +9 -0
- package/dist/infra/clock.js +15 -0
- package/dist/infra/clock.js.map +1 -0
- package/dist/infra/index.d.ts +9 -0
- package/dist/infra/index.js +7 -0
- package/dist/infra/index.js.map +1 -0
- package/dist/infra/ledger.d.ts +49 -0
- package/dist/infra/ledger.js +90 -0
- package/dist/infra/ledger.js.map +1 -0
- package/dist/infra/paths.d.ts +28 -0
- package/dist/infra/paths.js +38 -0
- package/dist/infra/paths.js.map +1 -0
- package/dist/infra/pricing.d.ts +47 -0
- package/dist/infra/pricing.js +151 -0
- package/dist/infra/pricing.js.map +1 -0
- package/dist/infra/session.d.ts +28 -0
- package/dist/infra/session.js +61 -0
- package/dist/infra/session.js.map +1 -0
- package/dist/interface/render.d.ts +27 -0
- package/dist/interface/render.js +134 -0
- package/dist/interface/render.js.map +1 -0
- package/dist/interface/repl.d.ts +23 -0
- package/dist/interface/repl.js +90 -0
- package/dist/interface/repl.js.map +1 -0
- package/dist/interface/run.d.ts +20 -0
- package/dist/interface/run.js +31 -0
- package/dist/interface/run.js.map +1 -0
- package/dist/providers/claude-parse.d.ts +24 -0
- package/dist/providers/claude-parse.js +113 -0
- package/dist/providers/claude-parse.js.map +1 -0
- package/dist/providers/claude.d.ts +45 -0
- package/dist/providers/claude.js +122 -0
- package/dist/providers/claude.js.map +1 -0
- package/dist/providers/codex-parse.d.ts +32 -0
- package/dist/providers/codex-parse.js +145 -0
- package/dist/providers/codex-parse.js.map +1 -0
- package/dist/providers/codex.d.ts +44 -0
- package/dist/providers/codex.js +124 -0
- package/dist/providers/codex.js.map +1 -0
- package/dist/providers/detect.d.ts +49 -0
- package/dist/providers/detect.js +125 -0
- package/dist/providers/detect.js.map +1 -0
- package/dist/providers/errors.d.ts +49 -0
- package/dist/providers/errors.js +189 -0
- package/dist/providers/errors.js.map +1 -0
- package/dist/providers/index.d.ts +9 -0
- package/dist/providers/index.js +7 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/port.d.ts +74 -0
- package/dist/providers/port.js +16 -0
- package/dist/providers/port.js.map +1 -0
- package/dist/providers/registry.d.ts +21 -0
- package/dist/providers/registry.js +34 -0
- package/dist/providers/registry.js.map +1 -0
- package/dist/ui/banner.d.ts +19 -0
- package/dist/ui/banner.js +32 -0
- package/dist/ui/banner.js.map +1 -0
- package/dist/ui/spinner.d.ts +27 -0
- package/dist/ui/spinner.js +67 -0
- package/dist/ui/spinner.js.map +1 -0
- package/dist/ui/theme.d.ts +32 -0
- package/dist/ui/theme.js +56 -0
- package/dist/ui/theme.js.map +1 -0
- package/package.json +55 -49
- package/data/orchestrator.json +0 -113
- package/src/auth/recovery.mjs +0 -328
- package/src/auth/refresh.mjs +0 -373
- package/src/chef.mjs +0 -348
- package/src/cli/doctor.mjs +0 -568
- package/src/cli/reset.mjs +0 -447
- package/src/cli/status.mjs +0 -379
- package/src/cli.mjs +0 -429
- package/src/commands/doctor.mjs +0 -375
- package/src/commands/help.mjs +0 -324
- package/src/commands/status.mjs +0 -331
- package/src/monitor/health.mjs +0 -486
- package/src/monitor/performance.mjs +0 -442
- package/src/monitor/report.mjs +0 -535
- package/src/orchestrator/classify.mjs +0 -391
- package/src/orchestrator/confidence.mjs +0 -151
- package/src/orchestrator/handoffs.mjs +0 -231
- package/src/orchestrator/review.mjs +0 -222
- package/src/providers/balance.mjs +0 -201
- package/src/providers/claude.mjs +0 -236
- package/src/providers/codex.mjs +0 -255
- package/src/providers/detect.mjs +0 -185
- package/src/providers/errors.mjs +0 -373
- package/src/providers/select.mjs +0 -162
- package/src/repl-enhanced.mjs +0 -417
- package/src/repl.mjs +0 -321
- package/src/state/archive.mjs +0 -366
- package/src/state/atomic.mjs +0 -116
- package/src/state/cleanup.mjs +0 -440
- package/src/state/recovery.mjs +0 -461
- package/src/state/session.mjs +0 -147
- package/src/ui/errors.mjs +0 -456
- package/src/ui/formatter.mjs +0 -327
- package/src/ui/icons.mjs +0 -318
- package/src/ui/progress.mjs +0 -468
- package/templates/prompts/confidence-format.txt +0 -14
- package/templates/prompts/ic-with-feedback.txt +0 -41
- package/templates/prompts/ic.txt +0 -13
- package/templates/prompts/manager-review.txt +0 -40
- package/templates/prompts/manager.txt +0 -14
- package/templates/prompts/worker.txt +0 -12
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"atomic.js","sourceRoot":"","sources":["../../src/infra/atomic.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/infra/clock.ts — System clock implementation of the Clock port.
|
|
3
|
+
*
|
|
4
|
+
* This is the SINGLE place in the codebase where impure time/random globals
|
|
5
|
+
* (Date, Math.random, randomUUID) are allowed. All other modules receive a
|
|
6
|
+
* Clock via injection, keeping them pure and testable.
|
|
7
|
+
*/
|
|
8
|
+
import type { Clock } from '../core/types.js';
|
|
9
|
+
export declare const systemClock: Clock;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/infra/clock.ts — System clock implementation of the Clock port.
|
|
3
|
+
*
|
|
4
|
+
* This is the SINGLE place in the codebase where impure time/random globals
|
|
5
|
+
* (Date, Math.random, randomUUID) are allowed. All other modules receive a
|
|
6
|
+
* Clock via injection, keeping them pure and testable.
|
|
7
|
+
*/
|
|
8
|
+
import { randomUUID } from 'node:crypto';
|
|
9
|
+
export const systemClock = {
|
|
10
|
+
now: () => Date.now(),
|
|
11
|
+
isoNow: () => new Date().toISOString(),
|
|
12
|
+
uuid: () => randomUUID(),
|
|
13
|
+
random: () => Math.random(),
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=clock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clock.js","sourceRoot":"","sources":["../../src/infra/clock.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,MAAM,CAAC,MAAM,WAAW,GAAU;IAChC,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE;IACrB,MAAM,EAAE,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;IACtC,IAAI,EAAE,GAAG,EAAE,CAAC,UAAU,EAAE;IACxB,MAAM,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE;CAC5B,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { acquireLock, releaseLock, withLock, atomicWrite, atomicAppendJSONL } from './atomic.js';
|
|
2
|
+
export type { LockOptions } from './atomic.js';
|
|
3
|
+
export { getModelPricing, calculateCost, getCheapestForTier, isPricingStale, PRICING_TABLE, } from './pricing.js';
|
|
4
|
+
export type { ModelPricing, PricingTable } from './pricing.js';
|
|
5
|
+
export { systemClock } from './clock.js';
|
|
6
|
+
export { getStateDir, getSessionsDir, getSessionFile, getLedgerFile } from './paths.js';
|
|
7
|
+
export { createSessionWriter, readSession } from './session.js';
|
|
8
|
+
export { createLedger, readLedger, summarizeLedger } from './ledger.js';
|
|
9
|
+
export type { ModelSummary, LedgerSummary } from './ledger.js';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { acquireLock, releaseLock, withLock, atomicWrite, atomicAppendJSONL } from './atomic.js';
|
|
2
|
+
export { getModelPricing, calculateCost, getCheapestForTier, isPricingStale, PRICING_TABLE, } from './pricing.js';
|
|
3
|
+
export { systemClock } from './clock.js';
|
|
4
|
+
export { getStateDir, getSessionsDir, getSessionFile, getLedgerFile } from './paths.js';
|
|
5
|
+
export { createSessionWriter, readSession } from './session.js';
|
|
6
|
+
export { createLedger, readLedger, summarizeLedger } from './ledger.js';
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/infra/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEjG,OAAO,EACL,eAAe,EACf,aAAa,EACb,kBAAkB,EAClB,cAAc,EACd,aAAa,GACd,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AACxF,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/infra/ledger.ts — LedgerWriter implementation, ledger reader, and summarizer.
|
|
3
|
+
*
|
|
4
|
+
* The ledger is a JSONL file at `.myshell-tools/ledger.jsonl`. Each `record` call appends
|
|
5
|
+
* one LedgerEntry atomically. `readLedger` re-hydrates entries (skipping malformed
|
|
6
|
+
* lines). `summarizeLedger` is a pure reduction used by `myshell-tools cost`.
|
|
7
|
+
*/
|
|
8
|
+
import type { LedgerEntry, LedgerWriter } from '../core/types.js';
|
|
9
|
+
/**
|
|
10
|
+
* Create a LedgerWriter for the given working directory.
|
|
11
|
+
*
|
|
12
|
+
* @param opts.cwd - The project working directory (parent of `.myshell-tools/`).
|
|
13
|
+
*/
|
|
14
|
+
export declare function createLedger(opts: {
|
|
15
|
+
cwd: string;
|
|
16
|
+
}): LedgerWriter;
|
|
17
|
+
/**
|
|
18
|
+
* Read all LedgerEntry records from the ledger JSONL file.
|
|
19
|
+
*
|
|
20
|
+
* Returns an empty array if the file does not exist. Malformed lines are
|
|
21
|
+
* silently skipped.
|
|
22
|
+
*
|
|
23
|
+
* @param cwd - The project working directory.
|
|
24
|
+
*/
|
|
25
|
+
export declare function readLedger(cwd: string): Promise<LedgerEntry[]>;
|
|
26
|
+
/** Per-model aggregation used in the summary. */
|
|
27
|
+
export interface ModelSummary {
|
|
28
|
+
readonly calls: number;
|
|
29
|
+
readonly usd: number;
|
|
30
|
+
}
|
|
31
|
+
/** Aggregate summary returned by `summarizeLedger`. */
|
|
32
|
+
export interface LedgerSummary {
|
|
33
|
+
readonly totalUsd: number;
|
|
34
|
+
readonly calls: number;
|
|
35
|
+
readonly byModel: Record<string, ModelSummary>;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Pure reduction over a ledger entry array.
|
|
39
|
+
*
|
|
40
|
+
* Computes:
|
|
41
|
+
* - `totalUsd` — sum of all `entry.usd` values
|
|
42
|
+
* - `calls` — total number of entries
|
|
43
|
+
* - `byModel` — per-model breakdown keyed by `entry.model`
|
|
44
|
+
*
|
|
45
|
+
* No I/O. Safe to call in tests with hand-built arrays.
|
|
46
|
+
*
|
|
47
|
+
* @param entries - Array of LedgerEntry objects (may be empty).
|
|
48
|
+
*/
|
|
49
|
+
export declare function summarizeLedger(entries: LedgerEntry[]): LedgerSummary;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/infra/ledger.ts — LedgerWriter implementation, ledger reader, and summarizer.
|
|
3
|
+
*
|
|
4
|
+
* The ledger is a JSONL file at `.myshell-tools/ledger.jsonl`. Each `record` call appends
|
|
5
|
+
* one LedgerEntry atomically. `readLedger` re-hydrates entries (skipping malformed
|
|
6
|
+
* lines). `summarizeLedger` is a pure reduction used by `myshell-tools cost`.
|
|
7
|
+
*/
|
|
8
|
+
import { mkdir, readFile } from 'node:fs/promises';
|
|
9
|
+
import { atomicAppendJSONL } from './atomic.js';
|
|
10
|
+
import { getStateDir, getLedgerFile } from './paths.js';
|
|
11
|
+
/**
|
|
12
|
+
* Create a LedgerWriter for the given working directory.
|
|
13
|
+
*
|
|
14
|
+
* @param opts.cwd - The project working directory (parent of `.myshell-tools/`).
|
|
15
|
+
*/
|
|
16
|
+
export function createLedger(opts) {
|
|
17
|
+
const { cwd } = opts;
|
|
18
|
+
return {
|
|
19
|
+
async record(entry) {
|
|
20
|
+
await mkdir(getStateDir(cwd), { recursive: true });
|
|
21
|
+
await atomicAppendJSONL(getLedgerFile(cwd), entry);
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Read all LedgerEntry records from the ledger JSONL file.
|
|
27
|
+
*
|
|
28
|
+
* Returns an empty array if the file does not exist. Malformed lines are
|
|
29
|
+
* silently skipped.
|
|
30
|
+
*
|
|
31
|
+
* @param cwd - The project working directory.
|
|
32
|
+
*/
|
|
33
|
+
export async function readLedger(cwd) {
|
|
34
|
+
let raw;
|
|
35
|
+
try {
|
|
36
|
+
raw = await readFile(getLedgerFile(cwd), 'utf8');
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
const nodeErr = err;
|
|
40
|
+
if (nodeErr.code === 'ENOENT')
|
|
41
|
+
return [];
|
|
42
|
+
throw err;
|
|
43
|
+
}
|
|
44
|
+
const entries = [];
|
|
45
|
+
for (const line of raw.split('\n')) {
|
|
46
|
+
const trimmed = line.trim();
|
|
47
|
+
if (trimmed.length === 0)
|
|
48
|
+
continue;
|
|
49
|
+
try {
|
|
50
|
+
entries.push(JSON.parse(trimmed));
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
// Skip malformed lines
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return entries;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Pure reduction over a ledger entry array.
|
|
60
|
+
*
|
|
61
|
+
* Computes:
|
|
62
|
+
* - `totalUsd` — sum of all `entry.usd` values
|
|
63
|
+
* - `calls` — total number of entries
|
|
64
|
+
* - `byModel` — per-model breakdown keyed by `entry.model`
|
|
65
|
+
*
|
|
66
|
+
* No I/O. Safe to call in tests with hand-built arrays.
|
|
67
|
+
*
|
|
68
|
+
* @param entries - Array of LedgerEntry objects (may be empty).
|
|
69
|
+
*/
|
|
70
|
+
export function summarizeLedger(entries) {
|
|
71
|
+
let totalUsd = 0;
|
|
72
|
+
const byModel = {};
|
|
73
|
+
for (const entry of entries) {
|
|
74
|
+
totalUsd += entry.usd;
|
|
75
|
+
const existing = byModel[entry.model];
|
|
76
|
+
if (existing !== undefined) {
|
|
77
|
+
existing.calls += 1;
|
|
78
|
+
existing.usd += entry.usd;
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
byModel[entry.model] = { calls: 1, usd: entry.usd };
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return {
|
|
85
|
+
totalUsd,
|
|
86
|
+
calls: entries.length,
|
|
87
|
+
byModel,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=ledger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ledger.js","sourceRoot":"","sources":["../../src/infra/ledger.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAExD;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,IAAqB;IAChD,MAAM,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IAErB,OAAO;QACL,KAAK,CAAC,MAAM,CAAC,KAAkB;YAC7B,MAAM,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACnD,MAAM,iBAAiB,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC;QACrD,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,GAAW;IAC1C,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC;IACnD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,GAA4B,CAAC;QAC7C,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,EAAE,CAAC;QACzC,MAAM,GAAG,CAAC;IACZ,CAAC;IAED,MAAM,OAAO,GAAkB,EAAE,CAAC;IAClC,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QACnC,IAAI,CAAC;YACH,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAgB,CAAC,CAAC;QACnD,CAAC;QAAC,MAAM,CAAC;YACP,uBAAuB;QACzB,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAeD;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,eAAe,CAAC,OAAsB;IACpD,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,MAAM,OAAO,GAAmD,EAAE,CAAC;IAEnE,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,QAAQ,IAAI,KAAK,CAAC,GAAG,CAAC;QAEtB,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACtC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC3B,QAAQ,CAAC,KAAK,IAAI,CAAC,CAAC;YACpB,QAAQ,CAAC,GAAG,IAAI,KAAK,CAAC,GAAG,CAAC;QAC5B,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC;QACtD,CAAC;IACH,CAAC;IAED,OAAO;QACL,QAAQ;QACR,KAAK,EAAE,OAAO,CAAC,MAAM;QACrB,OAAO;KACR,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/infra/paths.ts — Pure path helpers for myshell-tools's filesystem layout.
|
|
3
|
+
*
|
|
4
|
+
* All functions are pure path joins (no fs I/O). The canonical layout is:
|
|
5
|
+
* <cwd>/
|
|
6
|
+
* .myshell-tools/
|
|
7
|
+
* sessions/
|
|
8
|
+
* current.jsonl ← active session log
|
|
9
|
+
* ledger.jsonl ← cost/usage ledger
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Returns the path to the `.myshell-tools` directory inside the given working dir.
|
|
13
|
+
*/
|
|
14
|
+
export declare function getStateDir(cwd: string): string;
|
|
15
|
+
/**
|
|
16
|
+
* Returns the path to the `sessions` subdirectory inside `.myshell-tools`.
|
|
17
|
+
*/
|
|
18
|
+
export declare function getSessionsDir(cwd: string): string;
|
|
19
|
+
/**
|
|
20
|
+
* Returns the path to the current session JSONL file.
|
|
21
|
+
* Path: <cwd>/.myshell-tools/sessions/current.jsonl
|
|
22
|
+
*/
|
|
23
|
+
export declare function getSessionFile(cwd: string): string;
|
|
24
|
+
/**
|
|
25
|
+
* Returns the path to the cost/usage ledger JSONL file.
|
|
26
|
+
* Path: <cwd>/.myshell-tools/ledger.jsonl
|
|
27
|
+
*/
|
|
28
|
+
export declare function getLedgerFile(cwd: string): string;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/infra/paths.ts — Pure path helpers for myshell-tools's filesystem layout.
|
|
3
|
+
*
|
|
4
|
+
* All functions are pure path joins (no fs I/O). The canonical layout is:
|
|
5
|
+
* <cwd>/
|
|
6
|
+
* .myshell-tools/
|
|
7
|
+
* sessions/
|
|
8
|
+
* current.jsonl ← active session log
|
|
9
|
+
* ledger.jsonl ← cost/usage ledger
|
|
10
|
+
*/
|
|
11
|
+
import { join } from 'node:path';
|
|
12
|
+
/**
|
|
13
|
+
* Returns the path to the `.myshell-tools` directory inside the given working dir.
|
|
14
|
+
*/
|
|
15
|
+
export function getStateDir(cwd) {
|
|
16
|
+
return join(cwd, '.myshell-tools');
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Returns the path to the `sessions` subdirectory inside `.myshell-tools`.
|
|
20
|
+
*/
|
|
21
|
+
export function getSessionsDir(cwd) {
|
|
22
|
+
return join(getStateDir(cwd), 'sessions');
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Returns the path to the current session JSONL file.
|
|
26
|
+
* Path: <cwd>/.myshell-tools/sessions/current.jsonl
|
|
27
|
+
*/
|
|
28
|
+
export function getSessionFile(cwd) {
|
|
29
|
+
return join(getSessionsDir(cwd), 'current.jsonl');
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Returns the path to the cost/usage ledger JSONL file.
|
|
33
|
+
* Path: <cwd>/.myshell-tools/ledger.jsonl
|
|
34
|
+
*/
|
|
35
|
+
export function getLedgerFile(cwd) {
|
|
36
|
+
return join(getStateDir(cwd), 'ledger.jsonl');
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/infra/paths.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,GAAW;IACrC,OAAO,IAAI,CAAC,GAAG,EAAE,gBAAgB,CAAC,CAAC;AACrC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,OAAO,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,UAAU,CAAC,CAAC;AAC5C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,OAAO,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,eAAe,CAAC,CAAC;AACpD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,GAAW;IACvC,OAAO,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,cAAc,CAAC,CAAC;AAChD,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/infra/pricing.ts
|
|
3
|
+
*
|
|
4
|
+
* Corrected price table — Appendix A of the myshell-tools project plan.
|
|
5
|
+
*
|
|
6
|
+
* Provenance
|
|
7
|
+
* ----------
|
|
8
|
+
* Claude pricing : https://www.anthropic.com/pricing
|
|
9
|
+
* OpenAI pricing : https://platform.openai.com/docs/pricing
|
|
10
|
+
* Captured : 2026-05-29
|
|
11
|
+
*/
|
|
12
|
+
export interface ModelPricing {
|
|
13
|
+
readonly provider: 'claude' | 'codex';
|
|
14
|
+
readonly model: string;
|
|
15
|
+
readonly aliases: readonly string[];
|
|
16
|
+
readonly tier: 'worker' | 'ic' | 'manager';
|
|
17
|
+
readonly inputPer1M: number;
|
|
18
|
+
readonly outputPer1M: number;
|
|
19
|
+
readonly contextWindow: number;
|
|
20
|
+
}
|
|
21
|
+
export interface PricingTable {
|
|
22
|
+
readonly asOf: string;
|
|
23
|
+
readonly sourceUrls: readonly string[];
|
|
24
|
+
readonly models: readonly ModelPricing[];
|
|
25
|
+
}
|
|
26
|
+
export declare const PRICING_TABLE: PricingTable;
|
|
27
|
+
/**
|
|
28
|
+
* Look up a model entry by exact model ID or any of its aliases.
|
|
29
|
+
* The lookup is case-insensitive.
|
|
30
|
+
*/
|
|
31
|
+
export declare function getModelPricing(provider: string, model: string): ModelPricing | undefined;
|
|
32
|
+
/**
|
|
33
|
+
* Calculate the USD cost for a given number of input and output tokens.
|
|
34
|
+
*/
|
|
35
|
+
export declare function calculateCost(inputTokens: number, outputTokens: number, pricing: ModelPricing): number;
|
|
36
|
+
/**
|
|
37
|
+
* Return the cheapest model (lowest inputPer1M) for a given tier,
|
|
38
|
+
* optionally restricted to the supplied provider IDs.
|
|
39
|
+
*
|
|
40
|
+
* Throws if no matching model exists.
|
|
41
|
+
*/
|
|
42
|
+
export declare function getCheapestForTier(tier: 'worker' | 'ic' | 'manager', availableProviders?: string[]): ModelPricing;
|
|
43
|
+
/**
|
|
44
|
+
* Returns true when the pricing table is older than maxAgeDays (default 90).
|
|
45
|
+
* Useful for emitting a staleness warning at runtime.
|
|
46
|
+
*/
|
|
47
|
+
export declare function isPricingStale(maxAgeDays?: number): boolean;
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/infra/pricing.ts
|
|
3
|
+
*
|
|
4
|
+
* Corrected price table — Appendix A of the myshell-tools project plan.
|
|
5
|
+
*
|
|
6
|
+
* Provenance
|
|
7
|
+
* ----------
|
|
8
|
+
* Claude pricing : https://www.anthropic.com/pricing
|
|
9
|
+
* OpenAI pricing : https://platform.openai.com/docs/pricing
|
|
10
|
+
* Captured : 2026-05-29
|
|
11
|
+
*/
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
// Data
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
export const PRICING_TABLE = {
|
|
16
|
+
asOf: '2026-05-29',
|
|
17
|
+
sourceUrls: [
|
|
18
|
+
'https://www.anthropic.com/pricing',
|
|
19
|
+
'https://platform.openai.com/docs/pricing',
|
|
20
|
+
],
|
|
21
|
+
models: [
|
|
22
|
+
// ---- Anthropic / Claude ------------------------------------------------
|
|
23
|
+
{
|
|
24
|
+
provider: 'claude',
|
|
25
|
+
model: 'claude-opus-4-7',
|
|
26
|
+
aliases: ['opus', 'opus-4.7', 'claude-opus-4.7'],
|
|
27
|
+
tier: 'manager',
|
|
28
|
+
inputPer1M: 5,
|
|
29
|
+
outputPer1M: 25,
|
|
30
|
+
contextWindow: 200_000,
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
provider: 'claude',
|
|
34
|
+
model: 'claude-sonnet-4-6',
|
|
35
|
+
aliases: ['sonnet', 'sonnet-4.6', 'claude-sonnet-4.6'],
|
|
36
|
+
tier: 'ic',
|
|
37
|
+
inputPer1M: 3,
|
|
38
|
+
outputPer1M: 15,
|
|
39
|
+
contextWindow: 200_000,
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
provider: 'claude',
|
|
43
|
+
model: 'claude-haiku-4-5',
|
|
44
|
+
aliases: ['haiku', 'haiku-4.5', 'claude-haiku-4.5'],
|
|
45
|
+
tier: 'worker',
|
|
46
|
+
inputPer1M: 0.8,
|
|
47
|
+
outputPer1M: 4,
|
|
48
|
+
contextWindow: 200_000,
|
|
49
|
+
},
|
|
50
|
+
// ---- OpenAI / Codex ----------------------------------------------------
|
|
51
|
+
{
|
|
52
|
+
provider: 'codex',
|
|
53
|
+
model: 'gpt-5.5',
|
|
54
|
+
aliases: ['gpt5.5', 'gpt-5-5'],
|
|
55
|
+
tier: 'manager',
|
|
56
|
+
inputPer1M: 5,
|
|
57
|
+
outputPer1M: 30,
|
|
58
|
+
contextWindow: 128_000,
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
provider: 'codex',
|
|
62
|
+
model: 'gpt-5.4',
|
|
63
|
+
aliases: ['gpt5.4', 'gpt-5-4'],
|
|
64
|
+
tier: 'ic',
|
|
65
|
+
inputPer1M: 2.5,
|
|
66
|
+
outputPer1M: 15,
|
|
67
|
+
contextWindow: 128_000,
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
provider: 'codex',
|
|
71
|
+
model: 'gpt-5.4-mini',
|
|
72
|
+
aliases: ['gpt5.4-mini', 'gpt-5-4-mini'],
|
|
73
|
+
tier: 'worker',
|
|
74
|
+
inputPer1M: 0.75,
|
|
75
|
+
outputPer1M: 4.5,
|
|
76
|
+
contextWindow: 128_000,
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
provider: 'codex',
|
|
80
|
+
model: 'gpt-5.4-nano',
|
|
81
|
+
aliases: ['gpt5.4-nano', 'gpt-5-4-nano'],
|
|
82
|
+
tier: 'worker',
|
|
83
|
+
inputPer1M: 0.2,
|
|
84
|
+
outputPer1M: 1.25,
|
|
85
|
+
contextWindow: 128_000,
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
provider: 'codex',
|
|
89
|
+
model: 'gpt-5.2-codex',
|
|
90
|
+
aliases: ['codex', 'gpt5.2-codex', 'gpt-5-2-codex'],
|
|
91
|
+
tier: 'ic',
|
|
92
|
+
inputPer1M: 1.75,
|
|
93
|
+
outputPer1M: 14,
|
|
94
|
+
contextWindow: 128_000,
|
|
95
|
+
},
|
|
96
|
+
],
|
|
97
|
+
};
|
|
98
|
+
// ---------------------------------------------------------------------------
|
|
99
|
+
// Helpers
|
|
100
|
+
// ---------------------------------------------------------------------------
|
|
101
|
+
/**
|
|
102
|
+
* Look up a model entry by exact model ID or any of its aliases.
|
|
103
|
+
* The lookup is case-insensitive.
|
|
104
|
+
*/
|
|
105
|
+
export function getModelPricing(provider, model) {
|
|
106
|
+
const needle = model.toLowerCase();
|
|
107
|
+
return PRICING_TABLE.models.find((m) => m.provider === provider &&
|
|
108
|
+
(m.model.toLowerCase() === needle ||
|
|
109
|
+
m.aliases.some((a) => a.toLowerCase() === needle)));
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Calculate the USD cost for a given number of input and output tokens.
|
|
113
|
+
*/
|
|
114
|
+
export function calculateCost(inputTokens, outputTokens, pricing) {
|
|
115
|
+
const inputCost = (inputTokens / 1_000_000) * pricing.inputPer1M;
|
|
116
|
+
const outputCost = (outputTokens / 1_000_000) * pricing.outputPer1M;
|
|
117
|
+
return inputCost + outputCost;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Return the cheapest model (lowest inputPer1M) for a given tier,
|
|
121
|
+
* optionally restricted to the supplied provider IDs.
|
|
122
|
+
*
|
|
123
|
+
* Throws if no matching model exists.
|
|
124
|
+
*/
|
|
125
|
+
export function getCheapestForTier(tier, availableProviders) {
|
|
126
|
+
let candidates = PRICING_TABLE.models.filter((m) => m.tier === tier);
|
|
127
|
+
if (availableProviders && availableProviders.length > 0) {
|
|
128
|
+
candidates = candidates.filter((m) => availableProviders.includes(m.provider));
|
|
129
|
+
}
|
|
130
|
+
if (candidates.length === 0) {
|
|
131
|
+
throw new Error(`No models available for tier "${tier}"` +
|
|
132
|
+
(availableProviders ? ` with providers [${availableProviders.join(', ')}]` : ''));
|
|
133
|
+
}
|
|
134
|
+
// Primary sort: inputPer1M ascending; secondary: outputPer1M ascending
|
|
135
|
+
return candidates.reduce((cheapest, m) => m.inputPer1M < cheapest.inputPer1M ||
|
|
136
|
+
(m.inputPer1M === cheapest.inputPer1M && m.outputPer1M < cheapest.outputPer1M)
|
|
137
|
+
? m
|
|
138
|
+
: cheapest);
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Returns true when the pricing table is older than maxAgeDays (default 90).
|
|
142
|
+
* Useful for emitting a staleness warning at runtime.
|
|
143
|
+
*/
|
|
144
|
+
export function isPricingStale(maxAgeDays = 90) {
|
|
145
|
+
const asOf = new Date(PRICING_TABLE.asOf);
|
|
146
|
+
const now = new Date();
|
|
147
|
+
const diffMs = now.getTime() - asOf.getTime();
|
|
148
|
+
const diffDays = diffMs / (1_000 * 60 * 60 * 24);
|
|
149
|
+
return diffDays > maxAgeDays;
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=pricing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pricing.js","sourceRoot":"","sources":["../../src/infra/pricing.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/infra/session.ts — SessionWriter implementation and session reader.
|
|
3
|
+
*
|
|
4
|
+
* Sessions are persisted as JSONL files under `.myshell-tools/sessions/current.jsonl`.
|
|
5
|
+
* Each call to `append` writes a single line atomically using `atomicAppendJSONL`.
|
|
6
|
+
* `readSession` re-hydrates a session from the JSONL file, skipping any malformed
|
|
7
|
+
* lines so a partial write can never break a resume.
|
|
8
|
+
*/
|
|
9
|
+
import type { SessionEntry, SessionWriter } from '../core/types.js';
|
|
10
|
+
/**
|
|
11
|
+
* Create a SessionWriter for the given working directory and session id.
|
|
12
|
+
*
|
|
13
|
+
* @param opts.cwd - The project working directory (parent of `.myshell-tools/`).
|
|
14
|
+
* @param opts.id - A unique session identifier (typically a UUID).
|
|
15
|
+
*/
|
|
16
|
+
export declare function createSessionWriter(opts: {
|
|
17
|
+
cwd: string;
|
|
18
|
+
id: string;
|
|
19
|
+
}): SessionWriter;
|
|
20
|
+
/**
|
|
21
|
+
* Read all SessionEntry records from the current session JSONL file.
|
|
22
|
+
*
|
|
23
|
+
* Returns an empty array if the file does not exist. Malformed lines (e.g.
|
|
24
|
+
* caused by a partial write) are silently skipped.
|
|
25
|
+
*
|
|
26
|
+
* @param cwd - The project working directory.
|
|
27
|
+
*/
|
|
28
|
+
export declare function readSession(cwd: string): Promise<SessionEntry[]>;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/infra/session.ts — SessionWriter implementation and session reader.
|
|
3
|
+
*
|
|
4
|
+
* Sessions are persisted as JSONL files under `.myshell-tools/sessions/current.jsonl`.
|
|
5
|
+
* Each call to `append` writes a single line atomically using `atomicAppendJSONL`.
|
|
6
|
+
* `readSession` re-hydrates a session from the JSONL file, skipping any malformed
|
|
7
|
+
* lines so a partial write can never break a resume.
|
|
8
|
+
*/
|
|
9
|
+
import { mkdir, readFile } from 'node:fs/promises';
|
|
10
|
+
import { atomicAppendJSONL } from './atomic.js';
|
|
11
|
+
import { getSessionsDir, getSessionFile } from './paths.js';
|
|
12
|
+
/**
|
|
13
|
+
* Create a SessionWriter for the given working directory and session id.
|
|
14
|
+
*
|
|
15
|
+
* @param opts.cwd - The project working directory (parent of `.myshell-tools/`).
|
|
16
|
+
* @param opts.id - A unique session identifier (typically a UUID).
|
|
17
|
+
*/
|
|
18
|
+
export function createSessionWriter(opts) {
|
|
19
|
+
const { cwd, id } = opts;
|
|
20
|
+
return {
|
|
21
|
+
id,
|
|
22
|
+
async append(entry) {
|
|
23
|
+
await mkdir(getSessionsDir(cwd), { recursive: true });
|
|
24
|
+
await atomicAppendJSONL(getSessionFile(cwd), entry);
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Read all SessionEntry records from the current session JSONL file.
|
|
30
|
+
*
|
|
31
|
+
* Returns an empty array if the file does not exist. Malformed lines (e.g.
|
|
32
|
+
* caused by a partial write) are silently skipped.
|
|
33
|
+
*
|
|
34
|
+
* @param cwd - The project working directory.
|
|
35
|
+
*/
|
|
36
|
+
export async function readSession(cwd) {
|
|
37
|
+
let raw;
|
|
38
|
+
try {
|
|
39
|
+
raw = await readFile(getSessionFile(cwd), 'utf8');
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
const nodeErr = err;
|
|
43
|
+
if (nodeErr.code === 'ENOENT')
|
|
44
|
+
return [];
|
|
45
|
+
throw err;
|
|
46
|
+
}
|
|
47
|
+
const entries = [];
|
|
48
|
+
for (const line of raw.split('\n')) {
|
|
49
|
+
const trimmed = line.trim();
|
|
50
|
+
if (trimmed.length === 0)
|
|
51
|
+
continue;
|
|
52
|
+
try {
|
|
53
|
+
entries.push(JSON.parse(trimmed));
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
// Skip malformed lines
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return entries;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/infra/session.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5D;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAiC;IACnE,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,IAAI,CAAC;IAEzB,OAAO;QACL,EAAE;QAEF,KAAK,CAAC,MAAM,CAAC,KAAmB;YAC9B,MAAM,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACtD,MAAM,iBAAiB,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC;QACtD,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,GAAW;IAC3C,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,QAAQ,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC;IACpD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,GAA4B,CAAC;QAC7C,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,EAAE,CAAC;QACzC,MAAM,GAAG,CAAC;IACZ,CAAC;IAED,MAAM,OAAO,GAAmB,EAAE,CAAC;IACnC,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QACnC,IAAI,CAAC;YACH,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAiB,CAAC,CAAC;QACpD,CAAC;QAAC,MAAM,CAAC;YACP,uBAAuB;QACzB,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/interface/render.ts — Human-readable event stream renderer.
|
|
3
|
+
*
|
|
4
|
+
* Consumes the AsyncIterable<CoreEvent> produced by orchestrate() and writes
|
|
5
|
+
* a clean, truthful transcript to an OutputSink. All displayed values come
|
|
6
|
+
* directly from CoreEvent data — no fabricated metrics, no hardcoded strings.
|
|
7
|
+
*
|
|
8
|
+
* Honesty Contract: confidence is rendered as a computed percentage or the
|
|
9
|
+
* literal word "unrated" when null. No digit-% literals appear in this file.
|
|
10
|
+
*/
|
|
11
|
+
import type { CoreEvent } from '../core/types.js';
|
|
12
|
+
export interface OutputSink {
|
|
13
|
+
write(s: string): void;
|
|
14
|
+
readonly color: boolean;
|
|
15
|
+
readonly isTty: boolean;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Iterate events from orchestrate() and write a human-readable, truthful
|
|
19
|
+
* transcript to the OutputSink. Returns the success flag and the final event
|
|
20
|
+
* once the stream is exhausted.
|
|
21
|
+
*/
|
|
22
|
+
export declare function renderStream(events: AsyncIterable<CoreEvent>, out: OutputSink): Promise<{
|
|
23
|
+
success: boolean;
|
|
24
|
+
final?: Extract<CoreEvent, {
|
|
25
|
+
type: 'final';
|
|
26
|
+
}>;
|
|
27
|
+
}>;
|