@byok-sdk/cloud 0.8.0-beta.0 → 0.8.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/agent-home-projections.d.ts +23 -0
- package/dist/cloud.d.ts +15 -1
- package/dist/errors.d.ts +10 -0
- package/dist/handlers/agent-home-projections.d.ts +9 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +247 -3
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Durable task-free Agent-home projection facts.
|
|
3
|
+
*
|
|
4
|
+
* Desired projection and completion are deliberately two immutable request
|
|
5
|
+
* receipts. The receipt store is tenant-scoped and first-write-wins, so the
|
|
6
|
+
* composition does not need a second mutable projection authority merely to
|
|
7
|
+
* survive a process restart.
|
|
8
|
+
*/
|
|
9
|
+
import { type AgentHomeProjectionPayload, type AgentHomeProjectionCompletionRequest, type AgentHomeProjectionReadback } from '@byok-sdk/protocol';
|
|
10
|
+
import type { TenantId } from '@byok-sdk/core';
|
|
11
|
+
import type { TenantBoundReceipts } from './tenant-stores';
|
|
12
|
+
export interface AgentHomeProjectionReceiptInput {
|
|
13
|
+
readonly requestId: string;
|
|
14
|
+
readonly agentRef: AgentHomeProjectionPayload['agentRef'];
|
|
15
|
+
readonly projectionHash: AgentHomeProjectionPayload['projectionHash'];
|
|
16
|
+
}
|
|
17
|
+
export declare function agentHomeProjectionRequestKey(deviceId: string, requestId: string): string;
|
|
18
|
+
export declare function agentHomeProjectionCompletionKey(deviceId: string, requestId: string): string;
|
|
19
|
+
export declare function sameAgentHomeProjectionRequest(expected: AgentHomeProjectionPayload, actual: AgentHomeProjectionPayload): boolean;
|
|
20
|
+
export declare function receiptMatchesAgentHomeProjection(request: AgentHomeProjectionPayload, receipt: AgentHomeProjectionCompletionRequest): boolean;
|
|
21
|
+
export declare function statusInputMatchesAgentHomeProjection(request: AgentHomeProjectionPayload, input: AgentHomeProjectionReceiptInput): boolean;
|
|
22
|
+
export declare function readAgentHomeProjectionStatus(receipts: TenantBoundReceipts, tenant: TenantId, deviceId: string, input: AgentHomeProjectionReceiptInput): Promise<AgentHomeProjectionReadback | undefined>;
|
|
23
|
+
export declare function recordAgentHomeProjectionCompletion(receipts: TenantBoundReceipts, tenant: TenantId, deviceId: string, receiptInput: AgentHomeProjectionCompletionRequest): Promise<AgentHomeProjectionReadback>;
|
package/dist/cloud.d.ts
CHANGED
|
@@ -17,10 +17,11 @@
|
|
|
17
17
|
import { type BoardItem, type BoardItemInput, type BoardListQuery, type BoardPage, type CapabilityDeclaration, type Clock, type CoreStores, type PresenceHint, type SkillPackStore, type TenantId, type TenantReadiness } from '@byok-sdk/core';
|
|
18
18
|
import type { ActivityTail } from './activity';
|
|
19
19
|
import type { ApprovalTimelineTail } from './approval-timeline';
|
|
20
|
-
import { type Envelope, type AgentContentReadPayload, type TaskOfferPayload, type TaskOfferForAgentPayload, type TaskOfferForAgentWithEgressPayload, type TaskOfferForAgentWithEgressFreshPayload, type TaskOfferWithToolsetsPayload } from '@byok-sdk/protocol';
|
|
20
|
+
import { type Envelope, type AgentContentReadPayload, type AgentHomeProjectionCompletionRequest, type AgentHomeProjectionPayload, type AgentHomeProjectionReadback, type TaskOfferPayload, type TaskOfferForAgentPayload, type TaskOfferForAgentWithEgressPayload, type TaskOfferForAgentWithEgressFreshPayload, type TaskOfferWithToolsetsPayload } from '@byok-sdk/protocol';
|
|
21
21
|
import type { TokenSigner } from './auth/tokens';
|
|
22
22
|
import type { CloudCrypto } from './crypto/port';
|
|
23
23
|
import { type RouteDescriptor } from './router/registry';
|
|
24
|
+
import { type AgentHomeProjectionReceiptInput } from './agent-home-projections';
|
|
24
25
|
import type { BlobContentProxy, CloudStores, DeviceRecord, AgentEgressRecord, PairingCodeInfo, RequestReceipt, TaskAttempt } from './stores/ports';
|
|
25
26
|
import { type TerminalResult } from './terminal-result';
|
|
26
27
|
import type { TruthCommitter, TruthObjectDownloads } from './truth/contract';
|
|
@@ -125,10 +126,17 @@ export interface AgentEgressFreshSessionDispatchInput {
|
|
|
125
126
|
export interface AgentContentReadInput {
|
|
126
127
|
readonly payload: AgentContentReadPayload;
|
|
127
128
|
}
|
|
129
|
+
/** Task-free exact-device projection desired state, intentionally unrelated to TaskAttempt. */
|
|
130
|
+
export type AgentHomeProjectionInput = AgentHomeProjectionPayload;
|
|
131
|
+
/** Exact request identity a host must echo to read back durable projection status. */
|
|
132
|
+
export type AgentHomeProjectionStatusInput = AgentHomeProjectionReceiptInput;
|
|
128
133
|
export interface EnqueuedAgentControl {
|
|
129
134
|
readonly seq: number;
|
|
130
135
|
readonly envelope: Envelope;
|
|
131
136
|
}
|
|
137
|
+
export interface EnqueuedAgentHomeProjection extends EnqueuedAgentControl {
|
|
138
|
+
readonly status: AgentHomeProjectionReadback;
|
|
139
|
+
}
|
|
132
140
|
export interface EnqueuedOffer {
|
|
133
141
|
readonly taskId: string;
|
|
134
142
|
/** The per-(tenant, device) delivery seq — the daemon's redelivery cursor position for this envelope. */
|
|
@@ -180,6 +188,12 @@ export interface ByokCloud {
|
|
|
180
188
|
enqueueFreshAgentEgressOffer(tenant: TenantId, deviceId: string, input: AgentEgressFreshSessionDispatchInput): Promise<EnqueuedOffer>;
|
|
181
189
|
/** Host control plane: request one policy-bound content read without a task fallback. */
|
|
182
190
|
enqueueAgentContentRead(tenant: TenantId, deviceId: string, input: AgentContentReadInput): Promise<EnqueuedAgentControl>;
|
|
191
|
+
/** Durable, task-free projection request for precisely one admitted device. */
|
|
192
|
+
enqueueAgentHomeProjection(tenant: TenantId, deviceId: string, input: AgentHomeProjectionInput): Promise<EnqueuedAgentHomeProjection>;
|
|
193
|
+
/** Tenant/device/request-bound durable desired-state and terminal-outcome readback. */
|
|
194
|
+
getAgentHomeProjectionStatus(tenant: TenantId, deviceId: string, input: AgentHomeProjectionStatusInput): Promise<AgentHomeProjectionReadback | undefined>;
|
|
195
|
+
/** Direct device completion endpoint authority; first exact terminal receipt wins. */
|
|
196
|
+
completeAgentHomeProjection(tenant: TenantId, deviceId: string, receipt: AgentHomeProjectionCompletionRequest): Promise<AgentHomeProjectionReadback>;
|
|
183
197
|
/** Host control plane: durably request cancellation by tenant/task id. Idempotent. */
|
|
184
198
|
cancelTask(tenant: TenantId, taskId: string, reason?: string): Promise<TaskAttempt>;
|
|
185
199
|
readTaskAttempt(tenant: TenantId, taskId: string): Promise<TaskAttempt | undefined>;
|
package/dist/errors.d.ts
CHANGED
|
@@ -53,6 +53,16 @@ export declare const CLOUD_ERROR_CODES: {
|
|
|
53
53
|
readonly agent_content_request_mismatch: 'agent_content_request_mismatch';
|
|
54
54
|
/** A durable mailbox receipt id resolved to an envelope other than its exact acknowledgement. */
|
|
55
55
|
readonly mailbox_receipt_mismatch: 'mailbox_receipt_mismatch';
|
|
56
|
+
/** A task-free Agent-home request id already names a different immutable desired projection. */
|
|
57
|
+
readonly agent_home_projection_request_conflict: 'agent_home_projection_request_conflict';
|
|
58
|
+
/** A direct Agent-home completion did not identify a stored desired request for this exact device. */
|
|
59
|
+
readonly agent_home_projection_request_not_found: 'agent_home_projection_request_not_found';
|
|
60
|
+
/** A direct Agent-home completion changed the first durable terminal outcome. */
|
|
61
|
+
readonly agent_home_projection_completion_conflict: 'agent_home_projection_completion_conflict';
|
|
62
|
+
/** A task-free completion did not exactly echo its immutable desired projection binding. */
|
|
63
|
+
readonly agent_home_projection_receipt_mismatch: 'agent_home_projection_receipt_mismatch';
|
|
64
|
+
/** A receipt-store row at the projection namespace violated the frozen projection schema. */
|
|
65
|
+
readonly agent_home_projection_receipt_invalid: 'agent_home_projection_receipt_invalid';
|
|
56
66
|
};
|
|
57
67
|
export type CloudErrorCode = (typeof CLOUD_ERROR_CODES)[keyof typeof CLOUD_ERROR_CODES];
|
|
58
68
|
export declare class ByokCloudError extends Error {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Device-authenticated exact completion readback for task-free Agent-home projections. */
|
|
2
|
+
import type { Context } from 'hono';
|
|
3
|
+
import { type AgentHomeProjectionCompletionRequest, type AgentHomeProjectionReadback } from '@byok-sdk/protocol';
|
|
4
|
+
import { type DeviceRouteDeps } from './shared';
|
|
5
|
+
import type { TenantStores } from '../tenant-stores';
|
|
6
|
+
export interface AgentHomeProjectionRouteDeps extends DeviceRouteDeps {
|
|
7
|
+
readonly complete: (stores: TenantStores, deviceId: string, receipt: AgentHomeProjectionCompletionRequest) => Promise<AgentHomeProjectionReadback>;
|
|
8
|
+
}
|
|
9
|
+
export declare function agentHomeProjectionCompletionHandler(deps: AgentHomeProjectionRouteDeps): (c: Context) => Promise<Response>;
|
package/dist/index.d.ts
CHANGED
|
@@ -15,7 +15,9 @@
|
|
|
15
15
|
export { isTenantId, tenantId } from '@byok-sdk/core';
|
|
16
16
|
export type { TenantId } from '@byok-sdk/core';
|
|
17
17
|
export { createByokCloud } from './cloud';
|
|
18
|
-
export type { ByokCloud, ByokCloudOptions, AgentDispatchInput, AgentEgressDispatchInput, AgentEgressFreshSessionDispatchInput, AgentContentReadInput, EnqueueOfferInput, EnqueueToolsetOfferInput, EnqueuedAgentControl, EnqueuedOffer, } from './cloud';
|
|
18
|
+
export type { ByokCloud, ByokCloudOptions, AgentDispatchInput, AgentEgressDispatchInput, AgentEgressFreshSessionDispatchInput, AgentContentReadInput, AgentHomeProjectionInput, AgentHomeProjectionStatusInput, EnqueueOfferInput, EnqueueToolsetOfferInput, EnqueuedAgentControl, EnqueuedAgentHomeProjection, EnqueuedOffer, } from './cloud';
|
|
19
|
+
export { agentHomeProjectionCompletionKey, agentHomeProjectionRequestKey, readAgentHomeProjectionStatus, recordAgentHomeProjectionCompletion, } from './agent-home-projections';
|
|
20
|
+
export type { AgentHomeProjectionReceiptInput } from './agent-home-projections';
|
|
19
21
|
export { AGENT_HOME_CONTRACT_CAPABILITY, DEFAULT_EVENTS_PAGE_LIMIT, DEFAULT_LONG_POLL_HOLD_MS, DEFAULT_LONG_POLL_INTERVAL_MS, DEFAULT_MAX_BLOB_SIZE_BYTES, } from './cloud';
|
|
20
22
|
export { DEFAULT_BOARD_PAGE_LIMIT, DEFAULT_BOARD_STREAM_HEARTBEAT_INTERVAL_MS, DEFAULT_BOARD_STREAM_QUERY_INTERVAL_MS, DEFAULT_BOARD_STREAM_RECONCILIATION_INTERVAL_MS, } from './handlers/board';
|
|
21
23
|
export { DEFAULT_SKILL_PACK_PAGE_LIMIT } from './handlers/skill-packs';
|
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, 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, TaskOfferForAgentWithEgressFreshPayloadSchema, TaskOfferForAgentWithEgressPayloadSchema, TaskOfferForAgentPayloadSchema, AGENT_CONTENT_ARTIFACT_READ_CAPABILITY, AGENT_CONTENT_TRANSCRIPT_READ_CAPABILITY, AGENT_CONTENT_WORKSPACE_READ_CAPABILITY, AGENT_EGRESS_FRESH_SESSION_CAPABILITY, PairRequestSchema, PairResponseSchema, ChallengeRequestSchema, TokenRequestSchema, MessagesSendRequestSchema, PresencePublishRequestSchema, CreateBlobRequestSchema, byokBlobContentPath, AgentEgressAckPayloadSchema, AgentContentReceiptPayloadSchema } from '@byok-sdk/protocol';
|
|
3
|
+
import { AgentEventOrUnknownSchema, PROTOCOL_VERSION, DAEMON_TO_SERVER_TYPES, AGENT_EGRESS_RELIABLE_ACK_CAPABILITY, encodeEnvelope, AgentHomeProjectionCompletionRequestSchema, decodeEnvelope, BYOK_PAIR_PATH, BYOK_CHALLENGE_PATH, BYOK_TOKEN_PATH, BYOK_CAPABILITIES_PATH, BYOK_EVENTS_PATH, BYOK_MESSAGES_PATH, BYOK_AGENT_HOME_PROJECTION_COMPLETION_ROUTE, 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, AgentHomeProjectionPayloadSchema, AgentContentReadPayloadSchema, AGENT_EGRESS_POLICY_CAPABILITY, TaskOfferForAgentWithEgressFreshPayloadSchema, TaskOfferForAgentWithEgressPayloadSchema, TaskOfferForAgentPayloadSchema, STRICT_AGENT_ONLY_CAPABILITY, AGENT_CONTENT_ARTIFACT_READ_CAPABILITY, AGENT_CONTENT_TRANSCRIPT_READ_CAPABILITY, AGENT_CONTENT_WORKSPACE_READ_CAPABILITY, AGENT_HOME_PROJECTION_CAPABILITY, AGENT_EGRESS_FRESH_SESSION_CAPABILITY, PairRequestSchema, PairResponseSchema, 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
|
|
|
@@ -329,7 +329,17 @@ var CLOUD_ERROR_CODES = {
|
|
|
329
329
|
/** A first-write-wins Agent control record was replayed with a different body. */
|
|
330
330
|
agent_content_request_mismatch: "agent_content_request_mismatch",
|
|
331
331
|
/** A durable mailbox receipt id resolved to an envelope other than its exact acknowledgement. */
|
|
332
|
-
mailbox_receipt_mismatch: "mailbox_receipt_mismatch"
|
|
332
|
+
mailbox_receipt_mismatch: "mailbox_receipt_mismatch",
|
|
333
|
+
/** A task-free Agent-home request id already names a different immutable desired projection. */
|
|
334
|
+
agent_home_projection_request_conflict: "agent_home_projection_request_conflict",
|
|
335
|
+
/** A direct Agent-home completion did not identify a stored desired request for this exact device. */
|
|
336
|
+
agent_home_projection_request_not_found: "agent_home_projection_request_not_found",
|
|
337
|
+
/** A direct Agent-home completion changed the first durable terminal outcome. */
|
|
338
|
+
agent_home_projection_completion_conflict: "agent_home_projection_completion_conflict",
|
|
339
|
+
/** A task-free completion did not exactly echo its immutable desired projection binding. */
|
|
340
|
+
agent_home_projection_receipt_mismatch: "agent_home_projection_receipt_mismatch",
|
|
341
|
+
/** A receipt-store row at the projection namespace violated the frozen projection schema. */
|
|
342
|
+
agent_home_projection_receipt_invalid: "agent_home_projection_receipt_invalid"
|
|
333
343
|
};
|
|
334
344
|
var ByokCloudError = class extends Error {
|
|
335
345
|
code;
|
|
@@ -791,6 +801,7 @@ function tokenHandler(deps) {
|
|
|
791
801
|
var CLOUD_PROTOCOL_CAPABILITIES = [
|
|
792
802
|
"result-document",
|
|
793
803
|
"agent-home-contract",
|
|
804
|
+
"agent-home-projection",
|
|
794
805
|
"agent-egress-policy",
|
|
795
806
|
"agent-egress-reliable-ack",
|
|
796
807
|
"agent-egress-fresh-session",
|
|
@@ -1223,6 +1234,35 @@ function messagesHandler(deps) {
|
|
|
1223
1234
|
return c.json(response, 200);
|
|
1224
1235
|
};
|
|
1225
1236
|
}
|
|
1237
|
+
function agentHomeProjectionCompletionHandler(deps) {
|
|
1238
|
+
return async (c) => {
|
|
1239
|
+
const authenticated = await authenticateDevice(c, deps);
|
|
1240
|
+
if (authenticated === void 0) return c.json({ error: "unauthorized" }, 401);
|
|
1241
|
+
const parsed = AgentHomeProjectionCompletionRequestSchema.safeParse(await readJsonBody(c));
|
|
1242
|
+
if (!parsed.success) return c.json({ error: "invalid Agent-home projection completion" }, 422);
|
|
1243
|
+
const requestId = c.req.param("requestId");
|
|
1244
|
+
if (requestId === void 0 || requestId !== parsed.data.requestId) {
|
|
1245
|
+
return c.json({ error: "agent_home_projection_receipt_mismatch" }, 422);
|
|
1246
|
+
}
|
|
1247
|
+
try {
|
|
1248
|
+
return c.json(
|
|
1249
|
+
await deps.complete(authenticated.stores, authenticated.device.deviceId, parsed.data),
|
|
1250
|
+
200
|
|
1251
|
+
);
|
|
1252
|
+
} catch (error) {
|
|
1253
|
+
if (isCloudError(error, "agent_home_projection_request_not_found")) {
|
|
1254
|
+
return c.json({ error: error.code }, 404);
|
|
1255
|
+
}
|
|
1256
|
+
if (isCloudError(error, "agent_home_projection_receipt_mismatch") || isCloudError(error, "agent_home_projection_receipt_invalid")) {
|
|
1257
|
+
return c.json({ error: error.code }, 422);
|
|
1258
|
+
}
|
|
1259
|
+
if (isCloudError(error, "agent_home_projection_request_conflict") || isCloudError(error, "agent_home_projection_completion_conflict") || isCloudError(error, "agent_capability_missing")) {
|
|
1260
|
+
return c.json({ error: error.code }, 409);
|
|
1261
|
+
}
|
|
1262
|
+
throw error;
|
|
1263
|
+
}
|
|
1264
|
+
};
|
|
1265
|
+
}
|
|
1226
1266
|
var DEFAULT_BOARD_PAGE_LIMIT = 50;
|
|
1227
1267
|
var DEFAULT_BOARD_STREAM_QUERY_INTERVAL_MS = 5e3;
|
|
1228
1268
|
var DEFAULT_BOARD_STREAM_HEARTBEAT_INTERVAL_MS = 15e3;
|
|
@@ -1967,6 +2007,118 @@ var CloudRouteRegistry = class {
|
|
|
1967
2007
|
return this.#app.fetch;
|
|
1968
2008
|
}
|
|
1969
2009
|
};
|
|
2010
|
+
function agentHomeProjectionRequestKey(deviceId, requestId) {
|
|
2011
|
+
return `agent-home-projection:v1:${deviceId}:${requestId}:request`;
|
|
2012
|
+
}
|
|
2013
|
+
function agentHomeProjectionCompletionKey(deviceId, requestId) {
|
|
2014
|
+
return `agent-home-projection:v1:${deviceId}:${requestId}:completion`;
|
|
2015
|
+
}
|
|
2016
|
+
function sameAgentHomeProjectionRequest(expected, actual) {
|
|
2017
|
+
return expected.requestId === actual.requestId && expected.agentRef.agentId === actual.agentRef.agentId && expected.agentRef.profileRevision === actual.agentRef.profileRevision && expected.projectionHash === actual.projectionHash && JSON.stringify(expected.projection) === JSON.stringify(actual.projection);
|
|
2018
|
+
}
|
|
2019
|
+
function receiptMatchesAgentHomeProjection(request, receipt) {
|
|
2020
|
+
return receipt.requestId === request.requestId && receipt.agentRef.agentId === request.agentRef.agentId && receipt.agentRef.profileRevision === request.agentRef.profileRevision && receipt.projectionHash === request.projectionHash;
|
|
2021
|
+
}
|
|
2022
|
+
function statusInputMatchesAgentHomeProjection(request, input) {
|
|
2023
|
+
return input.requestId === request.requestId && input.agentRef.agentId === request.agentRef.agentId && input.agentRef.profileRevision === request.agentRef.profileRevision && input.projectionHash === request.projectionHash;
|
|
2024
|
+
}
|
|
2025
|
+
function parseRequestBody(body) {
|
|
2026
|
+
try {
|
|
2027
|
+
return AgentHomeProjectionPayloadSchema.parse(JSON.parse(body));
|
|
2028
|
+
} catch (error) {
|
|
2029
|
+
throw new ByokCloudError(
|
|
2030
|
+
"agent_home_projection_receipt_invalid",
|
|
2031
|
+
"Stored Agent-home projection request is not a valid immutable projection fact.",
|
|
2032
|
+
{ cause: error }
|
|
2033
|
+
);
|
|
2034
|
+
}
|
|
2035
|
+
}
|
|
2036
|
+
function parseCompletionBody(body) {
|
|
2037
|
+
try {
|
|
2038
|
+
return AgentHomeProjectionCompletionRequestSchema.parse(JSON.parse(body));
|
|
2039
|
+
} catch (error) {
|
|
2040
|
+
throw new ByokCloudError(
|
|
2041
|
+
"agent_home_projection_receipt_invalid",
|
|
2042
|
+
"Stored Agent-home projection completion is not a valid immutable receipt fact.",
|
|
2043
|
+
{ cause: error }
|
|
2044
|
+
);
|
|
2045
|
+
}
|
|
2046
|
+
}
|
|
2047
|
+
async function readAgentHomeProjectionStatus(receipts, tenant, deviceId, input) {
|
|
2048
|
+
const storedRequest = await receipts.get(agentHomeProjectionRequestKey(deviceId, input.requestId));
|
|
2049
|
+
if (storedRequest === void 0) return void 0;
|
|
2050
|
+
const request = parseRequestBody(storedRequest.body);
|
|
2051
|
+
if (!statusInputMatchesAgentHomeProjection(request, input)) {
|
|
2052
|
+
throw new ByokCloudError(
|
|
2053
|
+
"agent_home_projection_request_conflict",
|
|
2054
|
+
`Agent-home projection request ${input.requestId} does not match its immutable desired fact.`
|
|
2055
|
+
);
|
|
2056
|
+
}
|
|
2057
|
+
const storedCompletion = await receipts.get(agentHomeProjectionCompletionKey(deviceId, input.requestId));
|
|
2058
|
+
if (storedCompletion === void 0) {
|
|
2059
|
+
return {
|
|
2060
|
+
tenantId: tenant,
|
|
2061
|
+
deviceId,
|
|
2062
|
+
requestId: request.requestId,
|
|
2063
|
+
agentRef: request.agentRef,
|
|
2064
|
+
projectionHash: request.projectionHash,
|
|
2065
|
+
status: "pending"
|
|
2066
|
+
};
|
|
2067
|
+
}
|
|
2068
|
+
const completion = parseCompletionBody(storedCompletion.body);
|
|
2069
|
+
if (!receiptMatchesAgentHomeProjection(request, completion)) {
|
|
2070
|
+
throw new ByokCloudError(
|
|
2071
|
+
"agent_home_projection_receipt_mismatch",
|
|
2072
|
+
`Agent-home projection completion ${input.requestId} does not match its immutable desired fact.`
|
|
2073
|
+
);
|
|
2074
|
+
}
|
|
2075
|
+
return {
|
|
2076
|
+
tenantId: tenant,
|
|
2077
|
+
deviceId,
|
|
2078
|
+
requestId: request.requestId,
|
|
2079
|
+
agentRef: request.agentRef,
|
|
2080
|
+
projectionHash: request.projectionHash,
|
|
2081
|
+
status: completion.outcome,
|
|
2082
|
+
completedAt: storedCompletion.recordedAt
|
|
2083
|
+
};
|
|
2084
|
+
}
|
|
2085
|
+
async function recordAgentHomeProjectionCompletion(receipts, tenant, deviceId, receiptInput) {
|
|
2086
|
+
const receipt = AgentHomeProjectionCompletionRequestSchema.parse(receiptInput);
|
|
2087
|
+
const storedRequest = await receipts.get(agentHomeProjectionRequestKey(deviceId, receipt.requestId));
|
|
2088
|
+
if (storedRequest === void 0) {
|
|
2089
|
+
throw new ByokCloudError(
|
|
2090
|
+
"agent_home_projection_request_not_found",
|
|
2091
|
+
`Agent-home projection request ${receipt.requestId} was not found for this device.`
|
|
2092
|
+
);
|
|
2093
|
+
}
|
|
2094
|
+
const request = parseRequestBody(storedRequest.body);
|
|
2095
|
+
if (!receiptMatchesAgentHomeProjection(request, receipt)) {
|
|
2096
|
+
throw new ByokCloudError(
|
|
2097
|
+
"agent_home_projection_receipt_mismatch",
|
|
2098
|
+
`Agent-home projection completion ${receipt.requestId} does not exactly match its desired fact.`
|
|
2099
|
+
);
|
|
2100
|
+
}
|
|
2101
|
+
const body = JSON.stringify(receipt);
|
|
2102
|
+
const storedCompletion = await receipts.record({
|
|
2103
|
+
key: agentHomeProjectionCompletionKey(deviceId, receipt.requestId),
|
|
2104
|
+
body
|
|
2105
|
+
});
|
|
2106
|
+
if (!storedCompletion.created && storedCompletion.receipt.body !== body) {
|
|
2107
|
+
throw new ByokCloudError(
|
|
2108
|
+
"agent_home_projection_completion_conflict",
|
|
2109
|
+
`Agent-home projection request ${receipt.requestId} already has a different terminal completion.`
|
|
2110
|
+
);
|
|
2111
|
+
}
|
|
2112
|
+
return {
|
|
2113
|
+
tenantId: tenant,
|
|
2114
|
+
deviceId,
|
|
2115
|
+
requestId: request.requestId,
|
|
2116
|
+
agentRef: request.agentRef,
|
|
2117
|
+
projectionHash: request.projectionHash,
|
|
2118
|
+
status: receipt.outcome,
|
|
2119
|
+
completedAt: storedCompletion.receipt.recordedAt
|
|
2120
|
+
};
|
|
2121
|
+
}
|
|
1970
2122
|
function projectTerminalResult(taskId, receipt) {
|
|
1971
2123
|
let envelope;
|
|
1972
2124
|
try {
|
|
@@ -2086,6 +2238,13 @@ function createByokCloud(options) {
|
|
|
2086
2238
|
})
|
|
2087
2239
|
);
|
|
2088
2240
|
}
|
|
2241
|
+
registry.register(
|
|
2242
|
+
{ method: "PUT", path: BYOK_AGENT_HOME_PROJECTION_COMPLETION_ROUTE, class: "device" },
|
|
2243
|
+
agentHomeProjectionCompletionHandler({
|
|
2244
|
+
...deviceRouteDeps,
|
|
2245
|
+
complete: (stores, deviceId, receipt) => completeAgentHomeProjectionFromStores(stores, deviceId, receipt)
|
|
2246
|
+
})
|
|
2247
|
+
);
|
|
2089
2248
|
if (declares(declaration, CLOUD_CAPABILITIES.boardCoordination)) {
|
|
2090
2249
|
const boardDeps = {
|
|
2091
2250
|
...deviceRouteDeps,
|
|
@@ -2276,6 +2435,15 @@ function createByokCloud(options) {
|
|
|
2276
2435
|
);
|
|
2277
2436
|
}
|
|
2278
2437
|
}
|
|
2438
|
+
async function assertLegacyAdmission(tenant, deviceId) {
|
|
2439
|
+
const device = await options.cloud.devices.get(tenant, deviceId);
|
|
2440
|
+
if (device?.capabilities?.includes(STRICT_AGENT_ONLY_CAPABILITY) === true) {
|
|
2441
|
+
throw new ByokCloudError(
|
|
2442
|
+
"agent_capability_missing",
|
|
2443
|
+
`Device ${deviceId} advertises strict-agent-only; refusing legacy offer before mailbox append.`
|
|
2444
|
+
);
|
|
2445
|
+
}
|
|
2446
|
+
}
|
|
2279
2447
|
function contentReadCapability2(surface) {
|
|
2280
2448
|
switch (surface) {
|
|
2281
2449
|
case "workspace":
|
|
@@ -2310,6 +2478,34 @@ function createByokCloud(options) {
|
|
|
2310
2478
|
}
|
|
2311
2479
|
return { seq: message.seq, envelope };
|
|
2312
2480
|
}
|
|
2481
|
+
async function getAgentHomeProjectionStatus(tenant, deviceId, input) {
|
|
2482
|
+
return readAgentHomeProjectionStatus(
|
|
2483
|
+
tenantStoresFor(controlPlane(tenant), root).receipts,
|
|
2484
|
+
tenant,
|
|
2485
|
+
deviceId,
|
|
2486
|
+
input
|
|
2487
|
+
);
|
|
2488
|
+
}
|
|
2489
|
+
async function completeAgentHomeProjection(tenant, deviceId, receiptInput) {
|
|
2490
|
+
return completeAgentHomeProjectionFromStores(
|
|
2491
|
+
tenantStoresFor(controlPlane(tenant), root),
|
|
2492
|
+
deviceId,
|
|
2493
|
+
receiptInput
|
|
2494
|
+
);
|
|
2495
|
+
}
|
|
2496
|
+
async function completeAgentHomeProjectionFromStores(stores, deviceId, receiptInput) {
|
|
2497
|
+
const receipt = AgentHomeProjectionCompletionRequestSchema.parse(receiptInput);
|
|
2498
|
+
await assertAgentCapabilities(stores.tenant, deviceId, [
|
|
2499
|
+
AGENT_HOME_CONTRACT_CAPABILITY,
|
|
2500
|
+
AGENT_HOME_PROJECTION_CAPABILITY
|
|
2501
|
+
]);
|
|
2502
|
+
return recordAgentHomeProjectionCompletion(
|
|
2503
|
+
stores.receipts,
|
|
2504
|
+
stores.tenant,
|
|
2505
|
+
deviceId,
|
|
2506
|
+
receipt
|
|
2507
|
+
);
|
|
2508
|
+
}
|
|
2313
2509
|
async function enqueueReliableEgressAck(stores, record) {
|
|
2314
2510
|
const payload = AgentEgressAckPayloadSchema.parse({
|
|
2315
2511
|
agentRef: record.payload.agentRef,
|
|
@@ -2386,6 +2582,7 @@ function createByokCloud(options) {
|
|
|
2386
2582
|
return auth.createPairingCode(tenant, input);
|
|
2387
2583
|
},
|
|
2388
2584
|
async enqueueOffer(tenant, deviceId, input) {
|
|
2585
|
+
await assertLegacyAdmission(tenant, deviceId);
|
|
2389
2586
|
return enqueueTaskEnvelope(
|
|
2390
2587
|
tenant,
|
|
2391
2588
|
deviceId,
|
|
@@ -2395,6 +2592,7 @@ function createByokCloud(options) {
|
|
|
2395
2592
|
);
|
|
2396
2593
|
},
|
|
2397
2594
|
async enqueueToolsetOffer(tenant, deviceId, input) {
|
|
2595
|
+
await assertLegacyAdmission(tenant, deviceId);
|
|
2398
2596
|
return enqueueTaskEnvelope(
|
|
2399
2597
|
tenant,
|
|
2400
2598
|
deviceId,
|
|
@@ -2478,6 +2676,52 @@ function createByokCloud(options) {
|
|
|
2478
2676
|
}
|
|
2479
2677
|
return control;
|
|
2480
2678
|
},
|
|
2679
|
+
async enqueueAgentHomeProjection(tenant, deviceId, input) {
|
|
2680
|
+
const payload = AgentHomeProjectionPayloadSchema.parse(input);
|
|
2681
|
+
await assertAgentCapabilities(tenant, deviceId, [
|
|
2682
|
+
AGENT_HOME_CONTRACT_CAPABILITY,
|
|
2683
|
+
AGENT_HOME_PROJECTION_CAPABILITY
|
|
2684
|
+
]);
|
|
2685
|
+
const stores = tenantStoresFor(controlPlane(tenant), root);
|
|
2686
|
+
const requestBody = JSON.stringify(payload);
|
|
2687
|
+
const persisted = await stores.receipts.record({
|
|
2688
|
+
key: agentHomeProjectionRequestKey(deviceId, payload.requestId),
|
|
2689
|
+
body: requestBody
|
|
2690
|
+
});
|
|
2691
|
+
const persistedPayload = AgentHomeProjectionPayloadSchema.parse(JSON.parse(persisted.receipt.body));
|
|
2692
|
+
if (!sameAgentHomeProjectionRequest(payload, persistedPayload)) {
|
|
2693
|
+
throw new ByokCloudError(
|
|
2694
|
+
"agent_home_projection_request_conflict",
|
|
2695
|
+
`Agent-home projection request ${payload.requestId} already exists with a different immutable desired body.`
|
|
2696
|
+
);
|
|
2697
|
+
}
|
|
2698
|
+
const control = await enqueueAgentControlEnvelope(
|
|
2699
|
+
tenant,
|
|
2700
|
+
deviceId,
|
|
2701
|
+
payload.requestId,
|
|
2702
|
+
(seq) => createEnvelope("agent.home.projection", payload, { id: payload.requestId, seq })
|
|
2703
|
+
);
|
|
2704
|
+
if (control.envelope.type !== "agent.home.projection" || !sameAgentHomeProjectionRequest(payload, control.envelope.payload)) {
|
|
2705
|
+
throw new ByokCloudError(
|
|
2706
|
+
"agent_home_projection_request_conflict",
|
|
2707
|
+
`Mailbox request ${payload.requestId} does not match its immutable Agent-home projection fact.`
|
|
2708
|
+
);
|
|
2709
|
+
}
|
|
2710
|
+
const status = await getAgentHomeProjectionStatus(tenant, deviceId, {
|
|
2711
|
+
requestId: payload.requestId,
|
|
2712
|
+
agentRef: payload.agentRef,
|
|
2713
|
+
projectionHash: payload.projectionHash
|
|
2714
|
+
});
|
|
2715
|
+
if (status === void 0) {
|
|
2716
|
+
throw new ByokCloudError(
|
|
2717
|
+
"agent_home_projection_receipt_invalid",
|
|
2718
|
+
`Agent-home projection request ${payload.requestId} disappeared after durable allocation.`
|
|
2719
|
+
);
|
|
2720
|
+
}
|
|
2721
|
+
return { ...control, status };
|
|
2722
|
+
},
|
|
2723
|
+
getAgentHomeProjectionStatus,
|
|
2724
|
+
completeAgentHomeProjection,
|
|
2481
2725
|
async cancelTask(tenant, taskId, reason) {
|
|
2482
2726
|
const stores = tenantStoresFor(controlPlane(tenant), root);
|
|
2483
2727
|
const proposedMessageId = options.crypto.randomUuid();
|
|
@@ -3608,6 +3852,6 @@ var CLOUD_PORT_INTERFACES = {
|
|
|
3608
3852
|
rateLimiter: "InboundRateLimiter"
|
|
3609
3853
|
};
|
|
3610
3854
|
|
|
3611
|
-
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 };
|
|
3855
|
+
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, agentHomeProjectionCompletionKey, agentHomeProjectionRequestKey, approvalTimelineCursor, authenticateBearer, authenticateDeviceProof, authenticateHostedDeviceAssertion, createAuthPlane, createByokCloud, createHmacTokenSigner, createInMemoryBlobs, createInMemoryByokCloud, createInMemoryCloudStores, createWebCrypto, declares, extractBearerToken, fullCapabilityDeclaration, handleInboundEnvelope, isCloudError, isTruthCommitError, parseApprovalObservations, parseTimelineEvents, projectTerminalResult, projectTimelineEvents, readAgentHomeProjectionStatus, recordAgentHomeProjectionCompletion, routeKey, tenantStoresFor, terminalReceiptKey, truthManifestMetadata, truthRecordMetadata, validateActivityAppend, validateApprovalTimelineAppend, verifyNonceSignature };
|
|
3612
3856
|
//# sourceMappingURL=index.js.map
|
|
3613
3857
|
//# sourceMappingURL=index.js.map
|