@byok-sdk/cloud 0.7.0 → 0.8.0

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.
@@ -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 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';
@@ -114,14 +115,28 @@ export interface AgentEgressDispatchInput {
114
115
  readonly taskId?: string;
115
116
  readonly payload: TaskOfferForAgentWithEgressPayload;
116
117
  }
118
+ /** Strict Agent dispatch whose selected runtime mints its session after start. */
119
+ export interface AgentEgressFreshSessionDispatchInput {
120
+ /** Supply one to make the enqueue addressable by the host's own id; otherwise cloud mints one. */
121
+ readonly taskId?: string;
122
+ /** Deliberately session-free strict payload for the fresh-runtime path. */
123
+ readonly payload: TaskOfferForAgentWithEgressFreshPayload;
124
+ }
117
125
  /** A task-free, independently capability-gated Agent content read. */
118
126
  export interface AgentContentReadInput {
119
127
  readonly payload: AgentContentReadPayload;
120
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;
121
133
  export interface EnqueuedAgentControl {
122
134
  readonly seq: number;
123
135
  readonly envelope: Envelope;
124
136
  }
137
+ export interface EnqueuedAgentHomeProjection extends EnqueuedAgentControl {
138
+ readonly status: AgentHomeProjectionReadback;
139
+ }
125
140
  export interface EnqueuedOffer {
126
141
  readonly taskId: string;
127
142
  /** The per-(tenant, device) delivery seq — the daemon's redelivery cursor position for this envelope. */
@@ -165,8 +180,20 @@ export interface ByokCloud {
165
180
  * egress/reliable-ack capabilities reject before a mailbox row is allocated.
166
181
  */
167
182
  enqueueAgentEgressOffer(tenant: TenantId, deviceId: string, input: AgentEgressDispatchInput): Promise<EnqueuedOffer>;
183
+ /**
184
+ * Host control plane: enqueue the distinct fresh-session egress offer.
185
+ * The device must durably advertise fresh-session support before task or
186
+ * mailbox reservation, so older resume-only daemons never receive it.
187
+ */
188
+ enqueueFreshAgentEgressOffer(tenant: TenantId, deviceId: string, input: AgentEgressFreshSessionDispatchInput): Promise<EnqueuedOffer>;
168
189
  /** Host control plane: request one policy-bound content read without a task fallback. */
169
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>;
170
197
  /** Host control plane: durably request cancellation by tenant/task id. Idempotent. */
171
198
  cancelTask(tenant: TenantId, taskId: string, reason?: string): Promise<TaskAttempt>;
172
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, 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, TaskOfferForAgentWithEgressPayloadSchema, TaskOfferForAgentPayloadSchema, AGENT_CONTENT_ARTIFACT_READ_CAPABILITY, AGENT_CONTENT_TRANSCRIPT_READ_CAPABILITY, AGENT_CONTENT_WORKSPACE_READ_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, 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,8 +801,10 @@ 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",
807
+ "agent-egress-fresh-session",
796
808
  "agent-content-workspace-read",
797
809
  "agent-content-transcript-read",
798
810
  "agent-content-artifact-read"
@@ -828,13 +840,13 @@ function eventsHandler(deps) {
828
840
  if (page.messages.length === 0) break;
829
841
  const decoded = page.messages.map((message) => decodeEnvelope(message.body));
830
842
  const offeredTaskIds = decoded.flatMap(
831
- (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] : []
843
+ (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.type === "task.offer_for_agent_with_egress_fresh") && event.task_id !== void 0 ? [event.task_id] : []
832
844
  );
833
845
  const attemptsByTaskId = Object.fromEntries(
834
846
  (await stores.tasks.getMany(offeredTaskIds)).map((attempt2) => [attempt2.taskId, attempt2])
835
847
  );
836
848
  const events = decoded.filter((event) => {
837
- 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") {
849
+ 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" && event.type !== "task.offer_for_agent_with_egress_fresh") {
838
850
  return true;
839
851
  }
840
852
  return event.task_id === void 0 || attemptsByTaskId[event.task_id]?.cancellation === void 0;
@@ -1222,6 +1234,35 @@ function messagesHandler(deps) {
1222
1234
  return c.json(response, 200);
1223
1235
  };
1224
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
+ }
1225
1266
  var DEFAULT_BOARD_PAGE_LIMIT = 50;
1226
1267
  var DEFAULT_BOARD_STREAM_QUERY_INTERVAL_MS = 5e3;
1227
1268
  var DEFAULT_BOARD_STREAM_HEARTBEAT_INTERVAL_MS = 15e3;
@@ -1966,6 +2007,118 @@ var CloudRouteRegistry = class {
1966
2007
  return this.#app.fetch;
1967
2008
  }
1968
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
+ }
1969
2122
  function projectTerminalResult(taskId, receipt) {
1970
2123
  let envelope;
1971
2124
  try {
@@ -2085,6 +2238,13 @@ function createByokCloud(options) {
2085
2238
  })
2086
2239
  );
2087
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
+ );
2088
2248
  if (declares(declaration, CLOUD_CAPABILITIES.boardCoordination)) {
2089
2249
  const boardDeps = {
2090
2250
  ...deviceRouteDeps,
@@ -2309,6 +2469,34 @@ function createByokCloud(options) {
2309
2469
  }
2310
2470
  return { seq: message.seq, envelope };
2311
2471
  }
2472
+ async function getAgentHomeProjectionStatus(tenant, deviceId, input) {
2473
+ return readAgentHomeProjectionStatus(
2474
+ tenantStoresFor(controlPlane(tenant), root).receipts,
2475
+ tenant,
2476
+ deviceId,
2477
+ input
2478
+ );
2479
+ }
2480
+ async function completeAgentHomeProjection(tenant, deviceId, receiptInput) {
2481
+ return completeAgentHomeProjectionFromStores(
2482
+ tenantStoresFor(controlPlane(tenant), root),
2483
+ deviceId,
2484
+ receiptInput
2485
+ );
2486
+ }
2487
+ async function completeAgentHomeProjectionFromStores(stores, deviceId, receiptInput) {
2488
+ const receipt = AgentHomeProjectionCompletionRequestSchema.parse(receiptInput);
2489
+ await assertAgentCapabilities(stores.tenant, deviceId, [
2490
+ AGENT_HOME_CONTRACT_CAPABILITY,
2491
+ AGENT_HOME_PROJECTION_CAPABILITY
2492
+ ]);
2493
+ return recordAgentHomeProjectionCompletion(
2494
+ stores.receipts,
2495
+ stores.tenant,
2496
+ deviceId,
2497
+ receipt
2498
+ );
2499
+ }
2312
2500
  async function enqueueReliableEgressAck(stores, record) {
2313
2501
  const payload = AgentEgressAckPayloadSchema.parse({
2314
2502
  agentRef: record.payload.agentRef,
@@ -2428,6 +2616,22 @@ function createByokCloud(options) {
2428
2616
  (taskId, seq, messageId) => createEnvelope("task.offer_for_agent_with_egress", payload, { id: messageId, taskId, seq })
2429
2617
  );
2430
2618
  },
2619
+ async enqueueFreshAgentEgressOffer(tenant, deviceId, input) {
2620
+ await assertAgentCapabilities(tenant, deviceId, [
2621
+ AGENT_HOME_CONTRACT_CAPABILITY,
2622
+ AGENT_EGRESS_POLICY_CAPABILITY,
2623
+ AGENT_EGRESS_RELIABLE_ACK_CAPABILITY,
2624
+ AGENT_EGRESS_FRESH_SESSION_CAPABILITY
2625
+ ]);
2626
+ const payload = TaskOfferForAgentWithEgressFreshPayloadSchema.parse(input.payload);
2627
+ return enqueueTaskEnvelope(
2628
+ tenant,
2629
+ deviceId,
2630
+ input.taskId,
2631
+ payload.agentRef,
2632
+ (taskId, seq, messageId) => createEnvelope("task.offer_for_agent_with_egress_fresh", payload, { id: messageId, taskId, seq })
2633
+ );
2634
+ },
2431
2635
  async enqueueAgentContentRead(tenant, deviceId, input) {
2432
2636
  const payload = AgentContentReadPayloadSchema.parse(input.payload);
2433
2637
  await assertAgentCapabilities(tenant, deviceId, [
@@ -2461,6 +2665,52 @@ function createByokCloud(options) {
2461
2665
  }
2462
2666
  return control;
2463
2667
  },
2668
+ async enqueueAgentHomeProjection(tenant, deviceId, input) {
2669
+ const payload = AgentHomeProjectionPayloadSchema.parse(input);
2670
+ await assertAgentCapabilities(tenant, deviceId, [
2671
+ AGENT_HOME_CONTRACT_CAPABILITY,
2672
+ AGENT_HOME_PROJECTION_CAPABILITY
2673
+ ]);
2674
+ const stores = tenantStoresFor(controlPlane(tenant), root);
2675
+ const requestBody = JSON.stringify(payload);
2676
+ const persisted = await stores.receipts.record({
2677
+ key: agentHomeProjectionRequestKey(deviceId, payload.requestId),
2678
+ body: requestBody
2679
+ });
2680
+ const persistedPayload = AgentHomeProjectionPayloadSchema.parse(JSON.parse(persisted.receipt.body));
2681
+ if (!sameAgentHomeProjectionRequest(payload, persistedPayload)) {
2682
+ throw new ByokCloudError(
2683
+ "agent_home_projection_request_conflict",
2684
+ `Agent-home projection request ${payload.requestId} already exists with a different immutable desired body.`
2685
+ );
2686
+ }
2687
+ const control = await enqueueAgentControlEnvelope(
2688
+ tenant,
2689
+ deviceId,
2690
+ payload.requestId,
2691
+ (seq) => createEnvelope("agent.home.projection", payload, { id: payload.requestId, seq })
2692
+ );
2693
+ if (control.envelope.type !== "agent.home.projection" || !sameAgentHomeProjectionRequest(payload, control.envelope.payload)) {
2694
+ throw new ByokCloudError(
2695
+ "agent_home_projection_request_conflict",
2696
+ `Mailbox request ${payload.requestId} does not match its immutable Agent-home projection fact.`
2697
+ );
2698
+ }
2699
+ const status = await getAgentHomeProjectionStatus(tenant, deviceId, {
2700
+ requestId: payload.requestId,
2701
+ agentRef: payload.agentRef,
2702
+ projectionHash: payload.projectionHash
2703
+ });
2704
+ if (status === void 0) {
2705
+ throw new ByokCloudError(
2706
+ "agent_home_projection_receipt_invalid",
2707
+ `Agent-home projection request ${payload.requestId} disappeared after durable allocation.`
2708
+ );
2709
+ }
2710
+ return { ...control, status };
2711
+ },
2712
+ getAgentHomeProjectionStatus,
2713
+ completeAgentHomeProjection,
2464
2714
  async cancelTask(tenant, taskId, reason) {
2465
2715
  const stores = tenantStoresFor(controlPlane(tenant), root);
2466
2716
  const proposedMessageId = options.crypto.randomUuid();
@@ -3591,6 +3841,6 @@ var CLOUD_PORT_INTERFACES = {
3591
3841
  rateLimiter: "InboundRateLimiter"
3592
3842
  };
3593
3843
 
3594
- 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 };
3844
+ 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 };
3595
3845
  //# sourceMappingURL=index.js.map
3596
3846
  //# sourceMappingURL=index.js.map