maka-agent 0.2.0-dev.24.20260907 → 0.2.0-dev.26.20260909

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 (154) hide show
  1. package/README.md +38 -19
  2. package/README.zh-CN.md +34 -19
  3. package/dist/mcp-capability-provider.js +4 -1
  4. package/dist/pi-transcript-tools.js +6 -0
  5. package/dist/pi-tui-layout.js +56 -10
  6. package/dist/pi-tui-mcp-status.js +2 -2
  7. package/dist/pi-tui-pickers.js +121 -30
  8. package/dist/pi-tui-runner.js +156 -42
  9. package/dist/pi-tui-todo.js +221 -0
  10. package/dist/pi-tui-transcript-viewer.js +134 -7
  11. package/dist/runtime-host-cli-context.js +70 -13
  12. package/dist/runtime-host-handoff-surface.js +51 -26
  13. package/dist/runtime-host-local-handoff.js +11 -1
  14. package/dist/runtime-host-service-manager.js +0 -3
  15. package/dist/runtime-host-session-channel.js +13 -0
  16. package/dist/runtime-host-session-driver.js +42 -1
  17. package/dist/tui-autocomplete-layout.js +3 -1
  18. package/dist/tui-copy-catalog.js +85 -6
  19. package/dist/tui-editor-render.js +36 -0
  20. package/dist/tui-mcp-control.js +41 -6
  21. package/native/runtime-host-windows-task-launcher/prebuilds/win32-x64/maka-runtime-host-task-launcher.exe +0 -0
  22. package/node_modules/@maka/core/dist/agent-run.js +1 -0
  23. package/node_modules/@maka/core/dist/attachments.js +3 -0
  24. package/node_modules/@maka/core/dist/canonical-json.js +27 -0
  25. package/node_modules/@maka/core/dist/capabilities.js +35 -0
  26. package/node_modules/@maka/core/dist/computer-use.js +0 -1
  27. package/node_modules/@maka/core/dist/display-redaction.js +18 -0
  28. package/node_modules/@maka/core/dist/llm-connections.js +13 -0
  29. package/node_modules/@maka/core/dist/model-call-attempt.js +2 -0
  30. package/node_modules/@maka/core/dist/model-metadata.js +4 -0
  31. package/node_modules/@maka/core/dist/redaction.js +35 -0
  32. package/node_modules/@maka/core/dist/run-composition.js +77 -2
  33. package/node_modules/@maka/core/dist/runtime-event.js +3 -0
  34. package/node_modules/@maka/core/dist/session.js +57 -6
  35. package/node_modules/@maka/core/dist/slash-command-catalog.js +1 -0
  36. package/node_modules/@maka/core/dist/tool-result-record-schema.js +2 -1
  37. package/node_modules/@maka/core/dist/workhub-action-result.js +68 -0
  38. package/node_modules/@maka/core/package.json +3 -3
  39. package/node_modules/@maka/eval/dist/experiment-directory.js +4 -13
  40. package/node_modules/@maka/eval/dist/toolchain-verification.js +1 -1
  41. package/node_modules/@maka/mcp/dist/form-elicitation.js +213 -0
  42. package/node_modules/@maka/mcp/dist/index.js +337 -71
  43. package/node_modules/@maka/runtime/dist/agent-run-inspect.js +0 -13
  44. package/node_modules/@maka/runtime/dist/agent-run.js +90 -2
  45. package/node_modules/@maka/runtime/dist/ai-sdk-backend.js +16 -8
  46. package/node_modules/@maka/runtime/dist/ai-sdk-turn.js +57 -50
  47. package/node_modules/@maka/runtime/dist/archive-read-tool.js +2 -2
  48. package/node_modules/@maka/runtime/dist/context-budget-helpers.js +0 -16
  49. package/node_modules/@maka/runtime/dist/conversation-copy.js +153 -11
  50. package/node_modules/@maka/runtime/dist/github-copilot-oauth-enrollment.js +3 -3
  51. package/node_modules/@maka/runtime/dist/goal-continuation.js +5 -1
  52. package/node_modules/@maka/runtime/dist/ledger-tool-result-archive-reader.js +69 -1
  53. package/node_modules/@maka/runtime/dist/mcp-tools.js +7 -2
  54. package/node_modules/@maka/runtime/dist/model-fetcher.js +42 -2
  55. package/node_modules/@maka/runtime/dist/model-history.js +0 -112
  56. package/node_modules/@maka/runtime/dist/plugin-runtime.js +20 -10
  57. package/node_modules/@maka/runtime/dist/plugin-tool-service.js +205 -0
  58. package/node_modules/@maka/runtime/dist/provider-request-telemetry.js +8 -1
  59. package/node_modules/@maka/runtime/dist/request-shape.js +23 -0
  60. package/node_modules/@maka/runtime/dist/runtime-event-backfill.js +1 -1
  61. package/node_modules/@maka/runtime/dist/runtime-event-read-model.js +24 -1
  62. package/node_modules/@maka/runtime/dist/runtime-kernel.js +127 -13
  63. package/node_modules/@maka/runtime/dist/session-manager.js +20 -36
  64. package/node_modules/@maka/runtime/dist/stream-graph-coordinator.js +21 -0
  65. package/node_modules/@maka/runtime/dist/stream-graph-supervisor-tools.js +0 -5
  66. package/node_modules/@maka/runtime/dist/test-connection.js +0 -1
  67. package/node_modules/@maka/runtime/dist/tool-activation-identity.js +41 -0
  68. package/node_modules/@maka/runtime/dist/tool-availability.js +11 -1
  69. package/node_modules/@maka/runtime/dist/tool-result-archive-resource.js +63 -1
  70. package/node_modules/@maka/runtime/dist/tool-result-archive-transition.js +42 -12
  71. package/node_modules/@maka/runtime/dist/tool-result-archive.js +27 -4
  72. package/node_modules/@maka/runtime/package.json +1 -0
  73. package/node_modules/@maka/runtime-host/dist/client/connection.js +30 -5
  74. package/node_modules/@maka/runtime-host/dist/client/host-handoff-copy.js +52 -13
  75. package/node_modules/@maka/runtime-host/dist/client/host-handoff.js +2 -0
  76. package/node_modules/@maka/runtime-host/dist/client/host-retirement.js +4 -2
  77. package/node_modules/@maka/runtime-host/dist/client/peer-client.js +18 -1
  78. package/node_modules/@maka/runtime-host/dist/client/session-subscription.js +19 -0
  79. package/node_modules/@maka/runtime-host/dist/control/endpoint.js +1 -3
  80. package/node_modules/@maka/runtime-host/dist/node-error.js +22 -0
  81. package/node_modules/@maka/runtime-host/dist/operator/managed-deployment.js +1 -3
  82. package/node_modules/@maka/runtime-host/dist/peer-mesh/limits.js +0 -1
  83. package/node_modules/@maka/runtime-host/dist/peer-mesh/model.js +1 -1
  84. package/node_modules/@maka/runtime-host/dist/peer-reachability/publisher.js +1 -3
  85. package/node_modules/@maka/runtime-host/dist/protocol/index.js +9 -1
  86. package/node_modules/@maka/runtime-host/dist/protocol/operations.js +3 -2
  87. package/node_modules/@maka/runtime-host/dist/protocol/plan.js +1 -0
  88. package/node_modules/@maka/runtime-host/dist/protocol/plugin-platform.js +27 -5
  89. package/node_modules/@maka/runtime-host/dist/protocol/project-catalog.js +2 -2
  90. package/node_modules/@maka/runtime-host/dist/protocol/session-continuity.js +1 -0
  91. package/node_modules/@maka/runtime-host/dist/protocol/workhub-coordination.js +86 -157
  92. package/node_modules/@maka/runtime-host/dist/server/access-credential-store.js +4 -0
  93. package/node_modules/@maka/runtime-host/dist/server/agent-graph-coordinator.js +0 -3
  94. package/node_modules/@maka/runtime-host/dist/server/canonical-session-projection.js +2 -1
  95. package/node_modules/@maka/runtime-host/dist/server/connection-session.js +28 -8
  96. package/node_modules/@maka/runtime-host/dist/server/daily-review-coordinator.js +112 -56
  97. package/node_modules/@maka/runtime-host/dist/server/execution-artifacts.js +32 -32
  98. package/node_modules/@maka/runtime-host/dist/server/execution-composition.js +85 -25
  99. package/node_modules/@maka/runtime-host/dist/server/execution-model-composition.js +42 -14
  100. package/node_modules/@maka/runtime-host/dist/server/failure-diagnostic.js +24 -0
  101. package/node_modules/@maka/runtime-host/dist/server/goal-coordinator.js +7 -3
  102. package/node_modules/@maka/runtime-host/dist/server/host-kernel.js +3 -3
  103. package/node_modules/@maka/runtime-host/dist/server/host-session-availability.js +5 -2
  104. package/node_modules/@maka/runtime-host/dist/server/hosted-execution-recovery.js +3 -2
  105. package/node_modules/@maka/runtime-host/dist/server/hosted-execution-tool-profile.js +34 -4
  106. package/node_modules/@maka/runtime-host/dist/server/interactive-run-composer.js +51 -23
  107. package/node_modules/@maka/runtime-host/dist/server/operation-dispatcher.js +2 -7
  108. package/node_modules/@maka/runtime-host/dist/server/plugin-platform-coordinator.js +6 -0
  109. package/node_modules/@maka/runtime-host/dist/server/plugin-platform.js +6 -0
  110. package/node_modules/@maka/runtime-host/dist/server/root-turn-coordinator.js +110 -14
  111. package/node_modules/@maka/runtime-host/dist/server/runtime-resource-coordinator.js +11 -8
  112. package/node_modules/@maka/runtime-host/dist/server/scheduled-task-coordinator.js +31 -21
  113. package/node_modules/@maka/runtime-host/dist/server/serial-outbound-writer.js +1 -1
  114. package/node_modules/@maka/runtime-host/dist/server/session-catalog-coordinator.js +20 -8
  115. package/node_modules/@maka/runtime-host/dist/server/session-retirement-coordinator.js +5 -2
  116. package/node_modules/@maka/runtime-host/dist/server/session-revision-coordinator.js +4 -0
  117. package/node_modules/@maka/runtime-host/dist/server/session-transcript-reader.js +15 -104
  118. package/node_modules/@maka/runtime-host/dist/server/shared-session-transcript.js +3 -0
  119. package/node_modules/@maka/runtime-host/dist/server/workhub-coordination-action-gate.js +59 -82
  120. package/node_modules/@maka/runtime-host/dist/server/workhub-coordination-coordinator.js +132 -139
  121. package/node_modules/@maka/runtime-host/dist/server/workhub-message-attachments.js +46 -0
  122. package/node_modules/@maka/storage/dist/agent-run-store.js +14 -1
  123. package/node_modules/@maka/storage/dist/artifact-store.js +40 -3
  124. package/node_modules/@maka/storage/dist/atomic-file-write.js +74 -0
  125. package/node_modules/@maka/storage/dist/claude-code-session-adapter.js +0 -1
  126. package/node_modules/@maka/storage/dist/codex-session-adapter.js +284 -196
  127. package/node_modules/@maka/storage/dist/credential-store.js +12 -63
  128. package/node_modules/@maka/storage/dist/execution-stores.js +4 -1
  129. package/node_modules/@maka/storage/dist/git-exec.js +61 -0
  130. package/node_modules/@maka/storage/dist/git-worktree-child-executor.js +8 -35
  131. package/node_modules/@maka/storage/dist/goal-authority.js +2 -2
  132. package/node_modules/@maka/storage/dist/interaction-store.js +2 -2
  133. package/node_modules/@maka/storage/dist/mcp-config-store.js +10 -25
  134. package/node_modules/@maka/storage/dist/project-catalog.js +2 -23
  135. package/node_modules/@maka/storage/dist/runtime-event-invariants.js +2 -2
  136. package/node_modules/@maka/storage/dist/runtime-policy/connection-catalog-document.js +8 -3
  137. package/node_modules/@maka/storage/dist/scheduled-task-store.js +249 -283
  138. package/node_modules/@maka/storage/dist/session-bundle-manifest.js +5 -17
  139. package/node_modules/@maka/storage/dist/session-bundle-policy.js +2 -1
  140. package/node_modules/@maka/storage/dist/session-copy-cleanup.js +2 -1
  141. package/node_modules/@maka/storage/dist/session-store.js +14 -2
  142. package/node_modules/@maka/storage/dist/settings-store.js +8 -4
  143. package/node_modules/@maka/storage/dist/sqlite-artifact-metadata.js +11 -0
  144. package/node_modules/@maka/storage/dist/sqlite-runtime-store.js +1 -2
  145. package/node_modules/@maka/storage/dist/sqlite-session-metadata-schema.js +12 -1
  146. package/node_modules/@maka/storage/dist/sqlite-session-metadata-store.js +67 -3
  147. package/node_modules/@maka/storage/dist/stable-storage.js +14 -1
  148. package/node_modules/@maka/storage/dist/storage-id.js +28 -0
  149. package/node_modules/@maka/storage/dist/tool-result-archive-evidence.js +31 -4
  150. package/node_modules/@maka/storage/dist/workspace-identity.js +2 -15
  151. package/node_modules/@maka/storage/dist/workspace-version-authority-internal.js +1 -8
  152. package/package.json +1 -1
  153. package/node_modules/@maka/core/dist/workhub-creation-intent.js +0 -990
  154. package/node_modules/@maka/core/dist/workhub-session-resolver.js +0 -50
