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
@@ -45,6 +45,7 @@ export class HostPluginPlatform {
45
45
  #tools;
46
46
  #systemPrompt;
47
47
  #commands;
48
+ #executors;
48
49
  #authority = emptyCompositionAuthority();
49
50
  #desired = emptyCompositionState();
50
51
  #mutation = Promise.resolve();
@@ -68,6 +69,7 @@ export class HostPluginPlatform {
68
69
  this.#tools = options.tools;
69
70
  this.#systemPrompt = options.systemPrompt;
70
71
  this.#commands = options.commands;
72
+ this.#executors = options.executors;
71
73
  }
72
74
  async recover() {
73
75
  if (this.#recoveryStarted ||
@@ -356,6 +358,10 @@ export class HostPluginPlatform {
356
358
  this.#assertReadable();
357
359
  return this.#commands?.inspect(rootId) ?? Object.freeze([]);
358
360
  }
361
+ inspectExecutors(rootId) {
362
+ this.#assertReadable();
363
+ return this.#executors?.inspect(rootId) ?? Object.freeze([]);
364
+ }
359
365
  async status() {
360
366
  this.#assertReadable();
361
367
  return Object.freeze({
@@ -23,6 +23,7 @@ import { authorizeConnectionModel, connectionEnabledModelIds } from '@maka/core/
23
23
  import { isModelExplicitlyUnsupportedForChat } from '@maka/core/model-catalog';
24
24
  import { thinkingVariantsForConnection } from '@maka/core/model-thinking';
25
25
  import { executionBoundaryDisplayMode, } from '@maka/core/sandbox-boundary';
26
+ import { isExecutorId } from '@maka/core/executor-id';
26
27
  import { DEFAULT_SESSION_NAME, normalizeUserSessionName } from '@maka/core/session-name';
27
28
  import { isSessionStartModeLabel as isExecutionSemanticLabel, sessionStartModeSpec, } from '@maka/core/session-start-mode';
28
29
  import { WORKHUB_COORDINATION_SESSION_ID, isWorkHubCoordinationSession, isWorkHubCoordinationSessionId, isWorkHubCoordinationSessionTarget, } from '@maka/core/session';
@@ -142,6 +143,7 @@ export class HostSessionCatalogCoordinator {
142
143
  #continuity;
143
144
  #workspaceResolver;
144
145
  #requestDrain;
146
+ #assertExecutorAvailable;
145
147
  #sessionAccessAuthority;
146
148
  constructor(options) {
147
149
  this.#stores = options.stores;
@@ -152,6 +154,7 @@ export class HostSessionCatalogCoordinator {
152
154
  this.#continuity = options.continuity;
153
155
  this.#workspaceResolver = options.workspaceResolver;
154
156
  this.#requestDrain = options.requestDrain;
157
+ this.#assertExecutorAvailable = options.assertExecutorAvailable;
155
158
  this.#sessionAccessAuthority = options.sessionAccessAuthority;
156
159
  }
157
160
  /**
@@ -201,7 +204,7 @@ export class HostSessionCatalogCoordinator {
201
204
  const prepared = await prepareCreate(input);
202
205
  return this.#workspaceResolver.runWithUsageRecorded(input.workspace, async (workspace) => {
203
206
  const [model, policy] = await Promise.all([
204
- this.#resolveModel(input.modelTarget, input.thinkingLevel),
207
+ this.#resolveCreateExecution(input),
205
208
  this.#readRuntimePolicy(),
206
209
  ]);
207
210
  return {
@@ -212,7 +215,8 @@ export class HostSessionCatalogCoordinator {
212
215
  ...(workspace.projectId === null ? {} : { projectId: workspace.projectId }),
213
216
  name: prepared.name,
214
217
  labels: [...prepared.labels],
215
- llmConnectionId: model.connectionId,
218
+ ...(model.executorId ? { executorId: model.executorId } : {}),
219
+ ...(model.connectionId ? { llmConnectionId: model.connectionId } : {}),
216
220
  llmConnectionSlug: model.connectionSlug,
217
221
  model: model.model,
218
222
  ...(input.thinkingLevel === undefined ? {} : { thinkingLevel: input.thinkingLevel }),
@@ -373,7 +377,7 @@ export class HostSessionCatalogCoordinator {
373
377
  }
374
378
  return await this.#workspaceResolver.runWithUsageRecorded(input.workspace, async (workspace) => {
375
379
  const [model, policy] = await Promise.all([
376
- this.#resolveModel(input.modelTarget, input.thinkingLevel),
380
+ this.#resolveCreateExecution(input),
377
381
  this.#readRuntimePolicy(),
378
382
  ]);
379
383
  const createInput = {
@@ -381,7 +385,8 @@ export class HostSessionCatalogCoordinator {
381
385
  ...(workspace.projectId === null ? {} : { projectId: workspace.projectId }),
382
386
  name: prepared.name,
383
387
  labels: [...prepared.labels],
384
- llmConnectionId: model.connectionId,
388
+ ...(model.executorId ? { executorId: model.executorId } : {}),
389
+ ...(model.connectionId ? { llmConnectionId: model.connectionId } : {}),
385
390
  llmConnectionSlug: model.connectionSlug,
386
391
  model: model.model,
387
392
  ...(input.thinkingLevel === undefined ? {} : { thinkingLevel: input.thinkingLevel }),
@@ -806,7 +811,12 @@ export class HostSessionCatalogCoordinator {
806
811
  };
807
812
  }
808
813
  async #mergeConfigurationPatch(current, patch) {
809
- if (current.llmConnectionId === undefined && patch.modelTarget === undefined) {
814
+ if (current.backend === 'fake' && patch.modelTarget === undefined) {
815
+ throw new SessionOperationFailure('operation_conflict', 'Legacy test backend configuration requires an explicit account selection');
816
+ }
817
+ if (current.backend !== 'plugin-executor' &&
818
+ current.llmConnectionId === undefined &&
819
+ patch.modelTarget === undefined) {
810
820
  throw new SessionOperationFailure('operation_conflict', 'Legacy Session configuration requires an explicit account selection');
811
821
  }
812
822
  const thinkingLevel = patch.thinkingLevel === undefined
@@ -830,8 +840,9 @@ export class HostSessionCatalogCoordinator {
830
840
  }, thinkingLevel);
831
841
  }
832
842
  return {
833
- backend: 'ai-sdk',
834
- ...(model.connectionId === undefined ? {} : { llmConnectionId: model.connectionId }),
843
+ backend: patch.modelTarget || current.backend === 'ai-sdk' ? 'ai-sdk' : 'plugin-executor',
844
+ executorId: patch.modelTarget ? undefined : current.executorId,
845
+ llmConnectionId: model.connectionId,
835
846
  llmConnectionSlug: model.connectionSlug,
836
847
  model: model.model,
837
848
  thinkingLevel,
@@ -841,6 +852,25 @@ export class HostSessionCatalogCoordinator {
841
852
  orchestrationMode: patch.orchestrationMode ?? current.orchestrationMode ?? 'default',
842
853
  };
843
854
  }
855
+ async #resolveCreateExecution(input) {
856
+ if (input.executorId) {
857
+ try {
858
+ this.#assertExecutorAvailable?.(input.sessionId, input.executorId);
859
+ }
860
+ catch {
861
+ throw new SessionOperationFailure('operation_unavailable', `Plugin executor is unavailable: ${input.executorId}`);
862
+ }
863
+ return {
864
+ executorId: input.executorId,
865
+ connectionSlug: `executor:${input.executorId}`,
866
+ model: input.executorId,
867
+ };
868
+ }
869
+ if (!input.modelTarget) {
870
+ throw new SessionOperationFailure('invalid_request', 'Session creation requires a model target or executor id');
871
+ }
872
+ return await this.#resolveModel(input.modelTarget, input.thinkingLevel);
873
+ }
844
874
  async #readRuntimePolicy() {
845
875
  try {
846
876
  return await this.#runtimePolicy.runtimePolicy.getSnapshot();
@@ -851,7 +881,8 @@ export class HostSessionCatalogCoordinator {
851
881
  }
852
882
  }
853
883
  function sessionConfigurationMatches(header, configuration) {
854
- return (header.backend === 'ai-sdk' &&
884
+ return (header.backend === configuration.backend &&
885
+ header.executorId === configuration.executorId &&
855
886
  header.llmConnectionId === configuration.llmConnectionId &&
856
887
  header.llmConnectionSlug === configuration.llmConnectionSlug &&
857
888
  header.model === configuration.model &&
@@ -869,6 +900,12 @@ function isPermissionModeOnlyPatch(patch) {
869
900
  patch.orchestrationMode === undefined);
870
901
  }
871
902
  async function prepareCreate(input) {
903
+ if ((input.executorId === undefined) === (input.modelTarget === undefined)) {
904
+ throw new SessionOperationFailure('invalid_request', 'Session creation requires exactly one model target or executor id');
905
+ }
906
+ if (input.executorId !== undefined && !isExecutorId(input.executorId)) {
907
+ throw new SessionOperationFailure('invalid_request', 'Session executor id is invalid');
908
+ }
872
909
  if (input.labels?.some(isExecutionSemanticLabel)) {
873
910
  throw new SessionOperationFailure('invalid_request', 'Session creation cannot set reserved execution labels');
874
911
  }
@@ -894,14 +931,16 @@ function createRequestFingerprint(input, prepared) {
894
931
  : ['host_path', input.workspace.path],
895
932
  prepared.name,
896
933
  prepared.labels,
897
- input.modelTarget.kind === 'default'
898
- ? ['default']
899
- : [
900
- 'explicit',
901
- input.modelTarget.connectionId,
902
- input.modelTarget.connectionSlug,
903
- input.modelTarget.model,
904
- ],
934
+ input.executorId
935
+ ? ['executor', input.executorId]
936
+ : input.modelTarget?.kind === 'default'
937
+ ? ['default']
938
+ : [
939
+ 'explicit',
940
+ input.modelTarget.connectionId,
941
+ input.modelTarget.connectionSlug,
942
+ input.modelTarget.model,
943
+ ],
905
944
  input.thinkingLevel ?? null,
906
945
  input.toolProfile ?? null,
907
946
  prepared.permissionMode ?? ['runtime_default'],
@@ -969,6 +1008,7 @@ export function projectSessionCatalogRecord(record, liveRunState) {
969
1008
  ...(header.revisionIndex === undefined ? {} : { revisionIndex: header.revisionIndex }),
970
1009
  ...(header.revisionState === undefined ? {} : { revisionState: header.revisionState }),
971
1010
  backend: header.backend,
1011
+ ...(header.executorId ? { executorId: header.executorId } : {}),
972
1012
  llmConnectionId: header.llmConnectionId ?? null,
973
1013
  llmConnectionSlug: header.llmConnectionSlug,
974
1014
  connectionLocked: header.connectionLocked,
@@ -505,7 +505,7 @@ export class SessionContinuityCoordinator {
505
505
  }
506
506
  const textKey = assistantStreamKey('text', event.messageId);
507
507
  const text = state.assistantStreams.get(textKey);
508
- if (text || event.text.length > 0) {
508
+ if (text || event.text.length > 0 || event.interrupted) {
509
509
  const current = text ??
510
510
  {
511
511
  kind: 'text',
@@ -514,7 +514,7 @@ export class SessionContinuityCoordinator {
514
514
  text: '',
515
515
  };
516
516
  for (const subscriber of state.subscribers.values()) {
517
- this.#enqueueAssistantCompletion(subscriber, sessionId, runId, current, 'text', event.text);
517
+ this.#enqueueAssistantCompletion(subscriber, sessionId, runId, current, 'text', event.text, event.interrupted);
518
518
  }
519
519
  state.assistantStreams.delete(textKey);
520
520
  }
@@ -1247,7 +1247,7 @@ export class SessionContinuityCoordinator {
1247
1247
  #enqueueAssistantDelta(subscriber, sessionId, runId, event, kind, startOffset) {
1248
1248
  this.#enqueueAssistantText(subscriber, sessionId, runId, event, kind, startOffset, event.text);
1249
1249
  }
1250
- #enqueueAssistantCompletion(subscriber, sessionId, runId, current, kind, finalText) {
1250
+ #enqueueAssistantCompletion(subscriber, sessionId, runId, current, kind, finalText, interrupted) {
1251
1251
  const extendsPrefix = finalText.startsWith(current.text);
1252
1252
  const suffix = extendsPrefix ? finalText.slice(current.text.length) : finalText;
1253
1253
  if (suffix) {
@@ -1270,6 +1270,7 @@ export class SessionContinuityCoordinator {
1270
1270
  text: '',
1271
1271
  ...(!extendsPrefix && finalText.length === 0 ? { reset: true } : {}),
1272
1272
  complete: true,
1273
+ ...(interrupted ? { interrupted: true } : {}),
1273
1274
  },
1274
1275
  });
1275
1276
  }
@@ -20,6 +20,7 @@ import { createHash, randomUUID } from 'node:crypto';
20
20
  import { isDeepResearchSession } from '@maka/core/deep-research';
21
21
  import { SIDE_CONVERSATION_SESSION_LABEL } from '@maka/core/side-conversation';
22
22
  import { isWorkHubCoordinationSessionId, isWorkHubCoordinationSessionTarget, sessionRevisionFamilyId, } from '@maka/core/session';
23
+ import { runtimeHostConversationCopyUnavailableReason } from './host-session-availability.js';
23
24
  import { archivedToolResultContainsLinkedChildReferences, archivedToolResultContainsConversationOwnedReferences, cloneConversationRuntimeLedger, collectConversationCopyLinkedChildReferences, collectConversationCopySessionContextRefIds, collectConversationCopySessionFileRefs, createConversationCopySlice, prepareConversationRuntimeLedgerCopy, } from '@maka/runtime/conversation-copy';
24
25
  import { isArchivedToolResultPlaceholder } from '@maka/runtime/context-budget';
25
26
  import { decodeModelProjectionTransition, MODEL_PROJECTION_TRANSITION_EVENT_TYPE, } from '@maka/core/model-projection-transition';
@@ -204,6 +205,9 @@ export class HostSessionRevisionCoordinator {
204
205
  if (isDeepResearchSession(sourceHeader.labels)) {
205
206
  return copyFailure('operation_unavailable', 'Deep Research Sessions cannot be copied without an exact research ledger boundary');
206
207
  }
208
+ const copyUnavailableReason = runtimeHostConversationCopyUnavailableReason(sourceHeader);
209
+ if (copyUnavailableReason)
210
+ return copyFailure('operation_unavailable', copyUnavailableReason);
207
211
  if (kind !== 'side_conversation' && this.options.isSessionActive(input.sourceSessionId)) {
208
212
  return copyFailure('session_busy', 'Source Session has an active Turn');
209
213
  }
@@ -17,7 +17,7 @@
17
17
  * under the License.
18
18
  */
19
19
  import { buildWebFetchTool } from '@maka/runtime/web-fetch-tool';
20
- import { createLocalWebFetchExecutor } from '@maka/runtime/local-web-fetch';
20
+ import { assertAllowedTarget, createLocalWebFetchExecutor } from '@maka/runtime/local-web-fetch';
21
21
  import { createProxiedFetchTransport, } from '@maka/runtime/network/scoped-fetch-transport';
22
22
  import { toRuntimePolicyProxy } from './runtime-policy-proxy.js';
23
23
  export function createHostWebFetchService(input) {
@@ -43,6 +43,42 @@ export function createHostWebFetchService(input) {
43
43
  await transport.close();
44
44
  }
45
45
  },
46
+ probe: async ({ url, abortSignal }) => {
47
+ const parsed = new URL(url);
48
+ assertAllowedTarget(parsed);
49
+ abortSignal.throwIfAborted();
50
+ const resolved = await input.policy.resolveHostOutboundExecution();
51
+ if (resolved.kind === 'privacy_mode')
52
+ throw new Error('Endpoint health checks are disabled while privacy mode is active.');
53
+ if (resolved.kind === 'credential_not_configured')
54
+ throw new Error('Configure the network proxy credential before checking an endpoint.');
55
+ const transport = createFetchTransport(toRuntimePolicyProxy(resolved.networkProxy, resolved.secretMaterial.networkProxy?.secret));
56
+ const started = Date.now();
57
+ const timeout = new AbortController();
58
+ const timer = setTimeout(() => timeout.abort(new Error('Endpoint health probe timed out.')), input.probeTimeoutMs ?? 30_000);
59
+ const signal = AbortSignal.any([abortSignal, timeout.signal]);
60
+ try {
61
+ let response = await transport.fetch(parsed, {
62
+ method: 'HEAD',
63
+ redirect: 'manual',
64
+ signal,
65
+ });
66
+ await response.body?.cancel();
67
+ if (response.status === 405 || response.status === 501) {
68
+ response = await transport.fetch(parsed, { method: 'GET', redirect: 'manual', signal });
69
+ await response.body?.cancel();
70
+ }
71
+ return {
72
+ status: response.status,
73
+ ...(response.statusText ? { statusText: response.statusText } : {}),
74
+ elapsedMs: Date.now() - started,
75
+ };
76
+ }
77
+ finally {
78
+ clearTimeout(timer);
79
+ await transport.close();
80
+ }
81
+ },
46
82
  };
47
83
  }
48
84
  export function createHostWebFetchTool(input) {