@sapiom/harness 0.1.5 → 0.2.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 +151 -0
- package/dist/cli/args.d.ts +16 -0
- package/dist/cli/args.d.ts.map +1 -0
- package/dist/cli/args.js +80 -0
- package/dist/cli/args.js.map +1 -0
- package/dist/cli/bin.js +30 -66
- package/dist/cli/bin.js.map +1 -1
- package/dist/cli/consent.js +1 -1
- package/dist/cli/settings.d.ts.map +1 -1
- package/dist/cli/settings.js +33 -1
- package/dist/cli/settings.js.map +1 -1
- package/dist/core/adapters/adapter.d.ts +2 -2
- package/dist/core/adapters/claude-code.d.ts +60 -2
- package/dist/core/adapters/claude-code.d.ts.map +1 -1
- package/dist/core/adapters/claude-code.js +119 -32
- package/dist/core/adapters/claude-code.js.map +1 -1
- package/dist/core/adapters/codex.d.ts +21 -2
- package/dist/core/adapters/codex.d.ts.map +1 -1
- package/dist/core/adapters/codex.js +53 -2
- package/dist/core/adapters/codex.js.map +1 -1
- package/dist/core/adapters/detect.d.ts +9 -0
- package/dist/core/adapters/detect.d.ts.map +1 -1
- package/dist/core/adapters/detect.js +9 -0
- package/dist/core/adapters/detect.js.map +1 -1
- package/dist/core/api-key-provider.d.ts +79 -0
- package/dist/core/api-key-provider.d.ts.map +1 -0
- package/dist/core/api-key-provider.js +91 -0
- package/dist/core/api-key-provider.js.map +1 -0
- package/dist/core/canvas-body.d.ts +28 -28
- package/dist/core/canvas-body.d.ts.map +1 -1
- package/dist/core/canvas-body.js +117 -55
- package/dist/core/canvas-body.js.map +1 -1
- package/dist/core/canvas-derive.d.ts +43 -0
- package/dist/core/canvas-derive.d.ts.map +1 -0
- package/dist/core/canvas-derive.js +95 -0
- package/dist/core/canvas-derive.js.map +1 -0
- package/dist/core/canvas-enrichment.d.ts +52 -127
- package/dist/core/canvas-enrichment.d.ts.map +1 -1
- package/dist/core/canvas-enrichment.js +17 -178
- package/dist/core/canvas-enrichment.js.map +1 -1
- package/dist/core/canvas-graph.d.ts +40 -1
- package/dist/core/canvas-graph.d.ts.map +1 -1
- package/dist/core/canvas-graph.js +71 -9
- package/dist/core/canvas-graph.js.map +1 -1
- package/dist/core/canvas-interconnections.d.ts +26 -8
- package/dist/core/canvas-interconnections.d.ts.map +1 -1
- package/dist/core/canvas-interconnections.js +132 -24
- package/dist/core/canvas-interconnections.js.map +1 -1
- package/dist/core/canvas-manifest-check.d.ts.map +1 -1
- package/dist/core/canvas-manifest-check.js +15 -2
- package/dist/core/canvas-manifest-check.js.map +1 -1
- package/dist/core/canvas-render.d.ts +8 -15
- package/dist/core/canvas-render.d.ts.map +1 -1
- package/dist/core/canvas-render.js +29 -41
- package/dist/core/canvas-render.js.map +1 -1
- package/dist/core/canvas-run-state.d.ts +50 -5
- package/dist/core/canvas-run-state.d.ts.map +1 -1
- package/dist/core/canvas-run-state.js +176 -11
- package/dist/core/canvas-run-state.js.map +1 -1
- package/dist/core/canvas-svg.d.ts +9 -4
- package/dist/core/canvas-svg.d.ts.map +1 -1
- package/dist/core/canvas-svg.js +84 -13
- package/dist/core/canvas-svg.js.map +1 -1
- package/dist/core/canvas-template.d.ts +9 -10
- package/dist/core/canvas-template.d.ts.map +1 -1
- package/dist/core/canvas-template.js +57 -20
- package/dist/core/canvas-template.js.map +1 -1
- package/dist/core/canvas-watcher.d.ts +22 -1
- package/dist/core/canvas-watcher.d.ts.map +1 -1
- package/dist/core/canvas-watcher.js +111 -30
- package/dist/core/canvas-watcher.js.map +1 -1
- package/dist/core/collector/normalizer.d.ts +8 -0
- package/dist/core/collector/normalizer.d.ts.map +1 -1
- package/dist/core/collector/normalizer.js +8 -0
- package/dist/core/collector/normalizer.js.map +1 -1
- package/dist/core/collector/store.d.ts +75 -1
- package/dist/core/collector/store.d.ts.map +1 -1
- package/dist/core/collector/store.js +334 -2
- package/dist/core/collector/store.js.map +1 -1
- package/dist/core/definition-slug-resolver.d.ts +13 -0
- package/dist/core/definition-slug-resolver.d.ts.map +1 -1
- package/dist/core/definition-slug-resolver.js +29 -0
- package/dist/core/definition-slug-resolver.js.map +1 -1
- package/dist/core/errors.d.ts +10 -4
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +11 -5
- package/dist/core/errors.js.map +1 -1
- package/dist/core/example-seed.d.ts +8 -0
- package/dist/core/example-seed.d.ts.map +1 -1
- package/dist/core/example-seed.js +47 -10
- package/dist/core/example-seed.js.map +1 -1
- package/dist/core/inject/system-prompt.d.ts +8 -0
- package/dist/core/inject/system-prompt.d.ts.map +1 -1
- package/dist/core/inject/system-prompt.js +3 -1
- package/dist/core/inject/system-prompt.js.map +1 -1
- package/dist/core/macros.d.ts.map +1 -1
- package/dist/core/macros.js +5 -6
- package/dist/core/macros.js.map +1 -1
- package/dist/core/paths.d.ts +1 -0
- package/dist/core/paths.d.ts.map +1 -1
- package/dist/core/paths.js +1 -0
- package/dist/core/paths.js.map +1 -1
- package/dist/core/record-archive.d.ts +187 -0
- package/dist/core/record-archive.d.ts.map +1 -0
- package/dist/core/record-archive.js +465 -0
- package/dist/core/record-archive.js.map +1 -0
- package/dist/core/rehydration.d.ts +72 -0
- package/dist/core/rehydration.d.ts.map +1 -0
- package/dist/core/rehydration.js +72 -0
- package/dist/core/rehydration.js.map +1 -0
- package/dist/core/render-local-run.d.ts +82 -0
- package/dist/core/render-local-run.d.ts.map +1 -0
- package/dist/core/render-local-run.js +105 -0
- package/dist/core/render-local-run.js.map +1 -0
- package/dist/core/render-log-slice.d.ts +30 -0
- package/dist/core/render-log-slice.d.ts.map +1 -0
- package/dist/core/render-log-slice.js +49 -0
- package/dist/core/render-log-slice.js.map +1 -0
- package/dist/core/render-run-state.d.ts.map +1 -1
- package/dist/core/render-run-state.js +30 -49
- package/dist/core/render-run-state.js.map +1 -1
- package/dist/core/resume-brief.d.ts +130 -0
- package/dist/core/resume-brief.d.ts.map +1 -0
- package/dist/core/resume-brief.js +404 -0
- package/dist/core/resume-brief.js.map +1 -0
- package/dist/core/rolling-summary.d.ts +130 -0
- package/dist/core/rolling-summary.d.ts.map +1 -0
- package/dist/core/rolling-summary.js +227 -0
- package/dist/core/rolling-summary.js.map +1 -0
- package/dist/core/run-local-bootstrap.d.ts +93 -0
- package/dist/core/run-local-bootstrap.d.ts.map +1 -0
- package/dist/core/run-local-bootstrap.js +155 -0
- package/dist/core/run-local-bootstrap.js.map +1 -0
- package/dist/core/run-state.d.ts +16 -1
- package/dist/core/run-state.d.ts.map +1 -1
- package/dist/core/run-state.js +75 -25
- package/dist/core/run-state.js.map +1 -1
- package/dist/core/session-manager.d.ts +11 -3
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +56 -7
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/session-record.d.ts +165 -0
- package/dist/core/session-record.d.ts.map +1 -0
- package/dist/core/session-record.js +470 -0
- package/dist/core/session-record.js.map +1 -0
- package/dist/core/spawn-target.d.ts +12 -0
- package/dist/core/spawn-target.d.ts.map +1 -0
- package/dist/core/spawn-target.js +187 -0
- package/dist/core/spawn-target.js.map +1 -0
- package/dist/core/stub-feedback.d.ts +52 -0
- package/dist/core/stub-feedback.d.ts.map +1 -0
- package/dist/core/stub-feedback.js +33 -0
- package/dist/core/stub-feedback.js.map +1 -0
- package/dist/core/task-manager.d.ts.map +1 -1
- package/dist/core/task-manager.js +9 -1
- package/dist/core/task-manager.js.map +1 -1
- package/dist/core/template-catalog.d.ts +48 -0
- package/dist/core/template-catalog.d.ts.map +1 -0
- package/dist/core/template-catalog.js +338 -0
- package/dist/core/template-catalog.js.map +1 -0
- package/dist/core/workflow-registry.d.ts.map +1 -1
- package/dist/core/workflow-registry.js +2 -2
- package/dist/core/workflow-registry.js.map +1 -1
- package/dist/core/workspace-watcher.d.ts.map +1 -1
- package/dist/core/workspace-watcher.js +4 -3
- package/dist/core/workspace-watcher.js.map +1 -1
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -1
- package/dist/profiles/default.d.ts.map +1 -1
- package/dist/profiles/default.js +9 -14
- package/dist/profiles/default.js.map +1 -1
- package/dist/server/actions.d.ts +139 -0
- package/dist/server/actions.d.ts.map +1 -0
- package/dist/server/actions.js +430 -0
- package/dist/server/actions.js.map +1 -0
- package/dist/server/auth-routes.d.ts +92 -0
- package/dist/server/auth-routes.d.ts.map +1 -0
- package/dist/server/auth-routes.js +151 -0
- package/dist/server/auth-routes.js.map +1 -0
- package/dist/server/canvas.d.ts.map +1 -1
- package/dist/server/canvas.js +7 -7
- package/dist/server/canvas.js.map +1 -1
- package/dist/server/fs.d.ts.map +1 -1
- package/dist/server/fs.js +17 -1
- package/dist/server/fs.js.map +1 -1
- package/dist/server/index.d.ts +12 -3
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +0 -0
- package/dist/server/index.js.map +1 -1
- package/dist/server/ingest.d.ts +11 -0
- package/dist/server/ingest.d.ts.map +1 -1
- package/dist/server/ingest.js +1 -0
- package/dist/server/ingest.js.map +1 -1
- package/dist/server/macros.d.ts +4 -6
- package/dist/server/macros.d.ts.map +1 -1
- package/dist/server/macros.js.map +1 -1
- package/dist/server/rest.d.ts +18 -6
- package/dist/server/rest.d.ts.map +1 -1
- package/dist/server/rest.js +185 -50
- package/dist/server/rest.js.map +1 -1
- package/dist/server/runs.d.ts +16 -15
- package/dist/server/runs.d.ts.map +1 -1
- package/dist/server/runs.js +15 -80
- package/dist/server/runs.js.map +1 -1
- package/dist/server/static.d.ts +15 -1
- package/dist/server/static.d.ts.map +1 -1
- package/dist/server/static.js +54 -4
- package/dist/server/static.js.map +1 -1
- package/dist/server/templates.d.ts +24 -0
- package/dist/server/templates.d.ts.map +1 -0
- package/dist/server/templates.js +54 -0
- package/dist/server/templates.js.map +1 -0
- package/dist/shared/types.d.ts +558 -66
- package/dist/shared/types.d.ts.map +1 -1
- package/dist/shared/types.js +19 -11
- package/dist/shared/types.js.map +1 -1
- package/dist/web/assets/index-DC65cskq.js +446 -0
- package/dist/web/assets/index-xtD-3FFa.css +32 -0
- package/dist/web/canvas/sess-boot/index.html +305 -0
- package/dist/web/index.html +4 -9
- package/package.json +8 -4
- package/dist/core/canvas-enrich.d.ts +0 -115
- package/dist/core/canvas-enrich.d.ts.map +0 -1
- package/dist/core/canvas-enrich.js +0 -186
- package/dist/core/canvas-enrich.js.map +0 -1
- package/dist/core/run-spend.d.ts +0 -55
- package/dist/core/run-spend.d.ts.map +0 -1
- package/dist/core/run-spend.js +0 -109
- package/dist/core/run-spend.js.map +0 -1
- package/dist/core/run-transactions.d.ts +0 -60
- package/dist/core/run-transactions.d.ts.map +0 -1
- package/dist/core/run-transactions.js +0 -129
- package/dist/core/run-transactions.js.map +0 -1
- package/dist/profiles/canvas-guidelines.d.ts +0 -20
- package/dist/profiles/canvas-guidelines.d.ts.map +0 -1
- package/dist/profiles/canvas-guidelines.js +0 -48
- package/dist/profiles/canvas-guidelines.js.map +0 -1
- package/dist/server/skills.d.ts +0 -51
- package/dist/server/skills.d.ts.map +0 -1
- package/dist/server/skills.js +0 -312
- package/dist/server/skills.js.map +0 -1
- package/dist/web/assets/index-DM84J83Y.js +0 -234
- package/dist/web/assets/index-DemtWW4L.css +0 -32
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* renderLocalRun — the pure mapper from an offline stub run's per-step traces
|
|
3
|
+
* ({@link LocalStepTrace}[], streamed as NDJSON by `POST /api/runs/local`) to
|
|
4
|
+
* the same {@link RunView} the canvas renders for prod runs. Its twin is
|
|
5
|
+
* {@link renderRunState} (prod / local-backend); both emit the identical
|
|
6
|
+
* cost-free {@link StepView} shape, so ONE inspector renders every run source.
|
|
7
|
+
*
|
|
8
|
+
* Pure and deterministic: no LLM, no I/O, no clock. Every field is derived from
|
|
9
|
+
* the traces (plus the caller-supplied execution id and terminal outcome), so
|
|
10
|
+
* the same function can map a partial trace mid-stream and the final trace at
|
|
11
|
+
* the end — only the input grows, never this mapping. It is a Stryker target;
|
|
12
|
+
* the tests are mutation-first.
|
|
13
|
+
*
|
|
14
|
+
* Honest absence, matching renderRunState and the SDK's "null is honest absence,
|
|
15
|
+
* never a fabricated value" contract:
|
|
16
|
+
* - **No cost** — local runs are stubbed and free by construction; a StepView
|
|
17
|
+
* from here never carries `costUsd` (so the inspector reads "local run ·
|
|
18
|
+
* free", never "$0.00").
|
|
19
|
+
* - **No latency** — a {@link LocalStepTrace} carries no timing (agent-core's
|
|
20
|
+
* in-process dispatcher records none, and agent-core is consumed as-is), so
|
|
21
|
+
* `latencyMs` is ABSENT rather than a fabricated `0`.
|
|
22
|
+
* - **Output** is present only when the trace captured one (a step that threw,
|
|
23
|
+
* or a `continue` with no value, carries none) — but ABSENCE is `undefined`
|
|
24
|
+
* on the trace, and a genuine `null`/`false`/`0`/`""` output is a real value
|
|
25
|
+
* that passes through.
|
|
26
|
+
* - **Input** is always carried by a trace (every attempt ran on some input,
|
|
27
|
+
* even `undefined`); it is surfaced whenever it isn't `undefined`.
|
|
28
|
+
* - **Logs and errors** collapse to the same `logSlice`/`error` fields prod
|
|
29
|
+
* uses, via the shared formatter.
|
|
30
|
+
* - **Stub signal (WB15-2)** is RUN-LEVEL. A local run is stub-served by
|
|
31
|
+
* construction, so the run carries `stubbed: true` (prod's renderRunState
|
|
32
|
+
* never does) and the inspector marks each executed step with a "stubbed"
|
|
33
|
+
* chip — agent-core records no per-CALL stub attribution, so that is the
|
|
34
|
+
* honest granularity. The terminal summary's `unusedStubs` (a supplied key
|
|
35
|
+
* that matched nothing) and `stubWarnings` (a wrong-shape value) pass through
|
|
36
|
+
* only when NON-empty, so a clean run surfaces no notice at all.
|
|
37
|
+
*/
|
|
38
|
+
import type { LocalStepTrace, LocalRunOutcome } from "@sapiom/agent-core";
|
|
39
|
+
import type { RunView, UnusedStubView } from "../shared/types.js";
|
|
40
|
+
/**
|
|
41
|
+
* Options carrying the run-level facts a `LocalStepTrace[]` alone can't provide.
|
|
42
|
+
* Both are optional so the mapper can render a live, still-streaming trace (no
|
|
43
|
+
* terminal summary yet) exactly as it renders the final one.
|
|
44
|
+
*/
|
|
45
|
+
export interface RenderLocalRunOptions {
|
|
46
|
+
/**
|
|
47
|
+
* The execution id to stamp on the {@link RunView}. A local run has no
|
|
48
|
+
* server-issued id, so the caller (the SPA's run store) synthesizes and owns
|
|
49
|
+
* one; the mapper stays pure by taking it rather than minting time/randomness.
|
|
50
|
+
* Defaults to an empty string when the caller has none yet.
|
|
51
|
+
*/
|
|
52
|
+
executionId?: string;
|
|
53
|
+
/**
|
|
54
|
+
* The run's terminal outcome from the NDJSON summary line, when it has
|
|
55
|
+
* arrived. Absent while the stream is still open — the mapper then reports the
|
|
56
|
+
* run as `running` (steps may still be coming). Passing it flips the run to
|
|
57
|
+
* its settled status.
|
|
58
|
+
*/
|
|
59
|
+
outcome?: LocalRunOutcome;
|
|
60
|
+
/**
|
|
61
|
+
* Supplied stub keys that matched no capability call this run — from the
|
|
62
|
+
* terminal summary line. A no-op mock (typo'd path, wrong plural/singular)
|
|
63
|
+
* otherwise fails silently; surfacing it is the whole point of WB15-2. Only a
|
|
64
|
+
* NON-empty list reaches the {@link RunView} (honest absence), so pass it as-is
|
|
65
|
+
* from the summary and the mapper decides. Absent while the stream is open.
|
|
66
|
+
*/
|
|
67
|
+
unusedStubs?: UnusedStubView[];
|
|
68
|
+
/**
|
|
69
|
+
* Warnings about stub values that matched a key but carried the wrong shape —
|
|
70
|
+
* from the terminal summary line. Same honest-absence handling as
|
|
71
|
+
* {@link RenderLocalRunOptions.unusedStubs}: an empty list is dropped.
|
|
72
|
+
*/
|
|
73
|
+
stubWarnings?: string[];
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Map an offline stub run's traces (plus the caller-owned execution id and, once
|
|
77
|
+
* known, terminal outcome) to the {@link RunView} the canvas renders. Order-
|
|
78
|
+
* preserving over `traces` (execution order); total — never throws, mirroring
|
|
79
|
+
* renderRunState — because the traces are already the decoded wire shape.
|
|
80
|
+
*/
|
|
81
|
+
export declare function renderLocalRun(traces: LocalStepTrace[], options?: RenderLocalRunOptions): RunView;
|
|
82
|
+
//# sourceMappingURL=render-local-run.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-local-run.d.ts","sourceRoot":"","sources":["../../src/core/render-local-run.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAE1E,OAAO,KAAK,EACV,OAAO,EAIP,cAAc,EACf,MAAM,oBAAoB,CAAC;AAQ5B;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,eAAe,CAAC;IAC1B;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,cAAc,EAAE,CAAC;IAC/B;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAoED;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,cAAc,EAAE,EACxB,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAsBT"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
// Reuse prod's exact log-buffer formatter so a step's `logSlice` is byte-
|
|
2
|
+
// identical whether it came from a prod projection or a local trace — the
|
|
3
|
+
// inspector can never disagree with itself about how a log renders. Imported
|
|
4
|
+
// from the dependency-free module (NOT render-run-state) so this mapper carries
|
|
5
|
+
// no `@sapiom/agent-core`/`node:fs` runtime dep into the browser bundle.
|
|
6
|
+
import { toLogSlice } from "./render-log-slice.js";
|
|
7
|
+
/**
|
|
8
|
+
* Fold a single step-attempt's status into a {@link StepStatus}. A local trace's
|
|
9
|
+
* status vocabulary is exactly `succeeded | threw` (see agent-core's
|
|
10
|
+
* LocalStubDispatcher). `succeeded` → `passed`; `threw` → `failed` (it did not
|
|
11
|
+
* pass — mirrors renderRunState's fold of `threw`). Anything unrecognized is
|
|
12
|
+
* `pending` (defensive; the union shouldn't produce it), NEVER silently
|
|
13
|
+
* `passed`.
|
|
14
|
+
*/
|
|
15
|
+
function toStepStatus(raw) {
|
|
16
|
+
if (raw === "succeeded")
|
|
17
|
+
return "passed";
|
|
18
|
+
if (raw === "threw")
|
|
19
|
+
return "failed";
|
|
20
|
+
return "pending";
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Fold the run's terminal outcome into the four states the UI draws. A local run
|
|
24
|
+
* that `paused` is not yet done (the auto-resume loop or a human must advance
|
|
25
|
+
* it), so it reads as `running`, not a terminal state. An absent outcome (stream
|
|
26
|
+
* still open) is also `running`. `completed`/`failed` map straight through;
|
|
27
|
+
* there is no local "cancelled" outcome.
|
|
28
|
+
*/
|
|
29
|
+
function toRunStatus(outcome) {
|
|
30
|
+
if (outcome === "completed")
|
|
31
|
+
return "completed";
|
|
32
|
+
if (outcome === "failed")
|
|
33
|
+
return "failed";
|
|
34
|
+
// "paused", "running", or absent (still streaming) — not terminal.
|
|
35
|
+
return "running";
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Map one trace line to its {@link StepView}. Optional fields are assigned only
|
|
39
|
+
* when they carry a real value, so honest absence survives into the JSON the
|
|
40
|
+
* inspector reads (a missing field renders nothing rather than a fabricated
|
|
41
|
+
* zero/empty payload).
|
|
42
|
+
*/
|
|
43
|
+
function toStepView(trace) {
|
|
44
|
+
const view = {
|
|
45
|
+
// Local traces have no OTel span id; the (step, attempt) pair is the stable,
|
|
46
|
+
// collision-free key across a run's attempts of the same step.
|
|
47
|
+
id: `${trace.step}-${trace.attempt}`,
|
|
48
|
+
name: trace.step,
|
|
49
|
+
status: toStepStatus(trace.status),
|
|
50
|
+
};
|
|
51
|
+
// No costUsd, no latencyMs — a local run is free and untimed (see the file
|
|
52
|
+
// header). Their honest absence is the whole point of the local target.
|
|
53
|
+
if (trace.input !== undefined)
|
|
54
|
+
view.input = trace.input;
|
|
55
|
+
if (trace.output !== undefined)
|
|
56
|
+
view.output = trace.output;
|
|
57
|
+
if (trace.error?.message)
|
|
58
|
+
view.error = trace.error.message;
|
|
59
|
+
const logSlice = toLogSlice(trace.logs);
|
|
60
|
+
if (logSlice !== undefined)
|
|
61
|
+
view.logSlice = logSlice;
|
|
62
|
+
// Per-step capability calls from the stub client. Honest absence: only a
|
|
63
|
+
// non-empty list reaches the view (an empty list means no calls were made —
|
|
64
|
+
// but absence on the trace means the sink was never wired, so we leave it
|
|
65
|
+
// absent too). The StubCallRecord shape maps directly onto StepCall.
|
|
66
|
+
if (trace.calls && trace.calls.length > 0) {
|
|
67
|
+
view.calls = trace.calls.map((c) => ({
|
|
68
|
+
capability: c.capability,
|
|
69
|
+
stubUsed: c.stubUsed,
|
|
70
|
+
args: c.args,
|
|
71
|
+
result: c.result,
|
|
72
|
+
}));
|
|
73
|
+
}
|
|
74
|
+
return view;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Map an offline stub run's traces (plus the caller-owned execution id and, once
|
|
78
|
+
* known, terminal outcome) to the {@link RunView} the canvas renders. Order-
|
|
79
|
+
* preserving over `traces` (execution order); total — never throws, mirroring
|
|
80
|
+
* renderRunState — because the traces are already the decoded wire shape.
|
|
81
|
+
*/
|
|
82
|
+
export function renderLocalRun(traces, options = {}) {
|
|
83
|
+
const view = {
|
|
84
|
+
executionId: options.executionId ?? "",
|
|
85
|
+
status: toRunStatus(options.outcome),
|
|
86
|
+
steps: traces.map(toStepView),
|
|
87
|
+
// A local run is stub-served by construction (every ctx.sapiom.* call
|
|
88
|
+
// resolves from a stub, never the network) — so the run itself is `stubbed`,
|
|
89
|
+
// and the inspector marks each executed step with the chip. This is the
|
|
90
|
+
// honest per-run truth: agent-core records no per-CALL stub attribution, so
|
|
91
|
+
// there is nothing finer to claim. renderRunState (prod) never sets this.
|
|
92
|
+
stubbed: true,
|
|
93
|
+
};
|
|
94
|
+
// Honest absence: only a NON-empty signal reaches the view, so the read-only
|
|
95
|
+
// notice renders nothing when the run had no stub-hygiene problems. A supplied
|
|
96
|
+
// empty array is indistinguishable from "no problems" and must not surface.
|
|
97
|
+
if (options.unusedStubs && options.unusedStubs.length > 0) {
|
|
98
|
+
view.unusedStubs = options.unusedStubs;
|
|
99
|
+
}
|
|
100
|
+
if (options.stubWarnings && options.stubWarnings.length > 0) {
|
|
101
|
+
view.stubWarnings = options.stubWarnings;
|
|
102
|
+
}
|
|
103
|
+
return view;
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=render-local-run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-local-run.js","sourceRoot":"","sources":["../../src/core/render-local-run.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* render-log-slice — the shared, dependency-free formatter for a step's executor
|
|
3
|
+
* log buffer. Both run mappers use it so a step's `logSlice` is byte-identical
|
|
4
|
+
* whether it came from a prod {@link import("./render-run-state.js").renderRunState}
|
|
5
|
+
* projection or a local {@link import("./render-local-run.js").renderLocalRun}
|
|
6
|
+
* trace — the inspector can never disagree with itself about how a log renders.
|
|
7
|
+
*
|
|
8
|
+
* Kept in its OWN module (rather than in render-run-state.ts) precisely because
|
|
9
|
+
* it has NO `@sapiom/agent-core` dependency: render-run-state pulls in agent-core
|
|
10
|
+
* runtime helpers (e.g. `isExecutionTerminal`) that reach for `node:fs`, which
|
|
11
|
+
* must never enter the browser bundle. The local-run mapper is imported by the
|
|
12
|
+
* SPA, so it depends on THIS pure module instead — no Node built-ins ride along.
|
|
13
|
+
*
|
|
14
|
+
* Pure and deterministic: no I/O, no clock. Safe in both Node and the browser.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Cap on the characters of a step's executor log buffer surfaced in `logSlice`.
|
|
18
|
+
* The TAIL is kept (most recent lines) because failures surface at the end of a
|
|
19
|
+
* log. This is a payload guard on the poll/stream response; the debug-macro
|
|
20
|
+
* context extractor does the final, smaller trim for prompt injection.
|
|
21
|
+
*/
|
|
22
|
+
export declare const LOG_SLICE_MAX = 4000;
|
|
23
|
+
/** One executor log entry → a compact line. Accepts the `{ ts, level, msg }`
|
|
24
|
+
* wire shape (or `message`), a bare string, or anything else (stringified).
|
|
25
|
+
* A local trace's `{ level, msg }` entry is a subset of this same shape. */
|
|
26
|
+
export declare function formatLogEntry(entry: unknown): string;
|
|
27
|
+
/** Format the executor log buffer into a trimmed, tail-preserving slice, or
|
|
28
|
+
* `undefined` when there are no usable logs. */
|
|
29
|
+
export declare function toLogSlice(logs: unknown): string | undefined;
|
|
30
|
+
//# sourceMappingURL=render-log-slice.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-log-slice.d.ts","sourceRoot":"","sources":["../../src/core/render-log-slice.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH;;;;;GAKG;AACH,eAAO,MAAM,aAAa,OAAO,CAAC;AAElC;;6EAE6E;AAC7E,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAgBrD;AAED;iDACiD;AACjD,wBAAgB,UAAU,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAO5D"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* render-log-slice — the shared, dependency-free formatter for a step's executor
|
|
3
|
+
* log buffer. Both run mappers use it so a step's `logSlice` is byte-identical
|
|
4
|
+
* whether it came from a prod {@link import("./render-run-state.js").renderRunState}
|
|
5
|
+
* projection or a local {@link import("./render-local-run.js").renderLocalRun}
|
|
6
|
+
* trace — the inspector can never disagree with itself about how a log renders.
|
|
7
|
+
*
|
|
8
|
+
* Kept in its OWN module (rather than in render-run-state.ts) precisely because
|
|
9
|
+
* it has NO `@sapiom/agent-core` dependency: render-run-state pulls in agent-core
|
|
10
|
+
* runtime helpers (e.g. `isExecutionTerminal`) that reach for `node:fs`, which
|
|
11
|
+
* must never enter the browser bundle. The local-run mapper is imported by the
|
|
12
|
+
* SPA, so it depends on THIS pure module instead — no Node built-ins ride along.
|
|
13
|
+
*
|
|
14
|
+
* Pure and deterministic: no I/O, no clock. Safe in both Node and the browser.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Cap on the characters of a step's executor log buffer surfaced in `logSlice`.
|
|
18
|
+
* The TAIL is kept (most recent lines) because failures surface at the end of a
|
|
19
|
+
* log. This is a payload guard on the poll/stream response; the debug-macro
|
|
20
|
+
* context extractor does the final, smaller trim for prompt injection.
|
|
21
|
+
*/
|
|
22
|
+
export const LOG_SLICE_MAX = 4000;
|
|
23
|
+
/** One executor log entry → a compact line. Accepts the `{ ts, level, msg }`
|
|
24
|
+
* wire shape (or `message`), a bare string, or anything else (stringified).
|
|
25
|
+
* A local trace's `{ level, msg }` entry is a subset of this same shape. */
|
|
26
|
+
export function formatLogEntry(entry) {
|
|
27
|
+
if (typeof entry === "string")
|
|
28
|
+
return entry;
|
|
29
|
+
if (entry !== null && typeof entry === "object") {
|
|
30
|
+
const e = entry;
|
|
31
|
+
const parts = [e.ts, e.level, e.msg ?? e.message].filter((p) => typeof p === "string" || typeof p === "number");
|
|
32
|
+
if (parts.length > 0)
|
|
33
|
+
return parts.map(String).join(" ");
|
|
34
|
+
}
|
|
35
|
+
return String(entry);
|
|
36
|
+
}
|
|
37
|
+
/** Format the executor log buffer into a trimmed, tail-preserving slice, or
|
|
38
|
+
* `undefined` when there are no usable logs. */
|
|
39
|
+
export function toLogSlice(logs) {
|
|
40
|
+
if (!Array.isArray(logs) || logs.length === 0)
|
|
41
|
+
return undefined;
|
|
42
|
+
const text = logs.map(formatLogEntry).join("\n").trim();
|
|
43
|
+
if (text === "")
|
|
44
|
+
return undefined;
|
|
45
|
+
return text.length > LOG_SLICE_MAX
|
|
46
|
+
? text.slice(text.length - LOG_SLICE_MAX)
|
|
47
|
+
: text;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=render-log-slice.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-log-slice.js","sourceRoot":"","sources":["../../src/core/render-log-slice.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,CAAC;AAElC;;6EAE6E;AAC7E,MAAM,UAAU,cAAc,CAAC,KAAc;IAC3C,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC5C,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAChD,MAAM,CAAC,GAAG,KAKT,CAAC;QACF,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CACtD,CAAC,CAAC,EAAwB,EAAE,CAC1B,OAAO,CAAC,KAAK,QAAQ,IAAI,OAAO,CAAC,KAAK,QAAQ,CACjD,CAAC;QACF,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC3D,CAAC;IACD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC;AAED;iDACiD;AACjD,MAAM,UAAU,UAAU,CAAC,IAAa;IACtC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAChE,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;IACxD,IAAI,IAAI,KAAK,EAAE;QAAE,OAAO,SAAS,CAAC;IAClC,OAAO,IAAI,CAAC,MAAM,GAAG,aAAa;QAChC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,aAAa,CAAC;QACzC,CAAC,CAAC,IAAI,CAAC;AACX,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render-run-state.d.ts","sourceRoot":"","sources":["../../src/core/render-run-state.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"render-run-state.d.ts","sourceRoot":"","sources":["../../src/core/render-run-state.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EACV,mBAAmB,EAEpB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,KAAK,EAAE,OAAO,EAAwB,MAAM,oBAAoB,CAAC;AA0FxE;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAMpE"}
|
|
@@ -4,24 +4,21 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Pure and deterministic: no LLM, no I/O, no clock. Every field is derived from
|
|
6
6
|
* the decoded projection, so the same function drives the polling path today and
|
|
7
|
-
* a future WebSocket push (only the data source swaps, never this mapping).
|
|
8
|
-
*
|
|
7
|
+
* a future WebSocket push (only the data source swaps, never this mapping).
|
|
8
|
+
* Latency is read straight from the projection and rendered statically — the
|
|
9
9
|
* LLM is only ever invoked later by an explicit debug-macro press, never to
|
|
10
10
|
* compute what's shown here.
|
|
11
11
|
*
|
|
12
|
-
* Honest absence is preserved end to end: a step
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* absence, never a fabricated $0" contract.
|
|
12
|
+
* Honest absence is preserved end to end: a still-running step gets no
|
|
13
|
+
* `latencyMs`, and a step with no logs gets no `logSlice`. The inspector
|
|
14
|
+
* surfaces logs, latency, and pass/fail only — no cost.
|
|
16
15
|
*/
|
|
17
16
|
import { isExecutionTerminal } from "@sapiom/agent-core";
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
*/
|
|
24
|
-
const LOG_SLICE_MAX = 4000;
|
|
17
|
+
// The log-buffer formatter lives in its own dependency-free module so the
|
|
18
|
+
// local-run mapper (imported by the browser SPA) can share the SAME formatter
|
|
19
|
+
// WITHOUT dragging this file's `@sapiom/agent-core` runtime import — and its
|
|
20
|
+
// `node:fs` reach — into the web bundle.
|
|
21
|
+
import { toLogSlice } from "./render-log-slice.js";
|
|
25
22
|
/**
|
|
26
23
|
* Fold the run's lifecycle status into the four states the UI distinguishes.
|
|
27
24
|
* Reuses `isExecutionTerminal` (agent-core's single source of truth for "won't
|
|
@@ -57,14 +54,6 @@ function toStepStatus(raw) {
|
|
|
57
54
|
return "running";
|
|
58
55
|
return "pending";
|
|
59
56
|
}
|
|
60
|
-
/** Captured USD as a number; `undefined` on honest absence (null cost) or an
|
|
61
|
-
* unparseable amount — never a fabricated `0`. */
|
|
62
|
-
function toCostUsd(cost) {
|
|
63
|
-
if (!cost)
|
|
64
|
-
return undefined;
|
|
65
|
-
const n = Number(cost.capturedUsd);
|
|
66
|
-
return Number.isFinite(n) ? n : undefined;
|
|
67
|
-
}
|
|
68
57
|
/** `finishedAt − startedAt` in ms; `undefined` while still running (no finish)
|
|
69
58
|
* or when either timestamp is unparseable. A negative delta (clock skew) is
|
|
70
59
|
* dropped rather than shown as a misleading negative latency. */
|
|
@@ -78,31 +67,6 @@ function toLatencyMs(startedAt, finishedAt) {
|
|
|
78
67
|
const delta = end - start;
|
|
79
68
|
return delta >= 0 ? delta : undefined;
|
|
80
69
|
}
|
|
81
|
-
/** One executor log entry → a compact line. Accepts the `{ ts, level, msg }`
|
|
82
|
-
* wire shape (or `message`), a bare string, or anything else (stringified). */
|
|
83
|
-
function formatLogEntry(entry) {
|
|
84
|
-
if (typeof entry === "string")
|
|
85
|
-
return entry;
|
|
86
|
-
if (entry !== null && typeof entry === "object") {
|
|
87
|
-
const e = entry;
|
|
88
|
-
const parts = [e.ts, e.level, e.msg ?? e.message].filter((p) => typeof p === "string" || typeof p === "number");
|
|
89
|
-
if (parts.length > 0)
|
|
90
|
-
return parts.map(String).join(" ");
|
|
91
|
-
}
|
|
92
|
-
return String(entry);
|
|
93
|
-
}
|
|
94
|
-
/** Format the executor log buffer into a trimmed, tail-preserving slice, or
|
|
95
|
-
* `undefined` when there are no usable logs. */
|
|
96
|
-
function toLogSlice(logs) {
|
|
97
|
-
if (!Array.isArray(logs) || logs.length === 0)
|
|
98
|
-
return undefined;
|
|
99
|
-
const text = logs.map(formatLogEntry).join("\n").trim();
|
|
100
|
-
if (text === "")
|
|
101
|
-
return undefined;
|
|
102
|
-
return text.length > LOG_SLICE_MAX
|
|
103
|
-
? text.slice(text.length - LOG_SLICE_MAX)
|
|
104
|
-
: text;
|
|
105
|
-
}
|
|
106
70
|
/** Map one projection step to its render view. Optional fields are assigned only
|
|
107
71
|
* when present so absence stays absent (not `undefined`) in the JSON payload. */
|
|
108
72
|
function toStepView(step) {
|
|
@@ -111,9 +75,6 @@ function toStepView(step) {
|
|
|
111
75
|
name: step.stepName,
|
|
112
76
|
status: toStepStatus(step.status),
|
|
113
77
|
};
|
|
114
|
-
const costUsd = toCostUsd(step.cost);
|
|
115
|
-
if (costUsd !== undefined)
|
|
116
|
-
view.costUsd = costUsd;
|
|
117
78
|
const latencyMs = toLatencyMs(step.startedAt, step.finishedAt);
|
|
118
79
|
if (latencyMs !== undefined)
|
|
119
80
|
view.latencyMs = latencyMs;
|
|
@@ -122,6 +83,26 @@ function toStepView(step) {
|
|
|
122
83
|
const logSlice = toLogSlice(step.logs);
|
|
123
84
|
if (logSlice !== undefined)
|
|
124
85
|
view.logSlice = logSlice;
|
|
86
|
+
// Real per-step IO for the inspector's "Last run" block. The decoder
|
|
87
|
+
// collapses an absent input/output to `null` (its absence sentinel), so a
|
|
88
|
+
// `null` here means "the read carried nothing" — surfaced as ABSENT, never a
|
|
89
|
+
// fabricated payload. Any non-null value (including `0`, `false`, `""`) is a
|
|
90
|
+
// real payload and passes through. Capability, not model: these are the
|
|
91
|
+
// step's own values, with no provider/model surfaced.
|
|
92
|
+
if (step.input !== null)
|
|
93
|
+
view.input = step.input;
|
|
94
|
+
if (step.output !== null)
|
|
95
|
+
view.output = step.output;
|
|
96
|
+
// `step.events` are capability execution events forwarded by dispatched
|
|
97
|
+
// capabilities (e.g. tool_use / thinking / result events from a coding run).
|
|
98
|
+
// They do NOT represent dotted workflow capability calls (search.webSearch,
|
|
99
|
+
// memory.append, etc.) with args/results in the StepCall format, so we
|
|
100
|
+
// cannot map them to StepView.calls without fabricating structure that isn't
|
|
101
|
+
// there. `calls` is left absent for prod steps. The inspector's
|
|
102
|
+
// input/output/logs already carry the step-level evidence for prod runs;
|
|
103
|
+
// per-call detail is a fast-follow that requires a server-side addition to
|
|
104
|
+
// the projection shape (emitting dotted-capability call records alongside
|
|
105
|
+
// their args/results at the step level).
|
|
125
106
|
return view;
|
|
126
107
|
}
|
|
127
108
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render-run-state.js","sourceRoot":"","sources":["../../src/core/render-run-state.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"render-run-state.js","sourceRoot":"","sources":["../../src/core/render-run-state.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The "portable continue" brief: a bounded markdown reconstruction of a prior
|
|
3
|
+
* session, rendered from the SessionRecord our own events already produce (see
|
|
4
|
+
* core/session-record.ts).
|
|
5
|
+
*
|
|
6
|
+
* Why this exists rather than a vendor resume: `claude --resume` / `codex
|
|
7
|
+
* resume` only work when that agent, on this machine, still holds that
|
|
8
|
+
* conversation. H1 (SAP-2057) made us stop pretending otherwise; this is the
|
|
9
|
+
* other half — for every row where the agent does NOT hold it, start a fresh
|
|
10
|
+
* session seeded with what we recorded. Because the input is our normalized
|
|
11
|
+
* record and the output is plain text, the same code path serves claude-code
|
|
12
|
+
* (`--append-system-prompt`) and codex (`developer_instructions`), and would
|
|
13
|
+
* serve a harness with no prompt flag at all via post-ready injection.
|
|
14
|
+
*
|
|
15
|
+
* HONESTY IS THE PRODUCT HERE. A brief that reads like restored memory is
|
|
16
|
+
* worse than no brief: the agent will assert a file's contents or a command's
|
|
17
|
+
* outcome it never saw. So the header says outright that this is a
|
|
18
|
+
* reconstruction, `record.limitations` are spelled out, and every omission
|
|
19
|
+
* (dropped turns, clamped text, capped file lists) is stated in the text
|
|
20
|
+
* rather than silently applied.
|
|
21
|
+
*
|
|
22
|
+
* BUDGET. The brief is capped at `maxTokens` (default
|
|
23
|
+
* {@link RESUME_BRIEF_DEFAULT_MAX_TOKENS}), estimated at
|
|
24
|
+
* {@link CHARS_PER_TOKEN} characters per token — deliberately a crude
|
|
25
|
+
* estimator, since the consumer is a system prompt with room to spare, not a
|
|
26
|
+
* hard API limit, and a tokenizer dependency here would have to be right for
|
|
27
|
+
* two different vendors' tokenizers anyway. What gets squeezed, in order:
|
|
28
|
+
*
|
|
29
|
+
* 1. turns, oldest-first — the newest are the ones that explain what is in
|
|
30
|
+
* flight right now, and an old turn is the most verbose thing here per
|
|
31
|
+
* unit of usefulness;
|
|
32
|
+
* 2. the derived digests (files written, commands run). They go AFTER turns,
|
|
33
|
+
* not before, because they are hard-capped ({@link MAX_FILES} /
|
|
34
|
+
* {@link MAX_COMMANDS}) at a few hundred tokens for a whole session,
|
|
35
|
+
* where each turn costs a comparable amount on its own — trading a
|
|
36
|
+
* whole-session view for one more ancient turn is a bad deal. They can
|
|
37
|
+
* also be recovered by looking at the repository, so this only bites
|
|
38
|
+
* once every turn is already gone;
|
|
39
|
+
* 3. only then the rolling summary, tail-clamped. It is squeezed last
|
|
40
|
+
* because it is the one section that is a lossy fold of turns already
|
|
41
|
+
* dropped in step 1: cutting it loses history nothing else carries.
|
|
42
|
+
*
|
|
43
|
+
* The honesty header and the identity block are never dropped — a brief
|
|
44
|
+
* without them is a lie, not a shorter brief — so they act as a floor of
|
|
45
|
+
* roughly {@link RESUME_BRIEF_MIN_TOKENS} tokens that a smaller `maxTokens`
|
|
46
|
+
* cannot squeeze below.
|
|
47
|
+
*/
|
|
48
|
+
import type { SessionRecord, SessionRecordToolCall } from "../shared/types.js";
|
|
49
|
+
/** Default token ceiling for a brief — see the module header on the estimate. */
|
|
50
|
+
export declare const RESUME_BRIEF_DEFAULT_MAX_TOKENS = 6000;
|
|
51
|
+
/** Turns considered before budgeting; the budget may keep fewer, never more. */
|
|
52
|
+
export declare const RESUME_BRIEF_DEFAULT_MAX_TURNS = 12;
|
|
53
|
+
/**
|
|
54
|
+
* Characters per token. Roughly right for English prose and code across both
|
|
55
|
+
* vendors' tokenizers, and biased the safe way: real text averages slightly
|
|
56
|
+
* more than 4 chars/token, so this over-counts and lands under the ceiling.
|
|
57
|
+
*/
|
|
58
|
+
export declare const CHARS_PER_TOKEN = 4;
|
|
59
|
+
/**
|
|
60
|
+
* Floor the budget can never squeeze below — the honesty header plus the
|
|
61
|
+
* identity block. Approximate (it moves with the header's wording); it exists
|
|
62
|
+
* so callers can reason about "what does maxTokens: 200 even mean" rather than
|
|
63
|
+
* as an assertion about exact size.
|
|
64
|
+
*/
|
|
65
|
+
export declare const RESUME_BRIEF_MIN_TOKENS = 400;
|
|
66
|
+
/** The workflow the prior session was bound to, resolved by the caller against
|
|
67
|
+
* the live workflow registry (the record itself has no binding). */
|
|
68
|
+
export interface ResumeBriefWorkflow {
|
|
69
|
+
name: string;
|
|
70
|
+
path: string;
|
|
71
|
+
definitionId: number | null;
|
|
72
|
+
}
|
|
73
|
+
export interface BuildResumeBriefOptions {
|
|
74
|
+
/** Display title of the prior session, when a history row knew one. */
|
|
75
|
+
title?: string | null;
|
|
76
|
+
/** Git branch the prior session was last on, when a history row knew one. */
|
|
77
|
+
gitBranch?: string | null;
|
|
78
|
+
/** The prior session's bound workflow. */
|
|
79
|
+
workflow?: ResumeBriefWorkflow | null;
|
|
80
|
+
/**
|
|
81
|
+
* The rolling summary (`<generated>/<sessionId>/summary.md`) when one was
|
|
82
|
+
* ever produced. Absent, the brief degrades to the last N turns — which is
|
|
83
|
+
* the normal case, since the summary is opt-in (see core/rolling-summary.ts).
|
|
84
|
+
*/
|
|
85
|
+
summary?: string | null;
|
|
86
|
+
/** Token ceiling. Default {@link RESUME_BRIEF_DEFAULT_MAX_TOKENS}. */
|
|
87
|
+
maxTokens?: number;
|
|
88
|
+
/** Newest turns considered. Default {@link RESUME_BRIEF_DEFAULT_MAX_TURNS}. */
|
|
89
|
+
maxTurns?: number;
|
|
90
|
+
}
|
|
91
|
+
/** The crude char-count estimate the budget is enforced against. */
|
|
92
|
+
export declare function estimateBriefTokens(text: string): number;
|
|
93
|
+
/**
|
|
94
|
+
* The tool's target as a human would name it: the file it edited, the command
|
|
95
|
+
* it ran, or — failing both — a clamped slice of the raw input.
|
|
96
|
+
*
|
|
97
|
+
* `toolInput` is a string on the wire for both harnesses: claude-code's
|
|
98
|
+
* normalizer stores `JSON.stringify(tool_input)` and codex's tailer stores the
|
|
99
|
+
* function call's raw `arguments`, so a JSON parse covers both and a plain
|
|
100
|
+
* string (an untruncated free-text argument) falls through to the raw slice.
|
|
101
|
+
* Never throws on malformed input — a brief must render from whatever was
|
|
102
|
+
* recorded, including a payload the collector truncated mid-JSON.
|
|
103
|
+
*/
|
|
104
|
+
export declare function describeToolTarget(call: SessionRecordToolCall, cwd: string | null): string | null;
|
|
105
|
+
interface DerivedDigests {
|
|
106
|
+
/** Files written, most-recently-touched first, with their touch counts. */
|
|
107
|
+
files: Array<{
|
|
108
|
+
display: string;
|
|
109
|
+
count: number;
|
|
110
|
+
}>;
|
|
111
|
+
/** Total distinct files, which may exceed `files.length` after the cap. */
|
|
112
|
+
totalFiles: number;
|
|
113
|
+
/** Distinct shell commands, most recent first. */
|
|
114
|
+
commands: string[];
|
|
115
|
+
totalCommands: number;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Files touched and commands run, derived from `tool.call` inputs. Exported
|
|
119
|
+
* for tests and because the same derivation is worth reusing anywhere that
|
|
120
|
+
* needs "what did this session actually do to the tree".
|
|
121
|
+
*/
|
|
122
|
+
export declare function deriveDigests(record: SessionRecord): DerivedDigests;
|
|
123
|
+
/**
|
|
124
|
+
* Render a bounded brief for `record`. Pure and synchronous; the caller
|
|
125
|
+
* supplies the rolling summary and any registry-only context (title, branch,
|
|
126
|
+
* bound workflow) it can resolve.
|
|
127
|
+
*/
|
|
128
|
+
export declare function buildResumeBrief(record: SessionRecord, options?: BuildResumeBriefOptions): string;
|
|
129
|
+
export {};
|
|
130
|
+
//# sourceMappingURL=resume-brief.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resume-brief.d.ts","sourceRoot":"","sources":["../../src/core/resume-brief.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AAIH,OAAO,KAAK,EACV,aAAa,EAEb,qBAAqB,EAEtB,MAAM,oBAAoB,CAAC;AAE5B,iFAAiF;AACjF,eAAO,MAAM,+BAA+B,OAAQ,CAAC;AACrD,gFAAgF;AAChF,eAAO,MAAM,8BAA8B,KAAK,CAAC;AACjD;;;;GAIG;AACH,eAAO,MAAM,eAAe,IAAI,CAAC;AACjC;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAiB3C;qEACqE;AACrE,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,MAAM,WAAW,uBAAuB;IACtC,uEAAuE;IACvE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,6EAA6E;IAC7E,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,mBAAmB,GAAG,IAAI,CAAC;IACtC;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,sEAAsE;IACtE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,oEAAoE;AACpE,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAExD;AAUD;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,qBAAqB,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAYjG;AAyDD,UAAU,cAAc;IACtB,2EAA2E;IAC3E,KAAK,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACjD,2EAA2E;IAC3E,UAAU,EAAE,MAAM,CAAC;IACnB,kDAAkD;IAClD,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,aAAa,GAAG,cAAc,CAoCnE;AA0ED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,aAAa,EACrB,OAAO,GAAE,uBAA4B,GACpC,MAAM,CAyER"}
|