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
@@ -17,9 +17,28 @@
17
17
  * under the License.
18
18
  */
19
19
  import { createHash } from 'node:crypto';
20
- import { buildToolResultArchiveResourceRef, TOOL_RESULT_ARCHIVE_READ_INSTRUCTIONS, } from './tool-result-archive-resource.js';
20
+ import { buildToolResultArchiveResourceRef, TOOL_RESULT_ARCHIVE_READ_INSTRUCTIONS, isLedgerArchiveIdentity, } from './tool-result-archive-resource.js';
21
21
  export const ARCHIVED_TOOL_RESULT_PLACEHOLDER_KIND = 'maka.archived_tool_result';
22
22
  export const ARCHIVED_TOOL_RESULT_REWRITE_VERSION = 1;
23
+ export function buildLedgerArchivedToolResultPlaceholder(input) {
24
+ return {
25
+ storage: 'ledger',
26
+ runtimeEventId: input.runtimeEventId,
27
+ toolCallId: input.toolCallId,
28
+ toolName: input.toolName,
29
+ sourceProjectionDigest: input.sourceProjectionDigest,
30
+ ...(input.previousTransitionId ? { previousTransitionId: input.previousTransitionId } : {}),
31
+ bodySha256: input.bodySha256,
32
+ originalBytes: input.originalBytes,
33
+ originalEstimatedTokens: input.originalEstimatedTokens,
34
+ reason: input.reason,
35
+ ...(input.supersession ? { supersession: input.supersession } : {}),
36
+ kind: ARCHIVED_TOOL_RESULT_PLACEHOLDER_KIND,
37
+ rewriteVersion: 2,
38
+ resourceRef: buildToolResultArchiveResourceRef(input),
39
+ readInstructions: TOOL_RESULT_ARCHIVE_READ_INSTRUCTIONS,
40
+ };
41
+ }
23
42
  export function stableToolResultArchiveArtifactId(event) {
24
43
  return `tool-result-archive-${createHash('sha256')
25
44
  .update(JSON.stringify({
@@ -57,10 +76,12 @@ export function isArchivedToolResultPlaceholder(value) {
57
76
  if (!value || typeof value !== 'object')
58
77
  return false;
59
78
  const candidate = value;
79
+ const ledgerIdentity = isLedgerArchiveIdentity(value);
60
80
  return (candidate.kind === ARCHIVED_TOOL_RESULT_PLACEHOLDER_KIND &&
61
- candidate.rewriteVersion === ARCHIVED_TOOL_RESULT_REWRITE_VERSION &&
62
- typeof candidate.artifactId === 'string' &&
63
- candidate.artifactId.length > 0 &&
81
+ ((candidate.rewriteVersion === 1 &&
82
+ typeof candidate.artifactId === 'string' &&
83
+ candidate.artifactId.length > 0) ||
84
+ (candidate.rewriteVersion === 2 && ledgerIdentity)) &&
64
85
  typeof candidate.runtimeEventId === 'string' &&
65
86
  candidate.runtimeEventId.length > 0 &&
66
87
  typeof candidate.toolCallId === 'string' &&
@@ -100,6 +121,8 @@ function isValidSupersession(value) {
100
121
  export function withToolResultArchiveResourceRef(value) {
101
122
  if (!isArchivedToolResultPlaceholder(value))
102
123
  return value;
124
+ if (value.rewriteVersion === 2)
125
+ return buildLedgerArchivedToolResultPlaceholder(value);
103
126
  return {
104
127
  ...value,
105
128
  resourceRef: buildToolResultArchiveResourceRef({
@@ -78,6 +78,7 @@
78
78
  "./plugin-composition-loader": "./dist/plugin-composition-loader.js",
79
79
  "./plugin-kernel": "./dist/plugin-kernel.js",
80
80
  "./plugin-runtime": "./dist/plugin-runtime.js",
81
+ "./plugin-tool-service": "./dist/plugin-tool-service.js",
81
82
  "./process-tree-terminator": "./dist/process-tree-terminator.js",
82
83
  "./provider-request-telemetry": "./dist/provider-request-telemetry.js",
83
84
  "./request-customization-fetch": "./dist/request-customization-fetch.js",
@@ -78,6 +78,12 @@ export class RuntimeHostRequestInterruptedError extends Error {
78
78
  this.retryable = mode === 'query';
79
79
  }
80
80
  }
81
+ // A Host response can reach the Client before the Host's transport write
82
+ // promise resumes and retires that request. Leave one slot free so replacing
83
+ // the observed response cannot transiently cross the Host's hard limit. The
84
+ // Host serializes outbound writes, so at most one response occupies this
85
+ // acknowledgement window.
86
+ const CLIENT_MAX_IN_FLIGHT_DOMAIN_REQUESTS = RUNTIME_HOST_MAX_IN_FLIGHT_DOMAIN_REQUESTS - 1;
81
87
  class RuntimeHostConnectionImpl {
82
88
  cooperativeHandoff;
83
89
  rootId;
@@ -212,7 +218,7 @@ class RuntimeHostConnectionImpl {
212
218
  }
213
219
  #drainDomainRequests() {
214
220
  while (!this.#terminalError &&
215
- this.#inFlightDomainRequests < RUNTIME_HOST_MAX_IN_FLIGHT_DOMAIN_REQUESTS) {
221
+ this.#inFlightDomainRequests < CLIENT_MAX_IN_FLIGHT_DOMAIN_REQUESTS) {
216
222
  const queued = this.#queuedDomainFrames.shift();
217
223
  if (!queued)
218
224
  return;
@@ -243,9 +249,28 @@ class RuntimeHostConnectionImpl {
243
249
  }
244
250
  return status;
245
251
  }
246
- openSessionSubscription(input, timeoutMs) {
252
+ async openSessionSubscription(input, timeoutMs) {
253
+ const deadline = Date.now() + (timeoutMs === undefined ? 30_000 : requireTimeout(timeoutMs, 'timeoutMs'));
254
+ for (;;) {
255
+ try {
256
+ return await this.#openSessionSubscription(input, Math.max(1, deadline - Date.now()), timeoutMs);
257
+ }
258
+ catch (error) {
259
+ if (!(error instanceof RuntimeHostOperationError) ||
260
+ error.code !== 'transcript_preparing' ||
261
+ input.transcript.kind !== 'tail' ||
262
+ this.#terminalError ||
263
+ Date.now() >= deadline)
264
+ throw error;
265
+ // Each refusal committed a bounded, resumable index batch. Keep the
266
+ // caller in its loading state and yield before requesting more work.
267
+ await new Promise((resolve) => setTimeout(resolve, 25));
268
+ }
269
+ }
270
+ }
271
+ #openSessionSubscription(input, openTimeoutMs, requestTimeoutMs) {
247
272
  const expectedSessionId = input.sessionId;
248
- return this.#requestOperation('subscription.open', input, timeoutMs, (result) => {
273
+ return this.#requestOperation('subscription.open', input, openTimeoutMs, (result) => {
249
274
  if (result.hostEpoch !== this.hostEpoch) {
250
275
  throw new RuntimeHostSubscriptionError('host_epoch_changed', 'Session subscription opened for a different Host Epoch');
251
276
  }
@@ -255,9 +280,9 @@ class RuntimeHostConnectionImpl {
255
280
  if (this.#subscriptions.has(result.subscriptionId)) {
256
281
  throw new RuntimeHostSubscriptionError('correlation_changed', 'Runtime Host returned a duplicate subscription identity');
257
282
  }
258
- const subscription = new ClientSessionSubscription(result, () => this.#closeSessionSubscription(result.subscriptionId), (query) => this.request('session.transcript.page', query, timeoutMs), async () => {
283
+ const subscription = new ClientSessionSubscription(result, () => this.#closeSessionSubscription(result.subscriptionId), (query) => this.request('session.transcript.page', query, requestTimeoutMs), async () => {
259
284
  try {
260
- await this.request('session.transcript.overlay.release', { subscriptionId: result.subscriptionId }, timeoutMs);
285
+ await this.request('session.transcript.overlay.release', { subscriptionId: result.subscriptionId }, requestTimeoutMs);
261
286
  }
262
287
  catch (error) {
263
288
  this.#fail(asError(error));
@@ -24,7 +24,7 @@ export function formatHostHandoff(view, locale) {
24
24
  ? {
25
25
  busy: '背景服務仍在使用中',
26
26
  activity_unknown: '需要確認是否停止背景服務',
27
- operator_required: '需要在服務所在位置處理',
27
+ operator_required: '背景服務需要手動更新',
28
28
  repair_required: '背景服務需要修復',
29
29
  retry_required: '暫時無法完成交接',
30
30
  }
@@ -32,41 +32,78 @@ export function formatHostHandoff(view, locale) {
32
32
  ? {
33
33
  busy: '后台服务仍在使用中',
34
34
  activity_unknown: '需要确认是否停止后台服务',
35
- operator_required: '需要在服务所在位置处理',
35
+ operator_required: '后台服务需要手动更新',
36
36
  repair_required: '后台服务需要修复',
37
37
  retry_required: '暂时无法完成交接',
38
38
  }
39
39
  : {
40
40
  busy: 'Your background service is still in use',
41
41
  activity_unknown: 'Confirm before stopping the service',
42
- operator_required: 'Action is needed where the service runs',
42
+ operator_required: 'The background service needs a manual update',
43
43
  repair_required: 'Your background service needs repair',
44
44
  retry_required: 'The handoff could not finish yet',
45
45
  };
46
46
  const descriptions = tw
47
47
  ? {
48
48
  busy: '其他連線或正在執行的工作阻止了自動交接。停止並繼續可能中斷這些工作。',
49
- activity_unknown: '這個版本無法提供足夠的活動資訊。停止服務可能中斷其他視窗或裝置上的工作。',
50
- operator_required: `目前的用戶端沒有替換此服務的權限。請在 ${view.target.name} 上,由管理該服務的使用者更新或停止服務。`,
49
+ activity_unknown: '背景服務與目前用戶端不相容,且無法確認有哪些工作仍在執行。停止並繼續會重新啟動服務,可能中斷其他視窗或裝置上的工作。',
50
+ operator_required: `目前無法從這裡更新背景服務。請透過 ${view.target.name} 上管理此服務的應用程式或命令更新,再重試。`,
51
51
  repair_required: '上次啟動或交接未能完成。可以安全重試;若仍失敗,請複製診斷資訊。',
52
52
  retry_required: '服務狀態發生了變化,或交接尚未完成。可以安全重試,不會預設中斷工作。',
53
53
  }
54
54
  : zh
55
55
  ? {
56
56
  busy: '其它连接或正在执行的工作阻止了自动交接。停止并继续可能中断这些工作。',
57
- activity_unknown: '这个版本无法提供足够的活动信息。停止服务可能中断其它窗口或设备上的工作。',
58
- operator_required: `当前客户端没有替换此服务的权限。请在 ${view.target.name} 上,由管理该服务的用户更新或停止服务。`,
57
+ activity_unknown: '后台服务与当前客户端不兼容,且无法确认有哪些工作仍在运行。停止并继续会重新启动服务,可能中断其他窗口或设备上的工作。',
58
+ operator_required: `目前无法从这里更新后台服务。请通过 ${view.target.name} 上管理此服务的应用或命令更新,然后重试。`,
59
59
  repair_required: '上次启动或交接未能完成。可以安全重试;若仍失败,请复制诊断信息。',
60
60
  retry_required: '服务状态发生了变化,或交接尚未完成。可以安全重试,不会默认中断工作。',
61
61
  }
62
62
  : {
63
63
  busy: 'Other connections or work in progress prevent an automatic handoff. Stopping the service may interrupt that work.',
64
- activity_unknown: 'This version cannot provide enough activity information. Stopping it may interrupt work in other windows or on other devices.',
65
- operator_required: `This client cannot replace the service. Ask its operator to update or stop it on ${view.target.name}.`,
64
+ activity_unknown: 'The background service is incompatible with this client, and its active work is unknown. Stop and continue restarts it and may interrupt work in other windows or devices.',
65
+ operator_required: `This client cannot update the background service here. Use its managing app or operator command on ${view.target.name}, then retry.`,
66
66
  repair_required: 'The last startup or handoff did not finish. Retry safely, or copy diagnostics if it still fails.',
67
67
  retry_required: 'The service changed or the handoff has not finished. A safe retry will not interrupt work by default.',
68
68
  };
69
+ if (view.recoveryBlocker && view.reason === 'operator_required') {
70
+ const guidance = zh
71
+ ? tw
72
+ ? {
73
+ managed: '此背景服務由已安裝的管理程式維護。請在服務的管理應用程式中更新,再回到這裡重試。',
74
+ owner: '此背景服務屬於另一個 Maka 安裝。請使用管理它的 Maka 安裝更新,再重試。',
75
+ installation: '這次啟動使用暫存安裝,無法接管現有背景服務。請使用已安裝的 Maka 更新服務,再重試。',
76
+ identity: '無法確認舊背景服務的處理程序身分,因此不能安全停止它。請關閉啟動它的 Maka 或透過其管理程式停止服務,再重試。',
77
+ }
78
+ : {
79
+ managed: '此后台服务由已安装的管理程序维护。请在服务的管理应用中更新,再回到这里重试。',
80
+ owner: '此后台服务属于另一个 Maka 安装。请使用管理它的 Maka 安装更新,然后重试。',
81
+ installation: '本次启动使用临时安装,无法接管现有后台服务。请使用已安装的 Maka 更新服务,然后重试。',
82
+ identity: '无法确认旧后台服务的进程身份,因此不能安全停止它。请关闭启动它的 Maka 或通过其管理程序停止服务,然后重试。',
83
+ }
84
+ : {
85
+ managed: 'An installed operator manages this background service. Update it through its managing app, then return here and retry.',
86
+ owner: 'Another Maka installation owns this background service. Update it using that installation, then retry.',
87
+ installation: 'This temporary installation cannot take over the existing background service. Update it using an installed Maka, then retry.',
88
+ identity: 'The old background process could not be identified safely. Close the Maka instance that started it or stop it through its operator, then retry.',
89
+ };
90
+ descriptions.operator_required = guidance[view.recoveryBlocker];
91
+ }
69
92
  const activity = view.activity;
93
+ const background = activity?.drainResidencies;
94
+ const backgroundFacts = !activity
95
+ ? ''
96
+ : background !== undefined
97
+ ? tw
98
+ ? `${background} 個背景工作`
99
+ : zh
100
+ ? `${background} 个后台工作`
101
+ : `${background} background activities`
102
+ : tw
103
+ ? '背景工作數量未知'
104
+ : zh
105
+ ? '后台工作数量未知'
106
+ : 'Background activity count unknown';
70
107
  const facts = activity
71
108
  ? tw
72
109
  ? `${activity.connections} 個連線 · ${activity.activeOperations} 個進行中的操作`
@@ -81,10 +118,10 @@ export function formatHostHandoff(view, locale) {
81
118
  ? 'Maka 会持续检查,并在可以安全继续时自动继续。'
82
119
  : 'Maka keeps checking and continues automatically when it is safe.'
83
120
  : tw
84
- ? 'Maka 會持續檢查。常駐服務不會僅因等待而結束,可能需要你採取操作。'
121
+ ? 'Maka 會持續檢查。若狀態沒有改變,等待或重試不會解決此問題。'
85
122
  : zh
86
- ? 'Maka 会持续检查。常驻服务不会仅因等待而退出,可能需要你采取操作。'
87
- : 'Maka keeps checking. A persistent service will not exit just because you wait; action may be needed.';
123
+ ? 'Maka 会持续检查。若状态没有变化,等待或重试不会解决此问题。'
124
+ : 'Maka keeps checking. Waiting or retrying will not resolve this unless the service state changes.';
88
125
  const repairNotice = view.operation === 'repair'
89
126
  ? tw
90
127
  ? '修復將使用目前應用程式配套的版本,可能替換現有服務版本。'
@@ -150,7 +187,9 @@ export function formatHostHandoff(view, locale) {
150
187
  : zh
151
188
  ? '正在完成交接或安全收尾,请稍候。'
152
189
  : 'Finishing the handoff or its safe recovery. Please wait.'
153
- : [facts, waiting, repairNotice, view.operatorStep].filter(Boolean).join('\n'),
190
+ : [facts, backgroundFacts, waiting, repairNotice, view.operatorStep]
191
+ .filter(Boolean)
192
+ .join('\n'),
154
193
  actions: view.actions.map((action) => ({ action, label: labels[action] })),
155
194
  };
156
195
  }
@@ -247,6 +247,7 @@ function projectBlocker(blocker, revision, recovery) {
247
247
  ...(replacement ? { operation: replacement.kind } : {}),
248
248
  actions: replacement?.canInterrupt ? ['cancel', 'retry', 'interrupt'] : ['cancel', 'retry'],
249
249
  defaultAction: 'cancel',
250
+ ...(blocker.recoveryBlocker ? { recoveryBlocker: blocker.recoveryBlocker } : {}),
250
251
  ...(blocker.operatorStep ? { operatorStep: blocker.operatorStep } : {}),
251
252
  ...((recovery ?? blocker.diagnostic)
252
253
  ? { diagnostic: redactSecrets((recovery ?? blocker.diagnostic)).slice(0, 8_192) }
@@ -265,6 +266,7 @@ function blockerSignature(blocker) {
265
266
  blocker.replacement?.canReplaceIdle,
266
267
  blocker.replacement?.canInterrupt,
267
268
  blocker.operatorStep,
269
+ blocker.recoveryBlocker,
268
270
  blocker.diagnostic,
269
271
  ]);
270
272
  }
@@ -23,7 +23,7 @@
23
23
  * transport detail here so lifecycle owners can model the operation as
24
24
  * retirement instead of spreading update-specific authority.
25
25
  */
26
- export async function prepareConnectedRuntimeHostRetirement(connection, mode, timeoutMs, signal) {
26
+ export async function prepareConnectedRuntimeHostRetirement(connection, mode, timeoutMs, signal, options) {
27
27
  signal?.throwIfAborted();
28
28
  // Retirement uses a dedicated lifecycle connection. Closing it cancels the
29
29
  // Host's reversible preparation; a committed retirement remains committed.
@@ -35,7 +35,9 @@ export async function prepareConnectedRuntimeHostRetirement(connection, mode, ti
35
35
  return await connection.request('host.upgrade.prepare', {
36
36
  expectedHostEpoch: connection.hostEpoch,
37
37
  allowInterruptActiveTasks: mode === 'interrupt_active_work',
38
- ...(mode === 'refuse_active_work' && connection.cooperativeHandoff
38
+ ...(mode === 'refuse_active_work' &&
39
+ connection.cooperativeHandoff &&
40
+ options?.allowCooperativeHandoff !== false
39
41
  ? { allowCooperativeHandoff: true }
40
42
  : {}),
41
43
  }, timeoutMs);
@@ -149,6 +149,23 @@ class RuntimeHostPeerClientImpl {
149
149
  };
150
150
  }
151
151
  subscribeRoutes(peerId, listener) {
152
+ const snapshot = () => this.#connectionResolution({ peerId, routeHints: [], directDeadlineMs: 0 }, 'application', false);
153
+ let previous = snapshot();
154
+ let connected = this.isConnected(peerId);
155
+ return this.#subscribeRouteResolution(peerId, () => {
156
+ const next = snapshot();
157
+ const nextConnected = this.isConnected(peerId);
158
+ const available = next.state === 'available' &&
159
+ (!sameCandidates(previous, next) || (nextConnected && !connected));
160
+ previous = next;
161
+ connected = nextConnected;
162
+ // A dial's own recovery sweep toggles recovering/exhausted. Waking its
163
+ // reconnect owner for those transitions would bypass every backoff.
164
+ if (available)
165
+ listener();
166
+ });
167
+ }
168
+ #subscribeRouteResolution(peerId, listener) {
152
169
  const listeners = this.#routeListeners.get(peerId) ?? new Set();
153
170
  const first = listeners.size === 0;
154
171
  listeners.add(listener);
@@ -362,7 +379,7 @@ class RuntimeHostPeerClientImpl {
362
379
  updateTail = updateTail.then(() => updatePeerConnect(endpoint, requestId, candidates, () => settled), () => updatePeerConnect(endpoint, requestId, candidates, () => settled));
363
380
  void updateTail.catch(() => undefined);
364
381
  };
365
- const unsubscribe = kind === 'application' ? this.subscribeRoutes(input.peerId, update) : undefined;
382
+ const unsubscribe = kind === 'application' ? this.#subscribeRouteResolution(input.peerId, update) : undefined;
366
383
  let connection;
367
384
  try {
368
385
  connection = endpoint[kind === 'application' ? 'connect' : 'connectMeshControl']({
@@ -43,6 +43,7 @@ export class ClientSessionSubscription {
43
43
  #expectedSessionId;
44
44
  #queue = [];
45
45
  #ptyListeners = new Set();
46
+ #sessionDomainListeners = new Set();
46
47
  #queuedBytes = 0;
47
48
  #expectedSequence;
48
49
  #latestProjectionRevision;
@@ -79,6 +80,12 @@ export class ClientSessionSubscription {
79
80
  this.#ptyListeners.add(listener);
80
81
  return () => this.#ptyListeners.delete(listener);
81
82
  }
83
+ subscribeSessionDomainChanges(listener) {
84
+ if (this.#done || this.#terminalError || this.#closing)
85
+ return () => undefined;
86
+ this.#sessionDomainListeners.add(listener);
87
+ return () => this.#sessionDomainListeners.delete(listener);
88
+ }
82
89
  next() {
83
90
  const queued = this.#queue.shift();
84
91
  if (queued) {
@@ -369,12 +376,23 @@ export class ClientSessionSubscription {
369
376
  }
370
377
  this.#latestTranscriptThroughSequence = frame.throughSequence;
371
378
  }
379
+ if (frame.kind === 'subscription.session_domain_changed') {
380
+ for (const listener of this.#sessionDomainListeners) {
381
+ try {
382
+ listener(frame);
383
+ }
384
+ catch {
385
+ /* An invalidation consumer cannot terminate Session state. */
386
+ }
387
+ }
388
+ }
372
389
  this.#offer(frame);
373
390
  if (frame.kind === 'subscription.closed')
374
391
  this.#doneAfterQueue = true;
375
392
  }
376
393
  finish() {
377
394
  this.#ptyListeners.clear();
395
+ this.#sessionDomainListeners.clear();
378
396
  if (this.#done || this.#terminalError)
379
397
  return;
380
398
  this.#doneAfterQueue = true;
@@ -386,6 +404,7 @@ export class ClientSessionSubscription {
386
404
  }
387
405
  fail(error) {
388
406
  this.#ptyListeners.clear();
407
+ this.#sessionDomainListeners.clear();
389
408
  if (this.#done || this.#terminalError)
390
409
  return;
391
410
  this.#terminalError = error;
@@ -21,6 +21,7 @@ import { chmod, lstat, mkdtemp, readdir, rm, rmdir, unlink } from 'node:fs/promi
21
21
  import { tmpdir } from 'node:os';
22
22
  import { join } from 'node:path';
23
23
  import { truncateUtf8 } from '@maka/core/diagnostic-log';
24
+ import { isNodeError } from '../node-error.js';
24
25
  const FALLBACK_ENDPOINT_ROOT = '/tmp';
25
26
  const PORTABLE_UNIX_SOCKET_PATH_LIMIT = 100;
26
27
  const ENDPOINT_SOCKET_NAME = 'h.sock';
@@ -302,6 +303,3 @@ function currentUid() {
302
303
  }
303
304
  return process.getuid();
304
305
  }
305
- function isNodeError(error, code) {
306
- return (error instanceof Error && 'code' in error && error.code === code);
307
- }
@@ -0,0 +1,22 @@
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
+ /** Narrows a caught value to a Node errno error with one exact error code. */
20
+ export function isNodeError(error, code) {
21
+ return error instanceof Error && 'code' in error && error.code === code;
22
+ }
@@ -27,6 +27,7 @@ import { z } from 'zod';
27
27
  import { isCanonicalRuntimeHostWebSocketPath } from '../protocol/websocket-path.js';
28
28
  import { runtimeHostWebRtcStunPolicySchema } from '../webrtc-stun-policy.js';
29
29
  import { isProductReleaseVersion, isSha512PackageIntegrity, resolveRuntimeHostNpmDeploymentLayout, } from './update-package-evidence.js';
30
+ import { isNodeError } from '../node-error.js';
30
31
  export const RUNTIME_HOST_MANAGED_DEPLOYMENT_CONFIG_FILE = 'runtime-host-deployment.json';
31
32
  const SCHEMA_VERSION = 1;
32
33
  const MAX_DOCUMENT_BYTES = 256 * 1024;
@@ -824,6 +825,3 @@ function deploymentIo(message, cause) {
824
825
  cause,
825
826
  });
826
827
  }
827
- function isNodeError(error, code) {
828
- return error instanceof Error && 'code' in error && error.code === code;
829
- }
@@ -20,7 +20,6 @@ export const PEER_MESH_MAX_MEMBERS = 64;
20
20
  export const PEER_MESH_MAX_MESHES = 16;
21
21
  export const PEER_MESH_MAX_PENDING_INVITATIONS = 32;
22
22
  export const PEER_MESH_MAX_INVITATION_RECORDS = PEER_MESH_MAX_PENDING_INVITATIONS * 3;
23
- export const PEER_MESH_MAX_ROUTE_HINTS = 16;
24
23
  export const PEER_MESH_MAX_TRANSIT_RELAY_ADDRESSES = 256;
25
24
  export const PEER_MESH_MAX_TRANSIT_ADDRESSES_PER_RELAY = 4;
26
25
  export const PEER_MESH_MEMBER_ADVERTISEMENT_MAX_BYTES = 2 * 1024;
@@ -20,7 +20,7 @@ import { createHash, createPrivateKey, createPublicKey, generateKeyPairSync, ran
20
20
  import { decodePeerMeshInvitation as decodePeerMeshInvitationWire, } from '../protocol/peer-mesh.js';
21
21
  import { PEER_MESH_MEMBER_ADVERTISEMENT_MAX_BYTES, PEER_MESH_MAX_MEMBERS } from './limits.js';
22
22
  import { canonicalPeerMeshDisplayName } from './display-name.js';
23
- export { PEER_MESH_MAX_INVITATION_RECORDS, PEER_MESH_MAX_MEMBERS, PEER_MESH_MAX_MESHES, PEER_MESH_MAX_PENDING_INVITATIONS, PEER_MESH_MAX_ROUTE_HINTS, PEER_MESH_MAX_TRANSIT_ADDRESSES_PER_RELAY, PEER_MESH_MAX_TRANSIT_RELAY_ADDRESSES, PEER_MESH_MEMBER_ADVERTISEMENT_MAX_BYTES, } from './limits.js';
23
+ export { PEER_MESH_MAX_INVITATION_RECORDS, PEER_MESH_MAX_MEMBERS, PEER_MESH_MAX_MESHES, PEER_MESH_MAX_PENDING_INVITATIONS, PEER_MESH_MAX_TRANSIT_ADDRESSES_PER_RELAY, PEER_MESH_MAX_TRANSIT_RELAY_ADDRESSES, } from './limits.js';
24
24
  export function generatePeerMeshAuthorityKeyPair() {
25
25
  const { publicKey, privateKey } = generateKeyPairSync('ed25519');
26
26
  return Object.freeze({
@@ -20,6 +20,7 @@ import { chmod, lstat, mkdir, open, readFile, rename, unlink } from 'node:fs/pro
20
20
  import { dirname, join } from 'node:path';
21
21
  import { performance } from 'node:perf_hooks';
22
22
  import { authenticateSignedPeerReachabilityLease, canonicalPeerReachabilityLease, decodeSignedPeerReachabilityLease, isPeerReachabilityLeaseCurrent, PEER_REACHABILITY_LEASE_TTL_MS, PEER_REACHABILITY_REFRESH_LEAD_MS, peerReachabilityLeaseReceipt, peerReachabilityLeaseSigningBytes, samePeerReachabilityRoutes, verifySignedPeerReachabilityLease, } from './model.js';
23
+ import { isNodeError } from '../node-error.js';
23
24
  const STATE_FILE = 'peer-reachability.json';
24
25
  const MAX_STATE_BYTES = 64 * 1_024;
25
26
  export async function openPeerReachabilityPublisher(input) {
@@ -240,6 +241,3 @@ async function syncDirectory(path) {
240
241
  await handle.close();
241
242
  }
242
243
  }
243
- function isNodeError(error, code) {
244
- return error instanceof Error && 'code' in error && error.code === code;
245
- }
@@ -62,7 +62,15 @@ export const RUNTIME_HOST_REGISTRATION_SCHEMA_VERSION = 1;
62
62
  export const RUNTIME_HOST_PROTOCOL_VERSION = 0;
63
63
  // Increment when the same protocol version no longer guarantees safe Client-Host
64
64
  // interoperability. Mismatches are rejected before domain commands are admitted.
65
- export const RUNTIME_HOST_COMPATIBILITY_EPOCH = 130;
65
+ export const RUNTIME_HOST_COMPATIBILITY_EPOCH = 135;
66
+ // 135: WorkHub model Turns replace direct action proposals with active-Turn task tools.
67
+ // 134: Coordination actions own real Runtime Turns. Removes the synthetic record
68
+ // operation, projects typed action receipts and admitted action identities, and
69
+ // distinguishes stale candidate refusals and resumable transcript preparation.
70
+ // 133: WorkHub actions carry attachments and new-Work model/permission defaults.
71
+ // Epoch-132 peers reject these additional fields on strict action shapes.
72
+ // 132: new Tool Result archives use versioned ledger references, not Artifact payloads.
73
+ // 131: Logical model steps bind durable Request Composition identities.
66
74
  // 130: Turn contributions carry the optional bounded `failureMessage` diagnostic.
67
75
  // Epoch-129 peers reject this added field on the strict contribution shape.
68
76
  // 129: Turn states and Turn records drop `partialOutputRetained`. The fact was
@@ -218,9 +218,10 @@ export const REMOTE_OWNER_OPERATION_GRANTS = Object.freeze([
218
218
  'usage.query',
219
219
  'web-search.execute',
220
220
  'workhub.coordination.answer',
221
- 'workhub.coordination.act',
221
+ 'workhub.coordination.actFromTurn',
222
222
  'workhub.coordination.candidates',
223
- 'workhub.coordination.record',
223
+ 'workhub.coordination.configureModel',
224
+ 'workhub.coordination.query',
224
225
  'workhub.coordination.resolve',
225
226
  ]);
226
227
  const REMOTE_OWNER_OPERATION_GRANT_SET = new Set(REMOTE_OWNER_OPERATION_GRANTS);
@@ -34,6 +34,7 @@ const QUERY_ERRORS = [
34
34
  ];
35
35
  const CONTROL_ERRORS = [
36
36
  ...QUERY_ERRORS,
37
+ 'unauthorized',
37
38
  'session_busy',
38
39
  'operation_conflict',
39
40
  'persistence_failed',
@@ -108,7 +108,7 @@ export const PLUGIN_PLATFORM_OPERATION_SPECS = {
108
108
  };
109
109
  function decodePluginPlatformQueryInput(value) {
110
110
  const input = requireShapedRecord(value, 'Plugin Platform query input', ['view'], ['rootId', 'cursor', 'limit']);
111
- if (!['status', 'packages', 'entries', 'failures'].includes(input.view)) {
111
+ if (!['status', 'packages', 'entries', 'tools', 'failures'].includes(input.view)) {
112
112
  throw invalidProtocolFrame('Invalid Plugin Platform query view');
113
113
  }
114
114
  const view = input.view;
@@ -125,8 +125,8 @@ function decodePluginPlatformQueryInput(value) {
125
125
  (input.rootId !== undefined || cursor !== undefined || limit !== undefined)) {
126
126
  throw invalidProtocolFrame('Plugin Platform status query does not accept paging');
127
127
  }
128
- if (input.rootId !== undefined && view !== 'entries') {
129
- throw invalidProtocolFrame('Plugin root identity is only valid for Entry queries');
128
+ if (input.rootId !== undefined && view !== 'entries' && view !== 'tools') {
129
+ throw invalidProtocolFrame('Plugin root identity is only valid for Entry and Tool queries');
130
130
  }
131
131
  let rootId;
132
132
  if (input.rootId !== undefined) {
@@ -190,7 +190,7 @@ function decodePluginPlatformQueryResult(value) {
190
190
  ]);
191
191
  if (!Array.isArray(output.items) ||
192
192
  output.items.length > 64 ||
193
- !['packages', 'entries', 'failures'].includes(view)) {
193
+ !['packages', 'entries', 'tools', 'failures'].includes(view)) {
194
194
  throw invalidProtocolFrame('Invalid Plugin Platform page');
195
195
  }
196
196
  const nextCursor = output.nextCursor === null
@@ -201,7 +201,9 @@ function decodePluginPlatformQueryResult(value) {
201
201
  ? { view, items: output.items.map(decodePackageProjection), nextCursor }
202
202
  : view === 'entries'
203
203
  ? { view, items: decodeInspections(output.items), nextCursor }
204
- : { view: 'failures', items: output.items.map(decodePlatformFailure), nextCursor };
204
+ : view === 'tools'
205
+ ? { view, items: output.items.map(decodeToolInspection), nextCursor }
206
+ : { view: 'failures', items: output.items.map(decodePlatformFailure), nextCursor };
205
207
  }
206
208
  requireEncodedByteLimit(decoded, 'Plugin Platform query result', PLUGIN_PLATFORM_QUERY_RESULT_MAX_BYTES);
207
209
  return decoded;
@@ -443,6 +445,26 @@ function decodeInspections(value) {
443
445
  };
444
446
  });
445
447
  }
448
+ function decodeToolInspection(value) {
449
+ const inspection = requireExactRecord(value, 'Plugin Tool inspection', [
450
+ 'entryId',
451
+ 'scopeId',
452
+ 'extensionId',
453
+ 'generation',
454
+ 'toolName',
455
+ 'activeCalls',
456
+ 'retired',
457
+ ]);
458
+ return {
459
+ entryId: requireId(inspection.entryId, 'Plugin Tool Entry identity'),
460
+ scopeId: decodeRootId(inspection.scopeId),
461
+ extensionId: requireId(inspection.extensionId, 'Plugin Tool package identity'),
462
+ generation: requireCount(inspection.generation, 'Plugin Tool generation'),
463
+ toolName: requireString(inspection.toolName, 'Plugin Tool name', 128),
464
+ activeCalls: requireCount(inspection.activeCalls, 'Plugin Tool active call count'),
465
+ retired: requireBoolean(inspection.retired),
466
+ };
467
+ }
446
468
  function decodeEntries(value) {
447
469
  if (!Array.isArray(value))
448
470
  throw invalidProtocolFrame('Invalid Plugin Entry list');
@@ -24,14 +24,14 @@ export const PROJECT_CATALOG_PAGE_MAX_ITEMS = 64;
24
24
  export const PROJECT_CATALOG_PAGE_MAX_BYTES = 48 * 1024;
25
25
  export const PROJECT_CATALOG_CURSOR_MAX_BYTES = 128;
26
26
  export const PROJECT_CATALOG_NAME_MAX_BYTES = 16 * 1024;
27
- export const PROJECT_CATALOG_PATH_MAX_BYTES = 4 * 1024;
27
+ const PROJECT_CATALOG_PATH_MAX_BYTES = 4 * 1024;
28
28
  export const PROJECT_DIRECTORY_PAGE_MAX_ITEMS = 128;
29
29
  export const PROJECT_DIRECTORY_PAGE_MAX_BYTES = 32 * 1024;
30
30
  export const PROJECT_DIRECTORY_MAX_ENTRIES = 4_096;
31
31
  export const PROJECT_DIRECTORY_MAX_ROOTS = 8;
32
32
  export const PROJECT_DIRECTORY_MAX_SEGMENTS = 64;
33
33
  export const PROJECT_DIRECTORY_ROOT_LABEL_MAX_BYTES = 128;
34
- export const PROJECT_DIRECTORY_ROOT_PATH_MAX_BYTES = PROJECT_CATALOG_PATH_MAX_BYTES;
34
+ const PROJECT_DIRECTORY_ROOT_PATH_MAX_BYTES = PROJECT_CATALOG_PATH_MAX_BYTES;
35
35
  export const PROJECT_DIRECTORY_SEGMENT_MAX_BYTES = 255;
36
36
  const PROJECT_DIRECTORY_ROOT_TEXT_ENCODER = new TextEncoder();
37
37
  export function canonicalProjectDirectoryRootSpec(root) {
@@ -56,6 +56,7 @@ export const SESSION_DOMAINS = [
56
56
  ];
57
57
  export const SESSION_RUNTIME_RESOURCE_CHANGES_MAX = 64;
58
58
  const SUBSCRIPTION_OPEN_ERRORS = [
59
+ 'transcript_preparing',
59
60
  'host_not_ready',
60
61
  'host_draining',
61
62
  'operation_unavailable',