@byok-sdk/cloud 0.17.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.
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Durable remote input-preparation facts.
3
+ *
4
+ * Exactly the composition `agent-home-projections.ts` uses, for exactly the
5
+ * same reason: the desired request and the terminal completion are two
6
+ * IMMUTABLE first-write-wins receipts in the tenant-scoped receipt store, so
7
+ * this module needs no second mutable authority merely to survive a restart,
8
+ * and a replayed write is decided by comparing bodies rather than by trusting
9
+ * whichever writer arrived last.
10
+ *
11
+ * The one idempotency key is `(deviceId, agentRef, requestId)`, minted by the
12
+ * Host and carried unchanged through the cloud receipt, the device's durable
13
+ * namespace and the completion. A Host that times out therefore RE-READS
14
+ * status; it never mints a second requestId for the same turn, which is what
15
+ * keeps a duplicate from becoming a second counter call downstream.
16
+ */
17
+ import { type AgentInputPreparationPayload, type InputPreparationCompletionRequest, type InputPreparationReadback } from '@byok-sdk/protocol';
18
+ import type { TenantId } from '@byok-sdk/core';
19
+ import type { TenantBoundReceipts } from './tenant-stores';
20
+ /** Exact request identity a host must echo to read back durable preparation status. */
21
+ export interface InputPreparationReceiptInput {
22
+ readonly requestId: string;
23
+ readonly agentRef: AgentInputPreparationPayload['agentRef'];
24
+ }
25
+ export declare function inputPreparationRequestKey(deviceId: string, agentRef: AgentInputPreparationPayload['agentRef'], requestId: string): string;
26
+ export declare function inputPreparationCompletionKey(deviceId: string, agentRef: AgentInputPreparationPayload['agentRef'], requestId: string): string;
27
+ /**
28
+ * Whole-body equality, not a field subset.
29
+ *
30
+ * The desired fact is the ENTIRE authorized request — source digest, model
31
+ * selection, deadline, context and required toolsets alike. Comparing only the
32
+ * identity fields would let the same requestId silently re-bind to a different
33
+ * model, a different context or a looser deadline, which is precisely the
34
+ * substitution the immutable receipt exists to prevent. Both sides are already
35
+ * schema-parsed, so key order is the only degree of freedom left, and the
36
+ * stored body is re-serialized from a parse for that reason.
37
+ */
38
+ export declare function sameInputPreparationRequest(expected: AgentInputPreparationPayload, actual: AgentInputPreparationPayload): boolean;
39
+ export declare function receiptMatchesInputPreparation(request: AgentInputPreparationPayload, receipt: InputPreparationCompletionRequest): boolean;
40
+ export declare function statusInputMatchesInputPreparation(request: AgentInputPreparationPayload, input: InputPreparationReceiptInput): boolean;
41
+ export declare function readInputPreparationStatus(receipts: TenantBoundReceipts, tenant: TenantId, deviceId: string, input: InputPreparationReceiptInput): Promise<InputPreparationReadback | undefined>;
42
+ export declare function recordInputPreparationCompletion(receipts: TenantBoundReceipts, tenant: TenantId, deviceId: string, receiptInput: InputPreparationCompletionRequest): Promise<InputPreparationReadback>;
@@ -0,0 +1,121 @@
1
+ import { z } from 'zod';
2
+ /** Persist this validated input before dispatch; the Host owns Turn/generation and outbox. */
3
+ export declare const RecurringExecutionInputSchema: z.ZodObject<{
4
+ taskId: z.ZodString;
5
+ deviceId: z.ZodString;
6
+ payload: z.ZodObject<{
7
+ instruction: z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
8
+ blobRef: z.ZodObject<{
9
+ blobId: z.ZodString;
10
+ contentHash: z.ZodString;
11
+ size: z.ZodNumber;
12
+ contentType: z.ZodString;
13
+ url: z.ZodOptional<z.ZodString>;
14
+ }, z.core.$strip>;
15
+ }, z.core.$strict>]>;
16
+ policy: z.ZodObject<{
17
+ mode: z.ZodEnum<{
18
+ auto: "auto";
19
+ confirm: "confirm";
20
+ plan: "plan";
21
+ readonly: "readonly";
22
+ }>;
23
+ allowTools: z.ZodOptional<z.ZodArray<z.ZodString>>;
24
+ denyTools: z.ZodOptional<z.ZodArray<z.ZodString>>;
25
+ workspaceRoot: z.ZodOptional<z.ZodString>;
26
+ network: z.ZodOptional<z.ZodBoolean>;
27
+ }, z.core.$strict>;
28
+ agentRef: z.ZodObject<{
29
+ agentId: z.ZodString;
30
+ profileRevision: z.ZodString;
31
+ }, z.core.$strict>;
32
+ requiredToolsets: z.ZodOptional<z.ZodArray<z.ZodString>>;
33
+ runtime: z.ZodNonOptional<z.ZodOptional<z.ZodEnum<{
34
+ claude: "claude";
35
+ codex: "codex";
36
+ pi: "pi";
37
+ }>>>;
38
+ harnessId: z.ZodOptional<z.ZodString>;
39
+ dispatchSelection: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
40
+ lane: z.ZodLiteral<"subscription">;
41
+ runtimeId: z.ZodEnum<{
42
+ claude: "claude";
43
+ codex: "codex";
44
+ }>;
45
+ providerId: z.ZodNull;
46
+ modelId: z.ZodString;
47
+ }, z.core.$strict>, z.ZodObject<{
48
+ lane: z.ZodLiteral<"byok">;
49
+ runtimeId: z.ZodLiteral<"pi">;
50
+ providerId: z.ZodString;
51
+ modelId: z.ZodString;
52
+ }, z.core.$strict>, z.ZodObject<{
53
+ lane: z.ZodLiteral<"byok-profile">;
54
+ runtimeId: z.ZodLiteral<"pi">;
55
+ providerProfile: z.ZodObject<{
56
+ profileRef: z.ZodString;
57
+ profileRevision: z.ZodString;
58
+ profileHash: z.ZodString;
59
+ modelId: z.ZodString;
60
+ requiredCapabilities: z.ZodArray<z.ZodEnum<{
61
+ "image-input": "image-input";
62
+ }>>;
63
+ }, z.core.$strict>;
64
+ }, z.core.$strict>], "lane">>;
65
+ terminalProjection: z.ZodNonOptional<z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
66
+ mode: z.ZodLiteral<"none">;
67
+ }, z.core.$strict>, z.ZodObject<{
68
+ mode: z.ZodLiteral<"result-document">;
69
+ contract: z.ZodString;
70
+ }, z.core.$strict>], "mode">>>;
71
+ limits: z.ZodOptional<z.ZodObject<{
72
+ maxDurationMs: z.ZodOptional<z.ZodNumber>;
73
+ maxTokens: z.ZodOptional<z.ZodNumber>;
74
+ }, z.core.$strip>>;
75
+ egressPolicy: z.ZodObject<{
76
+ policyRevision: z.ZodString;
77
+ activity: z.ZodDiscriminatedUnion<[z.ZodObject<{
78
+ mode: z.ZodLiteral<"metadata-status">;
79
+ delivery: z.ZodLiteral<"latest-value">;
80
+ }, z.core.$strict>, z.ZodObject<{
81
+ mode: z.ZodLiteral<"contentful-trajectory">;
82
+ delivery: z.ZodLiteral<"latest-value">;
83
+ maxCoalesceMs: z.ZodNumber;
84
+ maxEventBytes: z.ZodNumber;
85
+ }, z.core.$strict>], "mode">;
86
+ reliable: z.ZodObject<{
87
+ maxPendingEventsPerAgent: z.ZodNumber;
88
+ maxPendingBytesPerAgent: z.ZodNumber;
89
+ maxPendingBytesPerTenant: z.ZodNumber;
90
+ }, z.core.$strict>;
91
+ transfers: z.ZodObject<{
92
+ workspace: z.ZodUnion<readonly [z.ZodLiteral<"disabled">, z.ZodObject<{
93
+ maxBytes: z.ZodNumber;
94
+ allowedMimeTypes: z.ZodArray<z.ZodString>;
95
+ }, z.core.$strict>]>;
96
+ transcript: z.ZodUnion<readonly [z.ZodLiteral<"disabled">, z.ZodObject<{
97
+ maxBytes: z.ZodNumber;
98
+ allowedMimeTypes: z.ZodArray<z.ZodString>;
99
+ }, z.core.$strict>]>;
100
+ artifact: z.ZodUnion<readonly [z.ZodLiteral<"disabled">, z.ZodObject<{
101
+ maxBytes: z.ZodNumber;
102
+ allowedMimeTypes: z.ZodArray<z.ZodString>;
103
+ }, z.core.$strict>]>;
104
+ }, z.core.$strict>;
105
+ }, z.core.$strict>;
106
+ messageEgress: z.ZodNonOptional<z.ZodOptional<z.ZodObject<{
107
+ mode: z.ZodLiteral<"required">;
108
+ contract: z.ZodString;
109
+ contentType: z.ZodEnum<{
110
+ "text/markdown": "text/markdown";
111
+ "text/plain": "text/plain";
112
+ }>;
113
+ maxBytes: z.ZodNumber;
114
+ }, z.core.$strict>>>;
115
+ }, z.core.$strict>;
116
+ agentMessageContext: z.ZodObject<{
117
+ destinationBinding: z.ZodString;
118
+ freshnessCursor: z.ZodOptional<z.ZodString>;
119
+ }, z.core.$strict>;
120
+ }, z.core.$strict>;
121
+ export type RecurringExecutionInput = z.infer<typeof RecurringExecutionInputSchema>;
@@ -43,6 +43,10 @@ export declare class InMemoryTaskAttemptStore implements TaskAttemptStore {
43
43
  readonly messageId: string;
44
44
  readonly payloadBody: string;
45
45
  }): Promise<'reserved' | 'pending' | 'rejected'>;
