maka-agent 0.2.0-dev.20.20260904 → 0.2.0-dev.22.20260905

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 (76) hide show
  1. package/dist/activation-command.js +1 -2
  2. package/dist/run-command-core.js +6 -14
  3. package/dist/runtime-host-run-command.js +6 -49
  4. package/native/runtime-host-peer/prebuilds/darwin-arm64/maka_runtime_host_peer.node +0 -0
  5. package/native/runtime-host-peer/prebuilds/linux-arm64/maka_runtime_host_peer.node +0 -0
  6. package/native/runtime-host-peer/prebuilds/linux-x64/maka_runtime_host_peer.node +0 -0
  7. package/native/runtime-host-peer/prebuilds/win32-x64/maka_runtime_host_peer.node +0 -0
  8. package/native/runtime-host-windows-task-launcher/prebuilds/win32-x64/maka-runtime-host-task-launcher.exe +0 -0
  9. package/node_modules/@maka/core/dist/artifacts.js +15 -22
  10. package/node_modules/@maka/core/dist/health.js +50 -45
  11. package/node_modules/@maka/core/dist/llm-connections.js +4 -5
  12. package/node_modules/@maka/core/dist/relative-time.js +4 -4
  13. package/node_modules/@maka/core/dist/runtime-policy/connection-catalog-codec.js +8 -2
  14. package/node_modules/@maka/core/dist/tool-quiet-preview.js +3 -3
  15. package/node_modules/@maka/core/dist/ui-locale.js +5 -3
  16. package/node_modules/@maka/runtime/dist/agent-run.js +0 -7
  17. package/node_modules/@maka/runtime/dist/ai-sdk-backend.js +87 -3844
  18. package/node_modules/@maka/runtime/dist/ai-sdk-message-projection.js +632 -0
  19. package/node_modules/@maka/runtime/dist/ai-sdk-tool-repair.js +115 -0
  20. package/node_modules/@maka/runtime/dist/ai-sdk-turn.js +2692 -0
  21. package/node_modules/@maka/runtime/dist/continuation-replay.js +4 -1
  22. package/node_modules/@maka/runtime/dist/conversation-copy.js +2 -6
  23. package/node_modules/@maka/runtime/dist/deep-research-tools.js +2 -16
  24. package/node_modules/@maka/runtime/dist/durable-tool-result-projection.js +2 -8
  25. package/node_modules/@maka/runtime/dist/goal-evaluator.js +10 -4
  26. package/node_modules/@maka/runtime/dist/history-compact-checkpoint.js +5 -12
  27. package/node_modules/@maka/runtime/dist/history-compact-ledger.js +3 -9
  28. package/node_modules/@maka/runtime/dist/history-compact-summarizer.js +49 -79
  29. package/node_modules/@maka/runtime/dist/history-compact-summary-validation.js +3 -13
  30. package/node_modules/@maka/runtime/dist/mcp-tools.js +7 -5
  31. package/node_modules/@maka/runtime/dist/model-history.js +115 -18
  32. package/node_modules/@maka/runtime/dist/openai-codex-history-compactor.js +9 -51
  33. package/node_modules/@maka/runtime/dist/provider-request-telemetry.js +93 -0
  34. package/node_modules/@maka/runtime/dist/runtime-kernel.js +0 -1
  35. package/node_modules/@maka/runtime/dist/session-manager.js +14 -15
  36. package/node_modules/@maka/runtime/dist/session-recap.js +81 -14
  37. package/node_modules/@maka/runtime-host/dist/client/connection.js +34 -33
  38. package/node_modules/@maka/runtime-host/dist/client/host-profile.js +55 -4
  39. package/node_modules/@maka/runtime-host/dist/client/index.js +1 -1
  40. package/node_modules/@maka/runtime-host/dist/client/peer-client.js +7 -4
  41. package/node_modules/@maka/runtime-host/dist/client/reconnect-lifecycle.js +9 -2
  42. package/node_modules/@maka/runtime-host/dist/protocol/artifact.js +9 -18
  43. package/node_modules/@maka/runtime-host/dist/protocol/client-capability.js +131 -34
  44. package/node_modules/@maka/runtime-host/dist/protocol/index.js +9 -1
  45. package/node_modules/@maka/runtime-host/dist/protocol/workhub-coordination.js +6 -8
  46. package/node_modules/@maka/runtime-host/dist/server/artifact-coordinator.js +6 -9
  47. package/node_modules/@maka/runtime-host/dist/server/connection-session.js +6 -0
  48. package/node_modules/@maka/runtime-host/dist/server/execution-artifacts.js +34 -5
  49. package/node_modules/@maka/runtime-host/dist/server/execution-composition.js +16 -40
  50. package/node_modules/@maka/runtime-host/dist/server/execution-model-composition.js +1 -1
  51. package/node_modules/@maka/runtime-host/dist/server/host-kernel.js +30 -7
  52. package/node_modules/@maka/runtime-host/dist/server/host-residency-registry.js +34 -19
  53. package/node_modules/@maka/runtime-host/dist/server/message-coordinator.js +3 -0
  54. package/node_modules/@maka/runtime-host/dist/server/peer-listener.js +122 -29
  55. package/node_modules/@maka/runtime-host/dist/server/session-admission-gate.js +9 -1
  56. package/node_modules/@maka/runtime-host/dist/server/session-effect-coordinator.js +1 -1
  57. package/node_modules/@maka/runtime-host/dist/server/session-revision-graph-references.js +2 -3
  58. package/node_modules/@maka/runtime-host/dist/server/workhub-coordination-action-gate.js +1 -2
  59. package/node_modules/@maka/runtime-host/dist/server/workhub-coordination-coordinator.js +32 -35
  60. package/node_modules/@maka/runtime-host/dist/transport/peer-native.js +60 -10
  61. package/node_modules/@maka/runtime-host/dist/transport/resumable-peer-stream.js +464 -0
  62. package/node_modules/@maka/storage/dist/artifact-attachments.js +7 -33
  63. package/node_modules/@maka/storage/dist/artifact-metadata-codec.js +24 -28
  64. package/node_modules/@maka/storage/dist/artifact-store.js +102 -749
  65. package/node_modules/@maka/storage/dist/artifact-stores.js +2 -97
  66. package/node_modules/@maka/storage/dist/artifact-writer-lock.js +1 -1
  67. package/node_modules/@maka/storage/dist/execution-stores.js +1 -0
  68. package/node_modules/@maka/storage/dist/operational-state-backup.js +6 -6
  69. package/node_modules/@maka/storage/dist/session-bundle-policy.js +1 -1
  70. package/node_modules/@maka/storage/dist/session-store.js +5 -10
  71. package/node_modules/@maka/storage/dist/sqlite-artifact-metadata.js +22 -21
  72. package/node_modules/@maka/storage/dist/sqlite-artifact-schema.js +55 -5
  73. package/node_modules/@maka/storage/dist/sqlite-session-metadata-store.js +105 -0
  74. package/package.json +1 -1
  75. package/node_modules/@maka/storage/dist/artifact-metadata-repository.js +0 -19
  76. package/node_modules/@maka/storage/dist/artifact-storage-layout.js +0 -26
