@inflexa-ai/harness 0.20.0 → 0.21.1
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/dist/agents/conversation-agent.d.ts +26 -14
- package/dist/agents/conversation-agent.js +12 -23
- package/dist/agents/report-session-agent.d.ts +31 -5
- package/dist/agents/report-session-agent.js +35 -9
- package/dist/app/chat-turn.js +3 -1
- package/dist/app/message-assembly.d.ts +15 -1
- package/dist/app/message-assembly.js +22 -8
- package/dist/app/report-session-runtime.d.ts +21 -4
- package/dist/app/report-session-runtime.js +53 -6
- package/dist/app/spawn-report-session.d.ts +174 -17
- package/dist/app/spawn-report-session.js +233 -21
- package/dist/contracts/chat-events.d.ts +7 -2
- package/dist/contracts/message.d.ts +10 -0
- package/dist/contracts/report-blocks.d.ts +743 -19
- package/dist/contracts/report-blocks.js +186 -11
- package/dist/contracts/report-reference.d.ts +88 -0
- package/dist/contracts/report-reference.js +48 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +20 -0
- package/dist/lib/chrome.d.ts +26 -6
- package/dist/lib/chrome.js +99 -32
- package/dist/lib/eyes.d.ts +57 -0
- package/dist/lib/eyes.js +45 -0
- package/dist/lib/page-capture.d.ts +14 -0
- package/dist/lib/page-capture.js +56 -2
- package/dist/loop/run-agent.js +58 -23
- package/dist/loop/tool-detail.d.ts +19 -2
- package/dist/loop/tool-detail.js +35 -2
- package/dist/memory/content-to-cortex.d.ts +3 -2
- package/dist/memory/content-to-cortex.js +21 -12
- package/dist/memory/conversation-display-replay.js +14 -7
- package/dist/memory/thread-history.d.ts +60 -3
- package/dist/memory/thread-history.js +55 -16
- package/dist/memory/thread-store.d.ts +11 -1
- package/dist/memory/thread-store.js +12 -2
- package/dist/prompts/conversation.d.ts +1 -1
- package/dist/prompts/conversation.js +23 -6
- package/dist/prompts/report-session.d.ts +1 -1
- package/dist/prompts/report-session.js +190 -9
- package/dist/report-model/authoring-grammar.d.ts +463 -0
- package/dist/report-model/authoring-grammar.js +77 -0
- package/dist/report-model/block-walk.d.ts +57 -14
- package/dist/report-model/block-walk.js +116 -11
- package/dist/report-model/draft-finish.d.ts +22 -4
- package/dist/report-model/draft-finish.js +39 -7
- package/dist/report-model/draft-operations.d.ts +3 -0
- package/dist/report-model/draft-operations.js +19 -5
- package/dist/report-model/draft-read.d.ts +8 -5
- package/dist/report-model/draft-read.js +21 -5
- package/dist/report-model/fixture-resolver.js +15 -4
- package/dist/report-model/pin-snapshot.d.ts +24 -6
- package/dist/report-model/pin-snapshot.js +204 -6
- package/dist/report-model/production-resolver.js +15 -4
- package/dist/report-model/reference-resolver.d.ts +50 -1
- package/dist/report-model/reference-resolver.js +94 -1
- package/dist/report-model/reference-stamp.d.ts +45 -0
- package/dist/report-model/reference-stamp.js +173 -0
- package/dist/report-model/structural-validation.d.ts +4 -1
- package/dist/report-model/structural-validation.js +48 -3
- package/dist/report-model/validate.d.ts +1 -1
- package/dist/report-model/validate.js +1 -1
- package/dist/report-render/asset-lookup.d.ts +19 -0
- package/dist/report-render/asset-lookup.js +37 -0
- package/dist/report-render/assets.d.ts +45 -1
- package/dist/report-render/assets.js +65 -6
- package/dist/report-render/chart-presets.d.ts +102 -0
- package/dist/report-render/chart-presets.js +205 -0
- package/dist/report-render/chart.d.ts +112 -10
- package/dist/report-render/chart.js +1164 -41
- package/dist/report-render/design.d.ts +99 -0
- package/dist/report-render/design.js +289 -107
- package/dist/report-render/number-format.d.ts +117 -0
- package/dist/report-render/number-format.js +479 -0
- package/dist/report-render/page.d.ts +121 -5
- package/dist/report-render/page.js +689 -7
- package/dist/report-render/references.d.ts +70 -16
- package/dist/report-render/references.js +54 -22
- package/dist/report-render/render.d.ts +23 -5
- package/dist/report-render/render.js +81 -22
- package/dist/report-render/table-data.d.ts +92 -0
- package/dist/report-render/table-data.js +129 -0
- package/dist/report-render/types.d.ts +15 -0
- package/dist/report-render/value-bridge.js +6 -2
- package/dist/report-render/views/chart-view.d.ts +12 -5
- package/dist/report-render/views/chart-view.js +14 -8
- package/dist/report-render/views/page-view.d.ts +36 -15
- package/dist/report-render/views/page-view.js +45 -23
- package/dist/report-render/views/prose.d.ts +12 -2
- package/dist/report-render/views/prose.js +29 -7
- package/dist/report-render/views/references-view.d.ts +22 -8
- package/dist/report-render/views/references-view.js +101 -13
- package/dist/report-render/views/values.d.ts +128 -13
- package/dist/report-render/views/values.js +199 -18
- package/dist/runtime/assemble.d.ts +39 -5
- package/dist/runtime/assemble.js +47 -6
- package/dist/sandbox/client.d.ts +10 -1
- package/dist/sandbox/create-sandbox.d.ts +9 -4
- package/dist/sandbox/create-sandbox.js +22 -16
- package/dist/sandbox/docker-client.js +10 -7
- package/dist/sandbox/mount-plan.d.ts +45 -7
- package/dist/sandbox/mount-plan.js +43 -5
- package/dist/sandbox/types.d.ts +6 -0
- package/dist/state/init.js +38 -9
- package/dist/state/report-session-state.d.ts +42 -1
- package/dist/state/report-session-state.js +70 -2
- package/dist/state/report-versions.d.ts +22 -17
- package/dist/state/report-versions.js +48 -35
- package/dist/state/snapshot-parse.js +16 -1
- package/dist/tools/define-tool.d.ts +32 -0
- package/dist/tools/define-tool.js +4 -0
- package/dist/tools/detail-resolver.d.ts +7 -2
- package/dist/tools/detail-resolver.js +7 -2
- package/dist/tools/iterate-report.d.ts +1 -1
- package/dist/tools/report/preview-snapshot.js +1 -0
- package/dist/tools/report-authoring/authoring-tools.d.ts +15 -6
- package/dist/tools/report-authoring/authoring-tools.js +99 -18
- package/dist/tools/report-session/derive-table.d.ts +162 -0
- package/dist/tools/report-session/derive-table.js +459 -0
- package/dist/tools/report-session/examine-page.d.ts +48 -18
- package/dist/tools/report-session/examine-page.js +204 -24
- package/dist/tools/report-session/index.d.ts +2 -0
- package/dist/tools/report-session/index.js +2 -0
- package/dist/tools/report-session/list-artifacts.d.ts +97 -0
- package/dist/tools/report-session/list-artifacts.js +197 -0
- package/dist/tools/report-session/preview-report.d.ts +6 -0
- package/dist/tools/report-session/preview-report.js +180 -28
- package/dist/tools/report-session/record-version.d.ts +22 -10
- package/dist/tools/report-session/record-version.js +99 -14
- package/dist/tools/start-report-session.d.ts +115 -0
- package/dist/tools/start-report-session.js +179 -0
- package/dist/workspace/paths.d.ts +50 -0
- package/dist/workspace/paths.js +63 -0
- package/package.json +2 -1
|
@@ -1,16 +1,57 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The value markup: the metric card, the data table, the figure, and the
|
|
2
|
+
* The value markup: the metric card, the data table, the figure, and the citation card.
|
|
3
|
+
*
|
|
4
|
+
* The citation card is the bibliography entry of its source. It carries the one link of the page body,
|
|
5
|
+
* which is a navigation to PubMed, thus the page loads nothing from a remote host.
|
|
3
6
|
*
|
|
4
7
|
* The caller resolves each value, and it narrows the value to the shape that the block needs. The runtime
|
|
5
8
|
* escapes every interpolated string, thus a hostile label, a hostile cell, a hostile caption, or a
|
|
6
|
-
* hostile source reaches the page as text.
|
|
9
|
+
* hostile source reaches the page as text. The `title` attribute takes the same escape as every other
|
|
10
|
+
* attribute value, thus the full digits cannot break out of their slot.
|
|
11
|
+
*
|
|
12
|
+
* A number reaches the page through the number format. A table cell takes the meaning that the binding
|
|
13
|
+
* declares for its column, and the column name answers for a column that declares none. A metric takes its
|
|
14
|
+
* label, because a value locator declares no column-wide meaning.
|
|
15
|
+
*
|
|
16
|
+
* A table card carries the grid mount and the download of the raw pinned bytes. The rows and the display of
|
|
17
|
+
* each column ride a data asset beside the page, and the page script builds the grid over them. Thus the
|
|
18
|
+
* markup carries no row, and `tableDisplay` gives the page what the server resolved for each column.
|
|
19
|
+
*
|
|
20
|
+
* Each card marks its binding in the shared ledger, thus every evidentiary block carries a marker and an
|
|
21
|
+
* appendix entry. A reference that two blocks share keeps one number and one entry.
|
|
7
22
|
*
|
|
8
23
|
* Each data card carries the `corner-accents` class. Thus the card keeps square corners with the L-shaped
|
|
9
24
|
* accents, which is the geometric identity of the report.
|
|
10
25
|
*/
|
|
11
26
|
import type { CitationBlock, FigureBlock, MetricBlock, TableBlock } from "../../contracts/report-blocks.js";
|
|
12
|
-
import type
|
|
27
|
+
import { type ArtifactTableReference } from "../../contracts/report-reference.js";
|
|
28
|
+
import type { CitationRecord } from "../../report-model/reference-resolver.js";
|
|
29
|
+
import { type ReferenceLedger } from "../references.js";
|
|
30
|
+
import type { ColumnDisplay } from "../table-data.js";
|
|
13
31
|
import type { RenderValue } from "../types.js";
|
|
32
|
+
/**
|
|
33
|
+
* The attribute that marks the grid mount of a table card, and that names the block of its data.
|
|
34
|
+
*
|
|
35
|
+
* The page script reads the same attribute, thus the card and the boot cannot disagree over a rename.
|
|
36
|
+
*/
|
|
37
|
+
export declare const GRID_MOUNT_ATTRIBUTE = "data-report-grid";
|
|
38
|
+
/**
|
|
39
|
+
* The class of the print note of a table card.
|
|
40
|
+
*
|
|
41
|
+
* The note is empty on the screen. The page script writes the bound of a truncated print form into it at
|
|
42
|
+
* print time, and it clears the text after. The page script reads the same class, thus the card and the
|
|
43
|
+
* boot cannot disagree over a rename.
|
|
44
|
+
*/
|
|
45
|
+
export declare const GRID_NOTE_CLASS = "report-grid-note";
|
|
46
|
+
/**
|
|
47
|
+
* The class of the row count of a table card.
|
|
48
|
+
*
|
|
49
|
+
* The renderer writes the count of the resolved rows, and the page script writes it again after each filter.
|
|
50
|
+
* The page script reads the same class, thus the card and the boot cannot disagree over a rename.
|
|
51
|
+
*/
|
|
52
|
+
export declare const GRID_COUNT_CLASS = "report-table-count";
|
|
53
|
+
/** The word that follows a row count, in the status line of the card and in the print note alike. */
|
|
54
|
+
export declare const GRID_ROWS_WORD = "rows";
|
|
14
55
|
/** The scalar value that a metric renders from. */
|
|
15
56
|
type ScalarValue = Extract<RenderValue, {
|
|
16
57
|
type: "scalar";
|
|
@@ -23,8 +64,20 @@ type TableValue = Extract<RenderValue, {
|
|
|
23
64
|
type FigureValue = Extract<RenderValue, {
|
|
24
65
|
type: "figure";
|
|
25
66
|
}>;
|
|
26
|
-
/**
|
|
27
|
-
|
|
67
|
+
/**
|
|
68
|
+
* Render a metric block as a stat card with the mono value and the mono label.
|
|
69
|
+
*
|
|
70
|
+
* The label names the value, thus it selects the number kind. The full digits ride the `title` attribute
|
|
71
|
+
* when the shown form hides one, and no attribute appears at any other time.
|
|
72
|
+
*
|
|
73
|
+
* A metric reads one cell and it has no column, thus no neighbor bounds a zero here. A zero under a
|
|
74
|
+
* p-value label reads as the near-zero form.
|
|
75
|
+
*
|
|
76
|
+
* The value binding joins the reference ladder, thus the label line carries the marker and the appendix
|
|
77
|
+
* names the cell. The marker sits on the label and never on the value, because the value line is the one
|
|
78
|
+
* figure that a reader takes from the card.
|
|
79
|
+
*/
|
|
80
|
+
export declare function renderMetric(block: MetricBlock, ledger: ReferenceLedger, value: ScalarValue): string;
|
|
28
81
|
/**
|
|
29
82
|
* Wrap a run of stat cards in one responsive grid. The caller renders each card first, and it passes the
|
|
30
83
|
* markup as one already-escaped string, thus `raw()` inserts it byte for byte. The grid carries its own
|
|
@@ -32,20 +85,82 @@ export declare function renderMetric(block: MetricBlock, value: ScalarValue): st
|
|
|
32
85
|
*/
|
|
33
86
|
export declare function renderMetricGrid(cardsHtml: string): string;
|
|
34
87
|
/**
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
88
|
+
* The column order of a table. The value columns win when they are present. The keys of the first row
|
|
89
|
+
* give the order otherwise, in first-appearance order.
|
|
90
|
+
*
|
|
91
|
+
* The header of the card and the payload of the data asset both read this order. Thus the position of a
|
|
92
|
+
* cell in an encoded row names the column of its header.
|
|
93
|
+
*/
|
|
94
|
+
export declare function tableColumns(value: TableValue): string[];
|
|
95
|
+
/**
|
|
96
|
+
* The display of each column of a table, in the column order of the header.
|
|
97
|
+
*
|
|
98
|
+
* The renderer resolves the label, the number kind, the filter, and the bound of a stored zero one time for
|
|
99
|
+
* each column, and the data asset ships them. Thus the page formats a cell with no read of a declaration
|
|
100
|
+
* and no second pass over a column.
|
|
101
|
+
*
|
|
102
|
+
* The argument is the binding and not the block, because a chart binds the same whole-table reference. A
|
|
103
|
+
* chart that reads the shared payload then resolves its columns through this one helper.
|
|
104
|
+
*
|
|
105
|
+
* The filter reads the cells and not the kind. A column of gene names carries no number, thus it takes the
|
|
106
|
+
* text filter and a reader finds a gene by its name. A column where one cell parses takes the number filter.
|
|
107
|
+
*
|
|
108
|
+
* A probability column carries the smallest positive value of its own rows as the bound. A column with no
|
|
109
|
+
* positive value takes no bound, and its zero then reads as the near-zero form.
|
|
110
|
+
*/
|
|
111
|
+
export declare function tableDisplay(binding: ArtifactTableReference, value: TableValue, columns: readonly string[]): ColumnDisplay[];
|
|
112
|
+
/**
|
|
113
|
+
* The status of a table card: the shown count against the pre-bound total of the artifact.
|
|
114
|
+
*
|
|
115
|
+
* A bound cut the rows, thus the shown count and the total differ and the line names both. A whole table
|
|
116
|
+
* shows every row that it holds, thus the line states the one count. The page script writes the same two
|
|
117
|
+
* forms after each filter, thus the first paint and every later one read alike.
|
|
38
118
|
*/
|
|
39
|
-
export declare function
|
|
119
|
+
export declare function tableStatusText(shown: number, total: number): string;
|
|
120
|
+
/**
|
|
121
|
+
* Render a table block as the grid mount and the download of its raw bytes.
|
|
122
|
+
*
|
|
123
|
+
* The rows ride a data asset beside the page. A page that stamped 14,201 rows into its markup weighed
|
|
124
|
+
* megabytes, and each row was a copy of the column names. Thus the markup holds one empty mount, and the
|
|
125
|
+
* page script builds the grid over the payload that registers under the block id.
|
|
126
|
+
*
|
|
127
|
+
* The mount names its block in the mount attribute. A mount whose block the registry does not hold stays
|
|
128
|
+
* empty, thus the card keeps its title, its status, and its download, and the page throws nothing.
|
|
129
|
+
*
|
|
130
|
+
* The footer holds one status line and the download button. The status states the count of the resolved
|
|
131
|
+
* rows against the pre-bound total of the artifact, and the row bound of the binding beside it. The page
|
|
132
|
+
* script writes the count again after each filter, thus a reader of a narrowed table sees what the grid
|
|
133
|
+
* shows and what the artifact holds.
|
|
134
|
+
*
|
|
135
|
+
* The note under the status stays empty on the screen. A print of a table that passes the print bound writes
|
|
136
|
+
* the bound into it, thus the paper states what it shows and what it leaves out.
|
|
137
|
+
*
|
|
138
|
+
* The download names the staged copy of the pinned artifact. The link is relative and the browser saves
|
|
139
|
+
* the file, thus the page fetches nothing when it opens and the reader still gets the whole table.
|
|
140
|
+
*
|
|
141
|
+
* The whole-table binding joins the reference ladder, thus the title line carries the marker and the
|
|
142
|
+
* appendix names the artifact. Every evidentiary block ledgers this way, and a card with no title still
|
|
143
|
+
* shows its marker on the same line.
|
|
144
|
+
*/
|
|
145
|
+
export declare function renderTable(block: TableBlock, ledger: ReferenceLedger, rowCount: number, total?: number): string;
|
|
40
146
|
/**
|
|
41
147
|
* Render a figure block as a corner-accent card. The source rides the `src` attribute, and the caption
|
|
42
148
|
* renders below the image. The caption also fills the `alt` attribute, thus the escape keeps a hostile
|
|
43
149
|
* source and a hostile caption inside their slots.
|
|
150
|
+
*
|
|
151
|
+
* The whole-file binding joins the reference ladder, thus the caption line carries the marker and the
|
|
152
|
+
* appendix names the image. A figure with no caption still shows its marker on that line. The marker stays
|
|
153
|
+
* out of the `alt` text, because a screen reader reads the alt as the picture and not as a footnote.
|
|
44
154
|
*/
|
|
45
|
-
export declare function renderFigure(block: FigureBlock, value: FigureValue): string;
|
|
155
|
+
export declare function renderFigure(block: FigureBlock, ledger: ReferenceLedger, value: FigureValue): string;
|
|
46
156
|
/**
|
|
47
|
-
* Render a citation block as a card
|
|
48
|
-
* binding, thus one shared source keeps one number. The
|
|
157
|
+
* Render a citation block as a bibliography card. The binding joins the one reference ladder like a claim
|
|
158
|
+
* binding, thus one shared source keeps one bracket number. The card shows the marker, the short citation
|
|
159
|
+
* of the pinned record, the optional note, and the citation key.
|
|
160
|
+
*
|
|
161
|
+
* The short citation of a `pmid:` record carries the PubMed link of its identifier. A key of another
|
|
162
|
+
* identifier space shows the citation as text. A key with no pinned record shows the key and the note
|
|
163
|
+
* alone, because absence is a normal condition and no text stands in for the paper.
|
|
49
164
|
*/
|
|
50
|
-
export declare function renderCitation(block: CitationBlock, ledger: ReferenceLedger): string;
|
|
165
|
+
export declare function renderCitation(block: CitationBlock, ledger: ReferenceLedger, record?: CitationRecord): string;
|
|
51
166
|
export {};
|
|
@@ -1,19 +1,77 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "hono/jsx/jsx-runtime";
|
|
2
2
|
/**
|
|
3
|
-
* The value markup: the metric card, the data table, the figure, and the
|
|
3
|
+
* The value markup: the metric card, the data table, the figure, and the citation card.
|
|
4
|
+
*
|
|
5
|
+
* The citation card is the bibliography entry of its source. It carries the one link of the page body,
|
|
6
|
+
* which is a navigation to PubMed, thus the page loads nothing from a remote host.
|
|
4
7
|
*
|
|
5
8
|
* The caller resolves each value, and it narrows the value to the shape that the block needs. The runtime
|
|
6
9
|
* escapes every interpolated string, thus a hostile label, a hostile cell, a hostile caption, or a
|
|
7
|
-
* hostile source reaches the page as text.
|
|
10
|
+
* hostile source reaches the page as text. The `title` attribute takes the same escape as every other
|
|
11
|
+
* attribute value, thus the full digits cannot break out of their slot.
|
|
12
|
+
*
|
|
13
|
+
* A number reaches the page through the number format. A table cell takes the meaning that the binding
|
|
14
|
+
* declares for its column, and the column name answers for a column that declares none. A metric takes its
|
|
15
|
+
* label, because a value locator declares no column-wide meaning.
|
|
16
|
+
*
|
|
17
|
+
* A table card carries the grid mount and the download of the raw pinned bytes. The rows and the display of
|
|
18
|
+
* each column ride a data asset beside the page, and the page script builds the grid over them. Thus the
|
|
19
|
+
* markup carries no row, and `tableDisplay` gives the page what the server resolved for each column.
|
|
20
|
+
*
|
|
21
|
+
* Each card marks its binding in the shared ledger, thus every evidentiary block carries a marker and an
|
|
22
|
+
* appendix entry. A reference that two blocks share keeps one number and one entry.
|
|
8
23
|
*
|
|
9
24
|
* Each data card carries the `corner-accents` class. Thus the card keeps square corners with the L-shaped
|
|
10
25
|
* accents, which is the geometric identity of the report.
|
|
11
26
|
*/
|
|
12
27
|
import { raw } from "hono/html";
|
|
28
|
+
import { declaredForColumn } from "../../contracts/report-reference.js";
|
|
29
|
+
import { stagedSource, tableSidecarName } from "../assets.js";
|
|
13
30
|
import { Marker } from "./references-view.js";
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
31
|
+
import { formatNumberCell, formatTableCell, holdsANumber, selectColumnKind, selectNumberKind, smallestPositiveValue } from "../number-format.js";
|
|
32
|
+
import { citationKeyOf } from "../references.js";
|
|
33
|
+
/**
|
|
34
|
+
* The attribute that marks the grid mount of a table card, and that names the block of its data.
|
|
35
|
+
*
|
|
36
|
+
* The page script reads the same attribute, thus the card and the boot cannot disagree over a rename.
|
|
37
|
+
*/
|
|
38
|
+
export const GRID_MOUNT_ATTRIBUTE = "data-report-grid";
|
|
39
|
+
/**
|
|
40
|
+
* The class of the print note of a table card.
|
|
41
|
+
*
|
|
42
|
+
* The note is empty on the screen. The page script writes the bound of a truncated print form into it at
|
|
43
|
+
* print time, and it clears the text after. The page script reads the same class, thus the card and the
|
|
44
|
+
* boot cannot disagree over a rename.
|
|
45
|
+
*/
|
|
46
|
+
export const GRID_NOTE_CLASS = "report-grid-note";
|
|
47
|
+
/**
|
|
48
|
+
* The class of the row count of a table card.
|
|
49
|
+
*
|
|
50
|
+
* The renderer writes the count of the resolved rows, and the page script writes it again after each filter.
|
|
51
|
+
* The page script reads the same class, thus the card and the boot cannot disagree over a rename.
|
|
52
|
+
*/
|
|
53
|
+
export const GRID_COUNT_CLASS = "report-table-count";
|
|
54
|
+
/** The word that follows a row count, in the status line of the card and in the print note alike. */
|
|
55
|
+
export const GRID_ROWS_WORD = "rows";
|
|
56
|
+
/** The label of the download button of a table card, without the format of the file. */
|
|
57
|
+
const DOWNLOAD_LABEL = "Download";
|
|
58
|
+
/**
|
|
59
|
+
* Render a metric block as a stat card with the mono value and the mono label.
|
|
60
|
+
*
|
|
61
|
+
* The label names the value, thus it selects the number kind. The full digits ride the `title` attribute
|
|
62
|
+
* when the shown form hides one, and no attribute appears at any other time.
|
|
63
|
+
*
|
|
64
|
+
* A metric reads one cell and it has no column, thus no neighbor bounds a zero here. A zero under a
|
|
65
|
+
* p-value label reads as the near-zero form.
|
|
66
|
+
*
|
|
67
|
+
* The value binding joins the reference ladder, thus the label line carries the marker and the appendix
|
|
68
|
+
* names the cell. The marker sits on the label and never on the value, because the value line is the one
|
|
69
|
+
* figure that a reader takes from the card.
|
|
70
|
+
*/
|
|
71
|
+
export function renderMetric(block, ledger, value) {
|
|
72
|
+
const n = ledger.mark(block.value);
|
|
73
|
+
const shown = formatNumberCell(value.value, selectNumberKind(block.label, value.value));
|
|
74
|
+
return String(_jsxs("div", { class: "stat-card corner-accents", children: [_jsx("div", { class: "stat-card-value", title: shown.full, children: shown.text }), _jsxs("div", { class: "stat-card-label", children: [block.label, _jsx(Marker, { n: n })] })] }));
|
|
17
75
|
}
|
|
18
76
|
/**
|
|
19
77
|
* Wrap a run of stat cards in one responsive grid. The caller renders each card first, and it passes the
|
|
@@ -26,8 +84,11 @@ export function renderMetricGrid(cardsHtml) {
|
|
|
26
84
|
/**
|
|
27
85
|
* The column order of a table. The value columns win when they are present. The keys of the first row
|
|
28
86
|
* give the order otherwise, in first-appearance order.
|
|
87
|
+
*
|
|
88
|
+
* The header of the card and the payload of the data asset both read this order. Thus the position of a
|
|
89
|
+
* cell in an encoded row names the column of its header.
|
|
29
90
|
*/
|
|
30
|
-
function tableColumns(value) {
|
|
91
|
+
export function tableColumns(value) {
|
|
31
92
|
if (value.columns !== undefined) {
|
|
32
93
|
return value.columns;
|
|
33
94
|
}
|
|
@@ -35,28 +96,148 @@ function tableColumns(value) {
|
|
|
35
96
|
return first !== undefined ? Object.keys(first) : [];
|
|
36
97
|
}
|
|
37
98
|
/**
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
99
|
+
* The header label of one column.
|
|
100
|
+
*
|
|
101
|
+
* A declared label names what the column measures. A column with no label prettifies, thus an underscore
|
|
102
|
+
* reads as a space. The page compares the label against the raw name, and it puts the raw name on the
|
|
103
|
+
* header hover where the two differ.
|
|
104
|
+
*/
|
|
105
|
+
function columnLabel(column, labels) {
|
|
106
|
+
return declaredForColumn(labels, column) ?? column.replaceAll("_", " ");
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* The display of each column of a table, in the column order of the header.
|
|
110
|
+
*
|
|
111
|
+
* The renderer resolves the label, the number kind, the filter, and the bound of a stored zero one time for
|
|
112
|
+
* each column, and the data asset ships them. Thus the page formats a cell with no read of a declaration
|
|
113
|
+
* and no second pass over a column.
|
|
114
|
+
*
|
|
115
|
+
* The argument is the binding and not the block, because a chart binds the same whole-table reference. A
|
|
116
|
+
* chart that reads the shared payload then resolves its columns through this one helper.
|
|
117
|
+
*
|
|
118
|
+
* The filter reads the cells and not the kind. A column of gene names carries no number, thus it takes the
|
|
119
|
+
* text filter and a reader finds a gene by its name. A column where one cell parses takes the number filter.
|
|
120
|
+
*
|
|
121
|
+
* A probability column carries the smallest positive value of its own rows as the bound. A column with no
|
|
122
|
+
* positive value takes no bound, and its zero then reads as the near-zero form.
|
|
123
|
+
*/
|
|
124
|
+
export function tableDisplay(binding, value, columns) {
|
|
125
|
+
return columns.map((column) => {
|
|
126
|
+
// One pass over the column serves the filter and the bound alike, thus a wide table reads no column
|
|
127
|
+
// twice.
|
|
128
|
+
const cells = value.rows.map((row) => row[column]);
|
|
129
|
+
const kind = selectColumnKind(column, declaredForColumn(binding.columnMeanings, column));
|
|
130
|
+
const label = columnLabel(column, binding.columnLabels);
|
|
131
|
+
const filter = holdsANumber(cells) ? "number" : "text";
|
|
132
|
+
if (kind !== "scientific") {
|
|
133
|
+
return { label, kind, filter };
|
|
134
|
+
}
|
|
135
|
+
const bound = smallestPositiveValue(cells);
|
|
136
|
+
return bound === undefined ? { label, kind, filter } : { label, kind, filter, bound };
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* The label of the download button: the word and the format of the pinned file, for example `Download CSV`.
|
|
141
|
+
*
|
|
142
|
+
* The extension of the path names the format, thus the label states what the reader gets. A path with no
|
|
143
|
+
* extension gives the word alone, because a made-up format would be a claim about bytes that nobody read.
|
|
144
|
+
*/
|
|
145
|
+
function downloadLabel(path) {
|
|
146
|
+
const base = path.slice(path.lastIndexOf("/") + 1);
|
|
147
|
+
const dot = base.lastIndexOf(".");
|
|
148
|
+
const format = dot > 0 ? base.slice(dot + 1).toUpperCase() : "";
|
|
149
|
+
return format === "" ? DOWNLOAD_LABEL : `${DOWNLOAD_LABEL} ${format}`;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* The row bound of a binding as text, for example `top 20 by padj`, or `undefined` where the binding carries
|
|
153
|
+
* none.
|
|
154
|
+
*
|
|
155
|
+
* The bound is what the resolution kept, thus the status line states it beside the count and a reader never
|
|
156
|
+
* reads a cut table as the whole artifact. The rank direction names the end that the bound kept.
|
|
41
157
|
*/
|
|
42
|
-
|
|
43
|
-
const
|
|
44
|
-
|
|
158
|
+
function boundText(binding) {
|
|
159
|
+
const bound = binding.rowBound;
|
|
160
|
+
if (bound === undefined) {
|
|
161
|
+
return undefined;
|
|
162
|
+
}
|
|
163
|
+
const end = bound.order === "asc" ? "lowest" : "top";
|
|
164
|
+
const count = formatTableCell(bound.count, "compact-scientific");
|
|
165
|
+
return `${end} ${count} by ${columnLabel(bound.column, binding.columnLabels)}`;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* The status of a table card: the shown count against the pre-bound total of the artifact.
|
|
169
|
+
*
|
|
170
|
+
* A bound cut the rows, thus the shown count and the total differ and the line names both. A whole table
|
|
171
|
+
* shows every row that it holds, thus the line states the one count. The page script writes the same two
|
|
172
|
+
* forms after each filter, thus the first paint and every later one read alike.
|
|
173
|
+
*/
|
|
174
|
+
export function tableStatusText(shown, total) {
|
|
175
|
+
const whole = `${formatTableCell(total, "compact-scientific")} ${GRID_ROWS_WORD}`;
|
|
176
|
+
return shown === total ? whole : `${formatTableCell(shown, "compact-scientific")} of ${whole}`;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Render a table block as the grid mount and the download of its raw bytes.
|
|
180
|
+
*
|
|
181
|
+
* The rows ride a data asset beside the page. A page that stamped 14,201 rows into its markup weighed
|
|
182
|
+
* megabytes, and each row was a copy of the column names. Thus the markup holds one empty mount, and the
|
|
183
|
+
* page script builds the grid over the payload that registers under the block id.
|
|
184
|
+
*
|
|
185
|
+
* The mount names its block in the mount attribute. A mount whose block the registry does not hold stays
|
|
186
|
+
* empty, thus the card keeps its title, its status, and its download, and the page throws nothing.
|
|
187
|
+
*
|
|
188
|
+
* The footer holds one status line and the download button. The status states the count of the resolved
|
|
189
|
+
* rows against the pre-bound total of the artifact, and the row bound of the binding beside it. The page
|
|
190
|
+
* script writes the count again after each filter, thus a reader of a narrowed table sees what the grid
|
|
191
|
+
* shows and what the artifact holds.
|
|
192
|
+
*
|
|
193
|
+
* The note under the status stays empty on the screen. A print of a table that passes the print bound writes
|
|
194
|
+
* the bound into it, thus the paper states what it shows and what it leaves out.
|
|
195
|
+
*
|
|
196
|
+
* The download names the staged copy of the pinned artifact. The link is relative and the browser saves
|
|
197
|
+
* the file, thus the page fetches nothing when it opens and the reader still gets the whole table.
|
|
198
|
+
*
|
|
199
|
+
* The whole-table binding joins the reference ladder, thus the title line carries the marker and the
|
|
200
|
+
* appendix names the artifact. Every evidentiary block ledgers this way, and a card with no title still
|
|
201
|
+
* shows its marker on the same line.
|
|
202
|
+
*/
|
|
203
|
+
export function renderTable(block, ledger, rowCount, total) {
|
|
204
|
+
const binding = block.binding;
|
|
205
|
+
const n = ledger.mark(binding);
|
|
206
|
+
const download = tableSidecarName(binding.hash, binding.path);
|
|
207
|
+
const bound = boundText(binding);
|
|
208
|
+
return String(_jsxs("div", { class: "report-table", children: [_jsxs("div", { class: "report-table-title", children: [block.title, _jsx(Marker, { n: n })] }), _jsxs("div", { class: "corner-accents", children: [_jsx("div", { class: "report-grid", [GRID_MOUNT_ATTRIBUTE]: block.id }), _jsxs("div", { class: "report-table-footer", children: [_jsxs("div", { class: "report-table-footer-row", children: [_jsxs("span", { class: "report-table-status", children: [_jsx("span", { class: GRID_COUNT_CLASS, children: tableStatusText(rowCount, total ?? rowCount) }), bound !== undefined ? _jsx("span", { class: "report-table-bound", children: bound }) : null] }), _jsx("a", { class: "report-table-download", href: stagedSource(download), download: download, children: downloadLabel(binding.path) })] }), _jsx("div", { class: GRID_NOTE_CLASS })] })] }), block.caption !== undefined ? _jsx("p", { class: "report-caption", children: block.caption }) : null] }));
|
|
45
209
|
}
|
|
46
210
|
/**
|
|
47
211
|
* Render a figure block as a corner-accent card. The source rides the `src` attribute, and the caption
|
|
48
212
|
* renders below the image. The caption also fills the `alt` attribute, thus the escape keeps a hostile
|
|
49
213
|
* source and a hostile caption inside their slots.
|
|
214
|
+
*
|
|
215
|
+
* The whole-file binding joins the reference ladder, thus the caption line carries the marker and the
|
|
216
|
+
* appendix names the image. A figure with no caption still shows its marker on that line. The marker stays
|
|
217
|
+
* out of the `alt` text, because a screen reader reads the alt as the picture and not as a footnote.
|
|
50
218
|
*/
|
|
51
|
-
export function renderFigure(block, value) {
|
|
219
|
+
export function renderFigure(block, ledger, value) {
|
|
220
|
+
const n = ledger.mark(block.binding);
|
|
52
221
|
const caption = block.caption;
|
|
53
|
-
return String(_jsxs("figure", { class: "report-figure corner-accents", children: [_jsx("img", { src: value.src, alt: caption !== undefined ? caption : "", class: "report-figure-image" }),
|
|
222
|
+
return String(_jsxs("figure", { class: "report-figure corner-accents", children: [_jsx("img", { src: value.src, alt: caption !== undefined ? caption : "", class: "report-figure-image" }), _jsxs("figcaption", { class: "report-caption", children: [caption, _jsx(Marker, { n: n })] })] }));
|
|
54
223
|
}
|
|
55
224
|
/**
|
|
56
|
-
*
|
|
57
|
-
*
|
|
225
|
+
* The PubMed address of one identifier. The address is deterministic, and an anchor loads nothing, thus a
|
|
226
|
+
* page with such a link still stands alone.
|
|
227
|
+
*/
|
|
228
|
+
const PUBMED_BASE = "https://pubmed.ncbi.nlm.nih.gov/";
|
|
229
|
+
/**
|
|
230
|
+
* Render a citation block as a bibliography card. The binding joins the one reference ladder like a claim
|
|
231
|
+
* binding, thus one shared source keeps one bracket number. The card shows the marker, the short citation
|
|
232
|
+
* of the pinned record, the optional note, and the citation key.
|
|
233
|
+
*
|
|
234
|
+
* The short citation of a `pmid:` record carries the PubMed link of its identifier. A key of another
|
|
235
|
+
* identifier space shows the citation as text. A key with no pinned record shows the key and the note
|
|
236
|
+
* alone, because absence is a normal condition and no text stands in for the paper.
|
|
58
237
|
*/
|
|
59
|
-
export function renderCitation(block, ledger) {
|
|
238
|
+
export function renderCitation(block, ledger, record) {
|
|
60
239
|
const n = ledger.mark(block.binding);
|
|
61
|
-
|
|
240
|
+
const binding = block.binding;
|
|
241
|
+
const key = citationKeyOf(binding);
|
|
242
|
+
return String(_jsxs("div", { class: "report-citation corner-accents", children: [_jsx(Marker, { n: n }), record !== undefined ? (_jsxs(_Fragment, { children: [" ", binding.idKind === "pmid" ? (_jsx("a", { class: "report-citation-source", href: `${PUBMED_BASE}${encodeURIComponent(binding.id)}/`, children: record.citation })) : (_jsx("span", { class: "report-citation-source", children: record.citation }))] })) : null, block.note !== undefined ? (_jsxs(_Fragment, { children: [" ", _jsx("span", { class: "report-citation-note", children: block.note })] })) : null, " ", _jsx("span", { class: "report-citation-key", children: key })] }));
|
|
62
243
|
}
|
|
@@ -20,6 +20,8 @@ import { type ReportSessionRuntime } from "../app/report-session-runtime.js";
|
|
|
20
20
|
import type { UsageRecorder } from "../billing/usage-recorder.js";
|
|
21
21
|
import type { ResourcePolicy } from "../config/resource-limits.js";
|
|
22
22
|
import type { AgentDefinition } from "../loop/types.js";
|
|
23
|
+
import { type ChromeConfig } from "../lib/chrome.js";
|
|
24
|
+
import { type AcquireEyes } from "../lib/eyes.js";
|
|
23
25
|
import type { ThreadType } from "../memory/thread-store.js";
|
|
24
26
|
import { type ExecuteAnalysisDeps, type ExecuteAnalysisInput, type ExecuteAnalysisResult } from "../workflows/execute-analysis.js";
|
|
25
27
|
import { type SandboxStepDeps, type SandboxStepInput, type SandboxStepResult } from "../workflows/sandbox-step.js";
|
|
@@ -61,12 +63,22 @@ export interface RegisteredWorkflows {
|
|
|
61
63
|
readonly extractValues: (input: ExtractValuesWorkflowInput) => Promise<ExtractValuesResult>;
|
|
62
64
|
}
|
|
63
65
|
/**
|
|
64
|
-
* Conversation-agent deps minus the workflow callable, the resource policy,
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
66
|
+
* Conversation-agent deps minus the workflow callable, the resource policy, the
|
|
67
|
+
* usage recorder, the report-session anchor, and the eyes.
|
|
68
|
+
* `assembleCoreRuntime` supplies each of those itself. Thus a caller cannot wire
|
|
69
|
+
* one of these five values:
|
|
70
|
+
*
|
|
71
|
+
* - a stale callable
|
|
72
|
+
* - a policy that diverges from the one the workflows see
|
|
73
|
+
* - a recorder that only half the agent tree reports to
|
|
74
|
+
* - an anchor over a different session runtime
|
|
75
|
+
* - a seam that only half the agent tree looks through
|
|
76
|
+
*
|
|
77
|
+
* The assembly resolves the eyes one time, from `CoreRuntimeDeps.eyes` and the
|
|
78
|
+
* chrome config. A caller that bound the eyes here would give the conversation
|
|
79
|
+
* agent a seam that the report agent never sees.
|
|
68
80
|
*/
|
|
69
|
-
export type ConversationAssemblyDeps = Omit<ConversationAgentDeps, "executeAnalysisWorkflow" | "resourcePolicy" | "usageRecorder" | "citationResolver">;
|
|
81
|
+
export type ConversationAssemblyDeps = Omit<ConversationAgentDeps, "executeAnalysisWorkflow" | "resourcePolicy" | "usageRecorder" | "citationResolver" | "anchorReportSession" | "eyes">;
|
|
70
82
|
/**
|
|
71
83
|
* What binds one reference resolver: the analysis whose pinned artifacts it reads, and the auth of the tool
|
|
72
84
|
* call that reads them. A resolver serves one analysis, thus the report tools build one for each call.
|
|
@@ -120,6 +132,15 @@ export interface CoreRuntimeDeps {
|
|
|
120
132
|
* materializes them to disk and binds its own lookup here.
|
|
121
133
|
*/
|
|
122
134
|
readonly resolveReportPageAsset?: ResolvePageAsset;
|
|
135
|
+
/**
|
|
136
|
+
* The eyes of a report session — where a browser comes from for one look at the rendered
|
|
137
|
+
* page. A host with no standing sidecar starts a browser for one look. Thus it binds its own
|
|
138
|
+
* realization here, and the harness keeps every page behavior. Absent, the assembly wraps a
|
|
139
|
+
* chrome config that names a browser into the static realization. Thus a composition that
|
|
140
|
+
* names a standing sidecar changes nothing. A composition with neither route has no eyes, and
|
|
141
|
+
* the eyes tool of a report session then reports that condition.
|
|
142
|
+
*/
|
|
143
|
+
readonly eyes?: AcquireEyes;
|
|
123
144
|
}
|
|
124
145
|
/**
|
|
125
146
|
* The refusal a thread type carries no agent yet. `report` is a valid
|
|
@@ -172,4 +193,17 @@ export interface CoreRuntime {
|
|
|
172
193
|
readonly workflows: RegisteredWorkflows;
|
|
173
194
|
readonly citationResolver: CitationResolver;
|
|
174
195
|
}
|
|
196
|
+
/**
|
|
197
|
+
* The eyes of the composition, or none.
|
|
198
|
+
*
|
|
199
|
+
* A seam that the embedder bound answers first. Otherwise a chrome config that names a browser
|
|
200
|
+
* becomes the static realization. Thus a composition with a standing sidecar keeps its endpoint,
|
|
201
|
+
* and it changes nothing. A config that names no browser gives no eyes at all, and the eyes tool
|
|
202
|
+
* then gives the no-browser outcome.
|
|
203
|
+
*
|
|
204
|
+
* `createStaticEyes` refuses a config with no endpoint, thus the gate on the config runs before
|
|
205
|
+
* the construction. The resolution stays apart from `assembleCoreRuntime`, the same as the thread
|
|
206
|
+
* resolver above. Thus a test drives the precedence with no DBOS registration.
|
|
207
|
+
*/
|
|
208
|
+
export declare function resolveCompositionEyes(seam: AcquireEyes | undefined, chrome: ChromeConfig): AcquireEyes | undefined;
|
|
175
209
|
export declare function assembleCoreRuntime(deps: CoreRuntimeDeps): CoreRuntime;
|
package/dist/runtime/assemble.js
CHANGED
|
@@ -19,6 +19,8 @@ import { createConversationAgent } from "../agents/conversation-agent.js";
|
|
|
19
19
|
import { createReportSessionAgent } from "../agents/report-session-agent.js";
|
|
20
20
|
import { createReportSessionRuntime } from "../app/report-session-runtime.js";
|
|
21
21
|
import { createNoopUsageRecorder } from "../billing/noop-usage-recorder.js";
|
|
22
|
+
import { hasBrowserUrl } from "../lib/chrome.js";
|
|
23
|
+
import { createStaticEyes } from "../lib/eyes.js";
|
|
22
24
|
import { registerExecuteAnalysis } from "../workflows/execute-analysis.js";
|
|
23
25
|
import { registerSandboxStep } from "../workflows/sandbox-step.js";
|
|
24
26
|
import { registerExecuteTargetAssessment, } from "../workflows/execute-target-assessment.js";
|
|
@@ -52,6 +54,25 @@ export function createThreadAgentResolver(registry) {
|
|
|
52
54
|
},
|
|
53
55
|
};
|
|
54
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* The eyes of the composition, or none.
|
|
59
|
+
*
|
|
60
|
+
* A seam that the embedder bound answers first. Otherwise a chrome config that names a browser
|
|
61
|
+
* becomes the static realization. Thus a composition with a standing sidecar keeps its endpoint,
|
|
62
|
+
* and it changes nothing. A config that names no browser gives no eyes at all, and the eyes tool
|
|
63
|
+
* then gives the no-browser outcome.
|
|
64
|
+
*
|
|
65
|
+
* `createStaticEyes` refuses a config with no endpoint, thus the gate on the config runs before
|
|
66
|
+
* the construction. The resolution stays apart from `assembleCoreRuntime`, the same as the thread
|
|
67
|
+
* resolver above. Thus a test drives the precedence with no DBOS registration.
|
|
68
|
+
*/
|
|
69
|
+
export function resolveCompositionEyes(seam, chrome) {
|
|
70
|
+
if (seam !== undefined)
|
|
71
|
+
return seam;
|
|
72
|
+
if (hasBrowserUrl(chrome))
|
|
73
|
+
return createStaticEyes(chrome);
|
|
74
|
+
return undefined;
|
|
75
|
+
}
|
|
55
76
|
export function assembleCoreRuntime(deps) {
|
|
56
77
|
const { conversation, workflows: wf, resourcePolicy } = deps;
|
|
57
78
|
const usageRecorder = deps.usageRecorder ?? createNoopUsageRecorder();
|
|
@@ -74,19 +95,32 @@ export function assembleCoreRuntime(deps) {
|
|
|
74
95
|
runAuthorizer: wf.dataProfile.runAuthorizer,
|
|
75
96
|
...(wf.dataProfile.logger ? { logger: wf.dataProfile.logger } : {}),
|
|
76
97
|
});
|
|
98
|
+
// The session runtime binds the per-session state to the thread behind the
|
|
99
|
+
// tool boundary, thus one instance serves every report thread. It comes before
|
|
100
|
+
// the conversation agent, because `start_report_session` takes its anchor
|
|
101
|
+
// operation and pins the snapshot of a new session at the spawn.
|
|
102
|
+
// The runtime takes the same root resolver as the session tools, because the pin reads the citation
|
|
103
|
+
// evidence out of the run tree of the analysis.
|
|
104
|
+
const reportSession = createReportSessionRuntime({
|
|
105
|
+
pool: conversation.pool,
|
|
106
|
+
resolveWorkspaceRoot: conversation.resolveWorkspaceRoot,
|
|
107
|
+
...(conversation.logger ? { logger: conversation.logger } : {}),
|
|
108
|
+
});
|
|
109
|
+
// The eyes of the composition resolve one time here. Thus the agent that looks at a page and
|
|
110
|
+
// the tool that starts a session read one answer. No tool reads the precedence again.
|
|
111
|
+
const eyes = resolveCompositionEyes(deps.eyes, conversation.chrome);
|
|
77
112
|
const conversationAgent = createConversationAgent({
|
|
78
113
|
...conversation,
|
|
79
114
|
executeAnalysisWorkflow: executeAnalysis,
|
|
115
|
+
anchorReportSession: reportSession.ensureSessionState,
|
|
80
116
|
resourcePolicy,
|
|
81
117
|
usageRecorder,
|
|
82
118
|
citationResolver,
|
|
119
|
+
...(eyes ? { eyes } : {}),
|
|
83
120
|
});
|
|
84
|
-
// The report agent is a singleton over the conversation deps
|
|
85
|
-
// runtime
|
|
86
|
-
//
|
|
87
|
-
// page into the analysis tree and returns the path, thus the page write reaches
|
|
88
|
-
// no host seam.
|
|
89
|
-
const reportSession = createReportSessionRuntime({ pool: conversation.pool, ...(conversation.logger ? { logger: conversation.logger } : {}) });
|
|
121
|
+
// The report agent is a singleton over the conversation deps, the same way the
|
|
122
|
+
// session runtime is. Its preview tool writes the page into the analysis tree
|
|
123
|
+
// and returns the path, thus the page write reaches no host seam.
|
|
90
124
|
const reportVersionStore = createReportVersionStore({ pool: conversation.pool, ...(conversation.logger ? { logger: conversation.logger } : {}) });
|
|
91
125
|
const reportThreads = createThreadStore(conversation.pool);
|
|
92
126
|
// The read cache of the production report path, one for each recent analysis. A preview
|
|
@@ -121,7 +155,14 @@ export function assembleCoreRuntime(deps) {
|
|
|
121
155
|
store: reportVersionStore,
|
|
122
156
|
threads: reportThreads,
|
|
123
157
|
chrome: conversation.chrome,
|
|
158
|
+
// The derivation tool draws the rails of the value tier: the same sandbox client
|
|
159
|
+
// and the same run authorizer. Thus a session derivation and an extraction run on
|
|
160
|
+
// one substrate, and neither one mints a run of the analysis.
|
|
161
|
+
derivations: reportSession.derivations,
|
|
162
|
+
sandboxClient: wf.dataProfile.sandboxClient,
|
|
163
|
+
runAuthorizer: conversation.runAuthorizer,
|
|
124
164
|
makeResolver: makeReportResolver,
|
|
165
|
+
...(eyes ? { eyes } : {}),
|
|
125
166
|
...(deps.resolveReportPageAsset ? { resolvePageAsset: deps.resolveReportPageAsset } : {}),
|
|
126
167
|
...(conversation.logger ? { logger: conversation.logger } : {}),
|
|
127
168
|
});
|
package/dist/sandbox/client.d.ts
CHANGED
|
@@ -20,8 +20,17 @@
|
|
|
20
20
|
* `awaitExec` runs in the workflow body (not as a DBOS step) because
|
|
21
21
|
* `DBOS.recv` and `DBOS.writeStream` are body-only.
|
|
22
22
|
*/
|
|
23
|
-
import type { CreateSandboxMeta, ExecEmit, ExecResult, ManagedSandbox, SandboxIdentity, SandboxLiveness, SandboxRef, SubmitExecBody } from "./types.js";
|
|
23
|
+
import type { CreateSandboxMeta, ExecEmit, ExecResult, ManagedSandbox, SandboxIdentity, SandboxLiveness, SandboxRef, SandboxTransport, SubmitExecBody } from "./types.js";
|
|
24
24
|
export interface SandboxClient {
|
|
25
|
+
/**
|
|
26
|
+
* The result transport this client awaits under, fixed at construction. A caller that runs outside a
|
|
27
|
+
* workflow body reads it: `callback` awaits through `DBOS.recv`, which is body-only, thus such a caller
|
|
28
|
+
* must refuse before it starts a container it can never await.
|
|
29
|
+
*
|
|
30
|
+
* Optional, because a hand-written realization states nothing here. Absent means unknown, and a caller
|
|
31
|
+
* treats it as the poll default rather than refusing every composition that omits it.
|
|
32
|
+
*/
|
|
33
|
+
readonly transport?: SandboxTransport;
|
|
25
34
|
/**
|
|
26
35
|
* DBOS step (`sandbox.create`) — the spawn half of the two-step create
|
|
27
36
|
* (see the harness-sandbox-exec spec). Launches the sandbox-base container/Job under the
|