@byok-sdk/server 0.8.0 → 0.9.0-rc.1
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 +18 -2
- package/dist/index.js +82 -7
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +22 -1
- package/package.json +3 -3
package/dist/hub.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { WebSocket } from 'ws';
|
|
2
|
-
import { type Envelope, type AgentHomeProjectionCompletionRequest, type AgentHomeProjectionReadback, type RuntimeId, type RuntimeInfo, type TaskState, type ToolsetId } from '@byok-sdk/protocol';
|
|
2
|
+
import { type Envelope, type AgentMessagePublishPayload, type AgentMessageServerContext, type AgentHomeProjectionCompletionRequest, type AgentHomeProjectionReadback, type RuntimeId, type RuntimeInfo, type TaskState, type ToolsetId } from '@byok-sdk/protocol';
|
|
3
3
|
import type { DeviceRegistry } from './auth';
|
|
4
4
|
import { RateLimiter } from './rate-limiter';
|
|
5
5
|
import type { TaskStore } from './task-store';
|
|
@@ -209,6 +209,7 @@ export declare class ConnectionHub {
|
|
|
209
209
|
* working unchanged.
|
|
210
210
|
*/
|
|
211
211
|
private readonly rateLimiter;
|
|
212
|
+
private readonly agentMessage?;
|
|
212
213
|
private readonly connections;
|
|
213
214
|
private readonly outboxes;
|
|
214
215
|
/** Idempotency window per device (N3) — recent inbound envelope ids, capped at {@link DEDUP_RING_CAPACITY}. */
|
|
@@ -218,6 +219,9 @@ export declare class ConnectionHub {
|
|
|
218
219
|
private readonly serverEvents;
|
|
219
220
|
/** First-write-wins reliable facts; the reference composition's bounded in-memory readback. */
|
|
220
221
|
private readonly agentEgressReceipts;
|
|
222
|
+
private readonly agentMessageRequirements;
|
|
223
|
+
private readonly agentMessageReceipts;
|
|
224
|
+
private readonly agentMessageTaskPayloads;
|
|
221
225
|
/** Accepted requests are the authority that later receipts/transfers must echo exactly. */
|
|
222
226
|
private readonly agentContentReadRequests;
|
|
223
227
|
/** Content-free explicit-read audit facts keyed by exact authenticated device/request identity. */
|
|
@@ -267,7 +271,17 @@ export declare class ConnectionHub {
|
|
|
267
271
|
* call site (this hub is constructed directly by several tests) keeps
|
|
268
272
|
* working unchanged.
|
|
269
273
|
*/
|
|
270
|
-
rateLimiter?: RateLimiter
|
|
274
|
+
rateLimiter?: RateLimiter, agentMessage?: {
|
|
275
|
+
consume(input: {
|
|
276
|
+
readonly deviceId: string;
|
|
277
|
+
readonly taskId: string;
|
|
278
|
+
readonly context: AgentMessageServerContext;
|
|
279
|
+
readonly payload: AgentMessagePublishPayload;
|
|
280
|
+
}): {
|
|
281
|
+
readonly outcome: 'accepted' | 'held' | 'refused';
|
|
282
|
+
readonly reasonCode?: string;
|
|
283
|
+
};
|
|
284
|
+
} | undefined);
|
|
271
285
|
/**
|
|
272
286
|
* Stop the task-lease reaper's sweep timer — called by `ByokServer.stop()`
|
|
273
287
|
* (`index.ts`) on shutdown. Idempotent: clearing an already-cleared
|
|
@@ -380,6 +394,8 @@ export declare class ConnectionHub {
|
|
|
380
394
|
* facts is rejected rather than treated as an update.
|
|
381
395
|
*/
|
|
382
396
|
private handleAgentEgressReliable;
|
|
397
|
+
private handleAgentMessagePublish;
|
|
398
|
+
private sendAgentMessageDisposition;
|
|
383
399
|
private handleAgentContentReceipt;
|
|
384
400
|
private sendAgentEgressAck;
|
|
385
401
|
private sendAgentContentReceiptAck;
|
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, AGENT_EGRESS_FRESH_SESSION_CAPABILITY, AgentContentReadPayloadSchema, AgentHomeProjectionPayloadSchema, AGENT_HOME_PROJECTION_CAPABILITY, AgentHomeProjectionReadbackSchema, AgentHomeProjectionCompletionRequestSchema, 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, BYOK_AGENT_HOME_PROJECTION_COMPLETION_ROUTE, AGENT_CONTENT_ARTIFACT_READ_CAPABILITY, AGENT_CONTENT_TRANSCRIPT_READ_CAPABILITY, AGENT_CONTENT_WORKSPACE_READ_CAPABILITY, PairResponseTenantIdSchema, 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, AGENT_MESSAGE_EGRESS_CAPABILITY, AgentRefSchema, AgentEgressPolicySchema, AgentMessageEgressRequirementSchema, TerminalProjectionSelectionSchema, AgentMessageServerContextSchema, DispatchSelectionSchema, RequiredToolsetsSchema, STRICT_AGENT_ONLY_CAPABILITY, AGENT_EGRESS_FRESH_SESSION_CAPABILITY, TERMINAL_PROJECTION_SELECTION_CAPABILITY, AgentContentReadPayloadSchema, AgentHomeProjectionPayloadSchema, AGENT_HOME_PROJECTION_CAPABILITY, AgentHomeProjectionReadbackSchema, AgentHomeProjectionCompletionRequestSchema, 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, BYOK_AGENT_HOME_PROJECTION_COMPLETION_ROUTE, 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';
|
|
@@ -540,11 +540,12 @@ var AgentHomeProjectionCompletionError = class extends Error {
|
|
|
540
540
|
code;
|
|
541
541
|
};
|
|
542
542
|
var ConnectionHub = class {
|
|
543
|
-
constructor(taskStore, devices, taskLeaseMs, rateLimiter = new RateLimiter()) {
|
|
543
|
+
constructor(taskStore, devices, taskLeaseMs, rateLimiter = new RateLimiter(), agentMessage) {
|
|
544
544
|
this.taskStore = taskStore;
|
|
545
545
|
this.devices = devices;
|
|
546
546
|
this.taskLeaseMs = taskLeaseMs;
|
|
547
547
|
this.rateLimiter = rateLimiter;
|
|
548
|
+
this.agentMessage = agentMessage;
|
|
548
549
|
const sweepIntervalMs = Math.min(Math.max(taskLeaseMs, 10), MAX_LEASE_REAPER_SWEEP_INTERVAL_MS);
|
|
549
550
|
this.leaseReaperTimer = setInterval(() => this.sweepLeases(), sweepIntervalMs);
|
|
550
551
|
this.leaseReaperTimer.unref?.();
|
|
@@ -553,6 +554,7 @@ var ConnectionHub = class {
|
|
|
553
554
|
devices;
|
|
554
555
|
taskLeaseMs;
|
|
555
556
|
rateLimiter;
|
|
557
|
+
agentMessage;
|
|
556
558
|
connections = /* @__PURE__ */ new Map();
|
|
557
559
|
outboxes = /* @__PURE__ */ new Map();
|
|
558
560
|
/** Idempotency window per device (N3) — recent inbound envelope ids, capped at {@link DEDUP_RING_CAPACITY}. */
|
|
@@ -562,6 +564,9 @@ var ConnectionHub = class {
|
|
|
562
564
|
serverEvents = new AsyncEventQueue();
|
|
563
565
|
/** First-write-wins reliable facts; the reference composition's bounded in-memory readback. */
|
|
564
566
|
agentEgressReceipts = /* @__PURE__ */ new Map();
|
|
567
|
+
agentMessageRequirements = /* @__PURE__ */ new Map();
|
|
568
|
+
agentMessageReceipts = /* @__PURE__ */ new Map();
|
|
569
|
+
agentMessageTaskPayloads = /* @__PURE__ */ new Map();
|
|
565
570
|
/** Accepted requests are the authority that later receipts/transfers must echo exactly. */
|
|
566
571
|
agentContentReadRequests = /* @__PURE__ */ new Map();
|
|
567
572
|
/** Content-free explicit-read audit facts keyed by exact authenticated device/request identity. */
|
|
@@ -824,6 +829,9 @@ var ConnectionHub = class {
|
|
|
824
829
|
if (envelope.type === "agent.egress.reliable") {
|
|
825
830
|
return this.handleAgentEgressReliable(deviceId, envelope.payload);
|
|
826
831
|
}
|
|
832
|
+
if (envelope.type === "agent.message.publish") {
|
|
833
|
+
return this.handleAgentMessagePublish(deviceId, envelope.task_id, envelope.payload);
|
|
834
|
+
}
|
|
827
835
|
if (envelope.type === "agent.content.receipt") {
|
|
828
836
|
return this.handleAgentContentReceipt(deviceId, envelope.payload);
|
|
829
837
|
}
|
|
@@ -868,6 +876,40 @@ var ConnectionHub = class {
|
|
|
868
876
|
this.sendAgentEgressAck(deviceId, receipt);
|
|
869
877
|
return "accepted";
|
|
870
878
|
}
|
|
879
|
+
handleAgentMessagePublish(deviceId, taskId, payload) {
|
|
880
|
+
if (!this.hasDeviceCapabilities(deviceId, [AGENT_MESSAGE_EGRESS_CAPABILITY])) return "rejected";
|
|
881
|
+
const binding = this.agentMessageRequirements.get(taskId);
|
|
882
|
+
const record = this.taskStore.get(taskId);
|
|
883
|
+
if (binding === void 0 || record === void 0 || record.deviceId !== deviceId || binding.deviceId !== deviceId || !sameAgentRef(binding.agentRef, payload.agentRef) || binding.sessionRef !== void 0 && binding.sessionRef !== payload.sessionRef || binding.requirement.contract !== payload.contract || binding.requirement.contentType !== payload.contentType || payload.byteCount > binding.requirement.maxBytes) return "rejected";
|
|
884
|
+
const taskPayload = this.agentMessageTaskPayloads.get(taskId);
|
|
885
|
+
if (taskPayload !== void 0 && JSON.stringify(taskPayload) !== JSON.stringify(payload)) return "rejected";
|
|
886
|
+
if (taskPayload === void 0) this.agentMessageTaskPayloads.set(taskId, payload);
|
|
887
|
+
const key = `${deviceId}\0${payload.messageId}`;
|
|
888
|
+
const previous = this.agentMessageReceipts.get(key);
|
|
889
|
+
if (previous !== void 0) {
|
|
890
|
+
if (JSON.stringify(previous.payload) !== JSON.stringify(payload)) return "rejected";
|
|
891
|
+
this.sendAgentMessageDisposition(deviceId, taskId, previous.disposition);
|
|
892
|
+
return "duplicate";
|
|
893
|
+
}
|
|
894
|
+
const decision = this.agentMessage?.consume({ deviceId, taskId, context: binding.context, payload }) ?? { outcome: "held", reasonCode: "consumer_unavailable" };
|
|
895
|
+
const disposition = {
|
|
896
|
+
agentRef: payload.agentRef,
|
|
897
|
+
sessionRef: payload.sessionRef,
|
|
898
|
+
contract: payload.contract,
|
|
899
|
+
messageId: payload.messageId,
|
|
900
|
+
cursor: payload.cursor,
|
|
901
|
+
contentHash: payload.contentHash,
|
|
902
|
+
outcome: decision.outcome,
|
|
903
|
+
receiptId: crypto.randomUUID(),
|
|
904
|
+
...decision.reasonCode === void 0 ? {} : { reasonCode: decision.reasonCode }
|
|
905
|
+
};
|
|
906
|
+
this.agentMessageReceipts.set(key, { payload, disposition });
|
|
907
|
+
this.sendAgentMessageDisposition(deviceId, taskId, disposition);
|
|
908
|
+
return "accepted";
|
|
909
|
+
}
|
|
910
|
+
sendAgentMessageDisposition(deviceId, taskId, payload) {
|
|
911
|
+
this.sendToDevice(deviceId, "agent.message.disposition", payload, { taskId });
|
|
912
|
+
}
|
|
871
913
|
handleAgentContentReceipt(deviceId, payload) {
|
|
872
914
|
const capability = contentReadCapability(payload.surface);
|
|
873
915
|
if (!this.hasDeviceCapabilities(deviceId, [capability, AGENT_EGRESS_RELIABLE_ACK_CAPABILITY])) return "rejected";
|
|
@@ -1627,20 +1669,34 @@ var ConnectionHub = class {
|
|
|
1627
1669
|
const sessionRef = "sessionRef" in input ? input.sessionRef : void 0;
|
|
1628
1670
|
const agentRef = input.agentRef === void 0 ? void 0 : AgentRefSchema.parse(input.agentRef);
|
|
1629
1671
|
const egressPolicy = input.egressPolicy === void 0 ? void 0 : AgentEgressPolicySchema.parse(input.egressPolicy);
|
|
1672
|
+
const messageEgress = input.messageEgress === void 0 ? void 0 : AgentMessageEgressRequirementSchema.parse(input.messageEgress);
|
|
1673
|
+
const terminalProjection = input.terminalProjection === void 0 ? void 0 : TerminalProjectionSelectionSchema.parse(input.terminalProjection);
|
|
1674
|
+
if (messageEgress === void 0 && input.agentMessageContext !== void 0) {
|
|
1675
|
+
throw new Error("agentMessageContext requires messageEgress");
|
|
1676
|
+
}
|
|
1677
|
+
const agentMessageContext = messageEgress === void 0 ? void 0 : AgentMessageServerContextSchema.parse(input.agentMessageContext);
|
|
1630
1678
|
const dispatchSelection = input.dispatchSelection === void 0 ? void 0 : DispatchSelectionSchema.parse(input.dispatchSelection);
|
|
1631
1679
|
const requiredToolsets = input.requiredToolsets === void 0 ? void 0 : RequiredToolsetsSchema.parse(input.requiredToolsets);
|
|
1632
|
-
const deviceId = input.deviceId ?? this.pickFirstConnectedDevice(requiredToolsets);
|
|
1680
|
+
const deviceId = input.deviceId ?? this.pickFirstConnectedDevice(requiredToolsets, agentRef !== void 0);
|
|
1633
1681
|
if (agentRef !== void 0 && input.deviceId === void 0) {
|
|
1634
1682
|
throw new Error("Agent-bound dispatch requires an explicit deviceId for capability admission");
|
|
1635
1683
|
}
|
|
1636
1684
|
if (egressPolicy !== void 0 && agentRef === void 0) {
|
|
1637
1685
|
throw new Error("Agent egress policy requires an explicit AgentRef; legacy task dispatch cannot consume it");
|
|
1638
1686
|
}
|
|
1687
|
+
if (messageEgress !== void 0 && egressPolicy === void 0) {
|
|
1688
|
+
throw new Error("Agent message egress requires the typed Agent egress offer path");
|
|
1689
|
+
}
|
|
1639
1690
|
if (!deviceId || !this.connections.get(deviceId)?.connected) {
|
|
1640
1691
|
throw new Error(
|
|
1641
1692
|
deviceId ? `device ${deviceId} is not connected` : "no connected device to dispatch to (M0 does not queue tasks until a device connects)"
|
|
1642
1693
|
);
|
|
1643
1694
|
}
|
|
1695
|
+
if (agentRef === void 0 && this.getDeviceCapabilities(deviceId)?.includes(STRICT_AGENT_ONLY_CAPABILITY) === true) {
|
|
1696
|
+
throw new Error(
|
|
1697
|
+
`device ${deviceId} advertises strict-agent-only; legacy task dispatch is refused before enqueue`
|
|
1698
|
+
);
|
|
1699
|
+
}
|
|
1644
1700
|
if (agentRef !== void 0 && !(this.getDeviceCapabilities(deviceId)?.includes("agent-home-contract") ?? false)) {
|
|
1645
1701
|
throw new Error(
|
|
1646
1702
|
`device ${deviceId} did not advertise agent-home-contract capability; refusing Agent-bound dispatch`
|
|
@@ -1656,6 +1712,12 @@ var ConnectionHub = class {
|
|
|
1656
1712
|
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`
|
|
1657
1713
|
);
|
|
1658
1714
|
}
|
|
1715
|
+
if (messageEgress !== void 0 && !this.hasDeviceCapabilities(deviceId, [AGENT_MESSAGE_EGRESS_CAPABILITY])) {
|
|
1716
|
+
throw new Error(`device ${deviceId} did not advertise Agent message egress capability; refusing before enqueue`);
|
|
1717
|
+
}
|
|
1718
|
+
if (terminalProjection !== void 0 && !this.hasDeviceCapabilities(deviceId, [TERMINAL_PROJECTION_SELECTION_CAPABILITY])) {
|
|
1719
|
+
throw new Error(`device ${deviceId} did not advertise terminal projection selection capability; refusing before enqueue`);
|
|
1720
|
+
}
|
|
1659
1721
|
if (dispatchSelection !== void 0 && !(this.getDeviceCapabilities(deviceId)?.includes("dispatch-selection") ?? false)) {
|
|
1660
1722
|
throw new Error(
|
|
1661
1723
|
`device ${deviceId} did not advertise dispatch-selection capability; refusing authoritative provider/model dispatch`
|
|
@@ -1705,6 +1767,9 @@ var ConnectionHub = class {
|
|
|
1705
1767
|
resolveResult = resolve;
|
|
1706
1768
|
});
|
|
1707
1769
|
this.runtimes.set(taskId, { queue, resolveResult, result });
|
|
1770
|
+
if (messageEgress !== void 0 && agentRef !== void 0) {
|
|
1771
|
+
this.agentMessageRequirements.set(taskId, { deviceId, agentRef, sessionRef, requirement: messageEgress, context: agentMessageContext });
|
|
1772
|
+
}
|
|
1708
1773
|
queue.push({ kind: "state", state: record.state, at: record.createdAt });
|
|
1709
1774
|
this.serverEvents.push({ kind: "task.created", taskId, at: record.createdAt });
|
|
1710
1775
|
const commonOffer = {
|
|
@@ -1722,6 +1787,8 @@ var ConnectionHub = class {
|
|
|
1722
1787
|
dispatchSelection,
|
|
1723
1788
|
agentRef,
|
|
1724
1789
|
egressPolicy,
|
|
1790
|
+
terminalProjection,
|
|
1791
|
+
...messageEgress === void 0 ? {} : { messageEgress },
|
|
1725
1792
|
...requiredToolsets === void 0 ? {} : { requiredToolsets }
|
|
1726
1793
|
};
|
|
1727
1794
|
this.sendToDevice(
|
|
@@ -1739,6 +1806,8 @@ var ConnectionHub = class {
|
|
|
1739
1806
|
sessionRef,
|
|
1740
1807
|
agentRef,
|
|
1741
1808
|
egressPolicy,
|
|
1809
|
+
terminalProjection,
|
|
1810
|
+
...messageEgress === void 0 ? {} : { messageEgress },
|
|
1742
1811
|
...requiredToolsets === void 0 ? {} : { requiredToolsets }
|
|
1743
1812
|
},
|
|
1744
1813
|
{ taskId, sessionRef }
|
|
@@ -1747,7 +1816,12 @@ var ConnectionHub = class {
|
|
|
1747
1816
|
this.sendToDevice(
|
|
1748
1817
|
deviceId,
|
|
1749
1818
|
"task.offer_for_agent",
|
|
1750
|
-
{
|
|
1819
|
+
{
|
|
1820
|
+
...commonOffer,
|
|
1821
|
+
agentRef,
|
|
1822
|
+
...terminalProjection === void 0 ? {} : { terminalProjection },
|
|
1823
|
+
...requiredToolsets === void 0 ? {} : { requiredToolsets }
|
|
1824
|
+
},
|
|
1751
1825
|
{ taskId, sessionRef }
|
|
1752
1826
|
);
|
|
1753
1827
|
} else if (requiredToolsets === void 0) {
|
|
@@ -2005,9 +2079,10 @@ var ConnectionHub = class {
|
|
|
2005
2079
|
}
|
|
2006
2080
|
this.sendToDevice(record.deviceId, "task.steer", { text }, { taskId });
|
|
2007
2081
|
}
|
|
2008
|
-
pickFirstConnectedDevice(requiredToolsets) {
|
|
2082
|
+
pickFirstConnectedDevice(requiredToolsets, allowStrictAgentOnly = false) {
|
|
2009
2083
|
for (const [deviceId, conn] of this.connections) {
|
|
2010
2084
|
if (!conn.connected) continue;
|
|
2085
|
+
if (!allowStrictAgentOnly && conn.capabilities?.includes(STRICT_AGENT_ONLY_CAPABILITY)) continue;
|
|
2011
2086
|
if (requiredToolsets === void 0) return deviceId;
|
|
2012
2087
|
if (!conn.capabilities?.includes("toolset-selection")) continue;
|
|
2013
2088
|
if (conn.configuredToolsets === void 0) continue;
|
|
@@ -2039,7 +2114,7 @@ var ConnectionHub = class {
|
|
|
2039
2114
|
const envelope = createEnvelope(type, payload, combinedOpts);
|
|
2040
2115
|
const taskId = opts.taskId;
|
|
2041
2116
|
const redeliverThroughTerminal = type === "task.cancel" || type === "task.reject";
|
|
2042
|
-
const redeliverWithoutTask = type === "agent.egress.ack" || type === "agent.content.read" || type === "agent.home.projection";
|
|
2117
|
+
const redeliverWithoutTask = type === "agent.egress.ack" || type === "agent.content.read" || type === "agent.home.projection" || type === "agent.message.disposition";
|
|
2043
2118
|
outbox.ring.push({ seq, taskId, envelope, redeliverThroughTerminal, redeliverWithoutTask });
|
|
2044
2119
|
if (outbox.ring.length > OUTBOX_RING_CAPACITY) outbox.ring.shift();
|
|
2045
2120
|
this.deliverToDevice(deviceId, envelope);
|
|
@@ -3145,7 +3220,7 @@ function createByokServer(opts) {
|
|
|
3145
3220
|
const taskLeaseMs = opts.taskLeaseMs ?? DEFAULT_TASK_LEASE_MS;
|
|
3146
3221
|
const rateLimiter = new RateLimiter(opts.rateLimit);
|
|
3147
3222
|
const taskStore = opts.taskStore ?? new InMemoryTaskStore();
|
|
3148
|
-
const hub = new ConnectionHub(taskStore, devices, taskLeaseMs, rateLimiter);
|
|
3223
|
+
const hub = new ConnectionHub(taskStore, devices, taskLeaseMs, rateLimiter, opts.agentMessage);
|
|
3149
3224
|
const hono = buildHonoApp({
|
|
3150
3225
|
pairing,
|
|
3151
3226
|
devices,
|