@byok-sdk/cloud 0.18.0 → 0.19.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.
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
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';
1
+ import { BOARD_STATUSES, CapabilityDeclarationSchema, NONCE_SIGNING_DOMAIN, hasCapability, isTenantId, tenantId, principalTenant, parseDeviceProofEnvelope, deviceProofSigningInput, contentHash, parseCapabilityDeclaration, ByokCoreError, tenantKey, PRESENCE_LEVELS, createInMemoryCoreStores, authenticateDeviceAssertion, authenticateTaskAssertion, 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
3
  import { z } from 'zod';
4
- import { AgentEventOrUnknownSchema, AgentMessageServerContextSchema, AgentMessageEgressRequirementSchema, AgentRefSchema, TaskOfferForAgentWithEgressFreshPayloadSchema, PROTOCOL_VERSION, DAEMON_TO_SERVER_TYPES, AGENT_EGRESS_RELIABLE_ACK_CAPABILITY, encodeEnvelope, decodeEnvelope, AgentHomeProjectionCompletionRequestSchema, BYOK_PAIR_PATH, BYOK_CHALLENGE_PATH, BYOK_TOKEN_PATH, BYOK_CAPABILITIES_PATH, BYOK_AGENT_MEMORY_PROJECTIONS_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, AgentMessagePublishPayloadSchema, isTaskOfferType, MESSAGE_PAYLOAD_SCHEMAS, createEnvelope, AgentHomeProjectionPayloadSchema, AgentContentReadPayloadSchema, AGENT_EGRESS_POLICY_CAPABILITY, AGENT_MESSAGE_EGRESS_CAPABILITY, TERMINAL_PROJECTION_SELECTION_CAPABILITY, TaskOfferForAgentWithEgressPayloadSchema, TaskOfferForAgentPayloadSchema, AgentMemoryProjectionMutationSchema, AgentMemoryProjectionReceiptSchema, AGENT_MEMORY_PROJECTION_MAX_ORDERING_VALUE, AgentMemoryProjectionEraseResultSchema, HarnessIdSchema, 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, AgentMemoryProjectionCommitRequestSchema, agentMemoryProjectionBase64UrlByteLength, MAILBOX_READ_AHEAD_MAX_SEQS, MAILBOX_READ_AHEAD_CAPABILITY, MessagesSendRequestSchema, PresencePublishRequestSchema, CreateBlobRequestSchema, byokBlobContentPath, AgentMessageDispositionPayloadSchema, AgentEgressAckPayloadSchema, AgentContentReceiptPayloadSchema } from '@byok-sdk/protocol';
4
+ import { AgentEventOrUnknownSchema, AgentMessageServerContextSchema, AgentMessageEgressRequirementSchema, AgentRefSchema, TaskOfferForAgentWithEgressFreshPayloadSchema, PROTOCOL_VERSION, DAEMON_TO_SERVER_TYPES, AGENT_EGRESS_RELIABLE_ACK_CAPABILITY, encodeEnvelope, decodeEnvelope, AgentHomeProjectionCompletionRequestSchema, AgentInputPreparationPayloadSchema, InputPreparationCompletionRequestSchema, BYOK_PAIR_PATH, BYOK_CHALLENGE_PATH, BYOK_TOKEN_PATH, BYOK_CAPABILITIES_PATH, BYOK_AGENT_MEMORY_PROJECTIONS_PATH, BYOK_EVENTS_PATH, BYOK_MESSAGES_PATH, BYOK_AGENT_HOME_PROJECTION_COMPLETION_ROUTE, BYOK_INPUT_PREPARATION_COMPLETION_ROUTE, BYOK_INPUT_PREPARATION_STATUS_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, AgentMessagePublishPayloadSchema, isTaskOfferType, MESSAGE_PAYLOAD_SCHEMAS, createEnvelope, AgentHomeProjectionPayloadSchema, AgentContentReadPayloadSchema, AGENT_EGRESS_POLICY_CAPABILITY, AGENT_MESSAGE_EGRESS_CAPABILITY, TERMINAL_PROJECTION_SELECTION_CAPABILITY, TaskOfferForAgentWithEgressPayloadSchema, AGENT_INPUT_PREPARATION_CAPABILITY, TaskOfferPreparedPayloadSchema, TaskOfferForAgentPayloadSchema, AgentMemoryProjectionMutationSchema, AgentMemoryProjectionReceiptSchema, AGENT_MEMORY_PROJECTION_MAX_ORDERING_VALUE, AgentMemoryProjectionEraseResultSchema, HarnessIdSchema, 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, AgentMemoryProjectionCommitRequestSchema, agentMemoryProjectionBase64UrlByteLength, MAILBOX_READ_AHEAD_MAX_SEQS, MAILBOX_READ_AHEAD_CAPABILITY, MessagesSendRequestSchema, InputPreparationStatusQuerySchema, PresencePublishRequestSchema, CreateBlobRequestSchema, byokBlobContentPath, AgentMessageDispositionPayloadSchema, AgentEgressAckPayloadSchema, AgentContentReceiptPayloadSchema } from '@byok-sdk/protocol';
5
5
  import { Hono } from 'hono';
6
6
 
7
7
  // src/index.ts
@@ -91,6 +91,16 @@ var CLOUD_ERROR_CODES = {
91
91
  agent_home_projection_receipt_mismatch: "agent_home_projection_receipt_mismatch",
92
92
  /** A receipt-store row at the projection namespace violated the frozen projection schema. */
93
93
  agent_home_projection_receipt_invalid: "agent_home_projection_receipt_invalid",
94
+ /** A remote input-preparation request id already names a different immutable desired request. */
95
+ input_preparation_request_conflict: "input_preparation_request_conflict",
96
+ /** A device completion did not identify a stored desired request for this exact device. */
97
+ input_preparation_request_not_found: "input_preparation_request_not_found",
98
+ /** A device completion changed the first durable terminal outcome. */
99
+ input_preparation_completion_conflict: "input_preparation_completion_conflict",
100
+ /** A completion did not exactly echo its immutable desired request/Agent/policy binding. */
101
+ input_preparation_receipt_mismatch: "input_preparation_receipt_mismatch",
102
+ /** A receipt-store row at the preparation namespace violated the frozen schema. */
103
+ input_preparation_receipt_invalid: "input_preparation_receipt_invalid",
94
104
  /** A hosted Agent-memory mutation did not match the durable task/device/AgentRef binding. */
95
105
  agent_memory_projection_task_mismatch: "agent_memory_projection_task_mismatch",
96
106
  /** The embedder-owned grant/consent authority denied a hosted memory mutation. */
@@ -1196,7 +1206,43 @@ var CLOUD_CAPABILITIES = {
1196
1206
  */
1197
1207
  skillPacks: "skills.pack",
1198
1208
  /** Optional, one-way redacted Agent-memory snapshot mutation route. */
1199
- agentMemoryProjection: "agent.memory.projection"
1209
+ agentMemoryProjection: "agent.memory.projection",
1210
+ /**
1211
+ * Remote authenticated runtime input preparation (C07 G4): the host control
1212
+ * plane enqueues `agent.input.preparation` and the device discharges it
1213
+ * through the completion/status pair.
1214
+ *
1215
+ * Informational like `host-mcp-task-context`, not route-gating. Both routes
1216
+ * mount unconditionally (`cloud.ts`) because the completion route is the
1217
+ * DEVICE's only way to discharge a mailbox row this same deployment handed
1218
+ * it — withholding it would strand the device's redelivery cursor rather
1219
+ * than degrade a feature. For the same reason the completion route asserts
1220
+ * no DEVICE capability either: the device-level `agent-input-preparation`
1221
+ * flag gates ADMISSION (`enqueueInputPreparation`) and nothing else, so an
1222
+ * unconfigured device is refused a row instead of being handed one whose
1223
+ * only honest answer — `input_preparation_unconfigured` — it could not then
1224
+ * record. What declaring THIS capability promises is that this deployment's
1225
+ * host side actually drives the lane, which is what a Host reads before
1226
+ * calling `enqueueInputPreparation` instead of probing.
1227
+ */
1228
+ inputPreparation: "agent.input.preparation",
1229
+ /**
1230
+ * Contract §8.1's capability gate for task-scoped tool authority
1231
+ * (`byok-task-assertion-v1`), deployment-level channel.
1232
+ *
1233
+ * The SAME literal name `@byok-sdk/protocol`'s
1234
+ * `HOST_MCP_TASK_CONTEXT_CAPABILITY` carries on the device-level channel —
1235
+ * §8.1 requires both to be in place, and a name spelled differently in the
1236
+ * two would make "both" unverifiable.
1237
+ *
1238
+ * Unlike its siblings above this capability mounts no route in this package:
1239
+ * what a deployment promises by declaring it is that its host side actually
1240
+ * VERIFIES task assertions (`authenticateHostedTaskAssertion` plus the frozen
1241
+ * offer check that only the host can make). That is why it is default-off
1242
+ * below and not derivable from anything this package can inspect — §8.2(1):
1243
+ * the capability is declared only once it is completely implemented.
1244
+ */
1245
+ hostMcpTaskContext: "host-mcp-task-context"
1200
1246
  };
1201
1247
  var CapabilitiesResponseSchema = CapabilityDeclarationSchema;
1202
1248
  function fullCapabilityDeclaration(version = 1, options = {}) {
@@ -1209,6 +1255,9 @@ function fullCapabilityDeclaration(version = 1, options = {}) {
1209
1255
  if (capability === CLOUD_CAPABILITIES.agentMemoryProjection) {
1210
1256
  return options.includeAgentMemoryProjection === true;
1211
1257
  }
1258
+ if (capability === CLOUD_CAPABILITIES.hostMcpTaskContext) {
1259
+ return options.includeHostMcpTaskContext === true;
1260
+ }
1212
1261
  return true;
1213
1262
  })
1214
1263
  };
@@ -1713,15 +1762,13 @@ function eventsHandler(deps) {
1713
1762
  if (page.messages.length === 0) break;
1714
1763
  const decoded = page.messages.map((message) => decodeEnvelope(message.body));
1715
1764
  const offeredTaskIds = decoded.flatMap(
1716
- (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] : []
1765
+ (event) => isTaskOfferType(event.type) && event.task_id !== void 0 ? [event.task_id] : []
1717
1766
  );
1718
1767
  const attemptsByTaskId = Object.fromEntries(
1719
1768
  (await stores.tasks.getMany(offeredTaskIds)).map((attempt2) => [attempt2.taskId, attempt2])
1720
1769
  );
1721
1770
  const events = decoded.filter((event) => {
1722
- 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") {
1723
- return true;
1724
- }
1771
+ if (!isTaskOfferType(event.type)) return true;
1725
1772
  return event.task_id === void 0 || attemptsByTaskId[event.task_id]?.cancellation === void 0;
1726
1773
  });
1727
1774
  if (events.length === 0 && page.hasMore) {
@@ -1824,6 +1871,63 @@ function agentHomeProjectionCompletionHandler(deps) {
1824
1871
  }
1825
1872
  };
1826
1873
  }