@@ -393,8 +393,7 @@ export async function runMakaActivationCli(argv, overrides = {}) {
393
393
  if (invocation?.failure?.class === 'permission_denied') {
394
394
  return finish('blocked', 'permission_denied', undefined, 'grant_permission');
395
395
  }
396
- if ((streamBoundaryFailure && invocation?.sandboxBoundary !== 'recovered') ||
397
- invocation?.sandboxBoundary === 'unresolved') {
396
+ if (streamBoundaryFailure || invocation?.sandboxBoundary === 'unresolved') {
398
397
  return finish('blocked', 'permission_required', undefined, 'grant_permission');
399
398
  }
400
399
  if (!invocation)
@@ -175,8 +175,7 @@ export async function runMakaTextCliCore(argv, adapter, overrides = {}) {
175
175
  return 2;
176
176
  }
177
177
  let outcome;
178
- let unclassifiedBoundaryFailure = false;
179
- const boundaryFailureInvocationIds = new Set();
178
+ let boundaryFailure = false;
180
179
  let context;
181
180
  try {
182
181
  context = await deps.createContext({
@@ -204,14 +203,8 @@ export async function runMakaTextCliCore(argv, adapter, overrides = {}) {
204
203
  ...(parsed.options.hostProfileId ? { hostProfileId: parsed.options.hostProfileId } : {}),
205
204
  ...(parsed.options.projectId ? { projectId: parsed.options.projectId } : {}),
206
205
  runOutcomeObserver: (result) => {
207
- if (result.sandboxBoundary === 'recovered') {
208
- boundaryFailureInvocationIds.delete(result.outcomeId);
209
- unclassifiedBoundaryFailure = false;
210
- }
211
- else if (result.sandboxBoundary === 'unresolved') {
212
- boundaryFailureInvocationIds.add(result.outcomeId);
213
- unclassifiedBoundaryFailure = false;
214
- }
206
+ if (result.sandboxBoundary === 'unresolved')
207
+ boundaryFailure = true;
215
208
  outcome = result;
216
209
  },
217
210
  });
@@ -298,7 +291,7 @@ export async function runMakaTextCliCore(argv, adapter, overrides = {}) {
298
291
  : {}),
299
292
  })) {
300
293
  if (event.type === 'sandbox_boundary_request') {
301
- unclassifiedBoundaryFailure = true;
294
+ boundaryFailure = true;
302
295
  deps.writeStderr('maka run: sandbox boundary expansion is unavailable in non-interactive mode\n');
303
296
  await context.runtime.respondToSandboxBoundary(session.id, {
304
297
  requestId: event.requestId,
@@ -307,7 +300,7 @@ export async function runMakaTextCliCore(argv, adapter, overrides = {}) {
307
300
  }
308
301
  const sandboxFailureReason = sessionEventSandboxBoundaryFailureReason(event);
309
302
  if (sandboxFailureReason) {
310
- unclassifiedBoundaryFailure = true;
303
+ boundaryFailure = true;
311
304
  deps.writeStderr(sandboxFailureReason === 'requires_bypass'
312
305
  ? 'maka run: sandbox bypass requires an explicit --yolo\n'
313
306
  : 'maka run: sandbox boundary expansion is unavailable in non-interactive mode\n');
@@ -341,9 +334,8 @@ export async function runMakaTextCliCore(argv, adapter, overrides = {}) {
341
334
  }
342
335
  if (streamFailed)
343
336
  return 1;
344
- if (unclassifiedBoundaryFailure || boundaryFailureInvocationIds.size > 0) {
337
+ if (boundaryFailure)
345
338
  return 1;
346
- }
347
339
  if (!outcome) {
348
340
  deps.writeStderr('maka run: runtime produced no outcome\n');
349
341
  return 1;
@@ -407,11 +407,9 @@ function runtimeHostSessionSummaries(items) {
407
407
  }
408
408
  class TurnOutcomeClassifier {
409
409
  #outcomeId;
410
- #callByToolUseId = new Map();
411
- #unresolvedSandboxFailures = new Map();
410
+ #unresolvedSandboxFailures = new Set();
412
411
  #finalOutput;
413
412
  #terminal;
414
- #sandboxBoundaryRecovered = false;
415
413
  constructor(outcomeId) {
416
414
  this.#outcomeId = outcomeId;
417
415
  }
@@ -427,34 +425,13 @@ class TurnOutcomeClassifier {
427
425
  this.#terminal = observation;
428
426
  }
429
427
  return;
430
- case 'tool_call':
431
- this.#callByToolUseId.set(observation.toolUseId, {
432
- stepId: observation.stepId,
433
- toolName: observation.toolName,
434
- });
435
- return;
436
428
  case 'tool_result': {
437
- const call = this.#callByToolUseId.get(observation.toolUseId);
438
429
  if (observation.outcome === 'sandbox_failure') {
439
- this.#unresolvedSandboxFailures.set(observation.toolUseId, {
440
- failedStepId: call?.stepId,
441
- failedToolName: call?.toolName,
442
- });
443
- return;
444
- }
445
- const unresolved = [...this.#unresolvedSandboxFailures.values()];
446
- // The wire has no retry identity. A later success can only prove recovery
447
- // when there is exactly one unresolved candidate.
448
- if (observation.outcome === 'success' &&
449
- call?.toolName !== 'request_sandbox_boundary' &&
450
- unresolved.length === 1 &&
451
- call?.stepId !== undefined &&
452
- unresolved[0]?.failedStepId !== undefined &&
453
- call.stepId !== unresolved[0].failedStepId &&
454
- call.toolName === unresolved[0].failedToolName) {
455
- this.#unresolvedSandboxFailures.clear();
456
- this.#sandboxBoundaryRecovered = true;
430
+ this.#unresolvedSandboxFailures.add(observation.toolUseId);
457
431
  }
432
+ // No clearing path: `maka run` denies every widening request, so the
433
+ // boundary cannot move mid-Turn and a later success cannot prove that
434
+ // a blocked call recovered. The failure stays unresolved to the end.
458
435
  return;
459
436
  }
460
437
  }
@@ -464,11 +441,7 @@ class TurnOutcomeClassifier {
464
441
  if (!terminal && incomplete === 'pending')
465
442
  return undefined;
466
443
  const completed = terminal?.status === 'completed';
467
- const sandboxBoundary = this.#unresolvedSandboxFailures.size > 0
468
- ? 'unresolved'
469
- : this.#sandboxBoundaryRecovered
470
- ? 'recovered'
471
- : 'none';
444
+ const sandboxBoundary = this.#unresolvedSandboxFailures.size > 0 ? 'unresolved' : 'none';
472
445
  const failure = terminal?.status === 'failed'
473
446
  ? terminal.failure
474
447
  : {
@@ -507,14 +480,6 @@ function observationFromSessionEvent(event) {
507
480
  if (event.type === 'complete') {
508
481
  return observationFromCompleteEvent(event);
509
482
  }
510
- if (event.type === 'tool_start') {
511
- return {
512
- kind: 'tool_call',
513
- toolUseId: event.toolUseId,
514
- stepId: event.stepId,
515
- toolName: event.toolName,
516
- };
517
- }
518
483
  return event.type === 'tool_result' ? observationFromToolResult(event) : undefined;
519
484
  }
520
485
  function observationFromStoredMessage(message) {
@@ -543,14 +508,6 @@ function observationFromStoredMessage(message) {
543
508
  },
544
509
  };
545
510
  }
546
- if (message.type === 'tool_call') {
547
- return {
548
- kind: 'tool_call',
549
- toolUseId: message.id,
550
- stepId: message.stepId,
551
- toolName: message.toolName,
552
- };
553
- }
554
511
  return message.type === 'tool_result' ? observationFromToolResult(message) : undefined;
555
512
  }
556
513
  function observationFromCompleteEvent(event) {
@@ -62,19 +62,11 @@ export const ARTIFACT_SOURCES = [
62
62
  'tool_result',
63
63
  'tool_result_projection',
64
64
  'tool_result_archive',
65
- 'synthesis_cache_block',
66
- 'history_compact_block',
67
- 'history_compact_source',
68
- 'provider_request_capture',
69
65
  'subagent_writeback',
70
66
  'deep_research',
71
67
  'user_upload',
72
- 'export',
73
- 'snapshot',
74
68
  'session_effect',
75
- 'fixture',
76
69
  ];
77
- export const ARTIFACT_STATUSES = ['live', 'deleted'];
78
70
  export const ARTIFACT_ENTITY_ID_MAX_CHARS = 128;
79
71
  export const ARTIFACT_TURN_KEY_MAX_CHARS = 512;
80
72
  const ARTIFACT_ENTITY_ID_PATTERN = new RegExp(`^[A-Za-z0-9_-]{1,${ARTIFACT_ENTITY_ID_MAX_CHARS}}$`);
@@ -92,26 +84,27 @@ const ARTIFACT_SOURCE_POLICIES = {
92
84
  tool_result: { userDeletable: true, userVisible: false, sharedReadable: true },
93
85
  tool_result_projection: { userDeletable: false, userVisible: false, sharedReadable: true },
94
86
  tool_result_archive: { userDeletable: false, userVisible: false, sharedReadable: false },
95
- synthesis_cache_block: { userDeletable: true, userVisible: false, sharedReadable: false },
96
- history_compact_block: { userDeletable: true, userVisible: false, sharedReadable: false },
97
- history_compact_source: { userDeletable: true, userVisible: false, sharedReadable: false },
98
- // Historical only: nothing produces these any more. The policy stays so the
99
- // records already on disk keep decoding and stay deletable.
100
- provider_request_capture: { userDeletable: true, userVisible: false, sharedReadable: false },
101
87
  subagent_writeback: { userDeletable: false, userVisible: true, sharedReadable: false },
102
88
  deep_research: { userDeletable: false, userVisible: true, sharedReadable: false },
103
89
  user_upload: { userDeletable: true, userVisible: false, sharedReadable: true },
104
- export: { userDeletable: true, userVisible: true, sharedReadable: false },
105
- snapshot: { userDeletable: true, userVisible: true, sharedReadable: false },
106
90
  session_effect: { userDeletable: false, userVisible: false, sharedReadable: false },
107
- fixture: { userDeletable: true, userVisible: true, sharedReadable: false },
108
91
  };
109
- export function canUserDeleteArtifact(record) {
110
- return record.source === undefined || ARTIFACT_SOURCE_POLICIES[record.source].userDeletable;
111
- }
92
+ const CHILD_RESULT_OUTPUT_SOURCES = new Set([
93
+ 'tool_result',
94
+ 'tool_result_projection',
95
+ 'subagent_writeback',
96
+ 'deep_research',
97
+ ]);
112
98
  export function isArtifactUserVisible(record) {
113
- return record.source === undefined || ARTIFACT_SOURCE_POLICIES[record.source].userVisible;
99
+ return ARTIFACT_SOURCE_POLICIES[record.source].userVisible;
100
+ }
101
+ /** Visibility does not grant permission to destroy evidence owned by a runtime workflow. */
102
+ export function canUserDeleteArtifact(record) {
103
+ return ARTIFACT_SOURCE_POLICIES[record.source].userDeletable;
114
104
  }
115
105
  export function isArtifactSharedSessionReadable(record) {
116
- return record.source !== undefined && ARTIFACT_SOURCE_POLICIES[record.source].sharedReadable;
106
+ return ARTIFACT_SOURCE_POLICIES[record.source].sharedReadable;
107
+ }
108
+ export function isArtifactChildResultOutput(record) {
109
+ return CHILD_RESULT_OUTPUT_SOURCES.has(record.source);
117
110
  }
@@ -16,7 +16,7 @@
16
16
  * specific language governing permissions and limitations
17
17
  * under the License.
18
18
  */
19
- import { connectionEnabledModelIds } from './llm-connections.js';
19
+ import { connectionEnabledModelIds, } from './llm-connections.js';
20
20
  export const HEALTH_SIGNAL_STATUSES = ['ok', 'info', 'warning', 'error', 'unknown'];
21
21
  export const HEALTH_SIGNAL_LAYERS = [
22
22
  'configuration',
@@ -81,7 +81,7 @@ export function healthSignalFromConnection(connection, checkedAt, options = {})
81
81
  status: 'info',
82
82
  source: 'settings',
83
83
  checkedAt,
84
- message: '连接已关闭。',
84
+ message: 'connection_disabled',
85
85
  blocksSend: false,
86
86
  };
87
87
  }
@@ -94,7 +94,7 @@ export function healthSignalFromConnection(connection, checkedAt, options = {})
94
94
  status: 'warning',
95
95
  source: 'settings',
96
96
  checkedAt,
97
- message: '等待选择默认模型。',
97
+ message: 'awaiting_default_model',
98
98
  blocksSend: true,
99
99
  };
100
100
  }
@@ -107,8 +107,8 @@ export function healthSignalFromConnection(connection, checkedAt, options = {})
107
107
  status: 'ok',
108
108
  source: 'connection_test',
109
109
  checkedAt: timeFromIso(connection.lastTestAt) ?? checkedAt,
110
- message: '凭据与端点验证已通过。',
111
- detail: '这是连接验证结果,不代表发送、流式输出或中断通路已经运行通过。',
110
+ message: 'validation_passed',
111
+ detail: { kind: 'validation_scope_note' },
112
112
  blocksSend: false,
113
113
  };
114
114
  }
