@byok-sdk/cloud 0.6.0 → 0.6.1
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/cloud.d.ts +44 -2
- package/dist/errors.d.ts +10 -0
- package/dist/handlers/messages.d.ts +11 -0
- package/dist/inbound.d.ts +4 -3
- package/dist/index.d.ts +5 -5
- package/dist/index.js +498 -45
- package/dist/index.js.map +1 -1
- package/dist/stores/in-memory/agent-egress.d.ts +12 -0
- package/dist/stores/in-memory/blobs.d.ts +8 -2
- package/dist/stores/in-memory/device-directory.d.ts +4 -0
- package/dist/stores/in-memory/index.d.ts +1 -0
- package/dist/stores/in-memory/task-attempts.d.ts +16 -5
- package/dist/stores/ports.d.ts +86 -3
- package/dist/tenant-stores.d.ts +24 -1
- package/dist/terminal-result.d.ts +5 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { BOARD_STATUSES, CapabilityDeclarationSchema, NONCE_SIGNING_DOMAIN, hasCapability, isTenantId, tenantId, principalTenant, parseDeviceProofEnvelope, deviceProofSigningInput, contentHash, parseCapabilityDeclaration, ByokCoreError, tenantKey, PRESENCE_LEVELS, createInMemoryCoreStores, authenticateDeviceAssertion, assertCapability, isCoreConflictError, isCoreError, DEVICE_PROOF_HEADER, TRUTH_RECORD_KINDS, STORAGE_ERROR_CODES, STORAGE_ERROR_HTTP_STATUS } from '@byok-sdk/core';
|
|
2
2
|
export { DEVICE_PROOF_HEADER, NONCE_SIGNING_DOMAIN, isTenantId, tenantId } from '@byok-sdk/core';
|
|
3
|
-
import { AgentEventOrUnknownSchema, DAEMON_TO_SERVER_TYPES, encodeEnvelope, decodeEnvelope, BYOK_PAIR_PATH, BYOK_CHALLENGE_PATH, BYOK_TOKEN_PATH, BYOK_CAPABILITIES_PATH, BYOK_EVENTS_PATH, BYOK_MESSAGES_PATH, BYOK_BOARD_PATH, BYOK_BOARD_CLAIM_ROUTE, BYOK_BOARD_UNCLAIM_ROUTE, BYOK_BOARD_STATUS_ROUTE, BYOK_BOARD_STREAM_PATH, BYOK_PRESENCE_PATH, BYOK_ACTIVITY_PATH, BYOK_RECORDS_PATH, BYOK_RECORD_ROUTE, BYOK_SKILL_PACKS_PATH, BYOK_SKILL_PACK_FILE_ROUTE, BYOK_BLOBS_PATH, BYOK_BLOB_FINALIZE_ROUTE, BYOK_BLOB_URL_ROUTE, BYOK_BLOB_CONTENT_ROUTE, createEnvelope, PairRequestSchema, ChallengeRequestSchema, TokenRequestSchema, MessagesSendRequestSchema, PresencePublishRequestSchema, CreateBlobRequestSchema, byokBlobContentPath } from '@byok-sdk/protocol';
|
|
3
|
+
import { AgentEventOrUnknownSchema, PROTOCOL_VERSION, DAEMON_TO_SERVER_TYPES, AGENT_EGRESS_RELIABLE_ACK_CAPABILITY, encodeEnvelope, decodeEnvelope, BYOK_PAIR_PATH, BYOK_CHALLENGE_PATH, BYOK_TOKEN_PATH, BYOK_CAPABILITIES_PATH, BYOK_EVENTS_PATH, BYOK_MESSAGES_PATH, BYOK_BOARD_PATH, BYOK_BOARD_CLAIM_ROUTE, BYOK_BOARD_UNCLAIM_ROUTE, BYOK_BOARD_STATUS_ROUTE, BYOK_BOARD_STREAM_PATH, BYOK_PRESENCE_PATH, BYOK_ACTIVITY_PATH, BYOK_RECORDS_PATH, BYOK_RECORD_ROUTE, BYOK_SKILL_PACKS_PATH, BYOK_SKILL_PACK_FILE_ROUTE, BYOK_BLOBS_PATH, BYOK_BLOB_FINALIZE_ROUTE, BYOK_BLOB_URL_ROUTE, BYOK_BLOB_CONTENT_ROUTE, createEnvelope, AgentContentReadPayloadSchema, AGENT_EGRESS_POLICY_CAPABILITY, TaskOfferForAgentWithEgressPayloadSchema, TaskOfferForAgentPayloadSchema, AGENT_CONTENT_ARTIFACT_READ_CAPABILITY, AGENT_CONTENT_TRANSCRIPT_READ_CAPABILITY, AGENT_CONTENT_WORKSPACE_READ_CAPABILITY, PairRequestSchema, ChallengeRequestSchema, TokenRequestSchema, MessagesSendRequestSchema, PresencePublishRequestSchema, CreateBlobRequestSchema, byokBlobContentPath, AgentEgressAckPayloadSchema, AgentContentReceiptPayloadSchema } from '@byok-sdk/protocol';
|
|
4
4
|
import { z } from 'zod';
|
|
5
5
|
import { Hono } from 'hono';
|
|
6
6
|
|
|
@@ -160,8 +160,8 @@ function createHmacTokenSigner(secret, clock) {
|
|
|
160
160
|
}
|
|
161
161
|
};
|
|
162
162
|
}
|
|
163
|
-
function verifyNonceSignature(
|
|
164
|
-
return
|
|
163
|
+
function verifyNonceSignature(crypto2, devicePublicKey, nonce, signature) {
|
|
164
|
+
return crypto2.verifyEd25519(devicePublicKey, NONCE_SIGNING_DOMAIN + nonce, signature);
|
|
165
165
|
}
|
|
166
166
|
|
|
167
167
|
// src/auth/plane.ts
|
|
@@ -170,13 +170,13 @@ var PAIRING_CODE_LENGTH = 8;
|
|
|
170
170
|
var DEVICE_IDENTITY_PROOF_KEY_ID = "identity";
|
|
171
171
|
var DEVICE_IDENTITY_PROOF_KEY_EPOCH = 0;
|
|
172
172
|
function createAuthPlane(deps) {
|
|
173
|
-
const { stores, crypto, clock, tokenSigner } = deps;
|
|
173
|
+
const { stores, crypto: crypto2, clock, tokenSigner } = deps;
|
|
174
174
|
const ttlSeconds = deps.accessTokenTtlSeconds ?? ACCESS_TOKEN_TTL_SECONDS;
|
|
175
175
|
return {
|
|
176
176
|
async createPairingCode(tenant, input) {
|
|
177
177
|
const expiresAt = new Date(clock.now().getTime() + (input.ttlMs ?? PAIRING_CODE_TTL_MS)).toISOString();
|
|
178
178
|
return stores.pairingCodes.issue(tenant, {
|
|
179
|
-
code:
|
|
179
|
+
code: crypto2.randomPairingCode(PAIRING_CODE_LENGTH),
|
|
180
180
|
productId: input.productId,
|
|
181
181
|
expiresAt
|
|
182
182
|
});
|
|
@@ -186,7 +186,7 @@ function createAuthPlane(deps) {
|
|
|
186
186
|
if (claims === void 0) return void 0;
|
|
187
187
|
return stores.devices.register(claims.tenantId, {
|
|
188
188
|
productId: claims.productId,
|
|
189
|
-
deviceId: `dev_${
|
|
189
|
+
deviceId: `dev_${crypto2.randomUuid()}`,
|
|
190
190
|
deviceName: input.deviceName,
|
|
191
191
|
devicePublicKey: input.devicePublicKey,
|
|
192
192
|
proofKeyId: DEVICE_IDENTITY_PROOF_KEY_ID,
|
|
@@ -208,7 +208,7 @@ function createAuthPlane(deps) {
|
|
|
208
208
|
return stores.nonces.markUsed(device.tenantId, nonce);
|
|
209
209
|
},
|
|
210
210
|
verifySignature(device, nonce, signature) {
|
|
211
|
-
return verifyNonceSignature(
|
|
211
|
+
return verifyNonceSignature(crypto2, device.devicePublicKey, nonce, signature);
|
|
212
212
|
},
|
|
213
213
|
async mintAccessToken(device) {
|
|
214
214
|
const accessToken = await tokenSigner.sign(
|
|
@@ -319,7 +319,17 @@ var CLOUD_ERROR_CODES = {
|
|
|
319
319
|
/** A progress/activity batch exceeded the configured event or byte ceiling. */
|
|
320
320
|
activity_batch_too_large: "activity_batch_too_large",
|
|
321
321
|
/** Host control-plane task lookup is tenant-closed and found no task. */
|
|
322
|
-
task_not_found: "task_not_found"
|
|
322
|
+
task_not_found: "task_not_found",
|
|
323
|
+
/** Durable target-device capability is absent, revoked, or unavailable. */
|
|
324
|
+
agent_capability_missing: "agent_capability_missing",
|
|
325
|
+
/** Inbound Agent identity did not exactly match the offered identity. */
|
|
326
|
+
agent_ref_mismatch: "agent_ref_mismatch",
|
|
327
|
+
/** A strict Agent task id already names a durable attempt and cannot be re-enqueued. */
|
|
328
|
+
agent_task_already_exists: "agent_task_already_exists",
|
|
329
|
+
/** A first-write-wins Agent control record was replayed with a different body. */
|
|
330
|
+
agent_content_request_mismatch: "agent_content_request_mismatch",
|
|
331
|
+
/** A durable mailbox receipt id resolved to an envelope other than its exact acknowledgement. */
|
|
332
|
+
mailbox_receipt_mismatch: "mailbox_receipt_mismatch"
|
|
323
333
|
};
|
|
324
334
|
var ByokCloudError = class extends Error {
|
|
325
335
|
code;
|
|
@@ -527,10 +537,15 @@ function tenantStoresFor(principal, root) {
|
|
|
527
537
|
get: (deviceId) => cloud.devices.get(tenant, deviceId),
|
|
528
538
|
list: () => cloud.devices.list(tenant),
|
|
529
539
|
revoke: (deviceId) => cloud.devices.revoke(tenant, deviceId),
|
|
540
|
+
recordCapabilities: (input) => principal.kind === "device" ? cloud.devices.recordCapabilities(tenant, {
|
|
541
|
+
deviceId: principal.deviceId,
|
|
542
|
+
capabilities: input.capabilities
|
|
543
|
+
}) : Promise.resolve(void 0),
|
|
530
544
|
readiness: () => cloud.devices.readiness(tenant, core.presence)
|
|
531
545
|
},
|
|
532
546
|
tasks: {
|
|
533
547
|
open: (input) => cloud.tasks.open(tenant, input),
|
|
548
|
+
reserveAgentOffer: (input) => cloud.tasks.reserveAgentOffer(tenant, input),
|
|
534
549
|
get: (taskId) => cloud.tasks.get(tenant, taskId),
|
|
535
550
|
getMany: (taskIds) => cloud.tasks.getMany(tenant, taskIds),
|
|
536
551
|
claim: (input) => cloud.tasks.claim(tenant, input),
|
|
@@ -546,6 +561,10 @@ function tenantStoresFor(principal, root) {
|
|
|
546
561
|
record: (input) => cloud.receipts.record(tenant, input),
|
|
547
562
|
get: (key) => cloud.receipts.get(tenant, key)
|
|
548
563
|
},
|
|
564
|
+
egress: {
|
|
565
|
+
record: (input) => cloud.egress.record(tenant, input),
|
|
566
|
+
get: (deviceId, eventId) => cloud.egress.get(tenant, deviceId, eventId)
|
|
567
|
+
},
|
|
549
568
|
blobs: {
|
|
550
569
|
createUpload: (reservation) => cloud.blobs.createUpload(tenant, reservation),
|
|
551
570
|
observeUpload: (blobId, reservation) => cloud.blobs.observeUpload(tenant, blobId, reservation),
|
|
@@ -685,11 +704,16 @@ function blobDownloadContentHandler(deps) {
|
|
|
685
704
|
if (!query.success || !await deps.contentProxy.verifySignedUrl(blobId, "get", query.data.sig, query.data.exp)) {
|
|
686
705
|
return c.json({ error: "invalid or expired signature" }, 401);
|
|
687
706
|
}
|
|
688
|
-
const
|
|
689
|
-
if (
|
|
690
|
-
|
|
707
|
+
const result = await deps.contentProxy.readContent(blobId);
|
|
708
|
+
if (result === void 0) return c.json({ error: "blob not found" }, 404);
|
|
709
|
+
if (!result.ok) return c.json({ error: result.code }, BLOB_READ_ERROR_HTTP_STATUS[result.code]);
|
|
710
|
+
return c.body(new Uint8Array(result.content.data), 200, { "content-type": result.content.contentType });
|
|
691
711
|
};
|
|
692
712
|
}
|
|
713
|
+
var BLOB_READ_ERROR_HTTP_STATUS = {
|
|
714
|
+
blob_upstream_unavailable: 502,
|
|
715
|
+
blob_upstream_stream_interrupted: 502
|
|
716
|
+
};
|
|
693
717
|
function idempotencyKey(c) {
|
|
694
718
|
const value = c.req.header("Idempotency-Key");
|
|
695
719
|
if (value === void 0 || value.length === 0 || value.length > 200) return void 0;
|
|
@@ -759,7 +783,15 @@ function tokenHandler(deps) {
|
|
|
759
783
|
return c.json(response, 200);
|
|
760
784
|
};
|
|
761
785
|
}
|
|
762
|
-
var CLOUD_PROTOCOL_CAPABILITIES = [
|
|
786
|
+
var CLOUD_PROTOCOL_CAPABILITIES = [
|
|
787
|
+
"result-document",
|
|
788
|
+
"agent-home-contract",
|
|
789
|
+
"agent-egress-policy",
|
|
790
|
+
"agent-egress-reliable-ack",
|
|
791
|
+
"agent-content-workspace-read",
|
|
792
|
+
"agent-content-transcript-read",
|
|
793
|
+
"agent-content-artifact-read"
|
|
794
|
+
];
|
|
763
795
|
function sleep(ms) {
|
|
764
796
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
765
797
|
}
|
|
@@ -791,13 +823,15 @@ function eventsHandler(deps) {
|
|
|
791
823
|
if (page.messages.length === 0) break;
|
|
792
824
|
const decoded = page.messages.map((message) => decodeEnvelope(message.body));
|
|
793
825
|
const offeredTaskIds = decoded.flatMap(
|
|
794
|
-
(event) => (event.type === "task.offer" || event.type === "task.offer_with_toolsets") && event.task_id !== void 0 ? [event.task_id] : []
|
|
826
|
+
(event) => (event.type === "task.offer" || event.type === "task.offer_with_toolsets" || event.type === "task.offer_for_agent" || event.type === "task.offer_for_agent_with_egress") && event.task_id !== void 0 ? [event.task_id] : []
|
|
795
827
|
);
|
|
796
828
|
const attemptsByTaskId = Object.fromEntries(
|
|
797
829
|
(await stores.tasks.getMany(offeredTaskIds)).map((attempt2) => [attempt2.taskId, attempt2])
|
|
798
830
|
);
|
|
799
831
|
const events = decoded.filter((event) => {
|
|
800
|
-
if (event.type !== "task.offer" && event.type !== "task.offer_with_toolsets")
|
|
832
|
+
if (event.type !== "task.offer" && event.type !== "task.offer_with_toolsets" && event.type !== "task.offer_for_agent" && event.type !== "task.offer_for_agent_with_egress") {
|
|
833
|
+
return true;
|
|
834
|
+
}
|
|
801
835
|
return event.task_id === void 0 || attemptsByTaskId[event.task_id]?.cancellation === void 0;
|
|
802
836
|
});
|
|
803
837
|
if (events.length === 0 && page.hasMore) {
|
|
@@ -910,13 +944,103 @@ async function projectTerminalToReview(board, taskId) {
|
|
|
910
944
|
function terminalReceiptKey(taskId) {
|
|
911
945
|
return `task:${taskId}:terminal`;
|
|
912
946
|
}
|
|
947
|
+
function sameAgentRef(expected, actual) {
|
|
948
|
+
return actual?.agentId === expected.agentId && actual.profileRevision === expected.profileRevision;
|
|
949
|
+
}
|
|
950
|
+
function sameReliableEgress(expected, actual) {
|
|
951
|
+
return sameAgentRef(expected.agentRef, actual.agentRef) && expected.sessionRef === actual.sessionRef && expected.policyRevision === actual.policyRevision && expected.eventId === actual.eventId && expected.cursor === actual.cursor && expected.contentHash === actual.contentHash && expected.byteCount === actual.byteCount && JSON.stringify(expected.payload) === JSON.stringify(actual.payload);
|
|
952
|
+
}
|
|
953
|
+
function contentReadCapability(surface) {
|
|
954
|
+
switch (surface) {
|
|
955
|
+
case "workspace":
|
|
956
|
+
return AGENT_CONTENT_WORKSPACE_READ_CAPABILITY;
|
|
957
|
+
case "transcript":
|
|
958
|
+
return AGENT_CONTENT_TRANSCRIPT_READ_CAPABILITY;
|
|
959
|
+
case "artifact":
|
|
960
|
+
return AGENT_CONTENT_ARTIFACT_READ_CAPABILITY;
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
function hasCapabilities(capabilities, required) {
|
|
964
|
+
return capabilities !== void 0 && required.every((capability) => capabilities.includes(capability));
|
|
965
|
+
}
|
|
966
|
+
function contentRequestReceiptKey(deviceId, requestId) {
|
|
967
|
+
return `agent-content-request:${deviceId}:${requestId}`;
|
|
968
|
+
}
|
|
969
|
+
function contentReceiptKey(deviceId, requestId) {
|
|
970
|
+
return `agent-content:${deviceId}:${requestId}`;
|
|
971
|
+
}
|
|
972
|
+
function matchesContentReadReceipt(request, receipt) {
|
|
973
|
+
return request.requestId === receipt.requestId && request.surface === receipt.surface && request.actor.kind === receipt.actor.kind && request.actor.id === receipt.actor.id && sameAgentRef(request.agentRef, receipt.agentRef) && request.sessionRef === receipt.sessionRef && request.runtime === receipt.runtime && request.cwd === receipt.cwd && request.policyRevision === receipt.policyRevision && request.target === receipt.target && request.mimeType === receipt.mimeType && request.decodeAs === receipt.decodeAs;
|
|
974
|
+
}
|
|
975
|
+
async function readContentRequest(stores, deviceId, requestId) {
|
|
976
|
+
const stored = await stores.receipts.get(contentRequestReceiptKey(deviceId, requestId));
|
|
977
|
+
if (stored === void 0) return void 0;
|
|
978
|
+
try {
|
|
979
|
+
return AgentContentReadPayloadSchema.parse(JSON.parse(stored.body));
|
|
980
|
+
} catch {
|
|
981
|
+
return void 0;
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
function inboundAgentRef(envelope) {
|
|
985
|
+
switch (envelope.type) {
|
|
986
|
+
case "task.claim":
|
|
987
|
+
case "task.decline":
|
|
988
|
+
case "task.complete":
|
|
989
|
+
case "task.fail":
|
|
990
|
+
case "task.cancelled":
|
|
991
|
+
return envelope.payload.agentRef;
|
|
992
|
+
default:
|
|
993
|
+
return void 0;
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
function agentRefEchoRequired(envelope) {
|
|
997
|
+
return envelope.type === "task.claim" || envelope.type === "task.decline" || envelope.type === "task.complete" || envelope.type === "task.fail" || envelope.type === "task.cancelled";
|
|
998
|
+
}
|
|
913
999
|
async function handleInboundEnvelope(stores, deviceId, envelope, activityBounds = DEFAULT_ACTIVITY_BOUNDS) {
|
|
914
1000
|
if (!await stores.rateLimiter.consume(deviceId)) return "rate_limited";
|
|
1001
|
+
if (envelope.type === "conn.hello") {
|
|
1002
|
+
if (envelope.payload.deviceId !== deviceId) return "rejected";
|
|
1003
|
+
if (!envelope.payload.protocolVersions.includes(PROTOCOL_VERSION)) return "rejected";
|
|
1004
|
+
const device = await stores.devices.get(deviceId);
|
|
1005
|
+
if (device === void 0 || device.revoked || device.productId !== envelope.payload.productId) {
|
|
1006
|
+
return "rejected";
|
|
1007
|
+
}
|
|
1008
|
+
if (await stores.dedup.checkAndRecord(deviceId, envelope.id)) return "duplicate";
|
|
1009
|
+
return await stores.devices.recordCapabilities({ capabilities: envelope.payload.capabilities }) === void 0 ? "rejected" : "accepted";
|
|
1010
|
+
}
|
|
915
1011
|
if (!DAEMON_TO_SERVER_TYPES.includes(envelope.type)) return "rejected";
|
|
1012
|
+
if (envelope.type === "agent.egress.reliable") {
|
|
1013
|
+
const device = await stores.devices.get(deviceId);
|
|
1014
|
+
if (device === void 0 || device.revoked || !hasCapabilities(device.capabilities, [AGENT_EGRESS_POLICY_CAPABILITY, AGENT_EGRESS_RELIABLE_ACK_CAPABILITY])) {
|
|
1015
|
+
return "rejected";
|
|
1016
|
+
}
|
|
1017
|
+
const outcome = await stores.egress.record({
|
|
1018
|
+
deviceId,
|
|
1019
|
+
payload: envelope.payload,
|
|
1020
|
+
receiptId: crypto.randomUUID()
|
|
1021
|
+
});
|
|
1022
|
+
return outcome.created || sameReliableEgress(outcome.record.payload, envelope.payload) ? outcome.created ? "accepted" : "duplicate" : "rejected";
|
|
1023
|
+
}
|
|
1024
|
+
if (envelope.type === "agent.content.receipt") {
|
|
1025
|
+
const device = await stores.devices.get(deviceId);
|
|
1026
|
+
if (device === void 0 || device.revoked || envelope.payload.eventId !== envelope.payload.requestId || !hasCapabilities(device.capabilities, [contentReadCapability(envelope.payload.surface), AGENT_EGRESS_RELIABLE_ACK_CAPABILITY])) {
|
|
1027
|
+
return "rejected";
|
|
1028
|
+
}
|
|
1029
|
+
const request = await readContentRequest(stores, deviceId, envelope.payload.requestId);
|
|
1030
|
+
if (request === void 0 || !matchesContentReadReceipt(request, envelope.payload)) return "rejected";
|
|
1031
|
+
const key = contentReceiptKey(deviceId, envelope.payload.requestId);
|
|
1032
|
+
const body = JSON.stringify(envelope.payload);
|
|
1033
|
+
const receipt = await stores.receipts.record({ key, body });
|
|
1034
|
+
return receipt.created ? "accepted" : receipt.receipt.body === body ? "duplicate" : "rejected";
|
|
1035
|
+
}
|
|
916
1036
|
const taskId = envelope.task_id;
|
|
917
1037
|
if (taskId === void 0) return "rejected";
|
|
918
1038
|
const attempt = await stores.tasks.get(taskId);
|
|
1039
|
+
if (attempt?.agentRef !== void 0 && attempt.deviceId !== deviceId) return "rejected";
|
|
919
1040
|
if (attempt?.ownerDeviceId !== void 0 && attempt.ownerDeviceId !== deviceId) return "rejected";
|
|
1041
|
+
if (attempt?.agentRef !== void 0 && agentRefEchoRequired(envelope) && !sameAgentRef(attempt.agentRef, inboundAgentRef(envelope))) {
|
|
1042
|
+
return "rejected";
|
|
1043
|
+
}
|
|
920
1044
|
if (envelope.type === "task.progress" && envelope.payload.events.length > 0) {
|
|
921
1045
|
try {
|
|
922
1046
|
validateActivityBatch(
|
|
@@ -946,19 +1070,27 @@ async function handleInboundEnvelope(stores, deviceId, envelope, activityBounds
|
|
|
946
1070
|
}
|
|
947
1071
|
}
|
|
948
1072
|
if (await stores.dedup.checkAndRecord(deviceId, envelope.id)) return "duplicate";
|
|
949
|
-
await applyLifecycle(stores, deviceId, taskId, envelope, activityBounds);
|
|
1073
|
+
await applyLifecycle(stores, deviceId, taskId, envelope, activityBounds, attempt?.agentRef);
|
|
950
1074
|
return "accepted";
|
|
951
1075
|
}
|
|
952
|
-
async function applyLifecycle(stores, deviceId, taskId, envelope, activityBounds) {
|
|
1076
|
+
async function applyLifecycle(stores, deviceId, taskId, envelope, activityBounds, persistedAgentRef) {
|
|
953
1077
|
switch (envelope.type) {
|
|
954
1078
|
case "task.claim":
|
|
955
1079
|
await stores.tasks.claim({ taskId, deviceId });
|
|
956
1080
|
return;
|
|
957
1081
|
case "task.started":
|
|
958
|
-
await stores.tasks.recordStatus({
|
|
1082
|
+
await stores.tasks.recordStatus({
|
|
1083
|
+
taskId,
|
|
1084
|
+
status: "running",
|
|
1085
|
+
...persistedAgentRef === void 0 ? {} : { agentRef: persistedAgentRef }
|
|
1086
|
+
});
|
|
959
1087
|
return;
|
|
960
1088
|
case "task.decline":
|
|
961
|
-
await stores.tasks.recordStatus({
|
|
1089
|
+
await stores.tasks.recordStatus({
|
|
1090
|
+
taskId,
|
|
1091
|
+
status: "failed",
|
|
1092
|
+
...persistedAgentRef === void 0 ? {} : { agentRef: persistedAgentRef }
|
|
1093
|
+
});
|
|
962
1094
|
return;
|
|
963
1095
|
case "task.progress":
|
|
964
1096
|
if (envelope.payload.events.length > 0) {
|
|
@@ -1030,12 +1162,22 @@ async function recordTerminal(stores, taskId, envelope, status) {
|
|
|
1030
1162
|
});
|
|
1031
1163
|
if (attempt?.cancellation !== void 0) {
|
|
1032
1164
|
if (status === "cancelled") {
|
|
1033
|
-
await stores.tasks.recordStatus({
|
|
1165
|
+
await stores.tasks.recordStatus({
|
|
1166
|
+
taskId,
|
|
1167
|
+
status: "cancelled",
|
|
1168
|
+
...attempt.agentRef === void 0 ? {} : { agentRef: attempt.agentRef }
|
|
1169
|
+
});
|
|
1034
1170
|
}
|
|
1035
1171
|
return;
|
|
1036
1172
|
}
|
|
1037
1173
|
if (!created) return;
|
|
1038
|
-
const
|
|
1174
|
+
const cause = envelope.type === "task.fail" || envelope.type === "task.cancelled" ? envelope.payload.reason : void 0;
|
|
1175
|
+
const recordedAttempt = await stores.tasks.recordStatus({
|
|
1176
|
+
taskId,
|
|
1177
|
+
status,
|
|
1178
|
+
...attempt?.agentRef === void 0 ? {} : { agentRef: attempt.agentRef },
|
|
1179
|
+
...cause === void 0 ? {} : { terminalCause: cause }
|
|
1180
|
+
});
|
|
1039
1181
|
if (recordedAttempt?.status !== status || recordedAttempt.cancellation !== void 0) return;
|
|
1040
1182
|
await projectTerminalToReview(stores.board, taskId);
|
|
1041
1183
|
}
|
|
@@ -1058,6 +1200,16 @@ function messagesHandler(deps) {
|
|
|
1058
1200
|
deps.activityBounds
|
|
1059
1201
|
);
|
|
1060
1202
|
if (outcome === "rate_limited") return c.json({ error: "rate limit exceeded" }, 429);
|
|
1203
|
+
if (envelope.type === "agent.egress.reliable" && (outcome === "accepted" || outcome === "duplicate")) {
|
|
1204
|
+
const record = await stores.egress.get(device.deviceId, envelope.payload.eventId);
|
|
1205
|
+
if (record === void 0) {
|
|
1206
|
+
throw new Error(`Accepted reliable egress ${envelope.payload.eventId} has no durable receipt record.`);
|
|
1207
|
+
}
|
|
1208
|
+
await deps.appendReliableEgressAck(stores, record);
|
|
1209
|
+
}
|
|
1210
|
+
if (envelope.type === "agent.content.receipt" && (outcome === "accepted" || outcome === "duplicate")) {
|
|
1211
|
+
await deps.appendContentReceiptAck(stores, device.deviceId, envelope.payload);
|
|
1212
|
+
}
|
|
1061
1213
|
if (outcome === "rejected") rejected += 1;
|
|
1062
1214
|
else accepted += 1;
|
|
1063
1215
|
}
|
|
@@ -1825,6 +1977,7 @@ function projectTerminalResult(taskId, receipt) {
|
|
|
1825
1977
|
return {
|
|
1826
1978
|
taskId,
|
|
1827
1979
|
state: "complete",
|
|
1980
|
+
...envelope.payload.agentRef === void 0 ? {} : { agentRef: envelope.payload.agentRef },
|
|
1828
1981
|
summary: envelope.payload.summary,
|
|
1829
1982
|
sessionRef: envelope.payload.sessionRef,
|
|
1830
1983
|
...envelope.payload.artifactRefs !== void 0 ? { artifactRefs: envelope.payload.artifactRefs } : {},
|
|
@@ -1836,7 +1989,9 @@ function projectTerminalResult(taskId, receipt) {
|
|
|
1836
1989
|
return {
|
|
1837
1990
|
taskId,
|
|
1838
1991
|
state: "failed",
|
|
1992
|
+
...envelope.payload.agentRef === void 0 ? {} : { agentRef: envelope.payload.agentRef },
|
|
1839
1993
|
reason: envelope.payload.reason,
|
|
1994
|
+
terminalCause: envelope.payload.reason,
|
|
1840
1995
|
...envelope.payload.retryable !== void 0 ? { retryable: envelope.payload.retryable } : {},
|
|
1841
1996
|
...envelope.payload.usage !== void 0 ? { usage: envelope.payload.usage } : {},
|
|
1842
1997
|
recordedAt: receipt.recordedAt
|
|
@@ -1845,7 +2000,9 @@ function projectTerminalResult(taskId, receipt) {
|
|
|
1845
2000
|
return {
|
|
1846
2001
|
taskId,
|
|
1847
2002
|
state: "cancelled",
|
|
2003
|
+
...envelope.payload.agentRef === void 0 ? {} : { agentRef: envelope.payload.agentRef },
|
|
1848
2004
|
...envelope.payload.reason !== void 0 ? { reason: envelope.payload.reason } : {},
|
|
2005
|
+
...envelope.payload.reason === void 0 ? {} : { terminalCause: envelope.payload.reason },
|
|
1849
2006
|
...envelope.payload.usage !== void 0 ? { usage: envelope.payload.usage } : {},
|
|
1850
2007
|
recordedAt: receipt.recordedAt
|
|
1851
2008
|
};
|
|
@@ -1862,6 +2019,10 @@ var DEFAULT_MAX_BLOB_SIZE_BYTES = 100 * 1024 * 1024;
|
|
|
1862
2019
|
var DEFAULT_LONG_POLL_HOLD_MS = 5e4;
|
|
1863
2020
|
var DEFAULT_LONG_POLL_INTERVAL_MS = 250;
|
|
1864
2021
|
var DEFAULT_EVENTS_PAGE_LIMIT = 50;
|
|
2022
|
+
var AGENT_HOME_CONTRACT_CAPABILITY = "agent-home-contract";
|
|
2023
|
+
function sameAgentRef2(expected, actual) {
|
|
2024
|
+
return actual?.agentId === expected.agentId && actual.profileRevision === expected.profileRevision;
|
|
2025
|
+
}
|
|
1865
2026
|
function createByokCloud(options) {
|
|
1866
2027
|
const declaration = parseDeclaration(options.capabilities);
|
|
1867
2028
|
assertNoOverDeclaration(
|
|
@@ -1911,7 +2072,12 @@ function createByokCloud(options) {
|
|
|
1911
2072
|
if (declares(declaration, CLOUD_CAPABILITIES.messagesBatch)) {
|
|
1912
2073
|
registry.register(
|
|
1913
2074
|
{ method: "POST", path: BYOK_MESSAGES_PATH, class: "device" },
|
|
1914
|
-
messagesHandler({
|
|
2075
|
+
messagesHandler({
|
|
2076
|
+
...deviceRouteDeps,
|
|
2077
|
+
activityBounds,
|
|
2078
|
+
appendReliableEgressAck: enqueueReliableEgressAck,
|
|
2079
|
+
appendContentReceiptAck: enqueueContentReceiptAck
|
|
2080
|
+
})
|
|
1915
2081
|
);
|
|
1916
2082
|
}
|
|
1917
2083
|
if (declares(declaration, CLOUD_CAPABILITIES.boardCoordination)) {
|
|
@@ -2029,16 +2195,98 @@ function createByokCloud(options) {
|
|
|
2029
2195
|
function controlPlane(tenant) {
|
|
2030
2196
|
return { kind: "control-plane", tenantId: tenant, operatorId };
|
|
2031
2197
|
}
|
|
2032
|
-
async function enqueueTaskEnvelope(tenant, deviceId, requestedTaskId, buildEnvelope) {
|
|
2198
|
+
async function enqueueTaskEnvelope(tenant, deviceId, requestedTaskId, agentRef, buildEnvelope) {
|
|
2033
2199
|
const stores = tenantStoresFor(controlPlane(tenant), root);
|
|
2034
2200
|
const taskId = requestedTaskId ?? `task_${options.crypto.randomUuid()}`;
|
|
2035
2201
|
const messageId = options.crypto.randomUuid();
|
|
2202
|
+
const reservation = agentRef === void 0 ? void 0 : await stores.tasks.reserveAgentOffer({ taskId, deviceId, agentRef });
|
|
2203
|
+
const openedBeforeAppend = reservation?.attempt;
|
|
2204
|
+
if (agentRef !== void 0 && (openedBeforeAppend === void 0 || openedBeforeAppend.deviceId !== deviceId || openedBeforeAppend.agentRef === void 0 || !sameAgentRef2(agentRef, openedBeforeAppend.agentRef))) {
|
|
2205
|
+
throw new ByokCloudError(
|
|
2206
|
+
"agent_ref_mismatch",
|
|
2207
|
+
`Task ${taskId} already has a different durable Agent identity or target device.`
|
|
2208
|
+
);
|
|
2209
|
+
}
|
|
2210
|
+
if (reservation !== void 0 && !reservation.created) {
|
|
2211
|
+
throw new ByokCloudError(
|
|
2212
|
+
"agent_task_already_exists",
|
|
2213
|
+
`Task ${taskId} already has a durable Agent attempt and cannot be enqueued again.`
|
|
2214
|
+
);
|
|
2215
|
+
}
|
|
2216
|
+
let message;
|
|
2217
|
+
try {
|
|
2218
|
+
message = await stores.mailbox.append({
|
|
2219
|
+
deviceId,
|
|
2220
|
+
messageId,
|
|
2221
|
+
materialize: async (seq) => {
|
|
2222
|
+
const envelope2 = buildEnvelope(taskId, seq, messageId);
|
|
2223
|
+
const body = encodeEnvelope(envelope2);
|
|
2224
|
+
const bytes = new TextEncoder().encode(body);
|
|
2225
|
+
return {
|
|
2226
|
+
body,
|
|
2227
|
+
bodyHash: contentHash(await options.crypto.sha256(bytes)),
|
|
2228
|
+
byteSize: BigInt(bytes.length)
|
|
2229
|
+
};
|
|
2230
|
+
}
|
|
2231
|
+
});
|
|
2232
|
+
} catch (error) {
|
|
2233
|
+
if (openedBeforeAppend !== void 0) {
|
|
2234
|
+
try {
|
|
2235
|
+
await stores.tasks.recordStatus({
|
|
2236
|
+
taskId,
|
|
2237
|
+
status: "failed",
|
|
2238
|
+
agentRef,
|
|
2239
|
+
terminalCause: "mailbox append failed before Agent offer delivery"
|
|
2240
|
+
});
|
|
2241
|
+
} catch (cleanupError) {
|
|
2242
|
+
throw new AggregateError(
|
|
2243
|
+
[error, cleanupError],
|
|
2244
|
+
`Agent task ${taskId} could not be delivered or durably closed`
|
|
2245
|
+
);
|
|
2246
|
+
}
|
|
2247
|
+
}
|
|
2248
|
+
throw error;
|
|
2249
|
+
}
|
|
2250
|
+
const envelope = decodeEnvelope(message.body);
|
|
2251
|
+
if (envelope.seq !== message.seq) {
|
|
2252
|
+
throw new ByokCloudError(
|
|
2253
|
+
"mailbox_seq_mismatch",
|
|
2254
|
+
`Mailbox stored offer seq ${String(envelope.seq)} at row ${message.seq}; the daemon's redelivery cursor would be wrong.`
|
|
2255
|
+
);
|
|
2256
|
+
}
|
|
2257
|
+
const attempt = openedBeforeAppend ?? await stores.tasks.open({
|
|
2258
|
+
taskId,
|
|
2259
|
+
deviceId
|
|
2260
|
+
});
|
|
2261
|
+
return { taskId, seq: message.seq, envelope, attempt };
|
|
2262
|
+
}
|
|
2263
|
+
async function assertAgentCapabilities(tenant, deviceId, required) {
|
|
2264
|
+
const device = await options.cloud.devices.get(tenant, deviceId);
|
|
2265
|
+
if (device === void 0 || device.revoked || !device.capabilities || !required.every((capability) => device.capabilities.includes(capability))) {
|
|
2266
|
+
const missing = required.filter((capability) => !device?.capabilities?.includes(capability));
|
|
2267
|
+
throw new ByokCloudError(
|
|
2268
|
+
"agent_capability_missing",
|
|
2269
|
+
`Device ${deviceId} lacks durable Agent capabilities (${missing.join(", ")}); refusing before mailbox append.`
|
|
2270
|
+
);
|
|
2271
|
+
}
|
|
2272
|
+
}
|
|
2273
|
+
function contentReadCapability2(surface) {
|
|
2274
|
+
switch (surface) {
|
|
2275
|
+
case "workspace":
|
|
2276
|
+
return AGENT_CONTENT_WORKSPACE_READ_CAPABILITY;
|
|
2277
|
+
case "transcript":
|
|
2278
|
+
return AGENT_CONTENT_TRANSCRIPT_READ_CAPABILITY;
|
|
2279
|
+
case "artifact":
|
|
2280
|
+
return AGENT_CONTENT_ARTIFACT_READ_CAPABILITY;
|
|
2281
|
+
}
|
|
2282
|
+
}
|
|
2283
|
+
async function enqueueAgentControlEnvelope(tenant, deviceId, messageId, buildEnvelope) {
|
|
2284
|
+
const stores = tenantStoresFor(controlPlane(tenant), root);
|
|
2036
2285
|
const message = await stores.mailbox.append({
|
|
2037
2286
|
deviceId,
|
|
2038
2287
|
messageId,
|
|
2039
2288
|
materialize: async (seq) => {
|
|
2040
|
-
const
|
|
2041
|
-
const body = encodeEnvelope(envelope2);
|
|
2289
|
+
const body = encodeEnvelope(buildEnvelope(seq));
|
|
2042
2290
|
const bytes = new TextEncoder().encode(body);
|
|
2043
2291
|
return {
|
|
2044
2292
|
body,
|
|
@@ -2051,11 +2299,77 @@ function createByokCloud(options) {
|
|
|
2051
2299
|
if (envelope.seq !== message.seq) {
|
|
2052
2300
|
throw new ByokCloudError(
|
|
2053
2301
|
"mailbox_seq_mismatch",
|
|
2054
|
-
`Mailbox stored
|
|
2302
|
+
`Mailbox stored Agent control seq ${String(envelope.seq)} at row ${message.seq}.`
|
|
2303
|
+
);
|
|
2304
|
+
}
|
|
2305
|
+
return { seq: message.seq, envelope };
|
|
2306
|
+
}
|
|
2307
|
+
async function enqueueReliableEgressAck(stores, record) {
|
|
2308
|
+
const payload = AgentEgressAckPayloadSchema.parse({
|
|
2309
|
+
agentRef: record.payload.agentRef,
|
|
2310
|
+
sessionRef: record.payload.sessionRef,
|
|
2311
|
+
policyRevision: record.payload.policyRevision,
|
|
2312
|
+
eventId: record.payload.eventId,
|
|
2313
|
+
cursor: record.payload.cursor,
|
|
2314
|
+
receiptId: record.receiptId
|
|
2315
|
+
});
|
|
2316
|
+
const message = await stores.mailbox.append({
|
|
2317
|
+
deviceId: record.deviceId,
|
|
2318
|
+
messageId: record.receiptId,
|
|
2319
|
+
materialize: async (seq) => {
|
|
2320
|
+
const body = encodeEnvelope(createEnvelope("agent.egress.ack", payload, { id: record.receiptId, seq }));
|
|
2321
|
+
const bytes = new TextEncoder().encode(body);
|
|
2322
|
+
return {
|
|
2323
|
+
body,
|
|
2324
|
+
bodyHash: contentHash(await options.crypto.sha256(bytes)),
|
|
2325
|
+
byteSize: BigInt(bytes.length)
|
|
2326
|
+
};
|
|
2327
|
+
}
|
|
2328
|
+
});
|
|
2329
|
+
const decoded = decodeEnvelope(message.body);
|
|
2330
|
+
if (decoded.type !== "agent.egress.ack" || decoded.seq !== message.seq || JSON.stringify(decoded.payload) !== JSON.stringify(payload)) {
|
|
2331
|
+
throw new ByokCloudError(
|
|
2332
|
+
"mailbox_receipt_mismatch",
|
|
2333
|
+
`Mailbox receipt ${record.receiptId} does not exactly acknowledge Agent egress ${record.payload.eventId}.`
|
|
2334
|
+
);
|
|
2335
|
+
}
|
|
2336
|
+
}
|
|
2337
|
+
async function enqueueContentReceiptAck(stores, deviceId, receipt) {
|
|
2338
|
+
const exactReceipt = AgentContentReceiptPayloadSchema.parse(receipt);
|
|
2339
|
+
if (exactReceipt.eventId !== exactReceipt.requestId) {
|
|
2340
|
+
throw new ByokCloudError("mailbox_receipt_mismatch", "Content receipt eventId must equal requestId.");
|
|
2341
|
+
}
|
|
2342
|
+
const payload = AgentEgressAckPayloadSchema.parse({
|
|
2343
|
+
agentRef: exactReceipt.agentRef,
|
|
2344
|
+
sessionRef: exactReceipt.sessionRef,
|
|
2345
|
+
policyRevision: exactReceipt.policyRevision,
|
|
2346
|
+
eventId: exactReceipt.eventId,
|
|
2347
|
+
cursor: exactReceipt.cursor,
|
|
2348
|
+
receiptId: exactReceipt.requestId
|
|
2349
|
+
});
|
|
2350
|
+
const message = await stores.mailbox.append({
|
|
2351
|
+
deviceId,
|
|
2352
|
+
// The request itself already occupies its bare request id in this
|
|
2353
|
+
// mailbox. A namespaced producer key keeps the ack idempotent without
|
|
2354
|
+
// returning that control envelope on duplicate receipt delivery.
|
|
2355
|
+
messageId: `agent-content-ack:${exactReceipt.requestId}`,
|
|
2356
|
+
materialize: async (seq) => {
|
|
2357
|
+
const body = encodeEnvelope(createEnvelope("agent.egress.ack", payload, { id: exactReceipt.requestId, seq }));
|
|
2358
|
+
const bytes = new TextEncoder().encode(body);
|
|
2359
|
+
return {
|
|
2360
|
+
body,
|
|
2361
|
+
bodyHash: contentHash(await options.crypto.sha256(bytes)),
|
|
2362
|
+
byteSize: BigInt(bytes.length)
|
|
2363
|
+
};
|
|
2364
|
+
}
|
|
2365
|
+
});
|
|
2366
|
+
const decoded = decodeEnvelope(message.body);
|
|
2367
|
+
if (decoded.type !== "agent.egress.ack" || decoded.seq !== message.seq || JSON.stringify(decoded.payload) !== JSON.stringify(payload)) {
|
|
2368
|
+
throw new ByokCloudError(
|
|
2369
|
+
"mailbox_receipt_mismatch",
|
|
2370
|
+
`Mailbox content receipt ${exactReceipt.requestId} does not exactly acknowledge its durable content fact.`
|
|
2055
2371
|
);
|
|
2056
2372
|
}
|
|
2057
|
-
const attempt = await stores.tasks.open({ taskId, deviceId });
|
|
2058
|
-
return { taskId, seq: message.seq, envelope, attempt };
|
|
2059
2373
|
}
|
|
2060
2374
|
return {
|
|
2061
2375
|
fetch: registry.fetch,
|
|
@@ -2070,6 +2384,7 @@ function createByokCloud(options) {
|
|
|
2070
2384
|
tenant,
|
|
2071
2385
|
deviceId,
|
|
2072
2386
|
input.taskId,
|
|
2387
|
+
void 0,
|
|
2073
2388
|
(taskId, seq, messageId) => createEnvelope("task.offer", input.payload, { id: messageId, taskId, seq })
|
|
2074
2389
|
);
|
|
2075
2390
|
},
|
|
@@ -2078,9 +2393,69 @@ function createByokCloud(options) {
|
|
|
2078
2393
|
tenant,
|
|
2079
2394
|
deviceId,
|
|
2080
2395
|
input.taskId,
|
|
2396
|
+
void 0,
|
|
2081
2397
|
(taskId, seq, messageId) => createEnvelope("task.offer_with_toolsets", input.payload, { id: messageId, taskId, seq })
|
|
2082
2398
|
);
|
|
2083
2399
|
},
|
|
2400
|
+
async enqueueAgentOffer(tenant, deviceId, input) {
|
|
2401
|
+
await assertAgentCapabilities(tenant, deviceId, [AGENT_HOME_CONTRACT_CAPABILITY]);
|
|
2402
|
+
const payload = TaskOfferForAgentPayloadSchema.parse(input.payload);
|
|
2403
|
+
return enqueueTaskEnvelope(
|
|
2404
|
+
tenant,
|
|
2405
|
+
deviceId,
|
|
2406
|
+
input.taskId,
|
|
2407
|
+
payload.agentRef,
|
|
2408
|
+
(taskId, seq, messageId) => createEnvelope("task.offer_for_agent", payload, { id: messageId, taskId, seq })
|
|
2409
|
+
);
|
|
2410
|
+
},
|
|
2411
|
+
async enqueueAgentEgressOffer(tenant, deviceId, input) {
|
|
2412
|
+
await assertAgentCapabilities(tenant, deviceId, [
|
|
2413
|
+
AGENT_HOME_CONTRACT_CAPABILITY,
|
|
2414
|
+
AGENT_EGRESS_POLICY_CAPABILITY,
|
|
2415
|
+
AGENT_EGRESS_RELIABLE_ACK_CAPABILITY
|
|
2416
|
+
]);
|
|
2417
|
+
const payload = TaskOfferForAgentWithEgressPayloadSchema.parse(input.payload);
|
|
2418
|
+
return enqueueTaskEnvelope(
|
|
2419
|
+
tenant,
|
|
2420
|
+
deviceId,
|
|
2421
|
+
input.taskId,
|
|
2422
|
+
payload.agentRef,
|
|
2423
|
+
(taskId, seq, messageId) => createEnvelope("task.offer_for_agent_with_egress", payload, { id: messageId, taskId, seq })
|
|
2424
|
+
);
|
|
2425
|
+
},
|
|
2426
|
+
async enqueueAgentContentRead(tenant, deviceId, input) {
|
|
2427
|
+
const payload = AgentContentReadPayloadSchema.parse(input.payload);
|
|
2428
|
+
await assertAgentCapabilities(tenant, deviceId, [
|
|
2429
|
+
AGENT_HOME_CONTRACT_CAPABILITY,
|
|
2430
|
+
AGENT_EGRESS_POLICY_CAPABILITY,
|
|
2431
|
+
AGENT_EGRESS_RELIABLE_ACK_CAPABILITY,
|
|
2432
|
+
contentReadCapability2(payload.surface)
|
|
2433
|
+
]);
|
|
2434
|
+
const stores = tenantStoresFor(controlPlane(tenant), root);
|
|
2435
|
+
const persisted = await stores.receipts.record({
|
|
2436
|
+
key: `agent-content-request:${deviceId}:${payload.requestId}`,
|
|
2437
|
+
body: JSON.stringify(payload)
|
|
2438
|
+
});
|
|
2439
|
+
if (!persisted.created && persisted.receipt.body !== JSON.stringify(payload)) {
|
|
2440
|
+
throw new ByokCloudError(
|
|
2441
|
+
"agent_content_request_mismatch",
|
|
2442
|
+
`Request ${payload.requestId} already exists with a different immutable content-read body.`
|
|
2443
|
+
);
|
|
2444
|
+
}
|
|
2445
|
+
const control = await enqueueAgentControlEnvelope(
|
|
2446
|
+
tenant,
|
|
2447
|
+
deviceId,
|
|
2448
|
+
payload.requestId,
|
|
2449
|
+
(seq) => createEnvelope("agent.content.read", payload, { id: payload.requestId, seq })
|
|
2450
|
+
);
|
|
2451
|
+
if (control.envelope.type !== "agent.content.read" || JSON.stringify(control.envelope.payload) !== JSON.stringify(payload)) {
|
|
2452
|
+
throw new ByokCloudError(
|
|
2453
|
+
"agent_content_request_mismatch",
|
|
2454
|
+
`Request ${payload.requestId} already exists with a different immutable content-read body.`
|
|
2455
|
+
);
|
|
2456
|
+
}
|
|
2457
|
+
return control;
|
|
2458
|
+
},
|
|
2084
2459
|
async cancelTask(tenant, taskId, reason) {
|
|
2085
2460
|
const stores = tenantStoresFor(controlPlane(tenant), root);
|
|
2086
2461
|
const proposedMessageId = options.crypto.randomUuid();
|
|
@@ -2123,6 +2498,9 @@ function createByokCloud(options) {
|
|
|
2123
2498
|
readTerminalReceipt(tenant, taskId) {
|
|
2124
2499
|
return tenantStoresFor(controlPlane(tenant), root).receipts.get(terminalReceiptKey(taskId));
|
|
2125
2500
|
},
|
|
2501
|
+
readAgentEgress(tenant, deviceId, eventId) {
|
|
2502
|
+
return tenantStoresFor(controlPlane(tenant), root).egress.get(deviceId, eventId);
|
|
2503
|
+
},
|
|
2126
2504
|
async readTaskResult(tenant, taskId) {
|
|
2127
2505
|
const stores = tenantStoresFor(controlPlane(tenant), root);
|
|
2128
2506
|
const attempt = await stores.tasks.get(taskId);
|
|
@@ -2130,7 +2508,9 @@ function createByokCloud(options) {
|
|
|
2130
2508
|
return {
|
|
2131
2509
|
taskId,
|
|
2132
2510
|
state: "cancelled",
|
|
2511
|
+
...attempt.agentRef === void 0 ? {} : { agentRef: attempt.agentRef },
|
|
2133
2512
|
...attempt.cancellation.reason === void 0 ? {} : { reason: attempt.cancellation.reason },
|
|
2513
|
+
...attempt.cancellation.reason === void 0 ? {} : { terminalCause: attempt.cancellation.reason },
|
|
2134
2514
|
recordedAt: attempt.cancellation.requestedAt
|
|
2135
2515
|
};
|
|
2136
2516
|
}
|
|
@@ -2235,9 +2615,9 @@ var InMemoryBlobRegistry = class {
|
|
|
2235
2615
|
crypto;
|
|
2236
2616
|
secret;
|
|
2237
2617
|
urlTtlMs;
|
|
2238
|
-
constructor(clock,
|
|
2618
|
+
constructor(clock, crypto2, options) {
|
|
2239
2619
|
this.clock = clock;
|
|
2240
|
-
this.crypto =
|
|
2620
|
+
this.crypto = crypto2;
|
|
2241
2621
|
this.secret = globalThis.crypto.getRandomValues(new Uint8Array(SIGNING_SECRET_BYTES));
|
|
2242
2622
|
this.urlTtlMs = options.urlTtlMs ?? BLOB_URL_TTL_MS;
|
|
2243
2623
|
}
|
|
@@ -2342,14 +2722,20 @@ var InMemoryBlobContentProxy = class {
|
|
|
2342
2722
|
record.uploaded = true;
|
|
2343
2723
|
return { ok: true };
|
|
2344
2724
|
}
|
|
2725
|
+
/**
|
|
2726
|
+
* Never returns `{ok:false}`: this composition holds the bytes in the same
|
|
2727
|
+
* process, so there is no upstream to be unreachable and no stream to be
|
|
2728
|
+
* interrupted. Both `BlobReadErrorCode`s are structurally unreachable here
|
|
2729
|
+
* — a proxy that fetches from object storage is where they become live.
|
|
2730
|
+
*/
|
|
2345
2731
|
async readContent(blobId) {
|
|
2346
2732
|
const record = this.#registry.blobs.get(blobId);
|
|
2347
2733
|
if (record === void 0 || !record.uploaded || record.data === void 0) return void 0;
|
|
2348
|
-
return { data: record.data, contentType: record.contentType };
|
|
2734
|
+
return { ok: true, content: { data: record.data, contentType: record.contentType } };
|
|
2349
2735
|
}
|
|
2350
2736
|
};
|
|
2351
|
-
function createInMemoryBlobs(clock,
|
|
2352
|
-
const registry = new InMemoryBlobRegistry(clock,
|
|
2737
|
+
function createInMemoryBlobs(clock, crypto2, objects, options = {}) {
|
|
2738
|
+
const registry = new InMemoryBlobRegistry(clock, crypto2, options);
|
|
2353
2739
|
return {
|
|
2354
2740
|
blobs: new InMemoryCloudBlobStore(registry, objects),
|
|
2355
2741
|
contentProxy: new InMemoryBlobContentProxy(registry)
|
|
@@ -2392,6 +2778,17 @@ var InMemoryDeviceDirectory = class {
|
|
|
2392
2778
|
if (record === void 0) return;
|
|
2393
2779
|
this.#byTenant.set(key, { ...record, revoked: true });
|
|
2394
2780
|
}
|
|
2781
|
+
async recordCapabilities(tenant, input) {
|
|
2782
|
+
const key = tenantKey(tenant, input.deviceId);
|
|
2783
|
+
const record = this.#byTenant.get(key);
|
|
2784
|
+
if (record === void 0 || record.revoked) return void 0;
|
|
2785
|
+
const updated = {
|
|
2786
|
+
...record,
|
|
2787
|
+
capabilities: Object.freeze([...input.capabilities])
|
|
2788
|
+
};
|
|
2789
|
+
this.#byTenant.set(key, updated);
|
|
2790
|
+
return updated;
|
|
2791
|
+
}
|
|
2395
2792
|
async list(tenant) {
|
|
2396
2793
|
const prefix = tenantKey(tenant, "");
|
|
2397
2794
|
return [...this.#byTenant.entries()].filter(([key]) => key.startsWith(prefix)).map(([, record]) => record);
|
|
@@ -2477,9 +2874,9 @@ var InMemoryNonceStore = class {
|
|
|
2477
2874
|
#clock;
|
|
2478
2875
|
#crypto;
|
|
2479
2876
|
#ttlMs;
|
|
2480
|
-
constructor(clock,
|
|
2877
|
+
constructor(clock, crypto2, ttlMs = NONCE_TTL_MS) {
|
|
2481
2878
|
this.#clock = clock;
|
|
2482
|
-
this.#crypto =
|
|
2879
|
+
this.#crypto = crypto2;
|
|
2483
2880
|
this.#ttlMs = ttlMs;
|
|
2484
2881
|
}
|
|
2485
2882
|
/** Number of records currently held (post-sweep). Test-facing only. */
|
|
@@ -2583,6 +2980,9 @@ var InMemoryProofRequestReceiptStore = class {
|
|
|
2583
2980
|
return this.#receipts.get(tenantKey(tenant, deviceId, requestId));
|
|
2584
2981
|
}
|
|
2585
2982
|
};
|
|
2983
|
+
function sameAgentRef3(left, right) {
|
|
2984
|
+
return left?.agentId === right?.agentId && left?.profileRevision === right?.profileRevision;
|
|
2985
|
+
}
|
|
2586
2986
|
var InMemoryTaskAttemptStore = class {
|
|
2587
2987
|
#state;
|
|
2588
2988
|
constructor(clock, state = new InMemoryTaskAttemptState(clock)) {
|
|
@@ -2597,6 +2997,7 @@ var InMemoryTaskAttemptStore = class {
|
|
|
2597
2997
|
tenantId: tenant,
|
|
2598
2998
|
taskId: input.taskId,
|
|
2599
2999
|
deviceId: input.deviceId,
|
|
3000
|
+
...input.agentRef === void 0 ? {} : { agentRef: { ...input.agentRef } },
|
|
2600
3001
|
status: "offered",
|
|
2601
3002
|
updatedAt: this.#now()
|
|
2602
3003
|
};
|
|
@@ -2604,6 +3005,23 @@ var InMemoryTaskAttemptStore = class {
|
|
|
2604
3005
|
return attempt;
|
|
2605
3006
|
});
|
|
2606
3007
|
}
|
|
3008
|
+
async reserveAgentOffer(tenant, input) {
|
|
3009
|
+
const key = tenantKey(tenant, input.taskId);
|
|
3010
|
+
return this.#state.mutate(key, () => {
|
|
3011
|
+
const existing = this.#state.attempts.get(key);
|
|
3012
|
+
if (existing !== void 0) return { attempt: existing, created: false };
|
|
3013
|
+
const attempt = {
|
|
3014
|
+
tenantId: tenant,
|
|
3015
|
+
taskId: input.taskId,
|
|
3016
|
+
deviceId: input.deviceId,
|
|
3017
|
+
agentRef: { ...input.agentRef },
|
|
3018
|
+
status: "offered",
|
|
3019
|
+
updatedAt: this.#now()
|
|
3020
|
+
};
|
|
3021
|
+
this.#state.attempts.set(key, attempt);
|
|
3022
|
+
return { attempt, created: true };
|
|
3023
|
+
});
|
|
3024
|
+
}
|
|
2607
3025
|
async get(tenant, taskId) {
|
|
2608
3026
|
return this.#state.attempts.get(tenantKey(tenant, taskId));
|
|
2609
3027
|
}
|
|
@@ -2634,12 +3052,18 @@ var InMemoryTaskAttemptStore = class {
|
|
|
2634
3052
|
return this.#state.mutate(key, () => {
|
|
2635
3053
|
const existing = this.#state.attempts.get(key);
|
|
2636
3054
|
if (existing === void 0) return void 0;
|
|
3055
|
+
if (existing.agentRef === void 0 !== (input.agentRef === void 0) || existing.agentRef !== void 0 && !sameAgentRef3(existing.agentRef, input.agentRef)) return existing;
|
|
2637
3056
|
if (existing.cancellation !== void 0) {
|
|
2638
3057
|
if (input.status !== "cancelled" || existing.status === "cancelled") return existing;
|
|
2639
3058
|
} else if (existing.status === "complete" || existing.status === "failed" || existing.status === "cancelled") {
|
|
2640
3059
|
return existing;
|
|
2641
3060
|
}
|
|
2642
|
-
const updated = {
|
|
3061
|
+
const updated = {
|
|
3062
|
+
...existing,
|
|
3063
|
+
status: input.status,
|
|
3064
|
+
...input.terminalCause === void 0 ? {} : { terminalCause: input.terminalCause },
|
|
3065
|
+
updatedAt: this.#now()
|
|
3066
|
+
};
|
|
2643
3067
|
this.#state.attempts.set(key, updated);
|
|
2644
3068
|
return updated;
|
|
2645
3069
|
});
|
|
@@ -2839,10 +3263,34 @@ var InMemoryApprovalTimelineStore = class {
|
|
|
2839
3263
|
return tail;
|
|
2840
3264
|
}
|
|
2841
3265
|
};
|
|
3266
|
+
var InMemoryAgentEgressStore = class {
|
|
3267
|
+
#records = /* @__PURE__ */ new Map();
|
|
3268
|
+
#clock;
|
|
3269
|
+
constructor(clock) {
|
|
3270
|
+
this.#clock = clock;
|
|
3271
|
+
}
|
|
3272
|
+
async record(tenant, input) {
|
|
3273
|
+
const key = tenantKey(tenant, `${input.deviceId}\0${input.payload.eventId}`);
|
|
3274
|
+
const existing = this.#records.get(key);
|
|
3275
|
+
if (existing !== void 0) return { record: existing, created: false };
|
|
3276
|
+
const record = {
|
|
3277
|
+
tenantId: tenant,
|
|
3278
|
+
deviceId: input.deviceId,
|
|
3279
|
+
payload: input.payload,
|
|
3280
|
+
receiptId: input.receiptId,
|
|
3281
|
+
recordedAt: this.#clock.now().toISOString()
|
|
3282
|
+
};
|
|
3283
|
+
this.#records.set(key, record);
|
|
3284
|
+
return { record, created: true };
|
|
3285
|
+
}
|
|
3286
|
+
async get(tenant, deviceId, eventId) {
|
|
3287
|
+
return this.#records.get(tenantKey(tenant, `${deviceId}\0${eventId}`));
|
|
3288
|
+
}
|
|
3289
|
+
};
|
|
2842
3290
|
|
|
2843
3291
|
// src/stores/in-memory/index.ts
|
|
2844
|
-
function createInMemoryCloudStores(clock,
|
|
2845
|
-
const blobs = createInMemoryBlobs(clock,
|
|
3292
|
+
function createInMemoryCloudStores(clock, crypto2, objects, mailbox) {
|
|
3293
|
+
const blobs = createInMemoryBlobs(clock, crypto2, objects);
|
|
2846
3294
|
const taskState = new InMemoryTaskAttemptState(clock);
|
|
2847
3295
|
const tasks = new InMemoryTaskAttemptStore(clock, taskState);
|
|
2848
3296
|
return {
|
|
@@ -2851,11 +3299,12 @@ function createInMemoryCloudStores(clock, crypto, objects, mailbox) {
|
|
|
2851
3299
|
approvals: new InMemoryApprovalTimelineStore(clock),
|
|
2852
3300
|
devices: new InMemoryDeviceDirectory(),
|
|
2853
3301
|
pairingCodes: new InMemoryPairingCodeStore(clock),
|
|
2854
|
-
nonces: new InMemoryNonceStore(clock,
|
|
3302
|
+
nonces: new InMemoryNonceStore(clock, crypto2),
|
|
2855
3303
|
dedup: new InMemoryInboundDedupStore(),
|
|
2856
3304
|
tasks,
|
|
2857
3305
|
cancellations: new InMemoryTaskCancellationStore(taskState, mailbox),
|
|
2858
3306
|
receipts: new InMemoryRequestReceiptStore(clock),
|
|
3307
|
+
egress: new InMemoryAgentEgressStore(clock),
|
|
2859
3308
|
proofReceipts: new InMemoryProofRequestReceiptStore(clock),
|
|
2860
3309
|
blobs: blobs.blobs,
|
|
2861
3310
|
rateLimiter: new AllowAllRateLimiter()
|
|
@@ -2871,11 +3320,11 @@ function systemClock() {
|
|
|
2871
3320
|
}
|
|
2872
3321
|
function createInMemoryByokCloud(options = {}) {
|
|
2873
3322
|
const clock = options.clock ?? systemClock();
|
|
2874
|
-
const
|
|
3323
|
+
const crypto2 = options.crypto ?? createWebCrypto();
|
|
2875
3324
|
const core = createInMemoryCoreStores({ clock }).stores;
|
|
2876
3325
|
const { stores, blobContentProxy } = createInMemoryCloudStores(
|
|
2877
3326
|
clock,
|
|
2878
|
-
|
|
3327
|
+
crypto2,
|
|
2879
3328
|
core.objects,
|
|
2880
3329
|
core.mailbox
|
|
2881
3330
|
);
|
|
@@ -2888,7 +3337,7 @@ function createInMemoryByokCloud(options = {}) {
|
|
|
2888
3337
|
// pairing is what keeps hosted-in-memory behavior identical to what it was
|
|
2889
3338
|
// before the port narrowed.
|
|
2890
3339
|
blobContentProxy,
|
|
2891
|
-
crypto,
|
|
3340
|
+
crypto: crypto2,
|
|
2892
3341
|
tokenSigner,
|
|
2893
3342
|
clock,
|
|
2894
3343
|
capabilities: options.capabilities ?? fullCapabilityDeclaration(),
|
|
@@ -2917,7 +3366,7 @@ function createInMemoryByokCloud(options = {}) {
|
|
|
2917
3366
|
...options.skillPacks === void 0 ? {} : { skillPacks: options.skillPacks },
|
|
2918
3367
|
...options.skillPackPageLimit === void 0 ? {} : { skillPackPageLimit: options.skillPackPageLimit }
|
|
2919
3368
|
});
|
|
2920
|
-
return { cloud, core, stores, blobContentProxy, clock, crypto };
|
|
3369
|
+
return { cloud, core, stores, blobContentProxy, clock, crypto: crypto2 };
|
|
2921
3370
|
}
|
|
2922
3371
|
function authenticateHostedDeviceAssertion(input, deps) {
|
|
2923
3372
|
return authenticateDeviceAssertion(input, {
|
|
@@ -3085,6 +3534,7 @@ var TASK_ATTEMPT_STATUSES = [
|
|
|
3085
3534
|
"failed",
|
|
3086
3535
|
"cancelled"
|
|
3087
3536
|
];
|
|
3537
|
+
var BLOB_READ_ERROR_CODES = ["blob_upstream_unavailable", "blob_upstream_stream_interrupted"];
|
|
3088
3538
|
var CLOUD_STORE_NAMES = [
|
|
3089
3539
|
"activity",
|
|
3090
3540
|
"approvals",
|
|
@@ -3095,6 +3545,7 @@ var CLOUD_STORE_NAMES = [
|
|
|
3095
3545
|
"tasks",
|
|
3096
3546
|
"cancellations",
|
|
3097
3547
|
"receipts",
|
|
3548
|
+
"egress",
|
|
3098
3549
|
"proofReceipts",
|
|
3099
3550
|
"blobs",
|
|
3100
3551
|
"rateLimiter"
|
|
@@ -3104,13 +3555,14 @@ var CLOUD_STORE_NAMES = [
|
|
|
3104
3555
|
var CLOUD_PORT_METHODS = {
|
|
3105
3556
|
activity: ["append", "read"],
|
|
3106
3557
|
approvals: ["append", "read"],
|
|
3107
|
-
devices: ["register", "get", "revoke", "list", "readiness", "resolveByDeviceId"],
|
|
3558
|
+
devices: ["register", "get", "revoke", "list", "readiness", "recordCapabilities", "resolveByDeviceId"],
|
|
3108
3559
|
pairingCodes: ["issue", "redeem"],
|
|
3109
3560
|
nonces: ["issue", "validate", "markUsed"],
|
|
3110
3561
|
dedup: ["checkAndRecord"],
|
|
3111
|
-
tasks: ["open", "get", "getMany", "claim", "recordStatus"],
|
|
3562
|
+
tasks: ["open", "reserveAgentOffer", "get", "getMany", "claim", "recordStatus"],
|
|
3112
3563
|
cancellations: ["request"],
|
|
3113
3564
|
receipts: ["record", "get"],
|
|
3565
|
+
egress: ["record", "get"],
|
|
3114
3566
|
proofReceipts: ["record", "get"],
|
|
3115
3567
|
// Three methods, not six: the byte-proxy trio moved to `BlobContentProxy`,
|
|
3116
3568
|
// which is a composition input rather than a port and therefore has no row
|
|
@@ -3128,11 +3580,12 @@ var CLOUD_PORT_INTERFACES = {
|
|
|
3128
3580
|
tasks: "TaskAttemptStore",
|
|
3129
3581
|
cancellations: "TaskCancellationStore",
|
|
3130
3582
|
receipts: "RequestReceiptStore",
|
|
3583
|
+
egress: "AgentEgressStore",
|
|
3131
3584
|
proofReceipts: "ProofRequestReceiptStore",
|
|
3132
3585
|
blobs: "CloudBlobStore",
|
|
3133
3586
|
rateLimiter: "InboundRateLimiter"
|
|
3134
3587
|
};
|
|
3135
3588
|
|
|
3136
|
-
export { ACCESS_TOKEN_TTL_SECONDS, APPROVAL_SUMMARY_MAX_BYTES, ActivityAppendRequestSchema, AllowAllRateLimiter, ApprovalObservationSchema, ApprovalTimelineEventSchema, BLOB_URL_TTL_MS, BoardFeedClient, BoardFeedRetryableError, BoardFeedStoppedError, ByokCloudError, CLOUD_CAPABILITIES, CLOUD_ERROR_CODES, CLOUD_PORT_INTERFACES, CLOUD_PORT_METHODS, CLOUD_STORE_NAMES, CapabilitiesResponseSchema, CloudRouteRegistry, DEDUP_RING_CAPACITY, DEFAULT_ACTIVITY_BOUNDS, DEFAULT_ACTIVITY_CAPACITY, DEFAULT_ACTIVITY_MAX_BYTES, DEFAULT_ACTIVITY_MAX_EVENTS, DEFAULT_ACTIVITY_TTL_MS, DEFAULT_APPROVAL_TIMELINE_CAPACITY, DEFAULT_APPROVAL_TIMELINE_TTL_MS, DEFAULT_BOARD_CHANNEL_MAX_BYTES, DEFAULT_BOARD_PAGE_LIMIT, DEFAULT_BOARD_STREAM_HEARTBEAT_INTERVAL_MS, DEFAULT_BOARD_STREAM_QUERY_INTERVAL_MS, DEFAULT_BOARD_STREAM_RECONCILIATION_INTERVAL_MS, DEFAULT_BOARD_TITLE_MAX_BYTES, DEFAULT_DEVICE_PROOF_CLOCK_SKEW_MS, DEFAULT_DEVICE_PROOF_MAX_LIFETIME_MS, DEFAULT_EVENTS_PAGE_LIMIT, DEFAULT_LONG_POLL_HOLD_MS, DEFAULT_LONG_POLL_INTERVAL_MS, DEFAULT_MAX_BLOB_SIZE_BYTES, DEFAULT_MAX_TRUTH_REQUEST_BYTES, DEFAULT_PRESENCE_DETAIL_MAX_BYTES, DEFAULT_PRESENCE_MINIMUM_INTERVAL_MS, DEFAULT_PRESENCE_TTL_MS, DEFAULT_SKILL_PACK_PAGE_LIMIT, DEVICE_IDENTITY_PROOF_KEY_EPOCH, DEVICE_IDENTITY_PROOF_KEY_ID, InMemoryActivityStore, InMemoryBlobContentProxy, InMemoryCloudBlobStore, InMemoryDeviceDirectory, InMemoryInboundDedupStore, InMemoryNonceStore, InMemoryPairingCodeStore, InMemoryProofRequestReceiptStore, InMemoryRequestReceiptStore, InMemoryTaskAttemptStore, InMemoryTaskCancellationStore, MAX_DEVICE_PROOF_CLOCK_SKEW_MS, MAX_DEVICE_PROOF_HEADER_BYTES, MAX_DEVICE_PROOF_MAX_LIFETIME_MS, NONCE_TTL_MS, PAIRING_CODE_TTL_MS, ROUTE_CLASSES, ROUTE_METHODS, TASK_ATTEMPT_STATUSES, TRUTH_BATCH_MAX_RECORDS, TRUTH_INLINE_CONTENT_TYPE, TRUTH_LABEL_MAX_LENGTH, TRUTH_MANIFEST_MAX_LIMIT, TRUTH_RECORD_CAPABILITY, TRUTH_RECORD_KEY_MAX_LENGTH, TRUTH_REQUEST_ID_MAX_LENGTH, TimelineEventSchema, TruthBodyInputSchema, TruthCommitError, TruthCommitResponseSchema, TruthRecordKeySchema, TruthRecordMetadataSchema, TruthWriteRequestSchema, activityCursor, approvalTimelineCursor, authenticateBearer, authenticateDeviceProof, authenticateHostedDeviceAssertion, createAuthPlane, createByokCloud, createHmacTokenSigner, createInMemoryBlobs, createInMemoryByokCloud, createInMemoryCloudStores, createWebCrypto, declares, extractBearerToken, fullCapabilityDeclaration, handleInboundEnvelope, isCloudError, isTruthCommitError, parseApprovalObservations, parseTimelineEvents, projectTerminalResult, projectTimelineEvents, routeKey, tenantStoresFor, terminalReceiptKey, truthManifestMetadata, truthRecordMetadata, validateActivityAppend, validateApprovalTimelineAppend, verifyNonceSignature };
|
|
3589
|
+
export { ACCESS_TOKEN_TTL_SECONDS, AGENT_HOME_CONTRACT_CAPABILITY, APPROVAL_SUMMARY_MAX_BYTES, ActivityAppendRequestSchema, AllowAllRateLimiter, ApprovalObservationSchema, ApprovalTimelineEventSchema, BLOB_READ_ERROR_CODES, BLOB_URL_TTL_MS, BoardFeedClient, BoardFeedRetryableError, BoardFeedStoppedError, ByokCloudError, CLOUD_CAPABILITIES, CLOUD_ERROR_CODES, CLOUD_PORT_INTERFACES, CLOUD_PORT_METHODS, CLOUD_STORE_NAMES, CapabilitiesResponseSchema, CloudRouteRegistry, DEDUP_RING_CAPACITY, DEFAULT_ACTIVITY_BOUNDS, DEFAULT_ACTIVITY_CAPACITY, DEFAULT_ACTIVITY_MAX_BYTES, DEFAULT_ACTIVITY_MAX_EVENTS, DEFAULT_ACTIVITY_TTL_MS, DEFAULT_APPROVAL_TIMELINE_CAPACITY, DEFAULT_APPROVAL_TIMELINE_TTL_MS, DEFAULT_BOARD_CHANNEL_MAX_BYTES, DEFAULT_BOARD_PAGE_LIMIT, DEFAULT_BOARD_STREAM_HEARTBEAT_INTERVAL_MS, DEFAULT_BOARD_STREAM_QUERY_INTERVAL_MS, DEFAULT_BOARD_STREAM_RECONCILIATION_INTERVAL_MS, DEFAULT_BOARD_TITLE_MAX_BYTES, DEFAULT_DEVICE_PROOF_CLOCK_SKEW_MS, DEFAULT_DEVICE_PROOF_MAX_LIFETIME_MS, DEFAULT_EVENTS_PAGE_LIMIT, DEFAULT_LONG_POLL_HOLD_MS, DEFAULT_LONG_POLL_INTERVAL_MS, DEFAULT_MAX_BLOB_SIZE_BYTES, DEFAULT_MAX_TRUTH_REQUEST_BYTES, DEFAULT_PRESENCE_DETAIL_MAX_BYTES, DEFAULT_PRESENCE_MINIMUM_INTERVAL_MS, DEFAULT_PRESENCE_TTL_MS, DEFAULT_SKILL_PACK_PAGE_LIMIT, DEVICE_IDENTITY_PROOF_KEY_EPOCH, DEVICE_IDENTITY_PROOF_KEY_ID, InMemoryActivityStore, InMemoryAgentEgressStore, InMemoryBlobContentProxy, InMemoryCloudBlobStore, InMemoryDeviceDirectory, InMemoryInboundDedupStore, InMemoryNonceStore, InMemoryPairingCodeStore, InMemoryProofRequestReceiptStore, InMemoryRequestReceiptStore, InMemoryTaskAttemptStore, InMemoryTaskCancellationStore, MAX_DEVICE_PROOF_CLOCK_SKEW_MS, MAX_DEVICE_PROOF_HEADER_BYTES, MAX_DEVICE_PROOF_MAX_LIFETIME_MS, NONCE_TTL_MS, PAIRING_CODE_TTL_MS, ROUTE_CLASSES, ROUTE_METHODS, TASK_ATTEMPT_STATUSES, TRUTH_BATCH_MAX_RECORDS, TRUTH_INLINE_CONTENT_TYPE, TRUTH_LABEL_MAX_LENGTH, TRUTH_MANIFEST_MAX_LIMIT, TRUTH_RECORD_CAPABILITY, TRUTH_RECORD_KEY_MAX_LENGTH, TRUTH_REQUEST_ID_MAX_LENGTH, TimelineEventSchema, TruthBodyInputSchema, TruthCommitError, TruthCommitResponseSchema, TruthRecordKeySchema, TruthRecordMetadataSchema, TruthWriteRequestSchema, activityCursor, approvalTimelineCursor, authenticateBearer, authenticateDeviceProof, authenticateHostedDeviceAssertion, createAuthPlane, createByokCloud, createHmacTokenSigner, createInMemoryBlobs, createInMemoryByokCloud, createInMemoryCloudStores, createWebCrypto, declares, extractBearerToken, fullCapabilityDeclaration, handleInboundEnvelope, isCloudError, isTruthCommitError, parseApprovalObservations, parseTimelineEvents, projectTerminalResult, projectTimelineEvents, routeKey, tenantStoresFor, terminalReceiptKey, truthManifestMetadata, truthRecordMetadata, validateActivityAppend, validateApprovalTimelineAppend, verifyNonceSignature };
|
|
3137
3590
|
//# sourceMappingURL=index.js.map
|
|
3138
3591
|
//# sourceMappingURL=index.js.map
|