@inflexa-ai/harness 0.17.0 → 0.19.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/dist/agents/report-builder.d.ts +2 -0
- package/dist/agents/report-builder.js +2 -0
- package/dist/agents/report-session-agent.d.ts +56 -0
- package/dist/agents/report-session-agent.js +72 -0
- package/dist/app/report-session-runtime.d.ts +72 -0
- package/dist/app/report-session-runtime.js +157 -0
- package/dist/app/spawn-report-session.d.ts +85 -0
- package/dist/app/spawn-report-session.js +83 -0
- package/dist/contracts/chat-events.d.ts +9 -0
- package/dist/contracts/index.d.ts +6 -2
- package/dist/contracts/index.js +3 -1
- package/dist/contracts/organ-system.d.ts +49 -0
- package/dist/contracts/organ-system.js +67 -0
- package/dist/contracts/report-blocks.d.ts +564 -0
- package/dist/contracts/report-blocks.js +117 -0
- package/dist/contracts/report-reference.d.ts +459 -0
- package/dist/contracts/report-reference.js +256 -0
- package/dist/contracts/schemas/chat-events.d.ts +2 -0
- package/dist/contracts/schemas/chat-events.js +2 -0
- package/dist/contracts/severity.d.ts +15 -0
- package/dist/contracts/severity.js +10 -0
- package/dist/contracts/target-dossier.d.ts +8675 -12972
- package/dist/contracts/target-dossier.js +534 -591
- package/dist/data/safety-panel-schema.d.ts +18 -5
- package/dist/data/safety-panel-schema.js +4 -4
- package/dist/execution/artifact-metadata.js +1 -0
- package/dist/execution/report-runner.js +1 -3
- package/dist/execution/run-synthesis.js +2 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +19 -0
- package/dist/lib/async-utils.d.ts +16 -4
- package/dist/lib/async-utils.js +20 -15
- package/dist/lib/host-concurrency.js +1 -0
- package/dist/loop/__fixtures__/scripted-provider.js +23 -2
- package/dist/loop/run-agent.js +58 -10
- package/dist/loop/tool-detail.d.ts +40 -0
- package/dist/loop/tool-detail.js +35 -3
- package/dist/loop/types.d.ts +13 -0
- package/dist/memory/thread-history.d.ts +10 -0
- package/dist/memory/thread-history.js +12 -1
- package/dist/memory/thread-store.d.ts +4 -4
- package/dist/memory/thread-store.js +18 -9
- package/dist/prompts/report-session.d.ts +1 -0
- package/dist/prompts/report-session.js +89 -0
- package/dist/prompts/target-assessment/briefs/executive-recommendation.d.ts +1 -1
- package/dist/prompts/target-assessment/briefs/executive-recommendation.js +5 -5
- package/dist/prompts/target-assessment/briefs/liability-bullets.d.ts +1 -1
- package/dist/prompts/target-assessment/briefs/liability-bullets.js +1 -1
- package/dist/prompts/target-assessment/briefs/target-organ-liabilities.d.ts +1 -1
- package/dist/prompts/target-assessment/briefs/target-organ-liabilities.js +11 -3
- package/dist/prompts/target-assessment/investigation/adversarial-critique.d.ts +1 -0
- package/dist/prompts/target-assessment/investigation/adversarial-critique.js +67 -0
- package/dist/prompts/target-assessment/investigation/claim-reverification.d.ts +1 -0
- package/dist/prompts/target-assessment/investigation/claim-reverification.js +49 -0
- package/dist/prompts/target-assessment/investigation/index.d.ts +3 -0
- package/dist/prompts/target-assessment/investigation/index.js +3 -0
- package/dist/prompts/target-assessment/investigation/mechanism-proposal.d.ts +1 -0
- package/dist/prompts/target-assessment/investigation/mechanism-proposal.js +49 -0
- package/dist/prompts/target-assessment/tox-voice/index.d.ts +1 -1
- package/dist/prompts/target-assessment/tox-voice/vocabulary.d.ts +8 -5
- package/dist/prompts/target-assessment/tox-voice/vocabulary.js +9 -20
- package/dist/providers/__fixtures__/session.d.ts +5 -4
- package/dist/providers/__fixtures__/session.js +4 -4
- package/dist/providers/ai-sdk.d.ts +77 -0
- package/dist/providers/ai-sdk.js +149 -19
- package/dist/providers/errors.d.ts +14 -0
- package/dist/providers/errors.js +103 -18
- package/dist/providers/types.d.ts +16 -0
- package/dist/providers/types.js +10 -1
- package/dist/report-model/block-walk.d.ts +56 -0
- package/dist/report-model/block-walk.js +89 -0
- package/dist/report-model/draft-finish.d.ts +60 -0
- package/dist/report-model/draft-finish.js +56 -0
- package/dist/report-model/draft-operations.d.ts +125 -0
- package/dist/report-model/draft-operations.js +341 -0
- package/dist/report-model/draft-read.d.ts +59 -0
- package/dist/report-model/draft-read.js +109 -0
- package/dist/report-model/draft.d.ts +51 -0
- package/dist/report-model/draft.js +32 -0
- package/dist/report-model/fixture-resolver.d.ts +8 -0
- package/dist/report-model/fixture-resolver.js +252 -0
- package/dist/report-model/pin-snapshot.d.ts +30 -0
- package/dist/report-model/pin-snapshot.js +40 -0
- package/dist/report-model/reference-resolver.d.ts +113 -0
- package/dist/report-model/reference-resolver.js +60 -0
- package/dist/report-model/structural-validation.d.ts +22 -0
- package/dist/report-model/structural-validation.js +68 -0
- package/dist/report-model/validate.d.ts +72 -0
- package/dist/report-model/validate.js +95 -0
- package/dist/report-render/chart.d.ts +33 -0
- package/dist/report-render/chart.js +538 -0
- package/dist/report-render/page.d.ts +127 -0
- package/dist/report-render/page.js +307 -0
- package/dist/report-render/references.d.ts +32 -0
- package/dist/report-render/references.js +44 -0
- package/dist/report-render/render.d.ts +25 -0
- package/dist/report-render/render.js +125 -0
- package/dist/report-render/script-json.d.ts +13 -0
- package/dist/report-render/script-json.js +15 -0
- package/dist/report-render/types.d.ts +39 -0
- package/dist/report-render/types.js +10 -0
- package/dist/report-render/value-bridge.d.ts +62 -0
- package/dist/report-render/value-bridge.js +82 -0
- package/dist/report-render/views/chart-view.d.ts +11 -0
- package/dist/report-render/views/chart-view.js +23 -0
- package/dist/report-render/views/page-view.d.ts +20 -0
- package/dist/report-render/views/page-view.js +49 -0
- package/dist/report-render/views/prose.d.ts +28 -0
- package/dist/report-render/views/prose.js +75 -0
- package/dist/report-render/views/references-view.d.ts +20 -0
- package/dist/report-render/views/references-view.js +64 -0
- package/dist/report-render/views/values.d.ts +42 -0
- package/dist/report-render/views/values.js +43 -0
- package/dist/runtime/assemble.d.ts +15 -0
- package/dist/runtime/assemble.js +28 -6
- package/dist/runtime/boot.d.ts +3 -3
- package/dist/runtime/boot.js +15 -4
- package/dist/runtime/dbos.d.ts +4 -4
- package/dist/state/artifacts.d.ts +16 -0
- package/dist/state/artifacts.js +18 -0
- package/dist/state/init.js +54 -0
- package/dist/state/purge-analysis.js +2 -0
- package/dist/state/report-session-state.d.ts +112 -0
- package/dist/state/report-session-state.js +150 -0
- package/dist/state/report-versions.d.ts +129 -0
- package/dist/state/report-versions.js +167 -0
- package/dist/state/snapshot-parse.d.ts +34 -0
- package/dist/state/snapshot-parse.js +82 -0
- package/dist/tasks/data-profile.js +1 -0
- package/dist/tools/ad-hoc-router.d.ts +7 -2
- package/dist/tools/ad-hoc-router.js +2 -1
- package/dist/tools/bio/chembl.js +1 -0
- package/dist/tools/bio/comptox.js +1 -0
- package/dist/tools/bio/drug-gene-interactions.js +1 -0
- package/dist/tools/bio/gene-disease-evidence.js +1 -0
- package/dist/tools/bio/gene-preclinical-profile.js +1 -0
- package/dist/tools/bio/keys.d.ts +3 -2
- package/dist/tools/bio/keys.js +3 -2
- package/dist/tools/bio/lookup-annotation.js +1 -0
- package/dist/tools/bio/opentargets.d.ts +3 -3
- package/dist/tools/bio/opentargets.js +4 -3
- package/dist/tools/bio/pubchem.js +1 -0
- package/dist/tools/bio/search-clinical-trials.js +1 -0
- package/dist/tools/bio/search-faers.js +1 -0
- package/dist/tools/bio/search-geo-datasets.js +1 -0
- package/dist/tools/bio/search-interactions.js +1 -0
- package/dist/tools/bio/target-safety.d.ts +4 -6
- package/dist/tools/bio/target-safety.js +7 -6
- package/dist/tools/define-tool.d.ts +19 -12
- package/dist/tools/define-tool.js +4 -2
- package/dist/tools/display/show-user.js +1 -0
- package/dist/tools/iterate-report.js +2 -0
- package/dist/tools/lib/chembl-client.d.ts +2 -0
- package/dist/tools/lib/chembl-client.js +1 -0
- package/dist/tools/lib/monarch-client.d.ts +42 -0
- package/dist/tools/lib/monarch-client.js +100 -0
- package/dist/tools/report/build-report.js +1 -0
- package/dist/tools/report/mint-preview-url.js +1 -0
- package/dist/tools/report/preview-snapshot.js +1 -0
- package/dist/tools/report/submit-report.js +1 -0
- package/dist/tools/report/version-fs.js +4 -0
- package/dist/tools/report-authoring/authoring-tools.d.ts +241 -0
- package/dist/tools/report-authoring/authoring-tools.js +460 -0
- package/dist/tools/report-session/index.d.ts +8 -0
- package/dist/tools/report-session/index.js +8 -0
- package/dist/tools/report-session/preview-report.d.ts +90 -0
- package/dist/tools/report-session/preview-report.js +245 -0
- package/dist/tools/research/context7-docs.js +2 -0
- package/dist/tools/research/generate-analogy-report.js +1 -0
- package/dist/tools/research/generate-plan.js +7 -2
- package/dist/tools/research/inspect-data-profile.js +4 -0
- package/dist/tools/research/literature-reviewer.js +1 -0
- package/dist/tools/research/search-arxiv.js +1 -0
- package/dist/tools/research/search-github-repos.js +1 -0
- package/dist/tools/research/search-semantic-scholar.js +1 -0
- package/dist/tools/sandbox/list-available-packages.js +23 -0
- package/dist/tools/sandbox/list-available-refs.js +36 -0
- package/dist/tools/sandbox/report-blocker.js +1 -0
- package/dist/tools/sandbox/skills.js +2 -0
- package/dist/tools/workspace/file-stat.js +1 -0
- package/dist/tools/workspace/show-file.js +2 -0
- package/dist/tools/workspace/show-plan.js +1 -0
- package/dist/workflows/execute-analysis.d.ts +5 -1
- package/dist/workflows/execute-analysis.js +5 -5
- package/dist/workflows/execute-target-assessment.d.ts +13 -2
- package/dist/workflows/execute-target-assessment.js +78 -16
- package/dist/workflows/target-assessment/assemblers/index.d.ts +1 -1
- package/dist/workflows/target-assessment/assemblers/index.js +1 -1
- package/dist/workflows/target-assessment/assemblers/literature.d.ts +9 -27
- package/dist/workflows/target-assessment/assemblers/literature.js +32 -48
- package/dist/workflows/target-assessment/assemblers/orchestrator.d.ts +17 -9
- package/dist/workflows/target-assessment/assemblers/orchestrator.js +195 -85
- package/dist/workflows/target-assessment/assemblers/safety.d.ts +70 -48
- package/dist/workflows/target-assessment/assemblers/safety.js +125 -42
- package/dist/workflows/target-assessment/collectors/index.d.ts +5 -2
- package/dist/workflows/target-assessment/collectors/index.js +48 -5
- package/dist/workflows/target-assessment/coverage.d.ts +43 -27
- package/dist/workflows/target-assessment/coverage.js +33 -29
- package/dist/workflows/target-assessment/fanout/index.js +1 -0
- package/dist/workflows/target-assessment/investigation/index.d.ts +97 -0
- package/dist/workflows/target-assessment/investigation/index.js +419 -0
- package/dist/workflows/target-assessment/lib/approval-precedents.d.ts +26 -5
- package/dist/workflows/target-assessment/lib/approval-precedents.js +95 -29
- package/dist/workflows/target-assessment/lib/citation-validator.js +1 -1
- package/dist/workflows/target-assessment/lib/clinical-consequence-annotator.d.ts +2 -2
- package/dist/workflows/target-assessment/lib/clinical-evidence-attribution.d.ts +2 -3
- package/dist/workflows/target-assessment/lib/clinical-evidence-attribution.js +0 -4
- package/dist/workflows/target-assessment/lib/compute-derived.d.ts +6 -5
- package/dist/workflows/target-assessment/lib/compute-derived.js +14 -5
- package/dist/workflows/target-assessment/lib/family-complex-supplement.d.ts +5 -6
- package/dist/workflows/target-assessment/lib/family-complex-supplement.js +2 -3
- package/dist/workflows/target-assessment/lib/fda-label-safety.d.ts +72 -0
- package/dist/workflows/target-assessment/lib/fda-label-safety.js +166 -0
- package/dist/workflows/target-assessment/lib/heterodimer-filter.d.ts +0 -9
- package/dist/workflows/target-assessment/lib/heterodimer-filter.js +0 -10
- package/dist/workflows/target-assessment/lib/hpo-organ-map.d.ts +34 -0
- package/dist/workflows/target-assessment/lib/hpo-organ-map.js +63 -0
- package/dist/workflows/target-assessment/lib/impc-organ-map.d.ts +19 -0
- package/dist/workflows/target-assessment/lib/impc-organ-map.js +39 -0
- package/dist/workflows/target-assessment/lib/meddra-organ-map.d.ts +24 -14
- package/dist/workflows/target-assessment/lib/meddra-organ-map.js +59 -47
- package/dist/workflows/target-assessment/lib/recommendation-sanitizer.js +1 -1
- package/dist/workflows/target-assessment/lib/regulatory-actions.d.ts +2 -3
- package/dist/workflows/target-assessment/lib/regulatory-actions.js +33 -4
- package/dist/workflows/target-assessment/lib/safety-corroboration.d.ts +44 -0
- package/dist/workflows/target-assessment/lib/safety-corroboration.js +273 -0
- package/dist/workflows/target-assessment/lib/target-identity-filter.d.ts +5 -7
- package/dist/workflows/target-assessment/lib/target-identity-filter.js +5 -7
- package/dist/workflows/target-assessment/metrics.d.ts +1 -6
- package/dist/workflows/target-assessment/metrics.js +1 -13
- package/dist/workflows/target-assessment/phase4-assemble.d.ts +2147 -807
- package/dist/workflows/target-assessment/phase4-assemble.js +19 -19
- package/dist/workflows/target-assessment/phase5-persist.d.ts +20 -21
- package/dist/workflows/target-assessment/phase5-persist.js +56 -173
- package/dist/workflows/target-assessment/schemas.d.ts +46 -1
- package/dist/workflows/target-assessment/schemas.js +19 -0
- package/dist/workflows/target-assessment/steps/fanout/polypharm-for-one-modulator-step.d.ts +1 -0
- package/dist/workflows/target-assessment/steps/fanout/polypharm-for-one-modulator-step.js +2 -0
- package/dist/workflows/target-assessment/steps/phase2-aggregate.d.ts +26 -62
- package/dist/workflows/target-assessment/steps/phase2-aggregate.js +0 -4
- package/dist/workflows/target-assessment/steps/phase3-aggregate.d.ts +27 -154
- package/dist/workflows/target-assessment/steps/phase3-aggregate.js +0 -6
- package/dist/workflows/target-assessment/steps/synthesis/diagnostics.d.ts +0 -6
- package/dist/workflows/target-assessment/steps/synthesis/diagnostics.js +0 -18
- package/dist/workflows/target-assessment/sub-workflows/per-modulator-polypharm.d.ts +1 -0
- package/dist/workflows/target-assessment/synthesis/index.d.ts +52 -5
- package/dist/workflows/target-assessment/synthesis/index.js +4 -1
- package/dist/workflows/target-assessment/synthesis-probes.d.ts +3 -3
- package/package.json +4 -1
|
@@ -3,11 +3,9 @@
|
|
|
3
3
|
* sources that carry it: the curated secondary-pharmacology panel that ships
|
|
4
4
|
* with the harness, and Open Targets' curated liabilities.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* (it named two tools that no longer exist). Both are keyed on the same target
|
|
10
|
-
* and answer the same question, so the pairing belongs in the tool.
|
|
6
|
+
* Both sources are keyed on the same target and answer the same question, so
|
|
7
|
+
* the pairing belongs in the tool rather than in prose a caller has to
|
|
8
|
+
* remember: one call consults both and merges what they carry.
|
|
11
9
|
*
|
|
12
10
|
* Identifier resolution is the tool's job, not the caller's: Open Targets
|
|
13
11
|
* accepts ONLY an Ensembl gene id, and it is taken from the panel entry when
|
|
@@ -41,7 +39,7 @@ export declare const targetSafetyTool: import("../define-tool.js").Tool<{
|
|
|
41
39
|
identifiers: string[];
|
|
42
40
|
identifierType?: "auto" | "gene_symbol" | "uniprot" | "chembl_id" | "ensembl_id" | undefined;
|
|
43
41
|
sources?: ("opentargets" | "panel")[] | undefined;
|
|
44
|
-
filterOrgan?: "hematologic" | "metabolic" | "immune" | "hepatic" | "cns" | "renal" | "respiratory" | "cardiac" | "gi" | undefined;
|
|
42
|
+
filterOrgan?: "hematologic" | "metabolic" | "immune" | "hepatic" | "musculoskeletal" | "cns" | "renal" | "reproductive" | "respiratory" | "cardiac" | "vascular" | "pns" | "gi" | "pancreas" | "endocrine_thyroid" | "dermatologic" | "ocular" | "oncology" | undefined;
|
|
45
43
|
minSeverity?: "high" | "medium" | "low" | undefined;
|
|
46
44
|
liabilityLimit?: number | undefined;
|
|
47
45
|
}, {
|
|
@@ -3,11 +3,9 @@
|
|
|
3
3
|
* sources that carry it: the curated secondary-pharmacology panel that ships
|
|
4
4
|
* with the harness, and Open Targets' curated liabilities.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* (it named two tools that no longer exist). Both are keyed on the same target
|
|
10
|
-
* and answer the same question, so the pairing belongs in the tool.
|
|
6
|
+
* Both sources are keyed on the same target and answer the same question, so
|
|
7
|
+
* the pairing belongs in the tool rather than in prose a caller has to
|
|
8
|
+
* remember: one call consults both and merges what they carry.
|
|
11
9
|
*
|
|
12
10
|
* Identifier resolution is the tool's job, not the caller's: Open Targets
|
|
13
11
|
* accepts ONLY an Ensembl gene id, and it is taken from the panel entry when
|
|
@@ -15,7 +13,9 @@
|
|
|
15
13
|
*/
|
|
16
14
|
import { ok } from "neverthrow";
|
|
17
15
|
import { z } from "zod";
|
|
18
|
-
import {
|
|
16
|
+
import { ORGAN_SYSTEMS } from "../../contracts/organ-system.js";
|
|
17
|
+
import { SEVERITIES } from "../../contracts/severity.js";
|
|
18
|
+
import { CHEMBL_RE, SafetyPanelFileSchema, UNIPROT_RE } from "../../data/safety-panel-schema.js";
|
|
19
19
|
import panelData from "../../data/safety-panel.json" with { type: "json" };
|
|
20
20
|
import { defineTool } from "../define-tool.js";
|
|
21
21
|
import { resolveSymbolToEnsemblId } from "../lib/ensembl-client.js";
|
|
@@ -100,6 +100,7 @@ export const targetSafetyTool = defineTool({
|
|
|
100
100
|
"means no CURATED liability, not that none exists. Both are valid no-data — do not retry. Read `perSource` and each row's `opentargetsNote`: a " +
|
|
101
101
|
"ChEMBL or UniProt identifier absent from the panel cannot be resolved to an Ensembl id, so its Open Targets half is skipped rather than empty.",
|
|
102
102
|
inputSchema,
|
|
103
|
+
describeCall: "none",
|
|
103
104
|
execute: async ({ identifiers, identifierType, sources, filterOrgan, minSeverity, liabilityLimit }) => {
|
|
104
105
|
const selected = sources ?? [...SOURCES];
|
|
105
106
|
const wantPanel = selected.includes("panel");
|
|
@@ -95,20 +95,28 @@ export interface ToolDefinition<Schema extends z.ZodType, Output> {
|
|
|
95
95
|
readonly inputSchema: Schema;
|
|
96
96
|
readonly executionMode?: ToolExecutionMode;
|
|
97
97
|
/**
|
|
98
|
-
* One line
|
|
98
|
+
* One line that names what THIS call does — the call-time counterpart of
|
|
99
99
|
* `description`. `description` self-describes the tool at attach time, so an
|
|
100
|
-
* agent knows what it holds
|
|
100
|
+
* agent knows what it holds. `describeCall` self-describes one invocation, so
|
|
101
101
|
* a surface can render four `update_working_memory` calls as four distinct
|
|
102
102
|
* lines instead of four identical chips.
|
|
103
103
|
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
104
|
+
* The decision is REQUIRED. Give a hook, or give the literal `"none"`.
|
|
105
|
+
* `"none"` declares that the input of the tool cannot distinguish its calls,
|
|
106
|
+
* thus a hook can only restate the name of the tool. `defineTool` consumes
|
|
107
|
+
* the sentinel at construction, and the sentinel never reaches a packaged
|
|
108
|
+
* tool. Thus a reader of a `Tool` sees a function, or sees nothing. A hook
|
|
109
|
+
* that returns the string `"none"` is still a hook, because the discriminator
|
|
110
|
+
* is `typeof`, not equality.
|
|
109
111
|
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
+
* A hook lives here, beside `inputSchema`, because that is the one place
|
|
113
|
+
* where the compiler checks the two against each other. A host-side formatter
|
|
114
|
+
* that reads `input.path` by string key breaks silently the day the schema
|
|
115
|
+
* moves. This one fails to build. The tool author writes it, because the tool
|
|
116
|
+
* author knows which field matters.
|
|
117
|
+
*
|
|
118
|
+
* A hook is synchronous and pure — no I/O, no ambient state. Dispatch is what
|
|
119
|
+
* the user waits on, and a description must never fail a call: the loop
|
|
112
120
|
* validates the input against `inputSchema` first, guards the call, and drops
|
|
113
121
|
* the detail on any failure (see the tool-call-detail capability).
|
|
114
122
|
*
|
|
@@ -116,10 +124,9 @@ export interface ToolDefinition<Schema extends z.ZodType, Output> {
|
|
|
116
124
|
* removed, secrets redacted, length capped — happens once at the emit site,
|
|
117
125
|
* never here.
|
|
118
126
|
*
|
|
119
|
-
*
|
|
120
|
-
* exactly as it is today. The hook never reaches the model.
|
|
127
|
+
* The hook never reaches the model.
|
|
121
128
|
*/
|
|
122
|
-
describeCall
|
|
129
|
+
describeCall: ((input: z.infer<Schema>) => string) | "none";
|
|
123
130
|
execute(input: z.infer<Schema>, ctx: ToolContext): Promise<Result<Output, ToolError>>;
|
|
124
131
|
}
|
|
125
132
|
/**
|
|
@@ -44,9 +44,11 @@ export function defineTool(def) {
|
|
|
44
44
|
inputSchema: def.inputSchema,
|
|
45
45
|
jsonSchema,
|
|
46
46
|
executionMode,
|
|
47
|
-
// Spread rather than assigned: a tool that
|
|
47
|
+
// Spread rather than assigned: a tool that declines carries no
|
|
48
48
|
// `describeCall` key at all, so "has a hook" is one property check.
|
|
49
|
-
|
|
49
|
+
// `typeof` is the discriminator, not equality with the sentinel, so a
|
|
50
|
+
// hook that returns the string `"none"` still packages as a hook.
|
|
51
|
+
...(typeof def.describeCall === "function" ? { describeCall: def.describeCall } : {}),
|
|
50
52
|
execute: def.execute,
|
|
51
53
|
};
|
|
52
54
|
}
|
|
@@ -61,6 +61,7 @@ export const showUserTool = defineTool({
|
|
|
61
61
|
"One card per call, rendered in call order; an identical repeat call resolves to the same card, so compose the " +
|
|
62
62
|
"finished content before calling rather than re-rendering a draft.",
|
|
63
63
|
inputSchema: ShowUserInputSchema,
|
|
64
|
+
describeCall: ({ kind, title }) => (title === undefined ? kind : `${kind}: ${title}`),
|
|
64
65
|
execute: async (input, ctx) => {
|
|
65
66
|
// `dataPath` is a reference the host resolves at render time; validate its
|
|
66
67
|
// shape only (existence is a render-time host concern), and treat a
|
|
@@ -413,6 +413,7 @@ export const planReportTool = defineTool({
|
|
|
413
413
|
"existing preview with `modifications` needs no brief — you may go " +
|
|
414
414
|
"straight to `submit_report`.)",
|
|
415
415
|
inputSchema: z.object({}),
|
|
416
|
+
describeCall: "none",
|
|
416
417
|
executionMode: "inline",
|
|
417
418
|
execute: async () => ok({
|
|
418
419
|
schema: REPORT_BRIEF_JSON_SCHEMA,
|
|
@@ -472,6 +473,7 @@ export function createReportSubmitTool(deps) {
|
|
|
472
473
|
"as an `error` string. Returns the preview id + version and emits a " +
|
|
473
474
|
"preview card.",
|
|
474
475
|
inputSchema: submitReportInputSchema,
|
|
476
|
+
describeCall: "none",
|
|
475
477
|
execute: async (input, ctx) => {
|
|
476
478
|
// The brief rides as `unknown` so its ~12k schema stays off the
|
|
477
479
|
// always-on tool surface. Validate it here and return issues as DATA
|
|
@@ -58,6 +58,8 @@ export interface ChemblPolypharmHit {
|
|
|
58
58
|
moleculeChemblId: string;
|
|
59
59
|
targetChemblId: string;
|
|
60
60
|
targetName: string | null;
|
|
61
|
+
/** The assay the reported activity was measured in, when ChEMBL names one. */
|
|
62
|
+
assayChemblId: string | null;
|
|
61
63
|
standardType: string | null;
|
|
62
64
|
standardValue: number | null;
|
|
63
65
|
standardUnits: string | null;
|
|
@@ -431,6 +431,7 @@ export async function getModulatorPolypharmacology(moleculeChemblId, options = {
|
|
|
431
431
|
moleculeChemblId,
|
|
432
432
|
targetChemblId: tid,
|
|
433
433
|
targetName: null,
|
|
434
|
+
assayChemblId: raw.assay_chembl_id ?? null,
|
|
434
435
|
standardType: raw.standard_type ?? null,
|
|
435
436
|
standardValue: parseNumeric(raw.standard_value),
|
|
436
437
|
standardUnits: raw.standard_units ?? null,
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure async client functions for the Monarch Initiative association API.
|
|
3
|
+
*
|
|
4
|
+
* Monarch curates human gene→phenotype annotations (HPO, from HPOA/OMIM/
|
|
5
|
+
* Orphanet): *human* loss-of-function evidence, meaning what is observed in
|
|
6
|
+
* people carrying variation in the gene, as opposed to a mouse knockout's
|
|
7
|
+
* phenotype or an aggregate gene-disease association score.
|
|
8
|
+
*
|
|
9
|
+
* Each phenotype association carries its HPO ancestor closure, which is what
|
|
10
|
+
* lets a consumer resolve the phenotype onto an organ system by identifier
|
|
11
|
+
* rather than by matching prose.
|
|
12
|
+
*
|
|
13
|
+
* The API is keyless and public.
|
|
14
|
+
*/
|
|
15
|
+
/** A curated human phenotype attributed to variation in the gene. */
|
|
16
|
+
export interface MonarchPhenotypeAssociation {
|
|
17
|
+
/** HPO term id, e.g. `HP:0001392`. */
|
|
18
|
+
readonly hpoId: string;
|
|
19
|
+
readonly label: string;
|
|
20
|
+
/** The term's HPO ancestor closure, for identifier-based organ resolution. */
|
|
21
|
+
readonly ancestorIds: string[];
|
|
22
|
+
/** PMIDs (as `PMID:…` curies) cited by the annotation. */
|
|
23
|
+
readonly publications: string[];
|
|
24
|
+
/** The disease the phenotype was annotated under, when the annotation names one. */
|
|
25
|
+
readonly diseaseContext: string | null;
|
|
26
|
+
/** Share of affected individuals showing the phenotype, when annotated. */
|
|
27
|
+
readonly frequencyPercent: number | null;
|
|
28
|
+
readonly primaryKnowledgeSource: string | null;
|
|
29
|
+
}
|
|
30
|
+
export interface MonarchGeneProfile {
|
|
31
|
+
/** The curie the gene was queried by, e.g. `HGNC:1097`. */
|
|
32
|
+
readonly geneCurie: string;
|
|
33
|
+
readonly phenotypes: MonarchPhenotypeAssociation[];
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Curated human phenotype associations for one gene.
|
|
37
|
+
*
|
|
38
|
+
* `geneCurie` is a prefixed identifier Monarch resolves — an HGNC id
|
|
39
|
+
* (`HGNC:1097`) or an NCBI gene id (`NCBIGene:673`). A gene Monarch does not
|
|
40
|
+
* hold returns an empty profile rather than an error.
|
|
41
|
+
*/
|
|
42
|
+
export declare function getGenePhenotypeProfile(geneCurie: string): Promise<MonarchGeneProfile>;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure async client functions for the Monarch Initiative association API.
|
|
3
|
+
*
|
|
4
|
+
* Monarch curates human gene→phenotype annotations (HPO, from HPOA/OMIM/
|
|
5
|
+
* Orphanet): *human* loss-of-function evidence, meaning what is observed in
|
|
6
|
+
* people carrying variation in the gene, as opposed to a mouse knockout's
|
|
7
|
+
* phenotype or an aggregate gene-disease association score.
|
|
8
|
+
*
|
|
9
|
+
* Each phenotype association carries its HPO ancestor closure, which is what
|
|
10
|
+
* lets a consumer resolve the phenotype onto an organ system by identifier
|
|
11
|
+
* rather than by matching prose.
|
|
12
|
+
*
|
|
13
|
+
* The API is keyless and public.
|
|
14
|
+
*/
|
|
15
|
+
import { z } from "zod";
|
|
16
|
+
import { apiFetchValidated, describeApiError, isUnexpectedApiError } from "./api-utils.js";
|
|
17
|
+
const MONARCH_BASE = "https://api-v3.monarchinitiative.org/v3/api";
|
|
18
|
+
/** Row cap per association category — a well-annotated gene carries a few hundred. */
|
|
19
|
+
const ASSOCIATION_ROW_CAP = 300;
|
|
20
|
+
/** The closure arrays make these responses large; the default timeout is short for them. */
|
|
21
|
+
const REQUEST_TIMEOUT_MS = 120_000;
|
|
22
|
+
const HUMAN_TAXON = "NCBITaxon:9606";
|
|
23
|
+
/** Phenotype terms live in the HPO namespace; a model-organism term would not. */
|
|
24
|
+
const HPO_NAMESPACE = "HP";
|
|
25
|
+
/**
|
|
26
|
+
* One association row. Every field is optional because Monarch returns the same
|
|
27
|
+
* envelope for every category and populates only what applies; the reader below
|
|
28
|
+
* treats a missing field as absent rather than trusting the wire.
|
|
29
|
+
*/
|
|
30
|
+
const MonarchAssociationSchema = z.object({
|
|
31
|
+
subject_taxon: z.string().nullish(),
|
|
32
|
+
object: z.string().optional(),
|
|
33
|
+
object_label: z.string().nullish(),
|
|
34
|
+
object_closure: z.array(z.string()).nullish(),
|
|
35
|
+
publications: z.array(z.string()).nullish(),
|
|
36
|
+
primary_knowledge_source: z.string().nullish(),
|
|
37
|
+
disease_context_qualifier: z.string().nullish(),
|
|
38
|
+
has_percentage: z.number().nullish(),
|
|
39
|
+
});
|
|
40
|
+
const MonarchAssociationPageSchema = z.object({
|
|
41
|
+
items: z.array(MonarchAssociationSchema).optional(),
|
|
42
|
+
});
|
|
43
|
+
async function fetchAssociations(geneCurie, category) {
|
|
44
|
+
const params = new URLSearchParams({
|
|
45
|
+
subject: geneCurie,
|
|
46
|
+
category,
|
|
47
|
+
limit: String(ASSOCIATION_ROW_CAP),
|
|
48
|
+
});
|
|
49
|
+
const res = await apiFetchValidated(`${MONARCH_BASE}/association?${params.toString()}`, MonarchAssociationPageSchema, {
|
|
50
|
+
timeoutMs: REQUEST_TIMEOUT_MS,
|
|
51
|
+
});
|
|
52
|
+
if (res.isErr()) {
|
|
53
|
+
// A 4xx means the gene curie is not one Monarch holds — an expected
|
|
54
|
+
// "not found", returned as an empty page. Anything else is a real
|
|
55
|
+
// failure and surfaces.
|
|
56
|
+
if (isUnexpectedApiError(res.error))
|
|
57
|
+
throw new Error(describeApiError(res.error));
|
|
58
|
+
return [];
|
|
59
|
+
}
|
|
60
|
+
return res.value.items ?? [];
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Human phenotype annotations only.
|
|
64
|
+
*
|
|
65
|
+
* Monarch serves a gene's phenotype edges from several annotation sets; the
|
|
66
|
+
* filter keeps the rows whose subject is the human gene and whose object is an
|
|
67
|
+
* HPO term, so model-organism phenotypes stay with the collector that owns them.
|
|
68
|
+
*/
|
|
69
|
+
function toPhenotype(row) {
|
|
70
|
+
if (!row.object || !row.object.startsWith(`${HPO_NAMESPACE}:`))
|
|
71
|
+
return null;
|
|
72
|
+
if (row.subject_taxon != null && row.subject_taxon !== HUMAN_TAXON)
|
|
73
|
+
return null;
|
|
74
|
+
return {
|
|
75
|
+
hpoId: row.object,
|
|
76
|
+
label: row.object_label ?? "",
|
|
77
|
+
ancestorIds: row.object_closure ?? [],
|
|
78
|
+
publications: row.publications ?? [],
|
|
79
|
+
diseaseContext: row.disease_context_qualifier ?? null,
|
|
80
|
+
frequencyPercent: row.has_percentage ?? null,
|
|
81
|
+
primaryKnowledgeSource: row.primary_knowledge_source ?? null,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Curated human phenotype associations for one gene.
|
|
86
|
+
*
|
|
87
|
+
* `geneCurie` is a prefixed identifier Monarch resolves — an HGNC id
|
|
88
|
+
* (`HGNC:1097`) or an NCBI gene id (`NCBIGene:673`). A gene Monarch does not
|
|
89
|
+
* hold returns an empty profile rather than an error.
|
|
90
|
+
*/
|
|
91
|
+
export async function getGenePhenotypeProfile(geneCurie) {
|
|
92
|
+
const rows = await fetchAssociations(geneCurie, "biolink:GeneToPhenotypicFeatureAssociation");
|
|
93
|
+
const phenotypes = [];
|
|
94
|
+
for (const row of rows) {
|
|
95
|
+
const p = toPhenotype(row);
|
|
96
|
+
if (p)
|
|
97
|
+
phenotypes.push(p);
|
|
98
|
+
}
|
|
99
|
+
return { geneCurie, phenotypes };
|
|
100
|
+
}
|
|
@@ -16,6 +16,7 @@ export function createBuildReportTool(state) {
|
|
|
16
16
|
"Always use this — never invoke a build script directly. Returns " +
|
|
17
17
|
"structured errors with line numbers when the template is broken.",
|
|
18
18
|
inputSchema: z.object({}),
|
|
19
|
+
describeCall: "none",
|
|
19
20
|
execute: async () => {
|
|
20
21
|
return ok(await renderReport({
|
|
21
22
|
versionDir: state.versionDir,
|
|
@@ -24,6 +24,7 @@ export function createMintPreviewUrlTool(state) {
|
|
|
24
24
|
inputSchema: z.object({
|
|
25
25
|
version: z.number().optional().describe("Version to mint for. Defaults to the iteration's current version."),
|
|
26
26
|
}),
|
|
27
|
+
describeCall: "none",
|
|
27
28
|
execute: async (input) => {
|
|
28
29
|
const version = input.version ?? state.currentVersion;
|
|
29
30
|
const result = await state.previews.mintPreviewAccess(state.resourceId, state.previewId);
|
|
@@ -47,6 +47,7 @@ export function createPreviewSnapshotTool(state) {
|
|
|
47
47
|
.optional()
|
|
48
48
|
.describe("Optional extra wait in ms after the theme-ready event (e.g., for chart paint). Capped at 30s."),
|
|
49
49
|
}),
|
|
50
|
+
describeCall: "none",
|
|
50
51
|
execute: async (input) => {
|
|
51
52
|
let url = state.urlCell.url;
|
|
52
53
|
const expiresAt = state.urlCell.expiresAt;
|
|
@@ -42,6 +42,7 @@ export function createSubmitReportTool(state) {
|
|
|
42
42
|
"samples — the rest had no QC row'. " +
|
|
43
43
|
"Leave empty when the report shipped cleanly."),
|
|
44
44
|
}),
|
|
45
|
+
describeCall: "none",
|
|
45
46
|
execute: async (input) => {
|
|
46
47
|
const problems = [];
|
|
47
48
|
// 1. report.html.j2 exists — the report itself, as opposed to the
|
|
@@ -44,6 +44,7 @@ export function createVersionFsTools(state) {
|
|
|
44
44
|
path: z.string().min(1),
|
|
45
45
|
content: z.string(),
|
|
46
46
|
}),
|
|
47
|
+
describeCall: "none",
|
|
47
48
|
execute: async ({ path, content }) => {
|
|
48
49
|
const resolved = resolveAgentPath(path, state.versionDir);
|
|
49
50
|
if (resolved.kind === "out_of_scope") {
|
|
@@ -73,6 +74,7 @@ export function createVersionFsTools(state) {
|
|
|
73
74
|
oldText: z.string().min(1),
|
|
74
75
|
newText: z.string(),
|
|
75
76
|
}),
|
|
77
|
+
describeCall: "none",
|
|
76
78
|
execute: async ({ path, oldText, newText }) => {
|
|
77
79
|
const resolved = resolveAgentPath(path, state.versionDir);
|
|
78
80
|
if (resolved.kind === "out_of_scope") {
|
|
@@ -112,6 +114,7 @@ export function createVersionFsTools(state) {
|
|
|
112
114
|
inputSchema: z.object({
|
|
113
115
|
path: z.string().min(1),
|
|
114
116
|
}),
|
|
117
|
+
describeCall: "none",
|
|
115
118
|
execute: async ({ path }) => {
|
|
116
119
|
const resolved = resolveAgentPath(path, state.versionDir);
|
|
117
120
|
if (resolved.kind === "out_of_scope") {
|
|
@@ -148,6 +151,7 @@ export function createVersionFsTools(state) {
|
|
|
148
151
|
inputSchema: z.object({
|
|
149
152
|
path: z.string().min(1),
|
|
150
153
|
}),
|
|
154
|
+
describeCall: "none",
|
|
151
155
|
execute: async ({ path }) => {
|
|
152
156
|
const resolved = resolveAgentPath(path, state.versionDir);
|
|
153
157
|
if (resolved.kind === "out_of_scope") {
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The authoring tool surface over the draft operations.
|
|
3
|
+
*
|
|
4
|
+
* The factory takes a session-state gateway, and it holds no draft. Each tool reads the thread id from the
|
|
5
|
+
* scope of the call, loads the state of that thread, applies the pure operation, and persists the new
|
|
6
|
+
* document. Thus two threads never share one draft, and a landed document outlives a host restart.
|
|
7
|
+
*
|
|
8
|
+
* Each tool maps its flat input onto a core operation, and it applies the pure operation. A landed
|
|
9
|
+
* document persists before the tool reports `applied: true`. A refused operation returns typed data in the
|
|
10
|
+
* ok channel, and the error channel stays for an unexpected failure.
|
|
11
|
+
*
|
|
12
|
+
* A call with no report thread in its scope, a thread with no stored state, and a gateway fault each
|
|
13
|
+
* refuse as typed data too. That refusal sits beside the core refusal, and it names the absent thread
|
|
14
|
+
* scope or the absent state.
|
|
15
|
+
*
|
|
16
|
+
* The primitive admits a flat object input only. Thus a destination is four optional fields, and not a
|
|
17
|
+
* nested union. A conflict between the flat fields refuses before the core runs.
|
|
18
|
+
*/
|
|
19
|
+
import { type Result } from "neverthrow";
|
|
20
|
+
import { z } from "zod";
|
|
21
|
+
import type { Scope } from "../../auth/types.js";
|
|
22
|
+
import { type DraftRefusal } from "../../report-model/draft-operations.js";
|
|
23
|
+
import { type OutlineEntry, type ReadableBlock } from "../../report-model/draft-read.js";
|
|
24
|
+
import { type FinishResult } from "../../report-model/draft-finish.js";
|
|
25
|
+
import { type DraftDocument } from "../../report-model/draft.js";
|
|
26
|
+
import type { ReportSnapshot } from "../../report-model/reference-resolver.js";
|
|
27
|
+
import { type Tool } from "../define-tool.js";
|
|
28
|
+
/** The flat destination fields. An anchor is `before` or `after`, and a place is `start` or `end`. */
|
|
29
|
+
declare const addBlockInput: z.ZodObject<{
|
|
30
|
+
block: z.ZodUnion<readonly [z.ZodType<import("../../report-model/draft.js").DraftBlock, unknown, z.core.$ZodTypeInternals<import("../../report-model/draft.js").DraftBlock, unknown>>, z.ZodUnknown]>;
|
|
31
|
+
parentId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
32
|
+
place: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
|
|
33
|
+
end: "end";
|
|
34
|
+
start: "start";
|
|
35
|
+
}>>>;
|
|
36
|
+
before: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
37
|
+
after: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
38
|
+
}, z.core.$strip>;
|
|
39
|
+
/**
|
|
40
|
+
* The change payload is a title for a section target, or a block for an atom target, and exactly one of
|
|
41
|
+
* the two. Both fields are absentable, because a section retitle names no block. Zod 4 treats a bare
|
|
42
|
+
* `z.unknown()` as a required key, thus an optional marker is what makes the retitle call representable.
|
|
43
|
+
*/
|
|
44
|
+
declare const changeBlockInput: z.ZodObject<{
|
|
45
|
+
targetId: z.ZodString;
|
|
46
|
+
title: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
47
|
+
block: z.ZodOptional<z.ZodUnion<readonly [z.ZodType<import("../../report-model/draft.js").DraftBlock, unknown, z.core.$ZodTypeInternals<import("../../report-model/draft.js").DraftBlock, unknown>>, z.ZodUnknown]>>;
|
|
48
|
+
}, z.core.$strip>;
|
|
49
|
+
declare const removeBlockInput: z.ZodObject<{
|
|
50
|
+
targetId: z.ZodString;
|
|
51
|
+
}, z.core.$strip>;
|
|
52
|
+
declare const moveBlockInput: z.ZodObject<{
|
|
53
|
+
targetId: z.ZodString;
|
|
54
|
+
parentId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
55
|
+
place: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
|
|
56
|
+
end: "end";
|
|
57
|
+
start: "start";
|
|
58
|
+
}>>>;
|
|
59
|
+
before: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
60
|
+
after: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
61
|
+
}, z.core.$strip>;
|
|
62
|
+
declare const readOutlineInput: z.ZodObject<{}, z.core.$strip>;
|
|
63
|
+
/** The read names its target with the same field name as each mutation, thus one id key serves them all. */
|
|
64
|
+
declare const readBlockInput: z.ZodObject<{
|
|
65
|
+
targetId: z.ZodString;
|
|
66
|
+
}, z.core.$strip>;
|
|
67
|
+
declare const setTitleInput: z.ZodObject<{
|
|
68
|
+
title: z.ZodString;
|
|
69
|
+
}, z.core.$strip>;
|
|
70
|
+
declare const finishDraftInput: z.ZodObject<{}, z.core.$strip>;
|
|
71
|
+
export type AddBlockInput = z.infer<typeof addBlockInput>;
|
|
72
|
+
export type ChangeBlockInput = z.infer<typeof changeBlockInput>;
|
|
73
|
+
export type RemoveBlockInput = z.infer<typeof removeBlockInput>;
|
|
74
|
+
export type MoveBlockInput = z.infer<typeof moveBlockInput>;
|
|
75
|
+
export type ReadOutlineInput = z.infer<typeof readOutlineInput>;
|
|
76
|
+
export type ReadBlockInput = z.infer<typeof readBlockInput>;
|
|
77
|
+
export type SetTitleInput = z.infer<typeof setTitleInput>;
|
|
78
|
+
export type FinishDraftInput = z.infer<typeof finishDraftInput>;
|
|
79
|
+
/** One container that an operation changed, and the child order inside it after the operation. */
|
|
80
|
+
export interface ChangedContainer {
|
|
81
|
+
/** The section that holds the children. It is absent when the container is the root. */
|
|
82
|
+
parentId?: string;
|
|
83
|
+
children: OutlineEntry[];
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* The closed set of tool-layer refusal reasons.
|
|
87
|
+
*
|
|
88
|
+
* `no-thread-scope` means that the scope of the call names no report thread. `absent-state` means that no
|
|
89
|
+
* report session exists for the thread, and it is permanent. `wrong-thread-type` means that the thread is
|
|
90
|
+
* not a report thread, and it is permanent. `scope-analysis-mismatch` means that the scope names one
|
|
91
|
+
* analysis and the thread belongs to another, and it is permanent. `stale-state` means that a concurrent
|
|
92
|
+
* turn landed first, and the agent must read the state again. `state-unavailable` means that the gateway
|
|
93
|
+
* cannot serve or store the state, and it is transient. The set is disjoint from the core
|
|
94
|
+
* `DraftRefusalReason`, thus a reader tells a core refusal from a tool-layer refusal by the reason alone.
|
|
95
|
+
*/
|
|
96
|
+
export type SessionRefusalReason = "no-thread-scope" | "absent-state" | "wrong-thread-type" | "scope-analysis-mismatch" | "stale-state" | "state-unavailable";
|
|
97
|
+
/**
|
|
98
|
+
* A refusal that the tool layer raises before the core runs.
|
|
99
|
+
*
|
|
100
|
+
* The core refuses a bad edit. This layer refuses a call that names no thread, a thread with no stored
|
|
101
|
+
* state, or a gateway that cannot give the state. It sits beside the core `DraftRefusal`, and it never
|
|
102
|
+
* widens the closed reason set of the core.
|
|
103
|
+
*/
|
|
104
|
+
export interface SessionRefusal {
|
|
105
|
+
reason: SessionRefusalReason;
|
|
106
|
+
detail: string;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* The result of a mutation tool. A refusal carries the typed reason, from the core or from the tool layer.
|
|
110
|
+
*
|
|
111
|
+
* A landing carries the child order of each container that it changed, and not the whole outline. A whole
|
|
112
|
+
* outline costs the size of the draft on every landing, thus composing a report of n blocks would spend
|
|
113
|
+
* n-squared outline entries of agent context to author it. Only the container that the operation touched
|
|
114
|
+
* can surprise the agent: it chose the id, and the rest of the tree did not move. `read_outline` stays
|
|
115
|
+
* the way to read the whole draft, and it costs one call when the agent wants one.
|
|
116
|
+
*
|
|
117
|
+
* A move across two containers reports both. An operation that changes no child order reports none.
|
|
118
|
+
*/
|
|
119
|
+
export type MutationResult = {
|
|
120
|
+
applied: true;
|
|
121
|
+
changed: ChangedContainer[];
|
|
122
|
+
} | {
|
|
123
|
+
applied: false;
|
|
124
|
+
refusal: DraftRefusal | SessionRefusal;
|
|
125
|
+
};
|
|
126
|
+
/** The result of `read_outline`. A load that gives no state refuses instead of an outline. */
|
|
127
|
+
export type OutlineResult = {
|
|
128
|
+
outline: OutlineEntry[];
|
|
129
|
+
} | {
|
|
130
|
+
refused: SessionRefusal;
|
|
131
|
+
};
|
|
132
|
+
/**
|
|
133
|
+
* The result of `read_block`. An absent block is an expected outcome, thus it stays in the ok channel. A
|
|
134
|
+
* load that gives no state refuses instead of a block.
|
|
135
|
+
*/
|
|
136
|
+
export type ReadBlockResult = {
|
|
137
|
+
found: true;
|
|
138
|
+
block: ReadableBlock;
|
|
139
|
+
} | {
|
|
140
|
+
found: false;
|
|
141
|
+
} | {
|
|
142
|
+
refused: SessionRefusal;
|
|
143
|
+
};
|
|
144
|
+
/** The result of `finish_draft`. A load that gives no state refuses instead of a finish outcome. */
|
|
145
|
+
export type FinishToolResult = FinishResult | {
|
|
146
|
+
refused: SessionRefusal;
|
|
147
|
+
};
|
|
148
|
+
/** The state of one report thread: the document under composition, and the frozen snapshot. */
|
|
149
|
+
export interface ReportSessionState {
|
|
150
|
+
readonly document: DraftDocument;
|
|
151
|
+
readonly snapshot: ReportSnapshot;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* The concurrency token that a load hands out and a persist compares against. It is the prior document
|
|
155
|
+
* that the load read, or `null` before the first document lands. The persist lands only when the row still
|
|
156
|
+
* holds it, thus a concurrent turn that landed first turns the next persist into a conflict.
|
|
157
|
+
*/
|
|
158
|
+
export type SessionStateToken = DraftDocument | null;
|
|
159
|
+
/**
|
|
160
|
+
* The outcome of a gateway load. `found` carries the state, the analysis that owns the thread, and the
|
|
161
|
+
* concurrency token. `absent` and `wrong-type` are permanent conditions, and `failed` is a transient fault
|
|
162
|
+
* that names its cause.
|
|
163
|
+
*/
|
|
164
|
+
export type SessionStateLoad = {
|
|
165
|
+
outcome: "found";
|
|
166
|
+
state: ReportSessionState;
|
|
167
|
+
analysisId: string;
|
|
168
|
+
token: SessionStateToken;
|
|
169
|
+
} | {
|
|
170
|
+
outcome: "absent";
|
|
171
|
+
} | {
|
|
172
|
+
outcome: "wrong-type";
|
|
173
|
+
detail: string;
|
|
174
|
+
} | {
|
|
175
|
+
outcome: "failed";
|
|
176
|
+
detail: string;
|
|
177
|
+
};
|
|
178
|
+
/** The outcome of a gateway persist. `conflict` means that a concurrent turn landed first. */
|
|
179
|
+
export type SessionStatePersist = {
|
|
180
|
+
outcome: "persisted";
|
|
181
|
+
} | {
|
|
182
|
+
outcome: "conflict";
|
|
183
|
+
} | {
|
|
184
|
+
outcome: "failed";
|
|
185
|
+
detail: string;
|
|
186
|
+
};
|
|
187
|
+
/**
|
|
188
|
+
* The session-state gateway that the tools read and write.
|
|
189
|
+
*
|
|
190
|
+
* The tool layer is the one consumer, thus the interface lives here. The interface speaks a plain
|
|
191
|
+
* discriminated value, not a `Result`, because the tools read the outcome as data. The runtime realizes
|
|
192
|
+
* the gateway over the durable store. A load gives the state, a typed absence, or a typed failure. A
|
|
193
|
+
* persist gives success, or a typed failure.
|
|
194
|
+
*/
|
|
195
|
+
export interface ReportSessionStateGateway {
|
|
196
|
+
load(threadId: string): Promise<SessionStateLoad>;
|
|
197
|
+
persist(threadId: string, document: DraftDocument, expected: SessionStateToken): Promise<SessionStatePersist>;
|
|
198
|
+
}
|
|
199
|
+
/** The thread of a call, its analysis, the loaded state, and the concurrency token that the persist compares against. */
|
|
200
|
+
export interface OpenedThread {
|
|
201
|
+
readonly threadId: string;
|
|
202
|
+
readonly analysisId: string;
|
|
203
|
+
readonly state: ReportSessionState;
|
|
204
|
+
readonly token: SessionStateToken;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Resolve the report thread of a call, and load its state through the gateway.
|
|
208
|
+
*
|
|
209
|
+
* The report thread and its analysis ride on the analysis scope. The thread id becomes one segment of a
|
|
210
|
+
* session directory, thus the safe-id check sits here beside the shape check: a scope whose id carries a
|
|
211
|
+
* separator or a traversal segment names no thread that a tool can write under.
|
|
212
|
+
*
|
|
213
|
+
* The stored analysis of the thread must match the scope. A mismatch reads one analysis's draft and writes
|
|
214
|
+
* into another analysis's workspace, thus the resolution refuses it with a permanent reason that names the
|
|
215
|
+
* two ids. A scope of a different kind, an unsafe id, an absent thread, a wrong thread type, and a gateway
|
|
216
|
+
* fault each refuse as a typed `SessionRefusal` too.
|
|
217
|
+
*
|
|
218
|
+
* The authoring tools and the preview tool share this one resolution, thus the two surfaces accept the
|
|
219
|
+
* same thread id and map a load outcome onto a refusal the same way.
|
|
220
|
+
*/
|
|
221
|
+
export declare function openReportThread(gateway: ReportSessionStateGateway, scope: Scope): Promise<Result<OpenedThread, SessionRefusal>>;
|
|
222
|
+
/** The eight authoring tools. */
|
|
223
|
+
export interface ReportAuthoringTools {
|
|
224
|
+
readonly add_block: Tool<AddBlockInput, MutationResult>;
|
|
225
|
+
readonly change_block: Tool<ChangeBlockInput, MutationResult>;
|
|
226
|
+
readonly remove_block: Tool<RemoveBlockInput, MutationResult>;
|
|
227
|
+
readonly move_block: Tool<MoveBlockInput, MutationResult>;
|
|
228
|
+
readonly set_title: Tool<SetTitleInput, MutationResult>;
|
|
229
|
+
readonly read_outline: Tool<ReadOutlineInput, OutlineResult>;
|
|
230
|
+
readonly read_block: Tool<ReadBlockInput, ReadBlockResult>;
|
|
231
|
+
readonly finish_draft: Tool<FinishDraftInput, FinishToolResult>;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Make the eight authoring tools over a session-state gateway.
|
|
235
|
+
*
|
|
236
|
+
* Each tool reads the thread id from the scope of the call, and it loads the state of that thread through
|
|
237
|
+
* the gateway. Thus one factory serves every thread, and two threads never share one draft. A mutation
|
|
238
|
+
* persists the new document before it reports `applied: true`, thus a reported landing is never lost.
|
|
239
|
+
*/
|
|
240
|
+
export declare function createReportAuthoringTools(gateway: ReportSessionStateGateway): ReportAuthoringTools;
|
|
241
|
+
export {};
|