maka-agent 0.2.0-dev.25.20260908 → 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 (65) hide show
  1. package/dist/mcp-capability-provider.js +4 -1
  2. package/dist/pi-tui-mcp-status.js +2 -2
  3. package/dist/pi-tui-pickers.js +19 -29
  4. package/dist/tui-autocomplete-layout.js +3 -1
  5. package/dist/tui-copy-catalog.js +6 -3
  6. package/dist/tui-editor-render.js +36 -0
  7. package/dist/tui-mcp-control.js +41 -6
  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/runtime-event.js +3 -0
  10. package/node_modules/@maka/core/dist/session.js +29 -4
  11. package/node_modules/@maka/core/dist/workhub-action-result.js +68 -0
  12. package/node_modules/@maka/core/package.json +2 -3
  13. package/node_modules/@maka/eval/dist/toolchain-verification.js +1 -1
  14. package/node_modules/@maka/mcp/dist/form-elicitation.js +213 -0
  15. package/node_modules/@maka/mcp/dist/index.js +337 -71
  16. package/node_modules/@maka/runtime/dist/agent-run.js +10 -1
  17. package/node_modules/@maka/runtime/dist/goal-continuation.js +5 -1
  18. package/node_modules/@maka/runtime/dist/runtime-event-read-model.js +20 -1
  19. package/node_modules/@maka/runtime/dist/runtime-kernel.js +120 -13
  20. package/node_modules/@maka/runtime/dist/session-manager.js +20 -36
  21. package/node_modules/@maka/runtime-host/dist/client/connection.js +30 -5
  22. package/node_modules/@maka/runtime-host/dist/client/host-handoff-copy.js +17 -1
  23. package/node_modules/@maka/runtime-host/dist/client/host-retirement.js +4 -2
  24. package/node_modules/@maka/runtime-host/dist/client/peer-client.js +18 -1
  25. package/node_modules/@maka/runtime-host/dist/protocol/index.js +5 -1
  26. package/node_modules/@maka/runtime-host/dist/protocol/operations.js +3 -2
  27. package/node_modules/@maka/runtime-host/dist/protocol/session-continuity.js +1 -0
  28. package/node_modules/@maka/runtime-host/dist/protocol/workhub-coordination.js +68 -168
  29. package/node_modules/@maka/runtime-host/dist/server/access-credential-store.js +4 -0
  30. package/node_modules/@maka/runtime-host/dist/server/canonical-session-projection.js +2 -1
  31. package/node_modules/@maka/runtime-host/dist/server/connection-session.js +28 -8
  32. package/node_modules/@maka/runtime-host/dist/server/daily-review-coordinator.js +112 -56
  33. package/node_modules/@maka/runtime-host/dist/server/execution-composition.js +45 -20
  34. package/node_modules/@maka/runtime-host/dist/server/failure-diagnostic.js +24 -0
  35. package/node_modules/@maka/runtime-host/dist/server/goal-coordinator.js +7 -3
  36. package/node_modules/@maka/runtime-host/dist/server/host-kernel.js +3 -3
  37. package/node_modules/@maka/runtime-host/dist/server/host-session-availability.js +5 -2
  38. package/node_modules/@maka/runtime-host/dist/server/hosted-execution-recovery.js +3 -2
  39. package/node_modules/@maka/runtime-host/dist/server/hosted-execution-tool-profile.js +34 -4
  40. package/node_modules/@maka/runtime-host/dist/server/interactive-run-composer.js +4 -1
  41. package/node_modules/@maka/runtime-host/dist/server/operation-dispatcher.js +2 -7
  42. package/node_modules/@maka/runtime-host/dist/server/root-turn-coordinator.js +110 -14
  43. package/node_modules/@maka/runtime-host/dist/server/runtime-resource-coordinator.js +11 -8
  44. package/node_modules/@maka/runtime-host/dist/server/scheduled-task-coordinator.js +31 -21
  45. package/node_modules/@maka/runtime-host/dist/server/serial-outbound-writer.js +1 -1
  46. package/node_modules/@maka/runtime-host/dist/server/session-catalog-coordinator.js +20 -8
  47. package/node_modules/@maka/runtime-host/dist/server/session-transcript-reader.js +15 -104
  48. package/node_modules/@maka/runtime-host/dist/server/shared-session-transcript.js +3 -0
  49. package/node_modules/@maka/runtime-host/dist/server/workhub-coordination-action-gate.js +44 -85
  50. package/node_modules/@maka/runtime-host/dist/server/workhub-coordination-coordinator.js +120 -137
  51. package/node_modules/@maka/storage/dist/agent-run-store.js +14 -1
  52. package/node_modules/@maka/storage/dist/artifact-store.js +40 -3
  53. package/node_modules/@maka/storage/dist/atomic-file-write.js +74 -0
  54. package/node_modules/@maka/storage/dist/credential-store.js +12 -63
  55. package/node_modules/@maka/storage/dist/execution-stores.js +4 -1
  56. package/node_modules/@maka/storage/dist/mcp-config-store.js +10 -25
  57. package/node_modules/@maka/storage/dist/session-store.js +14 -2
  58. package/node_modules/@maka/storage/dist/settings-store.js +8 -4
  59. package/node_modules/@maka/storage/dist/sqlite-artifact-metadata.js +11 -0
  60. package/node_modules/@maka/storage/dist/sqlite-session-metadata-schema.js +12 -1
  61. package/node_modules/@maka/storage/dist/sqlite-session-metadata-store.js +67 -3
  62. package/node_modules/@maka/storage/dist/stable-storage.js +14 -1
  63. package/package.json +1 -1
  64. package/node_modules/@maka/core/dist/workhub-creation-intent.js +0 -990
  65. package/node_modules/@maka/core/dist/workhub-session-resolver.js +0 -50
