maka-agent 0.2.0-dev.12.20260901 → 0.2.0-dev.14.20260902
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/THIRD_PARTY_NOTICES.txt +2 -2
- package/dist/acp/maka-acp-agent.js +6 -3
- package/dist/acp/session-registry.js +307 -0
- package/dist/acp/stdio-server.js +20 -1
- package/dist/cli-core.js +15 -2
- package/dist/pi-transcript.js +1 -1
- package/dist/pi-tui-layout.js +1 -1
- package/dist/pi-tui-mcp-status.js +1 -1
- package/dist/pi-tui-runner.js +1 -1
- package/dist/runtime-host-access-command.js +37 -4
- package/dist/runtime-host-capability-provider-command.js +16 -2
- package/dist/runtime-host-cli-context.js +73 -3
- package/dist/runtime-host-cli.js +37 -6
- package/dist/runtime-host-run-command.js +3 -1
- package/dist/runtime-host-update-command.js +59 -31
- package/dist/tui-copy-catalog.js +4 -2
- package/native/runtime-host-peer/prebuilds/darwin-arm64/maka_runtime_host_peer.node +0 -0
- package/native/runtime-host-peer/prebuilds/linux-arm64/maka_runtime_host_peer.node +0 -0
- package/native/runtime-host-peer/prebuilds/linux-x64/maka_runtime_host_peer.node +0 -0
- package/native/runtime-host-peer/prebuilds/win32-x64/maka_runtime_host_peer.node +0 -0
- package/node_modules/@maka/core/dist/attachments.js +12 -0
- package/node_modules/@maka/core/dist/connection-error-copy.js +17 -34
- package/node_modules/@maka/core/dist/events.js +0 -13
- package/node_modules/@maka/core/dist/maka-wordmark.js +23 -0
- package/node_modules/@maka/core/dist/model-catalog.js +22 -1
- package/node_modules/@maka/core/dist/runtime-event.js +1 -0
- package/node_modules/@maka/core/dist/runtime-policy/connection-catalog-codec.js +50 -1
- package/node_modules/@maka/core/dist/runtime-policy/credential-vault-codec.js +9 -1
- package/node_modules/@maka/core/dist/runtime-policy/model-catalog-entry-codec.js +10 -1
- package/node_modules/@maka/core/dist/runtime-policy/policy-codec.js +75 -0
- package/node_modules/@maka/core/dist/runtime-policy.js +4 -2
- package/node_modules/@maka/core/dist/session.js +1 -0
- package/node_modules/@maka/core/dist/settings.js +10 -2
- package/node_modules/@maka/core/dist/usage-record-schema.js +11 -1
- package/node_modules/@maka/core/package.json +2 -1
- package/node_modules/@maka/mcp/dist/index.js +1 -0
- package/node_modules/@maka/runtime/dist/ai-sdk-backend.js +52 -80
- package/node_modules/@maka/runtime/dist/ai-sdk-compaction.js +178 -140
- package/node_modules/@maka/runtime/dist/archive-read-tool.js +26 -5
- package/node_modules/@maka/runtime/dist/builtin-tools.js +27 -2
- package/node_modules/@maka/runtime/dist/context-budget-policy.js +0 -12
- package/node_modules/@maka/runtime/dist/conversation-copy.js +66 -43
- package/node_modules/@maka/runtime/dist/durable-tool-result-projection.js +31 -0
- package/node_modules/@maka/runtime/dist/history-compact-error.js +10 -2
- package/node_modules/@maka/runtime/dist/history-compact-input-fit.js +7 -1
- package/node_modules/@maka/runtime/dist/history-compaction.js +13 -22
- package/node_modules/@maka/runtime/dist/model-history.js +41 -16
- package/node_modules/@maka/runtime/dist/provider-image-overflow-recovery.js +12 -31
- package/node_modules/@maka/runtime/dist/runtime-event-backfill.js +3 -0
- package/node_modules/@maka/runtime/dist/runtime-event-read-model.js +13 -2
- package/node_modules/@maka/runtime/dist/session-event-runtime-mapper.js +3 -6
- package/node_modules/@maka/runtime/dist/shell-tools.js +77 -1
- package/node_modules/@maka/runtime/dist/tool-availability.js +74 -5
- package/node_modules/@maka/runtime/dist/tool-result-archive-resource.js +333 -52
- package/node_modules/@maka/runtime/dist/tool-result-archive-transition.js +34 -3
- package/node_modules/@maka/runtime/dist/tool-runtime.js +12 -0
- package/node_modules/@maka/runtime-host/dist/adapter/session-projector.js +0 -3
- package/node_modules/@maka/runtime-host/dist/client/catalog-reader.js +40 -13
- package/node_modules/@maka/runtime-host/dist/client/connection.js +50 -31
- package/node_modules/@maka/runtime-host/dist/client/host-profile.js +48 -4
- package/node_modules/@maka/runtime-host/dist/client/index.js +2 -2
- package/node_modules/@maka/runtime-host/dist/client/owner-connection-code.js +32 -1
- package/node_modules/@maka/runtime-host/dist/client/peer-client.js +22 -4
- package/node_modules/@maka/runtime-host/dist/operator/access-management-frame.js +10 -1
- package/node_modules/@maka/runtime-host/dist/peer-mesh/node.js +56 -12
- package/node_modules/@maka/runtime-host/dist/peer-mesh/owner.js +3 -0
- package/node_modules/@maka/runtime-host/dist/protocol/configuration.js +55 -9
- package/node_modules/@maka/runtime-host/dist/protocol/host-status.js +37 -0
- package/node_modules/@maka/runtime-host/dist/protocol/index.js +17 -1
- package/node_modules/@maka/runtime-host/dist/protocol/network-proxy.js +1 -7
- package/node_modules/@maka/runtime-host/dist/protocol/operations.js +2 -0
- package/node_modules/@maka/runtime-host/dist/protocol/runtime-policy.js +48 -1
- package/node_modules/@maka/runtime-host/dist/protocol/session-collaboration.js +4 -2
- package/node_modules/@maka/runtime-host/dist/protocol/turn.js +2 -12
- package/node_modules/@maka/runtime-host/dist/server/access-authority.js +2 -1
- package/node_modules/@maka/runtime-host/dist/server/agent-graph-execution-coordinator.js +1 -2
- package/node_modules/@maka/runtime-host/dist/server/canonical-turn-snapshot.js +0 -9
- package/node_modules/@maka/runtime-host/dist/server/configuration-coordinator.js +20 -1
- package/node_modules/@maka/runtime-host/dist/server/execution-composition.js +46 -24
- package/node_modules/@maka/runtime-host/dist/server/execution-service.js +4 -1
- package/node_modules/@maka/runtime-host/dist/server/host-kernel.js +15 -0
- package/node_modules/@maka/runtime-host/dist/server/listener-set.js +8 -4
- package/node_modules/@maka/runtime-host/dist/server/network-proxy-coordinator.js +0 -1
- package/node_modules/@maka/runtime-host/dist/server/peer-listener.js +3 -0
- package/node_modules/@maka/runtime-host/dist/server/runtime-policy-coordinator.js +28 -1
- package/node_modules/@maka/runtime-host/dist/server/session-retirement-coordinator.js +3 -3
- package/node_modules/@maka/runtime-host/dist/server/session-revision-coordinator.js +35 -3
- package/node_modules/@maka/runtime-host/dist/server/session-sidecar-purge.js +16 -0
- package/node_modules/@maka/storage/dist/runtime-policy/coordinator.js +189 -6
- package/node_modules/@maka/storage/dist/runtime-policy-stores.js +4 -1
- package/node_modules/@maka/storage/dist/settings-store.js +16 -25
- package/node_modules/fast-uri/index.js +215 -47
- package/node_modules/fast-uri/lib/schemes.js +9 -4
- package/node_modules/fast-uri/lib/utils.js +396 -92
- package/node_modules/fast-uri/package.json +1 -1
- package/node_modules/qs/.github/THREAT_MODEL.md +3 -3
- package/node_modules/qs/CHANGELOG.md +15 -0
- package/node_modules/qs/README.md +19 -1
- package/node_modules/qs/dist/qs.js +21 -21
- package/node_modules/qs/eslint.config.mjs +1 -1
- package/node_modules/qs/lib/parse.js +3 -4
- package/node_modules/qs/lib/stringify.js +23 -8
- package/node_modules/qs/lib/utils.js +10 -3
- package/node_modules/qs/package.json +4 -4
- package/package.json +1 -1
|
@@ -22,7 +22,8 @@ export const RUNTIME_HOST_ACCESS_MANAGEMENT_ERROR_CODE_MAX_BYTES = 128;
|
|
|
22
22
|
export const RUNTIME_HOST_ACCESS_MANAGEMENT_ERROR_MESSAGE_MAX_BYTES = 2 * 1024;
|
|
23
23
|
const FRAME_MAX_BYTES = 768 * 1024;
|
|
24
24
|
const CREDENTIAL_MAX_BYTES = 8 * 1024;
|
|
25
|
-
const
|
|
25
|
+
const CONNECTION_CODE_MAX_BYTES = 64 * 1024;
|
|
26
|
+
const ACCESS_ACTIONS = ['list', 'prepare', 'revoke', 'connection-code'];
|
|
26
27
|
const boundedString = (maxBytes) => z
|
|
27
28
|
.string()
|
|
28
29
|
.min(1)
|
|
@@ -69,6 +70,14 @@ const ACCESS_MANAGEMENT_FRAME_SCHEMA = z.union([
|
|
|
69
70
|
credentials: z.array(CREDENTIAL_METADATA_SCHEMA),
|
|
70
71
|
})
|
|
71
72
|
.strict(),
|
|
73
|
+
z
|
|
74
|
+
.object({
|
|
75
|
+
schemaVersion: z.literal(1),
|
|
76
|
+
kind: z.literal('result'),
|
|
77
|
+
action: z.literal('connection-code'),
|
|
78
|
+
connectionCode: boundedString(CONNECTION_CODE_MAX_BYTES),
|
|
79
|
+
})
|
|
80
|
+
.strict(),
|
|
72
81
|
z
|
|
73
82
|
.object({
|
|
74
83
|
schemaVersion: z.literal(1),
|
|
@@ -33,6 +33,7 @@ const ROUTE_PAGE_SIZE = 8;
|
|
|
33
33
|
const RECONCILE_CONCURRENCY = 4;
|
|
34
34
|
const RECONCILE_DEADLINE_MS = 60 * 1_000;
|
|
35
35
|
const RECONCILE_INTERVAL_MS = 30 * 1_000;
|
|
36
|
+
const LOCAL_ROUTE_OBSERVATION_INTERVAL_MS = 1_000;
|
|
36
37
|
export async function openPeerMeshNode(input) {
|
|
37
38
|
const store = await openPeerMeshStateStore(input.dataRoot, input.peer.identity().peerId);
|
|
38
39
|
const node = new PeerMeshNodeImpl({ ...input, store });
|
|
@@ -50,6 +51,7 @@ class PeerMeshNodeImpl {
|
|
|
50
51
|
#peer;
|
|
51
52
|
#endpointKind;
|
|
52
53
|
#now;
|
|
54
|
+
#onBackgroundReconcileError;
|
|
53
55
|
#activeControlStreams = new Set();
|
|
54
56
|
#lifetime = new AbortController();
|
|
55
57
|
#admissionTail = Promise.resolve();
|
|
@@ -64,6 +66,7 @@ class PeerMeshNodeImpl {
|
|
|
64
66
|
this.#peer = input.peer;
|
|
65
67
|
this.#endpointKind = input.endpointKind;
|
|
66
68
|
this.#now = input.now ?? Date.now;
|
|
69
|
+
this.#onBackgroundReconcileError = input.onBackgroundReconcileError;
|
|
67
70
|
}
|
|
68
71
|
async initialize() {
|
|
69
72
|
for (const route of this.#store.read().routes)
|
|
@@ -559,9 +562,11 @@ class PeerMeshNodeImpl {
|
|
|
559
562
|
const visible = stored.meshes.some((mesh) => isActiveMembership(mesh, localPeerId) && mesh.roster.roster.members.includes(peerId));
|
|
560
563
|
if (!visible)
|
|
561
564
|
return;
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
+
// A signed route can remain within its TTL after a peer restarted or
|
|
566
|
+
// rotated Relay reservations. Every connection establishment therefore
|
|
567
|
+
// asks the Mesh control plane for its newest record. Callers with a
|
|
568
|
+
// self-contained invitation run this reconciliation in parallel with the
|
|
569
|
+
// first dial; callers without usable routes wait for it.
|
|
565
570
|
await this.reconcile(signal);
|
|
566
571
|
}
|
|
567
572
|
reconcile(signal) {
|
|
@@ -621,11 +626,47 @@ class PeerMeshNodeImpl {
|
|
|
621
626
|
return this.#store.close();
|
|
622
627
|
}
|
|
623
628
|
async #runReconciliation(signal) {
|
|
629
|
+
let failureReported = false;
|
|
624
630
|
while (!signal.aborted) {
|
|
625
|
-
|
|
626
|
-
|
|
631
|
+
try {
|
|
632
|
+
await this.reconcile(signal);
|
|
633
|
+
failureReported = false;
|
|
634
|
+
}
|
|
635
|
+
catch (error) {
|
|
636
|
+
if (!signal.aborted && !failureReported) {
|
|
637
|
+
failureReported = true;
|
|
638
|
+
try {
|
|
639
|
+
this.#onBackgroundReconcileError?.(error);
|
|
640
|
+
}
|
|
641
|
+
catch {
|
|
642
|
+
// Diagnostics cannot control Peer Mesh reconciliation.
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
await this.#waitForReconciliationTrigger(signal).catch(() => undefined);
|
|
627
647
|
}
|
|
628
648
|
}
|
|
649
|
+
async #waitForReconciliationTrigger(signal) {
|
|
650
|
+
let remainingMs = RECONCILE_INTERVAL_MS;
|
|
651
|
+
while (!signal.aborted && remainingMs > 0) {
|
|
652
|
+
const waitMs = Math.min(LOCAL_ROUTE_OBSERVATION_INTERVAL_MS, remainingMs);
|
|
653
|
+
await delay(waitMs, undefined, { signal });
|
|
654
|
+
if (this.#localRouteRequiresRefresh())
|
|
655
|
+
return;
|
|
656
|
+
remainingMs -= waitMs;
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
#localRouteRequiresRefresh() {
|
|
660
|
+
const identity = this.#peer.identity();
|
|
661
|
+
const current = this.#store.read();
|
|
662
|
+
if (!current.meshes.some((state) => isActiveMembership(state, identity.peerId))) {
|
|
663
|
+
return false;
|
|
664
|
+
}
|
|
665
|
+
const existing = current.routes
|
|
666
|
+
.filter(({ route }) => route.peerId === identity.peerId)
|
|
667
|
+
.sort((left, right) => right.route.sequence - left.route.sequence)[0];
|
|
668
|
+
return !isCurrentLocalRoute(existing, identity, current, this.#endpointKind, this.#now());
|
|
669
|
+
}
|
|
629
670
|
async #reconcile(signal) {
|
|
630
671
|
const lifetimeSignal = signal
|
|
631
672
|
? AbortSignal.any([signal, this.#lifetime.signal])
|
|
@@ -811,13 +852,7 @@ class PeerMeshNodeImpl {
|
|
|
811
852
|
const existing = current.routes
|
|
812
853
|
.filter(({ route }) => route.peerId === identity.peerId)
|
|
813
854
|
.sort((left, right) => right.route.sequence - left.route.sequence)[0];
|
|
814
|
-
if (existing
|
|
815
|
-
existing.route.expiresAt > now + ROUTE_REFRESH_LEAD_MS &&
|
|
816
|
-
sameAddresses(existing.route.routeHints, identity.listenAddresses) &&
|
|
817
|
-
sameAddresses(existing.route.coordinationRelays, identity.coordinationRelays) &&
|
|
818
|
-
existing.route.endpointKind === this.#endpointKind &&
|
|
819
|
-
existing.route.displayName === (current.displayName ?? undefined) &&
|
|
820
|
-
existing.route.transitMeshId === current.transitMeshId) {
|
|
855
|
+
if (isCurrentLocalRoute(existing, identity, current, this.#endpointKind, now)) {
|
|
821
856
|
return { state: current, result: existing };
|
|
822
857
|
}
|
|
823
858
|
const route = await this.#signLocalRoute(current);
|
|
@@ -1519,6 +1554,15 @@ function responseRoutes(state, routes, knownRoutes, now) {
|
|
|
1519
1554
|
function sameAddresses(left, right) {
|
|
1520
1555
|
return left.length === right.length && left.every((address, index) => address === right[index]);
|
|
1521
1556
|
}
|
|
1557
|
+
function isCurrentLocalRoute(existing, identity, current, endpointKind, now) {
|
|
1558
|
+
return Boolean(existing &&
|
|
1559
|
+
existing.route.expiresAt > now + ROUTE_REFRESH_LEAD_MS &&
|
|
1560
|
+
sameAddresses(existing.route.routeHints, identity.listenAddresses) &&
|
|
1561
|
+
sameAddresses(existing.route.coordinationRelays, identity.coordinationRelays) &&
|
|
1562
|
+
existing.route.endpointKind === endpointKind &&
|
|
1563
|
+
existing.route.displayName === (current.displayName ?? undefined) &&
|
|
1564
|
+
existing.route.transitMeshId === current.transitMeshId);
|
|
1565
|
+
}
|
|
1522
1566
|
function mergeAddresses(primary, fallback) {
|
|
1523
1567
|
return Object.freeze([...new Set([...primary, ...fallback])].slice(0, 32));
|
|
1524
1568
|
}
|
|
@@ -57,6 +57,9 @@ export async function openRuntimeHostPeerMeshOwner(input) {
|
|
|
57
57
|
dataRoot: join(input.dataRoot, client.identity().peerId),
|
|
58
58
|
peer: client,
|
|
59
59
|
endpointKind: input.endpointKind,
|
|
60
|
+
...(input.onBackgroundReconcileError
|
|
61
|
+
? { onBackgroundReconcileError: input.onBackgroundReconcileError }
|
|
62
|
+
: {}),
|
|
60
63
|
});
|
|
61
64
|
resolverMesh = mesh;
|
|
62
65
|
}
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* specific language governing permissions and limitations
|
|
17
17
|
* under the License.
|
|
18
18
|
*/
|
|
19
|
-
import { decodeCredentialLocator, REQUEST_HEADERS_MAX_BYTES, } from '@maka/core/runtime-policy';
|
|
19
|
+
import { decodeCredentialLocator, decodeConnectionCredentialTarget, decodeConnectionVersionBasis, normalizeNetworkProxyCredentialTarget, REQUEST_HEADERS_MAX_BYTES, } from '@maka/core/runtime-policy';
|
|
20
20
|
import { requireEncodedByteLimit, requireExactRecord, requireShapedRecord, requireUtf8String, } from './codec.js';
|
|
21
21
|
import { invalidProtocolFrame } from './errors.js';
|
|
22
22
|
import { defineOperation } from './operation-spec.js';
|
|
@@ -39,17 +39,41 @@ export const CONFIGURATION_OPERATION_SPECS = {
|
|
|
39
39
|
}),
|
|
40
40
|
};
|
|
41
41
|
function decodeConfigurationCredentialExportInput(value) {
|
|
42
|
-
const input =
|
|
43
|
-
|
|
42
|
+
const input = requireShapedRecord(value, 'configuration credential export input', ['locator'], ['expectedConnection']);
|
|
43
|
+
const locator = decodeLocator(input.locator);
|
|
44
|
+
const expectedConnection = input.expectedConnection === undefined
|
|
45
|
+
? undefined
|
|
46
|
+
: decodeDomainValue(() => decodeConnectionCredentialTarget(input.expectedConnection));
|
|
47
|
+
if (expectedConnection && locator.scope !== 'connection') {
|
|
48
|
+
throw invalidProtocolFrame('Only connection credential exports accept a target basis');
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
locator,
|
|
52
|
+
...(expectedConnection === undefined ? {} : { expectedConnection }),
|
|
53
|
+
};
|
|
44
54
|
}
|
|
45
55
|
function decodeConfigurationCredentialExportResult(value) {
|
|
46
|
-
const result =
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
56
|
+
const result = requireShapedRecord(value, 'configuration credential export result', ['credential'], ['connectionStale']);
|
|
57
|
+
const connectionStale = result.connectionStale === undefined
|
|
58
|
+
? undefined
|
|
59
|
+
: decodeConnectionStale(result.connectionStale);
|
|
60
|
+
if (connectionStale && result.credential !== null) {
|
|
61
|
+
throw invalidProtocolFrame('A stale connection export must not include credential material');
|
|
62
|
+
}
|
|
63
|
+
if (result.credential === null) {
|
|
64
|
+
return {
|
|
65
|
+
credential: null,
|
|
66
|
+
...(connectionStale === undefined ? {} : { connectionStale }),
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
const entry = requireShapedRecord(result.credential, 'exported configuration credential', ['locator', 'secretBase64'], ['proxyTarget']);
|
|
52
70
|
const locator = decodeLocator(entry.locator);
|
|
71
|
+
const proxyTarget = entry.proxyTarget === undefined
|
|
72
|
+
? undefined
|
|
73
|
+
: decodeDomainValue(() => normalizeNetworkProxyCredentialTarget(entry.proxyTarget));
|
|
74
|
+
if (proxyTarget && locator.scope !== 'network_proxy') {
|
|
75
|
+
throw invalidProtocolFrame('Only proxy credentials may carry a proxy target');
|
|
76
|
+
}
|
|
53
77
|
const maxBytes = locator.scope === 'connection' && locator.kind === 'request_headers'
|
|
54
78
|
? REQUEST_HEADERS_MAX_BYTES
|
|
55
79
|
: CREDENTIAL_SECRET_MAX_BYTES;
|
|
@@ -57,11 +81,33 @@ function decodeConfigurationCredentialExportResult(value) {
|
|
|
57
81
|
credential: {
|
|
58
82
|
locator,
|
|
59
83
|
secretBase64: decodeCredentialSecretBase64(entry.secretBase64, maxBytes),
|
|
84
|
+
...(proxyTarget === undefined ? {} : { proxyTarget }),
|
|
60
85
|
},
|
|
86
|
+
...(connectionStale === undefined ? {} : { connectionStale }),
|
|
61
87
|
};
|
|
62
88
|
requireEncodedByteLimit(decoded, 'configuration credential export result', RESULT_MAX_BYTES);
|
|
63
89
|
return decoded;
|
|
64
90
|
}
|
|
91
|
+
function decodeConnectionStale(value) {
|
|
92
|
+
const stale = requireExactRecord(value, 'configuration credential stale connection', [
|
|
93
|
+
'expected',
|
|
94
|
+
'actual',
|
|
95
|
+
]);
|
|
96
|
+
return {
|
|
97
|
+
expected: decodeDomainValue(() => decodeConnectionVersionBasis(stale.expected)),
|
|
98
|
+
actual: stale.actual === null
|
|
99
|
+
? null
|
|
100
|
+
: decodeDomainValue(() => decodeConnectionVersionBasis(stale.actual)),
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
function decodeDomainValue(decode) {
|
|
104
|
+
try {
|
|
105
|
+
return decode();
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
throw invalidProtocolFrame('Invalid configuration credential connection basis');
|
|
109
|
+
}
|
|
110
|
+
}
|
|
65
111
|
function decodeCredentialSecretBase64(value, maxBytes) {
|
|
66
112
|
const encoded = requireUtf8String(value, 'exported configuration credential secret', Math.ceil(maxBytes / 3) * 4);
|
|
67
113
|
const decoded = Buffer.from(encoded, 'base64');
|
|
@@ -19,9 +19,17 @@
|
|
|
19
19
|
import { invalidProtocolFrame } from './errors.js';
|
|
20
20
|
import { requireCount, requireEncodedByteLimit, requireExactRecord, requireId, requireRecord, requireString, requireUtf8String, } from './codec.js';
|
|
21
21
|
import { defineOperation } from './operation-spec.js';
|
|
22
|
+
export function isHostActivityIdle(activity) {
|
|
23
|
+
return (activity.connections === 0 &&
|
|
24
|
+
activity.activeOperations === 0 &&
|
|
25
|
+
activity.residencies.length === 0);
|
|
26
|
+
}
|
|
22
27
|
export const HOST_DIAGNOSTICS_RESULT_MAX_BYTES = 72 * 1024;
|
|
23
28
|
export const HOST_DIAGNOSTIC_LOG_MAX_ENTRIES = 256;
|
|
24
29
|
export const HOST_DIAGNOSTIC_LOG_MAX_ENTRY_BYTES = 10 * 1024;
|
|
30
|
+
const HOST_PEER_ID_MAX_BYTES = 160;
|
|
31
|
+
const HOST_PEER_ADDRESS_MAX_BYTES = 2 * 1024;
|
|
32
|
+
const HOST_PEER_ROUTE_MAX = 16;
|
|
25
33
|
export const HOST_BOOTSTRAP_OPERATION_SPECS = {
|
|
26
34
|
'host.status': defineOperation({
|
|
27
35
|
mode: 'query',
|
|
@@ -45,11 +53,22 @@ export const HOST_BOOTSTRAP_OPERATION_SPECS = {
|
|
|
45
53
|
decodeOutput: decodeHostUpgradePrepareResult,
|
|
46
54
|
}),
|
|
47
55
|
};
|
|
56
|
+
function decodePeerAddresses(value, label) {
|
|
57
|
+
if (!Array.isArray(value) || value.length > HOST_PEER_ROUTE_MAX) {
|
|
58
|
+
throw invalidProtocolFrame(`Invalid ${label}`);
|
|
59
|
+
}
|
|
60
|
+
const addresses = value.map((address) => requireString(address, label, HOST_PEER_ADDRESS_MAX_BYTES));
|
|
61
|
+
if (new Set(addresses).size !== addresses.length) {
|
|
62
|
+
throw invalidProtocolFrame(`Duplicate ${label}`);
|
|
63
|
+
}
|
|
64
|
+
return Object.freeze(addresses);
|
|
65
|
+
}
|
|
48
66
|
function decodeEmptyHostInput(value, label) {
|
|
49
67
|
requireExactRecord(value, label, []);
|
|
50
68
|
return {};
|
|
51
69
|
}
|
|
52
70
|
function decodeHostStatusResult(value) {
|
|
71
|
+
const valueRecord = requireRecord(value, 'host.status result');
|
|
53
72
|
const record = requireExactRecord(value, 'host.status result', [
|
|
54
73
|
'hostEpoch',
|
|
55
74
|
'compositionId',
|
|
@@ -58,11 +77,13 @@ function decodeHostStatusResult(value) {
|
|
|
58
77
|
'connections',
|
|
59
78
|
'activeOperations',
|
|
60
79
|
'activeResidencies',
|
|
80
|
+
...(valueRecord.peerEndpoint === undefined ? [] : ['peerEndpoint']),
|
|
61
81
|
]);
|
|
62
82
|
return decodeHostStatusFields(record);
|
|
63
83
|
}
|
|
64
84
|
function decodeHostDiagnosticsResult(value) {
|
|
65
85
|
requireEncodedByteLimit(value, 'host.diagnostics.query result', HOST_DIAGNOSTICS_RESULT_MAX_BYTES);
|
|
86
|
+
const valueRecord = requireRecord(value, 'host.diagnostics.query result');
|
|
66
87
|
const record = requireExactRecord(value, 'host.diagnostics.query result', [
|
|
67
88
|
'hostEpoch',
|
|
68
89
|
'compositionId',
|
|
@@ -71,6 +92,7 @@ function decodeHostDiagnosticsResult(value) {
|
|
|
71
92
|
'connections',
|
|
72
93
|
'activeOperations',
|
|
73
94
|
'activeResidencies',
|
|
95
|
+
...(valueRecord.peerEndpoint === undefined ? [] : ['peerEndpoint']),
|
|
74
96
|
'compositionModules',
|
|
75
97
|
'residencies',
|
|
76
98
|
'protocolVersion',
|
|
@@ -177,6 +199,21 @@ function decodeHostStatusFields(record) {
|
|
|
177
199
|
connections: requireCount(record.connections, 'connections'),
|
|
178
200
|
activeOperations: requireCount(record.activeOperations, 'activeOperations'),
|
|
179
201
|
activeResidencies: requireCount(record.activeResidencies, 'activeResidencies'),
|
|
202
|
+
...(record.peerEndpoint === undefined
|
|
203
|
+
? {}
|
|
204
|
+
: { peerEndpoint: decodeHostPeerEndpoint(record.peerEndpoint) }),
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
function decodeHostPeerEndpoint(value) {
|
|
208
|
+
const record = requireExactRecord(value, 'Runtime Host peer endpoint', [
|
|
209
|
+
'peerId',
|
|
210
|
+
'routeHints',
|
|
211
|
+
'coordinationRelays',
|
|
212
|
+
]);
|
|
213
|
+
return {
|
|
214
|
+
peerId: requireString(record.peerId, 'Runtime Host peer id', HOST_PEER_ID_MAX_BYTES),
|
|
215
|
+
routeHints: decodePeerAddresses(record.routeHints, 'Runtime Host peer route hints'),
|
|
216
|
+
coordinationRelays: decodePeerAddresses(record.coordinationRelays, 'Runtime Host peer coordination relays'),
|
|
180
217
|
};
|
|
181
218
|
}
|
|
182
219
|
function requirePlatform(value) {
|
|
@@ -61,7 +61,23 @@ export const RUNTIME_HOST_REGISTRATION_SCHEMA_VERSION = 1;
|
|
|
61
61
|
export const RUNTIME_HOST_PROTOCOL_VERSION = 0;
|
|
62
62
|
// Increment when the same protocol version no longer guarantees safe Client-Host
|
|
63
63
|
// interoperability. Mismatches are rejected before domain commands are admitted.
|
|
64
|
-
export const RUNTIME_HOST_COMPATIBILITY_EPOCH =
|
|
64
|
+
export const RUNTIME_HOST_COMPATIBILITY_EPOCH = 96;
|
|
65
|
+
// 96: Read image tool results may carry durable `session_context` refs.
|
|
66
|
+
// 95: Catalog entries carry `describedByMetadata`, so a client asks the
|
|
67
|
+
// Host-resolved entry — not its own bundled table — whether a model needs a
|
|
68
|
+
// hand-written capability declaration. The field is required, so a newer Host's
|
|
69
|
+
// entry fails an older client's strict decoder, and an older Host's entry
|
|
70
|
+
// (lacking it) fails a newer client's.
|
|
71
|
+
// 94: A failed Turn snapshot no longer carries contextBudgetExhaustedDetail; the
|
|
72
|
+
// retired outcome reads as context_overflow at the ledger boundary, and an older
|
|
73
|
+
// Host still sending the field fails a newer client's closed snapshot decode.
|
|
74
|
+
// 93: Configuration credential transfer binds proxy destinations and
|
|
75
|
+
// Connection credentials to exact Host-owned targets before secret access.
|
|
76
|
+
// Proxy policy and credentials commit through one recoverable Host command;
|
|
77
|
+
// older peers can split the writes and violate the shared credential basis.
|
|
78
|
+
// 92: Owners can query their complete pending Session Turn-request inbox.
|
|
79
|
+
// 91: Host status publishes the live Direct peer endpoint so newly issued
|
|
80
|
+
// connection invitations do not preserve stale startup routes.
|
|
65
81
|
// 90: `session.create.mode` accepts the Bot session mode. A Host that predates
|
|
66
82
|
// it rejects the value as an invalid Session start mode.
|
|
67
83
|
// 89: The Host refreshes its models.dev catalog at startup and announces the
|
|
@@ -19,7 +19,6 @@
|
|
|
19
19
|
import { requireEncodedByteLimit, requireExactRecord, requireShapedRecord, requireUtf8String, } from './codec.js';
|
|
20
20
|
import { invalidProtocolFrame } from './errors.js';
|
|
21
21
|
import { defineOperation } from './operation-spec.js';
|
|
22
|
-
const SECRET_MAX_BYTES = 16 * 1024;
|
|
23
22
|
const RESULT_MAX_BYTES = 8 * 1024;
|
|
24
23
|
const ERRORS = [
|
|
25
24
|
'host_not_ready',
|
|
@@ -38,16 +37,11 @@ export const NETWORK_PROXY_OPERATION_SPECS = {
|
|
|
38
37
|
}),
|
|
39
38
|
};
|
|
40
39
|
function decodeNetworkProxyTestInput(value) {
|
|
41
|
-
const input = requireShapedRecord(value, 'network proxy test input', [], ['networkProxy', '
|
|
40
|
+
const input = requireShapedRecord(value, 'network proxy test input', [], ['networkProxy', 'url', 'timeoutMs']);
|
|
42
41
|
return {
|
|
43
42
|
...(input.networkProxy === undefined
|
|
44
43
|
? {}
|
|
45
44
|
: { networkProxy: decodeNetworkProxy(input.networkProxy) }),
|
|
46
|
-
...(input.password === undefined
|
|
47
|
-
? {}
|
|
48
|
-
: {
|
|
49
|
-
password: requireUtf8String(input.password, 'network proxy password', SECRET_MAX_BYTES),
|
|
50
|
-
}),
|
|
51
45
|
...(input.url === undefined ? {} : { url: decodeProbeUrl(input.url) }),
|
|
52
46
|
...(input.timeoutMs === undefined
|
|
53
47
|
? {}
|
|
@@ -59,6 +59,7 @@ import { TURN_OPERATION_SPECS } from './turn.js';
|
|
|
59
59
|
import { USAGE_PRICING_OPERATION_SPECS } from './usage-pricing.js';
|
|
60
60
|
import { WEB_SEARCH_OPERATION_SPECS } from './web-search.js';
|
|
61
61
|
import { WORKHUB_COORDINATION_OPERATION_SPECS } from './workhub-coordination.js';
|
|
62
|
+
export { isHostActivityIdle } from './host-status.js';
|
|
62
63
|
export { ARTIFACT_CURSOR_MAX_BYTES, ARTIFACT_INGEST_CHUNK_MAX_BYTES, ARTIFACT_INGEST_MIME_TYPE_MAX_BYTES, ARTIFACT_MIME_TYPE_MAX_BYTES, ARTIFACT_NAME_MAX_BYTES, ARTIFACT_PAGE_MAX_ITEMS, ARTIFACT_PREVIEW_MAX_BYTES, ARTIFACT_READ_CHUNK_MAX_BYTES, ARTIFACT_RESULT_MAX_BYTES, ARTIFACT_SUMMARY_MAX_BYTES, decodeArtifactDeleteInput, decodeArtifactDeleteResult, decodeArtifactIngestInput, decodeArtifactIngestResult, decodeArtifactQueryInput, decodeArtifactQueryResult, encodeArtifactDeleteResult, encodeArtifactQueryResult, } from './artifact.js';
|
|
63
64
|
export { TURN_FAILURE_MESSAGE_MAX_BYTES, TURN_MESSAGE_CONTENT_MAX_BYTES, TURN_MESSAGE_TEXT_MAX_BYTES, TURN_RESUME_PARK_REASONS, } from './turn.js';
|
|
64
65
|
export * from './connection-effects.js';
|
|
@@ -162,6 +163,7 @@ export const REMOTE_OWNER_OPERATION_GRANTS = Object.freeze([
|
|
|
162
163
|
'queue.entry.update',
|
|
163
164
|
'queue.retract',
|
|
164
165
|
'runtime.policy.mutate',
|
|
166
|
+
'runtime.policy.network-proxy.update',
|
|
165
167
|
'runtime.policy.query',
|
|
166
168
|
'runtime.resource.controller.acquire',
|
|
167
169
|
'runtime.resource.controller.control',
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* specific language governing permissions and limitations
|
|
17
17
|
* under the License.
|
|
18
18
|
*/
|
|
19
|
-
import { CONNECTION_CATALOG_MAX_CONNECTIONS, CONNECTION_CATALOG_MAX_ENABLED_MODEL_IDS, CONNECTION_CATALOG_MAX_ENTRIES_PER_CONNECTION, CONNECTION_CATALOG_MAX_MODELS_PER_CONNECTION, decodeCanonicalConnectionBaseUrl, decodeModelCatalogEntry, decodeCanonicalRuntimePolicy, decodeConnectionModel, decodeConnectionModelId, decodeConnectionName, decodeConnectionSlug, decodeConnectionTarget, decodeConnectionTestSummary, decodeConnectionVersionBasis, decodeRuntimePolicyEntityId, decodeCredentialLocator, decodeCredentialStatus, decodeCredentialVersionBasis, decodeProviderType, normalizeCreateCatalogConnectionInput, normalizeDeleteCredentialInput, normalizeRemoveCatalogConnectionInput, normalizeOptionalRequestBodyOverlay, normalizeRequestHeaderUpdates, normalizeRuntimePolicyMutation, normalizeSetCredentialInput, normalizeSetDefaultConnectionTargetInput, normalizeUpdateCatalogConnectionInput, REQUEST_HEADERS_MAX_BYTES, RequestCustomizationValidationError, RuntimePolicyDomainDecodeError, } from '@maka/core/runtime-policy';
|
|
19
|
+
import { CONNECTION_CATALOG_MAX_CONNECTIONS, CONNECTION_CATALOG_MAX_ENABLED_MODEL_IDS, CONNECTION_CATALOG_MAX_ENTRIES_PER_CONNECTION, CONNECTION_CATALOG_MAX_MODELS_PER_CONNECTION, decodeCanonicalConnectionBaseUrl, decodeModelCatalogEntry, decodeCanonicalRuntimePolicy, decodeConnectionModel, decodeConnectionModelId, decodeConnectionName, decodeConnectionSlug, decodeConnectionTarget, decodeConnectionTestSummary, decodeConnectionVersionBasis, decodeRuntimePolicyEntityId, decodeCredentialLocator, decodeCredentialStatus, decodeCredentialVersionBasis, decodeProviderType, normalizeCreateCatalogConnectionInput, normalizeDeleteCredentialInput, normalizeRemoveCatalogConnectionInput, normalizeOptionalRequestBodyOverlay, normalizeNetworkProxyUpdate, normalizeNetworkProxyCredentialTarget, normalizeRequestHeaderUpdates, normalizeRuntimePolicyMutation, normalizeSetCredentialInput, normalizeSetDefaultConnectionTargetInput, normalizeUpdateCatalogConnectionInput, REQUEST_HEADERS_MAX_BYTES, RequestCustomizationValidationError, RuntimePolicyDomainDecodeError, } from '@maka/core/runtime-policy';
|
|
20
20
|
import { normalizeRelayModelProfiles } from '@maka/core/model-thinking';
|
|
21
21
|
import { requireExactRecord, requireShapedRecord, requireRecord } from './codec.js';
|
|
22
22
|
import { invalidProtocolFrame } from './errors.js';
|
|
@@ -58,6 +58,13 @@ export const RUNTIME_POLICY_OPERATION_SPECS = {
|
|
|
58
58
|
decodeInput: decodeRuntimePolicyMutation,
|
|
59
59
|
decodeOutput: decodeRuntimePolicyMutationResult,
|
|
60
60
|
}),
|
|
61
|
+
'runtime.policy.network-proxy.update': defineOperation({
|
|
62
|
+
mode: 'command',
|
|
63
|
+
availability: 'ready',
|
|
64
|
+
errors: MUTATION_ERRORS,
|
|
65
|
+
decodeInput: decodeRuntimePolicyNetworkProxyUpdate,
|
|
66
|
+
decodeOutput: decodeRuntimePolicyNetworkProxyUpdateResult,
|
|
67
|
+
}),
|
|
61
68
|
'connection.catalog.query': defineOperation({
|
|
62
69
|
mode: 'query',
|
|
63
70
|
availability: 'ready',
|
|
@@ -158,6 +165,44 @@ function decodeRuntimePolicyMutationResult(value) {
|
|
|
158
165
|
}
|
|
159
166
|
return revisionConflict(item, 'runtime policy mutation result');
|
|
160
167
|
}
|
|
168
|
+
function decodeRuntimePolicyNetworkProxyUpdate(value) {
|
|
169
|
+
const input = decodeDomain(() => normalizeNetworkProxyUpdate(value));
|
|
170
|
+
if (input.credential.kind === 'replace' &&
|
|
171
|
+
Buffer.byteLength(input.credential.secret, 'utf8') > CREDENTIAL_SECRET_MAX_BYTES) {
|
|
172
|
+
throw invalidProtocolFrame('Invalid network proxy credential secret');
|
|
173
|
+
}
|
|
174
|
+
return input;
|
|
175
|
+
}
|
|
176
|
+
function decodeRuntimePolicyNetworkProxyUpdateResult(value) {
|
|
177
|
+
const item = requireRecord(value, 'network proxy update result');
|
|
178
|
+
if (item.kind === 'committed') {
|
|
179
|
+
const committed = requireExactRecord(item, 'network proxy update committed result', [
|
|
180
|
+
'kind',
|
|
181
|
+
'revision',
|
|
182
|
+
'credentialStatus',
|
|
183
|
+
]);
|
|
184
|
+
return {
|
|
185
|
+
kind: 'committed',
|
|
186
|
+
revision: revision(committed.revision, 'runtime policy revision'),
|
|
187
|
+
credentialStatus: decodeDomain(() => decodeCredentialStatus(committed.credentialStatus)),
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
if (item.kind === 'credential_stale')
|
|
191
|
+
return credentialStale(item);
|
|
192
|
+
if (item.kind === 'proxy_target_mismatch') {
|
|
193
|
+
const mismatch = requireExactRecord(item, 'network proxy target mismatch', [
|
|
194
|
+
'kind',
|
|
195
|
+
'expected',
|
|
196
|
+
'actual',
|
|
197
|
+
]);
|
|
198
|
+
return {
|
|
199
|
+
kind: 'proxy_target_mismatch',
|
|
200
|
+
expected: decodeDomain(() => normalizeNetworkProxyCredentialTarget(mismatch.expected)),
|
|
201
|
+
actual: decodeDomain(() => normalizeNetworkProxyCredentialTarget(mismatch.actual)),
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
return revisionConflict(item, 'network proxy update result');
|
|
205
|
+
}
|
|
161
206
|
function decodeCatalogQueryInput(value) {
|
|
162
207
|
const item = requireRecord(value, 'connection catalog query input');
|
|
163
208
|
if (item.kind === 'start') {
|
|
@@ -497,6 +542,8 @@ function decodeSetCredentialResult(value) {
|
|
|
497
542
|
requireExactRecord(item, 'credential connection not found result', ['kind']);
|
|
498
543
|
return { kind: 'connection_not_found' };
|
|
499
544
|
}
|
|
545
|
+
if (item.kind === 'connection_stale')
|
|
546
|
+
return connectionStale(item);
|
|
500
547
|
return credentialStale(item);
|
|
501
548
|
}
|
|
502
549
|
function decodeDeleteCredentialResult(value) {
|
|
@@ -212,8 +212,10 @@ function decodeCollaborationTurnRequestCreateInput(value) {
|
|
|
212
212
|
return { intent: decodeSessionTurnRequestIntent(record.intent) };
|
|
213
213
|
}
|
|
214
214
|
function decodeCollaborationTurnRequestQueryInput(value) {
|
|
215
|
-
const record =
|
|
216
|
-
return
|
|
215
|
+
const record = requireShapedRecord(value, 'collaboration Turn request query', [], ['sessionId']);
|
|
216
|
+
return record.sessionId === undefined
|
|
217
|
+
? {}
|
|
218
|
+
: { sessionId: requireEntityId(record.sessionId, 'sessionId') };
|
|
217
219
|
}
|
|
218
220
|
function decodeCollaborationTurnRequestQueryResult(value) {
|
|
219
221
|
const record = requireExactRecord(value, 'collaboration Turn request query result', [
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* under the License.
|
|
18
18
|
*/
|
|
19
19
|
import { MAX_ATTACHMENT_BYTES, MAX_ATTACHMENT_COUNT } from '@maka/core/attachments';
|
|
20
|
-
import { decodeMessageContent as decodeCanonicalMessageContent,
|
|
20
|
+
import { decodeMessageContent as decodeCanonicalMessageContent, DIRECTORY_REFERENCE_MAX_COUNT, isCanonicalAttachmentRef, } from '@maka/core/events';
|
|
21
21
|
import { isOrchestrationMode, isTurnOrchestrationSource, } from '@maka/core/orchestration';
|
|
22
22
|
import { decodeSkillInvocationResult, } from '@maka/core/skill-invocation';
|
|
23
23
|
import { invalidProtocolFrame } from './errors.js';
|
|
@@ -449,7 +449,7 @@ export function decodeTurnSnapshot(value) {
|
|
|
449
449
|
};
|
|
450
450
|
}
|
|
451
451
|
if (status === 'failed') {
|
|
452
|
-
requireShapedRecord(record, 'failed Turn snapshot', ['sessionId', 'turnId', 'runId', 'status', 'terminalEventId', 'failureClass'], ['failureMessage'
|
|
452
|
+
requireShapedRecord(record, 'failed Turn snapshot', ['sessionId', 'turnId', 'runId', 'status', 'terminalEventId', 'failureClass'], ['failureMessage']);
|
|
453
453
|
return {
|
|
454
454
|
...base,
|
|
455
455
|
status,
|
|
@@ -460,11 +460,6 @@ export function decodeTurnSnapshot(value) {
|
|
|
460
460
|
failureMessage: requireUtf8String(record.failureMessage, 'failureMessage', TURN_FAILURE_MESSAGE_MAX_BYTES, false),
|
|
461
461
|
}
|
|
462
462
|
: {}),
|
|
463
|
-
...(record.contextBudgetExhaustedDetail !== undefined
|
|
464
|
-
? {
|
|
465
|
-
contextBudgetExhaustedDetail: requireContextBudgetExhaustedDetail(record.contextBudgetExhaustedDetail),
|
|
466
|
-
}
|
|
467
|
-
: {}),
|
|
468
463
|
};
|
|
469
464
|
}
|
|
470
465
|
if (status === 'cancelled') {
|
|
@@ -492,11 +487,6 @@ export function decodeTurnSnapshot(value) {
|
|
|
492
487
|
: {}),
|
|
493
488
|
};
|
|
494
489
|
}
|
|
495
|
-
function requireContextBudgetExhaustedDetail(value) {
|
|
496
|
-
if (isContextBudgetExhaustedDetail(value))
|
|
497
|
-
return value;
|
|
498
|
-
throw invalidProtocolFrame('Invalid context budget exhausted detail');
|
|
499
|
-
}
|
|
500
490
|
export function decodeContextCompactionOutcome(value) {
|
|
501
491
|
const record = requireRecord(value, 'Context compaction outcome');
|
|
502
492
|
const kind = requireString(record.kind, 'kind', 32);
|
|
@@ -215,10 +215,11 @@ class FileRuntimeHostAccessAuthority {
|
|
|
215
215
|
const guest = principal.principalKind === 'session_guest';
|
|
216
216
|
return {
|
|
217
217
|
canRequestTurns: guest &&
|
|
218
|
+
input.sessionId !== undefined &&
|
|
218
219
|
this.activeSessionGrant(principal.principalId, input.sessionId, 'session_turn_request') !==
|
|
219
220
|
undefined,
|
|
220
221
|
requests: this.#file.turnAccessRequests.filter((request) => (!guest || request.principalId === principal.principalId) &&
|
|
221
|
-
request.intent.sessionId === input.sessionId),
|
|
222
|
+
(input.sessionId === undefined || request.intent.sessionId === input.sessionId)),
|
|
222
223
|
};
|
|
223
224
|
}
|
|
224
225
|
acknowledgeTurnAccessRequest(principalId, input) {
|
|
@@ -147,8 +147,7 @@ function classifyAgentGraphOutcome(snapshot) {
|
|
|
147
147
|
if (snapshot.status === 'cancelled')
|
|
148
148
|
return { kind: 'aborted', turnId: snapshot.turnId };
|
|
149
149
|
if (snapshot.status === 'failed') {
|
|
150
|
-
if (snapshot.failureClass === 'context_overflow'
|
|
151
|
-
snapshot.failureClass === 'context_budget_exhausted') {
|
|
150
|
+
if (snapshot.failureClass === 'context_overflow') {
|
|
152
151
|
return {
|
|
153
152
|
kind: 'context_overflow',
|
|
154
153
|
turnId: snapshot.turnId,
|
|
@@ -16,7 +16,6 @@
|
|
|
16
16
|
* specific language governing permissions and limitations
|
|
17
17
|
* under the License.
|
|
18
18
|
*/
|
|
19
|
-
import { isContextBudgetExhaustedDetail, } from '@maka/core/events';
|
|
20
19
|
import { truncateUtf8 } from '@maka/core/diagnostic-log';
|
|
21
20
|
import { redactSecrets } from '@maka/core/redaction';
|
|
22
21
|
import { classifyTerminalRuntimeLedger } from '@maka/runtime/terminal-run-commit';
|
|
@@ -53,7 +52,6 @@ export async function readCanonicalTurnSnapshot(stores, identity, knownRun) {
|
|
|
53
52
|
const failureMessage = fact.terminalEvent.content?.kind === 'error'
|
|
54
53
|
? truncateUtf8(redactSecrets(fact.terminalEvent.content.message), TURN_FAILURE_MESSAGE_MAX_BYTES, '…')
|
|
55
54
|
: undefined;
|
|
56
|
-
const contextBudgetExhaustedDetail = readContextBudgetExhaustedDetail(fact.terminalEvent.actions?.stateDelta?.contextBudgetExhaustedDetail);
|
|
57
55
|
return {
|
|
58
56
|
sessionId,
|
|
59
57
|
turnId,
|
|
@@ -62,7 +60,6 @@ export async function readCanonicalTurnSnapshot(stores, identity, knownRun) {
|
|
|
62
60
|
terminalEventId: fact.terminalEvent.id,
|
|
63
61
|
failureClass: fact.failureClass,
|
|
64
62
|
...(failureMessage ? { failureMessage } : {}),
|
|
65
|
-
...(contextBudgetExhaustedDetail ? { contextBudgetExhaustedDetail } : {}),
|
|
66
63
|
};
|
|
67
64
|
}
|
|
68
65
|
if (!fact.abortSource)
|
|
@@ -87,9 +84,6 @@ export async function readCanonicalTurnSnapshot(stores, identity, knownRun) {
|
|
|
87
84
|
}
|
|
88
85
|
return { sessionId, turnId, runId, status: run.status };
|
|
89
86
|
}
|
|
90
|
-
function readContextBudgetExhaustedDetail(value) {
|
|
91
|
-
return isContextBudgetExhaustedDetail(value) ? value : undefined;
|
|
92
|
-
}
|
|
93
87
|
function readContextCompactionOutcome(value) {
|
|
94
88
|
if (!value || typeof value !== 'object')
|
|
95
89
|
return undefined;
|
|
@@ -111,9 +105,6 @@ export function worstCaseFailedTurnSnapshot(identity) {
|
|
|
111
105
|
terminalEventId: 'x'.repeat(128),
|
|
112
106
|
failureClass: '\0'.repeat(128),
|
|
113
107
|
failureMessage: '\0'.repeat(TURN_FAILURE_MESSAGE_MAX_BYTES),
|
|
114
|
-
// Keep capacity preflight conservative for every protocol-valid failure
|
|
115
|
-
// detail, including the longest malformed-summary diagnostic.
|
|
116
|
-
contextBudgetExhaustedDetail: 'malformed_summary_too_small_for_fold',
|
|
117
108
|
};
|
|
118
109
|
}
|
|
119
110
|
async function readRunIfPresent(stores, sessionId, runId) {
|
|
@@ -26,11 +26,30 @@ export class HostConfigurationCoordinator {
|
|
|
26
26
|
}
|
|
27
27
|
async #exportCredentials(input) {
|
|
28
28
|
try {
|
|
29
|
-
const
|
|
29
|
+
const exported = input.expectedConnection
|
|
30
|
+
? await this.policy.exportCredentialMaterial(input.locator, input.expectedConnection)
|
|
31
|
+
: {
|
|
32
|
+
kind: 'exported',
|
|
33
|
+
material: await this.policy.exportCredentialMaterial(input.locator),
|
|
34
|
+
};
|
|
35
|
+
if (exported.kind === 'connection_stale') {
|
|
36
|
+
return {
|
|
37
|
+
ok: true,
|
|
38
|
+
result: {
|
|
39
|
+
credential: null,
|
|
40
|
+
connectionStale: {
|
|
41
|
+
expected: exported.expected,
|
|
42
|
+
actual: exported.actual,
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
const material = exported.material;
|
|
30
48
|
const credential = material
|
|
31
49
|
? {
|
|
32
50
|
locator: material.locator,
|
|
33
51
|
secretBase64: Buffer.from(material.secret, 'utf8').toString('base64'),
|
|
52
|
+
...(material.proxyTarget === undefined ? {} : { proxyTarget: material.proxyTarget }),
|
|
34
53
|
}
|
|
35
54
|
: null;
|
|
36
55
|
return { ok: true, result: { credential } };
|