@@ -121,8 +121,10 @@ export function healthSignalFromConnection(connection, checkedAt, options = {})
121
121
  status: 'error',
122
122
  source: 'connection_test',
123
123
  checkedAt: timeFromIso(connection.lastTestAt) ?? checkedAt,
124
- message: '连接需要重新修复认证。',
125
- detail: connection.lastTestMessage,
124
+ message: 'needs_reauth',
125
+ ...(connection.lastTestMessage
126
+ ? { detail: connectionLastTestDetail(connection.lastTestMessage) }
127
+ : {}),
126
128
  blocksSend: true,
127
129
  };
128
130
  }
@@ -135,8 +137,10 @@ export function healthSignalFromConnection(connection, checkedAt, options = {})
135
137
  status: 'warning',
136
138
  source: 'connection_test',
137
139
  checkedAt: timeFromIso(connection.lastTestAt) ?? checkedAt,
138
- message: '上次连接验证失败。',
139
- detail: connection.lastTestMessage,
140
+ message: 'validation_failed',
141
+ ...(connection.lastTestMessage
142
+ ? { detail: connectionLastTestDetail(connection.lastTestMessage) }
143
+ : {}),
140
144
  blocksSend: true,
141
145
  };
142
146
  }
@@ -155,8 +159,8 @@ export function healthSignalFromConnection(connection, checkedAt, options = {})
155
159
  status: 'warning',