@@ -16,14 +16,30 @@
16
16
  * specific language governing permissions and limitations
17
17
  * under the License.
18
18
  */
19
+ import { isWorkHubActionResult } from '@maka/core/workhub-action-result';
19
20
  import { decodeMessageContent } from './turn.js';
20
- import { isWorkHubCreateDefaults } from '@maka/core/session';
21
+ import { WORKHUB_COORDINATION_SESSION_ID, isWorkHubCreateDefaults, } from '@maka/core/session';
21
22
  import { requireCount, requireEntityId, requireExactRecord, requireRecord, requireShapedRecord, requireUtf8String, } from './codec.js';
22
23
  import { invalidProtocolFrame } from './errors.js';
23
24
  import { defineOperation } from './operation-spec.js';
24
25
  import { decodeWorkspaceProjection, decodeWorkspaceTarget, } from './workspace.js';
26
+ import { decodeSessionConfigurationUpdateInput, decodeSessionUpdateResult, decodeSessionCatalogItem, SESSION_CATALOG_OPERATION_SPECS, } from './session-catalog.js';
27
+ export function decodeWorkHubCoordinationConfigureModelInput(value) {
28
+ const input = requireExactRecord(value, 'WorkHub model configuration', [
29
+ 'expectedRevision',
30
+ 'modelTarget',
31
+ ]);
32
+ const decoded = decodeSessionConfigurationUpdateInput({
33
+ sessionId: WORKHUB_COORDINATION_SESSION_ID,
34
+ expectedRevision: input.expectedRevision,
35
+ patch: { modelTarget: input.modelTarget },
36
+ });
37
+ return {
38
+ expectedRevision: decoded.expectedRevision,
39
+ modelTarget: decoded.patch.modelTarget,
40
+ };
41
+ }
25
42
  export const WORKHUB_COORDINATION_TEXT_MAX_BYTES = 48 * 1024;
26
- export const WORKHUB_COORDINATION_SUMMARY_MAX_BYTES = 8 * 1024;
27
43
  const COORDINATION_TITLE_MAX_BYTES = 512;
28
44
  const CANDIDATE_SET_ID_MAX_BYTES = 96;
29
45
  export const WORKHUB_COORDINATION_CANDIDATE_MAX_ITEMS = 32;
@@ -56,6 +72,25 @@ const CANDIDATE_ERRORS = [
56
72
  'internal_failure',
57
73
  ];
