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.
Files changed (71) hide show
  1. package/dist/pi-transcript.js +3 -4
  2. package/native/runtime-host-windows-task-launcher/prebuilds/win32-x64/maka-runtime-host-task-launcher.exe +0 -0
  3. package/node_modules/@maka/core/dist/agent-graph-schedule.js +15 -4
  4. package/node_modules/@maka/core/dist/executor-id.js +22 -0
  5. package/node_modules/@maka/core/dist/external-session.js +18 -0
  6. package/node_modules/@maka/core/dist/model-call-usage-projection.js +0 -13
  7. package/node_modules/@maka/core/dist/runtime-event.js +19 -3
  8. package/node_modules/@maka/core/dist/session-send-projection.js +6 -3
  9. package/node_modules/@maka/core/dist/session.js +8 -2
  10. package/node_modules/@maka/core/dist/shell-run-result.js +1 -0
  11. package/node_modules/@maka/core/dist/shell-run.js +4 -0
  12. package/node_modules/@maka/core/dist/work-board.js +94 -1
  13. package/node_modules/@maka/core/package.json +1 -0
  14. package/node_modules/@maka/eval/dist/fleet-simulation.js +270 -0
  15. package/node_modules/@maka/eval/dist/fleet-store.js +243 -0
  16. package/node_modules/@maka/eval/dist/fleet-worker.js +125 -0
  17. package/node_modules/@maka/eval/dist/fleet.js +329 -0
  18. package/node_modules/@maka/eval/dist/index.js +3 -0
  19. package/node_modules/@maka/runtime/dist/agent-run.js +2 -17
  20. package/node_modules/@maka/runtime/dist/ai-sdk-compaction.js +6 -2
  21. package/node_modules/@maka/runtime/dist/ai-sdk-message-projection.js +36 -24
  22. package/node_modules/@maka/runtime/dist/ai-sdk-turn.js +257 -330
  23. package/node_modules/@maka/runtime/dist/background-task-health-tool.js +104 -0
  24. package/node_modules/@maka/runtime/dist/history-compaction.js +3 -1
  25. package/node_modules/@maka/runtime/dist/local-web-fetch.js +1 -1
  26. package/node_modules/@maka/runtime/dist/model-adapter.js +62 -53
  27. package/node_modules/@maka/runtime/dist/model-history.js +1 -5
  28. package/node_modules/@maka/runtime/dist/plugin-executor-backend.js +311 -0
  29. package/node_modules/@maka/runtime/dist/plugin-executor-service.js +344 -0
  30. package/node_modules/@maka/runtime/dist/provider-error-classification.js +7 -1
  31. package/node_modules/@maka/runtime/dist/provider-request-telemetry.js +35 -8
  32. package/node_modules/@maka/runtime/dist/runtime-event-backfill.js +7 -1
  33. package/node_modules/@maka/runtime/dist/runtime-event-read-model.js +1 -0
  34. package/node_modules/@maka/runtime/dist/runtime-invocation-route.js +49 -0
  35. package/node_modules/@maka/runtime/dist/runtime-kernel.js +72 -150
  36. package/node_modules/@maka/runtime/dist/runtime-read-model.js +0 -2
  37. package/node_modules/@maka/runtime/dist/session-event-runtime-mapper.js +3 -0
  38. package/node_modules/@maka/runtime/dist/session-manager.js +100 -58
  39. package/node_modules/@maka/runtime/dist/shell-run-manager.js +9 -3
  40. package/node_modules/@maka/runtime/dist/shell-run-tool-result.js +1 -0
  41. package/node_modules/@maka/runtime/dist/stream-graph-schedule-reconcile.js +1 -0
  42. package/node_modules/@maka/runtime/dist/stream-graph-supervisor-tools.js +26 -4
  43. package/node_modules/@maka/runtime/dist/subagent-tools.js +7 -0
  44. package/node_modules/@maka/runtime/dist/tool-runtime.js +45 -466
  45. package/node_modules/@maka/runtime/package.json +3 -0
  46. package/node_modules/@maka/runtime-host/dist/adapter/session-projector.js +7 -2
  47. package/node_modules/@maka/runtime-host/dist/client/session-catalog-summary.js +1 -0
  48. package/node_modules/@maka/runtime-host/dist/protocol/external-session.js +24 -3
  49. package/node_modules/@maka/runtime-host/dist/protocol/index.js +4 -1
  50. package/node_modules/@maka/runtime-host/dist/protocol/plugin-platform.js +42 -5
  51. package/node_modules/@maka/runtime-host/dist/protocol/session-catalog.js +31 -3
  52. package/node_modules/@maka/runtime-host/dist/protocol/session-continuity.js +6 -0
  53. package/node_modules/@maka/runtime-host/dist/server/child-agent-composition.js +1 -0
  54. package/node_modules/@maka/runtime-host/dist/server/execution-artifacts.js +1 -22
  55. package/node_modules/@maka/runtime-host/dist/server/execution-composition.js +54 -8
  56. package/node_modules/@maka/runtime-host/dist/server/external-session-coordinator.js +14 -1
  57. package/node_modules/@maka/runtime-host/dist/server/host-session-availability.js +10 -2
  58. package/node_modules/@maka/runtime-host/dist/server/plugin-platform-coordinator.js +6 -0
  59. package/node_modules/@maka/runtime-host/dist/server/plugin-platform.js +6 -0
  60. package/node_modules/@maka/runtime-host/dist/server/session-catalog-coordinator.js +56 -16
  61. package/node_modules/@maka/runtime-host/dist/server/session-continuity-coordinator.js +4 -3
  62. package/node_modules/@maka/runtime-host/dist/server/session-revision-coordinator.js +4 -0
  63. package/node_modules/@maka/runtime-host/dist/server/web-fetch-tool.js +37 -1
  64. package/node_modules/@maka/storage/dist/claude-code-session-adapter.js +450 -234
  65. package/node_modules/@maka/storage/dist/claude-code-transcript-lineage.js +106 -77
  66. package/node_modules/@maka/storage/dist/legacy-run-header.js +2 -2
  67. package/node_modules/@maka/storage/dist/model-call-usage-sql.js +1 -1
  68. package/node_modules/@maka/storage/dist/session-store.js +12 -2
  69. package/node_modules/@maka/storage/dist/sqlite-long-term-memory-store.js +86 -12
  70. package/node_modules/@maka/storage/dist/work-board-store.js +40 -1
  71. 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' || opened.modelId !== route.modelId)
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: input.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
- : input.model;
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
- settleOutcome(settled);
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, request } = evidence;
389
+ const { aborted, failure, sawFinish, finishReason, rawFinishReason, usage } = evidence;
382
390
  if (aborted || failure?.kind === 'abort') {
383
- return failedStepOutcome('aborted', failure ??
384
- normalizeProviderFailure(Object.assign(new Error('aborted'), { name: 'AbortError' })), request, usage);
391
+ return failedStepOutcome(failure ??
392
+ normalizeProviderFailure(Object.assign(new Error('aborted'), { name: 'AbortError' })), usage);
385
393
  }
386
394
  if (failure) {
387
- return failedStepOutcome('failed', failure, request, usage);
395
+ return failedStepOutcome(failure, usage);
388
396
  }
389
397
  if (!sawFinish || finishReason === 'other' || finishReason === 'unknown') {
390
- return failedStepOutcome('truncated', modelStepFailure('stream_truncated', `Provider stream ended without finishing (${finishReason})`), request, usage);
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('failed', terminalFailure, request, usage);
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: false };
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(kind, failure, request, usage) {
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 chunk.providerExecuted === true ? [{ kind: 'provider-tool-input' }] : [];
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: semanticKinds.includes('thinking') ||
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) {