maka-agent 0.2.0-dev.47.20260922 → 0.2.0-dev.48.20260923
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/runtime-host-capability-provider-command.js +25 -6
- package/dist/tui-mcp-control.js +37 -24
- package/native/runtime-host-windows-task-launcher/prebuilds/win32-x64/maka-runtime-host-task-launcher.exe +0 -0
- package/node_modules/@maka/acp-executor-plugin/dist/acp-errors.js +26 -0
- package/node_modules/@maka/acp-executor-plugin/dist/acp-filesystem.js +103 -0
- package/node_modules/@maka/acp-executor-plugin/dist/acp-process.js +119 -0
- package/node_modules/@maka/acp-executor-plugin/dist/acp-projection.js +146 -0
- package/node_modules/@maka/acp-executor-plugin/dist/index.js +653 -0
- package/node_modules/@maka/acp-executor-plugin/dist/plugin.mjs +24446 -0
- package/node_modules/@maka/acp-executor-plugin/package.json +15 -0
- package/node_modules/@maka/antigravity-acp-plugin/dist/index.js +88 -0
- package/node_modules/@maka/antigravity-acp-plugin/dist/model-presentation.js +53 -0
- package/node_modules/@maka/antigravity-acp-plugin/dist/plugin.mjs +115 -0
- package/node_modules/@maka/antigravity-acp-plugin/package.json +15 -0
- package/node_modules/@maka/core/dist/executor-catalog.js +106 -0
- package/node_modules/@maka/core/dist/mcp.js +4 -1
- package/node_modules/@maka/core/dist/model-metadata.js +28 -1
- package/node_modules/@maka/core/dist/runtime-event-store.js +25 -0
- package/node_modules/@maka/core/dist/runtime-invocation.js +5 -0
- package/node_modules/@maka/core/dist/runtime-policy/credential-vault-codec.js +6 -0
- package/node_modules/@maka/core/dist/runtime-policy/policy-codec.js +21 -0
- package/node_modules/@maka/core/dist/session.js +2 -0
- package/node_modules/@maka/core/dist/settings.js +1 -0
- package/node_modules/@maka/core/dist/tool-ledger-scanner.js +365 -104
- package/node_modules/@maka/core/dist/turn-origin.js +14 -0
- package/node_modules/@maka/core/package.json +2 -0
- package/node_modules/@maka/mcp/dist/credential-coordinator.js +6 -1
- package/node_modules/@maka/mcp/dist/index.js +31 -5
- package/node_modules/@maka/mcp/dist/oauth.js +54 -6
- package/node_modules/@maka/runtime/dist/agent-run-inspect.js +1 -1
- package/node_modules/@maka/runtime/dist/conversation-copy.js +56 -1
- package/node_modules/@maka/runtime/dist/mcp-tools.js +9 -2
- package/node_modules/@maka/runtime/dist/plugin-executor-backend.js +116 -3
- package/node_modules/@maka/runtime/dist/plugin-executor-service.js +212 -16
- package/node_modules/@maka/runtime/dist/runtime-ledger-repair.js +2 -2
- package/node_modules/@maka/runtime/dist/session-event-runtime-mapper.js +3 -0
- package/node_modules/@maka/runtime/dist/session-manager.js +170 -125
- package/node_modules/@maka/runtime/dist/shell-run-manager.js +3 -0
- package/node_modules/@maka/runtime/dist/stream-graph-coordinator.js +29 -4
- package/node_modules/@maka/runtime-host/dist/candidate-entry.js +8 -5
- package/node_modules/@maka/runtime-host/dist/client/index.js +1 -1
- package/node_modules/@maka/runtime-host/dist/client/reconnect-lifecycle.js +8 -1
- package/node_modules/@maka/runtime-host/dist/client/session-catalog-summary.js +6 -1
- package/node_modules/@maka/runtime-host/dist/composition-identity.js +19 -0
- package/node_modules/@maka/runtime-host/dist/protocol/index.js +10 -2
- package/node_modules/@maka/runtime-host/dist/protocol/plugin-platform.js +34 -0
- package/node_modules/@maka/runtime-host/dist/protocol/session-catalog.js +40 -2
- package/node_modules/@maka/runtime-host/dist/server/builtin-external-agent-plugins.js +188 -0
- package/node_modules/@maka/runtime-host/dist/server/candidate.js +12 -7
- package/node_modules/@maka/runtime-host/dist/server/client-capability-recovery.js +44 -46
- package/node_modules/@maka/runtime-host/dist/server/context-coordinator.js +2 -0
- package/node_modules/@maka/runtime-host/dist/server/execution-composition-factory.js +1 -1
- package/node_modules/@maka/runtime-host/dist/server/execution-composition.js +159 -19
- package/node_modules/@maka/runtime-host/dist/server/execution-model-authority.js +3 -0
- package/node_modules/@maka/runtime-host/dist/server/extension-bundle.js +4 -0
- package/node_modules/@maka/runtime-host/dist/server/host-composition-source.js +47 -0
- package/node_modules/@maka/runtime-host/dist/server/host-composition.js +1 -29
- package/node_modules/@maka/runtime-host/dist/server/host-kernel.js +2 -9
- package/node_modules/@maka/runtime-host/dist/server/hosted-execution-recovery.js +75 -9
- package/node_modules/@maka/runtime-host/dist/server/hosted-execution-tool-profile.js +4 -0
- package/node_modules/@maka/runtime-host/dist/server/interaction-coordinator.js +45 -0
- package/node_modules/@maka/runtime-host/dist/server/jev-routing-model.js +157 -0
- package/node_modules/@maka/runtime-host/dist/server/listener-set.js +2 -2
- package/node_modules/@maka/runtime-host/dist/server/message-coordinator.js +4 -0
- package/node_modules/@maka/runtime-host/dist/server/plugin-platform-coordinator.js +11 -1
- package/node_modules/@maka/runtime-host/dist/server/process-lifecycle.js +1 -1
- package/node_modules/@maka/runtime-host/dist/server/process-termination-error.js +27 -0
- package/node_modules/@maka/runtime-host/dist/server/root-turn-coordinator.js +91 -12
- package/node_modules/@maka/runtime-host/dist/server/runtime-policy-coordinator.js +2 -0
- package/node_modules/@maka/runtime-host/dist/server/session-catalog-coordinator.js +99 -12
- package/node_modules/@maka/runtime-host/dist/server/session-effect-coordinator.js +12 -6
- package/node_modules/@maka/runtime-host/dist/server/session-transcript-reader.js +33 -0
- package/node_modules/@maka/runtime-host/dist/server/workhub-coordination-coordinator.js +4 -0
- package/node_modules/@maka/runtime-host/dist/server/workhub-result-coordinator.js +173 -0
- package/node_modules/@maka/runtime-host/dist/server/workhub-result-runtime.js +293 -0
- package/node_modules/@maka/runtime-host/package.json +2 -0
- package/node_modules/@maka/storage/dist/agent-run-store-contract.js +8 -0
- package/node_modules/@maka/storage/dist/execution-stores.js +15 -3
- package/node_modules/@maka/storage/dist/mcp-config-store.js +91 -2
- package/node_modules/@maka/storage/dist/operational-state-store.js +15 -1
- package/node_modules/@maka/storage/dist/plan-authority.js +2 -0
- package/node_modules/@maka/storage/dist/plan-store.js +30 -0
- package/node_modules/@maka/storage/dist/runtime-event-persistence.js +1 -0
- package/node_modules/@maka/storage/dist/runtime-policy/credential-vault-document.js +4 -1
- package/node_modules/@maka/storage/dist/runtime-policy/policy-document.js +2 -0
- package/node_modules/@maka/storage/dist/session-store-values.js +16 -4
- package/node_modules/@maka/storage/dist/shell-run-authority.js +1 -0
- package/node_modules/@maka/storage/dist/shell-run-store.js +15 -0
- package/node_modules/@maka/storage/dist/sqlite-runtime-schema.js +74 -1
- package/node_modules/@maka/storage/dist/sqlite-runtime-store.js +724 -84
- package/node_modules/@maka/storage/dist/sqlite-session-metadata-store.js +16 -0
- package/package.json +1 -1
|
@@ -36,7 +36,7 @@ import { readLogicalRuntimeExecutionForRun } from '@maka/core/runtime-logical-ex
|
|
|
36
36
|
import { buildInvocationOpenedEvent, isSessionInlineInvocation, runtimeInvocationOutcome, } from '@maka/core/runtime-invocation';
|
|
37
37
|
import { isArtifactChildResultOutput } from '@maka/core/artifacts';
|
|
38
38
|
import { invocationMatchesClaimTarget } from '@maka/core/runtime-boundary';
|
|
39
|
-
import { readRunInvocation, } from '@maka/core/runtime-event-store';
|
|
39
|
+
import { readRunInvocation, runtimeInvocationRecoveryInventoryFromInvocations, } from '@maka/core/runtime-event-store';
|
|
40
40
|
import { AGENT_GRAPH_OPERATOR_PROVISION_SCHEMA_VERSION } from '@maka/core/agent-graph-topology';
|
|
41
41
|
import { runtimeInvocationFailureClass, } from './runtime-event-read-model.js';
|
|
42
42
|
import { RuntimeReadModel, RuntimeReadModelError, } from './runtime-read-model.js';
|
|
@@ -381,6 +381,8 @@ export class SessionManager {
|
|
|
381
381
|
if (current.revision !== input.expectedRevision) {
|
|
382
382
|
throw new SessionConfigurationRevisionConflictError(input.expectedRevision, current.revision);
|
|
383
383
|
}
|
|
384
|
+
if (current.header.executorId)
|
|
385
|
+
throw new SessionConfigurationTransitionError('operation_unavailable', 'External executor workspace is fixed. Start a new task.');
|
|
384
386
|
if (current.header.isArchived) {
|
|
385
387
|
throw new SessionConfigurationTransitionError('operation_conflict', 'Archived Session workspace cannot be relocated');
|
|
386
388
|
}
|
|
@@ -567,8 +569,43 @@ export class SessionManager {
|
|
|
567
569
|
return this.recoverInterruptedSessionsWithPolicy({ kind: 'strict', stores });
|
|
568
570
|
}
|
|
569
571
|
async recoverInterruptedSessionsWithPolicy(policy, scope) {
|
|
570
|
-
const
|
|
572
|
+
const profileEnabled = process.env.MAKA_STARTUP_PROFILE === '1';
|
|
573
|
+
const profileTotals = new Map();
|
|
574
|
+
const profileCalls = new Map();
|
|
575
|
+
const measure = async (label, operation) => {
|
|
576
|
+
if (!profileEnabled)
|
|
577
|
+
return operation();
|
|
578
|
+
const started = performance.now();
|
|
579
|
+
try {
|
|
580
|
+
return await operation();
|
|
581
|
+
}
|
|
582
|
+
finally {
|
|
583
|
+
profileTotals.set(label, (profileTotals.get(label) ?? 0) + performance.now() - started);
|
|
584
|
+
profileCalls.set(label, (profileCalls.get(label) ?? 0) + 1);
|
|
585
|
+
}
|
|
586
|
+
};
|
|
587
|
+
const interrupted = (await measure('list-sessions', () => listSessionsForRecovery(this.deps.store, policy))).filter((session) => !session.isArchived && (scope === undefined || scope.has(session.id)));
|
|
588
|
+
const recoveryCandidateSet = async (label, operation) => {
|
|
589
|
+
if (!operation)
|
|
590
|
+
return undefined;
|
|
591
|
+
const sessionIds = await measure(label, () => recoverOr(policy, operation, undefined));
|
|
592
|
+
return sessionIds ? new Set(sessionIds) : undefined;
|
|
593
|
+
};
|
|
594
|
+
const continuationAuthority = runtimeContinuationAuthority(this.deps.runtimeEventStore);
|
|
595
|
+
const [shellRecoverySessions, unsettledContinuationClaims, planRecoverySessions] = await Promise.all([
|
|
596
|
+
recoveryCandidateSet('shell-inventory', this.deps.shellRuns ? () => this.deps.shellRuns.listRecoverySessionIds() : undefined),
|
|
597
|
+
continuationAuthority?.listUnsettledContinuationClaimsForRecovery
|
|
598
|
+
? measure('continuation-inventory', () => recoverOr(policy, () => continuationAuthority.listUnsettledContinuationClaimsForRecovery(interrupted.map((session) => session.id)), undefined))
|
|
599
|
+
: Promise.resolve(undefined),
|
|
600
|
+
recoveryCandidateSet('plan-inventory', this.deps.planStore?.listPlanRecoverySessionIds
|
|
601
|
+
? () => this.deps.planStore.listPlanRecoverySessionIds()
|
|
602
|
+
: undefined),
|
|
603
|
+
]);
|
|
604
|
+
const continuationClaimsBySession = unsettledContinuationClaims
|
|
605
|
+
? groupContinuationClaimsBySession(unsettledContinuationClaims)
|
|
606
|
+
: undefined;
|
|
571
607
|
const recovered = new Set();
|
|
608
|
+
const runRecoveryQueue = [];
|
|
572
609
|
for (const session of interrupted) {
|
|
573
610
|
if (this.runtimeKernel.hasActiveRuns(session.id))
|
|
574
611
|
continue;
|
|
@@ -589,8 +626,9 @@ export class SessionManager {
|
|
|
589
626
|
}), undefined);
|
|
590
627
|
}
|
|
591
628
|
}
|
|
592
|
-
if (this.deps.shellRuns
|
|
593
|
-
|
|
629
|
+
if (this.deps.shellRuns &&
|
|
630
|
+
(!shellRecoverySessions || shellRecoverySessions.has(session.id))) {
|
|
631
|
+
const recoveredShellRuns = await measure('shell', () => recoverOr(policy, () => this.deps.shellRuns.recoverOrphanedSession(session.id), 0));
|
|
594
632
|
if (recoveredShellRuns > 0)
|
|
595
633
|
recovered.add(session.id);
|
|
596
634
|
}
|
|
@@ -599,10 +637,13 @@ export class SessionManager {
|
|
|
599
637
|
// recovery. Deciding it a second time here — off a transcript scan, and
|
|
600
638
|
// ending in `remove()` — could only ever contradict it.
|
|
601
639
|
let continuationClaimRecovered = false;
|
|
602
|
-
const
|
|
603
|
-
if (this.deps.runStore &&
|
|
640
|
+
const unsettledClaims = continuationClaimsBySession?.get(session.id);
|
|
641
|
+
if (this.deps.runStore &&
|
|
642
|
+
continuationAuthority &&
|
|
643
|
+
(!continuationClaimsBySession ||
|
|
644
|
+
unsettledClaims?.some((state) => state.startEventId === undefined || state.startKind === 'claim_repair'))) {
|
|
604
645
|
try {
|
|
605
|
-
continuationClaimRecovered = await this.recoverContinuationClaimsBeforeProvider(session.id, continuationAuthority, policy);
|
|
646
|
+
continuationClaimRecovered = await measure('continuation', () => this.recoverContinuationClaimsBeforeProvider(session.id, continuationAuthority, policy, unsettledClaims));
|
|
606
647
|
}
|
|
607
648
|
catch (error) {
|
|
608
649
|
if (policy.kind === 'strict')
|
|
@@ -616,26 +657,62 @@ export class SessionManager {
|
|
|
616
657
|
if (continuationClaimRecovered)
|
|
617
658
|
recovered.add(session.id);
|
|
618
659
|
}
|
|
619
|
-
if (this.deps.planStore) {
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
660
|
+
if (this.deps.planStore && (!planRecoverySessions || planRecoverySessions.has(session.id))) {
|
|
661
|
+
// Plan events are the domain authority for whether there is a Plan
|
|
662
|
+
// obligation at all. Runtime evidence is needed only to decide whether
|
|
663
|
+
// an existing active Plan belongs to a pending handoff and must survive.
|
|
664
|
+
const planState = await measure('plan-state', () => recoverOr(policy, () => this.deps.planStore.readState(session.id), undefined));
|
|
665
|
+
if (planState?.activeExecutionId) {
|
|
666
|
+
const preservesHandoff = await measure('plan-handoff', () => recoverOr(policy, async () => {
|
|
667
|
+
if (!continuationAuthority)
|
|
668
|
+
return false;
|
|
669
|
+
const latest = latestInvocation((await this.listInvocations(session.id)).filter((run) => isSessionInlineInvocation(run.opening)));
|
|
670
|
+
if (!latest)
|
|
671
|
+
return false;
|
|
672
|
+
// Only the current logical execution may preserve a session-owned Plan.
|
|
673
|
+
// Read after claim repair: an abandoned successor now has a real failure.
|
|
674
|
+
return Boolean((await readLogicalRuntimeExecutionForRun(continuationAuthority, latest))
|
|
675
|
+
?.pendingHandoff);
|
|
676
|
+
}, false));
|
|
677
|
+
if (!preservesHandoff) {
|
|
678
|
+
const planRecovery = await measure('plan-interrupt', () => recoverOr(policy, () => this.deps.planStore.interruptActiveExecution(session.id, 'runtime_recovery'), null));
|
|
679
|
+
if (planRecovery)
|
|
680
|
+
recovered.add(session.id);
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
runRecoveryQueue.push({
|
|
685
|
+
session,
|
|
686
|
+
continuationClaimRecovered,
|
|
687
|
+
...(continuationClaimsBySession
|
|
688
|
+
? {
|
|
689
|
+
claimOwnedUnsettledRunIds: new Set((unsettledClaims ?? []).map((state) => state.claim.target.runId)),
|
|
690
|
+
}
|
|
691
|
+
: {}),
|
|
692
|
+
});
|
|
693
|
+
}
|
|
694
|
+
let inventoryBySession;
|
|
695
|
+
if (this.deps.runStore &&
|
|
696
|
+
this.deps.runtimeEventStore?.listInvocationRecoveryInventory &&
|
|
697
|
+
runRecoveryQueue.length > 0) {
|
|
698
|
+
try {
|
|
699
|
+
const inventory = await measure('run-inventory', () => this.deps.runtimeEventStore.listInvocationRecoveryInventory(runRecoveryQueue.map(({ session }) => session.id)));
|
|
700
|
+
const mutable = new Map();
|
|
701
|
+
for (const entry of inventory) {
|
|
702
|
+
const entries = mutable.get(entry.sessionId) ?? [];
|
|
703
|
+
entries.push(entry);
|
|
704
|
+
mutable.set(entry.sessionId, entries);
|
|
635
705
|
}
|
|
706
|
+
inventoryBySession = mutable;
|
|
636
707
|
}
|
|
708
|
+
catch (error) {
|
|
709
|
+
if (policy.kind === 'strict')
|
|
710
|
+
throw error;
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
for (const { session, continuationClaimRecovered, claimOwnedUnsettledRunIds, } of runRecoveryQueue) {
|
|
637
714
|
if (this.deps.runStore) {
|
|
638
|
-
const runRecovery = await recoverOr(policy, () => this.recoverAgentRunsFromLedger(session.id, policy), undefined);
|
|
715
|
+
const runRecovery = await measure('runs', () => recoverOr(policy, () => this.recoverAgentRunsFromLedger(session.id, policy, inventoryBySession ? (inventoryBySession.get(session.id) ?? []) : undefined, claimOwnedUnsettledRunIds), undefined));
|
|
639
716
|
if (runRecovery?.hasLedger) {
|
|
640
717
|
if (runRecovery.recovered || continuationClaimRecovered) {
|
|
641
718
|
await recoverOr(policy, () => this.updateStatus(session.id, 'active'), undefined);
|
|
@@ -659,6 +736,15 @@ export class SessionManager {
|
|
|
659
736
|
recovered.add(session.id);
|
|
660
737
|
}
|
|
661
738
|
}
|
|
739
|
+
if (profileEnabled) {
|
|
740
|
+
console.error(`[startup-profile] session-recovery ${JSON.stringify({
|
|
741
|
+
sessions: interrupted.length,
|
|
742
|
+
totals: Object.fromEntries([...profileTotals].map(([label, ms]) => [
|
|
743
|
+
label,
|
|
744
|
+
{ calls: profileCalls.get(label) ?? 0, ms },
|
|
745
|
+
])),
|
|
746
|
+
})}`);
|
|
747
|
+
}
|
|
662
748
|
return [...recovered];
|
|
663
749
|
}
|
|
664
750
|
async setSessionStatus(sessionId, status, blockedReason) {
|
|
@@ -693,66 +779,6 @@ export class SessionManager {
|
|
|
693
779
|
await this.deps.store.readHeader(sessionId);
|
|
694
780
|
return this.runtimeKernel.listActiveInteractions?.(sessionId) ?? [];
|
|
695
781
|
}
|
|
696
|
-
async setPermissionMode(sessionId, mode) {
|
|
697
|
-
const readHeaderRecordSnapshot = this.deps.store.readHeaderRecordSnapshot?.bind(this.deps.store);
|
|
698
|
-
if (!readHeaderRecordSnapshot || !this.deps.store.updateSessionConfiguration) {
|
|
699
|
-
// Temporary compatibility bridge for SessionStore embeddings that predate
|
|
700
|
-
// versioned configuration authority. A follow-up PR will shortly remove
|
|
701
|
-
// setPermissionMode and this redundant fallback after callers migrate.
|
|
702
|
-
return this.setPermissionModeWithLegacyStore(sessionId, mode);
|
|
703
|
-
}
|
|
704
|
-
const current = await readHeaderRecordSnapshot(sessionId);
|
|
705
|
-
const next = await this.transitionSessionConfiguration(sessionId, {
|
|
706
|
-
expectedRevision: current.revision,
|
|
707
|
-
clearConnectionBlock: false,
|
|
708
|
-
permissionModeOnly: true,
|
|
709
|
-
configuration: sessionConfigurationWithPermissionMode(current.header, mode),
|
|
710
|
-
});
|
|
711
|
-
return headerToSummary(next.header);
|
|
712
|
-
}
|
|
713
|
-
async setPermissionModeWithLegacyStore(sessionId, mode) {
|
|
714
|
-
const previous = await this.deps.store.readHeader(sessionId);
|
|
715
|
-
const boundary = await this.deps.store.readExecutionBoundary(sessionId);
|
|
716
|
-
if (previous.permissionMode === mode &&
|
|
717
|
-
executionBoundaryMatchesPermissionMode(boundary, mode)) {
|
|
718
|
-
return headerToSummary(previous);
|
|
719
|
-
}
|
|
720
|
-
const labels = previous.labels;
|
|
721
|
-
const kind = mode === 'bypass' ? 'bypass' : 'managed';
|
|
722
|
-
await this.commitExecutionBoundaryTransition(sessionId, boundary, mode, async () => {
|
|
723
|
-
const current = await this.deps.store.readHeader(sessionId);
|
|
724
|
-
if (current.status === 'waiting_for_user') {
|
|
725
|
-
throw new SessionConfigurationTransitionError('session_busy', 'Session has a pending Interaction');
|
|
726
|
-
}
|
|
727
|
-
return () => this.deps.store.setExecutionBoundaryKind(sessionId, kind, {
|
|
728
|
-
permissionMode: mode,
|
|
729
|
-
labels,
|
|
730
|
-
});
|
|
731
|
-
});
|
|
732
|
-
const next = await this.deps.store.readHeader(sessionId);
|
|
733
|
-
this.runtimeKernel.updateCachedHeader(sessionId, next);
|
|
734
|
-
return headerToSummary(next);
|
|
735
|
-
}
|
|
736
|
-
async setExecutionBoundaryKind(sessionId, kind) {
|
|
737
|
-
const current = await this.deps.store.readExecutionBoundary(sessionId);
|
|
738
|
-
const header = await this.deps.store.readHeader(sessionId);
|
|
739
|
-
// Managed includes Explore. Match Storage's default projection, then pass
|
|
740
|
-
// it explicitly so classification and commit describe the same transition.
|
|
741
|
-
const permissionMode = kind === 'bypass'
|
|
742
|
-
? 'bypass'
|
|
743
|
-
: header.permissionMode === 'bypass'
|
|
744
|
-
? 'ask'
|
|
745
|
-
: header.permissionMode;
|
|
746
|
-
const narrows = narrowsExecutionAuthority(current, permissionMode);
|
|
747
|
-
if (narrows && this.runtimeKernel.hasActiveRuns(sessionId)) {
|
|
748
|
-
throw new SessionConfigurationTransitionError('session_busy', 'Execution boundary cannot change while a Turn is running');
|
|
749
|
-
}
|
|
750
|
-
if (header.status === 'waiting_for_user') {
|
|
751
|
-
throw new SessionConfigurationTransitionError('session_busy', 'Execution boundary cannot change while an Interaction is pending');
|
|
752
|
-
}
|
|
753
|
-
const boundary = await this.commitExecutionBoundaryTransition(sessionId, current, permissionMode, async () => () => this.deps.store.setExecutionBoundaryKind(sessionId, kind, { permissionMode }));
|
|
754
|
-
return boundary;
|
|
755
|
-
}
|
|
756
782
|
async commitExecutionBoundaryTransition(sessionId, current, nextPermissionMode, prepareCommit) {
|
|
757
783
|
const prepareBoundaryCommit = async () => {
|
|
758
784
|
const latest = await this.deps.store.readExecutionBoundary(sessionId);
|
|
@@ -3023,10 +3049,10 @@ export class SessionManager {
|
|
|
3023
3049
|
* dead, so that state remains `continuation_started_indeterminate` and is
|
|
3024
3050
|
* deliberately left non-terminal.
|
|
3025
3051
|
*/
|
|
3026
|
-
async recoverContinuationClaimsBeforeProvider(sessionId, authority, _policy) {
|
|
3052
|
+
async recoverContinuationClaimsBeforeProvider(sessionId, authority, _policy, recoveryStates) {
|
|
3027
3053
|
if (!this.deps.runStore)
|
|
3028
3054
|
return false;
|
|
3029
|
-
const states = await authority.listContinuationClaimsForRecovery(sessionId);
|
|
3055
|
+
const states = recoveryStates ?? (await authority.listContinuationClaimsForRecovery(sessionId));
|
|
3030
3056
|
let recovered = false;
|
|
3031
3057
|
for (const initialState of states) {
|
|
3032
3058
|
const { claim } = initialState;
|
|
@@ -3097,24 +3123,41 @@ export class SessionManager {
|
|
|
3097
3123
|
}
|
|
3098
3124
|
return recovered;
|
|
3099
3125
|
}
|
|
3100
|
-
async recoverAgentRunsFromLedger(sessionId, policy = { kind: 'best_effort' }) {
|
|
3126
|
+
async recoverAgentRunsFromLedger(sessionId, policy = { kind: 'best_effort' }, recoveryInventory, recoveryClaimRunIds) {
|
|
3101
3127
|
if (!this.deps.runStore || !this.deps.runtimeEventStore)
|
|
3102
3128
|
return { hasLedger: false, recovered: false };
|
|
3103
3129
|
// The importer may have committed only a prefix before a restart. Sealing
|
|
3104
3130
|
// that prefix here would make the next read skip the unconverted history.
|
|
3105
|
-
const
|
|
3106
|
-
|
|
3131
|
+
const inventory = recoveryInventory
|
|
3132
|
+
? recoveryInventory
|
|
3133
|
+
: this.deps.runtimeEventStore.listInvocationRecoveryInventory
|
|
3134
|
+
? await this.deps.runtimeEventStore.listInvocationRecoveryInventory([sessionId])
|
|
3135
|
+
: runtimeInvocationRecoveryInventoryFromInvocations(await this.listInvocations(sessionId));
|
|
3136
|
+
const ownedInventory = inventory.filter((entry) => {
|
|
3137
|
+
const identity = entry.candidate ?? entry.identity;
|
|
3138
|
+
return !identity || !isTranscriptLedgerInvocation(identity);
|
|
3139
|
+
});
|
|
3140
|
+
if (ownedInventory.length === 0)
|
|
3107
3141
|
return { hasLedger: false, recovered: false };
|
|
3142
|
+
let claimOwnedUnsettledRunIds = recoveryClaimRunIds;
|
|
3108
3143
|
const continuationAuthority = runtimeContinuationAuthority(this.deps.runtimeEventStore);
|
|
3109
|
-
|
|
3110
|
-
|
|
3144
|
+
if (!claimOwnedUnsettledRunIds && continuationAuthority) {
|
|
3145
|
+
const discovered = new Set();
|
|
3111
3146
|
for (const state of await continuationAuthority.listContinuationClaimsForRecovery(sessionId)) {
|
|
3112
3147
|
const events = await continuationAuthority.readImmutableRuntimeEvents(state.claim.target.sessionId, state.claim.target.runId);
|
|
3113
|
-
if (!events.some(isTerminalRuntimeEvent))
|
|
3114
|
-
|
|
3115
|
-
}
|
|
3148
|
+
if (!events.some(isTerminalRuntimeEvent))
|
|
3149
|
+
discovered.add(state.claim.target.runId);
|
|
3116
3150
|
}
|
|
3151
|
+
claimOwnedUnsettledRunIds = discovered;
|
|
3117
3152
|
}
|
|
3153
|
+
const runsNeedingRecovery = ownedInventory.flatMap((entry) => entry.candidate ? [entry.candidate] : []);
|
|
3154
|
+
if (runsNeedingRecovery.length === 0)
|
|
3155
|
+
return { hasLedger: true, recovered: false };
|
|
3156
|
+
const recoveryRunStore = policy.kind === 'strict'
|
|
3157
|
+
? {
|
|
3158
|
+
readEvents: (candidateSessionId, runId) => policy.stores.agentRunStore.readEventsForRecovery(candidateSessionId, runId),
|
|
3159
|
+
}
|
|
3160
|
+
: this.deps.runStore;
|
|
3118
3161
|
// Read once per recovered session, and only when a failure actually needs
|
|
3119
3162
|
// attributing, so healthy sessions pay nothing for the query.
|
|
3120
3163
|
let boundaryClosures;
|
|
@@ -3127,11 +3170,14 @@ export class SessionManager {
|
|
|
3127
3170
|
return boundaryClosures;
|
|
3128
3171
|
};
|
|
3129
3172
|
let recovered = false;
|
|
3130
|
-
for (const run of
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3173
|
+
for (const run of runsNeedingRecovery) {
|
|
3174
|
+
let inspected = await inspectAgentRunReadModel(recoveryRunStore, this.deps.runtimeEventStore, {
|
|
3175
|
+
sessionId,
|
|
3176
|
+
runId: run.runId,
|
|
3177
|
+
invocation: run,
|
|
3178
|
+
includeModelReplay: false,
|
|
3179
|
+
includeProjection: false,
|
|
3180
|
+
});
|
|
3135
3181
|
if (inspected.sourceHealth.runtimeLedger === 'read_failed') {
|
|
3136
3182
|
if (policy.kind === 'strict') {
|
|
3137
3183
|
throw new Error(`RuntimeEvent ledger is unreadable for run ${run.runId}`);
|
|
@@ -3151,7 +3197,7 @@ export class SessionManager {
|
|
|
3151
3197
|
// restart repair must neither replay its tools nor manufacture failure.
|
|
3152
3198
|
continue;
|
|
3153
3199
|
}
|
|
3154
|
-
if (claimOwnedUnsettledRunIds
|
|
3200
|
+
if (claimOwnedUnsettledRunIds?.has(run.runId) &&
|
|
3155
3201
|
!inspected.runtimeEvents.some(isTerminalRuntimeEvent)) {
|
|
3156
3202
|
// Every unresolved claim target belongs to the claim saga. This
|
|
3157
3203
|
// includes claim-only, deterministic repair-start, and live provider
|
|
@@ -3176,7 +3222,13 @@ export class SessionManager {
|
|
|
3176
3222
|
continue;
|
|
3177
3223
|
}
|
|
3178
3224
|
if (interruptedOutcomes.length > 0) {
|
|
3179
|
-
inspected = await inspectAgentRunReadModel(
|
|
3225
|
+
inspected = await inspectAgentRunReadModel(recoveryRunStore, this.deps.runtimeEventStore, {
|
|
3226
|
+
sessionId,
|
|
3227
|
+
runId: run.runId,
|
|
3228
|
+
invocation: run,
|
|
3229
|
+
includeModelReplay: false,
|
|
3230
|
+
includeProjection: false,
|
|
3231
|
+
});
|
|
3180
3232
|
}
|
|
3181
3233
|
}
|
|
3182
3234
|
const terminalLedger = classifyTerminalRuntimeLedger(run, inspected.runtimeEvents);
|
|
@@ -3273,6 +3325,16 @@ function continuationExecutionErrorClass(error) {
|
|
|
3273
3325
|
}
|
|
3274
3326
|
return error instanceof Error ? error.name : 'unknown';
|
|
3275
3327
|
}
|
|
3328
|
+
function groupContinuationClaimsBySession(states) {
|
|
3329
|
+
const grouped = new Map();
|
|
3330
|
+
for (const state of states) {
|
|
3331
|
+
const sessionId = state.claim.target.sessionId;
|
|
3332
|
+
const sessionStates = grouped.get(sessionId) ?? [];
|
|
3333
|
+
sessionStates.push(state);
|
|
3334
|
+
grouped.set(sessionId, sessionStates);
|
|
3335
|
+
}
|
|
3336
|
+
return grouped;
|
|
3337
|
+
}
|
|
3276
3338
|
const MAX_BEST_EFFORT_OUTCOME_COMMIT_ATTEMPTS = 2;
|
|
3277
3339
|
function listSessionsForRecovery(store, policy) {
|
|
3278
3340
|
return policy.kind === 'strict' ? policy.stores.sessionStore.listForRecovery() : store.list();
|
|
@@ -3404,7 +3466,12 @@ export function headerToSummary(h) {
|
|
|
3404
3466
|
...(h.revisionIndex !== undefined ? { revisionIndex: h.revisionIndex } : {}),
|
|
3405
3467
|
...(h.revisionState ? { revisionState: h.revisionState } : {}),
|
|
3406
3468
|
backend: h.backend,
|
|
3407
|
-
...(h.executorId
|
|
3469
|
+
...(h.executorId
|
|
3470
|
+
? {
|
|
3471
|
+
executorId: h.executorId,
|
|
3472
|
+
...(h.executorConfig ? { executorConfig: h.executorConfig } : {}),
|
|
3473
|
+
}
|
|
3474
|
+
: {}),
|
|
3408
3475
|
...(h.llmConnectionId === undefined ? {} : { llmConnectionId: h.llmConnectionId }),
|
|
3409
3476
|
llmConnectionSlug: h.llmConnectionSlug,
|
|
3410
3477
|
connectionLocked: h.connectionLocked,
|
|
@@ -3540,23 +3607,10 @@ function claimedAgentGraphIntentResult(claim, result) {
|
|
|
3540
3607
|
...result,
|
|
3541
3608
|
};
|
|
3542
3609
|
}
|
|
3543
|
-
function sessionConfigurationWithPermissionMode(header, permissionMode) {
|
|
3544
|
-
return {
|
|
3545
|
-
backend: header.backend,
|
|
3546
|
-
executorId: header.executorId,
|
|
3547
|
-
llmConnectionId: header.llmConnectionId,
|
|
3548
|
-
llmConnectionSlug: header.llmConnectionSlug,
|
|
3549
|
-
connectionLocked: header.connectionLocked,
|
|
3550
|
-
model: header.model,
|
|
3551
|
-
thinkingLevel: header.thinkingLevel,
|
|
3552
|
-
permissionMode,
|
|
3553
|
-
collaborationMode: header.collaborationMode ?? 'agent',
|
|
3554
|
-
orchestrationMode: header.orchestrationMode ?? 'default',
|
|
3555
|
-
};
|
|
3556
|
-
}
|
|
3557
3610
|
function sessionConfigurationMatchesExceptPermissionMode(header, configuration) {
|
|
3558
3611
|
return (header.backend === configuration.backend &&
|
|
3559
3612
|
header.executorId === configuration.executorId &&
|
|
3613
|
+
header.executorConfig?.model === configuration.executorConfig?.model &&
|
|
3560
3614
|
header.llmConnectionId === configuration.llmConnectionId &&
|
|
3561
3615
|
header.llmConnectionSlug === configuration.llmConnectionSlug &&
|
|
3562
3616
|
header.connectionLocked === configuration.connectionLocked &&
|
|
@@ -3569,15 +3623,6 @@ function sessionConfigurationMatches(header, configuration) {
|
|
|
3569
3623
|
return (header.permissionMode === configuration.permissionMode &&
|
|
3570
3624
|
sessionConfigurationMatchesExceptPermissionMode(header, configuration));
|
|
3571
3625
|
}
|
|
3572
|
-
function executionBoundaryMatchesPermissionMode(boundary, mode) {
|
|
3573
|
-
if (mode === 'bypass')
|
|
3574
|
-
return boundary.kind === 'bypass';
|
|
3575
|
-
if (boundary.kind !== 'managed')
|
|
3576
|
-
return false;
|
|
3577
|
-
return mode === 'explore'
|
|
3578
|
-
? boundary.profile.name === 'read-only'
|
|
3579
|
-
: boundary.profile.name !== 'read-only';
|
|
3580
|
-
}
|
|
3581
3626
|
function narrowsExecutionAuthority(boundary, nextPermissionMode) {
|
|
3582
3627
|
if (nextPermissionMode === 'bypass')
|
|
3583
3628
|
return false;
|
|
@@ -424,6 +424,9 @@ export class ShellRunProcessManager {
|
|
|
424
424
|
const records = await this.input.store.listSessionShellRuns(sessionId);
|
|
425
425
|
return records.map(shellRunUpdate);
|
|
426
426
|
}
|
|
427
|
+
listRecoverySessionIds() {
|
|
428
|
+
return this.input.store.listShellRunRecoverySessionIds?.() ?? Promise.resolve(undefined);
|
|
429
|
+
}
|
|
427
430
|
async getSessionUpdate(sessionId, ref) {
|
|
428
431
|
const target = parseShellRunResourceRef(ref);
|
|
429
432
|
if (!target)
|
|
@@ -324,16 +324,41 @@ export class AgentGraphCoordinator {
|
|
|
324
324
|
*/
|
|
325
325
|
async recover() {
|
|
326
326
|
const recovered = [];
|
|
327
|
+
const listedRecoveryGraphIds = this.#input.controlStore.listAgentGraphScheduleRecoveryGraphIds
|
|
328
|
+
? await this.#input.controlStore.listAgentGraphScheduleRecoveryGraphIds()
|
|
329
|
+
: undefined;
|
|
330
|
+
const recoveryGraphIds = listedRecoveryGraphIds ? new Set(listedRecoveryGraphIds) : undefined;
|
|
331
|
+
if (recoveryGraphIds?.size === 0)
|
|
332
|
+
return recovered;
|
|
333
|
+
const recoveryRootSessionIds = new Set();
|
|
334
|
+
if (recoveryGraphIds && this.#input.epochStore) {
|
|
335
|
+
for (const graphId of recoveryGraphIds) {
|
|
336
|
+
const binding = await this.#input.epochStore.readAgentGraphEpochByGraphId(graphId);
|
|
337
|
+
if (binding)
|
|
338
|
+
recoveryRootSessionIds.add(binding.rootSessionId);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
327
341
|
for (const header of await this.#input.sessionStore.listForRecovery()) {
|
|
328
342
|
if (this.#input.rootSessionId && header.id !== this.#input.rootSessionId)
|
|
329
343
|
continue;
|
|
330
344
|
if (header.subagentParent || header.isArchived)
|
|
331
345
|
continue;
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
346
|
+
if (recoveryGraphIds &&
|
|
347
|
+
!recoveryGraphIds.has(agentGraphIdForRootSession(header.id)) &&
|
|
348
|
+
!recoveryRootSessionIds.has(header.id)) {
|
|
335
349
|
continue;
|
|
336
|
-
|
|
350
|
+
}
|
|
351
|
+
const graphId = await this.currentGraphId(header.id);
|
|
352
|
+
if (recoveryGraphIds) {
|
|
353
|
+
if (!recoveryGraphIds.has(graphId))
|
|
354
|
+
continue;
|
|
355
|
+
}
|
|
356
|
+
else {
|
|
357
|
+
const updates = await this.#input.controlStore.listAgentGraphScheduleUpdates(graphId);
|
|
358
|
+
if (updates.length === 0)
|
|
359
|
+
continue;
|
|
360
|
+
updates.forEach((update) => this.#assertScheduleOwnedByRoot(update, header.id, graphId));
|
|
361
|
+
}
|
|
337
362
|
await this.reconcile(header.id);
|
|
338
363
|
recovered.push(header.id);
|
|
339
364
|
}
|
|
@@ -21,7 +21,6 @@ import { fileURLToPath } from 'node:url';
|
|
|
21
21
|
import { candidateStartupFailureExitCode, classifyCandidateStartupFailure, } from './candidate-startup-failure.js';
|
|
22
22
|
import { createRuntimeHostLaunchOwnerGuard } from './candidate-launch-owner-guard.js';
|
|
23
23
|
import { parseInteractiveRuntimeHostCandidateArguments } from './candidate-cli.js';
|
|
24
|
-
import { writeCandidateStartupDiagnostic } from './control/startup-diagnostic.js';
|
|
25
24
|
import { installRuntimeHostLogCapture, runtimeHostLogBuffer } from './process-diagnostics.js';
|
|
26
25
|
import { startExecutionRuntimeHostCandidate, } from './server/execution-candidate.js';
|
|
27
26
|
import { runRuntimeHostProcessLifecycle } from './server/process-lifecycle.js';
|
|
@@ -60,13 +59,17 @@ export async function runExecutionCandidateEntry(argv, entrypointUrl, hooks = {}
|
|
|
60
59
|
const logs = runtimeHostLogBuffer.snapshot();
|
|
61
60
|
console.error('[runtime-host] startup failed:', error);
|
|
62
61
|
if (rootId && startupAttemptId) {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
62
|
+
const diagnosticRootId = rootId;
|
|
63
|
+
const diagnosticStartupAttemptId = startupAttemptId;
|
|
64
|
+
await import('./control/startup-diagnostic.js')
|
|
65
|
+
.then(({ writeCandidateStartupDiagnostic }) => writeCandidateStartupDiagnostic({
|
|
66
|
+
rootId: diagnosticRootId,
|
|
67
|
+
startupAttemptId: diagnosticStartupAttemptId,
|
|
66
68
|
failure,
|
|
67
69
|
error,
|
|
68
70
|
logs,
|
|
69
|
-
})
|
|
71
|
+
}))
|
|
72
|
+
.catch(() => undefined);
|
|
70
73
|
}
|
|
71
74
|
process.exit(candidateStartupFailureExitCode(failure));
|
|
72
75
|
}
|
|
@@ -28,7 +28,7 @@ export { LOCAL_RUNTIME_HOST_PROFILE, RUNTIME_HOST_ACCESS_CREDENTIAL_MAX_BYTES, c
|
|
|
28
28
|
export { createRuntimeHostReconnectingConnection, isRuntimeHostReconnectingConnection, } from './reconnecting-connection.js';
|
|
29
29
|
export { RuntimeHostSshOperatorActivationError, activateRuntimeHostSshOperator, runtimeHostSshOperatorRemoteCommand, } from './ssh-operator-activation.js';
|
|
30
30
|
export { normalizeRuntimeHostSshDestination, openRuntimeHostSshTunnel, } from './ssh-tunnel.js';
|
|
31
|
-
export { RuntimeHostPermanentReconnectError, startRuntimeHostReconnectLifecycle, } from './reconnect-lifecycle.js';
|
|
31
|
+
export { RuntimeHostPermanentReconnectError, createRuntimeHostReconnectLifecycle, startRuntimeHostReconnectLifecycle, } from './reconnect-lifecycle.js';
|
|
32
32
|
export { RUNTIME_HOST_REMOTE_INCOMPATIBLE_CODE, RuntimeHostRemoteCompatibilityError, } from './remote-compatibility-error.js';
|
|
33
33
|
export { RuntimeHostSubscriptionError, SessionRemovedSubscriptionError, subscriptionClosedError, } from './session-subscription.js';
|
|
34
34
|
export { RuntimeHostStartupError, runtimeHostStartupError, } from './startup-error.js';
|
|
@@ -26,8 +26,15 @@ export class RuntimeHostPermanentReconnectError extends Error {
|
|
|
26
26
|
this.name = 'RuntimeHostPermanentReconnectError';
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
|
+
/**
|
|
30
|
+
* A lifecycle that exists before its first connection. `waitForCurrent` parks
|
|
31
|
+
* until `start()` installs one and rejects if the start fails permanently.
|
|
32
|
+
*/
|
|
33
|
+
export function createRuntimeHostReconnectLifecycle(input) {
|
|
34
|
+
return new RuntimeHostReconnectLifecycleImpl(input);
|
|
35
|
+
}
|
|
29
36
|
export async function startRuntimeHostReconnectLifecycle(input) {
|
|
30
|
-
const lifecycle =
|
|
37
|
+
const lifecycle = createRuntimeHostReconnectLifecycle(input);
|
|
31
38
|
await lifecycle.start();
|
|
32
39
|
return lifecycle;
|
|
33
40
|
}
|
|
@@ -54,7 +54,12 @@ export function projectSessionCatalogSummary(session) {
|
|
|
54
54
|
...(session.revisionIndex === undefined ? {} : { revisionIndex: session.revisionIndex }),
|
|
55
55
|
...(session.revisionState === undefined ? {} : { revisionState: session.revisionState }),
|
|
56
56
|
backend: session.backend,
|
|
57
|
-
...(session.executorId
|
|
57
|
+
...(session.executorId
|
|
58
|
+
? {
|
|
59
|
+
executorId: session.executorId,
|
|
60
|
+
...(session.executorConfig ? { executorConfig: session.executorConfig } : {}),
|
|
61
|
+
}
|
|
62
|
+
: {}),
|
|
58
63
|
...(session.llmConnectionId === null ? {} : { llmConnectionId: session.llmConnectionId }),
|
|
59
64
|
llmConnectionSlug: session.llmConnectionSlug,
|
|
60
65
|
connectionLocked: session.connectionLocked,
|
|
@@ -0,0 +1,19 @@
|
|
|
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
|
+
export const INTERACTIVE_RUNTIME_HOST_COMPOSITION_ID = 'maka.interactive';
|
|
@@ -28,6 +28,7 @@ import { decodeProjectCatalogChangedFrame, } from './project-catalog-change.js';
|
|
|
28
28
|
import { decodeConnectionCatalogChangedFrame, } from './connection-catalog-change.js';
|
|
29
29
|
import { decodeRequestFrame, decodeResponseFrame, } from './operations.js';
|
|
30
30
|
import { isCanonicalRuntimeHostWebSocketPath } from './websocket-path.js';
|
|
31
|
+
import { INTERACTIVE_RUNTIME_HOST_COMPOSITION_ID } from '../composition-identity.js';
|
|
31
32
|
export * from './access-authority.js';
|
|
32
33
|
export * from './agent-graph.js';
|
|
33
34
|
export * from './interaction.js';
|
|
@@ -58,11 +59,19 @@ export * from './session-todo.js';
|
|
|
58
59
|
export * from './workspace.js';
|
|
59
60
|
export * from './workhub-coordination.js';
|
|
60
61
|
export * from './websocket-path.js';
|
|
62
|
+
export { INTERACTIVE_RUNTIME_HOST_COMPOSITION_ID } from '../composition-identity.js';
|
|
61
63
|
export const RUNTIME_HOST_REGISTRATION_SCHEMA_VERSION = 1;
|
|
62
64
|
export const RUNTIME_HOST_PROTOCOL_VERSION = 0;
|
|
63
65
|
// Increment when the same protocol version no longer guarantees safe Client-Host
|
|
64
66
|
// interoperability. Mismatches are rejected before domain commands are admitted.
|
|
65
|
-
export const RUNTIME_HOST_COMPATIBILITY_EPOCH =
|
|
67
|
+
export const RUNTIME_HOST_COMPATIBILITY_EPOCH = 183;
|
|
68
|
+
// 183: Jev policy snapshots, set_jev mutation and credential locator require matching peers.
|
|
69
|
+
// 182: Executor catalogs expose structured model families and thinking variant IDs.
|
|
70
|
+
// 181: Canonical executor models and retained provider stop reasons after cancellation.
|
|
71
|
+
// 180: Reject contradictory executor configuration and legacy model targets.
|
|
72
|
+
// 179: Generic executor discovery and confirmed per-Session configuration.
|
|
73
|
+
// 178: WorkHub result turns carry a Host-owned workhub_result origin. Older
|
|
74
|
+
// Clients reject that origin and cannot render the result notification.
|
|
66
75
|
// 177: External Session import input may carry an optional Host-resolved
|
|
67
76
|
// workspace target. Epoch-176 peers reject the unknown `workspace` key.
|
|
68
77
|
// 176: Session-scoped capability publication and MCP admission require compatible
|
|
@@ -415,7 +424,6 @@ export const RUNTIME_HOST_COMPATIBILITY_EPOCH = 177;
|
|
|
415
424
|
// one transport message; narrower domains retain their own encoded limits.
|
|
416
425
|
export const RUNTIME_HOST_MAX_MESSAGE_BYTES = 768 * 1024;
|
|
417
426
|
export const RUNTIME_HOST_MAX_IN_FLIGHT_DOMAIN_REQUESTS = 64;
|
|
418
|
-
export const INTERACTIVE_RUNTIME_HOST_COMPOSITION_ID = 'maka.interactive';
|
|
419
427
|
export function negotiateProtocol(client, host) {
|
|
420
428
|
validateProtocolRange(client);
|
|
421
429
|
validateProtocolRange(host);
|