@byok-sdk/cloud 0.6.0 → 0.7.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/cloud.d.ts +44 -2
- package/dist/errors.d.ts +10 -0
- package/dist/handlers/messages.d.ts +11 -0
- package/dist/inbound.d.ts +4 -3
- package/dist/index.d.ts +5 -5
- package/dist/index.js +504 -46
- package/dist/index.js.map +1 -1
- package/dist/stores/in-memory/agent-egress.d.ts +12 -0
- package/dist/stores/in-memory/blobs.d.ts +8 -2
- package/dist/stores/in-memory/device-directory.d.ts +4 -0
- package/dist/stores/in-memory/index.d.ts +1 -0
- package/dist/stores/in-memory/task-attempts.d.ts +16 -5
- package/dist/stores/ports.d.ts +86 -3
- package/dist/tenant-stores.d.ts +24 -1
- package/dist/terminal-result.d.ts +5 -1
- package/package.json +3 -3
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type Clock, type TenantId } from '@byok-sdk/core';
|
|
2
|
+
import type { AgentEgressRecord, AgentEgressStore } from '../ports';
|
|
3
|
+
/** Reference egress fact store. Duplicate event ids return, never overwrite, the first receipt. */
|
|
4
|
+
export declare class InMemoryAgentEgressStore implements AgentEgressStore {
|
|
5
|
+
#private;
|
|
6
|
+
constructor(clock: Clock);
|
|
7
|
+
record(tenant: TenantId, input: Omit<AgentEgressRecord, 'tenantId' | 'recordedAt'>): Promise<{
|
|
8
|
+
readonly record: AgentEgressRecord;
|
|
9
|
+
readonly created: boolean;
|
|
10
|
+
}>;
|
|
11
|
+
get(tenant: TenantId, deviceId: string, eventId: string): Promise<AgentEgressRecord | undefined>;
|
|
12
|
+
}
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
*/
|
|
29
29
|
import { type Clock, type ContentHash, type ObjectStore, type StorageReservation, type TenantId } from '@byok-sdk/core';
|
|
30
30
|
import type { CloudCrypto } from '../../crypto/port';
|
|
31
|
-
import type {
|
|
31
|
+
import type { BlobContentProxy, BlobObservation, BlobReadResult, BlobWriteResult, CloudBlobStore } from '../ports';
|
|
32
32
|
/** How long a presigned upload/download URL stays valid. */
|
|
33
33
|
export declare const BLOB_URL_TTL_MS: number;
|
|
34
34
|
interface BlobRecord {
|
|
@@ -78,7 +78,13 @@ export declare class InMemoryBlobContentProxy implements BlobContentProxy {
|
|
|
78
78
|
constructor(registry: InMemoryBlobRegistry);
|
|
79
79
|
verifySignedUrl(blobId: string, action: 'put' | 'get', sig: string, exp: number): Promise<boolean>;
|
|
80
80
|
writeContent(blobId: string, data: Uint8Array): Promise<BlobWriteResult>;
|
|
81
|
-
|
|
81
|
+
/**
|
|
82
|
+
* Never returns `{ok:false}`: this composition holds the bytes in the same
|
|
83
|
+
* process, so there is no upstream to be unreachable and no stream to be
|
|
84
|
+
* interrupted. Both `BlobReadErrorCode`s are structurally unreachable here
|
|
85
|
+
* — a proxy that fetches from object storage is where they become live.
|
|
86
|
+
*/
|
|
87
|
+
readContent(blobId: string): Promise<BlobReadResult | undefined>;
|
|
82
88
|
}
|
|
83
89
|
/** Both halves over one registry. The only way to obtain either. */
|
|
84
90
|
export interface InMemoryBlobs {
|
|
@@ -14,6 +14,10 @@ export declare class InMemoryDeviceDirectory implements DeviceDirectory {
|
|
|
14
14
|
register(tenant: TenantId, input: DeviceRegistration): Promise<DeviceRecord>;
|
|
15
15
|
get(tenant: TenantId, deviceId: string): Promise<DeviceRecord | undefined>;
|
|
16
16
|
revoke(tenant: TenantId, deviceId: string): Promise<void>;
|
|
17
|
+
recordCapabilities(tenant: TenantId, input: {
|
|
18
|
+
readonly deviceId: string;
|
|
19
|
+
readonly capabilities: readonly string[];
|
|
20
|
+
}): Promise<DeviceRecord | undefined>;
|
|
17
21
|
list(tenant: TenantId): Promise<readonly DeviceRecord[]>;
|
|
18
22
|
readiness(tenant: TenantId, presence: PresenceStore): Promise<TenantReadiness>;
|
|
19
23
|
resolveByDeviceId(deviceId: string): Promise<DeviceRecord | undefined>;
|
|
@@ -22,6 +22,7 @@ export { InMemoryTaskAttemptStore } from './task-attempts';
|
|
|
22
22
|
export { InMemoryTaskCancellationStore } from './task-cancellations';
|
|
23
23
|
export { InMemoryActivityStore } from './activity';
|
|
24
24
|
export { InMemoryApprovalTimelineStore } from './approval-timeline';
|
|
25
|
+
export { InMemoryAgentEgressStore } from './agent-egress';
|
|
25
26
|
/**
|
|
26
27
|
* The port bundle plus the byte proxy, in the shape `createInMemoryCoreStores`
|
|
27
28
|
* already uses: the composition is an object with a `stores` field, not the
|
|
@@ -16,14 +16,23 @@
|
|
|
16
16
|
* unfalsifiable.
|
|
17
17
|
*/
|
|
18
18
|
import { type Clock, type TenantId } from '@byok-sdk/core';
|
|
19
|
-
import type { TaskAttempt, TaskAttemptStatus, TaskAttemptStore } from '../ports';
|
|
19
|
+
import type { AgentRef, TaskAttempt, TaskAttemptStatus, TaskAttemptStore } from '../ports';
|
|
20
20
|
export declare class InMemoryTaskAttemptStore implements TaskAttemptStore {
|
|
21
21
|
#private;
|
|
22
22
|
constructor(clock: Clock, state?: InMemoryTaskAttemptState);
|
|
23
23
|
open(tenant: TenantId, input: {
|
|
24
|
-
taskId: string;
|
|
25
|
-
deviceId: string;
|
|
24
|
+
readonly taskId: string;
|
|
25
|
+
readonly deviceId: string;
|
|
26
|
+
readonly agentRef?: AgentRef;
|
|
26
27
|
}): Promise<TaskAttempt>;
|
|
28
|
+
reserveAgentOffer(tenant: TenantId, input: {
|
|
29
|
+
readonly taskId: string;
|
|
30
|
+
readonly deviceId: string;
|
|
31
|
+
readonly agentRef: AgentRef;
|
|
32
|
+
}): Promise<{
|
|
33
|
+
readonly attempt: TaskAttempt;
|
|
34
|
+
readonly created: boolean;
|
|
35
|
+
}>;
|
|
27
36
|
get(tenant: TenantId, taskId: string): Promise<TaskAttempt | undefined>;
|
|
28
37
|
getMany(tenant: TenantId, taskIds: readonly string[]): Promise<readonly TaskAttempt[]>;
|
|
29
38
|
claim(tenant: TenantId, input: {
|
|
@@ -31,8 +40,10 @@ export declare class InMemoryTaskAttemptStore implements TaskAttemptStore {
|
|
|
31
40
|
deviceId: string;
|
|
32
41
|
}): Promise<TaskAttempt | undefined>;
|
|
33
42
|
recordStatus(tenant: TenantId, input: {
|
|
34
|
-
taskId: string;
|
|
35
|
-
status: TaskAttemptStatus;
|
|
43
|
+
readonly taskId: string;
|
|
44
|
+
readonly status: TaskAttemptStatus;
|
|
45
|
+
readonly agentRef?: AgentRef;
|
|
46
|
+
readonly terminalCause?: string;
|
|
36
47
|
}): Promise<TaskAttempt | undefined>;
|
|
37
48
|
}
|
|
38
49
|
/** Shared mutable state for the task and cancellation reference ports. */
|
package/dist/stores/ports.d.ts
CHANGED
|
@@ -35,6 +35,8 @@
|
|
|
35
35
|
* bytes (see the blobs section below).
|
|
36
36
|
*/
|
|
37
37
|
import type { MailboxBody, MailboxMessage, PresenceStore, StorageReservation, TenantId, TenantReadiness } from '@byok-sdk/core';
|
|
38
|
+
import type { AgentEgressReliablePayload, AgentRef } from '@byok-sdk/protocol';
|
|
39
|
+
export type { AgentEgressReliablePayload, AgentRef } from '@byok-sdk/protocol';
|
|
38
40
|
import type { ActivityStore } from '../activity';
|
|
39
41
|
import type { ApprovalTimelineStore } from '../approval-timeline';
|
|
40
42
|
export interface DeviceRecord {
|
|
@@ -49,6 +51,12 @@ export interface DeviceRecord {
|
|
|
49
51
|
/** Current proof signing-key rotation generation. */
|
|
50
52
|
readonly proofKeyEpoch: number;
|
|
51
53
|
readonly revoked: boolean;
|
|
54
|
+
/**
|
|
55
|
+
* The latest capability snapshot written by an authenticated device
|
|
56
|
+
* handshake. This is deliberately separate from core presence: presence is
|
|
57
|
+
* lossy/TTL-bounded and cannot authorize Agent dispatch.
|
|
58
|
+
*/
|
|
59
|
+
readonly capabilities?: readonly string[];
|
|
52
60
|
}
|
|
53
61
|
/** Everything `POST /byok/pair` knows at registration time. `tenantId` is the store's first parameter; `revoked` is the store's own to set. */
|
|
54
62
|
export interface DeviceRegistration {
|
|
@@ -67,6 +75,15 @@ export interface DeviceDirectory {
|
|
|
67
75
|
list(tenant: TenantId): Promise<readonly DeviceRecord[]>;
|
|
68
76
|
/** Set-wise tenant observation; revoked devices never contribute presence. */
|
|
69
77
|
readiness(tenant: TenantId, presence: PresenceStore): Promise<TenantReadiness>;
|
|
78
|
+
/**
|
|
79
|
+
* Persist a capability snapshot obtained from an authenticated device
|
|
80
|
+
* message. Implementations may return `undefined` for an unknown/revoked
|
|
81
|
+
* device; callers must fail closed in that case.
|
|
82
|
+
*/
|
|
83
|
+
recordCapabilities(tenant: TenantId, input: {
|
|
84
|
+
readonly deviceId: string;
|
|
85
|
+
readonly capabilities: readonly string[];
|
|
86
|
+
}): Promise<DeviceRecord | undefined>;
|
|
70
87
|
/** Pre-tenant. Two callers only: `POST /byok/challenge` and `POST /byok/token`. Never exposed through the tenant facade. */
|
|
71
88
|
resolveByDeviceId(deviceId: string): Promise<DeviceRecord | undefined>;
|
|
72
89
|
}
|
|
@@ -124,9 +141,13 @@ export interface TaskAttempt {
|
|
|
124
141
|
readonly taskId: string;
|
|
125
142
|
/** The device the offer was addressed to. */
|
|
126
143
|
readonly deviceId: string;
|
|
127
|
-
/**
|
|
144
|
+
/** Exact Agent identity sealed when the strict Agent offer was opened. */
|
|
145
|
+
readonly agentRef?: AgentRef;
|
|
146
|
+
/** Set by `task.claim`, and only by the first one. Legacy attempts remain claimable by any tenant device until then; strict Agent attempts are target-device bound before this field is consulted. */
|
|
128
147
|
readonly ownerDeviceId?: string;
|
|
129
148
|
readonly status: TaskAttemptStatus;
|
|
149
|
+
/** Runtime-reported terminal cause from the first winning terminal. */
|
|
150
|
+
readonly terminalCause?: string;
|
|
130
151
|
/** Durable host cancellation authority. Its presence outranks later device terminal receipts. */
|
|
131
152
|
readonly cancellation?: {
|
|
132
153
|
readonly requestedAt: string;
|
|
@@ -139,7 +160,20 @@ export interface TaskAttemptStore {
|
|
|
139
160
|
open(tenant: TenantId, input: {
|
|
140
161
|
readonly taskId: string;
|
|
141
162
|
readonly deviceId: string;
|
|
163
|
+
readonly agentRef?: AgentRef;
|
|
142
164
|
}): Promise<TaskAttempt>;
|
|
165
|
+
/**
|
|
166
|
+
* Atomically reserve one strict Agent offer. `created: false` means the task
|
|
167
|
+
* id already had durable authority and no caller may append another offer.
|
|
168
|
+
*/
|
|
169
|
+
reserveAgentOffer(tenant: TenantId, input: {
|
|
170
|
+
readonly taskId: string;
|
|
171
|
+
readonly deviceId: string;
|
|
172
|
+
readonly agentRef: AgentRef;
|
|
173
|
+
}): Promise<{
|
|
174
|
+
readonly attempt: TaskAttempt;
|
|
175
|
+
readonly created: boolean;
|
|
176
|
+
}>;
|
|
143
177
|
get(tenant: TenantId, taskId: string): Promise<TaskAttempt | undefined>;
|
|
144
178
|
/** Batch lookup used by mailbox projection; implementations must not turn one poll into N queries. */
|
|
145
179
|
getMany(tenant: TenantId, taskIds: readonly string[]): Promise<readonly TaskAttempt[]>;
|
|
@@ -152,6 +186,8 @@ export interface TaskAttemptStore {
|
|
|
152
186
|
recordStatus(tenant: TenantId, input: {
|
|
153
187
|
readonly taskId: string;
|
|
154
188
|
readonly status: TaskAttemptStatus;
|
|
189
|
+
readonly agentRef?: AgentRef;
|
|
190
|
+
readonly terminalCause?: string;
|
|
155
191
|
}): Promise<TaskAttempt | undefined>;
|
|
156
192
|
}
|
|
157
193
|
export interface TaskCancellationRequest {
|
|
@@ -195,6 +231,22 @@ export interface RequestReceiptStore {
|
|
|
195
231
|
}>;
|
|
196
232
|
get(tenant: TenantId, key: string): Promise<RequestReceipt | undefined>;
|
|
197
233
|
}
|
|
234
|
+
export interface AgentEgressRecord {
|
|
235
|
+
readonly tenantId: TenantId;
|
|
236
|
+
readonly deviceId: string;
|
|
237
|
+
readonly payload: AgentEgressReliablePayload;
|
|
238
|
+
/** Stable cloud-generated receipt identity echoed on every exact replay. */
|
|
239
|
+
readonly receiptId: string;
|
|
240
|
+
readonly recordedAt: string;
|
|
241
|
+
}
|
|
242
|
+
export interface AgentEgressStore {
|
|
243
|
+
/** First event-id write wins; callers reject mismatches rather than updating. */
|
|
244
|
+
record(tenant: TenantId, input: Omit<AgentEgressRecord, 'tenantId' | 'recordedAt'>): Promise<{
|
|
245
|
+
readonly record: AgentEgressRecord;
|
|
246
|
+
readonly created: boolean;
|
|
247
|
+
}>;
|
|
248
|
+
get(tenant: TenantId, deviceId: string, eventId: string): Promise<AgentEgressRecord | undefined>;
|
|
249
|
+
}
|
|
198
250
|
export interface ProofRequestReceipt {
|
|
199
251
|
readonly tenantId: TenantId;
|
|
200
252
|
readonly deviceId: string;
|
|
@@ -241,6 +293,35 @@ export interface BlobContent {
|
|
|
241
293
|
readonly data: Uint8Array;
|
|
242
294
|
readonly contentType: string;
|
|
243
295
|
}
|
|
296
|
+
/**
|
|
297
|
+
* How a byte-proxying read can fail while the blob itself is known to exist.
|
|
298
|
+
*
|
|
299
|
+
* The split is about WHERE the failure landed relative to the upstream
|
|
300
|
+
* response, because that is the only part a proxy can observe and the only
|
|
301
|
+
* part an operator can act on: `blob_upstream_unavailable` means nothing came
|
|
302
|
+
* back at all (the upstream was unreachable/refused before its response
|
|
303
|
+
* started), so a retry may succeed unchanged; `blob_upstream_stream_interrupted`
|
|
304
|
+
* means the response HAD started and died mid-transfer, so whatever the caller
|
|
305
|
+
* already has is a truncated prefix, not a short blob.
|
|
306
|
+
*
|
|
307
|
+
* Both are 502 on the wire (see `BLOB_READ_ERROR_HTTP_STATUS` in
|
|
308
|
+
* `handlers/blobs.ts`) — the CODE carries the distinction, not the status.
|
|
309
|
+
*/
|
|
310
|
+
export declare const BLOB_READ_ERROR_CODES: readonly ['blob_upstream_unavailable', 'blob_upstream_stream_interrupted'];
|
|
311
|
+
export type BlobReadErrorCode = (typeof BLOB_READ_ERROR_CODES)[number];
|
|
312
|
+
/**
|
|
313
|
+
* The result of {@link BlobContentProxy.readContent}, in the same union idiom
|
|
314
|
+
* as {@link BlobWriteResult}. Note what is NOT in here: not-found stays
|
|
315
|
+
* `undefined` at the method's return type, so "no such blob" keeps its
|
|
316
|
+
* existing 404 meaning and never has to be spelled as a failure code.
|
|
317
|
+
*/
|
|
318
|
+
export type BlobReadResult = {
|
|
319
|
+
readonly ok: true;
|
|
320
|
+
readonly content: BlobContent;
|
|
321
|
+
} | {
|
|
322
|
+
readonly ok: false;
|
|
323
|
+
readonly code: BlobReadErrorCode;
|
|
324
|
+
};
|
|
244
325
|
/**
|
|
245
326
|
* The capability-minting half of blobs: what EVERY composition can honestly
|
|
246
327
|
* provide, whoever holds the bytes.
|
|
@@ -289,7 +370,8 @@ export interface CloudBlobStore {
|
|
|
289
370
|
export interface BlobContentProxy {
|
|
290
371
|
verifySignedUrl(blobId: string, action: 'put' | 'get', sig: string, exp: number): Promise<boolean>;
|
|
291
372
|
writeContent(blobId: string, data: Uint8Array): Promise<BlobWriteResult>;
|
|
292
|
-
|
|
373
|
+
/** `undefined` = no such blob (404); a `{ok:false}` result = the blob exists but its bytes could not be proxied (502, distinguished by {@link BlobReadErrorCode}). */
|
|
374
|
+
readContent(blobId: string): Promise<BlobReadResult | undefined>;
|
|
293
375
|
}
|
|
294
376
|
/**
|
|
295
377
|
* Step 0 of the inbound gate. S3a ships an allow-all reference (a hosted
|
|
@@ -317,10 +399,11 @@ export interface CloudStores {
|
|
|
317
399
|
readonly tasks: TaskAttemptStore;
|
|
318
400
|
readonly cancellations: TaskCancellationStore;
|
|
319
401
|
readonly receipts: RequestReceiptStore;
|
|
402
|
+
readonly egress: AgentEgressStore;
|
|
320
403
|
readonly proofReceipts: ProofRequestReceiptStore;
|
|
321
404
|
readonly blobs: CloudBlobStore;
|
|
322
405
|
readonly rateLimiter: InboundRateLimiter;
|
|
323
406
|
}
|
|
324
407
|
/** Names of every port in {@link CloudStores}, in contract order. */
|
|
325
|
-
export declare const CLOUD_STORE_NAMES: readonly ['activity', 'approvals', 'devices', 'pairingCodes', 'nonces', 'dedup', 'tasks', 'cancellations', 'receipts', 'proofReceipts', 'blobs', 'rateLimiter'];
|
|
408
|
+
export declare const CLOUD_STORE_NAMES: readonly ['activity', 'approvals', 'devices', 'pairingCodes', 'nonces', 'dedup', 'tasks', 'cancellations', 'receipts', 'egress', 'proofReceipts', 'blobs', 'rateLimiter'];
|
|
326
409
|
export type CloudStoreName = (typeof CLOUD_STORE_NAMES)[number];
|
package/dist/tenant-stores.d.ts
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
import { type BoardClaimInput, type BoardItem, type BoardItemInput, type BoardListQuery, type BoardPage, type BoardStatusUpdateInput, type BoardUnclaimInput, type CoreStores, type MailboxAdvanceCursorInput, type MailboxAppendInput, type MailboxCursorState, type MailboxMessage, type MailboxPage, type MailboxReadQuery, type Principal, type PresenceHint, type PresenceHintInput, type TenantReadiness, type StorageFinalizeInput, type StorageFinalizeResult, type StorageReservation, type StorageReservationInput, type TenantId } from '@byok-sdk/core';
|
|
25
25
|
import type { ActivityAppendInput, ActivityTail } from './activity';
|
|
26
26
|
import type { ApprovalTimelineAppendInput, ApprovalTimelineTail } from './approval-timeline';
|
|
27
|
-
import type { BlobObservation, CloudStores, DeviceRecord, RequestReceipt, TaskCancellationMutation, TaskCancellationRequest, TaskAttempt, TaskAttemptStatus } from './stores/ports';
|
|
27
|
+
import type { BlobObservation, CloudStores, DeviceRecord, AgentEgressRecord, RequestReceipt, TaskCancellationMutation, TaskCancellationRequest, TaskAttempt, TaskAttemptStatus } from './stores/ports';
|
|
28
28
|
export interface TenantBoundMailbox {
|
|
29
29
|
append(input: MailboxAppendInput): Promise<MailboxMessage>;
|
|
30
30
|
/** Pure read. Never advances the cursor — the daemon's next poll is the only ack. */
|
|
@@ -57,13 +57,26 @@ export interface TenantBoundDevices {
|
|
|
57
57
|
get(deviceId: string): Promise<DeviceRecord | undefined>;
|
|
58
58
|
list(): Promise<readonly DeviceRecord[]>;
|
|
59
59
|
revoke(deviceId: string): Promise<void>;
|
|
60
|
+
/** Persist the authenticated device's own capability snapshot. */
|
|
61
|
+
recordCapabilities(input: {
|
|
62
|
+
readonly capabilities: readonly string[];
|
|
63
|
+
}): Promise<DeviceRecord | undefined>;
|
|
60
64
|
readiness(): Promise<TenantReadiness>;
|
|
61
65
|
}
|
|
62
66
|
export interface TenantBoundTaskAttempts {
|
|
63
67
|
open(input: {
|
|
64
68
|
readonly taskId: string;
|
|
65
69
|
readonly deviceId: string;
|
|
70
|
+
readonly agentRef?: TaskAttempt['agentRef'];
|
|
66
71
|
}): Promise<TaskAttempt>;
|
|
72
|
+
reserveAgentOffer(input: {
|
|
73
|
+
readonly taskId: string;
|
|
74
|
+
readonly deviceId: string;
|
|
75
|
+
readonly agentRef: NonNullable<TaskAttempt['agentRef']>;
|
|
76
|
+
}): Promise<{
|
|
77
|
+
readonly attempt: TaskAttempt;
|
|
78
|
+
readonly created: boolean;
|
|
79
|
+
}>;
|
|
67
80
|
get(taskId: string): Promise<TaskAttempt | undefined>;
|
|
68
81
|
getMany(taskIds: readonly string[]): Promise<readonly TaskAttempt[]>;
|
|
69
82
|
claim(input: {
|
|
@@ -73,6 +86,8 @@ export interface TenantBoundTaskAttempts {
|
|
|
73
86
|
recordStatus(input: {
|
|
74
87
|
readonly taskId: string;
|
|
75
88
|
readonly status: TaskAttemptStatus;
|
|
89
|
+
readonly agentRef?: TaskAttempt['agentRef'];
|
|
90
|
+
readonly terminalCause?: TaskAttempt['terminalCause'];
|
|
76
91
|
}): Promise<TaskAttempt | undefined>;
|
|
77
92
|
}
|
|
78
93
|
export interface TenantBoundTaskCancellations {
|
|
@@ -91,6 +106,13 @@ export interface TenantBoundReceipts {
|
|
|
91
106
|
}>;
|
|
92
107
|
get(key: string): Promise<RequestReceipt | undefined>;
|
|
93
108
|
}
|
|
109
|
+
export interface TenantBoundAgentEgress {
|
|
110
|
+
record(input: Omit<AgentEgressRecord, 'tenantId' | 'recordedAt'>): Promise<{
|
|
111
|
+
readonly record: AgentEgressRecord;
|
|
112
|
+
readonly created: boolean;
|
|
113
|
+
}>;
|
|
114
|
+
get(deviceId: string, eventId: string): Promise<AgentEgressRecord | undefined>;
|
|
115
|
+
}
|
|
94
116
|
export interface TenantBoundBlobs {
|
|
95
117
|
createUpload(reservation: StorageReservation): Promise<{
|
|
96
118
|
readonly blobId: string;
|
|
@@ -121,6 +143,7 @@ export interface TenantStores {
|
|
|
121
143
|
readonly cancellations: TenantBoundTaskCancellations;
|
|
122
144
|
readonly dedup: TenantBoundDedup;
|
|
123
145
|
readonly receipts: TenantBoundReceipts;
|
|
146
|
+
readonly egress: TenantBoundAgentEgress;
|
|
124
147
|
readonly blobs: TenantBoundBlobs;
|
|
125
148
|
readonly quota: TenantBoundQuota;
|
|
126
149
|
readonly rateLimiter: TenantBoundRateLimiter;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type BlobRef, type TerminalInferenceUsage } from '@byok-sdk/protocol';
|
|
1
|
+
import { type AgentRef, type BlobRef, type TerminalInferenceUsage } from '@byok-sdk/protocol';
|
|
2
2
|
import type { RequestReceipt } from './stores/ports';
|
|
3
3
|
/**
|
|
4
4
|
* The typed terminal read model — the hosted counterpart of the embedded
|
|
@@ -10,6 +10,8 @@ import type { RequestReceipt } from './stores/ports';
|
|
|
10
10
|
export interface TerminalResult {
|
|
11
11
|
readonly taskId: string;
|
|
12
12
|
readonly state: 'complete' | 'failed' | 'cancelled';
|
|
13
|
+
/** Exact Agent identity echoed by the winning terminal, when Agent-bound. */
|
|
14
|
+
readonly agentRef?: AgentRef;
|
|
13
15
|
readonly summary?: string;
|
|
14
16
|
readonly sessionRef?: string;
|
|
15
17
|
readonly artifactRefs?: readonly BlobRef[];
|
|
@@ -27,6 +29,8 @@ export interface TerminalResult {
|
|
|
27
29
|
*/
|
|
28
30
|
readonly usage?: TerminalInferenceUsage;
|
|
29
31
|
readonly reason?: string;
|
|
32
|
+
/** Terminal cause projection; currently the protocol's terminal reason. */
|
|
33
|
+
readonly terminalCause?: string;
|
|
30
34
|
readonly retryable?: boolean;
|
|
31
35
|
/** When the receipt store wrote the terminal fact — the first one, by its own first-write-wins rule. */
|
|
32
36
|
readonly recordedAt: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@byok-sdk/cloud",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.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.
|
|
48
|
-
"@byok-sdk/protocol": "0.
|
|
47
|
+
"@byok-sdk/core": "0.7.0",
|
|
48
|
+
"@byok-sdk/protocol": "0.7.0",
|
|
49
49
|
"hono": "^4.12.30",
|
|
50
50
|
"zod": "^4.4.3"
|
|
51
51
|
}
|