1874
+ function mapCloudError(c, error) {
1875
+ if (isCloudError(error, "input_preparation_request_not_found")) {
1876
+ return c.json({ error: error.code }, 404);
1877
+ }
1878
+ if (isCloudError(error, "input_preparation_receipt_mismatch") || isCloudError(error, "input_preparation_receipt_invalid")) {
1879
+ return c.json({ error: error.code }, 422);
1880
+ }
1881
+ if (isCloudError(error, "input_preparation_request_conflict") || isCloudError(error, "input_preparation_completion_conflict")) {
1882
+ return c.json({ error: error.code }, 409);
1883
+ }
1884
+ throw error;
1885
+ }
1886
+ function inputPreparationCompletionHandler(deps) {
1887
+ return async (c) => {
1888
+ const authenticated = await authenticateDevice(c, deps);
1889
+ if (authenticated === void 0) return c.json({ error: "unauthorized" }, 401);
1890
+ const parsed = InputPreparationCompletionRequestSchema.safeParse(await readJsonBody(c));
1891
+ if (!parsed.success) return c.json({ error: "invalid input preparation completion" }, 422);
1892
+ const requestId = c.req.param("requestId");
1893
+ if (requestId === void 0 || requestId !== parsed.data.requestId) {
1894
+ return c.json({ error: "input_preparation_receipt_mismatch" }, 422);
1895
+ }
1896
+ try {
1897
+ return c.json(
1898
+ await deps.complete(authenticated.stores, authenticated.device.deviceId, parsed.data),
1899
+ 200
1900
+ );
1901
+ } catch (error) {
1902
+ return mapCloudError(c, error);
1903
+ }
1904
+ };
1905
+ }
1906
+ function inputPreparationStatusHandler(deps) {
1907
+ return async (c) => {
1908
+ const authenticated = await authenticateDevice(c, deps);
1909
+ if (authenticated === void 0) return c.json({ error: "unauthorized" }, 401);
1910
+ const requestId = c.req.param("requestId");
1911
+ if (requestId === void 0 || requestId.length === 0) {
1912
+ return c.json({ error: "invalid input preparation request id" }, 422);
1913
+ }
1914
+ const query = InputPreparationStatusQuerySchema.safeParse({
1915
+ agentId: c.req.query("agentId"),
1916
+ profileRevision: c.req.query("profileRevision")
1917
+ });
1918
+ if (!query.success) return c.json({ error: "invalid input preparation status query" }, 422);
1919
+ try {
1920
+ const readback = await deps.status(authenticated.stores, authenticated.device.deviceId, {
1921
+ requestId,
1922
+ agentRef: { agentId: query.data.agentId, profileRevision: query.data.profileRevision }
1923
+ });
1924
+ if (readback === void 0) return c.json({ error: "input_preparation_request_not_found" }, 404);
1925
+ return c.json(readback, 200);
1926
+ } catch (error) {
1927
+ return mapCloudError(c, error);
1928
+ }
1929
+ };
1930
+ }
1827
1931
  var DEFAULT_MAX_AGENT_MEMORY_PROJECTION_REQUEST_BYTES = 1 * 1024 * 1024;
