@inflexa-ai/harness 0.39.2 → 0.40.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 -3
- package/dist/agents/conversation-agent.d.ts +3 -0
- package/dist/agents/conversation-agent.js +13 -2
- package/dist/agents/report-session-agent.d.ts +3 -0
- package/dist/agents/report-session-agent.js +2 -0
- package/dist/agents/sandbox/cheminformatics-agent.js +0 -3
- package/dist/agents/sandbox/shared.d.ts +11 -2
- package/dist/agents/sandbox/shared.js +4 -0
- package/dist/app/chat-turn.d.ts +75 -12
- package/dist/app/chat-turn.js +149 -21
- package/dist/app/message-assembly.d.ts +16 -52
- package/dist/app/message-assembly.js +41 -68
- package/dist/app/run-activity.d.ts +4 -6
- package/dist/app/run-activity.js +7 -27
- package/dist/app/spawn-report-session.d.ts +6 -11
- package/dist/app/spawn-report-session.js +5 -6
- package/dist/app/synthesize-run.d.ts +3 -0
- package/dist/app/synthesize-run.js +1 -0
- package/dist/billing/usage-recorder.d.ts +3 -4
- package/dist/billing/usage-recorder.js +3 -4
- package/dist/contracts/chat-parts.d.ts +11 -1
- package/dist/contracts/chat-parts.js +1 -0
- package/dist/contracts/index.d.ts +1 -1
- package/dist/contracts/part-registry.js +1 -0
- package/dist/contracts/report-blocks.d.ts +8 -8
- package/dist/contracts/schemas/chat-parts.d.ts +32 -9
- package/dist/contracts/schemas/chat-parts.js +10 -0
- package/dist/execution/artifact-metadata.d.ts +26 -33
- package/dist/execution/artifact-metadata.js +44 -106
- package/dist/execution/post-step-pipeline.d.ts +23 -16
- package/dist/execution/post-step-pipeline.js +19 -21
- package/dist/execution/run-synthesis.d.ts +3 -0
- package/dist/execution/run-synthesis.js +11 -1
- package/dist/execution/step-summary.d.ts +21 -30
- package/dist/execution/step-summary.js +30 -57
- package/dist/index.d.ts +9 -8
- package/dist/index.js +15 -34
- package/dist/lib/zod-issues.js +2 -4
- package/dist/loop/compaction.d.ts +20 -0
- package/dist/loop/compaction.js +2 -0
- package/dist/loop/continue-agent.d.ts +40 -0
- package/dist/loop/continue-agent.js +38 -0
- package/dist/loop/metrics.d.ts +30 -22
- package/dist/loop/metrics.js +51 -22
- package/dist/loop/run-agent.d.ts +111 -13
- package/dist/loop/run-agent.js +467 -220
- package/dist/loop/run-to-terminal.d.ts +16 -17
- package/dist/loop/run-to-terminal.js +24 -35
- package/dist/loop/tool-mask.d.ts +23 -0
- package/dist/loop/tool-mask.js +46 -0
- package/dist/loop/tool-output.d.ts +48 -0
- package/dist/loop/tool-output.js +79 -0
- package/dist/loop/types.d.ts +6 -3
- package/dist/memory/ai-sdk-message-storage.d.ts +49 -2
- package/dist/memory/ai-sdk-message-storage.js +78 -2
- package/dist/memory/conversation-display-recorder.d.ts +6 -0
- package/dist/memory/conversation-display-recorder.js +64 -22
- package/dist/memory/conversation-display-replay.d.ts +5 -14
- package/dist/memory/conversation-display-replay.js +66 -32
- package/dist/memory/conversation-display-storage.d.ts +2 -1
- package/dist/memory/conversation-display-storage.js +2 -1
- package/dist/memory/conversation-view.d.ts +53 -0
- package/dist/memory/conversation-view.js +130 -0
- package/dist/memory/count-tokens.d.ts +5 -7
- package/dist/memory/count-tokens.js +7 -9
- package/dist/memory/thread-history.d.ts +74 -102
- package/dist/memory/thread-history.js +181 -246
- package/dist/memory/thread-store.d.ts +3 -3
- package/dist/memory/thread-store.js +7 -2
- package/dist/memory/tool-call-integrity.d.ts +15 -21
- package/dist/memory/tool-call-integrity.js +31 -38
- package/dist/memory/working-memory.d.ts +2 -5
- package/dist/memory/working-memory.js +2 -5
- package/dist/prompts/SOUL.d.ts +2 -2
- package/dist/prompts/SOUL.js +2 -7
- package/dist/prompts/analogical-reasoner.d.ts +1 -1
- package/dist/prompts/analogical-reasoner.js +16 -32
- package/dist/prompts/briefing.js +1 -1
- package/dist/prompts/compaction.d.ts +4 -0
- package/dist/prompts/compaction.js +24 -0
- package/dist/prompts/conversation.d.ts +1 -1
- package/dist/prompts/conversation.js +26 -35
- package/dist/prompts/execute-analysis/step-summary.js +7 -5
- package/dist/prompts/literature-reviewer.d.ts +1 -1
- package/dist/prompts/literature-reviewer.js +29 -34
- package/dist/prompts/planner.js +15 -29
- package/dist/prompts/report-session.d.ts +1 -1
- package/dist/prompts/report-session.js +2 -33
- package/dist/prompts/sandbox/bulk-transcriptomics-agent.d.ts +1 -1
- package/dist/prompts/sandbox/bulk-transcriptomics-agent.js +1 -2
- package/dist/prompts/sandbox/cheminformatics-agent.d.ts +1 -1
- package/dist/prompts/sandbox/cheminformatics-agent.js +10 -29
- package/dist/prompts/sandbox/chromatin-agent.d.ts +1 -1
- package/dist/prompts/sandbox/chromatin-agent.js +1 -2
- package/dist/prompts/sandbox/data-profiler.js +6 -3
- package/dist/prompts/sandbox/dna-methylation-agent.d.ts +1 -1
- package/dist/prompts/sandbox/dna-methylation-agent.js +2 -7
- package/dist/prompts/sandbox/drug-repurposing-agent.d.ts +1 -1
- package/dist/prompts/sandbox/drug-repurposing-agent.js +20 -24
- package/dist/prompts/sandbox/enrichment-agent.d.ts +1 -1
- package/dist/prompts/sandbox/enrichment-agent.js +3 -2
- package/dist/prompts/sandbox/genomic-variant-agent.d.ts +1 -1
- package/dist/prompts/sandbox/genomic-variant-agent.js +0 -2
- package/dist/prompts/sandbox/immune-profiling-agent.d.ts +1 -1
- package/dist/prompts/sandbox/immune-profiling-agent.js +7 -14
- package/dist/prompts/sandbox/metabolomics-agent.d.ts +1 -1
- package/dist/prompts/sandbox/metabolomics-agent.js +0 -2
- package/dist/prompts/sandbox/microbiome-agent.d.ts +1 -1
- package/dist/prompts/sandbox/microbiome-agent.js +14 -21
- package/dist/prompts/sandbox/multi-omics-integration-agent.d.ts +1 -1
- package/dist/prompts/sandbox/multi-omics-integration-agent.js +9 -19
- package/dist/prompts/sandbox/multimodal-sc-agent.d.ts +1 -1
- package/dist/prompts/sandbox/multimodal-sc-agent.js +4 -5
- package/dist/prompts/sandbox/network-agent.d.ts +1 -1
- package/dist/prompts/sandbox/network-agent.js +7 -8
- package/dist/prompts/sandbox/pkpd-clinical-response-agent.d.ts +1 -1
- package/dist/prompts/sandbox/pkpd-clinical-response-agent.js +19 -19
- package/dist/prompts/sandbox/proteomics-agent.d.ts +1 -1
- package/dist/prompts/sandbox/proteomics-agent.js +3 -4
- package/dist/prompts/sandbox/scientific-executor.d.ts +1 -1
- package/dist/prompts/sandbox/scientific-executor.js +7 -10
- package/dist/prompts/sandbox/single-cell-agent.d.ts +1 -1
- package/dist/prompts/sandbox/single-cell-agent.js +2 -4
- package/dist/prompts/sandbox/spatial-omics-agent.d.ts +1 -1
- package/dist/prompts/sandbox/spatial-omics-agent.js +3 -5
- package/dist/prompts/sandbox/statistical-modeling-agent.d.ts +1 -1
- package/dist/prompts/sandbox/statistical-modeling-agent.js +1 -1
- package/dist/prompts/sandbox/translational-safety-agent.d.ts +1 -1
- package/dist/prompts/sandbox/translational-safety-agent.js +10 -19
- package/dist/prompts/sandbox-standards.d.ts +7 -7
- package/dist/prompts/sandbox-standards.js +74 -76
- package/dist/prompts/synthesis-agent.d.ts +1 -1
- package/dist/prompts/synthesis-agent.js +16 -42
- package/dist/providers/ai-sdk.d.ts +39 -6
- package/dist/providers/ai-sdk.js +117 -18
- package/dist/providers/errors.d.ts +2 -0
- package/dist/providers/errors.js +5 -0
- package/dist/providers/prompt-cache.d.ts +43 -41
- package/dist/providers/prompt-cache.js +47 -41
- package/dist/providers/reasoning.d.ts +10 -21
- package/dist/providers/reasoning.js +10 -21
- package/dist/providers/types.d.ts +21 -5
- package/dist/report-model/authoring-grammar.d.ts +2 -2
- package/dist/runtime/assemble.d.ts +9 -7
- package/dist/runtime/assemble.js +7 -3
- package/dist/sandbox/create-sandbox.d.ts +2 -2
- package/dist/sandbox/submit-exec.d.ts +1 -1
- package/dist/schemas/artifact-manifest.d.ts +4 -4
- package/dist/state/init.js +39 -4
- package/dist/state/purge-analysis.js +4 -0
- package/dist/state/tool-outputs.d.ts +4 -0
- package/dist/state/tool-outputs.js +30 -0
- package/dist/tasks/data-profile.d.ts +3 -0
- package/dist/tasks/data-profile.js +2 -0
- package/dist/tools/ad-hoc-router.d.ts +8 -0
- package/dist/tools/ad-hoc-router.js +21 -2
- package/dist/tools/display/show-user.d.ts +1 -1
- package/dist/tools/execute-analysis.d.ts +3 -0
- package/dist/tools/execute-analysis.js +9 -1
- package/dist/tools/read-tool-output.d.ts +7 -0
- package/dist/tools/read-tool-output.js +130 -0
- package/dist/tools/research/generate-analogy-report.d.ts +10 -26
- package/dist/tools/research/generate-analogy-report.js +76 -163
- package/dist/tools/research/generate-plan.d.ts +3 -0
- package/dist/tools/research/generate-plan.js +4 -1
- package/dist/tools/research/literature-reviewer.d.ts +3 -0
- package/dist/tools/research/literature-reviewer.js +3 -0
- package/dist/tools/sandbox/report-blocker.d.ts +18 -5
- package/dist/tools/sandbox/report-blocker.js +54 -6
- package/dist/tools/sandbox/submit-file-metadata.d.ts +30 -0
- package/dist/tools/sandbox/submit-file-metadata.js +67 -0
- package/dist/tools/start-report-session.d.ts +1 -3
- package/dist/tools/start-report-session.js +0 -2
- package/dist/tools/workspace/execute-command.js +7 -4
- package/dist/tools/workspace/result-bounds.d.ts +4 -4
- package/dist/tools/workspace/result-bounds.js +6 -5
- package/dist/tools/workspace/workspace-search.d.ts +1 -1
- package/dist/workflows/execute-analysis.d.ts +3 -0
- package/dist/workflows/execute-analysis.js +1 -0
- package/dist/workflows/sandbox-step.d.ts +30 -9
- package/dist/workflows/sandbox-step.js +37 -8
- package/package.json +9 -9
- package/dist/providers/anthropic.d.ts +0 -25
- package/dist/providers/anthropic.js +0 -28
|
@@ -1,66 +1,33 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Chat-turn message assembly
|
|
2
|
+
* Chat-turn message assembly: the view of the latest compaction marker, the user message, and then the
|
|
3
|
+
* context records. A kind gets a new record only when the view holds none of that kind, or when the hash
|
|
4
|
+
* of its text differs. The root loop compacts the view past its budget.
|
|
3
5
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* [ ...loadRecent(threadId, budget) ← stable, cacheable prefix
|
|
7
|
-
* {user: cortex_analysis_state.context}, ← tail
|
|
8
|
-
* {user: runActivityContext}, ← tail
|
|
9
|
-
* {user: render(workingMemory)}, ← tail, `conversation` thread only
|
|
10
|
-
* {user: normalizeUnicode(redactSecrets(input))} ] ← tail
|
|
11
|
-
*
|
|
12
|
-
* `system + tools + history` is the cacheable prefix — it only extends
|
|
13
|
-
* turn-to-turn. Run activity, working memory, and analysis context go in the
|
|
14
|
-
* **tail** as `user` messages: they change every turn, so a system-message
|
|
15
|
-
* placement would bust the Anthropic cache prefix.
|
|
16
|
-
*
|
|
17
|
-
* A `report` thread does not get the working-memory tail. The spawn copies the
|
|
18
|
-
* working-memory render into the child transcript at the anchor. A live render
|
|
19
|
-
* sees state past that anchor, and that breaks the knowledge cap of a report
|
|
20
|
-
* session. The analysis context and the run activity stay on both thread types.
|
|
21
|
-
*
|
|
22
|
-
* The history window of a `report` thread also keeps the first turn. That turn
|
|
23
|
-
* is the seed, and it is the one record of the brief and of the copied render.
|
|
24
|
-
* The window evicts the oldest turn first, thus a long session would drop its
|
|
25
|
-
* own charter and keep only its tools. A `conversation` thread evicts as before,
|
|
26
|
-
* because its live tail carries the working memory on each turn.
|
|
27
|
-
*
|
|
28
|
-
* Sanitization (`redactSecrets`, `normalizeUnicode`) is applied **once**, to
|
|
29
|
-
* the new user input only — never to history, assistant messages, tool
|
|
30
|
-
* results, the analysis context, or the rendered working memory.
|
|
31
|
-
*
|
|
32
|
-
* The returned `userMessage` is the sanitized user input on its own — the
|
|
33
|
-
* route persists `[userMessage, ...loop output]` via `appendTurn`, so the
|
|
34
|
-
* tail injections (ephemeral, re-derived each turn) are never written to the
|
|
35
|
-
* thread store.
|
|
6
|
+
* The view of a `report` thread keeps the first turn, because that turn is the seed: the one record of
|
|
7
|
+
* the brief and of the copied working memory.
|
|
36
8
|
*/
|
|
37
9
|
import { createNoopLogger } from "../lib/console-logger.js";
|
|
38
10
|
import { unwrapOrThrow } from "../lib/result.js";
|
|
39
|
-
import {
|
|
11
|
+
import { contextRecordMessage, contextRecordOf } from "../memory/ai-sdk-message-storage.js";
|
|
12
|
+
import { answerUnansweredToolCalls } from "../memory/tool-call-integrity.js";
|
|
40
13
|
import { normalizeUnicode, redactSecrets } from "../input-sanitization.js";
|
|
41
14
|
/**
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
* the three tail messages, and the output budget.
|
|
45
|
-
*/
|
|
46
|
-
export const DEFAULT_HISTORY_TOKEN_BUDGET = 120_000;
|
|
47
|
-
/**
|
|
48
|
-
* Assemble the message array for one chat turn. Async — it reads the history
|
|
49
|
-
* window and renders working memory.
|
|
15
|
+
* Assemble the message array for one chat turn. Async — it reads the view of
|
|
16
|
+
* the thread and renders working memory.
|
|
50
17
|
*/
|
|
51
18
|
export async function assembleMessages(args) {
|
|
52
|
-
const
|
|
53
|
-
const history = unwrapOrThrow(await args.history.loadRecent(args.threadId, budget, { keepFirstTurn: args.threadType === "report" }));
|
|
19
|
+
const history = unwrapOrThrow(await args.history.loadRecent(args.threadId, { keepFirstTurn: args.threadType === "report" }));
|
|
54
20
|
// Read-side safety net for the wire contract: every tool call carries a
|
|
55
21
|
// result. The loop upholds it at every exit, but the store outlives any one
|
|
56
22
|
// writer — a row an older build wrote, or a hand-edited database, can carry
|
|
57
23
|
// an unanswered call, and the provider boundary then refuses the WHOLE
|
|
58
|
-
// transcript on every turn: the thread is wedged forever.
|
|
59
|
-
//
|
|
60
|
-
//
|
|
61
|
-
|
|
24
|
+
// transcript on every turn: the thread is wedged forever. The fix inserts the
|
|
25
|
+
// same not-run result the loop gives, in place, so no stored message changes
|
|
26
|
+
// and the prefix stays identical across turns. The warning is the only
|
|
27
|
+
// account a reader gets that the stored thread and the assembled one differ.
|
|
28
|
+
const repaired = answerUnansweredToolCalls(history);
|
|
62
29
|
if (repaired.length > 0) {
|
|
63
|
-
(args.logger ?? createNoopLogger()).named("assembly").warn("unanswered tool calls
|
|
30
|
+
(args.logger ?? createNoopLogger()).named("assembly").warn("unanswered tool calls answered in thread history", {
|
|
64
31
|
threadId: args.threadId,
|
|
65
32
|
toolCallIds: repaired.map((d) => d.toolCallId),
|
|
66
33
|
tools: repaired.map((d) => d.toolName),
|
|
@@ -71,27 +38,33 @@ export async function assembleMessages(args) {
|
|
|
71
38
|
role: "user",
|
|
72
39
|
content: normalizeUnicode(redactSecrets(args.userInput)),
|
|
73
40
|
};
|
|
74
|
-
const
|
|
75
|
-
|
|
41
|
+
const contextRecords = await contextRecordsFor(args, history);
|
|
42
|
+
return { messages: [...history, userMessage, ...contextRecords], userMessage, contextRecords };
|
|
43
|
+
}
|
|
44
|
+
/** The context records of one turn, in the order analysis context, run activity, working memory. */
|
|
45
|
+
export async function contextRecordsFor(args, history) {
|
|
46
|
+
const texts = [];
|
|
76
47
|
if (args.analysisContext && args.analysisContext.trim().length > 0) {
|
|
77
|
-
|
|
78
|
-
role: "user",
|
|
79
|
-
content: `[Analysis Context]\n${args.analysisContext}`,
|
|
80
|
-
});
|
|
48
|
+
texts.push(["analysis-context", `[Analysis Context]\n${args.analysisContext}`]);
|
|
81
49
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
content: args.runActivityContext,
|
|
85
|
-
});
|
|
86
|
-
// Working memory — agent-authored and trusted. A `conversation` thread
|
|
87
|
-
// always gets it, because the render names each section even when it is
|
|
88
|
-
// empty. A `report` thread reads the frozen copy in its seed message.
|
|
50
|
+
texts.push(["run-activity", args.runActivityContext]);
|
|
51
|
+
// A `report` thread reads the frozen copy in its seed, because a live render sees state past its anchor.
|
|
89
52
|
if (args.threadType !== "report") {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
53
|
+
const render = unwrapOrThrow(await args.workingMemory.render(args.analysisId));
|
|
54
|
+
// An emptied memory needs a record of its own, or the last full copy would read as the current state.
|
|
55
|
+
texts.push(["working-memory", `[Working Memory]\n${render.length > 0 ? render : "The working memory is empty."}`]);
|
|
56
|
+
}
|
|
57
|
+
const latestHash = new Map();
|
|
58
|
+
for (const message of history) {
|
|
59
|
+
const record = contextRecordOf(message);
|
|
60
|
+
if (record !== undefined)
|
|
61
|
+
latestHash.set(record.kind, record.hash);
|
|
62
|
+
}
|
|
63
|
+
const records = [];
|
|
64
|
+
for (const [kind, text] of texts) {
|
|
65
|
+
const record = contextRecordMessage(kind, text);
|
|
66
|
+
if (contextRecordOf(record)?.hash !== latestHash.get(kind))
|
|
67
|
+
records.push(record);
|
|
94
68
|
}
|
|
95
|
-
|
|
96
|
-
return { messages: [...history, ...tail], userMessage };
|
|
69
|
+
return records;
|
|
97
70
|
}
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* This is derived operational state, not memory: callers render it afresh for
|
|
5
|
-
* each turn and never persist it to the thread.
|
|
2
|
+
* The Run Activity record of a chat turn. The render holds no time of the call, thus a set of runs
|
|
3
|
+
* that does not change gives byte-identical text, and the turn stores no new record.
|
|
6
4
|
*/
|
|
7
5
|
import type { RunPage } from "../state/runs.js";
|
|
8
6
|
/** Maximum detailed run rows paid into every conversation turn. */
|
|
9
7
|
export declare const RUN_ACTIVITY_DETAIL_LIMIT = 20;
|
|
10
|
-
/** Render the bounded run-activity snapshot
|
|
11
|
-
export declare function renderRunActivity(activity: RunPage
|
|
8
|
+
/** Render the bounded run-activity snapshot of a conversation turn. */
|
|
9
|
+
export declare function renderRunActivity(activity: RunPage): string;
|
|
12
10
|
/** Render an honest degraded state when the activity projection cannot be read. */
|
|
13
11
|
export declare function renderRunActivityUnavailable(): string;
|
package/dist/app/run-activity.js
CHANGED
|
@@ -1,36 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* This is derived operational state, not memory: callers render it afresh for
|
|
5
|
-
* each turn and never persist it to the thread.
|
|
2
|
+
* The Run Activity record of a chat turn. The render holds no time of the call, thus a set of runs
|
|
3
|
+
* that does not change gives byte-identical text, and the turn stores no new record.
|
|
6
4
|
*/
|
|
7
5
|
/** Maximum detailed run rows paid into every conversation turn. */
|
|
8
6
|
export const RUN_ACTIVITY_DETAIL_LIMIT = 20;
|
|
9
|
-
function
|
|
10
|
-
const startedMs = Date.parse(startedAt);
|
|
11
|
-
if (!Number.isFinite(startedMs))
|
|
12
|
-
return "unknown age";
|
|
13
|
-
const elapsedSeconds = Math.max(0, Math.floor((nowMs - startedMs) / 1_000));
|
|
14
|
-
if (elapsedSeconds < 60)
|
|
15
|
-
return `${elapsedSeconds}s ago`;
|
|
16
|
-
const elapsedMinutes = Math.floor(elapsedSeconds / 60);
|
|
17
|
-
if (elapsedMinutes < 60)
|
|
18
|
-
return `${elapsedMinutes}m ago`;
|
|
19
|
-
const elapsedHours = Math.floor(elapsedMinutes / 60);
|
|
20
|
-
if (elapsedHours < 24)
|
|
21
|
-
return `${elapsedHours}h ago`;
|
|
22
|
-
return `${Math.floor(elapsedHours / 24)}d ago`;
|
|
23
|
-
}
|
|
24
|
-
function renderRows(label, rows, nowMs) {
|
|
7
|
+
function renderRows(label, rows) {
|
|
25
8
|
if (rows.length === 0)
|
|
26
9
|
return [];
|
|
27
|
-
return [
|
|
28
|
-
`${label}:`,
|
|
29
|
-
...rows.map((run) => `- runId: ${run.runId} | planId: ${run.planId ?? "none"} | startedAt: ${run.startedAt} | started: ${compactAge(run.startedAt, nowMs)}`),
|
|
30
|
-
];
|
|
10
|
+
return [`${label}:`, ...rows.map((run) => `- runId: ${run.runId} | planId: ${run.planId ?? "none"} | startedAt: ${run.startedAt}`)];
|
|
31
11
|
}
|
|
32
|
-
/** Render the bounded run-activity snapshot
|
|
33
|
-
export function renderRunActivity(activity
|
|
12
|
+
/** Render the bounded run-activity snapshot of a conversation turn. */
|
|
13
|
+
export function renderRunActivity(activity) {
|
|
34
14
|
const lines = ["[Run Activity]"];
|
|
35
15
|
if (activity.total === 0) {
|
|
36
16
|
lines.push("No runs are currently running or suspended.");
|
|
@@ -38,7 +18,7 @@ export function renderRunActivity(activity, nowMs = Date.now()) {
|
|
|
38
18
|
}
|
|
39
19
|
const running = activity.runs.filter((run) => run.status === "running");
|
|
40
20
|
const suspended = activity.runs.filter((run) => run.status === "suspended_insufficient_funds");
|
|
41
|
-
lines.push(...renderRows("Running", running
|
|
21
|
+
lines.push(...renderRows("Running", running), ...renderRows("Suspended", suspended));
|
|
42
22
|
const omitted = activity.total - activity.runs.length;
|
|
43
23
|
if (omitted > 0) {
|
|
44
24
|
lines.push(`Showing ${activity.runs.length} of ${activity.total} non-terminal runs; ${omitted} omitted. Use inspect_run to page the full list.`);
|
|
@@ -77,11 +77,10 @@ import type { EnsureSessionStateResult } from "./report-session-runtime.js";
|
|
|
77
77
|
* The set is closed. `parent_not_found` covers an absent parent and an archived
|
|
78
78
|
* one alike, because `getThread` filters the tombstone and a spawn into hidden
|
|
79
79
|
* state is not permitted. `parent_not_a_conversation` keeps the tree flat: a
|
|
80
|
-
* report session cannot spawn another. `
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
* endpoint. It carries the line that explains the absent capability.
|
|
80
|
+
* report session cannot spawn another. `no_browser` refuses every spawn under
|
|
81
|
+
* a composition that gives no route to a look: no eyes seam, no capture seam,
|
|
82
|
+
* and no configured browser endpoint. It carries the line that explains the
|
|
83
|
+
* absent capability.
|
|
85
84
|
*/
|
|
86
85
|
export type SpawnRefusal = {
|
|
87
86
|
readonly type: "no_browser";
|
|
@@ -97,10 +96,6 @@ export type SpawnRefusal = {
|
|
|
97
96
|
readonly op: string;
|
|
98
97
|
readonly parentThreadId: string;
|
|
99
98
|
readonly threadType: ThreadType;
|
|
100
|
-
} | {
|
|
101
|
-
readonly type: "empty_parent_transcript";
|
|
102
|
-
readonly op: string;
|
|
103
|
-
readonly parentThreadId: string;
|
|
104
99
|
};
|
|
105
100
|
/** The paging inputs `listReportSessions` forwards to the thread listing. */
|
|
106
101
|
export interface ReportSessionPaging {
|
|
@@ -237,8 +232,8 @@ export interface ReportSessionSpawn {
|
|
|
237
232
|
* result on the ok channel, thus the outcome vocabulary holds no pin arm.
|
|
238
233
|
*
|
|
239
234
|
* Refused with a `SpawnRefusal`, no row written: a composition with no
|
|
240
|
-
* eyes, an absent or archived parent, a parent that is not a
|
|
241
|
-
*
|
|
235
|
+
* eyes, an absent or archived parent, and a parent that is not a
|
|
236
|
+
* conversation. A store refusal (`DbError`,
|
|
242
237
|
* `ThreadInputError`) passes through unchanged. A failed seed write purges
|
|
243
238
|
* the child and returns the fault, thus no context-less thread survives.
|
|
244
239
|
*/
|
|
@@ -264,12 +264,11 @@ export function createReportSessionSpawn(deps) {
|
|
|
264
264
|
if (parent.threadType !== "conversation") {
|
|
265
265
|
return errAsync({ type: "parent_not_a_conversation", op: OP, parentThreadId, threadType: parent.threadType });
|
|
266
266
|
}
|
|
267
|
-
return history.latestSeq(parentThreadId).andThen((
|
|
268
|
-
//
|
|
269
|
-
//
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
}
|
|
267
|
+
return history.latestSeq(parentThreadId).andThen((latest) => {
|
|
268
|
+
// A turn appends after its loop, thus the first ask of a chat finds
|
|
269
|
+
// no row. The seed and the tail carry the context, not the parent
|
|
270
|
+
// transcript. `-1` is the point before seq 0.
|
|
271
|
+
const anchor = latest ?? -1;
|
|
273
272
|
// `total`, not the page length: N counts every existing report child,
|
|
274
273
|
// not the count on one page. Two concurrent spawns can compose one N.
|
|
275
274
|
// The result is two titles a user renames, and no identifier collides.
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
import type { Pool } from "pg";
|
|
18
18
|
import type { SynthesisPhase } from "@inflexa-ai/harness/contracts/chat-parts.js";
|
|
19
19
|
import type { RunSession } from "../auth/types.js";
|
|
20
|
+
import type { ToolOutputStore } from "../loop/tool-output.js";
|
|
20
21
|
import type { EmitFn } from "../loop/types.js";
|
|
21
22
|
import type { ChatProvider, EmbeddingProvider } from "../providers/types.js";
|
|
22
23
|
import type { BioToolKeys } from "../tools/bio/keys.js";
|
|
@@ -43,6 +44,8 @@ export interface SynthesizeRunDeps {
|
|
|
43
44
|
readonly citationResolver: CitationResolver;
|
|
44
45
|
/** LLM usage-accounting seam for the synthesizer loop; omitted falls back to the no-op recorder. */
|
|
45
46
|
readonly usageRecorder?: UsageRecorder;
|
|
47
|
+
/** The store of the synthesizer and reviewer loops and of their read tools. */
|
|
48
|
+
readonly toolOutputStore?: ToolOutputStore;
|
|
46
49
|
}
|
|
47
50
|
/** Optional fields for a progress update, mirroring the wire part. */
|
|
48
51
|
export interface SynthesisProgressExtra {
|
|
@@ -6,10 +6,9 @@
|
|
|
6
6
|
* telemetry every completed LLM call produces. The harness names no storage or
|
|
7
7
|
* display technology — it emits records; the embedder decides where they land.
|
|
8
8
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* bags. OSS default: `createNoopUsageRecorder` (`./noop-usage-recorder.ts`).
|
|
9
|
+
* Delivery sites: the loop's `accountForChatCall`, and the two direct
|
|
10
|
+
* `provider.chat` callers outside a loop — the ad hoc router and the analogy
|
|
11
|
+
* conversion. OSS default: `createNoopUsageRecorder` (`./noop-usage-recorder.ts`).
|
|
13
12
|
*/
|
|
14
13
|
import type { ResultAsync } from "neverthrow";
|
|
15
14
|
import type { Scope } from "../auth/types.js";
|
|
@@ -6,9 +6,8 @@
|
|
|
6
6
|
* telemetry every completed LLM call produces. The harness names no storage or
|
|
7
7
|
* display technology — it emits records; the embedder decides where they land.
|
|
8
8
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* bags. OSS default: `createNoopUsageRecorder` (`./noop-usage-recorder.ts`).
|
|
9
|
+
* Delivery sites: the loop's `accountForChatCall`, and the two direct
|
|
10
|
+
* `provider.chat` callers outside a loop — the ad hoc router and the analogy
|
|
11
|
+
* conversion. OSS default: `createNoopUsageRecorder` (`./noop-usage-recorder.ts`).
|
|
13
12
|
*/
|
|
14
13
|
export {};
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* Presentation: data-presentation (agent-synthesized content),
|
|
7
7
|
* data-plan (plan by id), data-file-reference (files by path)
|
|
8
8
|
* Approval: data-ask (a tool's pending user-approval prompt)
|
|
9
|
+
* Compaction: data-compaction (a compaction of the conversation thread)
|
|
9
10
|
* Run lifecycle: run-started, dag-state, run-completed, run-failed, run-synthesis,
|
|
10
11
|
* synthesis-progress
|
|
11
12
|
* Per-step live: step-activity, step-file-tree
|
|
@@ -382,4 +383,13 @@ export interface ReportRenderedPart {
|
|
|
382
383
|
/** The title of the rendered document. */
|
|
383
384
|
title?: string;
|
|
384
385
|
}
|
|
385
|
-
|
|
386
|
+
/** One compaction of the thread: `running`, then `done` or `failed` under the same id. A reload shows it as a divider. */
|
|
387
|
+
export interface CompactionPart {
|
|
388
|
+
type: "data-compaction";
|
|
389
|
+
id: string;
|
|
390
|
+
status: "running" | "done" | "failed";
|
|
391
|
+
tokensBefore: number;
|
|
392
|
+
tokensAfter?: number;
|
|
393
|
+
durationMs?: number;
|
|
394
|
+
}
|
|
395
|
+
export type CortexChatPart = PresentationPart | PlanPart | RunCardPart | FileReferencePart | AskPart | RunStartedPart | DagStatePart | StepActivityPart | StepFileTreePart | StepOutputPart | StepSummaryPart | StepUsagePart | StepBlockedPart | RunSynthesisPart | SynthesisProgressPart | RunCompletedPart | RunFailedPart | ChildSessionStartedPart | ReportRenderedPart | CompactionPart;
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* Presentation: data-presentation (agent-synthesized content),
|
|
7
7
|
* data-plan (plan by id), data-file-reference (files by path)
|
|
8
8
|
* Approval: data-ask (a tool's pending user-approval prompt)
|
|
9
|
+
* Compaction: data-compaction (a compaction of the conversation thread)
|
|
9
10
|
* Run lifecycle: run-started, dag-state, run-completed, run-failed, run-synthesis,
|
|
10
11
|
* synthesis-progress
|
|
11
12
|
* Per-step live: step-activity, step-file-tree
|
|
@@ -2,7 +2,7 @@ export { ORGAN_SYSTEMS, OrganSystemSchema, ORGAN_SYSTEM_LABELS, organSystemLabel
|
|
|
2
2
|
export type { OrganSystem } from "./organ-system.js";
|
|
3
3
|
export { SEVERITIES, SeveritySchema } from "./severity.js";
|
|
4
4
|
export type { Severity } from "./severity.js";
|
|
5
|
-
export type { PlanStep, PresentationContent, PresentationPart, PlanPart, RunCardPart, FileReferenceEntry, FileReferencePart, AskPart, RunStartedPart, StepStatus, DagStepState, DagStatePart, StepPhase, StepActivityPart, FileTreeEntry, StepFileTreePart, StepOutputFile, StepOutputPart, StepSummaryPart, StepUsagePart, StepBlockedPart, SynthesizedFinding, BiologicalTheme, RunSynthesisPart, SynthesisPhase, SynthesisProgressPart, RunCompletedFinding, RunCompletedPart, RunFailedPart, ChildSessionStartedPart, ReportRenderedPart, CortexChatPart, } from "./chat-parts.js";
|
|
5
|
+
export type { PlanStep, PresentationContent, PresentationPart, PlanPart, RunCardPart, FileReferenceEntry, FileReferencePart, AskPart, RunStartedPart, StepStatus, DagStepState, DagStatePart, StepPhase, StepActivityPart, FileTreeEntry, StepFileTreePart, StepOutputFile, StepOutputPart, StepSummaryPart, StepUsagePart, StepBlockedPart, SynthesizedFinding, BiologicalTheme, RunSynthesisPart, SynthesisPhase, SynthesisProgressPart, RunCompletedFinding, RunCompletedPart, RunFailedPart, ChildSessionStartedPart, ReportRenderedPart, CompactionPart, CortexChatPart, } from "./chat-parts.js";
|
|
6
6
|
export type { EventSource, TextDeltaEvent, ToolStartedEvent, ToolFinishedEvent, FinishEvent, ChatErrorEvent, CortexChatEvent } from "./chat-events.js";
|
|
7
7
|
export type { TokenUsageRollup } from "./usage.js";
|
|
8
8
|
export { DATA_PROFILE_RUN_LITERAL } from "./data-profile.js";
|
|
@@ -18,6 +18,7 @@ export const PART_REGISTRY = {
|
|
|
18
18
|
"data-run-failed": { emitter: "workflow", consumer: "sidebar", transient: false, reconciling: false },
|
|
19
19
|
"data-child-session-started": { emitter: "conversation", consumer: "conversation", transient: false, reconciling: false },
|
|
20
20
|
"data-report-rendered": { emitter: "conversation", consumer: "conversation", transient: false, reconciling: false },
|
|
21
|
+
"data-compaction": { emitter: "conversation", consumer: "conversation", transient: true, reconciling: true },
|
|
21
22
|
};
|
|
22
23
|
export function isTransient(type) {
|
|
23
24
|
return PART_REGISTRY[type].transient;
|
|
@@ -200,15 +200,15 @@ export declare const ChartAxesSchema: z.ZodObject<{
|
|
|
200
200
|
x: z.ZodOptional<z.ZodObject<{
|
|
201
201
|
title: z.ZodOptional<z.ZodString>;
|
|
202
202
|
scale: z.ZodOptional<z.ZodEnum<{
|
|
203
|
-
linear: "linear";
|
|
204
203
|
log: "log";
|
|
204
|
+
linear: "linear";
|
|
205
205
|
}>>;
|
|
206
206
|
}, z.core.$strict>>;
|
|
207
207
|
y: z.ZodOptional<z.ZodObject<{
|
|
208
208
|
title: z.ZodOptional<z.ZodString>;
|
|
209
209
|
scale: z.ZodOptional<z.ZodEnum<{
|
|
210
|
-
linear: "linear";
|
|
211
210
|
log: "log";
|
|
211
|
+
linear: "linear";
|
|
212
212
|
}>>;
|
|
213
213
|
}, z.core.$strict>>;
|
|
214
214
|
}, z.core.$strict>;
|
|
@@ -297,15 +297,15 @@ export declare const ChartCompositionSchema: z.ZodObject<{
|
|
|
297
297
|
x: z.ZodOptional<z.ZodObject<{
|
|
298
298
|
title: z.ZodOptional<z.ZodString>;
|
|
299
299
|
scale: z.ZodOptional<z.ZodEnum<{
|
|
300
|
-
linear: "linear";
|
|
301
300
|
log: "log";
|
|
301
|
+
linear: "linear";
|
|
302
302
|
}>>;
|
|
303
303
|
}, z.core.$strict>>;
|
|
304
304
|
y: z.ZodOptional<z.ZodObject<{
|
|
305
305
|
title: z.ZodOptional<z.ZodString>;
|
|
306
306
|
scale: z.ZodOptional<z.ZodEnum<{
|
|
307
|
-
linear: "linear";
|
|
308
307
|
log: "log";
|
|
308
|
+
linear: "linear";
|
|
309
309
|
}>>;
|
|
310
310
|
}, z.core.$strict>>;
|
|
311
311
|
}, z.core.$strict>>;
|
|
@@ -724,15 +724,15 @@ export declare const ChartBlockSchema: z.ZodObject<{
|
|
|
724
724
|
x: z.ZodOptional<z.ZodObject<{
|
|
725
725
|
title: z.ZodOptional<z.ZodString>;
|
|
726
726
|
scale: z.ZodOptional<z.ZodEnum<{
|
|
727
|
-
linear: "linear";
|
|
728
727
|
log: "log";
|
|
728
|
+
linear: "linear";
|
|
729
729
|
}>>;
|
|
730
730
|
}, z.core.$strict>>;
|
|
731
731
|
y: z.ZodOptional<z.ZodObject<{
|
|
732
732
|
title: z.ZodOptional<z.ZodString>;
|
|
733
733
|
scale: z.ZodOptional<z.ZodEnum<{
|
|
734
|
-
linear: "linear";
|
|
735
734
|
log: "log";
|
|
735
|
+
linear: "linear";
|
|
736
736
|
}>>;
|
|
737
737
|
}, z.core.$strict>>;
|
|
738
738
|
}, z.core.$strict>>;
|
|
@@ -1168,15 +1168,15 @@ export declare const ATOM_BLOCK_SCHEMAS: readonly [z.ZodObject<{
|
|
|
1168
1168
|
x: z.ZodOptional<z.ZodObject<{
|
|
1169
1169
|
title: z.ZodOptional<z.ZodString>;
|
|
1170
1170
|
scale: z.ZodOptional<z.ZodEnum<{
|
|
1171
|
-
linear: "linear";
|
|
1172
1171
|
log: "log";
|
|
1172
|
+
linear: "linear";
|
|
1173
1173
|
}>>;
|
|
1174
1174
|
}, z.core.$strict>>;
|
|
1175
1175
|
y: z.ZodOptional<z.ZodObject<{
|
|
1176
1176
|
title: z.ZodOptional<z.ZodString>;
|
|
1177
1177
|
scale: z.ZodOptional<z.ZodEnum<{
|
|
1178
|
-
linear: "linear";
|
|
1179
1178
|
log: "log";
|
|
1179
|
+
linear: "linear";
|
|
1180
1180
|
}>>;
|
|
1181
1181
|
}, z.core.$strict>>;
|
|
1182
1182
|
}, z.core.$strict>>;
|
|
@@ -204,7 +204,6 @@ export declare const DagStatePartSchema: z.ZodObject<{
|
|
|
204
204
|
export declare const StepPhaseSchema: z.ZodEnum<{
|
|
205
205
|
failed: "failed";
|
|
206
206
|
complete: "complete";
|
|
207
|
-
warning: "warning";
|
|
208
207
|
"sandbox-init": "sandbox-init";
|
|
209
208
|
executing: "executing";
|
|
210
209
|
"generating-metadata": "generating-metadata";
|
|
@@ -212,6 +211,7 @@ export declare const StepPhaseSchema: z.ZodEnum<{
|
|
|
212
211
|
indexing: "indexing";
|
|
213
212
|
persisting: "persisting";
|
|
214
213
|
retrying: "retrying";
|
|
214
|
+
warning: "warning";
|
|
215
215
|
}>;
|
|
216
216
|
export declare const StepActivityPartSchema: z.ZodObject<{
|
|
217
217
|
type: z.ZodLiteral<"data-step-activity">;
|
|
@@ -221,7 +221,6 @@ export declare const StepActivityPartSchema: z.ZodObject<{
|
|
|
221
221
|
phase: z.ZodEnum<{
|
|
222
222
|
failed: "failed";
|
|
223
223
|
complete: "complete";
|
|
224
|
-
warning: "warning";
|
|
225
224
|
"sandbox-init": "sandbox-init";
|
|
226
225
|
executing: "executing";
|
|
227
226
|
"generating-metadata": "generating-metadata";
|
|
@@ -229,6 +228,7 @@ export declare const StepActivityPartSchema: z.ZodObject<{
|
|
|
229
228
|
indexing: "indexing";
|
|
230
229
|
persisting: "persisting";
|
|
231
230
|
retrying: "retrying";
|
|
231
|
+
warning: "warning";
|
|
232
232
|
}>;
|
|
233
233
|
activity: z.ZodString;
|
|
234
234
|
}, z.core.$strip>;
|
|
@@ -260,9 +260,9 @@ export declare const StepOutputFileSchema: z.ZodObject<{
|
|
|
260
260
|
fileType: z.ZodEnum<{
|
|
261
261
|
output: "output";
|
|
262
262
|
summary: "summary";
|
|
263
|
-
log: "log";
|
|
264
|
-
figure: "figure";
|
|
265
263
|
script: "script";
|
|
264
|
+
figure: "figure";
|
|
265
|
+
log: "log";
|
|
266
266
|
notebook: "notebook";
|
|
267
267
|
}>;
|
|
268
268
|
description: z.ZodString;
|
|
@@ -279,9 +279,9 @@ export declare const StepOutputPartSchema: z.ZodObject<{
|
|
|
279
279
|
fileType: z.ZodEnum<{
|
|
280
280
|
output: "output";
|
|
281
281
|
summary: "summary";
|
|
282
|
-
log: "log";
|
|
283
|
-
figure: "figure";
|
|
284
282
|
script: "script";
|
|
283
|
+
figure: "figure";
|
|
284
|
+
log: "log";
|
|
285
285
|
notebook: "notebook";
|
|
286
286
|
}>;
|
|
287
287
|
description: z.ZodString;
|
|
@@ -473,6 +473,18 @@ export declare const ReportRenderedPartSchema: z.ZodObject<{
|
|
|
473
473
|
renderedAt: z.ZodString;
|
|
474
474
|
title: z.ZodOptional<z.ZodString>;
|
|
475
475
|
}, z.core.$strip>;
|
|
476
|
+
export declare const CompactionPartSchema: z.ZodObject<{
|
|
477
|
+
type: z.ZodLiteral<"data-compaction">;
|
|
478
|
+
id: z.ZodString;
|
|
479
|
+
status: z.ZodEnum<{
|
|
480
|
+
failed: "failed";
|
|
481
|
+
done: "done";
|
|
482
|
+
running: "running";
|
|
483
|
+
}>;
|
|
484
|
+
tokensBefore: z.ZodNumber;
|
|
485
|
+
tokensAfter: z.ZodOptional<z.ZodNumber>;
|
|
486
|
+
durationMs: z.ZodOptional<z.ZodNumber>;
|
|
487
|
+
}, z.core.$strip>;
|
|
476
488
|
export declare const CortexChatPartSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
477
489
|
type: z.ZodLiteral<"data-presentation">;
|
|
478
490
|
id: z.ZodString;
|
|
@@ -592,7 +604,6 @@ export declare const CortexChatPartSchema: z.ZodDiscriminatedUnion<[z.ZodObject<
|
|
|
592
604
|
phase: z.ZodEnum<{
|
|
593
605
|
failed: "failed";
|
|
594
606
|
complete: "complete";
|
|
595
|
-
warning: "warning";
|
|
596
607
|
"sandbox-init": "sandbox-init";
|
|
597
608
|
executing: "executing";
|
|
598
609
|
"generating-metadata": "generating-metadata";
|
|
@@ -600,6 +611,7 @@ export declare const CortexChatPartSchema: z.ZodDiscriminatedUnion<[z.ZodObject<
|
|
|
600
611
|
indexing: "indexing";
|
|
601
612
|
persisting: "persisting";
|
|
602
613
|
retrying: "retrying";
|
|
614
|
+
warning: "warning";
|
|
603
615
|
}>;
|
|
604
616
|
activity: z.ZodString;
|
|
605
617
|
}, z.core.$strip>, z.ZodObject<{
|
|
@@ -627,9 +639,9 @@ export declare const CortexChatPartSchema: z.ZodDiscriminatedUnion<[z.ZodObject<
|
|
|
627
639
|
fileType: z.ZodEnum<{
|
|
628
640
|
output: "output";
|
|
629
641
|
summary: "summary";
|
|
630
|
-
log: "log";
|
|
631
|
-
figure: "figure";
|
|
632
642
|
script: "script";
|
|
643
|
+
figure: "figure";
|
|
644
|
+
log: "log";
|
|
633
645
|
notebook: "notebook";
|
|
634
646
|
}>;
|
|
635
647
|
description: z.ZodString;
|
|
@@ -765,4 +777,15 @@ export declare const CortexChatPartSchema: z.ZodDiscriminatedUnion<[z.ZodObject<
|
|
|
765
777
|
id: z.ZodString;
|
|
766
778
|
renderedAt: z.ZodString;
|
|
767
779
|
title: z.ZodOptional<z.ZodString>;
|
|
780
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
781
|
+
type: z.ZodLiteral<"data-compaction">;
|
|
782
|
+
id: z.ZodString;
|
|
783
|
+
status: z.ZodEnum<{
|
|
784
|
+
failed: "failed";
|
|
785
|
+
done: "done";
|
|
786
|
+
running: "running";
|
|
787
|
+
}>;
|
|
788
|
+
tokensBefore: z.ZodNumber;
|
|
789
|
+
tokensAfter: z.ZodOptional<z.ZodNumber>;
|
|
790
|
+
durationMs: z.ZodOptional<z.ZodNumber>;
|
|
768
791
|
}, z.core.$strip>], "type">;
|
|
@@ -299,6 +299,15 @@ export const ReportRenderedPartSchema = z.object({
|
|
|
299
299
|
renderedAt: z.string(),
|
|
300
300
|
title: z.string().optional(),
|
|
301
301
|
});
|
|
302
|
+
// ── Compaction ──────────────────────────────────────────────────────
|
|
303
|
+
export const CompactionPartSchema = z.object({
|
|
304
|
+
type: z.literal("data-compaction"),
|
|
305
|
+
id: z.string(),
|
|
306
|
+
status: z.enum(["running", "done", "failed"]),
|
|
307
|
+
tokensBefore: z.number().int().nonnegative(),
|
|
308
|
+
tokensAfter: z.number().int().nonnegative().optional(),
|
|
309
|
+
durationMs: z.number().int().nonnegative().optional(),
|
|
310
|
+
});
|
|
302
311
|
// ── Union ───────────────────────────────────────────────────────────
|
|
303
312
|
export const CortexChatPartSchema = z.discriminatedUnion("type", [
|
|
304
313
|
PresentationPartSchema,
|
|
@@ -320,4 +329,5 @@ export const CortexChatPartSchema = z.discriminatedUnion("type", [
|
|
|
320
329
|
RunFailedPartSchema,
|
|
321
330
|
ChildSessionStartedPartSchema,
|
|
322
331
|
ReportRenderedPartSchema,
|
|
332
|
+
CompactionPartSchema,
|
|
323
333
|
]);
|