@@ -31,6 +31,7 @@
31
31
  * Phase 1 scope: types + small pure helpers only. No storage, runner,
32
32
  * projection, or ledger logic lives here. Those arrive in later nodes.
33
33
  */
34
+ import { isWorkHubActionReceipt } from './workhub-action-result.js';
34
35
  import { isModelRetryDecision } from './model-failure.js';
35
36
  import { isRuntimeHandoffPause, runtimeHandoffPause, } from './runtime-handoff.js';
36
37
  import { isMessageContent, normalizeMessageContent, } from './events.js';
@@ -229,6 +230,7 @@ const INVOCATION_ROOT_SHAPES = {
229
230
  };
230
231
  const RUNTIME_ACTIONS_SHAPE = defineObjectShape()([], [
231
232
  'handoffPause',
233
+ 'coordination',
232
234
  'stateDelta',
233
235
  'artifactDelta',
234
236
  'permissionRequest',
@@ -583,6 +585,7 @@ function isRuntimeEventActions(value) {
583
585
  return false;
584
586
  }
585
587
  return ((value.handoffPause === undefined || isRuntimeHandoffPause(value.handoffPause)) &&
588
+ (value.coordination === undefined || isWorkHubActionReceipt(value.coordination)) &&
586
589
  (value.stateDelta === undefined || isRecord(value.stateDelta)) &&
587
590
  (value.artifactDelta === undefined ||
588
591
  (isRecord(value.artifactDelta) &&
@@ -16,9 +16,10 @@
16
16
  * specific language governing permissions and limitations
17
17
  * under the License.
18
18
  */
19
+ import { isWorkHubActionReceipt } from './workhub-action-result.js';
19
20
  import { MODEL_FAILURE_MESSAGE_MAX_BYTES, isModelRetryDecision, } from './model-failure.js';
20
21
  import { decodeMessageContent, TOOL_ACTIVITY_KINDS, } from './events.js';
21
- import { isToolCategory, } from './permission.js';
22
+ import { isPermissionMode, isToolCategory, } from './permission.js';
22
23
  import { defineObjectShape, hasExactShape, isFiniteNumber, isOptionalString, isRecord, pickShape, } from './record-schema.js';
23
24
  import { isPermissionDecisionFields } from './interaction-record-schema.js';
24
25
  import { isTokenUsageFields } from './usage-record-schema.js';
@@ -64,7 +65,11 @@ export function isTurnStatus(value) {
64
65
  // ============================================================================
65
66
  // Header (JSONL line 1)
66
67
  // ============================================================================
67
- export const SESSION_TOOL_PROFILES = ['headless-coding-v1', 'workhub-coordination-v1'];
68
+ export const SESSION_TOOL_PROFILES = [
69
+ 'headless-coding-v1',
70
+ 'workhub-coordination-v1',
71
+ 'workhub-coordination-v2',
72
+ ];
68
73
  export function isSessionToolProfile(value) {
69
74
  return typeof value === 'string' && SESSION_TOOL_PROFILES.includes(value);
70
75
  }
@@ -283,6 +288,19 @@ export function isUserVisibleSessionSystemNote(kind) {
283
288
  export const WORKHUB_COORDINATION_RECORD_SCHEMA_VERSION = 1;
284
289
  export const WORKHUB_COORDINATION_REPLACEMENT_SCHEMA_VERSION = 2;
285
290
  export const WORKHUB_COORDINATION_STOP_SCHEMA_VERSION = 3;
291
+ export function isWorkHubCreateDefaults(value) {
292
+ if (!isRecord(value) ||
293
+ Object.keys(value).some((key) => key !== 'model' && key !== 'permissionMode'))
294
+ return false;
295
+ if (value.permissionMode !== undefined && !isPermissionMode(value.permissionMode))
296
+ return false;
297
+ if (value.model === undefined)
298
+ return true;
299
+ const model = value.model;
300
+ return (isRecord(model) &&
301
+ Object.keys(model).length === 3 &&
302
+ ['llmConnectionId', 'llmConnectionSlug', 'model'].every((key) => typeof model[key] === 'string' && model[key].trim().length > 0 && model[key].length <= 512));
303
+ }
286
304
  function isWorkHubDelegationStopResolution(outcome, targetTurnId) {
287
305
  const hasTargetTurnId = typeof targetTurnId === 'string' && targetTurnId.length > 0;
288
306
  if (outcome === 'stop_delivered' || outcome === 'not_owned')
@@ -328,6 +346,7 @@ const USER_MESSAGE_SHAPE = defineObjectShape()(['type', 'id', 'turnId', 'ts', 't
328
346
  'quotes',
329
347
  'inlineReferences',
330
348
  'steeringEventId',
349
+ 'coordinationActionId',
331
350
  'origin',
332
351
  ]);
333
352
  const ASSISTANT_MESSAGE_SHAPE = defineObjectShape()(['type', 'id', 'turnId', 'ts', 'text', 'modelId'], ['thinking', 'contentOrder', 'providerOptions']);
@@ -405,7 +424,15 @@ const WORKHUB_DELEGATION_ASSIGNED_MESSAGE_SHAPE = defineObjectShape()([
405
424
  'targetTurnId',
406
425
  'targetMessageId',
407
426
  'targetSessionName',
408
- ], ['create', 'steered', 'replacesActionId', 'replacesDelegationId']);
427
+ ], [
428
+ 'attachments',
429
+ 'targetAttachments',
430
+ 'create',
431
+ 'steered',
432
+ 'replacesActionId',
433
+ 'replacesDelegationId',
434
+ 'delegationText',
435
+ ]);
409
436
  const WORKHUB_DELEGATION_REPLACEMENT_REQUESTED_MESSAGE_SHAPE = defineObjectShape()([
410
437
  'type',
411
438
  'id',
@@ -424,7 +451,7 @@ const WORKHUB_DELEGATION_REPLACEMENT_REQUESTED_MESSAGE_SHAPE = defineObjectShape
424
451
  'replacedTargetSessionId',
425
452
  'replacedTargetMessageId',
426
453
  'targetSessionName',
427
- ], ['create']);
454
+ ], ['attachments', 'create', 'delegationText']);
428
455
  const WORKHUB_DELEGATION_SUPERSEDED_MESSAGE_SHAPE = defineObjectShape()([
429
456
  'type',
430
457
  'id',
@@ -486,7 +513,7 @@ const WORKHUB_DELEGATION_STOP_RESOLVED_MESSAGE_SHAPE = defineObjectShape()([
486
513
  'targetSessionId',
487
514
  'outcome',
488
515
  ], ['targetTurnId']);
489
- const WORKHUB_DELEGATION_CREATE_SHAPE = defineObjectShape()(['title', 'workspace'], []);
516
+ const WORKHUB_DELEGATION_CREATE_SHAPE = defineObjectShape()(['title', 'workspace'], ['defaults']);
490
517
  const WORKHUB_DELEGATION_PROJECT_WORKSPACE_SHAPE = defineObjectShape()(['kind', 'projectId'], []);
491
518
  const WORKHUB_DELEGATION_HOST_PATH_WORKSPACE_SHAPE = defineObjectShape()(['kind', 'path'], []);
492
519
  const SYSTEM_NOTE_MESSAGE_SHAPE = defineObjectShape()(['type', 'id', 'ts', 'kind'], ['turnId', 'data']);
@@ -510,7 +537,10 @@ function decodeMessage(value, decodeToolResultContent) {
510
537
  case 'user':
511
538
  if (hasExactShape(message, USER_MESSAGE_SHAPE) &&
512
539
  hasMessageEnvelope(message, true) &&
513
- (message.origin === undefined || decodeTurnOrigin(message.origin) !== undefined)) {
540
+ (message.origin === undefined || decodeTurnOrigin(message.origin) !== undefined) &&
541
+ (message.coordinationActionId === undefined ||
542
+ (typeof message.coordinationActionId === 'string' &&
543
+ message.coordinationActionId.length > 0))) {
514
544
  const { displayText, attachments, directoryReferences, quotes, inlineReferences, origin, ...envelope } = message;
515
545
  const decodedOrigin = origin === undefined ? undefined : decodeTurnOrigin(origin);
516
546
  try {
@@ -619,6 +649,11 @@ function decodeMessage(value, decodeToolResultContent) {
619
649
  throw new Error('Invalid stored message schema');
620
650
  }
621
651
  function isWorkHubCoordinationMessage(message) {
652
+ if (message.kind === 'action_receipt')
653
+ return (hasMessageEnvelope(message, true) &&
654
+ message.schemaVersion === 1 &&
655
+ Object.keys(message).every((k) => ['type', 'kind', 'schemaVersion', 'id', 'turnId', 'ts', 'receipt'].includes(k)) &&
656
+ isWorkHubActionReceipt(message.receipt));
622
657
  if (message.kind === 'delegation_stop_requested') {
623
658
  return (hasMessageEnvelope(message, true) &&
624
659
  hasExactShape(message, WORKHUB_DELEGATION_STOP_REQUESTED_MESSAGE_SHAPE) &&
@@ -694,6 +729,9 @@ function isWorkHubCoordinationMessage(message) {
694
729
  typeof message.targetSessionId === 'string' &&
695
730
  typeof message.userText === 'string' &&
696
731
  message.userText.trim().length > 0 &&
732
+ isWorkHubMessageAttachments(message.attachments) &&
733
+ (message.delegationText === undefined ||
734
+ (typeof message.delegationText === 'string' && message.delegationText.trim().length > 0)) &&
697
735
  ((message.disposition === 'delegate_existing' && message.create === undefined) ||
698
736
  (message.disposition === 'create_new' && isWorkHubDelegationCreateSpec(message.create))) &&
699
737
  (message.disposition === 'delegate_existing' || message.disposition === 'create_new');
@@ -715,6 +753,7 @@ function isWorkHubCoordinationMessage(message) {
715
753
  }
716
754
  return (message.kind === 'delegation_assigned' &&
717
755
  hasExactShape(message, WORKHUB_DELEGATION_ASSIGNED_MESSAGE_SHAPE) &&
756
+ isWorkHubMessageAttachments(message.targetAttachments) &&
718
757
  typeof message.delegationId === 'string' &&
719
758
  typeof message.targetTurnId === 'string' &&
720
759
  typeof message.targetMessageId === 'string' &&
@@ -739,9 +778,21 @@ function isWorkHubActionIdentity(message) {
739
778
  message.coordinationTurnId.length > 0 &&
740
779
  message.turnId === message.coordinationTurnId);
741
780
  }
781
+ function isWorkHubMessageAttachments(value) {
782
+ if (value === undefined)
783
+ return true;
784
+ try {
785
+ decodeMessageContent({ text: '', attachments: value });
786
+ return true;
787
+ }
788
+ catch {
789
+ return false;
790
+ }
791
+ }
742
792
  function isWorkHubDelegationCreateSpec(value) {
743
793
  if (!isRecord(value) ||
744
794
  !hasExactShape(value, WORKHUB_DELEGATION_CREATE_SHAPE) ||
795
+ (value.defaults !== undefined && !isWorkHubCreateDefaults(value.defaults)) ||
745
796
  typeof value.title !== 'string' ||
746
797
  value.title.trim().length === 0 ||
747
798
  !isRecord(value.workspace)) {
@@ -40,6 +40,7 @@ export const SLASH_COMMAND_CATALOG = [
40
40
  { id: 'skill', session: 'required', surfaces: ['tui'] },
41
41
  { id: 'swarm', session: 'none', surfaces: ['desktop', 'tui'] },
42
42
  { id: 'thinking', session: 'required', surfaces: ['tui'] },
43
+ { id: 'todo', session: 'required', surfaces: ['tui'] },
43
44
  { id: 'transcript', session: 'required', surfaces: ['tui'] },
44
45
  { id: 'update', session: 'none', surfaces: ['tui'] },
45
46
  ];
@@ -37,7 +37,7 @@ const ARCHIVED_SHAPE = defineObjectShape()([
37
37
  'originalBytes',
38
38
  'rewriteVersion',
39
39
  'reason',
40
- ], ['artifactId', 'bodySha256']);
40
+ ], ['artifactId', 'resourceRef', 'bodySha256']);
41
41
  const IMAGE_SHAPE = defineObjectShape()(['kind', 'mimeType', 'ref'], []);
42
42
  const SUMMARY_SHAPE = defineObjectShape()(['kind', 'original', 'summarized', 'reason'], []);
43
43
  const WEB_SEARCH_SHAPE = defineObjectShape()(['kind', 'provider', 'query', 'rows'], []);
@@ -157,6 +157,7 @@ function isNonShellToolResultContent(value) {
157
157
  typeof value.toolCallId === 'string' &&
158
158
  typeof value.toolName === 'string' &&
159
159
  isOptionalString(value.artifactId) &&
160
+ isOptionalString(value.resourceRef) &&
160
161
  isOptionalString(value.bodySha256) &&
161
162
  isFiniteNumber(value.originalEstimatedTokens) &&
162
163
  isFiniteNumber(value.originalBytes) &&
@@ -0,0 +1,68 @@
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 { isRecord } from './record-schema.js';
20
+ export function isWorkHubActionReceipt(value) {
21
+ if (!isRecord(value) ||
22
+ Object.keys(value).some((k) => !['actionId', 'userText', 'result', 'clarification'].includes(k)) ||
23
+ typeof value.actionId !== 'string' ||
24
+ !value.actionId ||
25
+ typeof value.userText !== 'string' ||
26
+ !value.userText.trim() ||
27
+ (value.clarification !== undefined && typeof value.clarification !== 'string'))
28
+ return false;
29
+ return isWorkHubActionResult(value.result);
30
+ }
31
+ /** Shared closed result contract for Runtime receipts and Host protocol replies. */
32
+ export function isWorkHubActionResult(r) {
33
+ if (!isRecord(r))
34
+ return false;
35
+ const text = (k) => typeof r[k] === 'string' && /^[A-Za-z0-9_-]{1,128}$/u.test(r[k]);
36
+ const keys = (allowed) => Object.keys(r).every((k) => allowed.includes(k));
37
+ if (r.disposition === 'answer_here' || r.disposition === 'clarify')
38
+ return keys(['disposition', 'coordinationTurnId']) && text('coordinationTurnId');
39
+ if (r.disposition === 'delegate_existing' ||
40
+ r.disposition === 'create_new' ||
41
+ r.disposition === 'replace')
42
+ return (keys([
43
+ 'disposition',
44
+ 'targetSessionId',
45
+ 'targetTurnId',
46
+ 'steered',
47
+ ...(r.disposition === 'replace' ? ['replacementDisposition'] : []),
48
+ ]) &&
49
+ text('targetSessionId') &&
50
+ text('targetTurnId') &&
51
+ (r.steered === undefined || r.steered === true) &&
52
+ (r.disposition !== 'replace' ||
53
+ r.replacementDisposition === 'delegate_existing' ||
54
+ r.replacementDisposition === 'create_new'));
55
+ if (r.disposition === 'stop_work' || r.disposition === 'resume_work')
56
+ return ((r.disposition === 'stop_work'
57
+ ? ((r.outcome !== 'stop_delivered' && r.outcome !== 'not_owned') ||
58
+ r.targetTurnId !== undefined) &&
59
+ (r.outcome !== 'cancelled_pending' || r.targetTurnId === undefined)
60
+ : (r.outcome === 'resume_started') === (r.targetTurnId !== undefined)) &&
61
+ keys(['disposition', 'outcome', 'targetSessionId', 'targetTurnId']) &&
62
+ text('targetSessionId') &&
63
+ (r.targetTurnId === undefined || text('targetTurnId')) &&
64
+ (r.disposition === 'stop_work'
65
+ ? ['cancelled_pending', 'stop_delivered', 'already_terminal', 'not_owned']
66
+ : ['resume_started', 'already_running']).includes(String(r.outcome)));
67
+ return false;
68
+ }
@@ -9,6 +9,7 @@
9
9
  "./durable-tool-result-projection": "./dist/durable-tool-result-projection.js",
10
10
  "./model-projection-transition": "./dist/model-projection-transition.js",
11
11
  "./canonical-runtime-event": "./dist/canonical-runtime-event.js",
12
+ "./canonical-json": "./dist/canonical-json.js",
12
13
  "./runtime-boundary": "./dist/runtime-boundary.js",
13
14
  "./runtime-handoff": "./dist/runtime-handoff.js",
14
15
  "./runtime-logical-execution": "./dist/runtime-logical-execution.js",
@@ -82,8 +83,6 @@
82
83
  "./deep-research-client-progress": "./dist/deep-research-client-progress.js",
83
84
  "./daily-review": "./dist/daily-review.js",
84
85
  "./work-board": "./dist/work-board.js",
85
- "./workhub-creation-intent": "./dist/workhub-creation-intent.js",
86
- "./workhub-session-resolver": "./dist/workhub-session-resolver.js",
87
86
  "./deep-research": "./dist/deep-research.js",
88
87
  "./session-start-mode": "./dist/session-start-mode.js",
89
88
  "./long-term-memory": "./dist/long-term-memory.js",
@@ -155,7 +154,8 @@
155
154
  "./ui-locale": "./dist/ui-locale.js",
156
155
  "./unified-diff": "./dist/unified-diff.js",
157
156
  "./dev-single-instance": "./dist/dev-single-instance.js",
158
- "./maka-wordmark": "./dist/maka-wordmark.js"
157
+ "./maka-wordmark": "./dist/maka-wordmark.js",
158
+ "./workhub-action-result": "./dist/workhub-action-result.js"
159
159
  },
160
160
  "dependencies": {
161
161
  "intl-messageformat": "11.2.14"
@@ -19,13 +19,14 @@
19
19
  import { randomUUID } from 'node:crypto';
20
20
  import { link, mkdir, open, readFile, unlink } from 'node:fs/promises';
21
21
  import { join } from 'node:path';
22
+ import { stableJsonStringify } from '@maka/core/canonical-json';
22
23
  import { FileAttemptStore } from './attempt-store.js';
23
24
  import { parseExperimentSpec } from './spec.js';
24
25
  export async function openExperimentDirectory(root, spec) {
25
26
  await mkdir(root, { recursive: true });
26
27
  const specPath = join(root, 'experiment.json');
27
28
  const temporaryPath = join(root, `.experiment-${randomUUID()}.tmp`);
28
- const canonical = `${canonicalJson(spec)}\n`;
29
+ const canonical = `${stableJsonStringify(spec)}\n`;
29
30
  const temporary = await open(temporaryPath, 'wx', 0o600);
30
31
  try {
31
32
  await temporary.writeFile(canonical);
@@ -37,8 +38,9 @@ export async function openExperimentDirectory(root, spec) {
37
38
  if (error.code !== 'EEXIST')
38
39
  throw error;
39
40
  const existing = parseExperimentSpec(JSON.parse(await readFile(specPath, 'utf8')));
40
- if (canonicalJson(existing) !== canonicalJson(spec))
41
+ if (stableJsonStringify(existing) !== stableJsonStringify(spec)) {
41
42
  throw new Error('experiment spec differs');
43
+ }
42
44
  }
43
45
  finally {
44
46
  await temporary.close().catch(() => undefined);
@@ -46,14 +48,3 @@ export async function openExperimentDirectory(root, spec) {
46
48
  }
47
49
  return { root, specPath, attempts: new FileAttemptStore(join(root, 'attempts')) };
48
50
  }
49
- function canonicalJson(value) {
50
- if (Array.isArray(value))
51
- return `[${value.map(canonicalJson).join(',')}]`;
52
- if (value && typeof value === 'object') {
53
- return `{${Object.entries(value)
54
- .sort(([left], [right]) => left.localeCompare(right))
55
- .map(([key, child]) => `${JSON.stringify(key)}:${canonicalJson(child)}`)
56
- .join(',')}}`;
57
- }
58
- return JSON.stringify(value);
59
- }
@@ -60,7 +60,7 @@ export const TOOLCHAIN_IDENTITIES = {
60
60
  'deepseek-harness': {
61
61
  root: '/opt/maka-deepseek-harness-toolchain',
62
62
  version: '0.1.0-rc.6',
63
- fingerprint: 'sha256:a0882b448718ddfb7b64e33a12369c92b0064baf8388fe08a8ff64fe3dd98896',
63
+ fingerprint: 'sha256:5314e15659d4c35381ce15ca4802933d61bc3af718d7eeb8260f4fa32ccf5860',
64
64
  },
65
65
  };
66
66
  // The identity table is the profile registry: a profile without a pinned
@@ -0,0 +1,213 @@
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 { decodeInteractionAnswer, decodeInteractionRequest, interactionFormAnswerMatchesRequest, projectInteractionFormRequest, } from '@maka/core/interaction';
20
+ // Unbounded protocol strings need a visible client input limit: Core reserves
21
+ // the worst-case JSON-escaped answer within its serialized interaction budget.
22
+ // Explicit server bounds are preserved and still checked by Core admission.
23
+ const DEFAULT_STRING_MAX_LENGTH = 256;
24
+ /** Inspect raw keys and values before projection can escape control characters.
25
+ * This is a containment check, not a comparison with redacted output: a state
26
+ * may itself be identical to the redaction marker.
27
+ */
28
+ export function containsMcpFormState(value, states) {
29
+ const pending = [value];
30
+ while (pending.length) {
31
+ const item = pending.pop();
32
+ if (typeof item === 'string') {
33
+ if (states.some((state) => state.length > 0 && item.includes(state)))
34
+ return true;
35
+ }
36
+ else if (item !== null && typeof item === 'object') {
37
+ for (const [key, child] of Object.entries(item))
38
+ pending.push(key, child);
39
+ }
40
+ }
41
+ return false;
42
+ }
43
+ function record(value) {
44
+ if (value === null || typeof value !== 'object' || Array.isArray(value))
45
+ throw new Error();
46
+ const prototype = Object.getPrototypeOf(value);
47
+ if (prototype !== Object.prototype && prototype !== null)
48
+ throw new Error();
49
+ return value;
50
+ }
51
+ function keys(value, allowed) {
52
+ if (Object.keys(value).some((key) => !allowed.includes(key)))
53
+ throw new Error();
54
+ }
55
+ function select(value, names) {
56
+ return Object.fromEntries(names.filter((name) => Object.hasOwn(value, name)).map((name) => [name, value[name]]));
57
+ }
58
+ function options(value, titles) {
59
+ if (!Array.isArray(value) ||
60
+ (titles !== undefined && (!Array.isArray(titles) || titles.length !== value.length)))
61
+ throw new Error();
62
+ return value.map((entry, index) => ({
63
+ value: entry,
64
+ label: Array.isArray(titles) ? titles[index] : entry,
65
+ }));
66
+ }
67
+ function titledOptions(value) {
68
+ if (!Array.isArray(value))
69
+ throw new Error();
70
+ return value.map((entry) => {
71
+ const option = record(entry);
72
+ keys(option, ['const', 'title']);
73
+ return { value: option.const, label: option.title };
74
+ });
75
+ }
76
+ function field(name, value, required) {
77
+ const schema = record(value);
78
+ const sharedKeys = ['type', 'title', 'description', 'default'];
79
+ const shared = {
80
+ name,
81
+ label: Object.hasOwn(schema, 'title') ? schema.title : name,
82
+ required,
83
+ ...select(schema, ['description', 'default']),
84
+ };
85
+ if (schema.type === 'string') {
86
+ if (Object.hasOwn(schema, 'enum')) {
87
+ keys(schema, [...sharedKeys, 'enum', 'enumNames']);
88
+ return { ...shared, kind: 'single_select', options: options(schema.enum, schema.enumNames) };
89
+ }
90
+ if (Object.hasOwn(schema, 'oneOf')) {
91
+ keys(schema, [...sharedKeys, 'oneOf']);
92
+ return { ...shared, kind: 'single_select', options: titledOptions(schema.oneOf) };
93
+ }
94
+ keys(schema, [...sharedKeys, 'minLength', 'maxLength', 'format']);
95
+ return {
96
+ ...shared,
97
+ kind: 'string',
98
+ ...select(schema, ['minLength', 'maxLength', 'format']),
99
+ ...(schema.maxLength === undefined ? { maxLength: DEFAULT_STRING_MAX_LENGTH } : {}),
100
+ };
101
+ }
102
+ if (schema.type === 'number' || schema.type === 'integer') {
103
+ keys(schema, [...sharedKeys, 'minimum', 'maximum']);
104
+ // Core validates numeric ranges; an integer-only interval may additionally be empty.
105
+ if (schema.type === 'integer' &&
106
+ typeof schema.minimum === 'number' &&
107
+ typeof schema.maximum === 'number' &&
108
+ Math.ceil(schema.minimum) > Math.floor(schema.maximum))
109
+ throw new Error();
110
+ return { ...shared, kind: schema.type, ...select(schema, ['minimum', 'maximum']) };
111
+ }
112
+ if (schema.type === 'boolean') {
113
+ keys(schema, sharedKeys);
114
+ return { ...shared, kind: 'boolean' };
115
+ }
116
+ if (schema.type === 'array') {
117
+ keys(schema, [...sharedKeys, 'items', 'minItems', 'maxItems']);
118
+ const items = record(schema.items);
119
+ let choices;
120
+ if (Object.hasOwn(items, 'anyOf')) {
121
+ keys(items, ['anyOf']);
122
+ choices = titledOptions(items.anyOf);
123
+ }
124
+ else {
125
+ keys(items, ['type', 'enum']);
126
+ if (items.type !== 'string')
127
+ throw new Error();
128
+ choices = options(items.enum);
129
+ }
130
+ return {
131
+ ...shared,
132
+ kind: 'multi_select',
133
+ options: choices,
134
+ ...select(schema, ['minItems', 'maxItems']),
135
+ };
136
+ }
137
+ throw new Error();
138
+ }
139
+ /** Adapt one embedded MCP form request without exposing protocol state to the UI. */
140
+ export function prepareMcpForm(request, requester) {
141
+ try {
142
+ const embedded = record(request);
143
+ keys(embedded, ['method', 'params']);
144
+ if (embedded.method !== 'elicitation/create')
145
+ throw new Error();
146
+ const params = record(embedded.params);
147
+ keys(params, ['mode', 'message', 'requestedSchema', '_meta']);
148
+ if (params.mode !== undefined && params.mode !== 'form')
149
+ throw new Error();
150
+ const schema = record(params.requestedSchema);
151
+ keys(schema, [
152
+ 'type',
153
+ 'properties',
154
+ 'required',
155
+ '$schema',
156
+ 'title',
157
+ 'description',
158
+ 'additionalProperties',
159
+ ]);
160
+ if (schema.type !== 'object' ||
161
+ (schema.additionalProperties !== undefined && schema.additionalProperties !== false))
162
+ throw new Error();
163
+ for (const annotation of ['$schema', 'title', 'description']) {
164
+ if (schema[annotation] !== undefined && typeof schema[annotation] !== 'string')
165
+ throw new Error();
166
+ }
167
+ const properties = record(schema.properties);
168
+ const required = schema.required === undefined ? [] : schema.required;
169
+ if (!Array.isArray(required) ||
170
+ required.some((name) => typeof name !== 'string' || !Object.hasOwn(properties, name)) ||
171
+ new Set(required).size !== required.length)
172
+ throw new Error();
173
+ const decoded = decodeInteractionRequest({
174
+ kind: 'form',
175
+ toolUseId: 'mcp-form',
176
+ message: params.message,
177
+ requester,
178
+ fields: Object.entries(properties).map(([name, schema]) => field(name, schema, required.includes(name))),
179
+ });
180
+ if (decoded.kind !== 'form')
181
+ throw new Error();
182
+ const projected = projectInteractionFormRequest(decoded);
183
+ return {
184
+ form: {
185
+ message: projected.message,
186
+ requester: projected.requester,
187
+ fields: projected.fields,
188
+ },
189
+ respond(result) {
190
+ try {
191
+ const answer = decodeInteractionAnswer({ ...result, kind: 'form' });
192
+ if (answer.kind !== 'form' || !interactionFormAnswerMatchesRequest(projected, answer))
193
+ throw new Error();
194
+ if (answer.action !== 'accept')
195
+ return { action: answer.action };
196
+ return {
197
+ action: 'accept',
198
+ content: Object.fromEntries(Object.entries(answer.values).map(([name, value]) => [
199
+ name,
200
+ typeof value === 'object' ? [...value] : value,
201
+ ])),
202
+ };
203
+ }
204
+ catch {
205
+ throw new Error('Invalid MCP form response');
206
+ }
207
+ },
208
+ };
209
+ }
210
+ catch {
211
+ throw new Error('Unsupported or invalid MCP form request');
212
+ }
213
+ }