156
160
  source: 'settings',
157
161
  checkedAt,
158
- message: '没有启用任何模型。',
159
- detail: '在 设置 · 模型 的连接详情里启用至少一个模型后才能使用该连接。',
162
+ message: 'no_models_enabled',
163
+ detail: { kind: 'no_models_enabled_hint' },
160
164
  blocksSend: false,
161
165
  };
162
166
  }
@@ -168,8 +172,8 @@ export function healthSignalFromConnection(connection, checkedAt, options = {})
168
172
  status: 'info',
169
173
  source: 'settings',
170
174
  checkedAt,
171
- message: '不是工作区的默认模型来源。',
172
- detail: '在任务中显式选择该连接的模型即可正常使用;新对话的默认模型在 设置 · 通用 配置。',
175
+ message: 'not_default_source',
176
+ detail: { kind: 'not_default_source_hint' },
173
177
  blocksSend: false,
174
178
  };
175
179
  }
@@ -181,7 +185,7 @@ export function healthSignalFromConnection(connection, checkedAt, options = {})
181
185
  status: 'unknown',
182
186
  source: 'connection_test',
183
187
  checkedAt,
184
- message: '等待验证连接。',
188
+ message: 'awaiting_validation',
185
189
  blocksSend: false,
186
190
  };
187
191
  }
