maka-agent 0.2.0-dev.31.20260913 → 0.2.0-dev.32.20260914
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/pi-transcript.js +3 -4
- package/native/runtime-host-windows-task-launcher/prebuilds/win32-x64/maka-runtime-host-task-launcher.exe +0 -0
- package/node_modules/@maka/core/dist/agent-graph-schedule.js +15 -4
- package/node_modules/@maka/core/dist/executor-id.js +22 -0
- package/node_modules/@maka/core/dist/external-session.js +18 -0
- package/node_modules/@maka/core/dist/model-call-usage-projection.js +0 -13
- package/node_modules/@maka/core/dist/runtime-event.js +19 -3
- package/node_modules/@maka/core/dist/session-send-projection.js +6 -3
- package/node_modules/@maka/core/dist/session.js +8 -2
- package/node_modules/@maka/core/dist/shell-run-result.js +1 -0
- package/node_modules/@maka/core/dist/shell-run.js +4 -0
- package/node_modules/@maka/core/dist/work-board.js +94 -1
- package/node_modules/@maka/core/package.json +1 -0
- package/node_modules/@maka/eval/dist/fleet-simulation.js +270 -0
- package/node_modules/@maka/eval/dist/fleet-store.js +243 -0
- package/node_modules/@maka/eval/dist/fleet-worker.js +125 -0
- package/node_modules/@maka/eval/dist/fleet.js +329 -0
- package/node_modules/@maka/eval/dist/index.js +3 -0
- package/node_modules/@maka/runtime/dist/agent-run.js +2 -17
- package/node_modules/@maka/runtime/dist/ai-sdk-compaction.js +6 -2
- package/node_modules/@maka/runtime/dist/ai-sdk-message-projection.js +36 -24
- package/node_modules/@maka/runtime/dist/ai-sdk-turn.js +257 -330
- package/node_modules/@maka/runtime/dist/background-task-health-tool.js +104 -0
- package/node_modules/@maka/runtime/dist/history-compaction.js +3 -1
- package/node_modules/@maka/runtime/dist/local-web-fetch.js +1 -1
- package/node_modules/@maka/runtime/dist/model-adapter.js +62 -53
- package/node_modules/@maka/runtime/dist/model-history.js +1 -5
- package/node_modules/@maka/runtime/dist/plugin-executor-backend.js +311 -0
- package/node_modules/@maka/runtime/dist/plugin-executor-service.js +344 -0
- package/node_modules/@maka/runtime/dist/provider-error-classification.js +7 -1
- package/node_modules/@maka/runtime/dist/provider-request-telemetry.js +35 -8
- package/node_modules/@maka/runtime/dist/runtime-event-backfill.js +7 -1
- package/node_modules/@maka/runtime/dist/runtime-event-read-model.js +1 -0
- package/node_modules/@maka/runtime/dist/runtime-invocation-route.js +49 -0
- package/node_modules/@maka/runtime/dist/runtime-kernel.js +72 -150
- package/node_modules/@maka/runtime/dist/runtime-read-model.js +0 -2
- package/node_modules/@maka/runtime/dist/session-event-runtime-mapper.js +3 -0
- package/node_modules/@maka/runtime/dist/session-manager.js +100 -58
- package/node_modules/@maka/runtime/dist/shell-run-manager.js +9 -3
- package/node_modules/@maka/runtime/dist/shell-run-tool-result.js +1 -0
- package/node_modules/@maka/runtime/dist/stream-graph-schedule-reconcile.js +1 -0
- package/node_modules/@maka/runtime/dist/stream-graph-supervisor-tools.js +26 -4
- package/node_modules/@maka/runtime/dist/subagent-tools.js +7 -0
- package/node_modules/@maka/runtime/dist/tool-runtime.js +45 -466
- package/node_modules/@maka/runtime/package.json +3 -0
- package/node_modules/@maka/runtime-host/dist/adapter/session-projector.js +7 -2
- package/node_modules/@maka/runtime-host/dist/client/session-catalog-summary.js +1 -0
- package/node_modules/@maka/runtime-host/dist/protocol/external-session.js +24 -3
- package/node_modules/@maka/runtime-host/dist/protocol/index.js +4 -1
- package/node_modules/@maka/runtime-host/dist/protocol/plugin-platform.js +42 -5
- package/node_modules/@maka/runtime-host/dist/protocol/session-catalog.js +31 -3
- package/node_modules/@maka/runtime-host/dist/protocol/session-continuity.js +6 -0
- package/node_modules/@maka/runtime-host/dist/server/child-agent-composition.js +1 -0
- package/node_modules/@maka/runtime-host/dist/server/execution-artifacts.js +1 -22
- package/node_modules/@maka/runtime-host/dist/server/execution-composition.js +54 -8
- package/node_modules/@maka/runtime-host/dist/server/external-session-coordinator.js +14 -1
- package/node_modules/@maka/runtime-host/dist/server/host-session-availability.js +10 -2
- package/node_modules/@maka/runtime-host/dist/server/plugin-platform-coordinator.js +6 -0
- package/node_modules/@maka/runtime-host/dist/server/plugin-platform.js +6 -0
- package/node_modules/@maka/runtime-host/dist/server/session-catalog-coordinator.js +56 -16
- package/node_modules/@maka/runtime-host/dist/server/session-continuity-coordinator.js +4 -3
- package/node_modules/@maka/runtime-host/dist/server/session-revision-coordinator.js +4 -0
- package/node_modules/@maka/runtime-host/dist/server/web-fetch-tool.js +37 -1
- package/node_modules/@maka/storage/dist/claude-code-session-adapter.js +450 -234
- package/node_modules/@maka/storage/dist/claude-code-transcript-lineage.js +106 -77
- package/node_modules/@maka/storage/dist/legacy-run-header.js +2 -2
- package/node_modules/@maka/storage/dist/model-call-usage-sql.js +1 -1
- package/node_modules/@maka/storage/dist/session-store.js +12 -2
- package/node_modules/@maka/storage/dist/sqlite-long-term-memory-store.js +86 -12
- package/node_modules/@maka/storage/dist/work-board-store.js +40 -1
- package/package.json +1 -1
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Licensed to the Apache Software Foundation (ASF) under one
|
|
3
|
+
* or more contributor license agreements. See the NOTICE file
|
|
4
|
+
* distributed with this work for additional information
|
|
5
|
+
* regarding copyright ownership. The ASF licenses this file
|
|
6
|
+
* to you under the Apache License, Version 2.0 (the
|
|
7
|
+
* "License"); you may not use this file except in compliance
|
|
8
|
+
* with the License. You may obtain a copy of the License at
|
|
9
|
+
*
|
|
10
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
*
|
|
12
|
+
* Unless required by applicable law or agreed to in writing,
|
|
13
|
+
* software distributed under the License is distributed on an
|
|
14
|
+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
15
|
+
* KIND, either express or implied. See the License for the
|
|
16
|
+
* specific language governing permissions and limitations
|
|
17
|
+
* under the License.
|
|
18
|
+
*/
|
|
19
|
+
import { z } from 'zod';
|
|
20
|
+
/**
|
|
21
|
+
* Produces an explicit two-axis result. A tracked process is never described
|
|
22
|
+
* as endpoint-ready unless the caller supplied a URL and the probe succeeded.
|
|
23
|
+
*/
|
|
24
|
+
export function buildBackgroundTaskHealthTool(reader, probe) {
|
|
25
|
+
return {
|
|
26
|
+
name: 'BackgroundTaskHealth',
|
|
27
|
+
displayName: 'Background task health',
|
|
28
|
+
categoryHint: 'web_read',
|
|
29
|
+
description: 'Check a tracked background task and an optional HTTP endpoint. Uses HEAD with one GET fallback for 405/501; discards the body. Reports HTTP status only, not browser loading or ownership of the listener. Redirects are not followed. Logs are omitted by default; use Read(ref) for full logs.',
|
|
30
|
+
parameters: z
|
|
31
|
+
.object({
|
|
32
|
+
ref: z.string().describe('The maka://runtime/background-tasks/<id> ref returned by Bash'),
|
|
33
|
+
include_logs: z.boolean().optional().describe('Include captured task logs in this report'),
|
|
34
|
+
url: z
|
|
35
|
+
.string()
|
|
36
|
+
.url()
|
|
37
|
+
.refine((value) => ['http:', 'https:'].includes(new URL(value).protocol), 'Health endpoint must use HTTP or HTTPS')
|
|
38
|
+
.optional()
|
|
39
|
+
.describe('The HTTP or HTTPS endpoint to probe'),
|
|
40
|
+
})
|
|
41
|
+
.strict(),
|
|
42
|
+
impl: async ({ ref, url, include_logs }, context) => {
|
|
43
|
+
const resource = await reader.readRuntimeResource(context.sessionId, ref, context.abortSignal);
|
|
44
|
+
if (!resource ||
|
|
45
|
+
typeof resource !== 'object' ||
|
|
46
|
+
Array.isArray(resource) ||
|
|
47
|
+
resource.kind !== 'shell_run') {
|
|
48
|
+
throw new Error('BackgroundTaskHealth requires a shell_run runtime resource');
|
|
49
|
+
}
|
|
50
|
+
const shell = resource;
|
|
51
|
+
const process = {
|
|
52
|
+
status: shell.status,
|
|
53
|
+
tracked: true,
|
|
54
|
+
startedAt: shell.startedAt,
|
|
55
|
+
updatedAt: shell.updatedAt,
|
|
56
|
+
...(shell.pid !== undefined ? { pid: shell.pid } : {}),
|
|
57
|
+
...(shell.completedAt !== undefined ? { completedAt: shell.completedAt } : {}),
|
|
58
|
+
...(shell.failureMessage !== undefined ? { failureMessage: shell.failureMessage } : {}),
|
|
59
|
+
...(include_logs && shell.output
|
|
60
|
+
? {
|
|
61
|
+
logs: shell.output.mode === 'pipes'
|
|
62
|
+
? { stdout: shell.output.stdout, stderr: shell.output.stderr }
|
|
63
|
+
: { screen: shell.output.screen, scrollback: shell.output.scrollback },
|
|
64
|
+
}
|
|
65
|
+
: {}),
|
|
66
|
+
};
|
|
67
|
+
if (!url)
|
|
68
|
+
return JSON.stringify({ process, endpoint: { state: 'not_checked' } });
|
|
69
|
+
let endpoint;
|
|
70
|
+
try {
|
|
71
|
+
endpoint = await probe.probe({
|
|
72
|
+
url,
|
|
73
|
+
sessionId: context.sessionId,
|
|
74
|
+
abortSignal: context.abortSignal,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
context.abortSignal.throwIfAborted();
|
|
79
|
+
return JSON.stringify({
|
|
80
|
+
process,
|
|
81
|
+
endpoint: {
|
|
82
|
+
state: 'unknown',
|
|
83
|
+
target: new URL(url).href,
|
|
84
|
+
error: error instanceof Error ? error.message : String(error),
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
return JSON.stringify({
|
|
89
|
+
process,
|
|
90
|
+
endpoint: {
|
|
91
|
+
state: 'checked',
|
|
92
|
+
httpStatus: endpoint.status,
|
|
93
|
+
elapsedMs: endpoint.elapsedMs,
|
|
94
|
+
target: new URL(url).href,
|
|
95
|
+
health: endpoint.status >= 200 && endpoint.status < 300
|
|
96
|
+
? 'healthy'
|
|
97
|
+
: endpoint.status < 400
|
|
98
|
+
? 'unknown'
|
|
99
|
+
: 'unhealthy',
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
}
|
|
@@ -120,7 +120,9 @@ function acceptedInputBoundary(events, invocations, route) {
|
|
|
120
120
|
if (event?.role !== 'model')
|
|
121
121
|
return false;
|
|
122
122
|
const opened = invocations.find((candidate) => candidate.runId === event.runId)?.opening.route;
|
|
123
|
-
if (opened?.provenance !== 'runtime' ||
|
|
123
|
+
if (opened?.provenance !== 'runtime' ||
|
|
124
|
+
opened.backendKind === 'plugin-executor' ||
|
|
125
|
+
opened.modelId !== route.modelId)
|
|
124
126
|
return false;
|
|
125
127
|
return opened.llmConnectionId === route.connectionId;
|
|
126
128
|
};
|
|
@@ -119,7 +119,7 @@ export function createLocalWebFetchExecutor(input) {
|
|
|
119
119
|
function responseLimitError() {
|
|
120
120
|
return new Error('WebFetch response exceeds the 5 MB response limit.');
|
|
121
121
|
}
|
|
122
|
-
function assertAllowedTarget(url) {
|
|
122
|
+
export function assertAllowedTarget(url) {
|
|
123
123
|
if (url.protocol !== 'http:' && url.protocol !== 'https:') {
|
|
124
124
|
throw new Error('WebFetch URL must use HTTP or HTTPS.');
|
|
125
125
|
}
|
|
@@ -101,17 +101,22 @@ export class ModelAdapter {
|
|
|
101
101
|
});
|
|
102
102
|
const { streamText, wrapLanguageModel } = ai;
|
|
103
103
|
const maxOutputTokens = selectedModelMaxOutputTokens(this.input.connection, this.input.modelId, this.input.providerOptions, this.runtime);
|
|
104
|
+
let settleAccounting;
|
|
105
|
+
const terminalModel = withProviderFinishBoundary(input.model, wrapLanguageModel);
|
|
104
106
|
const trackedModel = input.providerRequestTracker
|
|
105
107
|
? withProviderStreamTracking({
|
|
106
|
-
model:
|
|
108
|
+
model: terminalModel,
|
|
107
109
|
wrapLanguageModel,
|
|
108
110
|
tracker: input.providerRequestTracker,
|
|
109
111
|
abortSignal: input.abortSignal,
|
|
112
|
+
onAttempt: (settle) => {
|
|
113
|
+
settleAccounting = settle;
|
|
114
|
+
},
|
|
110
115
|
...(input.historyCompactBoundary
|
|
111
116
|
? { historyCompactBoundary: input.historyCompactBoundary }
|
|
112
117
|
: {}),
|
|
113
118
|
})
|
|
114
|
-
:
|
|
119
|
+
: terminalModel;
|
|
115
120
|
const usesOpenAiResponsesAdapter = hasOpenAiResponsesAdapter(this.runtime);
|
|
116
121
|
const providerToolName = (name) => usesOpenAiResponsesAdapter && name === TOOL_SEARCH_NAME ? TOOL_SEARCH_PROVIDER_NAME : name;
|
|
117
122
|
const runtimeToolName = (name) => usesOpenAiResponsesAdapter && name === TOOL_SEARCH_PROVIDER_NAME ? TOOL_SEARCH_NAME : name;
|
|
@@ -158,10 +163,6 @@ export class ModelAdapter {
|
|
|
158
163
|
providerOptions,
|
|
159
164
|
...(responsesLane ? { headers: { [OPENAI_RESPONSES_LANE_HEADER]: responsesLane } } : {}),
|
|
160
165
|
maxRetries: 0,
|
|
161
|
-
// Preserve the final request's Maka-owned message projection without
|
|
162
|
-
// retaining the provider request body. ProviderRequestTracker owns body
|
|
163
|
-
// capture; duplicating it here can retain large base64 image payloads.
|
|
164
|
-
include: { requestMessages: true },
|
|
165
166
|
// With no continuation predicate, streamText performs one provider step.
|
|
166
167
|
// Continuation belongs to the Runtime above this adapter.
|
|
167
168
|
abortSignal: input.abortSignal,
|
|
@@ -176,6 +177,9 @@ export class ModelAdapter {
|
|
|
176
177
|
requestMessages: fullMessages,
|
|
177
178
|
abortSignal: input.abortSignal,
|
|
178
179
|
runtimeToolName,
|
|
180
|
+
settleAccounting: async (outcome) => {
|
|
181
|
+
await settleAccounting?.(outcome);
|
|
182
|
+
},
|
|
179
183
|
});
|
|
180
184
|
}
|
|
181
185
|
/**
|
|
@@ -194,7 +198,6 @@ export class ModelAdapter {
|
|
|
194
198
|
const outcome = new Promise((resolve) => {
|
|
195
199
|
settleOutcome = resolve;
|
|
196
200
|
});
|
|
197
|
-
const request = { messages: continuation.requestMessages };
|
|
198
201
|
const events = {
|
|
199
202
|
async *[Symbol.asyncIterator]() {
|
|
200
203
|
let failure;
|
|
@@ -210,6 +213,10 @@ export class ModelAdapter {
|
|
|
210
213
|
chunk.type === 'step-finish') {
|
|
211
214
|
streamedRawFinishReason =
|
|
212
215
|
rawFinishReasonString(chunk.rawFinishReason) ?? streamedRawFinishReason;
|
|
216
|
+
streamedFinishReason = chunkFinishReason(chunk) ?? streamedFinishReason;
|
|
217
|
+
if (chunk.type === 'finish')
|
|
218
|
+
sawFinish = true;
|
|
219
|
+
continue;
|
|
213
220
|
}
|
|
214
221
|
if (isUnfinalizedPlaintextSummaryReasoningEnd(chunk, resolvedRuntime)) {
|
|
215
222
|
// The SDK emits this trailer from flush() when no
|
|
@@ -223,11 +230,6 @@ export class ModelAdapter {
|
|
|
223
230
|
for (const event of translateChunk(chunk, openAiChatReasoningTransportState, resolvedRuntime, continuation.runtimeToolName)) {
|
|
224
231
|
if (event.kind === 'error')
|
|
225
232
|
failure = event.failure;
|
|
226
|
-
if (event.kind === 'finish')
|
|
227
|
-
sawFinish = true;
|
|
228
|
-
if (event.kind === 'finish' || event.kind === 'step-finish') {
|
|
229
|
-
streamedFinishReason = event.finishReason ?? streamedFinishReason;
|
|
230
|
-
}
|
|
231
233
|
yield event;
|
|
232
234
|
}
|
|
233
235
|
}
|
|
@@ -239,6 +241,9 @@ export class ModelAdapter {
|
|
|
239
241
|
}
|
|
240
242
|
}
|
|
241
243
|
finally {
|
|
244
|
+
if (continuation.abortSignal.aborted) {
|
|
245
|
+
failure = normalizeProviderFailure(continuation.abortSignal.reason);
|
|
246
|
+
}
|
|
242
247
|
const [sdkUsage, sdkFinishReason] = await Promise.all([
|
|
243
248
|
sdk.usage.catch(() => undefined),
|
|
244
249
|
sdk.finishReason.catch(() => undefined),
|
|
@@ -263,7 +268,6 @@ export class ModelAdapter {
|
|
|
263
268
|
finishReason,
|
|
264
269
|
rawFinishReason,
|
|
265
270
|
usage,
|
|
266
|
-
request,
|
|
267
271
|
});
|
|
268
272
|
let deferredFailure;
|
|
269
273
|
if (sawUnfinalizedPlaintextSummary && settled.kind === 'completed') {
|
|
@@ -276,7 +280,6 @@ export class ModelAdapter {
|
|
|
276
280
|
finishReason,
|
|
277
281
|
rawFinishReason,
|
|
278
282
|
usage,
|
|
279
|
-
request,
|
|
280
283
|
});
|
|
281
284
|
}
|
|
282
285
|
try {
|
|
@@ -301,7 +304,12 @@ export class ModelAdapter {
|
|
|
301
304
|
}
|
|
302
305
|
}
|
|
303
306
|
finally {
|
|
304
|
-
|
|
307
|
+
try {
|
|
308
|
+
await continuation.settleAccounting(settled);
|
|
309
|
+
}
|
|
310
|
+
finally {
|
|
311
|
+
settleOutcome(settled);
|
|
312
|
+
}
|
|
305
313
|
}
|
|
306
314
|
if (deferredFailure) {
|
|
307
315
|
// Consumers may stop iterating at the first error. The outcome and
|
|
@@ -378,33 +386,32 @@ export class ModelAdapter {
|
|
|
378
386
|
}
|
|
379
387
|
}
|
|
380
388
|
export function settleModelStepOutcome(evidence) {
|
|
381
|
-
const { aborted, failure, sawFinish, finishReason, rawFinishReason, usage
|
|
389
|
+
const { aborted, failure, sawFinish, finishReason, rawFinishReason, usage } = evidence;
|
|
382
390
|
if (aborted || failure?.kind === 'abort') {
|
|
383
|
-
return failedStepOutcome(
|
|
384
|
-
normalizeProviderFailure(Object.assign(new Error('aborted'), { name: 'AbortError' })),
|
|
391
|
+
return failedStepOutcome(failure ??
|
|
392
|
+
normalizeProviderFailure(Object.assign(new Error('aborted'), { name: 'AbortError' })), usage);
|
|
385
393
|
}
|
|
386
394
|
if (failure) {
|
|
387
|
-
return failedStepOutcome(
|
|
395
|
+
return failedStepOutcome(failure, usage);
|
|
388
396
|
}
|
|
389
397
|
if (!sawFinish || finishReason === 'other' || finishReason === 'unknown') {
|
|
390
|
-
return failedStepOutcome(
|
|
398
|
+
return failedStepOutcome(modelStepFailure('stream_truncated', `Provider stream ended without finishing (${finishReason})`), usage);
|
|
391
399
|
}
|
|
392
400
|
if (finishReason === 'content-filter' || finishReason === 'error') {
|
|
393
401
|
const terminalFailure = finishReason === 'error'
|
|
394
402
|
? providerFinishFailure(rawFinishReason)
|
|
395
403
|
: modelStepFailure('unknown', 'Provider stopped the stream on a content filter');
|
|
396
|
-
return failedStepOutcome(
|
|
404
|
+
return failedStepOutcome(terminalFailure, usage);
|
|
397
405
|
}
|
|
398
406
|
return {
|
|
399
407
|
kind: 'completed',
|
|
400
408
|
finishReason,
|
|
401
409
|
...(usage ? { usage } : {}),
|
|
402
|
-
request,
|
|
403
410
|
continuation: 'none',
|
|
404
411
|
};
|
|
405
412
|
}
|
|
406
413
|
function modelStepFailure(kind, message) {
|
|
407
|
-
return { type: 'model_failure', kind, message, retryable:
|
|
414
|
+
return { type: 'model_failure', kind, message, retryable: kind === 'stream_truncated' };
|
|
408
415
|
}
|
|
409
416
|
function providerFinishFailure(rawFinishReason) {
|
|
410
417
|
if (rawFinishReason && rawFinishReason !== 'error') {
|
|
@@ -424,12 +431,11 @@ function providerFinishFailure(rawFinishReason) {
|
|
|
424
431
|
}
|
|
425
432
|
return modelStepFailure('provider_unavailable', 'Provider stopped the stream with an error');
|
|
426
433
|
}
|
|
427
|
-
function failedStepOutcome(
|
|
434
|
+
function failedStepOutcome(failure, usage) {
|
|
428
435
|
return {
|
|
429
|
-
kind,
|
|
436
|
+
kind: 'failed',
|
|
430
437
|
failure,
|
|
431
438
|
...(usage ? { usage } : {}),
|
|
432
|
-
request,
|
|
433
439
|
continuation: 'none',
|
|
434
440
|
};
|
|
435
441
|
}
|
|
@@ -486,6 +492,35 @@ function requireResponsesReplayProfile(runtime) {
|
|
|
486
492
|
}
|
|
487
493
|
return runtime.responsesReplayProfile;
|
|
488
494
|
}
|
|
495
|
+
/**
|
|
496
|
+
* A provider `finish` part is the LanguageModel stream's terminal semantic
|
|
497
|
+
* boundary. Expose EOF at that boundary so the SDK can flush its public
|
|
498
|
+
* finish/usage promises even when the transport keeps the connection open.
|
|
499
|
+
*/
|
|
500
|
+
function withProviderFinishBoundary(model, wrapLanguageModel) {
|
|
501
|
+
return wrapLanguageModel({
|
|
502
|
+
model,
|
|
503
|
+
middleware: {
|
|
504
|
+
wrapStream: async ({ doStream, }) => {
|
|
505
|
+
const result = await doStream();
|
|
506
|
+
return {
|
|
507
|
+
...result,
|
|
508
|
+
stream: result.stream.pipeThrough(new TransformStream({
|
|
509
|
+
transform(part, controller) {
|
|
510
|
+
controller.enqueue(part);
|
|
511
|
+
if (part !== null &&
|
|
512
|
+
typeof part === 'object' &&
|
|
513
|
+
!Array.isArray(part) &&
|
|
514
|
+
part.type === 'finish') {
|
|
515
|
+
controller.terminate();
|
|
516
|
+
}
|
|
517
|
+
},
|
|
518
|
+
})),
|
|
519
|
+
};
|
|
520
|
+
},
|
|
521
|
+
},
|
|
522
|
+
});
|
|
523
|
+
}
|
|
489
524
|
/**
|
|
490
525
|
* The finish reason to forward, preferring what the provider actually said.
|
|
491
526
|
*
|
|
@@ -750,33 +785,7 @@ function translateChunk(chunk, openAiChatReasoningTransportState, runtime, runti
|
|
|
750
785
|
case 'tool-input-start':
|
|
751
786
|
case 'tool-input-delta':
|
|
752
787
|
case 'tool-input-end':
|
|
753
|
-
return
|
|
754
|
-
// Step boundaries (`start-step` / `finish-step`) and the terminal `finish`
|
|
755
|
-
// carry no text/thinking to stream. The backend owns step accounting: it
|
|
756
|
-
// counts and flushes one AssistantMessage per step and rotates the
|
|
757
|
-
// messageId at each `finish-step`. `step-finish` is legacy replay fixture
|
|
758
|
-
// compatibility — handled as a step boundary, not a text carrier.
|
|
759
|
-
case 'finish-step':
|
|
760
|
-
case 'step-finish': {
|
|
761
|
-
const finishReason = chunkFinishReason(chunk);
|
|
762
|
-
const rawFinishReason = rawFinishReasonString(chunk.rawFinishReason);
|
|
763
|
-
// The same value the turn's outcome is decided from, so the record and
|
|
764
|
-
// the outcome cannot name different reasons for the same stream.
|
|
765
|
-
const usage = normalizeAiSdkUsage(chunk.usage, {
|
|
766
|
-
rawFinishReason: rawFinishReason ?? finishReason,
|
|
767
|
-
});
|
|
768
|
-
return [
|
|
769
|
-
{
|
|
770
|
-
kind: 'step-finish',
|
|
771
|
-
...(usage ? { usage } : {}),
|
|
772
|
-
...(finishReason ? { finishReason } : {}),
|
|
773
|
-
},
|
|
774
|
-
];
|
|
775
|
-
}
|
|
776
|
-
case 'finish': {
|
|
777
|
-
const finishReason = chunkFinishReason(chunk);
|
|
778
|
-
return [{ kind: 'finish', ...(finishReason ? { finishReason } : {}) }];
|
|
779
|
-
}
|
|
788
|
+
return [{ kind: 'tool-input', providerExecuted: chunk.providerExecuted === true }];
|
|
780
789
|
case 'start-step':
|
|
781
790
|
case 'tool-result':
|
|
782
791
|
case 'tool-error': {
|
|
@@ -606,15 +606,11 @@ export function buildRuntimeEventModelReplayPlan(events, options = {}) {
|
|
|
606
606
|
providerOptions: steeringProviderOptions(item.steering.eventId),
|
|
607
607
|
}
|
|
608
608
|
: { role: item.role, content: item.content });
|
|
609
|
-
const semanticKinds = [...new Set(items.map((item) => item.kind))];
|
|
610
609
|
return {
|
|
611
610
|
items,
|
|
612
611
|
textMessages,
|
|
613
|
-
semanticKinds,
|
|
614
612
|
diagnostics,
|
|
615
|
-
hasProviderNativeSemantics:
|
|
616
|
-
semanticKinds.includes('tool_call') ||
|
|
617
|
-
semanticKinds.includes('tool_result'),
|
|
613
|
+
hasProviderNativeSemantics: items.some((item) => item.kind !== 'text'),
|
|
618
614
|
};
|
|
619
615
|
}
|
|
620
616
|
function modelTextRole(role) {
|