1828
1932
  function agentMemoryProjectionHandler(deps) {
1829
1933
  return async (c) => {
@@ -2710,6 +2814,128 @@ async function recordAgentHomeProjectionCompletion(receipts, tenant, deviceId, r
2710
2814
  completedAt: storedCompletion.receipt.recordedAt
2711
2815
  };
2712
2816
  }
2817
+ function inputPreparationRequestKey(deviceId, agentRef, requestId) {
2818
+ return agentReliabilityKey("agent-input-preparation-request", deviceId, agentRef, requestId);
2819
+ }
2820
+ function inputPreparationCompletionKey(deviceId, agentRef, requestId) {
2821
+ return agentReliabilityKey("agent-input-preparation-completion", deviceId, agentRef, requestId);
2822
+ }
2823
+ function sameInputPreparationRequest(expected, actual) {
2824
+ return canonicalRequestBody(expected) === canonicalRequestBody(actual);
2825
+ }
2826
+ function canonicalRequestBody(payload) {
2827
+ return JSON.stringify(AgentInputPreparationPayloadSchema.parse(payload));
2828
+ }
2829
+ function receiptMatchesInputPreparation(request, receipt) {
2830
+ return receipt.requestId === request.requestId && receipt.agentRef.agentId === request.agentRef.agentId && receipt.agentRef.profileRevision === request.agentRef.profileRevision && receipt.profileId === request.profileId && receipt.policyRevision === request.policyRevision;
2831
+ }
2832
+ function statusInputMatchesInputPreparation(request, input) {
2833
+ return input.requestId === request.requestId && input.agentRef.agentId === request.agentRef.agentId && input.agentRef.profileRevision === request.agentRef.profileRevision;
2834
+ }
2835
+ function parseRequestBody2(body) {
2836
+ try {
2837
+ return AgentInputPreparationPayloadSchema.parse(JSON.parse(body));
2838
+ } catch (error) {
2839
+ throw new ByokCloudError(
2840
+ "input_preparation_receipt_invalid",
2841
+ "Stored input-preparation request is not a valid immutable desired fact.",
2842
+ { cause: error }
2843
+ );
2844
+ }
2845
+ }
2846
+ function parseCompletionBody2(body) {
2847
+ try {
2848
+ return InputPreparationCompletionRequestSchema.parse(JSON.parse(body));
2849
+ } catch (error) {
2850
+ throw new ByokCloudError(
2851
+ "input_preparation_receipt_invalid",
2852
+ "Stored input-preparation completion is not a valid immutable receipt fact.",
2853
+ { cause: error }
2854
+ );
2855
+ }
2856
+ }
2857
+ function terminalReadback(tenant, deviceId, request, completion, completedAt) {
2858
+ const common = {
2859
+ tenantId: tenant,
2860
+ deviceId,
2861
+ requestId: request.requestId,
2862
+ agentRef: request.agentRef,
2863
+ profileId: request.profileId,
2864
+ policyRevision: request.policyRevision,
2865
+ completedAt
2866
+ };
2867
+ return completion.outcome === "prepared" ? { ...common, status: "prepared", receipt: completion.receipt } : { ...common, status: "rejected", reason: completion.reason };
2868
+ }
2869
+ async function readInputPreparationStatus(receipts, tenant, deviceId, input) {
2870
+ const storedRequest = await receipts.get(inputPreparationRequestKey(deviceId, input.agentRef, input.requestId));
2871
+ if (storedRequest === void 0) return void 0;
2872
+ const request = parseRequestBody2(storedRequest.body);
2873
+ if (!statusInputMatchesInputPreparation(request, input)) {
2874
+ throw new ByokCloudError(
2875
+ "input_preparation_request_conflict",
2876
+ `Input-preparation request ${input.requestId} does not match its immutable desired fact.`
2877
+ );
2878
+ }
2879
+ const storedCompletion = await receipts.get(
2880
+ inputPreparationCompletionKey(deviceId, request.agentRef, input.requestId)
2881
+ );
2882
+ if (storedCompletion === void 0) {
2883
+ return {
2884
+ tenantId: tenant,
2885
+ deviceId,
2886
+ requestId: request.requestId,
2887
+ agentRef: request.agentRef,
2888
+ profileId: request.profileId,
2889
+ policyRevision: request.policyRevision,
2890
+ status: "pending"
2891
+ };
2892
+ }
2893
+ const completion = parseCompletionBody2(storedCompletion.body);
2894
+ if (!receiptMatchesInputPreparation(request, completion)) {
2895
+ throw new ByokCloudError(
2896
+ "input_preparation_receipt_mismatch",
2897
+ `Input-preparation completion ${input.requestId} does not match its immutable desired fact.`
2898
+ );
2899
+ }
2900
+ return terminalReadback(tenant, deviceId, request, completion, storedCompletion.recordedAt);
2901
+ }
2902
+ async function recordInputPreparationCompletion(receipts, tenant, deviceId, receiptInput) {
2903
+ const receipt = InputPreparationCompletionRequestSchema.parse(receiptInput);
2904
+ const storedRequest = await receipts.get(
2905
+ inputPreparationRequestKey(deviceId, receipt.agentRef, receipt.requestId)
2906
+ );
2907
+ if (storedRequest === void 0) {
2908
+ throw new ByokCloudError(
2909
+ "input_preparation_request_not_found",
2910
+ `Input-preparation request ${receipt.requestId} was not found for this device.`
2911
+ );
2912
+ }
2913
+ const request = parseRequestBody2(storedRequest.body);
2914
+ if (!receiptMatchesInputPreparation(request, receipt)) {
2915
+ throw new ByokCloudError(
2916
+ "input_preparation_receipt_mismatch",
2917
+ `Input-preparation completion ${receipt.requestId} does not exactly match its desired fact.`
2918
+ );
2919
+ }
2920
+ const body = JSON.stringify(receipt);
2921
+ const storedCompletion = await receipts.record({
2922
+ key: inputPreparationCompletionKey(deviceId, request.agentRef, receipt.requestId),
2923
+ body
2924
+ });
2925
+ if (!storedCompletion.created && storedCompletion.receipt.body !== body) {
2926
+ throw new ByokCloudError(
2927
+ "input_preparation_completion_conflict",
2928
+ `Input-preparation request ${receipt.requestId} already has a different terminal completion.`
2929
+ );
2930
+ }
2931
+ return terminalReadback(
2932
+ tenant,
2933
+ deviceId,
2934
+ request,
2935
+ parseCompletionBody2(storedCompletion.receipt.body),
2936
+ storedCompletion.receipt.recordedAt
2937
+ );
2938
+ }
2713
2939
  function readDeviceTerminalReceipt(taskId, receipt) {
2714
2940
  const envelope = decodeEnvelope(receipt.body);
2715
2941
  if (envelope.task_id !== taskId || envelope.type !== "task.complete" && envelope.type !== "task.fail" && envelope.type !== "task.decline" && envelope.type !== "task.cancelled") {
@@ -2886,6 +3112,19 @@ function createByokCloud(options) {
2886
3112
  complete: (stores, deviceId, receipt) => completeAgentHomeProjectionFromStores(stores, deviceId, receipt)
2887
3113
  })
2888
3114
  );
3115
+ const inputPreparationRouteDeps = {
3116
+ ...deviceRouteDeps,
3117
+ complete: (stores, deviceId, receipt) => completeInputPreparationFromStores(stores, deviceId, receipt),
3118
+ status: (stores, deviceId, input) => readInputPreparationStatus(stores.receipts, stores.tenant, deviceId, input)
3119
+ };
3120
+ registry.register(
3121
+ { method: "PUT", path: BYOK_INPUT_PREPARATION_COMPLETION_ROUTE, class: "device" },
3122
+ inputPreparationCompletionHandler(inputPreparationRouteDeps)
3123
+ );
3124
+ registry.register(
3125
+ { method: "GET", path: BYOK_INPUT_PREPARATION_STATUS_ROUTE, class: "device" },
3126
+ inputPreparationStatusHandler(inputPreparationRouteDeps)
3127
+ );
2889
3128
  if (declares(declaration, CLOUD_CAPABILITIES.boardCoordination)) {
2890
3129
  const boardDeps = {
2891
3130
  ...deviceRouteDeps,
@@ -3396,6 +3635,25 @@ function createByokCloud(options) {
3396
3635
  receipt
3397
3636
  );
3398
3637
  }
3638
+ async function getInputPreparationStatus(tenant, deviceId, input) {
3639
+ return readInputPreparationStatus(
3640
+ tenantStoresFor(controlPlane(tenant), root).receipts,
3641
+ tenant,
3642
+ deviceId,
3643
+ input
3644
+ );
3645
+ }
3646
+ async function completeInputPreparation(tenant, deviceId, receiptInput) {
3647
+ return completeInputPreparationFromStores(
3648
+ tenantStoresFor(controlPlane(tenant), root),
3649
+ deviceId,
3650
+ receiptInput
3651
+ );
3652
+ }
3653
+ async function completeInputPreparationFromStores(stores, deviceId, receiptInput) {
3654
+ const receipt = InputPreparationCompletionRequestSchema.parse(receiptInput);
3655
+ return recordInputPreparationCompletion(stores.receipts, stores.tenant, deviceId, receipt);
3656
+ }
3399
3657
  async function commitAgentMemoryProjectionFromStores(stores, deviceId, mutationInput, redactedBytes) {
3400
3658
  const mutation = AgentMemoryProjectionCommitRequestSchema.parse(mutationInput);
3401
3659
  const attempt = await stores.tasks.get(mutation.taskId);
@@ -3602,6 +3860,21 @@ function createByokCloud(options) {
3602
3860
  (taskId, seq, messageId) => createEnvelope("task.offer_for_agent", payload, { id: messageId, taskId, seq })
3603
3861
  );
3604
3862
  },
3863
+ async enqueuePreparedOffer(tenant, deviceId, input) {
3864
+ await assertAgentCapabilities(tenant, deviceId, [
3865
+ AGENT_HOME_CONTRACT_CAPABILITY,
3866
+ AGENT_INPUT_PREPARATION_CAPABILITY,
3867
+ ...input.payload.terminalProjection === void 0 ? [] : [TERMINAL_PROJECTION_SELECTION_CAPABILITY]
3868
+ ]);
3869
+ const payload = TaskOfferPreparedPayloadSchema.parse(input.payload);
3870
+ return enqueueTaskEnvelope(
3871
+ tenant,
3872
+ deviceId,
3873
+ input.taskId,
3874
+ payload.agentRef,
3875
+ (taskId, seq, messageId) => createEnvelope("task.offer_prepared", payload, { id: messageId, taskId, seq })
3876
+ );
3877
+ },
3605
3878
  async enqueueAgentEgressOffer(tenant, deviceId, input) {
3606
3879
  await assertAgentCapabilities(tenant, deviceId, [
3607
3880
  AGENT_HOME_CONTRACT_CAPABILITY,
@@ -3730,6 +4003,58 @@ function createByokCloud(options) {
3730
4003
  },
3731
4004
  getAgentHomeProjectionStatus,
3732
4005
  completeAgentHomeProjection,
4006
+ async enqueueInputPreparation(tenant, deviceId, input) {
4007
+ const payload = AgentInputPreparationPayloadSchema.parse(input);
4008
+ await assertAgentCapabilities(tenant, deviceId, [
4009
+ AGENT_HOME_CONTRACT_CAPABILITY,
4010
+ AGENT_INPUT_PREPARATION_CAPABILITY
4011
+ ]);
4012
+ const stores = tenantStoresFor(controlPlane(tenant), root);
4013
+ const requestBody = JSON.stringify(payload);
4014
+ const persisted = await stores.receipts.record({
4015
+ key: inputPreparationRequestKey(deviceId, payload.agentRef, payload.requestId),
4016
+ body: requestBody
4017
+ });
4018
+ const persistedPayload = AgentInputPreparationPayloadSchema.parse(JSON.parse(persisted.receipt.body));
4019
+ if (!sameInputPreparationRequest(payload, persistedPayload)) {
4020
+ throw new ByokCloudError(
4021
+ "input_preparation_request_conflict",
4022
+ `Input-preparation request ${payload.requestId} already exists with a different immutable desired body.`
4023
+ );
4024
+ }
4025
+ const messageId = await agentControlEnvelopeId(
4026
+ "byok:agent-input-preparation",
4027
+ tenant,
4028
+ deviceId,
4029
+ payload.agentRef,
4030
+ payload.requestId
4031
+ );
4032
+ const control = await enqueueAgentControlEnvelope(
4033
+ tenant,
4034
+ deviceId,
4035
+ messageId,
4036
+ (seq) => createEnvelope("agent.input.preparation", payload, { id: messageId, seq })
4037
+ );
4038
+ if (control.envelope.type !== "agent.input.preparation" || !sameInputPreparationRequest(payload, control.envelope.payload)) {
4039
+ throw new ByokCloudError(
4040
+ "input_preparation_request_conflict",
4041
+ `Mailbox request ${payload.requestId} does not match its immutable input-preparation fact.`
4042
+ );
4043
+ }
4044
+ const status = await getInputPreparationStatus(tenant, deviceId, {
4045
+ requestId: payload.requestId,
4046
+ agentRef: payload.agentRef
4047
+ });
4048
+ if (status === void 0) {
4049
+ throw new ByokCloudError(
4050
+ "input_preparation_receipt_invalid",
4051
+ `Input-preparation request ${payload.requestId} disappeared after durable allocation.`
4052
+ );
4053
+ }
4054
+ return { ...control, status };
4055
+ },
4056
+ getInputPreparationStatus,
4057
+ completeInputPreparation,
3733
4058
  eraseAgentMemoryProjection,
3734
4059
  approveTask(tenant, taskId, opts) {
3735
4060
  return resolveApproval(tenant, taskId, "approve", opts);
@@ -5142,6 +5467,28 @@ function authenticateHostedDeviceAssertion(input, deps) {
5142
5467
  ...deps.maxLifetimeMs === void 0 ? {} : { maxLifetimeMs: deps.maxLifetimeMs }
5143
5468
  });
5144
5469
  }
5470
+ function authenticateHostedTaskAssertion(input, deps) {
5471
+ return authenticateTaskAssertion(input, {
5472
+ verifier: {
5473
+ verify: ({ publicKey, signingInput, signature }) => deps.crypto.verifyEd25519(publicKey, signingInput, signature)
5474
+ },
5475
+ lookupDevice: async (deviceId) => {
5476
+ const row = await deps.devices.resolveByDeviceId(deviceId);
5477
+ if (row === void 0) return void 0;
5478
+ return {
5479
+ tenantId: row.tenantId,
5480
+ productId: row.productId,
5481
+ deviceId: row.deviceId,
5482
+ publicKeyJwkX: row.devicePublicKey,
5483
+ revoked: row.revoked
5484
+ };
5485
+ },
5486
+ replay: deps.replay,
5487
+ expected: deps.expected,
5488
+ now: deps.clock.now(),
5489
+ ...deps.maxLifetimeMs === void 0 ? {} : { maxLifetimeMs: deps.maxLifetimeMs }
5490
+ });
5491
+ }
5145
5492
  var BoardFeedItemSchema = z.object({
5146
5493
  tenantId: z.string(),
5147
5494
  itemId: z.string(),
@@ -5325,6 +5672,6 @@ var CLOUD_PORT_INTERFACES = {
5325
5672
  rateLimiter: "InboundRateLimiter"
5326
5673
  };
5327
5674
 
5328
- 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, InMemoryAgentMemoryProjectionAuthorizer, InMemoryAgentMemoryProjectionStore, 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, RecurringExecutionInputSchema, StaleApprovalError, SteerRejectedError, 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, activitySourceBatchState, agentHomeProjectionCompletionKey, agentHomeProjectionRequestKey, approvalTimelineCursor, assertTaskAttemptListLimit, authenticateBearer, authenticateDeviceProof, authenticateHostedDeviceAssertion, createAuthPlane, createByokCloud, createHmacTokenSigner, createInMemoryBlobs, createInMemoryByokCloud, createInMemoryCloudStores, createWebCrypto, declares, extractBearerToken, fullCapabilityDeclaration, handleInboundEnvelope, isCloudError, isTruthCommitError, parseApprovalObservations, parseTimelineEvents, pendingApproval, projectTerminalResult, projectTimelineEvents, readAgentHomeProjectionStatus, recordAgentHomeProjectionCompletion, routeKey, tenantStoresFor, terminalReceiptKey, truthManifestMetadata, truthRecordMetadata, validateActivityAppend, validateApprovalTimelineAppend, validateApprovalTimelineResolve, verifyNonceSignature };
5675
+ 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, InMemoryAgentMemoryProjectionAuthorizer, InMemoryAgentMemoryProjectionStore, 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, RecurringExecutionInputSchema, StaleApprovalError, SteerRejectedError, 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, activitySourceBatchState, agentHomeProjectionCompletionKey, agentHomeProjectionRequestKey, approvalTimelineCursor, assertTaskAttemptListLimit, authenticateBearer, authenticateDeviceProof, authenticateHostedDeviceAssertion, authenticateHostedTaskAssertion, createAuthPlane, createByokCloud, createHmacTokenSigner, createInMemoryBlobs, createInMemoryByokCloud, createInMemoryCloudStores, createWebCrypto, declares, extractBearerToken, fullCapabilityDeclaration, handleInboundEnvelope, inputPreparationCompletionKey, inputPreparationRequestKey, isCloudError, isTruthCommitError, parseApprovalObservations, parseTimelineEvents, pendingApproval, projectTerminalResult, projectTimelineEvents, readAgentHomeProjectionStatus, readInputPreparationStatus, recordAgentHomeProjectionCompletion, recordInputPreparationCompletion, routeKey, sameInputPreparationRequest, tenantStoresFor, terminalReceiptKey, truthManifestMetadata, truthRecordMetadata, validateActivityAppend, validateApprovalTimelineAppend, validateApprovalTimelineResolve, verifyNonceSignature };
5329
5676
  //# sourceMappingURL=index.js.map
5330
5677
  //# sourceMappingURL=index.js.map