58
74
  export const WORKHUB_COORDINATION_OPERATION_SPECS = {
75
+ 'workhub.coordination.configureModel': defineOperation({
76
+ mode: 'command',
77
+ availability: 'ready',
78
+ errors: SESSION_CATALOG_OPERATION_SPECS['session.configuration.update'].errors,
79
+ decodeInput: decodeWorkHubCoordinationConfigureModelInput,
80
+ decodeOutput: decodeSessionUpdateResult,
81
+ assertOutputForInput: (input, output) => SESSION_CATALOG_OPERATION_SPECS['session.configuration.update'].assertOutputForInput?.({
82
+ sessionId: WORKHUB_COORDINATION_SESSION_ID,
83
+ expectedRevision: input.expectedRevision,
84
+ patch: { modelTarget: input.modelTarget },
85
+ }, output),
86
+ }),
87
+ 'workhub.coordination.query': defineOperation({
88
+ mode: 'query',
89
+ availability: 'ready',
90
+ errors: RESOLVE_ERRORS,
91
+ decodeInput: decodeWorkHubCoordinationResolveInput,
92
+ decodeOutput: decodeSessionCatalogItem,
93
+ }),
59
94
  'workhub.coordination.resolve': defineOperation({
60
95
  mode: 'command',
61
96
  availability: 'ready',
@@ -70,13 +105,6 @@ export const WORKHUB_COORDINATION_OPERATION_SPECS = {
70
105
  decodeInput: decodeWorkHubCoordinationAnswerInput,
71
106
  decodeOutput: decodeWorkHubCoordinationTurnResult,
72
107
  }),
73
- 'workhub.coordination.record': defineOperation({
74
- mode: 'command',
75
- availability: 'ready',
76
- errors: TURN_ERRORS,
77
- decodeInput: decodeWorkHubCoordinationRecordInput,
78
- decodeOutput: decodeWorkHubCoordinationTurnResult,
79
- }),
80
108
  'workhub.coordination.candidates': defineOperation({
81
109
  mode: 'query',
82
110
  availability: 'ready',
@@ -84,11 +112,11 @@ export const WORKHUB_COORDINATION_OPERATION_SPECS = {
84
112
  decodeInput: decodeWorkHubCoordinationCandidatesInput,
85
113
  decodeOutput: decodeWorkHubCoordinationCandidatesResult,
86
114
  }),
87
- 'workhub.coordination.act': defineOperation({
115
+ 'workhub.coordination.actFromTurn': defineOperation({
88
116
  mode: 'command',
89
117
  availability: 'ready',
90
- errors: TURN_ERRORS,
91
- decodeInput: decodeWorkHubCoordinationActInput,
118
+ errors: [...TURN_ERRORS, 'candidate_set_stale'],
119
+ decodeInput: decodeWorkHubCoordinationActFromTurnInput,
92
120
  decodeOutput: decodeWorkHubCoordinationActResult,
93
121
  }),
94
122
  };
@@ -115,18 +143,6 @@ export function decodeWorkHubCoordinationAnswerInput(value) {
115
143
  text: requireUtf8String(input.text, 'WorkHub Coordination answer text', WORKHUB_COORDINATION_TEXT_MAX_BYTES),
116
144
  };
117
145
  }
118
- export function decodeWorkHubCoordinationRecordInput(value) {
119
- const input = requireExactRecord(value, 'WorkHub Coordination record input', [
120
- 'turnId',
121
- 'userText',
122
- 'assistantText',
123
- ]);
124
- return {
125
- turnId: requireEntityId(input.turnId, 'WorkHub Coordination Turn id'),
126
- userText: requireUtf8String(input.userText, 'WorkHub Coordination user text', WORKHUB_COORDINATION_TEXT_MAX_BYTES),
127
- assistantText: requireUtf8String(input.assistantText, 'WorkHub Coordination assistant text', WORKHUB_COORDINATION_SUMMARY_MAX_BYTES),
128
- };
129
- }
130
146
  export function decodeWorkHubCoordinationTurnResult(value) {
131
147
  const result = requireExactRecord(value, 'WorkHub Coordination Turn result', ['turnId']);
132
148
  return {
@@ -153,8 +169,16 @@ export function decodeWorkHubCoordinationCandidatesResult(value) {
153
169
  candidates: result.candidates.map(decodeWorkHubCoordinationCandidate),
154
170
  };
155
171
  }
156
- export function decodeWorkHubCoordinationActInput(value) {
157
- const input = requireShapedRecord(value, 'WorkHub Coordination action input', ['actionId', 'userText', 'proposal'], ['candidateSetId', 'create', 'confirmation', 'newWorkDefaults', 'attachments']);
172
+ export function decodeWorkHubCoordinationActFromTurnInput(value) {
173
+ const input = requireShapedRecord(value, 'WorkHub active Turn action input', ['turnId', 'actionId', 'proposal'], ['candidateSetId', 'create', 'newWorkDefaults', 'delegationText']);
174
+ const fields = decodeWorkHubCoordinationActionFields(input);
175
+ return {
176
+ ...fields,
177
+ proposal: fields.proposal,
178
+ turnId: requireEntityId(input.turnId, 'WorkHub Coordination Turn id'),
179
+ };
180
+ }
181
+ function decodeWorkHubCoordinationActionFields(input) {
158
182
  const proposal = decodeWorkHubCoordinationProposal(input.proposal);
159
183
  if (input.newWorkDefaults !== undefined &&
160
184
  (!isWorkHubCreateDefaults(input.newWorkDefaults) ||
@@ -162,47 +186,37 @@ export function decodeWorkHubCoordinationActInput(value) {
162
186
  (proposal.disposition === 'replace' && proposal.target.disposition === 'create_new')))) {
163
187
  throw invalidProtocolFrame('Invalid WorkHub creation defaults');
164
188
  }
165
- if (input.attachments !== undefined &&
166
- !['answer_here', 'delegate_existing', 'create_new', 'replace'].includes(proposal.disposition)) {
167
- throw invalidProtocolFrame('This WorkHub action does not accept attachments');
189
+ const delegationText = input.delegationText === undefined
190
+ ? undefined
191
+ : requireUtf8String(input.delegationText, 'WorkHub delegation text', WORKHUB_COORDINATION_TEXT_MAX_BYTES);
192
+ if (delegationText !== undefined &&
193
+ (!delegationText.trim() ||
194
+ (proposal.disposition !== 'delegate_existing' &&
195
+ proposal.disposition !== 'create_new' &&
196
+ proposal.disposition !== 'replace'))) {
197
+ throw invalidProtocolFrame('Invalid WorkHub delegation text');
168
198
  }
169
199
  const base = {
170
200
  actionId: requireEntityId(input.actionId, 'WorkHub Coordination action id'),
171
- userText: requireUtf8String(input.userText, 'WorkHub Coordination action text', WORKHUB_COORDINATION_TEXT_MAX_BYTES),
172
201
  proposal,
173
- ...(input.attachments !== undefined
174
- ? {
175
- attachments: decodeMessageContent({
176
- text: input.userText,
177
- attachments: input.attachments,
178
- }).attachments,
179
- }
180
- : {}),
181
202
  ...(input.newWorkDefaults !== undefined
182
203
  ? { newWorkDefaults: input.newWorkDefaults }
183
204
  : {}),
205
+ ...(delegationText === undefined ? {} : { delegationText }),
184
206
  };
185
207
  if (proposal.disposition === 'delegate_existing') {
186
- if (input.create !== undefined ||
187
- input.candidateSetId === undefined ||
188
- input.confirmation !== undefined) {
208
+ if (input.create !== undefined || input.candidateSetId === undefined) {
189
209
  throw invalidProtocolFrame('Invalid WorkHub delegation context');
190
210
  }
191
211
  return { ...base, candidateSetId: candidateSetId(input.candidateSetId) };
192
212
  }
193
213
  if (proposal.disposition === 'create_new') {
194
- if (input.candidateSetId !== undefined ||
195
- input.create === undefined ||
196
- input.confirmation !== undefined) {
214
+ if (input.candidateSetId !== undefined || input.create === undefined) {
197
215
  throw invalidProtocolFrame('Invalid WorkHub creation context');
198
216
  }
199
217
  return { ...base, create: decodeWorkHubCoordinationCreateContext(input.create) };
200
218
  }
201
219
  if (proposal.disposition === 'replace') {
202
- const confirmation = decodeWorkHubCoordinationDestructiveConfirmation(input.confirmation);
203
- if (confirmation.kind !== 'user_correction') {
204
- throw invalidProtocolFrame('Invalid WorkHub replacement confirmation');
205
- }
206
220
  if (proposal.target.disposition === 'delegate_existing') {
207
221
  if (input.candidateSetId === undefined || input.create !== undefined) {
208
222
  throw invalidProtocolFrame('Invalid WorkHub replacement context');
@@ -210,7 +224,6 @@ export function decodeWorkHubCoordinationActInput(value) {
210
224
  return {
211
225
  ...base,
212
226
  candidateSetId: candidateSetId(input.candidateSetId),
213
- confirmation,
214
227
  };
215
228
  }
216
229
  if (input.candidateSetId !== undefined || input.create === undefined) {
@@ -219,112 +232,20 @@ export function decodeWorkHubCoordinationActInput(value) {
219
232
  return {
220
233
  ...base,
221
234
  create: decodeWorkHubCoordinationCreateContext(input.create),
222
- confirmation,
223
235
  };
224
236
  }
225
- if (proposal.disposition === 'stop_work') {
226
- const confirmation = decodeWorkHubCoordinationDestructiveConfirmation(input.confirmation);
227
- if (confirmation.kind !== 'user_stop' ||
228
- input.candidateSetId !== undefined ||
229
- input.create !== undefined) {
230
- throw invalidProtocolFrame('Invalid WorkHub stop context');
231
- }
232
- return { ...base, confirmation };
233
- }
234
- if (input.candidateSetId !== undefined ||
235
- input.create !== undefined ||
236
- input.confirmation !== undefined) {
237
+ if (input.candidateSetId !== undefined || input.create !== undefined) {
237
238
  throw invalidProtocolFrame('Unexpected WorkHub action context');
238
239
  }
239
240
  return base;
240
241
  }
241
242
  export function decodeWorkHubCoordinationActResult(value) {
242
- const result = requireRecord(value, 'WorkHub Coordination action result');
243
- if (result.disposition === 'answer_here' || result.disposition === 'clarify') {
244
- const exact = requireExactRecord(result, 'WorkHub Coordination local action result', [
245
- 'disposition',
246
- 'coordinationTurnId',
247
- ]);
248
- return {
249
- disposition: result.disposition,
250
- coordinationTurnId: requireEntityId(exact.coordinationTurnId, 'WorkHub Coordination Turn id'),
251
- };
252
- }
253
- if (result.disposition === 'delegate_existing' || result.disposition === 'create_new') {
254
- const exact = requireShapedRecord(result, 'WorkHub Coordination execution action result', ['disposition', 'targetSessionId', 'targetTurnId'], ['steered']);
255
- if (exact.steered !== undefined && exact.steered !== true) {
256
- throw invalidProtocolFrame('Invalid WorkHub Coordination steering result');
257
- }
258
- return {
259
- disposition: result.disposition,
260
- targetSessionId: requireEntityId(exact.targetSessionId, 'WorkHub target Session id'),
261
- targetTurnId: requireEntityId(exact.targetTurnId, 'WorkHub target Turn id'),
262
- ...(exact.steered === true ? { steered: true } : {}),
263
- };
264
- }
265
- if (result.disposition === 'replace') {
266
- const exact = requireShapedRecord(result, 'WorkHub Coordination replacement result', ['disposition', 'replacementDisposition', 'targetSessionId', 'targetTurnId'], ['steered']);
267
- if (exact.replacementDisposition !== 'delegate_existing' &&
268
- exact.replacementDisposition !== 'create_new') {
269
- throw invalidProtocolFrame('Invalid WorkHub replacement disposition');
270
- }
271
- if (exact.steered !== undefined && exact.steered !== true) {
272
- throw invalidProtocolFrame('Invalid WorkHub Coordination steering result');
273
- }
274
- return {
275
- disposition: 'replace',
276
- replacementDisposition: exact.replacementDisposition,
277
- targetSessionId: requireEntityId(exact.targetSessionId, 'WorkHub target Session id'),
278
- targetTurnId: requireEntityId(exact.targetTurnId, 'WorkHub target Turn id'),
279
- ...(exact.steered === true ? { steered: true } : {}),
280
- };
281
- }
282
- if (result.disposition === 'stop_work') {
283
- const exact = requireShapedRecord(result, 'WorkHub Coordination stop result', ['disposition', 'outcome', 'targetSessionId'], ['targetTurnId']);
284
- if (exact.outcome !== 'cancelled_pending' &&
285
- exact.outcome !== 'stop_delivered' &&
286
- exact.outcome !== 'already_terminal' &&
287
- exact.outcome !== 'not_owned') {
288
- throw invalidProtocolFrame('Invalid WorkHub stop outcome');
289
- }
290
- if (((exact.outcome === 'stop_delivered' || exact.outcome === 'not_owned') &&
291
- exact.targetTurnId === undefined) ||
292
- (exact.outcome === 'cancelled_pending' && exact.targetTurnId !== undefined)) {
293
- throw invalidProtocolFrame('Invalid WorkHub stop target Turn');
294
- }
295
- return {
296
- disposition: 'stop_work',
297
- outcome: exact.outcome,
298
- targetSessionId: requireEntityId(exact.targetSessionId, 'WorkHub target Session id'),
299
- ...(exact.targetTurnId === undefined
300
- ? {}
301
- : {
302
- targetTurnId: requireEntityId(exact.targetTurnId, 'WorkHub target Turn id'),
303
- }),
304
- };
305
- }
306
- if (result.disposition === 'resume_work') {
307
- const exact = requireShapedRecord(result, 'WorkHub Coordination resume result', ['disposition', 'outcome', 'targetSessionId'], ['targetTurnId']);
308
- if (exact.outcome !== 'resume_started' && exact.outcome !== 'already_running') {
309
- throw invalidProtocolFrame('Invalid WorkHub resume outcome');
310
- }
311
- // Only a started continuation names a Turn: the Host has one to name, and
312
- // the other two outcomes changed nothing that could carry an identity.
313
- if ((exact.outcome === 'resume_started') !== (exact.targetTurnId !== undefined)) {
314
- throw invalidProtocolFrame('Invalid WorkHub resume target Turn');
315
- }
316
- return {
317
- disposition: 'resume_work',
318
- outcome: exact.outcome,
319
- targetSessionId: requireEntityId(exact.targetSessionId, 'WorkHub target Session id'),
320
- ...(exact.targetTurnId === undefined
321
- ? {}
322
- : {
323
- targetTurnId: requireEntityId(exact.targetTurnId, 'WorkHub target Turn id'),
324
- }),
325
- };
243
+ if (!isWorkHubActionResult(value) ||
244
+ value.disposition === 'answer_here' ||
245
+ value.disposition === 'clarify') {
246
+ throw invalidProtocolFrame('Invalid WorkHub Coordination action result');
326
247
  }
327
- throw invalidProtocolFrame('Invalid WorkHub Coordination action disposition');
248
+ return Object.fromEntries(Object.entries(value).filter(([, field]) => field !== undefined));
328
249
  }
329
250
  function decodeWorkHubCoordinationCandidate(value) {
330
251
  const candidate = requireShapedRecord(value, 'WorkHub Coordination candidate', ['candidateRef', 'sessionId', 'sessionName', 'workspace', 'state', 'updatedAt'], ['latestDelegationActionId']);
@@ -344,20 +265,6 @@ function decodeWorkHubCoordinationCandidate(value) {
344
265
  }
345
266
  function decodeWorkHubCoordinationProposal(value) {
346
267
  const proposal = requireRecord(value, 'WorkHub Coordination proposal');
347
- if (proposal.disposition === 'answer_here') {
348
- requireExactRecord(proposal, 'WorkHub answer proposal', ['disposition']);
349
- return { disposition: 'answer_here' };
350
- }
351
- if (proposal.disposition === 'clarify') {
352
- const exact = requireExactRecord(proposal, 'WorkHub clarification proposal', [
353
- 'disposition',
354
- 'assistantText',
355
- ]);
356
- return {
357
- disposition: 'clarify',
358
- assistantText: requireUtf8String(exact.assistantText, 'WorkHub clarification text', WORKHUB_COORDINATION_SUMMARY_MAX_BYTES),
359
- };
360
- }
361
268
  if (proposal.disposition === 'delegate_existing') {
362
269
  const exact = requireExactRecord(proposal, 'WorkHub delegation proposal', [
363
270
  'disposition',
@@ -448,13 +355,6 @@ function decodeWorkHubCoordinationCreateContext(value) {
448
355
  workspace: decodeWorkspaceTarget(context.workspace),
449
356
  };
450
357
  }
451
- function decodeWorkHubCoordinationDestructiveConfirmation(value) {
452
- const confirmation = requireExactRecord(value, 'WorkHub destructive confirmation', ['kind']);
453
- if (confirmation.kind !== 'user_correction' && confirmation.kind !== 'user_stop') {
454
- throw invalidProtocolFrame('Invalid WorkHub destructive confirmation');
455
- }
456
- return { kind: confirmation.kind };
457
- }
458
358
  function candidateSetId(value) {
459
359
  const id = requireUtf8String(value, 'WorkHub candidate set id', CANDIDATE_SET_ID_MAX_BYTES);
460
360
  if (!/^sha256:[a-f0-9]{64}$/u.test(id)) {
@@ -53,6 +53,10 @@ const PERSISTED_GRANT_MIGRATIONS = new Map([
53
53
  // Retired with the second execution-inspection contract; no shipped surface
54
54
  // called execution.inspect.resolve.
55
55
  ['execution.inspect.resolve', { kind: 'release' }],
56
+ // Direct WorkHub actions and record writes were retired. Their grants do not
57
+ // authorize actFromTurn, which requires the active coordination Turn.
58
+ ['workhub.coordination.act', { kind: 'release' }],
59
+ ['workhub.coordination.record', { kind: 'release' }],
56
60
  ]);
57
61
  export const ACCESS_FILE_NAME = 'runtime-host-access.json';
58
62
  export const SESSION_GUEST_OPERATION_GRANTS = Object.freeze([
@@ -16,6 +16,7 @@
16
16
  * specific language governing permissions and limitations
17
17
  * under the License.
18
18
  */
19
+ import { isSessionNotFoundError } from '@maka/storage/execution-stores';
19
20
  import { decodeSessionContinuitySnapshot, SESSION_CONTINUITY_SCHEMA_VERSION, SESSION_CONTINUITY_SNAPSHOT_MAX_BYTES, } from '../protocol/index.js';
20
21
  import { isMissingFile, readCanonicalTurnSnapshot, worstCaseFailedTurnSnapshot, } from './canonical-turn-snapshot.js';
21
22
  import { worstCaseMessageQueueProjection } from './message-queue-capacity.js';
@@ -42,7 +43,7 @@ export class CanonicalSessionProjectionReader {
42
43
  metadataRevision = record.revision;
43
44
  }
44
45
  catch (error) {
45
- if (isMissingFile(error))
46
+ if (isMissingFile(error) || isSessionNotFoundError(error))
46
47
  return null;
47
48
  throw error;
48
49
  }
@@ -17,13 +17,16 @@
17
17
  * under the License.
18
18
  */
19
19
  import { decodeClientFrame, isClientCapabilityClientFrameKind, RUNTIME_HOST_MAX_IN_FLIGHT_DOMAIN_REQUESTS, } from '../protocol/index.js';
20
+ import { runtimeHostLogBuffer } from '../process-diagnostics.js';
20
21
  import { dispatchOperation, operationFailureResponse, } from './operation-dispatcher.js';
21
22
  import { BoundedSerialOutboundWriter } from './serial-outbound-writer.js';
22
23
  import { RuntimeHostTransportError } from '../transport/framed-transport.js';
23
24
  import { authorizeClientCapabilityFrame, authorizeRuntimeHostOperation, hasRuntimeHostOperationGrant, } from './connection-authority.js';
25
+ import { boundedFailureDiagnostic } from './failure-diagnostic.js';
24
26
  export class RuntimeHostConnectionSession {
25
27
  #options;
26
28
  #writer;
29
+ #onDiagnostic;
27
30
  #requests = new Map();
28
31
  #transcriptPageTail = Promise.resolve();
29
32
  #inFlightStatusRequests = 0;
@@ -37,7 +40,9 @@ export class RuntimeHostConnectionSession {
37
40
  #closed = false;
38
41
  constructor(options) {
39
42
  this.#options = options;
40
- this.#writer = new BoundedSerialOutboundWriter(options.transport, () => this.#teardown());
43
+ this.#onDiagnostic =
44
+ options.onDiagnostic ?? ((diagnostic) => runtimeHostLogBuffer.append('error', diagnostic));
45
+ this.#writer = new BoundedSerialOutboundWriter(options.transport, (error) => this.#fail(error));
41
46
  }
42
47
  async run() {
43
48
  this.attachGlobalChanges();
@@ -51,8 +56,8 @@ export class RuntimeHostConnectionSession {
51
56
  await this.#closeAfterDispatchedReplies();
52
57
  }
53
58
  }
54
- catch {
55
- this.#teardown();
59
+ catch (error) {
60
+ this.#fail(error);
56
61
  }
57
62
  finally {
58
63
  this.#teardown();
@@ -94,7 +99,7 @@ export class RuntimeHostConnectionSession {
94
99
  if (isClientCapabilityClientFrameKind(frame.kind)) {
95
100
  const capabilityFrame = frame;
96
101
  if (!authorizeClientCapabilityFrame(this.#options.connection.authority, capabilityFrame)) {
97
- this.#teardown();
102
+ this.#fail(new Error('Runtime Host Client Capability frame is not authorized'));
98
103
  return;
99
104
  }
100
105
  this.#ensureClientCapabilities()?.accept(capabilityFrame);
@@ -104,9 +109,13 @@ export class RuntimeHostConnectionSession {
104
109
  }
105
110
  const usesLivenessReserve = this.#requests.size === RUNTIME_HOST_MAX_IN_FLIGHT_DOMAIN_REQUESTS &&
106
111
  (frame.operation === 'host.status' || this.#inFlightStatusRequests > 0);
107
- if (this.#requests.has(frame.requestId) ||
108
- (this.#requests.size >= RUNTIME_HOST_MAX_IN_FLIGHT_DOMAIN_REQUESTS && !usesLivenessReserve)) {
109
- this.#teardown();
112
+ if (this.#requests.has(frame.requestId)) {
113
+ this.#fail(new Error('Runtime Host Client reused an active request id'));
114
+ return;
115
+ }
116
+ if (this.#requests.size >= RUNTIME_HOST_MAX_IN_FLIGHT_DOMAIN_REQUESTS &&
117
+ !usesLivenessReserve) {
118
+ this.#fail(new Error('Runtime Host Client exceeded the in-flight request limit'));
110
119
  return;
111
120
  }
112
121
  this.#dispatch(frame);
@@ -119,7 +128,7 @@ export class RuntimeHostConnectionSession {
119
128
  ? this.#transcriptPageTail.then(() => this.#handleRequest(frame))
120
129
  : this.#handleRequest(frame);
121
130
  const task = handling
122
- .catch(() => this.#teardown())
131
+ .catch((error) => this.#fail(error))
123
132
  .finally(() => {
124
133
  if (this.#requests.get(frame.requestId) === task) {
125
134
  this.#requests.delete(frame.requestId);
@@ -313,6 +322,17 @@ export class RuntimeHostConnectionSession {
313
322
  this.#hostChanges?.close();
314
323
  this.#hostChanges = undefined;
315
324
  }
325
+ #fail(error) {
326
+ if (this.#closed)
327
+ return;
328
+ try {
329
+ this.#onDiagnostic(`[runtime-host] connection session failed: ${boundedFailureDiagnostic(error)}`);
330
+ }
331
+ catch {
332
+ // Diagnostics cannot keep an invalid connection alive.
333
+ }
334
+ this.#teardown();
335
+ }
316
336
  #teardown() {
317
337
  if (this.#closed)
318
338
  return;