@@ -191,21 +195,21 @@ export function healthSignalFromConnectionRuntime(connection, latestRuntimeProbe
191
195
  if (!latestRuntimeProbe) {
192
196
  return {
193
197
  id: `connection:${connection.slug}:runtime`,
194
- label: `${connection.name} 运行态`,
198
+ label: connection.name,
195
199
  scope: 'llm_connection',
196
200
  layer: 'runtime_probe',
197
201
  status: 'unknown',
198
202
  source: 'runtime_probe',
199
203
  checkedAt,
200
- message: '等待完成发送运行态探测。',
201
- detail: '凭据验证与真实发送、流式输出、中断通路是两层健康信号。',
204
+ message: 'runtime_probe_pending',
205
+ detail: { kind: 'runtime_probe_layers_note' },
202
206
  blocksSend: false,
203
207
  };
204
208
  }
205
209
  const status = runtimeStatusToHealth(latestRuntimeProbe.status);
206
210
  return {
207
211
  id: `connection:${connection.slug}:runtime`,
208
- label: `${connection.name} 运行态`,
212
+ label: connection.name,
209
213
  scope: 'llm_connection',
210
214
  layer: 'runtime_probe',
211
215
  status,
@@ -255,35 +259,34 @@ function healthLayerFromCapability(capability) {
255
259
  function capabilityMessage(readiness) {
256
260
  switch (readiness) {
257
261
  case 'enabled':
258
- return '能力门禁已满足。';
262
+ return 'capability_ok';
259
263
  case 'paused':
260
- return '能力已关闭或暂停。';
264
+ return 'capability_paused';
261
265
  case 'not_configured':
262
- return '等待补齐能力配置。';
266
+ return 'capability_not_configured';
263
267
  case 'denied':
264
- return '能力被必要系统权限阻塞。';
268
+ return 'capability_denied';
265
269
  case 'degraded':
266
- return '能力运行态探测处于降级状态。';
270
+ return 'capability_degraded';
267
271
  }
268
272
  }
269
273
  function capabilityDetail(capability) {
270
- return userVisibleCapabilityReason(capability.runtimeProbe.reason ?? capability.feature.reason ?? capability.configuration.reason);
274
+ const reason = (capability.runtimeProbe.reason ??
275
+ capability.feature.reason ??
276
+ capability.configuration.reason)?.trim();
277
+ return reason ? { kind: 'capability_reason', reason } : undefined;
271
278
  }
272
- function userVisibleCapabilityReason(reason) {
273
- const raw = reason?.trim();
274
- if (!raw)
275
- return undefined;
276
- switch (raw) {
277
- case 'disabled':
278
- return '该能力当前已关闭。';
279
- case 'missing platform credentials':
280
- return '等待填写平台凭据。';
281
- case 'macOS TCC only':
282
- return '仅 macOS 系统权限可探测。';
283
- case 'no Electron API for per-target Apple Events TCC status':
284
- return '系统未提供可直接读取的授权状态。';
279
+ function connectionLastTestDetail(message) {
280
+ const normalized = message.trim().toLowerCase();
281
+ switch (normalized) {
282
+ case 'auth':
283
+ case 'timeout':
284
+ case 'provider_unavailable':
285
+ case 'network':
286
+ case 'unknown':
287
+ return { kind: 'last_test_error_class', errorClass: normalized };
285
288
  default:
286
- return /[\u3400-\u9fff]/.test(raw) ? raw : '状态详情请见对应设置页。';
289
+ return { kind: 'last_test_message' };
287
290
  }
288
291
  }
289
292
  function timeFromIso(value) {
@@ -305,16 +308,18 @@ function runtimeStatusToHealth(status) {
305
308
  function runtimeProbeMessage(status) {
306
309
  switch (status) {
307
310
  case 'success':
308
- return '最近一次发送已完成。';
311
+ return 'send_completed';
309
312
  case 'aborted':
310
- return '最近一次发送已由用户停止。';
313
+ return 'send_aborted';
311
314
  case 'error':
312
- return '最近一次发送失败。';
315
+ return 'send_failed';
313
316
  }
314
317
  }
315
318
  function runtimeProbeDetail(row) {
316
- const parts = [`模型=${row.modelId}`, `延迟=${row.latencyMs}ms`];
317
- if (row.errorClass)
318
- parts.push(`错误类型=${row.errorClass}`);
319
- return parts.join(' · ');
319
+ return {
320
+ kind: 'runtime_probe_result',
321
+ modelId: row.modelId,
322
+ latencyMs: row.latencyMs,
323
+ ...(row.errorClass ? { errorClass: row.errorClass } : {}),
324
+ };
320
325
  }
@@ -282,12 +282,11 @@ export function effectiveBaseUrl(c) {
282
282
  }
283
283
  export function validateSlug(slug) {
284
284
  if (!slug.trim())
285
- return 'Slug is required';
286
- if (!/^[a-z0-9][a-z0-9-]*[a-z0-9]$/.test(slug)) {
287
- return 'Slug must be lowercase letters, digits, and hyphens';
288
- }
285
+ return 'required';
286
+ if (!/^[a-z0-9][a-z0-9-]*[a-z0-9]$/.test(slug))
287
+ return 'format';
289
288
  if (slug.length > 64)
290
- return 'Slug must be 64 characters or fewer';
289
+ return 'too_long';
291
290
  return null;
292
291
  }
293
292
  /** Derive an unused connection slug from a catalog provider type. */
@@ -84,7 +84,7 @@ function getAbsoluteFormat(uiLocale) {
84
84
  * reading a relative label falls back to and a tooltip shows; `@maka/ui` had
85
85
  * its own uncached copy of the same `Intl` options until this became public.
86
86
  */
87
- export function formatAbsoluteTimestamp(ts, locale = 'zh-CN') {
87
+ export function formatAbsoluteTimestamp(ts, locale) {
88
88
  return getAbsoluteFormat(locale).format(new Date(ts));
89
89
  }
90
90
  /**
@@ -92,7 +92,7 @@ export function formatAbsoluteTimestamp(ts, locale = 'zh-CN') {
92
92
  * absolute date string. `now` is injectable so tests pin a deterministic clock;
93
93
  * future timestamps (clock skew) snap to the just-now label.
94
94
  */
95
- export function formatRelativeTimestamp(ts, now = Date.now(), locale = 'zh-CN') {
95
+ export function formatRelativeTimestamp(ts, now, locale) {
96
96
  const diffMs = relativeAgeMs(ts, now);
97
97
  if (diffMs < JUST_NOW_MS) {
98
98
  return JUST_NOW[locale];
@@ -135,7 +135,7 @@ function getCompactFormats(uiLocale) {
135
135
  * Compact variant for wider list rows: relative inside the seven-day horizon,
136
136
  * then a localized date-only label.
137
137
  */
138
- export function formatCompactTimestamp(ts, now = Date.now(), locale = 'zh-CN') {
138
+ export function formatCompactTimestamp(ts, now, locale) {
139
139
  const diffMs = relativeAgeMs(ts, now);
140
140
  if (diffMs <= RELATIVE_HORIZON_MS)
141
141
  return formatRelativeTimestamp(ts, now, locale);
@@ -151,7 +151,7 @@ export function formatCompactTimestamp(ts, now = Date.now(), locale = 'zh-CN') {
151
151
  * Unit tokens stay deliberately locale-neutral so the trailing column remains
152
152
  * stable across UI languages: "46min", "13h", "17d", "1mo", "1y".
153
153
  */
154
- export function formatSidebarTimestamp(ts, now = Date.now(), locale = 'zh-CN') {
154
+ export function formatSidebarTimestamp(ts, now, locale) {
155
155
  const diffMs = relativeAgeMs(ts, now);
156
156
  if (diffMs < JUST_NOW_MS)
157
157
  return JUST_NOW[locale];
@@ -534,8 +534,14 @@ export function decodeConnectionSlug(value) {
534
534
  if (typeof value !== 'string')
535
535
  throw domainError('connection slug must be a string');
536
536
  const error = validateSlug(value);
537
- if (error)
538
- throw domainError(`connection slug: ${error}`);
537
+ if (error) {
538
+ const messages = {
539
+ required: 'Slug is required',
540
+ format: 'Slug must be lowercase letters, digits, and hyphens',
541
+ too_long: 'Slug must be 64 characters or fewer',
542
+ };
543
+ throw domainError(`connection slug: ${messages[error]}`);
544
+ }
539
545
  return value;
540
546
  }
541
547
  export function decodeConnectionName(value) {
@@ -190,7 +190,7 @@ function formatRangeSuffix(args) {
190
190
  * First-line invocation for the quiet panel from tool args — never a
191
191
  * pretty-printed args object.
192
192
  */
193
- export function formatToolInvocationLine(item, locale = 'zh-CN') {
193
+ export function formatToolInvocationLine(item, locale) {
194
194
  const s = strings(locale);
195
195
  const args = asRecord(item.args);
196
196
  if (!args) {
@@ -459,7 +459,7 @@ export function projectToolArgsPreview(toolName, args) {
459
459
  * Primary list/text fields become the main body; remaining fields (error, ok,
460
460
  * truncated, …) are appended so diagnostics cannot vanish.
461
461
  */
462
- export function formatQuietJsonValue(value, locale = 'zh-CN') {
462
+ export function formatQuietJsonValue(value, locale) {
463
463
  const s = strings(locale);
464
464
  if (value === null || value === undefined) {
465
465
  return { body: s.empty };
@@ -613,7 +613,7 @@ function formatArrayAsBody(values, locale) {
613
613
  * Keys and whole lines pass through `redactSecrets`; sensitive key names force
614
614
  * value masking even when the value itself is a short non-token secret.
615
615
  */
616
- export function formatAsKeyValueLines(record, depth = 0, locale = 'zh-CN') {
616
+ export function formatAsKeyValueLines(record, depth, locale) {
617
617
  const s = strings(locale);
618
618
  if (depth > 3)
619
619
  return redactSecrets(String(record));
@@ -27,9 +27,7 @@ export function defineUiMessageCatalog() {
27
27
  export function resolveUiMessageCatalog(catalog) {
28
28
  return Object.fromEntries(UI_LOCALES.map((locale) => [
29
29
  locale,
30
- locale === 'en'
31
- ? catalog.en
32
- : mergeUiMessages(catalog.en, catalog[locale]),
30
+ mergeUiMessages(catalog.en, catalog[locale]),
33
31
  ]));
34
32
  }
35
33
  export function formatUiMessage(template, values, locale) {
@@ -106,3 +104,7 @@ export function resolveUiLocale(preference, systemLocale, override) {
106
104
  export function uiLocaleToIntlLocale(locale) {
107
105
  return locale;
108
106
  }
107
+ /** Copy for a wire code, or undefined when a newer producer sent one this catalog does not know. */
108
+ export function lookupCopy(map, code) {
109
+ return code !== undefined && Object.hasOwn(map, code) ? map[code] : undefined;
110
+ }
@@ -29,7 +29,6 @@ import { redactSecrets } from '@maka/core/redaction';
29
29
  import { MODEL_CALL_ATTEMPT_EVENT_TYPE, } from '@maka/core/model-call-attempt';
30
30
  import { resolveEffectiveOrchestration, } from '@maka/core/orchestration';
31
31
  import { messageContentsEqual } from '@maka/core/events';
32
- import { projectRuntimeEventsToStoredMessages } from './runtime-event-read-model.js';
33
32
  import { buildPriorRuntimeContext as buildPriorRuntimeContextProjection, } from './prior-run-context.js';
34
33
  import { buildStatusPatch, normalizeStopSessionSource, statusFromEvent, turnStatusFromEvent, } from './session-projection-helpers.js';
35
34
  import { commitOrCreateTerminalRunFact } from './terminal-run-commit.js';
@@ -481,11 +480,6 @@ export class AgentRun {
481
480
  this.active = await this.input.hooks.reserveRun(this.sessionId, this.header, this);
482
481
  await this.input.hooks.updateStatus(this.sessionId, 'running', undefined, this.lastTs);
483
482
  const priorRuntimeContext = await this.buildPriorRuntimeContext();
484
- const projectionContext = priorRuntimeContext
485
- ? projectRuntimeEventsToStoredMessages(priorRuntimeContext.events, {
486
- invocations: priorRuntimeContext.invocations,
487
- }).messages
488
- : [];
489
483
  return {
490
484
  backend: this.active.backend,
491
485
  backendInput: cloneAndFreezeRuntimeSnapshot({
@@ -503,7 +497,6 @@ export class AgentRun {
503
497
  ? { directoryReferences: this.input.userInput.directoryReferences }
504
498
  : {}),
505
499
  ...(this.input.userInput.quotes ? { quotes: this.input.userInput.quotes } : {}),
506
- context: projectionContext,
507
500
  ...(priorRuntimeContext
508
501
  ? {
509
502
  runtimeContext: priorRuntimeContext.events,