46
+ readTaskAgentMessage(tenant: TenantId, input: {
47
+ readonly taskId: string;
48
+ readonly deviceId: string;
49
+ }): Promise<AgentMessageAdmission | undefined>;
46
50
  readAgentMessage(tenant: TenantId, input: {
47
51
  readonly taskId: string;
48
52
  readonly deviceId: string;
@@ -331,6 +331,11 @@ export interface TaskAttemptStore {
331
331
  readonly messageId: string;
332
332
  readonly payloadBody: string;
333
333
  }): Promise<'reserved' | 'pending' | 'rejected'>;
334
+ /** Discover the unique immutable message for a tenant/device/task; caller validates its frozen Agent binding. */
335
+ readTaskAgentMessage(tenant: TenantId, input: {
336
+ readonly taskId: string;
337
+ readonly deviceId: string;
338
+ }): Promise<AgentMessageAdmission | undefined>;
334
339
  /** Read only an exact reservation; conflicting task/message bindings are not observable. */
335
340
  readAgentMessage(tenant: TenantId, input: {
336
341
  readonly taskId: string;
@@ -0,0 +1,11 @@
1
+ import { type AgentRef, type AgentMessagePublishPayload, type AgentMessageServerContext, type AgentMessageDispositionPayload } from '@byok-sdk/protocol';
2
+ import type { TenantStores } from './tenant-stores';
3
+ /** SDK transmission evidence; payload remains untrusted and never authors a Host product message. */
4
+ export interface TaskAgentMessage {
5
+ readonly payload: AgentMessagePublishPayload;
6
+ readonly context: AgentMessageServerContext;
7
+ /** Absent while the exact first-message reservation remains pending. */
8
+ readonly disposition?: AgentMessageDispositionPayload;
9
+ }
10
+ /** Discover the one durable message without requiring the Host to have received its body. */
11
+ export declare function readTaskAgentMessage(stores: TenantStores, deviceId: string, taskId: string, expectedRef: AgentRef): Promise<TaskAgentMessage | undefined>;
@@ -87,6 +87,10 @@ export interface TenantBoundTaskAttempts {
87
87
  readonly messageId: string;
88
88
  readonly payloadBody: string;
89
89
  }): Promise<'reserved' | 'pending' | 'rejected'>;
90
+ readTaskAgentMessage(input: {
91
+ readonly taskId: string;
92
+ readonly deviceId: string;
93
+ }): Promise<import('./stores/ports').AgentMessageAdmission | undefined>;
90
94
  readAgentMessage(input: {
91
95
  readonly taskId: string;
92
96
  readonly deviceId: string;
@@ -1,5 +1,13 @@
1
- import { type AgentRef, type BlobRef, type TerminalInferenceUsage, type TaskFailPayload } from '@byok-sdk/protocol';
1
+ import { type AgentRef, type BlobRef, type Envelope, type TerminalInferenceUsage, type TaskFailPayload } from '@byok-sdk/protocol';
2
2
  import type { RequestReceipt } from './stores/ports';
3
+ /** Canonical device evidence, independent of the Host cancellation projection. */
4
+ export interface DeviceTerminal {
5
+ readonly envelope: Extract<Envelope, {
6
+ type: 'task.complete' | 'task.fail' | 'task.decline' | 'task.cancelled';
7
+ }>;
8
+ readonly recordedAt: string;
9
+ }
10
+ export declare function readDeviceTerminalReceipt(taskId: string, receipt: RequestReceipt): DeviceTerminal;
3
11
  /**
4
12
  * The typed terminal read model — the hosted counterpart of the embedded
5
13
  * coordinator's `TaskResult`, projected off the receipt the inbound gate
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@byok-sdk/cloud",
3
- "version": "0.17.0",
3
+ "version": "0.19.0",
4
4
  "description": "BYOK SDK hosted device surface: stateless frozen-v1 HTTP handlers over tenant-first @byok-sdk/core ports",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -44,8 +44,8 @@
44
44
  "clean": "rm -rf dist"
45
45
  },
46
46
  "dependencies": {
47
- "@byok-sdk/core": "0.17.0",
48
- "@byok-sdk/protocol": "0.17.0",
47
+ "@byok-sdk/core": "0.19.0",
48
+ "@byok-sdk/protocol": "0.19.0",
49
49
  "hono": "^4.12.30",
50
50
  "zod": "^4.4.3"
51
51
  }