@inflexa-ai/harness 0.14.2 → 0.15.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/dist/agents/conversation-agent.d.ts +7 -0
- package/dist/agents/conversation-agent.js +5 -3
- package/dist/agents/sandbox/drug-repurposing-agent.js +5 -1
- package/dist/agents/sandbox/immune-profiling-agent.js +4 -1
- package/dist/app/synthesize-run.d.ts +3 -0
- package/dist/app/synthesize-run.js +2 -1
- package/dist/billing/noop-usage-recorder.d.ts +7 -0
- package/dist/billing/noop-usage-recorder.js +10 -0
- package/dist/billing/usage-recorder.d.ts +63 -0
- package/dist/billing/usage-recorder.js +15 -0
- package/dist/contracts/chat-events.d.ts +44 -3
- package/dist/contracts/chat-parts.d.ts +38 -2
- package/dist/contracts/chat-parts.js +1 -1
- package/dist/contracts/data-profile.d.ts +26 -0
- package/dist/contracts/data-profile.js +26 -0
- package/dist/contracts/index.d.ts +3 -1
- package/dist/contracts/index.js +1 -0
- package/dist/contracts/message.d.ts +21 -1
- package/dist/contracts/part-registry.js +1 -0
- package/dist/contracts/schemas/chat-events.d.ts +48 -2
- package/dist/contracts/schemas/chat-events.js +8 -1
- package/dist/contracts/schemas/chat-parts.d.ts +46 -3
- package/dist/contracts/schemas/chat-parts.js +13 -0
- package/dist/contracts/schemas/index.d.ts +2 -1
- package/dist/contracts/schemas/index.js +2 -1
- package/dist/contracts/schemas/usage.d.ts +11 -0
- package/dist/contracts/schemas/usage.js +18 -0
- package/dist/contracts/usage.d.ts +51 -0
- package/dist/contracts/usage.js +41 -0
- package/dist/execution/artifact-metadata.d.ts +3 -0
- package/dist/execution/artifact-metadata.js +1 -0
- package/dist/execution/dbos-workflow-purger.d.ts +30 -0
- package/dist/execution/dbos-workflow-purger.js +193 -0
- package/dist/execution/post-step-pipeline.d.ts +3 -0
- package/dist/execution/post-step-pipeline.js +2 -0
- package/dist/execution/reconcile-manifest.js +28 -15
- package/dist/execution/report-runner.d.ts +16 -0
- package/dist/execution/report-runner.js +4 -0
- package/dist/execution/run-synthesis.d.ts +3 -0
- package/dist/execution/run-synthesis.js +2 -0
- package/dist/execution/step-summary.d.ts +3 -0
- package/dist/execution/step-summary.js +1 -0
- package/dist/execution/workflow-purger.d.ts +38 -0
- package/dist/execution/workflow-purger.js +24 -0
- package/dist/index.d.ts +24 -2
- package/dist/index.js +27 -0
- package/dist/lib/metrics.js +2 -1
- package/dist/loop/metrics.d.ts +18 -0
- package/dist/loop/metrics.js +18 -1
- package/dist/loop/run-agent.d.ts +35 -0
- package/dist/loop/run-agent.js +149 -23
- package/dist/loop/run-to-terminal.d.ts +5 -2
- package/dist/loop/run-to-terminal.js +36 -2
- package/dist/loop/tool-detail.d.ts +54 -0
- package/dist/loop/tool-detail.js +105 -0
- package/dist/loop/tool-outcome.d.ts +21 -0
- package/dist/loop/tool-outcome.js +25 -0
- package/dist/loop/types.d.ts +15 -1
- package/dist/memory/content-to-cortex.d.ts +28 -4
- package/dist/memory/content-to-cortex.js +70 -14
- package/dist/memory/thread-history.d.ts +21 -1
- package/dist/memory/thread-history.js +29 -7
- package/dist/memory/thread-store.d.ts +65 -8
- package/dist/memory/thread-store.js +81 -17
- package/dist/prompts/sandbox/bulk-transcriptomics-agent.d.ts +1 -1
- package/dist/prompts/sandbox/bulk-transcriptomics-agent.js +17 -13
- package/dist/prompts/sandbox/chromatin-agent.d.ts +1 -1
- package/dist/prompts/sandbox/chromatin-agent.js +45 -54
- package/dist/prompts/sandbox/genomic-variant-agent.d.ts +1 -1
- package/dist/prompts/sandbox/genomic-variant-agent.js +39 -37
- package/dist/prompts/sandbox-standards.d.ts +1 -1
- package/dist/prompts/sandbox-standards.js +21 -2
- package/dist/provenance/collector.d.ts +5 -3
- package/dist/provenance/collector.js +5 -3
- package/dist/providers/ai-sdk.js +91 -16
- package/dist/providers/streaming-chat.js +5 -0
- package/dist/providers/types.d.ts +23 -0
- package/dist/providers/types.js +1 -0
- package/dist/reference-data/catalog.js +536 -0
- package/dist/runtime/assemble.d.ts +25 -8
- package/dist/runtime/assemble.js +7 -4
- package/dist/sandbox/sandbox-step-translate.d.ts +22 -1
- package/dist/sandbox/sandbox-step-translate.js +23 -36
- package/dist/schemas/run-synthesis.d.ts +2 -2
- package/dist/state/index.d.ts +2 -0
- package/dist/state/index.js +3 -0
- package/dist/state/init.js +28 -0
- package/dist/state/purge-analysis.d.ts +74 -0
- package/dist/state/purge-analysis.js +205 -0
- package/dist/state/vector-store.d.ts +6 -0
- package/dist/state/vector-store.js +22 -2
- package/dist/tasks/data-profile-activity.d.ts +14 -2
- package/dist/tasks/data-profile-activity.js +1 -1
- package/dist/tasks/data-profile.d.ts +3 -0
- package/dist/tasks/data-profile.js +9 -3
- package/dist/tools/bio/pubmed.js +15 -0
- package/dist/tools/bio/search-gene.js +12 -0
- package/dist/tools/define-tool.d.ts +41 -3
- package/dist/tools/define-tool.js +4 -1
- package/dist/tools/detail-resolver.d.ts +35 -0
- package/dist/tools/detail-resolver.js +39 -0
- package/dist/tools/execute-analysis.js +3 -0
- package/dist/tools/iterate-report.d.ts +3 -0
- package/dist/tools/iterate-report.js +3 -0
- package/dist/tools/memory/update-working-memory.js +8 -0
- package/dist/tools/research/generate-analogy-report.d.ts +3 -0
- package/dist/tools/research/generate-analogy-report.js +6 -0
- package/dist/tools/research/generate-plan.d.ts +3 -0
- package/dist/tools/research/generate-plan.js +6 -0
- package/dist/tools/research/inspect-run.js +4 -0
- package/dist/tools/research/literature-reviewer.d.ts +3 -0
- package/dist/tools/research/literature-reviewer.js +6 -0
- package/dist/tools/workspace/edit-file.js +2 -0
- package/dist/tools/workspace/execute-command.js +25 -0
- package/dist/tools/workspace/grep.js +3 -0
- package/dist/tools/workspace/list-files.js +2 -0
- package/dist/tools/workspace/read-file.js +7 -0
- package/dist/tools/workspace/workspace-search.js +1 -0
- package/dist/tools/workspace/write-file.js +3 -0
- package/dist/workflows/execute-analysis.d.ts +7 -0
- package/dist/workflows/execute-analysis.js +31 -2
- package/dist/workflows/execute-target-assessment.d.ts +3 -0
- package/dist/workflows/sandbox-step.d.ts +23 -0
- package/dist/workflows/sandbox-step.js +33 -2
- package/dist/workflows/target-assessment/lib/clinical-consequence-annotator.d.ts +3 -0
- package/dist/workflows/target-assessment/lib/clinical-consequence-annotator.js +1 -0
- package/package.json +1 -1
package/dist/providers/ai-sdk.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { generateText, streamText } from "ai";
|
|
1
|
+
import { generateText, streamText, wrapLanguageModel } from "ai";
|
|
2
2
|
import { createAnthropic } from "@ai-sdk/anthropic";
|
|
3
3
|
import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
|
|
4
4
|
import { APICallError } from "@ai-sdk/provider";
|
|
@@ -222,6 +222,10 @@ function createRetry(signal, logger) {
|
|
|
222
222
|
* vendor's own snake_case.
|
|
223
223
|
*
|
|
224
224
|
* `inputTokens` is the total billed prefix, cache reads included.
|
|
225
|
+
*
|
|
226
|
+
* `reasoningTokens` rides the neutral `outputTokenDetails` beside the text
|
|
227
|
+
* count and is copied verbatim: providers disagree on whether reasoning tokens
|
|
228
|
+
* are already inside the output total, so the harness reconciles nothing.
|
|
225
229
|
*/
|
|
226
230
|
function toChatUsage(usage) {
|
|
227
231
|
if (usage === undefined)
|
|
@@ -231,22 +235,72 @@ function toChatUsage(usage) {
|
|
|
231
235
|
outputTokens: usage.outputTokens,
|
|
232
236
|
cacheCreationInputTokens: usage.inputTokenDetails?.cacheWriteTokens,
|
|
233
237
|
cacheReadInputTokens: usage.inputTokenDetails?.cacheReadTokens,
|
|
238
|
+
reasoningTokens: usage.outputTokenDetails?.reasoningTokens,
|
|
234
239
|
};
|
|
235
240
|
}
|
|
236
|
-
|
|
241
|
+
/** The id of the model bound into this provider — a bare id string is its own id. */
|
|
242
|
+
function requestedModelIdOf(model) {
|
|
243
|
+
return typeof model === "string" ? model : model.modelId;
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Capture the served model id at the raw model boundary, because that is the
|
|
247
|
+
* only place it is still distinguishable from the requested one: `generateText`
|
|
248
|
+
* and `streamText` both coalesce an unreported response model id to the bound
|
|
249
|
+
* model's own id, so reading `result.response.modelId` would silently republish
|
|
250
|
+
* the requested id as an endpoint's claim. A middleware sees the provider's
|
|
251
|
+
* result before that fallback applies, so "reported nothing" stays absent.
|
|
252
|
+
*
|
|
253
|
+
* Built per call, never per provider: one provider instance serves concurrent
|
|
254
|
+
* calls, and a shared mutable slot would hand one call another's answer. A bare
|
|
255
|
+
* model-id string has no wire result to observe, so it captures nothing.
|
|
256
|
+
*/
|
|
257
|
+
function captureServedModelId(model) {
|
|
258
|
+
if (typeof model === "string")
|
|
259
|
+
return { model, servedModelId: () => undefined };
|
|
260
|
+
let served;
|
|
261
|
+
const wrapped = wrapLanguageModel({
|
|
262
|
+
model,
|
|
263
|
+
middleware: {
|
|
264
|
+
wrapGenerate: async ({ doGenerate }) => {
|
|
265
|
+
const result = await doGenerate();
|
|
266
|
+
served = result.response?.modelId;
|
|
267
|
+
return result;
|
|
268
|
+
},
|
|
269
|
+
wrapStream: async ({ doStream }) => {
|
|
270
|
+
const result = await doStream();
|
|
271
|
+
return {
|
|
272
|
+
...result,
|
|
273
|
+
stream: result.stream.pipeThrough(new TransformStream({
|
|
274
|
+
transform(chunk, controller) {
|
|
275
|
+
if (chunk.type === "response-metadata" && chunk.modelId !== undefined)
|
|
276
|
+
served = chunk.modelId;
|
|
277
|
+
controller.enqueue(chunk);
|
|
278
|
+
},
|
|
279
|
+
})),
|
|
280
|
+
};
|
|
281
|
+
},
|
|
282
|
+
},
|
|
283
|
+
});
|
|
284
|
+
return { model: wrapped, servedModelId: () => served };
|
|
285
|
+
}
|
|
286
|
+
function responseFromMessages(input) {
|
|
287
|
+
const { messages, fallbackText, finishReason, rawFinishReason, requestedModelId, servedModelId } = input;
|
|
288
|
+
const usage = toChatUsage(input.usage);
|
|
237
289
|
const message = [...messages].reverse().find((m) => m.role === "assistant");
|
|
238
290
|
if (message === undefined) {
|
|
239
|
-
return {
|
|
240
|
-
message: { role: "assistant", content: fallbackText },
|
|
241
|
-
finishReason,
|
|
242
|
-
rawFinishReason,
|
|
243
|
-
usage: toChatUsage(usage),
|
|
244
|
-
};
|
|
291
|
+
return { message: { role: "assistant", content: fallbackText }, finishReason, rawFinishReason, usage, requestedModelId, servedModelId };
|
|
245
292
|
}
|
|
246
|
-
return { message, finishReason, rawFinishReason, usage
|
|
293
|
+
return { message, finishReason, rawFinishReason, usage, requestedModelId, servedModelId };
|
|
247
294
|
}
|
|
248
|
-
function responseFromGenerate(result) {
|
|
249
|
-
return responseFromMessages(
|
|
295
|
+
function responseFromGenerate(result, identity) {
|
|
296
|
+
return responseFromMessages({
|
|
297
|
+
messages: result.responseMessages,
|
|
298
|
+
fallbackText: result.text,
|
|
299
|
+
finishReason: result.finishReason,
|
|
300
|
+
rawFinishReason: result.rawFinishReason,
|
|
301
|
+
usage: result.usage,
|
|
302
|
+
...identity,
|
|
303
|
+
});
|
|
250
304
|
}
|
|
251
305
|
/**
|
|
252
306
|
* Drop empty text parts — and messages left with no content at all — before
|
|
@@ -279,17 +333,19 @@ export function createAiSdkProvider(deps) {
|
|
|
279
333
|
const capabilities = { toolCalling: deps.capabilities?.toolCalling ?? true };
|
|
280
334
|
const logger = (deps.logger ?? createNoopLogger()).named("providers.ai-sdk");
|
|
281
335
|
const maxOutputTokens = deps.maxOutputTokens ?? DEFAULT_MAX_OUTPUT_TOKENS;
|
|
336
|
+
const requestedModelId = requestedModelIdOf(deps.model);
|
|
282
337
|
routeSdkWarningsTo(logger);
|
|
283
338
|
function chat(req, session, signal) {
|
|
284
339
|
const run = async () => {
|
|
285
340
|
const retry = createRetry(signal, logger);
|
|
341
|
+
const capture = captureServedModelId(deps.model);
|
|
286
342
|
try {
|
|
287
343
|
const result = await retry(async () => {
|
|
288
344
|
// Attribution headers are time-limited; resolving them inside the
|
|
289
345
|
// retried closure keeps them fresh across a multi-minute window.
|
|
290
346
|
const headers = await resolveBillingHeaders(deps.resolveBilling, session);
|
|
291
347
|
return generateText({
|
|
292
|
-
model:
|
|
348
|
+
model: capture.model,
|
|
293
349
|
system: req.system,
|
|
294
350
|
messages: sanitizeMessages(req.messages),
|
|
295
351
|
tools: req.tools,
|
|
@@ -304,7 +360,7 @@ export function createAiSdkProvider(deps) {
|
|
|
304
360
|
providerOptions: req.providerOptions,
|
|
305
361
|
});
|
|
306
362
|
});
|
|
307
|
-
return ok(responseFromGenerate(result));
|
|
363
|
+
return ok(responseFromGenerate(result, { requestedModelId, servedModelId: capture.servedModelId() }));
|
|
308
364
|
}
|
|
309
365
|
catch (e) {
|
|
310
366
|
if (isAbortError(e) || signal?.aborted)
|
|
@@ -316,6 +372,7 @@ export function createAiSdkProvider(deps) {
|
|
|
316
372
|
}
|
|
317
373
|
async function* chatStream(req, session, signal) {
|
|
318
374
|
const retry = createRetry(signal, logger);
|
|
375
|
+
const capture = captureServedModelId(deps.model);
|
|
319
376
|
try {
|
|
320
377
|
// Retry covers only stream establishment: streamText defers wire errors
|
|
321
378
|
// to consumption, so a failure is not visible until the stream is read.
|
|
@@ -328,7 +385,7 @@ export function createAiSdkProvider(deps) {
|
|
|
328
385
|
const opened = await retry(async () => {
|
|
329
386
|
const headers = await resolveBillingHeaders(deps.resolveBilling, session);
|
|
330
387
|
const result = streamText({
|
|
331
|
-
model:
|
|
388
|
+
model: capture.model,
|
|
332
389
|
system: req.system,
|
|
333
390
|
messages: sanitizeMessages(req.messages),
|
|
334
391
|
tools: req.tools,
|
|
@@ -364,7 +421,15 @@ export function createAiSdkProvider(deps) {
|
|
|
364
421
|
return { kind: "streaming", result, iterator, firstDelta: first.value };
|
|
365
422
|
});
|
|
366
423
|
if (opened.kind === "completed") {
|
|
367
|
-
const response = responseFromMessages(
|
|
424
|
+
const response = responseFromMessages({
|
|
425
|
+
messages: opened.messages,
|
|
426
|
+
fallbackText: "",
|
|
427
|
+
finishReason: opened.finishReason,
|
|
428
|
+
rawFinishReason: opened.rawFinishReason,
|
|
429
|
+
usage: opened.usage,
|
|
430
|
+
requestedModelId,
|
|
431
|
+
servedModelId: capture.servedModelId(),
|
|
432
|
+
});
|
|
368
433
|
yield { type: "done", response };
|
|
369
434
|
return;
|
|
370
435
|
}
|
|
@@ -377,7 +442,17 @@ export function createAiSdkProvider(deps) {
|
|
|
377
442
|
text += next.value;
|
|
378
443
|
yield { type: "text-delta", text: next.value };
|
|
379
444
|
}
|
|
380
|
-
const response = responseFromMessages(
|
|
445
|
+
const response = responseFromMessages({
|
|
446
|
+
messages: await result.responseMessages,
|
|
447
|
+
fallbackText: text,
|
|
448
|
+
finishReason: await result.finishReason,
|
|
449
|
+
rawFinishReason: await result.rawFinishReason,
|
|
450
|
+
usage: await result.usage,
|
|
451
|
+
requestedModelId,
|
|
452
|
+
// Read after the drain: the metadata chunk carrying the served id
|
|
453
|
+
// reaches the capture only as the stream is consumed.
|
|
454
|
+
servedModelId: capture.servedModelId(),
|
|
455
|
+
});
|
|
381
456
|
yield { type: "done", response };
|
|
382
457
|
}
|
|
383
458
|
catch (e) {
|
|
@@ -67,6 +67,11 @@ export function createStreamingChat(provider, onText) {
|
|
|
67
67
|
// response is authoritative, so return it rather than the assembled deltas.
|
|
68
68
|
if (final !== undefined)
|
|
69
69
|
return ok(final);
|
|
70
|
+
// The partial carries no model identity and no usage: it is
|
|
71
|
+
// assembled from deltas rather than from a provider response, so
|
|
72
|
+
// nothing here reported which model answered or what it cost.
|
|
73
|
+
// Stamping the requested id would manufacture a claim the
|
|
74
|
+
// endpoint never made.
|
|
70
75
|
return ok({ message: { role: "assistant", content: partial }, finishReason: "aborted" });
|
|
71
76
|
}
|
|
72
77
|
return err(toProviderError(e, workload));
|
|
@@ -46,6 +46,11 @@ export type PromptCachePolicy = {
|
|
|
46
46
|
* seeds the cache (billed at a premium; it only pays for itself once a later
|
|
47
47
|
* call reads it back).
|
|
48
48
|
*
|
|
49
|
+
* `reasoningTokens` is exactly what the provider reported — never derived from,
|
|
50
|
+
* nor reconciled against, `outputTokens`. Whether reasoning tokens are counted
|
|
51
|
+
* inside the output total varies by provider, so any arithmetic between the two
|
|
52
|
+
* would be a guess dressed as a figure.
|
|
53
|
+
*
|
|
49
54
|
* Every field is optional: a provider that reports no usage at all, or reports
|
|
50
55
|
* totals without a cache breakdown, is legitimate. Absent means "not reported",
|
|
51
56
|
* never "zero".
|
|
@@ -55,6 +60,7 @@ export interface ChatUsage {
|
|
|
55
60
|
readonly outputTokens?: number;
|
|
56
61
|
readonly cacheCreationInputTokens?: number;
|
|
57
62
|
readonly cacheReadInputTokens?: number;
|
|
63
|
+
readonly reasoningTokens?: number;
|
|
58
64
|
}
|
|
59
65
|
export interface ChatResponse {
|
|
60
66
|
readonly message: Extract<ModelMessage, {
|
|
@@ -72,6 +78,23 @@ export interface ChatResponse {
|
|
|
72
78
|
readonly finishReason: FinishReason | "aborted";
|
|
73
79
|
readonly rawFinishReason?: string;
|
|
74
80
|
readonly usage?: ChatUsage;
|
|
81
|
+
/**
|
|
82
|
+
* The id of the model this provider instance is bound to — what the caller
|
|
83
|
+
* asked for. Absent when the binding names no id.
|
|
84
|
+
*/
|
|
85
|
+
readonly requestedModelId?: string;
|
|
86
|
+
/**
|
|
87
|
+
* The model id the provider itself reported as having answered. Absent
|
|
88
|
+
* whenever the provider reported none — it is NEVER filled in from
|
|
89
|
+
* `requestedModelId`, because a claim about which model answered is only
|
|
90
|
+
* worth anything when the endpoint actually made it.
|
|
91
|
+
*
|
|
92
|
+
* A value differing from `requestedModelId` is not an error: the pair exists
|
|
93
|
+
* so a consumer can observe an endpoint or proxy serving a different model
|
|
94
|
+
* version than the one configured. Treat the comparison as best-effort
|
|
95
|
+
* diagnostics, never as an invariant.
|
|
96
|
+
*/
|
|
97
|
+
readonly servedModelId?: string;
|
|
75
98
|
}
|
|
76
99
|
export type ChatStreamEvent = {
|
|
77
100
|
readonly type: "text-delta";
|