maka-agent 0.2.0-dev.26.20260909 → 0.2.0-dev.27.20260910
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/cli-core.js +21 -0
- package/dist/runtime-host-cli.js +43 -3
- package/dist/runtime-host-handoff-surface.js +10 -8
- package/dist/runtime-host-lifecycle-transaction.js +28 -3
- package/dist/runtime-host-local-source-retirement.js +1 -1
- package/dist/runtime-host-setup-command.js +29 -6
- package/dist/runtime-host-update-command.js +49 -5
- package/dist/session-export-command.js +72 -0
- package/native/runtime-host-windows-task-launcher/prebuilds/win32-x64/maka-runtime-host-task-launcher.exe +0 -0
- package/node_modules/@maka/core/dist/usage-stats/types.js +2 -0
- package/node_modules/@maka/core/dist/workhub-routing.js +126 -0
- package/node_modules/@maka/core/package.json +2 -1
- package/node_modules/@maka/runtime/dist/ai-sdk-turn.js +7 -3
- package/node_modules/@maka/runtime/dist/builtin-tools.js +21 -2
- package/node_modules/@maka/runtime/dist/plugin-agent-service.js +131 -0
- package/node_modules/@maka/runtime/dist/plugin-approval-service.js +33 -0
- package/node_modules/@maka/runtime/dist/plugin-attachment-service.js +53 -0
- package/node_modules/@maka/runtime/dist/plugin-command-service.js +100 -0
- package/node_modules/@maka/runtime/dist/plugin-data-services.js +332 -0
- package/node_modules/@maka/runtime/dist/plugin-fs-service.js +62 -0
- package/node_modules/@maka/runtime/dist/plugin-goal-service.js +61 -0
- package/node_modules/@maka/runtime/dist/plugin-invocation-signal.js +24 -0
- package/node_modules/@maka/runtime/dist/plugin-llm-service.js +85 -0
- package/node_modules/@maka/runtime/dist/plugin-lsp-service.js +94 -0
- package/node_modules/@maka/runtime/dist/plugin-scope-registry.js +91 -0
- package/node_modules/@maka/runtime/dist/plugin-session-query-service.js +71 -0
- package/node_modules/@maka/runtime/dist/plugin-shell-env-service.js +87 -0
- package/node_modules/@maka/runtime/dist/plugin-shell-service.js +74 -0
- package/node_modules/@maka/runtime/dist/plugin-skill-service.js +93 -0
- package/node_modules/@maka/runtime/dist/plugin-system-prompt-service.js +346 -0
- package/node_modules/@maka/runtime/dist/plugin-tool-service.js +18 -52
- package/node_modules/@maka/runtime/dist/plugin-user-question-service.js +43 -0
- package/node_modules/@maka/runtime/dist/plugin-web-service.js +69 -0
- package/node_modules/@maka/runtime/dist/session-export.js +177 -0
- package/node_modules/@maka/runtime/package.json +18 -0
- package/node_modules/@maka/runtime-host/dist/client/host-handoff-copy.js +67 -18
- package/node_modules/@maka/runtime-host/dist/client/host-handoff.js +46 -12
- package/node_modules/@maka/runtime-host/dist/operator/setup-frame.js +31 -21
- package/node_modules/@maka/runtime-host/dist/protocol/index.js +9 -1
- package/node_modules/@maka/runtime-host/dist/protocol/plugin-platform.js +30 -5
- package/node_modules/@maka/runtime-host/dist/protocol/workhub-coordination.js +25 -23
- package/node_modules/@maka/runtime-host/dist/server/client-capability-coordinator.js +62 -4
- package/node_modules/@maka/runtime-host/dist/server/execution-composition.js +452 -7
- package/node_modules/@maka/runtime-host/dist/server/execution-model-authority.js +74 -0
- package/node_modules/@maka/runtime-host/dist/server/hosted-execution-recovery.js +2 -2
- package/node_modules/@maka/runtime-host/dist/server/hosted-execution-tool-profile.js +30 -0
- package/node_modules/@maka/runtime-host/dist/server/interactive-run-composer.js +79 -16
- package/node_modules/@maka/runtime-host/dist/server/message-coordinator.js +25 -4
- package/node_modules/@maka/runtime-host/dist/server/plugin-data-runtime.js +234 -0
- package/node_modules/@maka/runtime-host/dist/server/plugin-platform-coordinator.js +6 -0
- package/node_modules/@maka/runtime-host/dist/server/plugin-platform.js +12 -0
- package/node_modules/@maka/runtime-host/dist/server/root-turn-coordinator.js +189 -92
- package/node_modules/@maka/runtime-host/dist/server/workhub-coordination-action-gate.js +44 -35
- package/node_modules/@maka/runtime-host/dist/server/workhub-coordination-coordinator.js +92 -10
- package/node_modules/@maka/storage/dist/agent-run-store.js +54 -10
- package/node_modules/@maka/storage/dist/context-offload-snapshot.js +13 -6
- package/node_modules/@maka/storage/dist/execution-stores.js +1 -1
- package/node_modules/@maka/storage/dist/session-bundle-policy.js +333 -30
- package/node_modules/@maka/storage/dist/session-store.js +2 -2
- package/node_modules/@maka/storage/dist/sqlite-session-metadata-store.js +12 -5
- package/node_modules/@maka/storage/package.json +2 -0
- package/package.json +1 -1
package/dist/cli-core.js
CHANGED
|
@@ -52,6 +52,8 @@ export function parseMakaCliArgs(argv, version, cliCommand = RELEASE_MAKA_CLI_LA
|
|
|
52
52
|
return { kind: 'run', args: argv.slice(1) };
|
|
53
53
|
if (first === 'activate')
|
|
54
54
|
return { kind: 'activate', args: argv.slice(1) };
|
|
55
|
+
if (first === 'session-export')
|
|
56
|
+
return { kind: 'session-export', args: argv.slice(1) };
|
|
55
57
|
if (first === 'eval')
|
|
56
58
|
return { kind: 'eval', args: argv.slice(1) };
|
|
57
59
|
if (first === 'update')
|
|
@@ -97,6 +99,7 @@ function helpText(cliCommand) {
|
|
|
97
99
|
` ${cliCommand} --acp Serve ACP v1 over stdio (initialize, session/new, session/list)`,
|
|
98
100
|
` ${cliCommand} run ... Run one non-interactive model turn`,
|
|
99
101
|
` ${cliCommand} activate ... Run one Cloud Session activation and emit JSONL`,
|
|
102
|
+
` ${cliCommand} session-export --workspace-root <dir> --session <id> --out <file.maka-session>`,
|
|
100
103
|
` ${cliCommand} -p ... Alias for ${cliCommand} run`,
|
|
101
104
|
` ${cliCommand} eval ... Run one declarative multi-arm experiment`,
|
|
102
105
|
` ${cliCommand} update --target <latest|next|version> Update this npm-global CLI and its local Runtime Host`,
|
|
@@ -243,6 +246,10 @@ export async function runMakaCli(argv = process.argv.slice(2), options = RELEASE
|
|
|
243
246
|
const { runMakaActivationCli } = await import('./activation-command.js');
|
|
244
247
|
return runMakaActivationCli(command.args);
|
|
245
248
|
}
|
|
249
|
+
case 'session-export': {
|
|
250
|
+
const { runMakaSessionExportCli } = await import('./session-export-command.js');
|
|
251
|
+
return runMakaSessionExportCli(command.args);
|
|
252
|
+
}
|
|
246
253
|
case 'eval': {
|
|
247
254
|
const { configureInstalledEvalBundle } = await import('./eval-bundle-path.js');
|
|
248
255
|
configureInstalledEvalBundle();
|
|
@@ -386,6 +393,8 @@ export async function runMakaCli(argv = process.argv.slice(2), options = RELEASE
|
|
|
386
393
|
bindPairingToClient: command.bindPairingToClient,
|
|
387
394
|
...(command.repairRootAfterRemount ? { repairRootAfterRemount: true } : {}),
|
|
388
395
|
updateExisting: command.updateExisting,
|
|
396
|
+
reuseExistingEnvironment: command.reuseExistingEnvironment,
|
|
397
|
+
allowInterruptActiveTasks: command.allowInterruptActiveTasks,
|
|
389
398
|
...(command.rootPath ? { rootPath: command.rootPath } : {}),
|
|
390
399
|
...(command.projectDirectoryRoots
|
|
391
400
|
? { projectDirectoryRoots: command.projectDirectoryRoots }
|
|
@@ -485,7 +494,13 @@ export async function runMakaCli(argv = process.argv.slice(2), options = RELEASE
|
|
|
485
494
|
defaultRootPath: serviceDataRoots.workspaceRoot,
|
|
486
495
|
selector: command.selector,
|
|
487
496
|
expectedTarget: command.expectedTarget,
|
|
497
|
+
...(command.expectedSourceVersion
|
|
498
|
+
? { expectedSourceVersion: command.expectedSourceVersion }
|
|
499
|
+
: {}),
|
|
488
500
|
...(command.expectedHost ? { expectedHost: command.expectedHost } : {}),
|
|
501
|
+
...(command.expectedConfigFingerprint
|
|
502
|
+
? { expectedConfigFingerprint: command.expectedConfigFingerprint }
|
|
503
|
+
: {}),
|
|
489
504
|
...(command.managedRootId ? { managedRootId: command.managedRootId } : {}),
|
|
490
505
|
...(command.operatorDeploymentId
|
|
491
506
|
? { operatorDeploymentId: command.operatorDeploymentId }
|
|
@@ -503,7 +518,13 @@ export async function runMakaCli(argv = process.argv.slice(2), options = RELEASE
|
|
|
503
518
|
...(sourcePackageIntegrity ? { sourcePackageIntegrity } : {}),
|
|
504
519
|
version,
|
|
505
520
|
expectedTarget: command.expectedTarget,
|
|
521
|
+
...(command.expectedSourceVersion
|
|
522
|
+
? { expectedSourceVersion: command.expectedSourceVersion }
|
|
523
|
+
: {}),
|
|
506
524
|
...(command.expectedHost ? { expectedHost: command.expectedHost } : {}),
|
|
525
|
+
...(command.expectedConfigFingerprint
|
|
526
|
+
? { expectedConfigFingerprint: command.expectedConfigFingerprint }
|
|
527
|
+
: {}),
|
|
507
528
|
...(command.managedRootId ? { managedRootId: command.managedRootId } : {}),
|
|
508
529
|
...(command.operatorDeploymentId
|
|
509
530
|
? { operatorDeploymentId: command.operatorDeploymentId }
|
package/dist/runtime-host-cli.js
CHANGED
|
@@ -363,6 +363,8 @@ function parseSetupCommand(argv) {
|
|
|
363
363
|
let bindPairingToClient = false;
|
|
364
364
|
let repairRootAfterRemount = false;
|
|
365
365
|
let updateExisting = false;
|
|
366
|
+
let reuseExistingEnvironment = false;
|
|
367
|
+
let allowInterruptActiveTasks = false;
|
|
366
368
|
let clientDataRoot;
|
|
367
369
|
let enableDirectPeer = false;
|
|
368
370
|
const coordinationRelays = [];
|
|
@@ -418,6 +420,16 @@ function parseSetupCommand(argv) {
|
|
|
418
420
|
return error('Duplicate --repair-root-after-remount');
|
|
419
421
|
repairRootAfterRemount = true;
|
|
420
422
|
},
|
|
423
|
+
'--allow-interrupt-active-tasks': () => {
|
|
424
|
+
if (allowInterruptActiveTasks)
|
|
425
|
+
return error('Duplicate --allow-interrupt-active-tasks');
|
|
426
|
+
allowInterruptActiveTasks = true;
|
|
427
|
+
},
|
|
428
|
+
'--reuse-existing-environment': () => {
|
|
429
|
+
if (reuseExistingEnvironment)
|
|
430
|
+
return error('Duplicate --reuse-existing-environment');
|
|
431
|
+
reuseExistingEnvironment = true;
|
|
432
|
+
},
|
|
421
433
|
'--update-existing': () => {
|
|
422
434
|
if (updateExisting)
|
|
423
435
|
return error('Duplicate --update-existing');
|
|
@@ -427,6 +439,17 @@ function parseSetupCommand(argv) {
|
|
|
427
439
|
});
|
|
428
440
|
if ('kind' in options)
|
|
429
441
|
return options;
|
|
442
|
+
if (reuseExistingEnvironment &&
|
|
443
|
+
(lifecycle !== 'on_demand' ||
|
|
444
|
+
updateExisting ||
|
|
445
|
+
enableDirectPeer ||
|
|
446
|
+
deferPairingCommit ||
|
|
447
|
+
bindPairingToClient)) {
|
|
448
|
+
return error('--reuse-existing-environment requires on-demand local setup without update or remote pairing options');
|
|
449
|
+
}
|
|
450
|
+
if (allowInterruptActiveTasks && !updateExisting) {
|
|
451
|
+
return error('--allow-interrupt-active-tasks requires --update-existing');
|
|
452
|
+
}
|
|
430
453
|
if (!principalId || !/^[A-Za-z0-9_.:-]{1,128}$/u.test(principalId)) {
|
|
431
454
|
return error('runtime-host setup requires a valid --principal');
|
|
432
455
|
}
|
|
@@ -448,6 +471,8 @@ function parseSetupCommand(argv) {
|
|
|
448
471
|
...(bindPairingToClient ? { bindPairingToClient: true } : {}),
|
|
449
472
|
...(repairRootAfterRemount ? { repairRootAfterRemount: true } : {}),
|
|
450
473
|
...(updateExisting ? { updateExisting: true } : {}),
|
|
474
|
+
...(reuseExistingEnvironment ? { reuseExistingEnvironment: true } : {}),
|
|
475
|
+
...(allowInterruptActiveTasks ? { allowInterruptActiveTasks: true } : {}),
|
|
451
476
|
...(clientDataRoot ? { clientDataRoot } : {}),
|
|
452
477
|
...(enableDirectPeer ? { directPeer: { coordinationRelays } } : {}),
|
|
453
478
|
};
|
|
@@ -522,6 +547,7 @@ function parseServiceManagementCommand(argv) {
|
|
|
522
547
|
let updateTarget;
|
|
523
548
|
let expectedHost;
|
|
524
549
|
let expectedConfigFingerprint;
|
|
550
|
+
let expectedSourceVersion;
|
|
525
551
|
const flagOptions = action === 'uninstall'
|
|
526
552
|
? {
|
|
527
553
|
'--retain-managed-deployment': () => {
|
|
@@ -580,6 +606,17 @@ function parseServiceManagementCommand(argv) {
|
|
|
580
606
|
},
|
|
581
607
|
}
|
|
582
608
|
: {}),
|
|
609
|
+
...(action === 'update'
|
|
610
|
+
? {
|
|
611
|
+
'--expected-source-version': (value) => {
|
|
612
|
+
if (expectedSourceVersion !== undefined)
|
|
613
|
+
return error('Duplicate --expected-source-version');
|
|
614
|
+
if (!isProductReleaseVersion(value))
|
|
615
|
+
return error('--expected-source-version must be an exact package version');
|
|
616
|
+
expectedSourceVersion = value;
|
|
617
|
+
},
|
|
618
|
+
}
|
|
619
|
+
: {}),
|
|
583
620
|
...(action === 'update' || action === 'restart'
|
|
584
621
|
? {
|
|
585
622
|
'--expected-host-json': (value) => {
|
|
@@ -592,7 +629,7 @@ function parseServiceManagementCommand(argv) {
|
|
|
592
629
|
},
|
|
593
630
|
}
|
|
594
631
|
: {}),
|
|
595
|
-
...(action === 'configure'
|
|
632
|
+
...(action === 'configure' || action === 'update'
|
|
596
633
|
? {
|
|
597
634
|
'--expected-config-fingerprint': (value) => {
|
|
598
635
|
if (expectedConfigFingerprint !== undefined) {
|
|
@@ -674,8 +711,9 @@ function parseServiceManagementCommand(argv) {
|
|
|
674
711
|
};
|
|
675
712
|
}
|
|
676
713
|
if (action === 'update') {
|
|
677
|
-
if (expectedHost
|
|
678
|
-
|
|
714
|
+
if ((expectedHost || expectedSourceVersion || expectedConfigFingerprint) &&
|
|
715
|
+
!options.managedRootId) {
|
|
716
|
+
return error('Observed Host and deployment fences require --managed-root-id');
|
|
679
717
|
}
|
|
680
718
|
const selector = updateTarget === undefined ? undefined : parseUpdateSelector(updateTarget, 'update');
|
|
681
719
|
if (selector && 'kind' in selector && selector.kind === 'error')
|
|
@@ -697,6 +735,8 @@ function parseServiceManagementCommand(argv) {
|
|
|
697
735
|
: {}),
|
|
698
736
|
expectedTarget: options.expectedTarget,
|
|
699
737
|
...(expectedHost ? { expectedHost } : {}),
|
|
738
|
+
...(expectedConfigFingerprint ? { expectedConfigFingerprint } : {}),
|
|
739
|
+
...(expectedSourceVersion ? { expectedSourceVersion } : {}),
|
|
700
740
|
...(selector ? { selector } : {}),
|
|
701
741
|
...(allowManualUpdate ? { allowManualUpdate: true } : {}),
|
|
702
742
|
...(allowInterruptActiveTasks ? { allowInterruptActiveTasks: true } : {}),
|
|
@@ -60,7 +60,7 @@ export function createCliHostHandoffSurface(locale, input = process.stdin, outpu
|
|
|
60
60
|
'\n');
|
|
61
61
|
if (view.actions.length === 0)
|
|
62
62
|
return;
|
|
63
|
-
const options = copy.actions.map(({ action, label }) => `${action === 'interrupt' ? 'stop' : action === 'retry' ? 'r' : 'Enter'}: ${label}`);
|
|
63
|
+
const options = copy.actions.map(({ action, label }) => `${action === 'interrupt' ? 'stop' : action === 'retry' ? 'r' : action === 'replace' ? 'update' : 'Enter'}: ${label}`);
|
|
64
64
|
// Create the reader only after the explanation is visible, with the
|
|
65
65
|
// final action prompt already installed. Never draw readline's default >.
|
|
66
66
|
const reader = createInterface({
|
|
@@ -82,13 +82,15 @@ export function createCliHostHandoffSurface(locale, input = process.stdin, outpu
|
|
|
82
82
|
if (readline !== reader || current?.revision !== view.revision)
|
|
83
83
|
return;
|
|
84
84
|
const answer = line.trim().toLowerCase();
|
|
85
|
-
const action = answer === '
|
|
86
|
-
? '
|
|
87
|
-
: answer === '
|
|
88
|
-
? '
|
|
89
|
-
: answer === ''
|
|
90
|
-
? '
|
|
91
|
-
:
|
|
85
|
+
const action = answer === 'update'
|
|
86
|
+
? 'replace'
|
|
87
|
+
: answer === 'r'
|
|
88
|
+
? 'retry'
|
|
89
|
+
: answer === 'stop'
|
|
90
|
+
? 'interrupt'
|
|
91
|
+
: answer === ''
|
|
92
|
+
? 'cancel'
|
|
93
|
+
: undefined;
|
|
92
94
|
if (!action || !view.actions.includes(action)) {
|
|
93
95
|
reader.prompt();
|
|
94
96
|
return;
|
|
@@ -178,9 +178,6 @@ export async function retireRuntimeHostLifecycleOwner(input) {
|
|
|
178
178
|
}
|
|
179
179
|
async function retireRuntimeHostLifecycleOwnerWithSignal(input, signal) {
|
|
180
180
|
signal?.throwIfAborted();
|
|
181
|
-
if (input.expectedOwner && !input.supervisor) {
|
|
182
|
-
throw new RuntimeHostLifecycleTransactionError('owner_changed', 'A Runtime Host identity fence requires a supervised deployment');
|
|
183
|
-
}
|
|
184
181
|
const capability = await resolveExistingStorageRoot({
|
|
185
182
|
path: input.rootPath,
|
|
186
183
|
kind: 'interactive',
|
|
@@ -189,6 +186,9 @@ async function retireRuntimeHostLifecycleOwnerWithSignal(input, signal) {
|
|
|
189
186
|
const idleOwner = await tryAcquireStateRootOwner(capability);
|
|
190
187
|
if (idleOwner) {
|
|
191
188
|
try {
|
|
189
|
+
if (input.expectedOwner && !input.supervisor) {
|
|
190
|
+
throw new RuntimeHostLifecycleTransactionError('owner_changed', 'The observed Runtime Host has exited');
|
|
191
|
+
}
|
|
192
192
|
if (input.expectedOwner && input.supervisor) {
|
|
193
193
|
const status = await input.supervisor.status();
|
|
194
194
|
assertExpectedSupervisorOwner(input.expectedOwner, status);
|
|
@@ -212,6 +212,21 @@ async function retireRuntimeHostLifecycleOwnerWithSignal(input, signal) {
|
|
|
212
212
|
});
|
|
213
213
|
assertExpectedRuntimeHostOwner(input.expectedOwner, 'registration' in connected ? connected.registration : undefined);
|
|
214
214
|
if (connected.kind !== 'connected') {
|
|
215
|
+
if (connected.kind === 'incompatible' &&
|
|
216
|
+
connected.registration?.rootId === input.rootId &&
|
|
217
|
+
connected.registration.lifecycleMode === 'ephemeral' &&
|
|
218
|
+
input.expectedOwner &&
|
|
219
|
+
!input.supervisor &&
|
|
220
|
+
input.prepareSourceRetirement) {
|
|
221
|
+
signal?.throwIfAborted();
|
|
222
|
+
const prepared = await input.prepareSourceRetirement(signal);
|
|
223
|
+
if (prepared === 'active_work')
|
|
224
|
+
return { kind: 'active_tasks' };
|
|
225
|
+
if (prepared === 'prepared') {
|
|
226
|
+
return waitForRuntimeHostLifecycleOwner(capability, input.timeoutMs ?? 45_000);
|
|
227
|
+
}
|
|
228
|
+
throw new RuntimeHostLifecycleTransactionError('transition_failed', 'The installed source package cannot retire this Runtime Host');
|
|
229
|
+
}
|
|
215
230
|
if (input.supervisor) {
|
|
216
231
|
const status = await input.supervisor.status();
|
|
217
232
|
assertExpectedSupervisorOwner(input.expectedOwner, status);
|
|
@@ -316,6 +331,10 @@ export async function replaceRuntimeHostLifecycle(input) {
|
|
|
316
331
|
const retirement = await retireRuntimeHostLifecycleOwner({
|
|
317
332
|
rootPath: desired.root.path,
|
|
318
333
|
rootId: desired.root.id,
|
|
334
|
+
...(input.deps.connectExisting ? { connectExisting: input.deps.connectExisting } : {}),
|
|
335
|
+
...(input.prepareSourceRetirement
|
|
336
|
+
? { prepareSourceRetirement: input.prepareSourceRetirement }
|
|
337
|
+
: {}),
|
|
319
338
|
...(input.retirementSupervisor
|
|
320
339
|
? { supervisor: input.retirementSupervisor }
|
|
321
340
|
: currentProvider
|
|
@@ -345,6 +364,12 @@ export async function replaceRuntimeHostLifecycle(input) {
|
|
|
345
364
|
}
|
|
346
365
|
}
|
|
347
366
|
catch (activationError) {
|
|
367
|
+
// An on-demand update may have allowed its successor to open the State Root
|
|
368
|
+
// before readiness failed. Keep that successor authoritative; configuring an
|
|
369
|
+
// existing package and supervised updates retain their rollback behavior.
|
|
370
|
+
if (input.operation === 'update' && desired.lifecycle.mode === 'on_demand') {
|
|
371
|
+
throw new RuntimeHostLifecycleTransactionError('recovery_failed', 'The updated Runtime Host could not become ready. Its deployment is retained; retry activation or repair it without restoring older code.', { cause: activationError });
|
|
372
|
+
}
|
|
348
373
|
const rollback = current
|
|
349
374
|
? {
|
|
350
375
|
...current,
|
|
@@ -74,7 +74,7 @@ export function launchRuntimeHostLocalSourceRetirement(input) {
|
|
|
74
74
|
: []),
|
|
75
75
|
];
|
|
76
76
|
return new Promise((resolve, reject) => {
|
|
77
|
-
const child = spawn(process.execPath, args, {
|
|
77
|
+
const child = spawn(input.sourceNodePath ?? process.execPath, args, {
|
|
78
78
|
// fd 4 inherits the existing owner-authority lease. The source helper
|
|
79
79
|
// holds it only while the authenticated retirement request is in flight.
|
|
80
80
|
stdio: ['ignore', 'ignore', 'inherit', 'ignore', input.inheritableAuthorityLeaseFd],
|
|
@@ -23,7 +23,7 @@ import { isDeepStrictEqual } from 'node:util';
|
|
|
23
23
|
import { truncateUtf8 } from '@maka/core/diagnostic-log';
|
|
24
24
|
import { generalizedErrorMessage } from '@maka/core/redaction';
|
|
25
25
|
import { activateRuntimeHostManagedDeployment, connectRemoteRuntimeHost, ensureRuntimeHostPeerIdentity, RuntimeHostOperationError, } from '@maka/runtime-host/client';
|
|
26
|
-
import { RuntimeHostManagedDeploymentError as RuntimeHostDeploymentAuthorityError, encodeRuntimeHostSetupFrame, isSha512PackageIntegrity, resolveRuntimeHostManagedDeployment, runtimeHostManagedOperatorCommand, RUNTIME_HOST_SETUP_ERROR_CODE_MAX_BYTES, RUNTIME_HOST_SETUP_ERROR_MESSAGE_MAX_BYTES, } from '@maka/runtime-host/operator';
|
|
26
|
+
import { RuntimeHostManagedDeploymentError as RuntimeHostDeploymentAuthorityError, encodeRuntimeHostSetupFrame, isSha512PackageIntegrity, resolveRuntimeHostManagedDeployment, resolveRuntimeHostManagedDeploymentAuthority, runtimeHostManagedOperatorCommand, RUNTIME_HOST_SETUP_ERROR_CODE_MAX_BYTES, RUNTIME_HOST_SETUP_ERROR_MESSAGE_MAX_BYTES, } from '@maka/runtime-host/operator';
|
|
27
27
|
import { INTERACTIVE_RUNTIME_HOST_COMPOSITION_ID, RUNTIME_HOST_PROTOCOL_VERSION, } from '@maka/runtime-host/protocol';
|
|
28
28
|
import { prepareRuntimeHostAccessCredential, replaceRuntimeHostAccessCredential, revokeRuntimeHostAccessCredential, RuntimeHostAccessUnavailableError, } from './runtime-host-access-command.js';
|
|
29
29
|
import { convergeRuntimeHostManagedOperator, verifyRuntimeHostManagedOperator, isRuntimeHostDevelopmentPackageVersion, openRuntimeHostManagedPackageDeployment, prepareRuntimeHostManagedPackageDeployment, pruneRuntimeHostManagedPackages, removeRuntimeHostManagedDeployment, resolveRuntimeHostManagedPackageCliPath, resolveRuntimeHostManagedControlRoot, resolveRuntimeHostManagedDeploymentRoot, restoreRuntimeHostLegacyManagedOperator, RuntimeHostManagedDeploymentError, } from './runtime-host-managed-deployment.js';
|
|
@@ -107,7 +107,7 @@ export async function runRuntimeHostSetupCli(options, overrides = {}) {
|
|
|
107
107
|
try {
|
|
108
108
|
const rootId = await resolveRuntimeHostSetupRootId(options);
|
|
109
109
|
const controlRoot = resolveRuntimeHostManagedControlRoot(rootId);
|
|
110
|
-
await withRuntimeHostManagedServiceDeploymentLock(options.clientDataRoot, () => withRuntimeHostManagedServiceLifecycleLock(options.clientDataRoot, () => withRuntimeHostManagedServiceDeploymentLock(controlRoot, () => withRuntimeHostManagedServiceLifecycleLock(controlRoot, () => runRuntimeHostSetupLocked(options, deps, emit), SETUP_LOCK_TIMEOUT_MS), SETUP_LOCK_TIMEOUT_MS), SETUP_LOCK_TIMEOUT_MS), SETUP_LOCK_TIMEOUT_MS);
|
|
110
|
+
await withRuntimeHostManagedServiceDeploymentLock(options.clientDataRoot, () => withRuntimeHostManagedServiceLifecycleLock(options.clientDataRoot, () => withRuntimeHostManagedServiceDeploymentLock(controlRoot, () => withRuntimeHostManagedServiceLifecycleLock(controlRoot, () => runRuntimeHostSetupLocked(options, deps, emit, rootId), SETUP_LOCK_TIMEOUT_MS), SETUP_LOCK_TIMEOUT_MS), SETUP_LOCK_TIMEOUT_MS), SETUP_LOCK_TIMEOUT_MS);
|
|
111
111
|
return 0;
|
|
112
112
|
}
|
|
113
113
|
catch (error) {
|
|
@@ -138,7 +138,30 @@ async function readOptionalLegacyServiceConfig(clientDataRoot) {
|
|
|
138
138
|
throw error;
|
|
139
139
|
}
|
|
140
140
|
}
|
|
141
|
-
async function runRuntimeHostSetupLocked(options, deps, emit) {
|
|
141
|
+
async function runRuntimeHostSetupLocked(options, deps, emit, rootId) {
|
|
142
|
+
if (options.reuseExistingEnvironment) {
|
|
143
|
+
if (options.lifecycle !== 'on_demand' || options.updateExisting) {
|
|
144
|
+
throw new RuntimeHostSetupError('invalid_setup', 'Environment discovery cannot replace a deployment');
|
|
145
|
+
}
|
|
146
|
+
const existing = await resolveRuntimeHostManagedDeploymentAuthority(rootId);
|
|
147
|
+
if (existing) {
|
|
148
|
+
const { config, capability } = await resolveRuntimeHostManagedDeployment(rootId);
|
|
149
|
+
assertCanonicalSetupTarget(options.expectedTarget, rootId, capability.canonicalPath);
|
|
150
|
+
assertExpectedDeploymentGeneration(options.expectedTarget, config);
|
|
151
|
+
// The binding comes from canonical authority. The installed operator validates
|
|
152
|
+
// its own projection when connected; discovery must not rewrite an older launcher.
|
|
153
|
+
emit({
|
|
154
|
+
kind: 'existing_environment',
|
|
155
|
+
version: config.launch.package.version,
|
|
156
|
+
serviceId: rootId,
|
|
157
|
+
deploymentId: config.deploymentId,
|
|
158
|
+
rootId,
|
|
159
|
+
rootPath: capability.canonicalPath,
|
|
160
|
+
operator: runtimeHostManagedOperatorCommand(config, process.platform === 'win32' ? 'win32' : 'posix'),
|
|
161
|
+
});
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
142
165
|
if (options.lifecycle === 'on_demand') {
|
|
143
166
|
await runRuntimeHostOnDemandSetupLocked(options, deps, emit);
|
|
144
167
|
return;
|
|
@@ -260,7 +283,7 @@ async function runRuntimeHostSupervisedSetupLocked(options, deps, emit) {
|
|
|
260
283
|
.then(() => undefined),
|
|
261
284
|
}
|
|
262
285
|
: {}),
|
|
263
|
-
allowInterruptActiveTasks:
|
|
286
|
+
allowInterruptActiveTasks: options.allowInterruptActiveTasks === true,
|
|
264
287
|
deps: lifecycleDeps,
|
|
265
288
|
});
|
|
266
289
|
if (replacement.kind === 'active_tasks') {
|
|
@@ -561,7 +584,7 @@ async function runRuntimeHostOnDemandSetupLocked(options, deps, emit) {
|
|
|
561
584
|
activateDesired: async () => {
|
|
562
585
|
await deps.activateDesired({ rootId: capability.rootId });
|
|
563
586
|
},
|
|
564
|
-
allowInterruptActiveTasks:
|
|
587
|
+
allowInterruptActiveTasks: options.allowInterruptActiveTasks === true,
|
|
565
588
|
deps: lifecycleDeps,
|
|
566
589
|
});
|
|
567
590
|
if (replacement.kind === 'active_tasks') {
|
|
@@ -826,7 +849,7 @@ function createEmitter(json, deps) {
|
|
|
826
849
|
if (frame.kind === 'progress') {
|
|
827
850
|
deps.writeOutput(`${humanPhase(frame.phase)}\n`);
|
|
828
851
|
}
|
|
829
|
-
else if (frame.kind === 'complete') {
|
|
852
|
+
else if (frame.kind === 'complete' || frame.kind === 'existing_environment') {
|
|
830
853
|
deps.writeOutput(`${JSON.stringify(frame, null, 2)}\n`);
|
|
831
854
|
}
|
|
832
855
|
else {
|
|
@@ -20,13 +20,14 @@ import { spawn } from 'node:child_process';
|
|
|
20
20
|
import { dirname, join, resolve } from 'node:path';
|
|
21
21
|
import { truncateUtf8 } from '@maka/core/diagnostic-log';
|
|
22
22
|
import { activateRuntimeHostManagedDeployment } from '@maka/runtime-host/client';
|
|
23
|
-
import { createRuntimeHostLegacyPosixOperatorCommand, decodeRuntimeHostServiceManagementFrame, encodeRuntimeHostServiceManagementFrame, RUNTIME_HOST_SERVICE_ERROR_CODE_MAX_BYTES, RUNTIME_HOST_SERVICE_ERROR_MESSAGE_MAX_BYTES, RUNTIME_HOST_OPERATOR_ACCESS_MANAGEMENT_CAPABILITY, RUNTIME_HOST_OPERATOR_CAPABILITY_REQUEST_ENV, RUNTIME_HOST_OPERATOR_PROCESS_LIFETIME_LOCK_CAPABILITY, runtimeHostOperatorInvocation, RuntimeHostManagedDeploymentError as RuntimeHostDeploymentAuthorityError, } from '@maka/runtime-host/operator';
|
|
24
|
-
import { assertRuntimeHostManagedOperatorConfig, assertRuntimeHostManagedOperatorDeployment, convergeRuntimeHostManagedOperator, verifyRuntimeHostManagedOperator, openRuntimeHostManagedPackageDeployment, prepareRuntimeHostManagedPackageDeployment, pruneRuntimeHostManagedPackages, resolveRuntimeHostManagedControlRoot, resolveRuntimeHostManagedPackageCliPath, RuntimeHostManagedDeploymentError, } from './runtime-host-managed-deployment.js';
|
|
25
|
-
import { manageRuntimeHostService, replaceRuntimeHostManagedService, resolveRuntimeHostManagedServiceId, RuntimeHostServiceManagerError, verifyRuntimeHostManagedServiceReady, withRuntimeHostManagedServiceDeploymentLock, withRuntimeHostManagedServiceLegacyOperatorLeases, withRuntimeHostManagedServiceLifecycleLock, } from './runtime-host-service-manager.js';
|
|
23
|
+
import { compareProductReleaseVersions, createRuntimeHostLegacyPosixOperatorCommand, decodeRuntimeHostServiceManagementFrame, encodeRuntimeHostServiceManagementFrame, RUNTIME_HOST_SERVICE_ERROR_CODE_MAX_BYTES, RUNTIME_HOST_SERVICE_ERROR_MESSAGE_MAX_BYTES, RUNTIME_HOST_OPERATOR_ACCESS_MANAGEMENT_CAPABILITY, RUNTIME_HOST_OPERATOR_CAPABILITY_REQUEST_ENV, RUNTIME_HOST_OPERATOR_PROCESS_LIFETIME_LOCK_CAPABILITY, runtimeHostOperatorInvocation, RuntimeHostManagedDeploymentError as RuntimeHostDeploymentAuthorityError, } from '@maka/runtime-host/operator';
|
|
24
|
+
import { isRuntimeHostDevelopmentPackageVersion, assertRuntimeHostManagedOperatorConfig, assertRuntimeHostManagedOperatorDeployment, convergeRuntimeHostManagedOperator, verifyRuntimeHostManagedOperator, openRuntimeHostManagedPackageDeployment, prepareRuntimeHostManagedPackageDeployment, pruneRuntimeHostManagedPackages, resolveRuntimeHostManagedControlRoot, resolveRuntimeHostManagedPackageCliPath, RuntimeHostManagedDeploymentError, } from './runtime-host-managed-deployment.js';
|
|
25
|
+
import { runtimeHostManagedServiceConfigFingerprint, manageRuntimeHostService, replaceRuntimeHostManagedService, resolveRuntimeHostManagedServiceId, RuntimeHostServiceManagerError, verifyRuntimeHostManagedServiceReady, withRuntimeHostManagedServiceDeploymentLock, withRuntimeHostManagedServiceLegacyOperatorLeases, withRuntimeHostManagedServiceLifecycleLock, } from './runtime-host-service-manager.js';
|
|
26
26
|
import { createPlatformRuntimeHostServiceBackend, resolveRuntimeHostLifecycleProvider, runtimeHostServiceSummary, } from './runtime-host-service-management-command.js';
|
|
27
27
|
import { resolveManagedRuntimeHostUpdateSelection, RuntimeHostUpdateDiscoveryError, } from './runtime-host-update-discovery.js';
|
|
28
28
|
import { RuntimeHostUpdatePackageError, withRuntimeHostRegistryUpdatePackage, } from './runtime-host-update-package.js';
|
|
29
29
|
import { canDiscardRuntimeHostLifecycleDesiredArtifacts, convergeRuntimeHostLifecycleControlProjection, replaceRuntimeHostLifecycle, resolveRecoverableRuntimeHostManagedDeployment, RuntimeHostLifecycleTransactionError, verifyRuntimeHostLifecycleProjection, } from './runtime-host-lifecycle-transaction.js';
|
|
30
|
+
import { launchRuntimeHostLocalSourceRetirement } from './runtime-host-local-source-retirement.js';
|
|
30
31
|
import { manageRuntimeHostManagedLifecycle } from './runtime-host-managed-lifecycle-manager.js';
|
|
31
32
|
const OPERATOR_TIMEOUT_MS = 2 * 60_000;
|
|
32
33
|
const OPERATOR_OUTPUT_MAX_BYTES = 256 * 1024;
|
|
@@ -53,6 +54,7 @@ export async function runManagedRuntimeHostUpdateCli(options, overrides = {}, fr
|
|
|
53
54
|
openDeployment: openRuntimeHostManagedPackageDeployment,
|
|
54
55
|
prepareDeployment: prepareRuntimeHostManagedPackageDeployment,
|
|
55
56
|
prunePackages: pruneRuntimeHostManagedPackages,
|
|
57
|
+
retireSource: launchRuntimeHostLocalSourceRetirement,
|
|
56
58
|
activateDesired: (input) => activateRuntimeHostManagedDeployment(input, {
|
|
57
59
|
reconcileActivation: async () => undefined,
|
|
58
60
|
}),
|
|
@@ -379,7 +381,7 @@ export async function runManagedRuntimeHostUpdateCli(options, overrides = {}, fr
|
|
|
379
381
|
async function runCanonicalRuntimeHostUpdate(options, deps, emit) {
|
|
380
382
|
let staged;
|
|
381
383
|
try {
|
|
382
|
-
return await deps.withDeploymentLock(resolveRuntimeHostManagedControlRoot(options.managedRootId), async () => {
|
|
384
|
+
return await deps.withDeploymentLock(resolveRuntimeHostManagedControlRoot(options.managedRootId), async (inheritableAuthorityLeaseFd) => {
|
|
383
385
|
await deps.canonical.assertOperatorDeployment(options.managedRootId, options.operatorDeploymentId, process.argv[1] ?? '');
|
|
384
386
|
const rejection = await deps.revalidateSelection();
|
|
385
387
|
if (rejection) {
|
|
@@ -395,6 +397,10 @@ async function runCanonicalRuntimeHostUpdate(options, deps, emit) {
|
|
|
395
397
|
throw new RuntimeHostServiceManagerError('not_installed', 'The managed Runtime Host deployment is not installed');
|
|
396
398
|
}
|
|
397
399
|
const current = recovered.config;
|
|
400
|
+
if (options.expectedSourceVersion &&
|
|
401
|
+
current.launch.package.version !== options.expectedSourceVersion) {
|
|
402
|
+
throw new RuntimeHostServiceManagerError('target_mismatch', 'The installed Runtime Host package changed; check it again before updating');
|
|
403
|
+
}
|
|
398
404
|
await deps.canonical.convergeControlProjection(current, lifecycleDeps);
|
|
399
405
|
await deps.canonical.verifyProjection(current, lifecycleDeps);
|
|
400
406
|
deps.canonical.assertOperatorConfig(current, options.operatorDeploymentId, process.argv[1] ?? '');
|
|
@@ -406,6 +412,21 @@ async function runCanonicalRuntimeHostUpdate(options, deps, emit) {
|
|
|
406
412
|
cliPath: process.argv[1] ?? '',
|
|
407
413
|
expectedTarget: options.expectedTarget,
|
|
408
414
|
}, { resolveProvider: resolveRuntimeHostLifecycleProvider });
|
|
415
|
+
if (options.expectedConfigFingerprint &&
|
|
416
|
+
(!currentStatus.service.config ||
|
|
417
|
+
runtimeHostManagedServiceConfigFingerprint(currentStatus.service.config) !==
|
|
418
|
+
options.expectedConfigFingerprint)) {
|
|
419
|
+
throw new RuntimeHostServiceManagerError('target_mismatch', 'The managed Runtime Host configuration changed; check it again before updating');
|
|
420
|
+
}
|
|
421
|
+
const developmentArtifact = isRuntimeHostDevelopmentPackageVersion(options.version) ||
|
|
422
|
+
isRuntimeHostDevelopmentPackageVersion(current.launch.package.version);
|
|
423
|
+
if (developmentArtifact && !options.sourcePackageIntegrity) {
|
|
424
|
+
throw new RuntimeHostServiceManagerError('target_mismatch', 'Development deployments require an explicitly selected source artifact; source hashes do not establish release order');
|
|
425
|
+
}
|
|
426
|
+
if (!developmentArtifact &&
|
|
427
|
+
compareProductReleaseVersions(options.version, current.launch.package.version) < 0) {
|
|
428
|
+
throw new RuntimeHostServiceManagerError('target_mismatch', 'This update would downgrade the shared Runtime Host. Update the Client instead.');
|
|
429
|
+
}
|
|
409
430
|
const targetIntegrity = options.sourcePackageIntegrity ??
|
|
410
431
|
options.registrySelection?.integrity ??
|
|
411
432
|
(options.version === current.launch.package.version
|
|
@@ -468,15 +489,38 @@ async function runCanonicalRuntimeHostUpdate(options, deps, emit) {
|
|
|
468
489
|
},
|
|
469
490
|
};
|
|
470
491
|
emit(progress('retiring', current.launch.package.version, options.version));
|
|
471
|
-
emit(progress('replacing', current.launch.package.version, options.version));
|
|
472
492
|
const replacement = await deps.canonical.replaceLifecycle({
|
|
473
493
|
operation: 'update',
|
|
494
|
+
validateRetiredState: async () => {
|
|
495
|
+
emit(progress('replacing', current.launch.package.version, options.version));
|
|
496
|
+
},
|
|
474
497
|
current,
|
|
475
498
|
desired,
|
|
476
499
|
allowInterruptActiveTasks: options.allowInterruptActiveTasks ?? false,
|
|
477
500
|
...(options.expectedHost ? { expectedOwner: options.expectedHost } : {}),
|
|
478
501
|
...(desired.lifecycle.mode === 'on_demand'
|
|
479
502
|
? {
|
|
503
|
+
...(options.expectedHost
|
|
504
|
+
? {
|
|
505
|
+
prepareSourceRetirement: (signal) => {
|
|
506
|
+
if (inheritableAuthorityLeaseFd === undefined) {
|
|
507
|
+
throw new RuntimeHostServiceManagerError('target_mismatch', 'Source-package retirement requires the deployment authority lease');
|
|
508
|
+
}
|
|
509
|
+
return deps.retireSource({
|
|
510
|
+
sourceCliPath: currentCliPath,
|
|
511
|
+
sourceNodePath: current.launch.nodePath,
|
|
512
|
+
rootPath: current.root.path,
|
|
513
|
+
expectedRootId: current.root.id,
|
|
514
|
+
expectedHostEpoch: options.expectedHost.hostEpoch,
|
|
515
|
+
activeWorkPolicy: options.allowInterruptActiveTasks
|
|
516
|
+
? 'interrupt_active_work'
|
|
517
|
+
: 'refuse_active_work',
|
|
518
|
+
inheritableAuthorityLeaseFd,
|
|
519
|
+
...(signal ? { signal } : {}),
|
|
520
|
+
});
|
|
521
|
+
},
|
|
522
|
+
}
|
|
523
|
+
: {}),
|
|
480
524
|
activateDesired: async () => {
|
|
481
525
|
await deps.activateDesired({ rootId: options.managedRootId });
|
|
482
526
|
},
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Licensed to the Apache Software Foundation (ASF) under one
|
|
3
|
+
* or more contributor license agreements. See the NOTICE file
|
|
4
|
+
* distributed with this work for additional information
|
|
5
|
+
* regarding copyright ownership. The ASF licenses this file
|
|
6
|
+
* to you under the Apache License, Version 2.0 (the
|
|
7
|
+
* "License"); you may not use this file except in compliance
|
|
8
|
+
* with the License. You may obtain a copy of the License at
|
|
9
|
+
*
|
|
10
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
*
|
|
12
|
+
* Unless required by applicable law or agreed to in writing,
|
|
13
|
+
* software distributed under the License is distributed on an
|
|
14
|
+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
15
|
+
* KIND, either express or implied. See the License for the
|
|
16
|
+
* specific language governing permissions and limitations
|
|
17
|
+
* under the License.
|
|
18
|
+
*/
|
|
19
|
+
import { exportSessionBundle } from '@maka/runtime/session-export';
|
|
20
|
+
const USAGE = 'maka session-export --workspace-root <dir> --session <id> --out <file.maka-session>';
|
|
21
|
+
const FAILURE_EXIT_CODES = {
|
|
22
|
+
session_not_found: 2,
|
|
23
|
+
session_active: 3,
|
|
24
|
+
artifact_missing: 4,
|
|
25
|
+
destination_exists: 5,
|
|
26
|
+
workspace_not_found: 6,
|
|
27
|
+
};
|
|
28
|
+
function parseArgs(args) {
|
|
29
|
+
const values = {};
|
|
30
|
+
for (let index = 0; index < args.length; index += 2) {
|
|
31
|
+
const name = args[index];
|
|
32
|
+
const value = args[index + 1];
|
|
33
|
+
if (!name || !value)
|
|
34
|
+
throw new Error(USAGE);
|
|
35
|
+
if (name === '--workspace-root')
|
|
36
|
+
values.workspaceRoot = value;
|
|
37
|
+
else if (name === '--session')
|
|
38
|
+
values.sessionId = value;
|
|
39
|
+
else if (name === '--out')
|
|
40
|
+
values.destination = value;
|
|
41
|
+
else
|
|
42
|
+
throw new Error(USAGE);
|
|
43
|
+
}
|
|
44
|
+
if (!values.workspaceRoot || !values.sessionId || !values.destination)
|
|
45
|
+
throw new Error(USAGE);
|
|
46
|
+
return values;
|
|
47
|
+
}
|
|
48
|
+
export async function runMakaSessionExportCli(args) {
|
|
49
|
+
let parsed;
|
|
50
|
+
try {
|
|
51
|
+
parsed = parseArgs(args);
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
|
|
55
|
+
return 1;
|
|
56
|
+
}
|
|
57
|
+
const result = await exportSessionBundle({
|
|
58
|
+
workspaceRoot: parsed.workspaceRoot,
|
|
59
|
+
sessionId: parsed.sessionId,
|
|
60
|
+
destination: parsed.destination,
|
|
61
|
+
});
|
|
62
|
+
if (!result.ok) {
|
|
63
|
+
process.stderr.write(`${JSON.stringify(result.reason)}\n`);
|
|
64
|
+
return FAILURE_EXIT_CODES[result.reason.kind] ?? 1;
|
|
65
|
+
}
|
|
66
|
+
process.stdout.write(`${JSON.stringify({
|
|
67
|
+
export: result.export,
|
|
68
|
+
archiveDigest: result.artifact.archiveDigest,
|
|
69
|
+
compressedBytes: result.artifact.compressedBytes,
|
|
70
|
+
})}\n`);
|
|
71
|
+
return 0;
|
|
72
|
+
}
|
|
Binary file
|