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.
- package/dist/mcp-capability-provider.js +4 -1
- package/dist/pi-tui-mcp-status.js +2 -2
- package/dist/pi-tui-pickers.js +19 -29
- package/dist/tui-autocomplete-layout.js +3 -1
- package/dist/tui-copy-catalog.js +6 -3
- package/dist/tui-editor-render.js +36 -0
- package/dist/tui-mcp-control.js +41 -6
- package/native/runtime-host-windows-task-launcher/prebuilds/win32-x64/maka-runtime-host-task-launcher.exe +0 -0
- package/node_modules/@maka/core/dist/runtime-event.js +3 -0
- package/node_modules/@maka/core/dist/session.js +29 -4
- package/node_modules/@maka/core/dist/workhub-action-result.js +68 -0
- package/node_modules/@maka/core/package.json +2 -3
- package/node_modules/@maka/eval/dist/toolchain-verification.js +1 -1
- package/node_modules/@maka/mcp/dist/form-elicitation.js +213 -0
- package/node_modules/@maka/mcp/dist/index.js +337 -71
- package/node_modules/@maka/runtime/dist/agent-run.js +10 -1
- package/node_modules/@maka/runtime/dist/goal-continuation.js +5 -1
- package/node_modules/@maka/runtime/dist/runtime-event-read-model.js +20 -1
- package/node_modules/@maka/runtime/dist/runtime-kernel.js +120 -13
- package/node_modules/@maka/runtime/dist/session-manager.js +20 -36
- package/node_modules/@maka/runtime-host/dist/client/connection.js +30 -5
- package/node_modules/@maka/runtime-host/dist/client/host-handoff-copy.js +17 -1
- package/node_modules/@maka/runtime-host/dist/client/host-retirement.js +4 -2
- package/node_modules/@maka/runtime-host/dist/client/peer-client.js +18 -1
- package/node_modules/@maka/runtime-host/dist/protocol/index.js +5 -1
- package/node_modules/@maka/runtime-host/dist/protocol/operations.js +3 -2
- package/node_modules/@maka/runtime-host/dist/protocol/session-continuity.js +1 -0
- package/node_modules/@maka/runtime-host/dist/protocol/workhub-coordination.js +68 -168
- package/node_modules/@maka/runtime-host/dist/server/access-credential-store.js +4 -0
- package/node_modules/@maka/runtime-host/dist/server/canonical-session-projection.js +2 -1
- package/node_modules/@maka/runtime-host/dist/server/connection-session.js +28 -8
- package/node_modules/@maka/runtime-host/dist/server/daily-review-coordinator.js +112 -56
- package/node_modules/@maka/runtime-host/dist/server/execution-composition.js +45 -20
- package/node_modules/@maka/runtime-host/dist/server/failure-diagnostic.js +24 -0
- package/node_modules/@maka/runtime-host/dist/server/goal-coordinator.js +7 -3
- package/node_modules/@maka/runtime-host/dist/server/host-kernel.js +3 -3
- package/node_modules/@maka/runtime-host/dist/server/host-session-availability.js +5 -2
- package/node_modules/@maka/runtime-host/dist/server/hosted-execution-recovery.js +3 -2
- package/node_modules/@maka/runtime-host/dist/server/hosted-execution-tool-profile.js +34 -4
- package/node_modules/@maka/runtime-host/dist/server/interactive-run-composer.js +4 -1
- package/node_modules/@maka/runtime-host/dist/server/operation-dispatcher.js +2 -7
- package/node_modules/@maka/runtime-host/dist/server/root-turn-coordinator.js +110 -14
- package/node_modules/@maka/runtime-host/dist/server/runtime-resource-coordinator.js +11 -8
- package/node_modules/@maka/runtime-host/dist/server/scheduled-task-coordinator.js +31 -21
- package/node_modules/@maka/runtime-host/dist/server/serial-outbound-writer.js +1 -1
- package/node_modules/@maka/runtime-host/dist/server/session-catalog-coordinator.js +20 -8
- package/node_modules/@maka/runtime-host/dist/server/session-transcript-reader.js +15 -104
- package/node_modules/@maka/runtime-host/dist/server/shared-session-transcript.js +3 -0
- package/node_modules/@maka/runtime-host/dist/server/workhub-coordination-action-gate.js +44 -85
- package/node_modules/@maka/runtime-host/dist/server/workhub-coordination-coordinator.js +120 -137
- package/node_modules/@maka/storage/dist/agent-run-store.js +14 -1
- package/node_modules/@maka/storage/dist/artifact-store.js +40 -3
- package/node_modules/@maka/storage/dist/atomic-file-write.js +74 -0
- package/node_modules/@maka/storage/dist/credential-store.js +12 -63
- package/node_modules/@maka/storage/dist/execution-stores.js +4 -1
- package/node_modules/@maka/storage/dist/mcp-config-store.js +10 -25
- package/node_modules/@maka/storage/dist/session-store.js +14 -2
- package/node_modules/@maka/storage/dist/settings-store.js +8 -4
- package/node_modules/@maka/storage/dist/sqlite-artifact-metadata.js +11 -0
- package/node_modules/@maka/storage/dist/sqlite-session-metadata-schema.js +12 -1
- package/node_modules/@maka/storage/dist/sqlite-session-metadata-store.js +67 -3
- package/node_modules/@maka/storage/dist/stable-storage.js +14 -1
- package/package.json +1 -1
- package/node_modules/@maka/core/dist/workhub-creation-intent.js +0 -990
- 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.
|
|
115
|
+
'workhub.coordination.actFromTurn': defineOperation({
|
|
88
116
|
mode: 'command',
|
|
89
117
|
availability: 'ready',
|
|
90
|
-
errors: TURN_ERRORS,
|
|
91
|
-
decodeInput:
|
|
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
|
|
157
|
-
const input = requireShapedRecord(value, 'WorkHub
|
|
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
|
-
|
|
166
|
-
|
|
167
|
-
|
|
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 (
|
|
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
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
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
|
-
|
|
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.#
|
|
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.#
|
|
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.#
|
|
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
|
-
|
|
109
|
-
|
|
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.#
|
|
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;
|