@byok-sdk/server 0.6.1 → 0.8.0-beta.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/hub.d.ts +3 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.js +69 -23
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +9 -0
- package/package.json +3 -3
package/dist/hub.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { type Envelope, type RuntimeId, type RuntimeInfo, type TaskState, type T
|
|
|
3
3
|
import type { DeviceRegistry } from './auth';
|
|
4
4
|
import { RateLimiter } from './rate-limiter';
|
|
5
5
|
import type { TaskStore } from './task-store';
|
|
6
|
-
import type { ByokServerEvent, AgentContentReadRequest, AgentEgressReceipt, DispatchInput, HubStats, MachineInfo, TaskHandle, TaskSnapshot } from './types';
|
|
6
|
+
import type { ByokServerEvent, AgentContentReadRequest, AgentEgressReceipt, DispatchInput, FreshAgentEgressDispatchInput, HubStats, MachineInfo, TaskHandle, TaskSnapshot } from './types';
|
|
7
7
|
/**
|
|
8
8
|
* The connection hub: tracks each device's live transport (WS or long-poll —
|
|
9
9
|
* never both at once, see {@link takeOverAsLongPoll}), routes `dispatch()`'d
|
|
@@ -749,6 +749,8 @@ export declare class ConnectionHub {
|
|
|
749
749
|
/** Reap one lease-expired task through the exact same TaskStore/canTransition path — and terminal-event emission — as any other `task.fail` (see {@link applyOrFail}). */
|
|
750
750
|
private reapTask;
|
|
751
751
|
dispatch(input: DispatchInput): Promise<TaskHandle>;
|
|
752
|
+
dispatchFreshAgentEgress(input: FreshAgentEgressDispatchInput): Promise<TaskHandle>;
|
|
753
|
+
private dispatchInternal;
|
|
752
754
|
/** Capability-gated control-plane read request; no request enters the outbox on omission. */
|
|
753
755
|
requestAgentContentRead(input: AgentContentReadRequest): Promise<void>;
|
|
754
756
|
private buildTaskHandle;
|
package/dist/index.d.ts
CHANGED
|
@@ -2,8 +2,8 @@ import type { Server as HttpServer } from 'node:http';
|
|
|
2
2
|
import type { Hono } from 'hono';
|
|
3
3
|
import { type TenantId } from './auth';
|
|
4
4
|
import { type PairingCodeClaims, type PairingCodeInfo } from './pairing';
|
|
5
|
-
import type { ByokServerEvent, AgentContentReadRequest, AgentEgressReceipt, CreateByokServerOptions, DispatchInput, HubStats, MachineInfo, TaskHandle, TaskSnapshot } from './types';
|
|
6
|
-
export type { ByokServerEvent, AgentContentReadRequest, AgentEgressReceipt, CreateByokServerOptions, DispatchInput, HubStats, MachineInfo, ServerTaskEvent, TaskHandle, TaskResult, TaskSnapshot, } from './types';
|
|
5
|
+
import type { ByokServerEvent, AgentContentReadRequest, AgentEgressReceipt, CreateByokServerOptions, DispatchInput, FreshAgentEgressDispatchInput, HubStats, MachineInfo, TaskHandle, TaskSnapshot } from './types';
|
|
6
|
+
export type { ByokServerEvent, AgentContentReadRequest, AgentEgressReceipt, CreateByokServerOptions, DispatchInput, FreshAgentEgressDispatchInput, HubStats, MachineInfo, ServerTaskEvent, TaskHandle, TaskResult, TaskSnapshot, } from './types';
|
|
7
7
|
export type { CreateTaskInput, TaskRecord, TaskStore } from './task-store';
|
|
8
8
|
export { IllegalTaskTransitionError, InMemoryTaskStore } from './task-store';
|
|
9
9
|
/**
|
|
@@ -60,6 +60,8 @@ export interface ByokServer {
|
|
|
60
60
|
createPairingCode(claims: PairingCodeClaims): PairingCodeInfo;
|
|
61
61
|
};
|
|
62
62
|
dispatch(input: DispatchInput): Promise<TaskHandle>;
|
|
63
|
+
/** Dispatch a fresh Agent execution whose runtime will mint its session after start. */
|
|
64
|
+
dispatchFreshAgentEgress(input: FreshAgentEgressDispatchInput): Promise<TaskHandle>;
|
|
63
65
|
/** Enqueue one capability-gated, exact-identity content-read request. */
|
|
64
66
|
requestAgentContentRead(input: AgentContentReadRequest): Promise<void>;
|
|
65
67
|
tasks: {
|
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import { mkdir, writeFile, readFile } from 'fs/promises';
|
|
|
5
5
|
import { mkdtempSync, mkdirSync, existsSync, chmodSync } from 'fs';
|
|
6
6
|
import { tmpdir } from 'os';
|
|
7
7
|
import path, { dirname } from 'path';
|
|
8
|
-
import { CAPABILITY_FLAGS, byokBlobContentPath, canTransition, PROTOCOL_VERSION, encodeEnvelope, DAEMON_TO_SERVER_TYPES, AGENT_EGRESS_POLICY_CAPABILITY, AGENT_EGRESS_RELIABLE_ACK_CAPABILITY, AgentRefSchema, AgentEgressPolicySchema, DispatchSelectionSchema, RequiredToolsetsSchema, AgentContentReadPayloadSchema, createEnvelope, TASK_STATES, BYOK_PAIR_PATH, PairRequestSchema, BYOK_CHALLENGE_PATH, ChallengeRequestSchema, BYOK_TOKEN_PATH, TokenRequestSchema, BYOK_BLOBS_PATH, CreateBlobRequestSchema, BYOK_BLOB_FINALIZE_ROUTE, BYOK_BLOB_URL_ROUTE, BYOK_BLOB_CONTENT_ROUTE, BYOK_EVENTS_PATH, BYOK_MESSAGES_PATH, MessagesSendRequestSchema, AGENT_CONTENT_ARTIFACT_READ_CAPABILITY, AGENT_CONTENT_TRANSCRIPT_READ_CAPABILITY, AGENT_CONTENT_WORKSPACE_READ_CAPABILITY, decodeEnvelope, BYOK_WS_PATH } from '@byok-sdk/protocol';
|
|
8
|
+
import { CAPABILITY_FLAGS, byokBlobContentPath, canTransition, PROTOCOL_VERSION, encodeEnvelope, DAEMON_TO_SERVER_TYPES, AGENT_EGRESS_POLICY_CAPABILITY, AGENT_EGRESS_RELIABLE_ACK_CAPABILITY, AgentRefSchema, AgentEgressPolicySchema, DispatchSelectionSchema, RequiredToolsetsSchema, AGENT_EGRESS_FRESH_SESSION_CAPABILITY, AgentContentReadPayloadSchema, createEnvelope, TASK_STATES, BYOK_PAIR_PATH, PairRequestSchema, PairResponseSchema, BYOK_CHALLENGE_PATH, ChallengeRequestSchema, BYOK_TOKEN_PATH, TokenRequestSchema, BYOK_BLOBS_PATH, CreateBlobRequestSchema, BYOK_BLOB_FINALIZE_ROUTE, BYOK_BLOB_URL_ROUTE, BYOK_BLOB_CONTENT_ROUTE, BYOK_EVENTS_PATH, BYOK_MESSAGES_PATH, MessagesSendRequestSchema, AGENT_CONTENT_ARTIFACT_READ_CAPABILITY, AGENT_CONTENT_TRANSCRIPT_READ_CAPABILITY, AGENT_CONTENT_WORKSPACE_READ_CAPABILITY, PairResponseTenantIdSchema, decodeEnvelope, BYOK_WS_PATH } from '@byok-sdk/protocol';
|
|
9
9
|
import { Hono } from 'hono';
|
|
10
10
|
import { WebSocketServer } from 'ws';
|
|
11
11
|
import { createRequire } from 'module';
|
|
@@ -266,8 +266,6 @@ function generateDeviceId() {
|
|
|
266
266
|
function generateTaskId() {
|
|
267
267
|
return `task_${randomUUID()}`;
|
|
268
268
|
}
|
|
269
|
-
|
|
270
|
-
// src/pairing.ts
|
|
271
269
|
var PAIRING_CODE_TTL_MS = 10 * 60 * 1e3;
|
|
272
270
|
var PairingCodeInvalidError = class extends Error {
|
|
273
271
|
constructor(reason) {
|
|
@@ -320,13 +318,14 @@ function validatePairingCodeClaims(claims) {
|
|
|
320
318
|
throw new TypeError("createPairingCode requires { tenantId, productId } claims");
|
|
321
319
|
}
|
|
322
320
|
const { tenantId, productId } = claims;
|
|
323
|
-
|
|
324
|
-
|
|
321
|
+
const tenantResult = PairResponseTenantIdSchema.safeParse(tenantId);
|
|
322
|
+
if (!tenantResult.success) {
|
|
323
|
+
throw new TypeError("createPairingCode requires a valid bounded tenantId");
|
|
325
324
|
}
|
|
326
325
|
if (typeof productId !== "string" || productId.length === 0) {
|
|
327
326
|
throw new TypeError("createPairingCode requires a non-empty productId");
|
|
328
327
|
}
|
|
329
|
-
return { tenantId, productId };
|
|
328
|
+
return { tenantId: tenantResult.data, productId };
|
|
330
329
|
}
|
|
331
330
|
|
|
332
331
|
// src/http.ts
|
|
@@ -366,12 +365,21 @@ function buildHonoApp(deps) {
|
|
|
366
365
|
deviceName,
|
|
367
366
|
devicePublicKey
|
|
368
367
|
});
|
|
368
|
+
const device = deps.devices.get(claims.tenantId, deviceId);
|
|
369
|
+
if (device === void 0) {
|
|
370
|
+
throw new Error("paired device row was not persisted");
|
|
371
|
+
}
|
|
369
372
|
const { accessToken, expiresAt } = await mintAccessToken(deps.tokenSigner, {
|
|
370
|
-
deviceId,
|
|
371
|
-
tenantId:
|
|
372
|
-
productId:
|
|
373
|
+
deviceId: device.deviceId,
|
|
374
|
+
tenantId: device.tenantId,
|
|
375
|
+
productId: device.productId
|
|
376
|
+
});
|
|
377
|
+
const response = PairResponseSchema.parse({
|
|
378
|
+
deviceId: device.deviceId,
|
|
379
|
+
accessToken,
|
|
380
|
+
refreshHint: expiresAt,
|
|
381
|
+
tenantId: device.tenantId
|
|
373
382
|
});
|
|
374
|
-
const response = { deviceId, accessToken, refreshHint: expiresAt };
|
|
375
383
|
return c.json(response, 200);
|
|
376
384
|
});
|
|
377
385
|
app.post(BYOK_CHALLENGE_PATH, async (c) => {
|
|
@@ -1849,6 +1857,25 @@ var ConnectionHub = class {
|
|
|
1849
1857
|
// dispatch() and the TaskHandle it returns
|
|
1850
1858
|
// ---------------------------------------------------------------------
|
|
1851
1859
|
async dispatch(input) {
|
|
1860
|
+
if (input.egressPolicy !== void 0 && input.sessionRef === void 0) {
|
|
1861
|
+
throw new Error("Agent egress resume dispatch requires an exact sessionRef; use dispatchFreshAgentEgress for fresh execution");
|
|
1862
|
+
}
|
|
1863
|
+
return this.dispatchInternal(input, false);
|
|
1864
|
+
}
|
|
1865
|
+
async dispatchFreshAgentEgress(input) {
|
|
1866
|
+
if (Object.prototype.hasOwnProperty.call(input, "sessionRef")) {
|
|
1867
|
+
throw new Error("fresh Agent egress dispatch must not carry sessionRef");
|
|
1868
|
+
}
|
|
1869
|
+
if (typeof input.deviceId !== "string" || input.deviceId.length === 0) {
|
|
1870
|
+
throw new Error("fresh Agent egress dispatch requires an explicit deviceId");
|
|
1871
|
+
}
|
|
1872
|
+
if (input.agentRef === void 0 || input.egressPolicy === void 0) {
|
|
1873
|
+
throw new Error("fresh Agent egress dispatch requires exact AgentRef and egress policy");
|
|
1874
|
+
}
|
|
1875
|
+
return this.dispatchInternal(input, true);
|
|
1876
|
+
}
|
|
1877
|
+
async dispatchInternal(input, freshAgentEgress) {
|
|
1878
|
+
const sessionRef = "sessionRef" in input ? input.sessionRef : void 0;
|
|
1852
1879
|
const agentRef = input.agentRef === void 0 ? void 0 : AgentRefSchema.parse(input.agentRef);
|
|
1853
1880
|
const egressPolicy = input.egressPolicy === void 0 ? void 0 : AgentEgressPolicySchema.parse(input.egressPolicy);
|
|
1854
1881
|
const dispatchSelection = input.dispatchSelection === void 0 ? void 0 : DispatchSelectionSchema.parse(input.dispatchSelection);
|
|
@@ -1860,9 +1887,6 @@ var ConnectionHub = class {
|
|
|
1860
1887
|
if (egressPolicy !== void 0 && agentRef === void 0) {
|
|
1861
1888
|
throw new Error("Agent egress policy requires an explicit AgentRef; legacy task dispatch cannot consume it");
|
|
1862
1889
|
}
|
|
1863
|
-
if (egressPolicy !== void 0 && input.sessionRef === void 0) {
|
|
1864
|
-
throw new Error("Agent egress policy requires an exact sessionRef");
|
|
1865
|
-
}
|
|
1866
1890
|
if (!deviceId || !this.connections.get(deviceId)?.connected) {
|
|
1867
1891
|
throw new Error(
|
|
1868
1892
|
deviceId ? `device ${deviceId} is not connected` : "no connected device to dispatch to (M0 does not queue tasks until a device connects)"
|
|
@@ -1873,9 +1897,14 @@ var ConnectionHub = class {
|
|
|
1873
1897
|
`device ${deviceId} did not advertise agent-home-contract capability; refusing Agent-bound dispatch`
|
|
1874
1898
|
);
|
|
1875
1899
|
}
|
|
1876
|
-
|
|
1900
|
+
const requiredEgressCapabilities = freshAgentEgress ? [
|
|
1901
|
+
AGENT_EGRESS_POLICY_CAPABILITY,
|
|
1902
|
+
AGENT_EGRESS_RELIABLE_ACK_CAPABILITY,
|
|
1903
|
+
AGENT_EGRESS_FRESH_SESSION_CAPABILITY
|
|
1904
|
+
] : [AGENT_EGRESS_POLICY_CAPABILITY, AGENT_EGRESS_RELIABLE_ACK_CAPABILITY];
|
|
1905
|
+
if (egressPolicy !== void 0 && !this.hasDeviceCapabilities(deviceId, requiredEgressCapabilities)) {
|
|
1877
1906
|
throw new Error(
|
|
1878
|
-
`device ${deviceId} did not advertise Agent egress policy and reliable acknowledgement capabilities; refusing before enqueue`
|
|
1907
|
+
freshAgentEgress ? `device ${deviceId} did not advertise Agent egress policy, reliable acknowledgement, and fresh-session capabilities; refusing before enqueue` : `device ${deviceId} did not advertise Agent egress policy and reliable acknowledgement capabilities; refusing before enqueue`
|
|
1879
1908
|
);
|
|
1880
1909
|
}
|
|
1881
1910
|
if (dispatchSelection !== void 0 && !(this.getDeviceCapabilities(deviceId)?.includes("dispatch-selection") ?? false)) {
|
|
@@ -1918,7 +1947,7 @@ var ConnectionHub = class {
|
|
|
1918
1947
|
policy,
|
|
1919
1948
|
requiredToolsets,
|
|
1920
1949
|
deviceId,
|
|
1921
|
-
sessionRef
|
|
1950
|
+
sessionRef,
|
|
1922
1951
|
agentRef
|
|
1923
1952
|
});
|
|
1924
1953
|
const queue = new AsyncEventQueue();
|
|
@@ -1934,36 +1963,52 @@ var ConnectionHub = class {
|
|
|
1934
1963
|
policy,
|
|
1935
1964
|
runtime,
|
|
1936
1965
|
dispatchSelection,
|
|
1937
|
-
sessionRef
|
|
1966
|
+
sessionRef
|
|
1938
1967
|
};
|
|
1939
|
-
if (agentRef !== void 0 && egressPolicy !== void 0) {
|
|
1968
|
+
if (agentRef !== void 0 && egressPolicy !== void 0 && freshAgentEgress) {
|
|
1969
|
+
const freshOffer = {
|
|
1970
|
+
instruction: input.instruction,
|
|
1971
|
+
policy,
|
|
1972
|
+
runtime,
|
|
1973
|
+
dispatchSelection,
|
|
1974
|
+
agentRef,
|
|
1975
|
+
egressPolicy,
|
|
1976
|
+
...requiredToolsets === void 0 ? {} : { requiredToolsets }
|
|
1977
|
+
};
|
|
1978
|
+
this.sendToDevice(
|
|
1979
|
+
deviceId,
|
|
1980
|
+
"task.offer_for_agent_with_egress_fresh",
|
|
1981
|
+
freshOffer,
|
|
1982
|
+
{ taskId }
|
|
1983
|
+
);
|
|
1984
|
+
} else if (agentRef !== void 0 && egressPolicy !== void 0) {
|
|
1940
1985
|
this.sendToDevice(
|
|
1941
1986
|
deviceId,
|
|
1942
1987
|
"task.offer_for_agent_with_egress",
|
|
1943
1988
|
{
|
|
1944
1989
|
...commonOffer,
|
|
1945
|
-
sessionRef
|
|
1990
|
+
sessionRef,
|
|
1946
1991
|
agentRef,
|
|
1947
1992
|
egressPolicy,
|
|
1948
1993
|
...requiredToolsets === void 0 ? {} : { requiredToolsets }
|
|
1949
1994
|
},
|
|
1950
|
-
{ taskId, sessionRef
|
|
1995
|
+
{ taskId, sessionRef }
|
|
1951
1996
|
);
|
|
1952
1997
|
} else if (agentRef !== void 0) {
|
|
1953
1998
|
this.sendToDevice(
|
|
1954
1999
|
deviceId,
|
|
1955
2000
|
"task.offer_for_agent",
|
|
1956
2001
|
{ ...commonOffer, agentRef, ...requiredToolsets === void 0 ? {} : { requiredToolsets } },
|
|
1957
|
-
{ taskId, sessionRef
|
|
2002
|
+
{ taskId, sessionRef }
|
|
1958
2003
|
);
|
|
1959
2004
|
} else if (requiredToolsets === void 0) {
|
|
1960
|
-
this.sendToDevice(deviceId, "task.offer", commonOffer, { taskId, sessionRef
|
|
2005
|
+
this.sendToDevice(deviceId, "task.offer", commonOffer, { taskId, sessionRef });
|
|
1961
2006
|
} else {
|
|
1962
2007
|
this.sendToDevice(
|
|
1963
2008
|
deviceId,
|
|
1964
2009
|
"task.offer_with_toolsets",
|
|
1965
2010
|
{ ...commonOffer, requiredToolsets },
|
|
1966
|
-
{ taskId, sessionRef
|
|
2011
|
+
{ taskId, sessionRef }
|
|
1967
2012
|
);
|
|
1968
2013
|
}
|
|
1969
2014
|
return this.buildTaskHandle(taskId);
|
|
@@ -3027,6 +3072,7 @@ function createByokServer(opts) {
|
|
|
3027
3072
|
createPairingCode: (claims) => pairing.createPairingCode(claims)
|
|
3028
3073
|
},
|
|
3029
3074
|
dispatch: (input) => hub.dispatch(input),
|
|
3075
|
+
dispatchFreshAgentEgress: (input) => hub.dispatchFreshAgentEgress(input),
|
|
3030
3076
|
requestAgentContentRead: (input) => hub.requestAgentContentRead(input),
|
|
3031
3077
|
tasks: {
|
|
3032
3078
|
get: (taskId) => hub.getTask(taskId),
|