@llm4ts/runner 3.4.0 → 4.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.
Files changed (84) hide show
  1. package/dist/Connectors.d.ts +0 -6
  2. package/dist/Connectors.d.ts.map +1 -1
  3. package/dist/Connectors.js +0 -9
  4. package/dist/Connectors.js.map +1 -1
  5. package/dist/EventPresentation.d.ts.map +1 -1
  6. package/dist/EventPresentation.js +0 -1
  7. package/dist/EventPresentation.js.map +1 -1
  8. package/dist/FlowRunner.d.ts +10 -3
  9. package/dist/FlowRunner.d.ts.map +1 -1
  10. package/dist/FlowRunner.js +20 -2
  11. package/dist/FlowRunner.js.map +1 -1
  12. package/dist/NodeGeminiCliExecutor.d.ts.map +1 -1
  13. package/dist/NodeGeminiCliExecutor.js +1 -0
  14. package/dist/NodeGeminiCliExecutor.js.map +1 -1
  15. package/dist/NodeGeminiModelBridge.d.ts.map +1 -1
  16. package/dist/NodeGeminiModelBridge.js +1 -0
  17. package/dist/NodeGeminiModelBridge.js.map +1 -1
  18. package/dist/NodeHttpClient.d.ts.map +1 -1
  19. package/dist/NodeHttpClient.js +1 -0
  20. package/dist/NodeHttpClient.js.map +1 -1
  21. package/dist/Otel.d.ts.map +1 -1
  22. package/dist/Otel.js +1 -0
  23. package/dist/Otel.js.map +1 -1
  24. package/dist/Package.d.ts.map +1 -1
  25. package/dist/Package.js +1 -0
  26. package/dist/Package.js.map +1 -1
  27. package/dist/Terminal.d.ts +1 -2
  28. package/dist/Terminal.d.ts.map +1 -1
  29. package/dist/Terminal.js +1 -4
  30. package/dist/Terminal.js.map +1 -1
  31. package/dist/WindowsCommand.d.ts.map +1 -1
  32. package/dist/WindowsCommand.js +1 -0
  33. package/dist/WindowsCommand.js.map +1 -1
  34. package/dist/index.d.ts +1 -2
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +1 -2
  37. package/dist/index.js.map +1 -1
  38. package/package.json +8 -21
  39. package/src/Connectors.ts +0 -10
  40. package/src/EventPresentation.ts +0 -1
  41. package/src/FlowRunner.ts +26 -6
  42. package/src/NodeGeminiCliExecutor.ts +1 -0
  43. package/src/NodeGeminiModelBridge.ts +1 -0
  44. package/src/NodeHttpClient.ts +1 -0
  45. package/src/Otel.ts +1 -0
  46. package/src/Package.ts +1 -0
  47. package/src/Terminal.ts +1 -5
  48. package/src/WindowsCommand.ts +1 -0
  49. package/src/index.ts +0 -2
  50. package/dist/Costs.d.ts +0 -52
  51. package/dist/Costs.d.ts.map +0 -1
  52. package/dist/Costs.js +0 -95
  53. package/dist/Costs.js.map +0 -1
  54. package/dist/McpStdio.d.ts +0 -7
  55. package/dist/McpStdio.d.ts.map +0 -1
  56. package/dist/McpStdio.js +0 -19
  57. package/dist/McpStdio.js.map +0 -1
  58. package/dist/Profile.d.ts +0 -313
  59. package/dist/Profile.d.ts.map +0 -1
  60. package/dist/Profile.js +0 -937
  61. package/dist/Profile.js.map +0 -1
  62. package/dist/ReviewFingerprint.d.ts +0 -2
  63. package/dist/ReviewFingerprint.d.ts.map +0 -1
  64. package/dist/ReviewFingerprint.js +0 -13
  65. package/dist/ReviewFingerprint.js.map +0 -1
  66. package/dist/RunReaders.d.ts +0 -70
  67. package/dist/RunReaders.d.ts.map +0 -1
  68. package/dist/RunReaders.js +0 -236
  69. package/dist/RunReaders.js.map +0 -1
  70. package/dist/StoryReaders.d.ts +0 -16
  71. package/dist/StoryReaders.d.ts.map +0 -1
  72. package/dist/StoryReaders.js +0 -107
  73. package/dist/StoryReaders.js.map +0 -1
  74. package/dist/Watch.d.ts +0 -68
  75. package/dist/Watch.d.ts.map +0 -1
  76. package/dist/Watch.js +0 -261
  77. package/dist/Watch.js.map +0 -1
  78. package/src/Costs.ts +0 -148
  79. package/src/McpStdio.ts +0 -41
  80. package/src/Profile.ts +0 -1196
  81. package/src/ReviewFingerprint.ts +0 -13
  82. package/src/RunReaders.ts +0 -370
  83. package/src/StoryReaders.ts +0 -157
  84. package/src/Watch.ts +0 -446
