@inflexa-ai/harness 0.42.1 → 0.43.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/README.md +2 -2
- package/dist/agents/conversation-agent.js +5 -1
- package/dist/agents/sandbox/drug-repurposing-agent.js +1 -0
- package/dist/agents/sandbox/shared.d.ts +1 -6
- package/dist/agents/sandbox/shared.js +3 -16
- package/dist/agents/sandbox/types.d.ts +1 -1
- package/dist/app/chat-turn.js +13 -1
- package/dist/config/environment-stores.d.ts +4 -2
- package/dist/contracts/chat-events.d.ts +9 -1
- package/dist/contracts/chat-frame.d.ts +3 -3
- package/dist/contracts/chat-frame.js +8 -3
- package/dist/contracts/chat-parts.d.ts +4 -1
- package/dist/contracts/data-profile.d.ts +4 -6
- package/dist/contracts/index.d.ts +1 -1
- package/dist/contracts/report-blocks.d.ts +1364 -75
- package/dist/contracts/report-blocks.js +221 -29
- package/dist/contracts/report-reference.js +1 -1
- package/dist/contracts/schemas/chat-events.d.ts +13 -0
- package/dist/contracts/schemas/chat-events.js +5 -0
- package/dist/contracts/schemas/chat-parts.d.ts +2 -2
- package/dist/contracts/schemas/index.d.ts +1 -1
- package/dist/contracts/schemas/index.js +1 -1
- package/dist/execution/input-signature.d.ts +7 -13
- package/dist/execution/input-signature.js +0 -0
- package/dist/execution/run-canceler.d.ts +3 -2
- package/dist/execution/run-canceler.js +3 -2
- package/dist/execution/run-event-stream.d.ts +16 -2
- package/dist/execution/run-event-stream.js +54 -3
- package/dist/index.d.ts +1 -8
- package/dist/index.js +5 -16
- package/dist/input-scan/enrich.d.ts +0 -2
- package/dist/input-scan/enrich.js +0 -1
- package/dist/lib/metrics.js +6 -7
- package/dist/lib/otel-spans.d.ts +4 -9
- package/dist/lib/otel-spans.js +3 -8
- package/dist/loop/run-agent.d.ts +4 -2
- package/dist/loop/run-agent.js +38 -23
- package/dist/memory/thread-history.d.ts +1 -1
- package/dist/prompts/report-session.d.ts +1 -1
- package/dist/prompts/report-session.js +17 -0
- package/dist/prompts/sandbox/drug-repurposing-agent.d.ts +1 -1
- package/dist/prompts/sandbox/drug-repurposing-agent.js +7 -0
- package/dist/provenance/exec-frame.d.ts +1 -1
- package/dist/report-model/authoring-grammar.d.ts +416 -17
- package/dist/report-model/authoring-grammar.js +25 -4
- package/dist/report-model/block-walk.d.ts +20 -4
- package/dist/report-model/block-walk.js +64 -7
- package/dist/report-model/draft-finish.d.ts +6 -2
- package/dist/report-model/draft-finish.js +6 -1
- package/dist/report-model/production-resolver.d.ts +8 -0
- package/dist/report-model/production-resolver.js +1 -1
- package/dist/report-model/validate.d.ts +20 -10
- package/dist/report-model/validate.js +29 -13
- package/dist/report-render/chart-export.d.ts +52 -0
- package/dist/report-render/chart-export.js +192 -0
- package/dist/report-render/chart-presets.d.ts +46 -47
- package/dist/report-render/chart-presets.js +31 -101
- package/dist/report-render/chart-renderers.d.ts +163 -0
- package/dist/report-render/chart-renderers.js +1055 -0
- package/dist/report-render/chart-toolbox.d.ts +124 -0
- package/dist/report-render/chart-toolbox.js +595 -0
- package/dist/report-render/chart.d.ts +60 -27
- package/dist/report-render/chart.js +2323 -524
- package/dist/report-render/design.d.ts +476 -16
- package/dist/report-render/design.js +390 -56
- package/dist/report-render/figures/common.d.ts +321 -0
- package/dist/report-render/figures/common.js +759 -0
- package/dist/report-render/figures/dendrogram.d.ts +36 -0
- package/dist/report-render/figures/dendrogram.js +130 -0
- package/dist/report-render/figures/dense.d.ts +111 -0
- package/dist/report-render/figures/dense.js +204 -0
- package/dist/report-render/figures/dotplot.d.ts +28 -0
- package/dist/report-render/figures/dotplot.js +234 -0
- package/dist/report-render/figures/embedding.d.ts +43 -0
- package/dist/report-render/figures/embedding.js +360 -0
- package/dist/report-render/figures/equal-units.d.ts +101 -0
- package/dist/report-render/figures/equal-units.js +215 -0
- package/dist/report-render/figures/forest.d.ts +20 -0
- package/dist/report-render/figures/forest.js +398 -0
- package/dist/report-render/figures/gsea.d.ts +30 -0
- package/dist/report-render/figures/gsea.js +391 -0
- package/dist/report-render/figures/heatmap.d.ts +40 -0
- package/dist/report-render/figures/heatmap.js +395 -0
- package/dist/report-render/figures/index.d.ts +135 -0
- package/dist/report-render/figures/index.js +100 -0
- package/dist/report-render/figures/km.d.ts +16 -0
- package/dist/report-render/figures/km.js +406 -0
- package/dist/report-render/figures/label-room.d.ts +130 -0
- package/dist/report-render/figures/label-room.js +341 -0
- package/dist/report-render/figures/locuszoom.d.ts +50 -0
- package/dist/report-render/figures/locuszoom.js +675 -0
- package/dist/report-render/figures/lollipop.d.ts +16 -0
- package/dist/report-render/figures/lollipop.js +247 -0
- package/dist/report-render/figures/ma.d.ts +20 -0
- package/dist/report-render/figures/ma.js +114 -0
- package/dist/report-render/figures/manhattan.d.ts +60 -0
- package/dist/report-render/figures/manhattan.js +343 -0
- package/dist/report-render/figures/oncoprint.d.ts +41 -0
- package/dist/report-render/figures/oncoprint.js +420 -0
- package/dist/report-render/figures/pca.d.ts +37 -0
- package/dist/report-render/figures/pca.js +241 -0
- package/dist/report-render/figures/qq.d.ts +30 -0
- package/dist/report-render/figures/qq.js +182 -0
- package/dist/report-render/figures/roc.d.ts +17 -0
- package/dist/report-render/figures/roc.js +116 -0
- package/dist/report-render/figures/sankey.d.ts +48 -0
- package/dist/report-render/figures/sankey.js +353 -0
- package/dist/report-render/figures/upset.d.ts +60 -0
- package/dist/report-render/figures/upset.js +316 -0
- package/dist/report-render/figures/volcano.d.ts +25 -0
- package/dist/report-render/figures/volcano.js +166 -0
- package/dist/report-render/hybrid-svg.d.ts +75 -0
- package/dist/report-render/hybrid-svg.js +504 -0
- package/dist/report-render/number-format.d.ts +19 -0
- package/dist/report-render/number-format.js +25 -1
- package/dist/report-render/page.d.ts +41 -4
- package/dist/report-render/page.js +247 -12
- package/dist/report-render/render.d.ts +13 -4
- package/dist/report-render/render.js +37 -6
- package/dist/report-render/types.d.ts +23 -2
- package/dist/report-render/value-bridge.d.ts +38 -3
- package/dist/report-render/value-bridge.js +137 -6
- package/dist/report-render/views/chart-view.d.ts +42 -6
- package/dist/report-render/views/chart-view.js +70 -9
- package/dist/report-render/views/page-view.js +9 -10
- package/dist/runtime/assemble.js +2 -2
- package/dist/sandbox/client.d.ts +23 -32
- package/dist/sandbox/client.js +3 -11
- package/dist/sandbox/create-sandbox.d.ts +9 -24
- package/dist/sandbox/create-sandbox.js +15 -30
- package/dist/sandbox/docker-client.d.ts +12 -22
- package/dist/sandbox/docker-client.js +29 -43
- package/dist/sandbox/exec.d.ts +58 -0
- package/dist/sandbox/exec.js +197 -0
- package/dist/sandbox/identity.d.ts +5 -5
- package/dist/sandbox/identity.js +7 -10
- package/dist/sandbox/k8s-client.d.ts +4 -10
- package/dist/sandbox/k8s-client.js +5 -12
- package/dist/sandbox/liveness.d.ts +5 -12
- package/dist/sandbox/liveness.js +5 -12
- package/dist/sandbox/notification-sweep.d.ts +4 -7
- package/dist/sandbox/notification-sweep.js +4 -7
- package/dist/sandbox/reaper.d.ts +3 -3
- package/dist/sandbox/reaper.js +3 -3
- package/dist/sandbox/sandbox-error.d.ts +10 -11
- package/dist/sandbox/sandbox-error.js +10 -11
- package/dist/sandbox/sandbox-step-translate.d.ts +1 -1
- package/dist/sandbox/sandbox-step-translate.js +1 -1
- package/dist/sandbox/types.d.ts +31 -99
- package/dist/sandbox/types.js +17 -84
- package/dist/state/active-sandboxes.d.ts +7 -32
- package/dist/state/active-sandboxes.js +11 -46
- package/dist/state/index.d.ts +1 -2
- package/dist/state/index.js +1 -1
- package/dist/state/migrations/20261005120000_drop_the_active_exec_tracking.d.ts +7 -0
- package/dist/state/migrations/20261005120000_drop_the_active_exec_tracking.js +12 -0
- package/dist/state/migrations/index.js +2 -0
- package/dist/state/schema.d.ts +1 -5
- package/dist/state/schema.js +1 -6
- package/dist/state/step-executions.js +1 -2
- package/dist/tasks/data-profile.js +7 -20
- package/dist/tasks/derive-table-exec.d.ts +4 -14
- package/dist/tasks/derive-table-exec.js +9 -24
- package/dist/tasks/extract-values.d.ts +2 -2
- package/dist/tasks/extract-values.js +4 -7
- package/dist/tools/bio/index.d.ts +2 -0
- package/dist/tools/bio/index.js +3 -0
- package/dist/tools/bio/keys.d.ts +11 -0
- package/dist/tools/bio/keys.js +15 -0
- package/dist/tools/bio/search-clinical-trials.d.ts +1 -1
- package/dist/tools/bio/search-patents.d.ts +46 -0
- package/dist/tools/bio/search-patents.js +134 -0
- package/dist/tools/bio/search-regulatory-approvals.d.ts +49 -0
- package/dist/tools/bio/search-regulatory-approvals.js +158 -0
- package/dist/tools/define-tool.d.ts +56 -13
- package/dist/tools/define-tool.js +28 -1
- package/dist/tools/execute-analysis.js +3 -3
- package/dist/tools/lib/amass-client.d.ts +586 -0
- package/dist/tools/lib/amass-client.js +492 -0
- package/dist/tools/lib/amass-config.d.ts +2 -0
- package/dist/tools/lib/amass-config.js +10 -0
- package/dist/tools/report-session/derive-table.d.ts +8 -9
- package/dist/tools/report-session/derive-table.js +3 -4
- package/dist/tools/report-session/preview-report.js +4 -49
- package/dist/tools/sandbox/list-available-packages.d.ts +1 -1
- package/dist/tools/sandbox/list-available-packages.js +5 -4
- package/dist/tools/workspace/edit-file.d.ts +5 -4
- package/dist/tools/workspace/edit-file.js +10 -13
- package/dist/tools/workspace/execute-command.d.ts +27 -42
- package/dist/tools/workspace/execute-command.js +42 -38
- package/dist/tools/workspace/index.d.ts +5 -6
- package/dist/tools/workspace/index.js +5 -6
- package/dist/tools/workspace/mutator.d.ts +43 -8
- package/dist/tools/workspace/mutator.js +45 -34
- package/dist/tools/workspace/run-exec.d.ts +3 -12
- package/dist/tools/workspace/run-exec.js +7 -24
- package/dist/tools/workspace/scan-inputs.d.ts +0 -3
- package/dist/tools/workspace/scan-inputs.js +0 -1
- package/dist/tools/workspace/write-file.d.ts +12 -3
- package/dist/tools/workspace/write-file.js +17 -13
- package/dist/workflows/sandbox-step.d.ts +7 -11
- package/dist/workflows/sandbox-step.js +24 -27
- package/package.json +3 -1
- package/dist/sandbox/await-exec.d.ts +0 -143
- package/dist/sandbox/await-exec.js +0 -417
- package/dist/sandbox/deliver-exec-event.d.ts +0 -25
- package/dist/sandbox/deliver-exec-event.js +0 -29
- package/dist/sandbox/digest.d.ts +0 -14
- package/dist/sandbox/digest.js +0 -17
- package/dist/sandbox/exec-id.d.ts +0 -12
- package/dist/sandbox/exec-id.js +0 -20
- package/dist/sandbox/hmac.d.ts +0 -62
- package/dist/sandbox/hmac.js +0 -72
- package/dist/sandbox/submit-exec.d.ts +0 -38
- package/dist/sandbox/submit-exec.js +0 -80
- package/dist/sandbox/watchdog.d.ts +0 -71
- package/dist/sandbox/watchdog.js +0 -161
|
@@ -0,0 +1,492 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure async client functions for the Amass Data Platform API: RegulatoryCore
|
|
3
|
+
* (the FDA and EMA authorizations, with the parsed sections of their labels,
|
|
4
|
+
* reviews, SmPCs and EPARs) and PatentCore (patents).
|
|
5
|
+
*
|
|
6
|
+
* The schemas mirror the published OpenAPI document
|
|
7
|
+
* (`https://api.amass.tech/api/doc/openapi.json`). A live key verified them on
|
|
8
|
+
* 2026-09-30, and the golden fixtures under `__fixtures__/amass/` hold those
|
|
9
|
+
* answers.
|
|
10
|
+
*
|
|
11
|
+
* Absence policy: a base field is always present, and an absent value is an
|
|
12
|
+
* explicit `null` (`therapeuticIndication`, `grantDate`). A field that only an
|
|
13
|
+
* `include` parameter adds (`fdaDetails`, `emaDetails`, `claims`,
|
|
14
|
+
* `description`) is an omitted key when the request does not ask for it. Thus
|
|
15
|
+
* a base field carries `.nullable()`, and an include field carries
|
|
16
|
+
* `.nullable().optional()`. A lookup item omits `amassIds` when it carries
|
|
17
|
+
* `error`, and omits `error` when it carries `amassIds`.
|
|
18
|
+
*
|
|
19
|
+
* A response enum is a plain string here. Amass grows those vocabularies, and
|
|
20
|
+
* one unknown value would otherwise reject a whole search. The input filters
|
|
21
|
+
* of the tools carry the enums of the OpenAPI document.
|
|
22
|
+
*
|
|
23
|
+
* Status policy: only a 404 and a lookup item with `NOT_FOUND` are an absence.
|
|
24
|
+
* `isUnexpectedApiError` reads every 4xx as an absence, which would turn a
|
|
25
|
+
* rejected key (401) or a refused organization (403) into "no such record".
|
|
26
|
+
* Thus this client classifies each status itself.
|
|
27
|
+
*
|
|
28
|
+
* Every call spends credits: a search costs 5 credits for each 20 records of
|
|
29
|
+
* `limit`, and a get, a lookup (whatever its item count) or a 404 costs 1.
|
|
30
|
+
*/
|
|
31
|
+
import { err, ok } from "neverthrow";
|
|
32
|
+
import { z } from "zod";
|
|
33
|
+
import { apiFetchValidated, describeApiError } from "./api-utils.js";
|
|
34
|
+
import { AMASS_BASE } from "./amass-config.js";
|
|
35
|
+
/** Render an `AmassError` as a one-line message for the model or for a throw. */
|
|
36
|
+
export function describeAmassError(e) {
|
|
37
|
+
switch (e.type) {
|
|
38
|
+
case "invalid_input":
|
|
39
|
+
return `Amass rejected the request (HTTP ${e.status}): ${e.message}`;
|
|
40
|
+
case "unauthorized":
|
|
41
|
+
return `Amass rejected the API key (HTTP 401): ${e.message}. Make sure that AMASS_API_KEY is correct.`;
|
|
42
|
+
case "forbidden":
|
|
43
|
+
return (`Amass refused the request (HTTP 403): ${e.message}. ` +
|
|
44
|
+
"Make sure that AMASS_API_KEY is correct and that the organization of the key has Amass credits.");
|
|
45
|
+
case "rejected":
|
|
46
|
+
return `Amass answered ${e.code}${e.status === null ? "" : ` (HTTP ${e.status})`}: ${e.message}`;
|
|
47
|
+
case "api":
|
|
48
|
+
return describeApiError(e.error);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
// Every error of Amass has this one shape. A 400 adds `fields`, the reason for
|
|
52
|
+
// each rejected parameter.
|
|
53
|
+
export const AmassErrorEnvelopeSchema = z.object({
|
|
54
|
+
error: z.object({
|
|
55
|
+
status: z.number(),
|
|
56
|
+
code: z.string(),
|
|
57
|
+
message: z.string(),
|
|
58
|
+
fields: z.record(z.string(), z.string()).optional(),
|
|
59
|
+
}),
|
|
60
|
+
});
|
|
61
|
+
/** Read the message of an Amass error body, with the per-field reasons of a 400. */
|
|
62
|
+
function envelopeOf(body) {
|
|
63
|
+
let parsed;
|
|
64
|
+
try {
|
|
65
|
+
parsed = JSON.parse(body);
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
return { code: null, message: body || "no message" };
|
|
69
|
+
}
|
|
70
|
+
const envelope = AmassErrorEnvelopeSchema.safeParse(parsed);
|
|
71
|
+
if (!envelope.success)
|
|
72
|
+
return { code: null, message: body || "no message" };
|
|
73
|
+
const { code, message, fields } = envelope.data.error;
|
|
74
|
+
const reasons = fields ? Object.entries(fields).map(([field, reason]) => `${field}: ${reason}`) : [];
|
|
75
|
+
return { code, message: reasons.length > 0 ? `${message} (${reasons.join("; ")})` : message };
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Classify a failed call. A 404 is the one absence, thus it resolves to `ok(null)`.
|
|
79
|
+
* A 429 that outlived the retries arrives as `exhausted`, never as `http_status`.
|
|
80
|
+
*/
|
|
81
|
+
function classify(e) {
|
|
82
|
+
if (e.type !== "http_status")
|
|
83
|
+
return err({ type: "api", error: e });
|
|
84
|
+
if (e.status === 404)
|
|
85
|
+
return ok(null);
|
|
86
|
+
const { code, message } = envelopeOf(e.body);
|
|
87
|
+
if (e.status === 400 || e.status === 422)
|
|
88
|
+
return err({ type: "invalid_input", status: e.status, message });
|
|
89
|
+
if (e.status === 401)
|
|
90
|
+
return err({ type: "unauthorized", message });
|
|
91
|
+
if (e.status === 403)
|
|
92
|
+
return err({ type: "forbidden", message });
|
|
93
|
+
if (e.status >= 400 && e.status < 500)
|
|
94
|
+
return err({ type: "rejected", status: e.status, code: code ?? "UNKNOWN", message });
|
|
95
|
+
return err({ type: "api", error: e });
|
|
96
|
+
}
|
|
97
|
+
function amassFetch(url, schema, headers, body) {
|
|
98
|
+
const options = body === undefined ? { headers } : { method: "POST", headers: { ...headers, "Content-Type": "application/json" }, body: JSON.stringify(body) };
|
|
99
|
+
return apiFetchValidated(url.toString(), schema, options).orElse(classify);
|
|
100
|
+
}
|
|
101
|
+
/** Append each defined value; an array repeats the parameter, which Amass reads as "match any". */
|
|
102
|
+
function urlOf(path, params) {
|
|
103
|
+
const url = new URL(`${AMASS_BASE}${path}`);
|
|
104
|
+
for (const [key, value] of Object.entries(params)) {
|
|
105
|
+
if (value === undefined)
|
|
106
|
+
continue;
|
|
107
|
+
if (Array.isArray(value)) {
|
|
108
|
+
for (const item of value)
|
|
109
|
+
url.searchParams.append(key, item);
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
url.searchParams.append(key, String(value));
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return url;
|
|
116
|
+
}
|
|
117
|
+
// ---------------------------------------------------------------------------
|
|
118
|
+
// Lookup
|
|
119
|
+
// ---------------------------------------------------------------------------
|
|
120
|
+
export const AmassLookupResponseSchema = z.object({
|
|
121
|
+
data: z.array(z.object({
|
|
122
|
+
input: z.record(z.string(), z.string()),
|
|
123
|
+
amassIds: z.array(z.string()).optional(),
|
|
124
|
+
error: z.object({ code: z.string(), message: z.string() }).optional(),
|
|
125
|
+
})),
|
|
126
|
+
});
|
|
127
|
+
/**
|
|
128
|
+
* Resolve external identifiers to Amass IDs in one lookup request. The IDs of every
|
|
129
|
+
* item are merged, in order and without duplicates. An item with `NOT_FOUND`
|
|
130
|
+
* contributes no ID; an item with any other error code rejects the whole lookup.
|
|
131
|
+
*/
|
|
132
|
+
function lookup(core, items, headers) {
|
|
133
|
+
return amassFetch(urlOf(`/cores/${core}/records/lookup`, {}), AmassLookupResponseSchema, headers, { items }).andThen((response) => {
|
|
134
|
+
const ids = [];
|
|
135
|
+
for (const item of response?.data ?? []) {
|
|
136
|
+
if (item.error && item.error.code !== "NOT_FOUND") {
|
|
137
|
+
return err({ type: "rejected", status: null, code: item.error.code, message: item.error.message });
|
|
138
|
+
}
|
|
139
|
+
for (const id of item.amassIds ?? []) {
|
|
140
|
+
if (!ids.includes(id))
|
|
141
|
+
ids.push(id);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return ok(ids);
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
// ---------------------------------------------------------------------------
|
|
148
|
+
// Identifier forms
|
|
149
|
+
// ---------------------------------------------------------------------------
|
|
150
|
+
const FDA_APPLICATION_PREFIXES = ["NDA", "BLA", "ANDA"];
|
|
151
|
+
/**
|
|
152
|
+
* The lookup forms of an FDA application number. Amass stores the number with its
|
|
153
|
+
* prefix (`NDA021588`) and answers `NOT_FOUND` for the bare `021588`. A bare number
|
|
154
|
+
* thus goes as all three prefixes, in one request at the price of one.
|
|
155
|
+
*/
|
|
156
|
+
export function fdaApplicationForms(input) {
|
|
157
|
+
const compact = input.replace(/[\s-]/g, "").toUpperCase();
|
|
158
|
+
if (/^\d+$/.test(compact))
|
|
159
|
+
return FDA_APPLICATION_PREFIXES.map((prefix) => `${prefix}${compact}`);
|
|
160
|
+
return [compact];
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* The lookup form of an NDC. Amass stores the two-segment product NDC (`0078-0401`)
|
|
164
|
+
* and answers `NOT_FOUND` for the package NDC (`0078-0401-05`).
|
|
165
|
+
*/
|
|
166
|
+
export function productNdcOf(input) {
|
|
167
|
+
const trimmed = input.trim();
|
|
168
|
+
const segments = trimmed.split("-");
|
|
169
|
+
return segments.length === 3 && segments.every((segment) => /^\d+$/.test(segment)) ? `${segments[0]}-${segments[1]}` : trimmed;
|
|
170
|
+
}
|
|
171
|
+
// ---------------------------------------------------------------------------
|
|
172
|
+
// RegulatoryCore
|
|
173
|
+
// ---------------------------------------------------------------------------
|
|
174
|
+
export const REGULATORY_AGENCIES = ["FDA", "EMA"];
|
|
175
|
+
export const REGULATORY_MOLECULE_TYPES = [
|
|
176
|
+
"SMALL_MOLECULE",
|
|
177
|
+
"ANTIBODY",
|
|
178
|
+
"PROTEIN",
|
|
179
|
+
"ENZYME",
|
|
180
|
+
"OLIGONUCLEOTIDE",
|
|
181
|
+
"GENE",
|
|
182
|
+
"CELL",
|
|
183
|
+
"ANTIBODY_DRUG_CONJUGATE",
|
|
184
|
+
"VACCINE_COMPONENT",
|
|
185
|
+
"VACCINE",
|
|
186
|
+
"OLIGOSACCHARIDE",
|
|
187
|
+
"UNKNOWN",
|
|
188
|
+
];
|
|
189
|
+
export const REGULATORY_AUTHORIZATION_STATUSES = [
|
|
190
|
+
"ACTIVE",
|
|
191
|
+
"APPROVED_NOT_MARKETED",
|
|
192
|
+
"CONDITIONAL",
|
|
193
|
+
"SUSPENDED",
|
|
194
|
+
"WITHDRAWN_VOLUNTARY",
|
|
195
|
+
"WITHDRAWN_FORCED",
|
|
196
|
+
"REVOKED",
|
|
197
|
+
"LAPSED_SUNSET",
|
|
198
|
+
"REFUSED",
|
|
199
|
+
"WITHDRAWN_DURING_REVIEW",
|
|
200
|
+
"EXPIRED",
|
|
201
|
+
"UNKNOWN",
|
|
202
|
+
];
|
|
203
|
+
export const REGULATORY_DESIGNATIONS = [
|
|
204
|
+
"PRIORITY_REVIEW",
|
|
205
|
+
"BREAKTHROUGH_THERAPY",
|
|
206
|
+
"FAST_TRACK",
|
|
207
|
+
"RMAT",
|
|
208
|
+
"ACCELERATED_APPROVAL",
|
|
209
|
+
"ACCELERATED_ASSESSMENT",
|
|
210
|
+
"PRIME",
|
|
211
|
+
"CONDITIONAL_MA",
|
|
212
|
+
"EXCEPTIONAL_CIRCUMSTANCES",
|
|
213
|
+
];
|
|
214
|
+
const DocumentSectionSchema = z.object({
|
|
215
|
+
documentSectionId: z.string(),
|
|
216
|
+
amassId: z.string(),
|
|
217
|
+
docType: z.string(),
|
|
218
|
+
path: z.string().nullable(),
|
|
219
|
+
title: z.string().nullable(),
|
|
220
|
+
textType: z.string().nullable(),
|
|
221
|
+
sourceUrl: z.string().nullable(),
|
|
222
|
+
sourceDate: z.string().nullable(),
|
|
223
|
+
});
|
|
224
|
+
const MatchedSectionSchema = DocumentSectionSchema.extend({ matchedText: z.string().nullable() });
|
|
225
|
+
const DesignationSchema = z.object({
|
|
226
|
+
axis: z.string(),
|
|
227
|
+
type: z.string(),
|
|
228
|
+
agency: z.string(),
|
|
229
|
+
nativeName: z.string().nullable(),
|
|
230
|
+
basis: z.string().nullable(),
|
|
231
|
+
indication: z.string().nullable(),
|
|
232
|
+
postMarketingObligation: z.boolean().nullable(),
|
|
233
|
+
});
|
|
234
|
+
const OtherAuthorizationSchema = z.object({
|
|
235
|
+
amassId: z.string(),
|
|
236
|
+
agency: z.string(),
|
|
237
|
+
name: z.string().nullable(),
|
|
238
|
+
authorizationStatus: z.string().nullable(),
|
|
239
|
+
});
|
|
240
|
+
const FdaDetailsSchema = z.object({
|
|
241
|
+
applicationNumber: z.string().nullable(),
|
|
242
|
+
prescriptionClass: z.string().nullable(),
|
|
243
|
+
submissionClassCode: z.string().nullable(),
|
|
244
|
+
labelDate: z.string().nullable(),
|
|
245
|
+
labelUrl: z.string().nullable(),
|
|
246
|
+
ndc: z.array(z.string()),
|
|
247
|
+
splSetId: z.array(z.string()),
|
|
248
|
+
withdrawalDate: z.string().nullable(),
|
|
249
|
+
withdrawalReason: z.string().nullable(),
|
|
250
|
+
withdrawalSourceUrl: z.string().nullable(),
|
|
251
|
+
});
|
|
252
|
+
const EmaDetailsSchema = z.object({
|
|
253
|
+
productNumber: z.string().nullable(),
|
|
254
|
+
category: z.string().nullable(),
|
|
255
|
+
opinionStatus: z.string().nullable(),
|
|
256
|
+
isBiosimilar: z.boolean().nullable(),
|
|
257
|
+
isAdvancedTherapy: z.boolean().nullable(),
|
|
258
|
+
isGenericOrHybrid: z.boolean().nullable(),
|
|
259
|
+
additionalMonitoring: z.boolean().nullable(),
|
|
260
|
+
pharmacotherapeuticGroup: z.string().nullable(),
|
|
261
|
+
patientSafety: z.string().nullable(),
|
|
262
|
+
latestProcedure: z.string().nullable(),
|
|
263
|
+
revisionNumber: z.number().nullable(),
|
|
264
|
+
smpcUrl: z.string().nullable(),
|
|
265
|
+
smpcDate: z.string().nullable(),
|
|
266
|
+
opinionAdoptedDate: z.string().nullable(),
|
|
267
|
+
europeanCommissionDecisionDate: z.string().nullable(),
|
|
268
|
+
withdrawalOfApplicationDate: z.string().nullable(),
|
|
269
|
+
refusalOfMarketingAuthorisationDate: z.string().nullable(),
|
|
270
|
+
withdrawalExpiryRevocationLapseDate: z.string().nullable(),
|
|
271
|
+
firstPublishedDate: z.string().nullable(),
|
|
272
|
+
});
|
|
273
|
+
const RegulatoryBaseSchema = z.object({
|
|
274
|
+
amassId: z.string(),
|
|
275
|
+
agency: z.string(),
|
|
276
|
+
name: z.string().nullable(),
|
|
277
|
+
activeSubstance: z.string().nullable(),
|
|
278
|
+
moleculeType: z.string().nullable(),
|
|
279
|
+
authorizationStatus: z.string().nullable(),
|
|
280
|
+
procedureType: z.string().nullable(),
|
|
281
|
+
therapeuticIndication: z.string().nullable(),
|
|
282
|
+
marketingAuthorisationHolder: z.string().nullable(),
|
|
283
|
+
authorizationDate: z.string().nullable(),
|
|
284
|
+
firstAuthorizationDate: z.string().nullable(),
|
|
285
|
+
sourceUrl: z.string().nullable(),
|
|
286
|
+
isOrphan: z.boolean().nullable(),
|
|
287
|
+
designations: z.array(DesignationSchema),
|
|
288
|
+
authorizationsByAgency: z.array(OtherAuthorizationSchema),
|
|
289
|
+
fdaDetails: FdaDetailsSchema.nullable().optional(),
|
|
290
|
+
emaDetails: EmaDetailsSchema.nullable().optional(),
|
|
291
|
+
});
|
|
292
|
+
export const RegulatorySearchResponseSchema = z.object({
|
|
293
|
+
data: z.array(RegulatoryBaseSchema.extend({ documentSections: z.array(MatchedSectionSchema) })),
|
|
294
|
+
});
|
|
295
|
+
export const RegulatoryRecordResponseSchema = z.object({
|
|
296
|
+
data: RegulatoryBaseSchema.extend({ documentSections: z.array(DocumentSectionSchema) }),
|
|
297
|
+
});
|
|
298
|
+
export const RegulatorySectionResponseSchema = z.object({
|
|
299
|
+
data: DocumentSectionSchema.extend({ content: z.string().nullable() }),
|
|
300
|
+
});
|
|
301
|
+
/**
|
|
302
|
+
* Group sections by their source document, in the order of first appearance. An
|
|
303
|
+
* FDA label has a hundred sections or more, and each raw entry repeats the record
|
|
304
|
+
* ID, the PDF URL and the revision date; the group states the last two once.
|
|
305
|
+
*/
|
|
306
|
+
function groupSections(sections, entryOf) {
|
|
307
|
+
const groups = new Map();
|
|
308
|
+
for (const section of sections) {
|
|
309
|
+
const key = `${section.docType}\u0000${section.sourceUrl ?? ""}\u0000${section.sourceDate ?? ""}`;
|
|
310
|
+
let group = groups.get(key);
|
|
311
|
+
if (!group) {
|
|
312
|
+
group = { docType: section.docType, sourceUrl: section.sourceUrl, sourceDate: section.sourceDate, sections: [] };
|
|
313
|
+
groups.set(key, group);
|
|
314
|
+
}
|
|
315
|
+
group.sections.push(entryOf(section));
|
|
316
|
+
}
|
|
317
|
+
return [...groups.values()];
|
|
318
|
+
}
|
|
319
|
+
function summaryOf(record) {
|
|
320
|
+
return {
|
|
321
|
+
amassId: record.amassId,
|
|
322
|
+
agency: record.agency,
|
|
323
|
+
name: record.name,
|
|
324
|
+
activeSubstance: record.activeSubstance,
|
|
325
|
+
moleculeType: record.moleculeType,
|
|
326
|
+
authorizationStatus: record.authorizationStatus,
|
|
327
|
+
procedureType: record.procedureType,
|
|
328
|
+
therapeuticIndication: record.therapeuticIndication,
|
|
329
|
+
marketingAuthorisationHolder: record.marketingAuthorisationHolder,
|
|
330
|
+
authorizationDate: record.authorizationDate,
|
|
331
|
+
firstAuthorizationDate: record.firstAuthorizationDate,
|
|
332
|
+
isOrphan: record.isOrphan,
|
|
333
|
+
designations: record.designations,
|
|
334
|
+
otherAuthorizations: record.authorizationsByAgency,
|
|
335
|
+
sourceUrl: record.sourceUrl,
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
/** The matched sections that a search row keeps. The count still reports all of them. */
|
|
339
|
+
export const MAX_MATCHED_SECTIONS = 5;
|
|
340
|
+
export function mapRegulatorySearchRow(record) {
|
|
341
|
+
return {
|
|
342
|
+
...summaryOf(record),
|
|
343
|
+
matchedSectionCount: record.documentSections.length,
|
|
344
|
+
matchedDocuments: groupSections(record.documentSections.slice(0, MAX_MATCHED_SECTIONS), (section) => ({
|
|
345
|
+
documentSectionId: section.documentSectionId,
|
|
346
|
+
path: section.path,
|
|
347
|
+
title: section.title,
|
|
348
|
+
matchedText: section.matchedText,
|
|
349
|
+
})),
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
export function mapRegulatoryRecord(record) {
|
|
353
|
+
return {
|
|
354
|
+
...summaryOf(record),
|
|
355
|
+
fdaDetails: record.fdaDetails ?? null,
|
|
356
|
+
emaDetails: record.emaDetails ?? null,
|
|
357
|
+
sectionCount: record.documentSections.length,
|
|
358
|
+
documents: groupSections(record.documentSections, (section) => ({
|
|
359
|
+
documentSectionId: section.documentSectionId,
|
|
360
|
+
path: section.path,
|
|
361
|
+
title: section.title,
|
|
362
|
+
})),
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
export function searchRegulatoryRecords(params, headers) {
|
|
366
|
+
const url = urlOf("/cores/regulatorycore/records", { ...params });
|
|
367
|
+
return amassFetch(url, RegulatorySearchResponseSchema, headers).map((response) => (response?.data ?? []).map(mapRegulatorySearchRow));
|
|
368
|
+
}
|
|
369
|
+
/** One authorization with its table of contents, or `null` when Amass holds no such ID. */
|
|
370
|
+
export function getRegulatoryRecord(amassId, headers) {
|
|
371
|
+
const url = urlOf(`/cores/regulatorycore/records/${encodeURIComponent(amassId)}`, { include: ["fdaDetails", "emaDetails"] });
|
|
372
|
+
return amassFetch(url, RegulatoryRecordResponseSchema, headers).map((response) => (response ? mapRegulatoryRecord(response.data) : null));
|
|
373
|
+
}
|
|
374
|
+
/** The full text of one document section, or `null` when Amass holds no such section. */
|
|
375
|
+
export function getRegulatorySection(amassId, documentSectionId, headers) {
|
|
376
|
+
const url = urlOf(`/cores/regulatorycore/records/${encodeURIComponent(amassId)}/document-sections/${encodeURIComponent(documentSectionId)}`, {});
|
|
377
|
+
return amassFetch(url, RegulatorySectionResponseSchema, headers).map((response) => {
|
|
378
|
+
if (!response)
|
|
379
|
+
return null;
|
|
380
|
+
const { textType: _textType, ...section } = response.data;
|
|
381
|
+
return section;
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
export function regulatoryLookupItems(id) {
|
|
385
|
+
if (id.fdaApplicationNumber !== undefined)
|
|
386
|
+
return fdaApplicationForms(id.fdaApplicationNumber).map((form) => ({ fdaApplicationNumber: form }));
|
|
387
|
+
if (id.ndc !== undefined)
|
|
388
|
+
return [{ ndc: productNdcOf(id.ndc) }];
|
|
389
|
+
if (id.emaProductNumber !== undefined)
|
|
390
|
+
return [{ emaProductNumber: id.emaProductNumber.trim() }];
|
|
391
|
+
if (id.splSetId !== undefined)
|
|
392
|
+
return [{ splSetId: id.splSetId.trim() }];
|
|
393
|
+
return [];
|
|
394
|
+
}
|
|
395
|
+
export function lookupRegulatoryIds(id, headers) {
|
|
396
|
+
return lookup("regulatorycore", regulatoryLookupItems(id), headers);
|
|
397
|
+
}
|
|
398
|
+
// ---------------------------------------------------------------------------
|
|
399
|
+
// PatentCore
|
|
400
|
+
// ---------------------------------------------------------------------------
|
|
401
|
+
const PatentBaseSchema = z.object({
|
|
402
|
+
amassId: z.string(),
|
|
403
|
+
publicationNumber: z.string().nullable(),
|
|
404
|
+
url: z.string().nullable(),
|
|
405
|
+
applicationNumber: z.string().nullable(),
|
|
406
|
+
countryCode: z.string().nullable(),
|
|
407
|
+
kindCode: z.string().nullable(),
|
|
408
|
+
familyId: z.string().nullable(),
|
|
409
|
+
familyMembers: z.array(z.string()),
|
|
410
|
+
title: z.string().nullable(),
|
|
411
|
+
abstract: z.string().nullable(),
|
|
412
|
+
language: z.string().nullable(),
|
|
413
|
+
nonEnglishFallback: z.boolean().nullable(),
|
|
414
|
+
cpcCodes: z.array(z.string()),
|
|
415
|
+
inventors: z.array(z.string()),
|
|
416
|
+
assignees: z.array(z.string()),
|
|
417
|
+
publicationDate: z.string().nullable(),
|
|
418
|
+
filingDate: z.string().nullable(),
|
|
419
|
+
grantDate: z.string().nullable(),
|
|
420
|
+
priorityDate: z.string().nullable(),
|
|
421
|
+
citedPatents: z.array(z.string()),
|
|
422
|
+
hasClaims: z.boolean().nullable(),
|
|
423
|
+
hasDescription: z.boolean().nullable(),
|
|
424
|
+
nplCount: z.number().nullable(),
|
|
425
|
+
citedByCount: z.number().nullable(),
|
|
426
|
+
claims: z.string().nullable().optional(),
|
|
427
|
+
description: z.string().nullable().optional(),
|
|
428
|
+
});
|
|
429
|
+
export const PatentSearchResponseSchema = z.object({ data: z.array(PatentBaseSchema) });
|
|
430
|
+
export const PatentRecordResponseSchema = z.object({ data: PatentBaseSchema });
|
|
431
|
+
export function mapPatentSummary(record) {
|
|
432
|
+
return {
|
|
433
|
+
amassId: record.amassId,
|
|
434
|
+
publicationNumber: record.publicationNumber,
|
|
435
|
+
applicationNumber: record.applicationNumber,
|
|
436
|
+
countryCode: record.countryCode,
|
|
437
|
+
kindCode: record.kindCode,
|
|
438
|
+
familyId: record.familyId,
|
|
439
|
+
familyMemberCount: record.familyMembers.length,
|
|
440
|
+
title: record.title,
|
|
441
|
+
abstract: record.abstract,
|
|
442
|
+
assignees: record.assignees,
|
|
443
|
+
inventors: record.inventors,
|
|
444
|
+
cpcCodes: record.cpcCodes,
|
|
445
|
+
publicationDate: record.publicationDate,
|
|
446
|
+
filingDate: record.filingDate,
|
|
447
|
+
grantDate: record.grantDate,
|
|
448
|
+
priorityDate: record.priorityDate,
|
|
449
|
+
citedPatentCount: record.citedPatents.length,
|
|
450
|
+
citedByCount: record.citedByCount,
|
|
451
|
+
nplCount: record.nplCount,
|
|
452
|
+
hasClaims: record.hasClaims,
|
|
453
|
+
hasDescription: record.hasDescription,
|
|
454
|
+
url: record.url,
|
|
455
|
+
};
|
|
456
|
+
}
|
|
457
|
+
export function mapPatentRecord(record) {
|
|
458
|
+
return {
|
|
459
|
+
...mapPatentSummary(record),
|
|
460
|
+
familyMembers: record.familyMembers,
|
|
461
|
+
language: record.language,
|
|
462
|
+
nonEnglishFallback: record.nonEnglishFallback,
|
|
463
|
+
...(record.claims === undefined ? {} : { claims: record.claims }),
|
|
464
|
+
...(record.description === undefined ? {} : { description: record.description }),
|
|
465
|
+
};
|
|
466
|
+
}
|
|
467
|
+
/** PatentCore reads a list filter as one comma-separated value, not as a repeated parameter. */
|
|
468
|
+
function commaList(values) {
|
|
469
|
+
return values && values.length > 0 ? values.join(",") : undefined;
|
|
470
|
+
}
|
|
471
|
+
export function searchPatentRecords(params, headers) {
|
|
472
|
+
const url = urlOf("/cores/patentcore/records", {
|
|
473
|
+
...params,
|
|
474
|
+
assignee: commaList(params.assignee),
|
|
475
|
+
cpcCodes: commaList(params.cpcCodes),
|
|
476
|
+
countryCode: commaList(params.countryCode),
|
|
477
|
+
});
|
|
478
|
+
return amassFetch(url, PatentSearchResponseSchema, headers).map((response) => (response?.data ?? []).map(mapPatentSummary));
|
|
479
|
+
}
|
|
480
|
+
export function getPatentRecord(amassId, include, headers) {
|
|
481
|
+
const includes = [...(include.claims ? ["claims"] : []), ...(include.description ? ["description"] : [])];
|
|
482
|
+
const url = urlOf(`/cores/patentcore/records/${encodeURIComponent(amassId)}`, { include: includes });
|
|
483
|
+
return amassFetch(url, PatentRecordResponseSchema, headers).map((response) => (response ? mapPatentRecord(response.data) : null));
|
|
484
|
+
}
|
|
485
|
+
export function lookupPatentIds(id, headers) {
|
|
486
|
+
const items = id.publicationNumber !== undefined
|
|
487
|
+
? [{ publicationNumber: id.publicationNumber.trim() }]
|
|
488
|
+
: id.applicationNumber !== undefined
|
|
489
|
+
? [{ applicationNumber: id.applicationNumber.trim() }]
|
|
490
|
+
: [];
|
|
491
|
+
return lookup("patentcore", items, headers);
|
|
492
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export const AMASS_BASE = "https://api.amass.tech/api/v1";
|
|
2
|
+
export function getAmassHeaders(apiKey) {
|
|
3
|
+
if (!apiKey) {
|
|
4
|
+
throw new Error("AMASS_API_KEY environment variable is not set. " + "Obtain a key from https://platform.amass.tech/api-keys");
|
|
5
|
+
}
|
|
6
|
+
return {
|
|
7
|
+
Authorization: `Bearer ${apiKey}`,
|
|
8
|
+
Accept: "application/json",
|
|
9
|
+
};
|
|
10
|
+
}
|
|
@@ -29,9 +29,9 @@
|
|
|
29
29
|
* condition one time, up front, the same discipline as the eyes. A per-attempt failure would instead read as
|
|
30
30
|
* a transient fault, and it would invite a repeat of a call that can never pass.
|
|
31
31
|
*
|
|
32
|
-
* The container runs behind a seam, and never in the turn. An
|
|
33
|
-
*
|
|
34
|
-
*
|
|
32
|
+
* The container runs behind a seam, and never in the turn. An exec is a durable step of a workflow, and a
|
|
33
|
+
* report turn is not a workflow. Thus the tool takes an injected runner, and a registered workflow owns the
|
|
34
|
+
* container. The tool holds no sandbox client, and it imports no DBOS.
|
|
35
35
|
*/
|
|
36
36
|
import { type Result } from "neverthrow";
|
|
37
37
|
import { z } from "zod";
|
|
@@ -40,7 +40,7 @@ import type { Suspension } from "../../workflows/suspension.js";
|
|
|
40
40
|
import type { RunAuthorizer } from "../../execution/run-authorizer.js";
|
|
41
41
|
import { type Logger } from "../../lib/logger.js";
|
|
42
42
|
import type { ResourceSpec } from "../../config/resource-limits.js";
|
|
43
|
-
import type {
|
|
43
|
+
import type { ExecRequest, ExecResult } from "../../sandbox/types.js";
|
|
44
44
|
import type { DerivationSource, ReportSessionStateStore } from "../../state/report-session-state.js";
|
|
45
45
|
import { type ResolveWorkspaceRoot } from "../../workspace/paths.js";
|
|
46
46
|
import { type Tool } from "../define-tool.js";
|
|
@@ -156,11 +156,10 @@ export interface DerivationInputMount {
|
|
|
156
156
|
*/
|
|
157
157
|
export declare function buildDerivationExec(args: {
|
|
158
158
|
readonly script: string;
|
|
159
|
-
readonly execId: string;
|
|
160
159
|
readonly workingDir: string;
|
|
161
160
|
readonly inputs: readonly DerivationInputMount[];
|
|
162
161
|
readonly output: string;
|
|
163
|
-
}):
|
|
162
|
+
}): ExecRequest;
|
|
164
163
|
/**
|
|
165
164
|
* Give the failure of an exec result, or `undefined` when the script ran to a clean exit.
|
|
166
165
|
*
|
|
@@ -190,9 +189,9 @@ export interface DeriveTableExecInput {
|
|
|
190
189
|
/**
|
|
191
190
|
* Run one derivation exec and give the terminal result back.
|
|
192
191
|
*
|
|
193
|
-
* The composition realizes it over a registered workflow, thus the container
|
|
194
|
-
*
|
|
195
|
-
*
|
|
192
|
+
* The composition realizes it over a registered workflow, thus the container and its exec live inside a
|
|
193
|
+
* workflow. A fault of the sandbox rejects the promise, and the tool turns that rejection into one short
|
|
194
|
+
* detail.
|
|
196
195
|
*/
|
|
197
196
|
export type DeriveTableRunner = (input: DeriveTableExecInput) => Promise<Result<ExecResult, Suspension>>;
|
|
198
197
|
/**
|
|
@@ -29,9 +29,9 @@
|
|
|
29
29
|
* condition one time, up front, the same discipline as the eyes. A per-attempt failure would instead read as
|
|
30
30
|
* a transient fault, and it would invite a repeat of a call that can never pass.
|
|
31
31
|
*
|
|
32
|
-
* The container runs behind a seam, and never in the turn. An
|
|
33
|
-
*
|
|
34
|
-
*
|
|
32
|
+
* The container runs behind a seam, and never in the turn. An exec is a durable step of a workflow, and a
|
|
33
|
+
* report turn is not a workflow. Thus the tool takes an injected runner, and a registered workflow owns the
|
|
34
|
+
* container. The tool holds no sandbox client, and it imports no DBOS.
|
|
35
35
|
*/
|
|
36
36
|
import { ok } from "neverthrow";
|
|
37
37
|
import { unlink } from "node:fs/promises";
|
|
@@ -90,7 +90,6 @@ const NO_SANDBOX_DETAIL = "the composition gives no sandbox, thus this session c
|
|
|
90
90
|
export function buildDerivationExec(args) {
|
|
91
91
|
return {
|
|
92
92
|
command: ["python3", "-c", args.script],
|
|
93
|
-
execId: args.execId,
|
|
94
93
|
cwd: args.workingDir,
|
|
95
94
|
env: {
|
|
96
95
|
[DERIVE_INPUT_ENV]: JSON.stringify(args.inputs.map((input) => ({ path: input.path, hash: input.hash }))),
|
|
@@ -52,7 +52,7 @@ import { referencedPaths, walkBlocks } from "../../report-model/block-walk.js";
|
|
|
52
52
|
import { computeDraftHash } from "../../report-model/draft-hash.js";
|
|
53
53
|
import { finishDraft } from "../../report-model/draft-finish.js";
|
|
54
54
|
import { resolveDocumentReferences } from "../../report-model/validate.js";
|
|
55
|
-
import { bridgeValues } from "../../report-render/value-bridge.js";
|
|
55
|
+
import { bridgeValues, collectResolutions } from "../../report-render/value-bridge.js";
|
|
56
56
|
import { resolvePageAssetFromInstallation } from "../../report-render/asset-lookup.js";
|
|
57
57
|
import { ASSETS_DIR, DEPS_DIR, derivationScriptName, PAGE_ASSETS, stagedSource, tableSidecarName } from "../../report-render/assets.js";
|
|
58
58
|
import { renderReportPage } from "../../report-render/render.js";
|
|
@@ -77,51 +77,6 @@ function assetFileName(file) {
|
|
|
77
77
|
function figureSourcePolicy(file) {
|
|
78
78
|
return `assets/${assetFileName(file)}`;
|
|
79
79
|
}
|
|
80
|
-
/**
|
|
81
|
-
* Pair each block with the resolved value of its binding, in document order.
|
|
82
|
-
*
|
|
83
|
-
* A value-bearing kind carries the resolved value of its one reference, looked up by the block id from
|
|
84
|
-
* the map that the resolution pass filled. A no-value kind carries none. Where a reference sits in a
|
|
85
|
-
* block is the knowledge of `block-walk.ts`, thus this walk reads the block id alone and never a binding
|
|
86
|
-
* field.
|
|
87
|
-
*
|
|
88
|
-
* The switch is exhaustive over the eight block kinds. A ninth kind reaches the end with no return, and
|
|
89
|
-
* the declared return type fails the build. Thus the walk cannot drop a kind in silence. A value-bearing
|
|
90
|
-
* block reaches here only when its reference resolved, because an unresolved reference short-circuits
|
|
91
|
-
* before this walk.
|
|
92
|
-
*/
|
|
93
|
-
function collectResolutions(blocks, resolvedByBlock) {
|
|
94
|
-
const resolutions = [];
|
|
95
|
-
const visit = (block) => {
|
|
96
|
-
switch (block.kind) {
|
|
97
|
-
case "section":
|
|
98
|
-
resolutions.push({ blockId: block.id, kind: "section" });
|
|
99
|
-
for (const child of block.blocks) {
|
|
100
|
-
visit(child);
|
|
101
|
-
}
|
|
102
|
-
return;
|
|
103
|
-
case "text":
|
|
104
|
-
case "claim":
|
|
105
|
-
case "citation":
|
|
106
|
-
resolutions.push({ blockId: block.id, kind: block.kind });
|
|
107
|
-
return;
|
|
108
|
-
case "metric":
|
|
109
|
-
case "table":
|
|
110
|
-
case "chart":
|
|
111
|
-
case "figure": {
|
|
112
|
-
const resolved = resolvedByBlock.get(block.id);
|
|
113
|
-
if (resolved !== undefined) {
|
|
114
|
-
resolutions.push({ blockId: block.id, kind: block.kind, resolved });
|
|
115
|
-
}
|
|
116
|
-
return;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
};
|
|
120
|
-
for (const block of blocks) {
|
|
121
|
-
visit(block);
|
|
122
|
-
}
|
|
123
|
-
return resolutions;
|
|
124
|
-
}
|
|
125
80
|
/**
|
|
126
81
|
* The sidecar of each table block of the document, in document order.
|
|
127
82
|
*
|
|
@@ -201,11 +156,11 @@ function scriptAssets(records) {
|
|
|
201
156
|
* references. On a clean pass the resolutions map onto the render model in document order.
|
|
202
157
|
*/
|
|
203
158
|
async function resolveDocument(document, resolver, snapshot) {
|
|
204
|
-
const { resolvedByBlock, failures } = await resolveDocumentReferences(document.sections, snapshot, resolver);
|
|
159
|
+
const { resolvedByBlock, resolvedBySlot, failures } = await resolveDocumentReferences(document.sections, snapshot, resolver);
|
|
205
160
|
if (failures.length > 0) {
|
|
206
161
|
return { resolutions: [], unresolved: failures };
|
|
207
162
|
}
|
|
208
|
-
return { resolutions: collectResolutions(document.sections, resolvedByBlock), unresolved: [] };
|
|
163
|
+
return { resolutions: collectResolutions(document.sections, resolvedByBlock, resolvedBySlot), unresolved: [] };
|
|
209
164
|
}
|
|
210
165
|
/**
|
|
211
166
|
* Resolve the page root, stage each bound image and each manifest entry, and write the page.
|
|
@@ -456,7 +411,7 @@ export function createPreviewReportTool(deps) {
|
|
|
456
411
|
// the renderer moves it into a data asset and no part of this path reads a field of it. Absence
|
|
457
412
|
// gives a page with no provenance asset, and each other part of the render is unchanged.
|
|
458
413
|
const provenance = await readProvenance(analysisId);
|
|
459
|
-
const rendered = renderReportPage(document, bridged.value, {
|
|
414
|
+
const rendered = await renderReportPage(document, bridged.value, {
|
|
460
415
|
records: snapshot.citationRecords,
|
|
461
416
|
derivations: used.map((record) => chainOf(record, sessionDir)),
|
|
462
417
|
provenance,
|
|
@@ -140,7 +140,7 @@ export type InventoryRead = {
|
|
|
140
140
|
* here, thus the census a model sees and the check a launch runs never
|
|
141
141
|
* disagree about what the source holds.
|
|
142
142
|
*/
|
|
143
|
-
export declare function readInventorySections(deps: ListAvailablePackagesDeps): Promise<InventoryRead>;
|
|
143
|
+
export declare function readInventorySections(deps: ListAvailablePackagesDeps, analysisId: string): Promise<InventoryRead>;
|
|
144
144
|
/**
|
|
145
145
|
* Create the package inventory over the bound source: the pool-scope reader
|
|
146
146
|
* when the embedder binds one (a conversation or planning surface), the
|