package/dist/Watch.d.ts DELETED
@@ -1,68 +0,0 @@
1
- import * as Effect from "effect/Effect";
2
- import * as Schema from "effect/Schema";
3
- import * as Stream from "effect/Stream";
4
- import { type EpicRun } from "@llm4ts/flow/EpicRuns";
5
- import type { FlowError } from "@llm4ts/flow/FlowError";
6
- import { type PlainFileStoreShape } from "@llm4ts/flow/Persistence";
7
- import { type TranscriptFiles } from "./Transcripts.ts";
8
- /**
9
- * `llm4ts watch` (ADR 0022): the agent tree over a trace file — a live run
10
- * followed as it grows, a finished run's last frame, or a replay on the
11
- * trace's own timestamps. The trace is the only source; the epic's board
12
- * adds the stories that have not started.
13
- */
14
- export interface WatchOptions {
15
- readonly repo: string;
16
- /** A trace file; the newest in the repository's `.llm4ts/` when omitted. */
17
- readonly trace?: string;
18
- /** An epic id: its latest recorded run. */
19
- readonly epic?: string;
20
- readonly replay?: boolean;
21
- /** Replay speed-up (default 10). */
22
- readonly speed?: number;
23
- /** A live lane with no event for this long is marked idle (`LLM4TS_IDLE_AFTER`). */
24
- readonly idleAfterMs?: number;
25
- /** Print this story's or executor's transcript as it grows, instead of the tree. */
26
- readonly tail?: string;
27
- }
28
- export interface WatchOutput {
29
- readonly write: (text: string) => Effect.Effect<void>;
30
- readonly columns: () => number | undefined;
31
- readonly rows: () => number | undefined;
32
- /** A terminal a person looks at: full-screen, keys, following. */
33
- readonly interactive: boolean;
34
- readonly colour: boolean;
35
- }
36
- export interface WatchDependencies {
37
- readonly files: PlainFileStoreShape;
38
- readonly listTraces: (directory: string) => ReadonlyArray<string>;
39
- /** Epic folder names under `.llm4ts/epics/`. */
40
- readonly listEpics: (directory: string) => ReadonlyArray<string>;
41
- readonly output: WatchOutput;
42
- /** Key names as `onTreeKey` reads them: "up", "enter", "q", … */
43
- readonly keys: Stream.Stream<string>;
44
- /** A run's transcript files (`--transcript`); the disk by default. */
45
- readonly transcripts?: TranscriptFiles;
46
- }
47
- declare const WatchTargetMissing_base: Schema.Class<WatchTargetMissing, Schema.TaggedStruct<"WatchTargetMissing", {
48
- readonly message: Schema.String;
49
- }>, import("effect/Cause").YieldableError>;
50
- export declare class WatchTargetMissing extends WatchTargetMissing_base {
51
- }
52
- /** Where a run's trace and its epic are read from. */
53
- export type TraceSources = Pick<WatchDependencies, "files" | "listTraces" | "listEpics">;
54
- /** A trace to read: given, an epic's latest run, or the newest in the repository. */
55
- export type TraceChoice = Pick<WatchOptions, "repo" | "trace" | "epic">;
56
- export interface WatchTarget {
57
- readonly tracePath: string;
58
- readonly epicDir: string | undefined;
59
- readonly run: EpicRun | undefined;
60
- }
61
- export declare const resolveTraceTarget: (options: TraceChoice, dependencies: TraceSources) => Effect.Effect<WatchTarget, FlowError | WatchTargetMissing>;
62
- export declare const makeWatchProgram: (options: WatchOptions, dependencies: WatchDependencies) => Effect.Effect<void, import("@llm4ts/flow/FlowError").PersistenceError | import("@llm4ts/flow/FlowError").PlanParseError | import("@llm4ts/flow/FlowError").UnsupportedSchemaVersion | import("@llm4ts/flow/FlowError").WorkspacePathError | import("@llm4ts/flow/FlowError").WorkspaceLimitError | import("@llm4ts/flow/FlowError").WorkspaceIoError | import("@llm4ts/flow/FlowError").FlowAborted | import("@llm4ts/flow/FlowError").ProcessError | import("@llm4ts/flow/FlowError").FlowLlmError | import("@llm4ts/flow/FlowError").FlowCapabilityDenied | import("@llm4ts/flow/FlowError").ColumnNotFound | import("@llm4ts/flow/FlowError").BudgetExceeded | import("@llm4ts/flow/FlowError").StoryPlanInvalid | import("@llm4ts/flow/FlowError").PerimeterViolation | import("@llm4ts/flow/FlowError").MissingDependency | import("@llm4ts/flow/FlowError").MergeConflict | import("@llm4ts/flow/FlowError").EpicCheckoutDirty | import("@llm4ts/flow/FlowError").RosterExhausted | import("@llm4ts/flow/FlowError").RosterInvalid | import("@llm4ts/flow/FlowError").EpicIncomplete | import("@llm4ts/flow/FlowError").LandingFailed | import("@llm4ts/flow/FlowError").StoryFailed | import("@llm4ts/flow/FlowError").Stalled | import("@llm4ts/flow/FlowError").DecisionsInvalid | import("@llm4ts/flow/FlowError").OpenPointsPending | import("@llm4ts/flow/FlowError").ContractConflict | import("@llm4ts/flow/FlowError").ExtractPackMissing | import("@llm4ts/flow/FlowError").EpicBriefInvalid | import("@llm4ts/flow/FlowError").EpicBriefNotApproved | import("@llm4ts/flow/FlowError").RefineRefused | import("@llm4ts/flow/FlowError").PersonaInvalid | import("@llm4ts/flow/FlowError").MeetingInvalid | import("@llm4ts/flow/FlowError").TurnsInvalid | import("@llm4ts/flow/FlowError").AgendaPending | import("@llm4ts/flow/FlowError").PlanInvalid | import("@llm4ts/flow/FlowError").ReportInvalid | import("@llm4ts/flow/FlowError").PlanPending | WatchTargetMissing, never>;
63
- /** Folder names under an `epics/` directory; none when it is absent. */
64
- export declare const nodeListEpics: (directory: string) => ReadonlyArray<string>;
65
- export declare const nodeTraceSources: TraceSources;
66
- export declare const nodeWatchDependencies: (environment?: Readonly<Record<string, string | undefined>>) => WatchDependencies;
67
- export {};
68
- //# sourceMappingURL=Watch.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Watch.d.ts","sourceRoot":"","sources":["../src/Watch.ts"],"names":[],"mappings":"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"}
package/dist/Watch.js DELETED
@@ -1,261 +0,0 @@
1
- import { readdirSync, existsSync, statSync } from "node:fs";
2
- import { join } from "node:path";
3
- import * as Clock from "effect/Clock";
4
- import * as Duration from "effect/Duration";
5
- import * as Effect from "effect/Effect";
6
- import * as Queue from "effect/Queue";
7
- import * as Ref from "effect/Ref";
8
- import * as Schema from "effect/Schema";
9
- import * as Stream from "effect/Stream";
10
- import { Board, BoardVersion } from "@llm4ts/flow/BoardSync";
11
- import { readEpicRuns } from "@llm4ts/flow/EpicRuns";
12
- import { loadVersioned } from "@llm4ts/flow/Persistence";
13
- import { readTrace } from "@llm4ts/flow/Replay";
14
- import { emptyTree, initialView, onTreeKey, reduceTree, renderTree, tailTargetOf, treeInputsOfTrace } from "./AgentTree.js";
15
- import { enterScreen, leaveScreen, makeScreenPainter, nodeTreeKeys } from "./AgentTreeSurface.js";
16
- import { loadTranscript, nodeTranscriptFiles, renderTranscript, tailLinesOf, transcriptFileOf } from "./Transcripts.js";
17
- import { nodeListTraces, TraceDirectoryName } from "./Costs.js";
18
- import { nodePlainFileStore } from "./NodePlainFileStore.js";
19
- export class WatchTargetMissing extends Schema.TaggedError()("WatchTargetMissing", { message: Schema.String }) {
20
- }
21
- const epicsDirOf = (repo) => join(repo, TraceDirectoryName, "epics");
22
- /** The epic whose `runs.jsonl` names this trace, if one does. */
23
- const epicOfTrace = (tracePath, repo, dependencies) => Effect.gen(function* () {
24
- const epicsDir = epicsDirOf(repo);
25
- for (const epic of dependencies.listEpics(epicsDir)) {
26
- const dir = join(epicsDir, epic);
27
- const run = [...(yield* readEpicRuns(dependencies.files, dir))]
28
- .reverse()
29
- .find((candidate) => candidate.tracePath === tracePath);
30
- if (run !== undefined) {
31
- return { dir, run };
32
- }
33
- }
34
- return undefined;
35
- });
36
- export const resolveTraceTarget = (options, dependencies) => Effect.gen(function* () {
37
- if (options.epic !== undefined) {
38
- const dir = join(epicsDirOf(options.repo), options.epic);
39
- const run = (yield* readEpicRuns(dependencies.files, dir)).at(-1);
40
- if (run === undefined) {
41
- return yield* WatchTargetMissing.make({
42
- message: `epic ${options.epic} has no recorded run in ${dir}/runs.jsonl`
43
- });
44
- }
45
- return { tracePath: run.tracePath, epicDir: dir, run };
46
- }
47
- const tracePath = options.trace ?? dependencies.listTraces(join(options.repo, TraceDirectoryName)).at(-1);
48
- if (tracePath === undefined) {
49
- return yield* WatchTargetMissing.make({
50
- message: `no trace in ${join(options.repo, TraceDirectoryName)}; pass a trace file or --epic`
51
- });
52
- }
53
- const epic = yield* epicOfTrace(tracePath, options.repo, dependencies);
54
- return { tracePath, epicDir: epic?.dir, run: epic?.run };
55
- });
56
- const actionWords = (run) => {
57
- if (run === undefined) {
58
- return undefined;
59
- }
60
- switch (run.action) {
61
- case "RunPlan":
62
- return "run plan";
63
- case "RunRound":
64
- return `round ${run.round ?? "?"}`;
65
- case "PlanRound":
66
- return `plan round ${run.round ?? "?"}`;
67
- case "Land":
68
- return "land";
69
- default:
70
- return run.action;
71
- }
72
- };
73
- /** The tree before any event: the epic's board, when the trace belongs to one. */
74
- const startingTree = (target, files, idleAfterMs) => Effect.gen(function* () {
75
- const action = actionWords(target.run);
76
- const idle = idleAfterMs === undefined ? {} : { idleAfterMs };
77
- if (target.epicDir === undefined) {
78
- return emptyTree({ ...idle, ...(action === undefined ? {} : { action }) });
79
- }
80
- const boardDir = target.run?.round === undefined
81
- ? target.epicDir
82
- : join(target.epicDir, "rounds", String(target.run.round));
83
- const board = yield* loadVersioned(files, join(boardDir, "board.json"), BoardVersion, Board);
84
- const epicId = target.epicDir.split("/").at(-1) ?? "epic";
85
- return emptyTree({
86
- title: board === undefined ? `epic ${epicId}` : board.title.replace(/^Epic:\s*/u, "epic "),
87
- stories: (board?.items ?? []).map((item) => ({ id: item.id, status: item.status })),
88
- ...idle,
89
- ...(action === undefined ? {} : { action })
90
- });
91
- });
92
- const readInputs = (target, files) => Effect.map(readTrace(files, target.tracePath), treeInputsOfTrace);
93
- const pollInterval = Duration.millis(500);
94
- const replayGapCap = 2_000;
95
- const draw = (state, view, output, height, tail) => renderTree(state, {
96
- width: Math.max(90, output.columns() ?? 90),
97
- colour: output.colour,
98
- view,
99
- ...(height === undefined ? {} : { height }),
100
- ...(tail === undefined ? {} : { tail })
101
- }).join("\n");
102
- /** A full-screen frame: no taller than the terminal. */
103
- const screenLines = (state, view, output, tail) => draw(state, view, output, output.rows(), tail).split("\n");
104
- /** Rows the tail pane shows. */
105
- const tailRows = 16;
106
- /** Where a trace's run kept its transcript: `.llm4ts/transcripts/<run-id>/`. */
107
- const transcriptDirOf = (repo, target, files) => Effect.map(readTrace(files, target.tracePath), (lines) => {
108
- const runId = lines[0]?.runId;
109
- return runId === undefined ? undefined : join(repo, TraceDirectoryName, "transcripts", runId);
110
- });
111
- export const makeWatchProgram = Effect.fn("@llm4ts/runner/Watch.make")(function* (options, dependencies) {
112
- const target = yield* resolveTraceTarget(options, dependencies);
113
- const { files, output } = dependencies;
114
- const fold = (inputs) => Effect.map(startingTree(target, files, options.idleAfterMs), (start) => inputs.reduce(reduceTree, start));
115
- const transcripts = dependencies.transcripts ?? nodeTranscriptFiles;
116
- const transcriptDir = yield* transcriptDirOf(options.repo, target, files);
117
- if (options.tail !== undefined) {
118
- if (transcriptDir === undefined || transcripts.list(transcriptDir).length === 0) {
119
- return yield* WatchTargetMissing.make({
120
- message: "no transcript for this run — start it with llm4ts run … --transcript"
121
- });
122
- }
123
- return yield* followTail(options.tail, transcriptDir, transcripts, output, () => Effect.map(readInputs(target, files), (inputs) => inputs.some((input) => input._tag === "RunEnded")));
124
- }
125
- /** The open tail's lines, for the view's selection. */
126
- const tailFor = (view) => {
127
- const selected = tailTargetOf(view);
128
- return !view.tail || selected === undefined || transcriptDir === undefined
129
- ? Effect.succeed(undefined)
130
- : Effect.map(loadTranscript(transcripts, transcriptDir, selected), (entries) => tailLinesOf(entries, selected, view.tailRole, Math.max(90, output.columns() ?? 90) - 32, tailRows, view.tailBack));
131
- };
132
- if (!output.interactive) {
133
- const state = yield* Effect.flatMap(readInputs(target, files), fold);
134
- return yield* output.write(`${draw(state, initialView, output)}\n`);
135
- }
136
- yield* Effect.scoped(Effect.gen(function* () {
137
- const keys = yield* Queue.unbounded();
138
- yield* Effect.forkScoped(Stream.runForEach(dependencies.keys, (key) => Queue.offer(keys, key)));
139
- const view = yield* Ref.make(initialView);
140
- const all = yield* readInputs(target, files);
141
- // Replay steps through the inputs on their timestamps; otherwise the
142
- // whole trace is shown and re-read while the run goes on.
143
- const shown = yield* Ref.make(options.replay === true ? Math.min(1, all.length) : all.length);
144
- const inputs = yield* Ref.make(all);
145
- const speed = Math.max(1, options.speed ?? 10);
146
- /** Waits for a key or for `wait`; true when the key was `q`. */
147
- const awaitKey = (wait) => Effect.raceFirst(Effect.flatMap(Queue.take(keys), (key) => Effect.gen(function* () {
148
- const state = yield* Effect.orDie(Effect.flatMap(Ref.get(inputs), (current) => Effect.flatMap(Ref.get(shown), (count) => fold(current.slice(0, count)))));
149
- const next = onTreeKey(yield* Ref.get(view), key, state);
150
- if (next === "quit") {
151
- return true;
152
- }
153
- yield* Ref.set(view, next);
154
- return false;
155
- })), Effect.as(Effect.sleep(wait), false));
156
- const painter = yield* makeScreenPainter;
157
- yield* output.write(enterScreen);
158
- yield* Effect.gen(function* () {
159
- while (true) {
160
- const current = yield* Ref.get(inputs);
161
- const count = yield* Ref.get(shown);
162
- const folded = yield* fold(current.slice(0, count));
163
- // Following a live run, the clock moves between events; a replay
164
- // and a finished run keep the trace's own time.
165
- const state = options.replay !== true && folded.ended === undefined
166
- ? reduceTree(folded, { _tag: "Tick", at: yield* Clock.currentTimeMillis })
167
- : folded;
168
- const text = yield* painter.paint(screenLines(state, yield* Ref.get(view), output, yield* tailFor(yield* Ref.get(view))), `${output.columns()}x${output.rows()}`);
169
- if (text.length > 0) {
170
- yield* output.write(text);
171
- }
172
- const replaying = options.replay === true && count < current.length;
173
- const gap = replaying
174
- ? Math.min(replayGapCap, (current[count]?.at ?? 0) - (current[count - 1]?.at ?? 0)) /
175
- speed
176
- : Duration.toMillis(pollInterval);
177
- if (yield* awaitKey(Duration.millis(Math.max(0, gap)))) {
178
- return;
179
- }
180
- if (replaying) {
181
- yield* Ref.update(shown, (shownCount) => shownCount + 1);
182
- }
183
- else if (state.ended === undefined) {
184
- const reread = yield* readInputs(target, files);
185
- yield* Ref.set(inputs, reread);
186
- yield* Ref.set(shown, reread.length);
187
- }
188
- }
189
- }).pipe(Effect.ensuring(output.write(leaveScreen)));
190
- }));
191
- });
192
- // ── node wiring ─────────────────────────────────────────────────────────────
193
- /** Folder names under an `epics/` directory; none when it is absent. */
194
- export const nodeListEpics = (directory) => existsSync(directory)
195
- ? readdirSync(directory).filter((name) => statSync(join(directory, name)).isDirectory())
196
- : [];
197
- export const nodeTraceSources = {
198
- files: nodePlainFileStore,
199
- listTraces: nodeListTraces,
200
- listEpics: nodeListEpics
201
- };
202
- export const nodeWatchDependencies = (environment = process.env) => {
203
- const interactive = process.stdout.isTTY === true && process.stdin.isTTY === true;
204
- return {
205
- files: nodePlainFileStore,
206
- listTraces: nodeListTraces,
207
- listEpics: nodeListEpics,
208
- output: {
209
- write: (text) => Effect.sync(() => void process.stdout.write(text)),
210
- columns: () => process.stdout.columns,
211
- rows: () => process.stdout.rows,
212
- interactive,
213
- colour: process.stdout.isTTY === true && environment.NO_COLOR === undefined
214
- },
215
- keys: nodeTreeKeys("detach")
216
- };
217
- };
218
- // ── tail ────────────────────────────────────────────────────────────────────
219
- /**
220
- * `llm4ts watch --tail <story|executor>`: the transcript printed as it grows,
221
- * like `tail -f` — a call's reply streams in as written — until the run ends.
222
- * A name with its own file is a story; any other is an executor.
223
- */
224
- const followTail = (name, directory, transcripts, output, ended) => Effect.gen(function* () {
225
- const target = transcripts.list(directory).includes(transcriptFileOf(name))
226
- ? { lane: name }
227
- : { executor: name };
228
- const width = Math.max(60, output.columns() ?? 100);
229
- let shown = 0;
230
- let start;
231
- const wanted = new Set();
232
- let replying;
233
- while (true) {
234
- const done = yield* ended();
235
- const entries = (yield* loadTranscript(transcripts, directory, target)) ?? [];
236
- for (const entry of entries.slice(shown)) {
237
- start = start ?? entry.at;
238
- if (entry._tag === "Call" && ("lane" in target || entry.executor === target.executor)) {
239
- wanted.add(entry.call);
240
- }
241
- if (!wanted.has(entry.call)) {
242
- continue;
243
- }
244
- if (entry._tag === "Reply") {
245
- // A reply streams: its text as it arrived, on one growing paragraph.
246
- yield* output.write(`${replying === entry.call ? "" : "◀ "}${entry.text}`);
247
- replying = entry.call;
248
- continue;
249
- }
250
- const lines = renderTranscript([entry], { width, since: start });
251
- yield* output.write(`${replying === undefined ? "" : "\n"}${lines.join("\n")}\n`);
252
- replying = undefined;
253
- }
254
- shown = entries.length;
255
- if (done) {
256
- return;
257
- }
258
- yield* Effect.sleep(pollInterval);
259
- }
260
- });
261
- //# sourceMappingURL=Watch.js.map
package/dist/Watch.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"Watch.js","sourceRoot":"","sources":["../src/Watch.ts"],"names":[],"mappings":"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"}
package/src/Costs.ts DELETED
@@ -1,148 +0,0 @@
1
- import { existsSync, readdirSync } from "node:fs"
2
- import { join } from "node:path"
3
- import type * as DateTime from "effect/DateTime"
4
- import * as Effect from "effect/Effect"
5
- import * as Schema from "effect/Schema"
6
- import { CostLedgerFileName, loadCostLedger, type CostRecord } from "@llm4ts/flow/CostLedger"
7
- import {
8
- CostReport,
9
- buildCostReport,
10
- reconcileWithLedger,
11
- renderCostReport,
12
- usageSamplesFromTrace,
13
- type UsageSample
14
- } from "@llm4ts/flow/CostReport"
15
- import { describeFlowError } from "@llm4ts/flow/FlowError"
16
- import type { PlainFileStoreShape } from "@llm4ts/flow/Persistence"
17
- import { readTrace } from "@llm4ts/flow/Replay"
18
- import { nodePlainFileStore } from "./NodePlainFileStore.ts"
19
-
20
- /**
21
- * `llm4ts costs`: the budgeting view over every trace the runner wrote.
22
- *
23
- * Traces are the source for timing: a run can span hours and only the trace
24
- * carries a timestamp per token report, which the hourly buckets need. The
25
- * cost ledger is the source for each run's total: its line is the run's own
26
- * summary, and a trace can be short (`CostReport.reconcileWithLedger`). One
27
- * unreadable trace is reported and skipped rather than failing the whole
28
- * report — the other runs still answer the question.
29
- */
30
-
31
- export const TraceDirectoryName = ".llm4ts"
32
-
33
- /** `trace-<timestamp>.jsonl` as the runner writes it, or a prefixed variant like `loop-trace-…`. */
34
- export const isTraceFileName = (name: string): boolean => /(?:^|-)trace-\d+\.jsonl$/u.test(name)
35
-
36
- export const nodeListTraces = (directory: string): ReadonlyArray<string> =>
37
- existsSync(directory)
38
- ? readdirSync(directory)
39
- .filter(isTraceFileName)
40
- .sort()
41
- .map((name) => join(directory, name))
42
- : []
43
-
44
- export interface CostsOptions {
45
- /** Repositories whose `.llm4ts/` traces are read. */
46
- readonly repos: ReadonlyArray<string>
47
- /** Drop token reports before this epoch millisecond. */
48
- readonly since?: number
49
- readonly timeZone?: DateTime.TimeZone
50
- readonly runsPerDay?: number
51
- }
52
-
53
- export interface CostsDependencies {
54
- readonly files: PlainFileStoreShape
55
- /** Absolute trace paths under one `.llm4ts/` directory. */
56
- readonly listTraces: (directory: string) => ReadonlyArray<string>
57
- }
58
-
59
- export const nodeCostsDependencies = (): CostsDependencies => ({
60
- files: nodePlainFileStore,
61
- listTraces: nodeListTraces
62
- })
63
-
64
- export class SkippedTrace extends Schema.Class<SkippedTrace>("SkippedTrace")({
65
- path: Schema.String,
66
- reason: Schema.String
67
- }) {}
68
-
69
- export class CostsResult extends Schema.Class<CostsResult>("CostsResult")({
70
- report: CostReport,
71
- traces: Schema.Int,
72
- skipped: Schema.Array(SkippedTrace),
73
- /** Runs whose trace was short or missing, completed from their cost ledger line. */
74
- ledgerRuns: Schema.Array(Schema.String).pipe(
75
- Schema.withConstructorDefault(Effect.succeed<ReadonlyArray<string>>([])),
76
- Schema.withDecodingDefaultKey(Effect.succeed<ReadonlyArray<string>>([]))
77
- )
78
- }) {}
79
-
80
- export const makeCostsProgram = Effect.fn("@llm4ts/runner/Costs.make")(function* (
81
- options: CostsOptions,
82
- dependencies: CostsDependencies = nodeCostsDependencies()
83
- ): Effect.fn.Return<CostsResult> {
84
- const paths = options.repos.flatMap((repo) =>
85
- dependencies.listTraces(join(repo, TraceDirectoryName))
86
- )
87
- const skipped: Array<SkippedTrace> = []
88
- const traced: Array<UsageSample> = []
89
- for (const path of paths) {
90
- const lines = yield* readTrace(dependencies.files, path).pipe(
91
- Effect.catch((error) =>
92
- Effect.sync(() => {
93
- skipped.push(SkippedTrace.make({ path, reason: describeFlowError(error) }))
94
- return []
95
- })
96
- )
97
- )
98
- traced.push(...usageSamplesFromTrace(lines))
99
- }
100
- // An unreadable ledger is no ledger: the traces still answer, uncorrected.
101
- const records: Array<CostRecord> = []
102
- for (const repo of options.repos) {
103
- const path = join(repo, TraceDirectoryName, CostLedgerFileName)
104
- records.push(
105
- ...(yield* loadCostLedger(dependencies.files, path).pipe(
106
- Effect.catch((error) =>
107
- Effect.sync(() => {
108
- skipped.push(SkippedTrace.make({ path, reason: describeFlowError(error) }))
109
- return []
110
- })
111
- )
112
- ))
113
- )
114
- }
115
- const reconciled = reconcileWithLedger(traced, records)
116
- const samples = reconciled.samples.filter(
117
- (sample) => options.since === undefined || sample.at >= options.since
118
- )
119
- return CostsResult.make({
120
- report: buildCostReport(samples, {
121
- ...(options.timeZone === undefined ? {} : { timeZone: options.timeZone }),
122
- ...(options.runsPerDay === undefined ? {} : { runsPerDay: options.runsPerDay })
123
- }),
124
- traces: paths.length,
125
- skipped,
126
- ledgerRuns: reconciled.filledRuns
127
- })
128
- })
129
-
130
- export const renderCostsResult = (result: CostsResult): string => {
131
- const skipped =
132
- result.skipped.length === 0
133
- ? []
134
- : ["", ...result.skipped.map((entry) => `skipped ${entry.path}: ${entry.reason}`)]
135
- const ledger =
136
- result.ledgerRuns.length === 0
137
- ? []
138
- : [
139
- `${result.ledgerRuns.length} run${result.ledgerRuns.length === 1 ? "" : "s"} completed from the cost ledger (trace short or missing, remainder at the run's start): ${result.ledgerRuns.join(", ")}`
140
- ]
141
- return [
142
- renderCostReport(result.report),
143
- "",
144
- `traces read: ${result.traces - result.skipped.length} of ${result.traces}`,
145
- ...ledger,
146
- ...skipped
147
- ].join("\n")
148
- }
package/src/McpStdio.ts DELETED
@@ -1,41 +0,0 @@
1
- import { createInterface } from "node:readline"
2
- import { stdin, stdout } from "node:process"
3
- import * as Effect from "effect/Effect"
4
- import * as Stream from "effect/Stream"
5
- import { ProcessError, type FlowError } from "@llm4ts/flow/FlowError"
6
- import { handleMcpLine, type McpTool } from "@llm4ts/flow/McpServer"
7
-
8
- export const mcpStdioResponses = <R>(
9
- lines: Stream.Stream<string, FlowError, R>,
10
- tools: ReadonlyArray<McpTool>
11
- ): Stream.Stream<string, FlowError, R> =>
12
- lines.pipe(
13
- Stream.mapEffect((line) => handleMcpLine(line, tools)),
14
- Stream.filter((response): response is string => response !== undefined)
15
- )
16
-
17
- export const runMcpStdio = (
18
- tools: ReadonlyArray<McpTool>,
19
- write: (line: string) => void = (line) => stdout.write(`${line}\n`)
20
- ): Effect.Effect<void, FlowError> =>
21
- Effect.acquireUseRelease(
22
- Effect.sync(() =>
23
- createInterface({
24
- input: stdin,
25
- crlfDelay: Infinity,
26
- terminal: false
27
- })
28
- ),
29
- (input) => {
30
- const lines = Stream.fromAsyncIterable(input, (error) =>
31
- ProcessError.make({
32
- message: "MCP stdio input",
33
- detail: error instanceof Error ? error.message : String(error)
34
- })
35
- )
36
- return mcpStdioResponses(lines, tools).pipe(
37
- Stream.runForEach((line) => Effect.sync(() => write(line)))
38
- )
39
- },
40
- (input) => Effect.sync(() => input.close())
41
- )