@masons/agent-network 0.5.321 → 0.5.323
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/runtime-endpoint-client.d.ts +10 -0
- package/dist/runtime-endpoint-client.d.ts.map +1 -1
- package/dist/runtime-endpoint-client.js +79 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +14 -22
- package/dist/broker/broker-daemon.d.ts +0 -57
- package/dist/broker/broker-daemon.d.ts.map +0 -1
- package/dist/broker/broker-daemon.js +0 -759
- package/dist/broker/claude-code-spawn-driver.d.ts +0 -14
- package/dist/broker/claude-code-spawn-driver.d.ts.map +0 -1
- package/dist/broker/claude-code-spawn-driver.js +0 -39
- package/dist/broker/closed-endpoint-lookup.d.ts +0 -25
- package/dist/broker/closed-endpoint-lookup.d.ts.map +0 -1
- package/dist/broker/closed-endpoint-lookup.js +0 -59
- package/dist/broker/codex-spawn-driver-stub.d.ts +0 -7
- package/dist/broker/codex-spawn-driver-stub.d.ts.map +0 -1
- package/dist/broker/codex-spawn-driver-stub.js +0 -13
- package/dist/broker/connector-ws.d.ts +0 -47
- package/dist/broker/connector-ws.d.ts.map +0 -1
- package/dist/broker/connector-ws.js +0 -60
- package/dist/broker/control-event-dispatcher.d.ts +0 -21
- package/dist/broker/control-event-dispatcher.d.ts.map +0 -1
- package/dist/broker/control-event-dispatcher.js +0 -45
- package/dist/broker/control-event-types.d.ts +0 -28
- package/dist/broker/control-event-types.d.ts.map +0 -1
- package/dist/broker/control-event-types.js +0 -1
- package/dist/broker/correlation-ring.d.ts +0 -10
- package/dist/broker/correlation-ring.d.ts.map +0 -1
- package/dist/broker/correlation-ring.js +0 -32
- package/dist/broker/discovery-file.d.ts +0 -12
- package/dist/broker/discovery-file.d.ts.map +0 -1
- package/dist/broker/discovery-file.js +0 -77
- package/dist/broker/endpoint-registry.d.ts +0 -53
- package/dist/broker/endpoint-registry.d.ts.map +0 -1
- package/dist/broker/endpoint-registry.js +0 -83
- package/dist/broker/endpoint-state-machine.d.ts +0 -40
- package/dist/broker/endpoint-state-machine.d.ts.map +0 -1
- package/dist/broker/endpoint-state-machine.js +0 -92
- package/dist/broker/entry.d.ts +0 -13
- package/dist/broker/entry.d.ts.map +0 -1
- package/dist/broker/entry.js +0 -229
- package/dist/broker/grace-timer.d.ts +0 -9
- package/dist/broker/grace-timer.d.ts.map +0 -1
- package/dist/broker/grace-timer.js +0 -34
- package/dist/broker/ipc-server.d.ts +0 -79
- package/dist/broker/ipc-server.d.ts.map +0 -1
- package/dist/broker/ipc-server.js +0 -263
- package/dist/broker/logger.d.ts +0 -10
- package/dist/broker/logger.d.ts.map +0 -1
- package/dist/broker/logger.js +0 -34
- package/dist/broker/network-presence.d.ts +0 -31
- package/dist/broker/network-presence.d.ts.map +0 -1
- package/dist/broker/network-presence.js +0 -109
- package/dist/broker/paths.d.ts +0 -11
- package/dist/broker/paths.d.ts.map +0 -1
- package/dist/broker/paths.js +0 -30
- package/dist/broker/plugin-liveness.d.ts +0 -2
- package/dist/broker/plugin-liveness.d.ts.map +0 -1
- package/dist/broker/plugin-liveness.js +0 -15
- package/dist/broker/received-message-correlation-cache.d.ts +0 -23
- package/dist/broker/received-message-correlation-cache.d.ts.map +0 -1
- package/dist/broker/received-message-correlation-cache.js +0 -114
- package/dist/broker/reconnecting-buffer.d.ts +0 -23
- package/dist/broker/reconnecting-buffer.d.ts.map +0 -1
- package/dist/broker/reconnecting-buffer.js +0 -107
- package/dist/broker/routing-table.d.ts +0 -22
- package/dist/broker/routing-table.d.ts.map +0 -1
- package/dist/broker/routing-table.js +0 -35
- package/dist/broker/runtime-endpoint-port.d.ts +0 -8
- package/dist/broker/runtime-endpoint-port.d.ts.map +0 -1
- package/dist/broker/runtime-endpoint-port.js +0 -1
- package/dist/broker/services-event-client.d.ts +0 -21
- package/dist/broker/services-event-client.d.ts.map +0 -1
- package/dist/broker/services-event-client.js +0 -221
- package/dist/broker/spawn-correlation.d.ts +0 -28
- package/dist/broker/spawn-correlation.d.ts.map +0 -1
- package/dist/broker/spawn-correlation.js +0 -77
- package/dist/broker/spawn-driver.d.ts +0 -27
- package/dist/broker/spawn-driver.d.ts.map +0 -1
- package/dist/broker/spawn-driver.js +0 -15
- package/dist/broker/task-hint-handler.d.ts +0 -21
- package/dist/broker/task-hint-handler.d.ts.map +0 -1
- package/dist/broker/task-hint-handler.js +0 -33
- package/dist/broker/transition-state-retry-queue.d.ts +0 -20
- package/dist/broker/transition-state-retry-queue.d.ts.map +0 -1
- package/dist/broker/transition-state-retry-queue.js +0 -48
- package/dist/broker/undispatched-inbox.d.ts +0 -26
- package/dist/broker/undispatched-inbox.d.ts.map +0 -1
- package/dist/broker/undispatched-inbox.js +0 -53
- package/dist/broker/version-handshake.d.ts +0 -30
- package/dist/broker/version-handshake.d.ts.map +0 -1
- package/dist/broker/version-handshake.js +0 -47
- package/dist/broker-client/broker-client.d.ts +0 -65
- package/dist/broker-client/broker-client.d.ts.map +0 -1
- package/dist/broker-client/broker-client.js +0 -165
- package/dist/broker-client/lazy-spawn.d.ts +0 -18
- package/dist/broker-client/lazy-spawn.d.ts.map +0 -1
- package/dist/broker-client/lazy-spawn.js +0 -61
- package/dist/session-lifecycle.d.ts +0 -89
- package/dist/session-lifecycle.d.ts.map +0 -1
- package/dist/session-lifecycle.js +0 -348
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
export interface BufferedMessage {
|
|
2
|
-
id: string;
|
|
3
|
-
arrived_at: string;
|
|
4
|
-
envelope: {
|
|
5
|
-
from: string;
|
|
6
|
-
content: string;
|
|
7
|
-
contentType: string;
|
|
8
|
-
metadata?: Record<string, unknown>;
|
|
9
|
-
};
|
|
10
|
-
}
|
|
11
|
-
export interface ReconnectingBuffer {
|
|
12
|
-
append(msg: BufferedMessage): void;
|
|
13
|
-
read(): BufferedMessage[];
|
|
14
|
-
drain(): BufferedMessage[];
|
|
15
|
-
delete(): void;
|
|
16
|
-
size(): number;
|
|
17
|
-
}
|
|
18
|
-
export interface ReconnectingBufferManager {
|
|
19
|
-
forEndpoint(endpoint_id: string): ReconnectingBuffer;
|
|
20
|
-
cleanup(endpoint_id: string): void;
|
|
21
|
-
}
|
|
22
|
-
export declare function createReconnectingBufferManager(buffersDir: string): ReconnectingBufferManager;
|
|
23
|
-
//# sourceMappingURL=reconnecting-buffer.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"reconnecting-buffer.d.ts","sourceRoot":"","sources":["../../src/broker/reconnecting-buffer.ts"],"names":[],"mappings":"AA+CA,MAAM,WAAW,eAAe;IAE9B,EAAE,EAAE,MAAM,CAAC;IAEX,UAAU,EAAE,MAAM,CAAC;IAEnB,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACpC,CAAC;CACH;AAED,MAAM,WAAW,kBAAkB;IAEjC,MAAM,CAAC,GAAG,EAAE,eAAe,GAAG,IAAI,CAAC;IAEnC,IAAI,IAAI,eAAe,EAAE,CAAC;IAE1B,KAAK,IAAI,eAAe,EAAE,CAAC;IAE3B,MAAM,IAAI,IAAI,CAAC;IAEf,IAAI,IAAI,MAAM,CAAC;CAChB;AA8ED,MAAM,WAAW,yBAAyB;IAExC,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,kBAAkB,CAAC;IAErD,OAAO,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CACpC;AAED,wBAAgB,+BAA+B,CAC7C,UAAU,EAAE,MAAM,GACjB,yBAAyB,CAmB3B"}
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
import { closeSync, fdatasyncSync, mkdirSync, openSync, readFileSync, unlinkSync, writeSync, } from "node:fs";
|
|
2
|
-
import { join } from "node:path";
|
|
3
|
-
class FileBackedBuffer {
|
|
4
|
-
path;
|
|
5
|
-
cached = null;
|
|
6
|
-
constructor(path) {
|
|
7
|
-
this.path = path;
|
|
8
|
-
}
|
|
9
|
-
append(msg) {
|
|
10
|
-
const line = `${JSON.stringify(msg)}\n`;
|
|
11
|
-
try {
|
|
12
|
-
mkdirSync(dirname(this.path), { recursive: true, mode: 0o700 });
|
|
13
|
-
}
|
|
14
|
-
catch {
|
|
15
|
-
}
|
|
16
|
-
const fd = openSync(this.path, "a", 0o600);
|
|
17
|
-
try {
|
|
18
|
-
writeSync(fd, line);
|
|
19
|
-
fdatasyncSync(fd);
|
|
20
|
-
}
|
|
21
|
-
finally {
|
|
22
|
-
closeSync(fd);
|
|
23
|
-
}
|
|
24
|
-
this.cached = null;
|
|
25
|
-
}
|
|
26
|
-
read() {
|
|
27
|
-
if (this.cached !== null)
|
|
28
|
-
return [...this.cached];
|
|
29
|
-
let raw;
|
|
30
|
-
try {
|
|
31
|
-
raw = readFileSync(this.path, "utf8");
|
|
32
|
-
}
|
|
33
|
-
catch (err) {
|
|
34
|
-
if (isNodeErr(err, "ENOENT")) {
|
|
35
|
-
this.cached = [];
|
|
36
|
-
return [];
|
|
37
|
-
}
|
|
38
|
-
throw err;
|
|
39
|
-
}
|
|
40
|
-
const lines = raw.split("\n").filter((l) => l.length > 0);
|
|
41
|
-
const parsed = [];
|
|
42
|
-
for (const line of lines) {
|
|
43
|
-
try {
|
|
44
|
-
parsed.push(JSON.parse(line));
|
|
45
|
-
}
|
|
46
|
-
catch {
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
this.cached = parsed;
|
|
50
|
-
return [...parsed];
|
|
51
|
-
}
|
|
52
|
-
drain() {
|
|
53
|
-
const out = this.read();
|
|
54
|
-
this.delete();
|
|
55
|
-
return out;
|
|
56
|
-
}
|
|
57
|
-
delete() {
|
|
58
|
-
try {
|
|
59
|
-
unlinkSync(this.path);
|
|
60
|
-
}
|
|
61
|
-
catch (err) {
|
|
62
|
-
if (isNodeErr(err, "ENOENT")) {
|
|
63
|
-
}
|
|
64
|
-
else {
|
|
65
|
-
throw err;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
this.cached = [];
|
|
69
|
-
}
|
|
70
|
-
size() {
|
|
71
|
-
if (this.cached !== null)
|
|
72
|
-
return this.cached.length;
|
|
73
|
-
return this.read().length;
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
export function createReconnectingBufferManager(buffersDir) {
|
|
77
|
-
const cache = new Map();
|
|
78
|
-
return {
|
|
79
|
-
forEndpoint(endpoint_id) {
|
|
80
|
-
let buf = cache.get(endpoint_id);
|
|
81
|
-
if (!buf) {
|
|
82
|
-
buf = new FileBackedBuffer(join(buffersDir, `${sanitizeId(endpoint_id)}.ndjson`));
|
|
83
|
-
cache.set(endpoint_id, buf);
|
|
84
|
-
}
|
|
85
|
-
return buf;
|
|
86
|
-
},
|
|
87
|
-
cleanup(endpoint_id) {
|
|
88
|
-
const buf = cache.get(endpoint_id);
|
|
89
|
-
if (buf)
|
|
90
|
-
buf.delete();
|
|
91
|
-
cache.delete(endpoint_id);
|
|
92
|
-
},
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
function sanitizeId(id) {
|
|
96
|
-
return id.replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
97
|
-
}
|
|
98
|
-
function dirname(p) {
|
|
99
|
-
const idx = p.lastIndexOf("/");
|
|
100
|
-
return idx >= 0 ? p.slice(0, idx) : ".";
|
|
101
|
-
}
|
|
102
|
-
function isNodeErr(err, code) {
|
|
103
|
-
return (typeof err === "object" &&
|
|
104
|
-
err !== null &&
|
|
105
|
-
"code" in err &&
|
|
106
|
-
err.code === code);
|
|
107
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import type { BrokerEndpointEntry, EndpointRegistry } from "./endpoint-registry.js";
|
|
2
|
-
export interface InboundMessageMeta {
|
|
3
|
-
target_endpoint_id?: string;
|
|
4
|
-
correlation_id?: string;
|
|
5
|
-
}
|
|
6
|
-
export type RouteResult = {
|
|
7
|
-
kind: "endpoint";
|
|
8
|
-
entry: BrokerEndpointEntry;
|
|
9
|
-
via: "target_endpoint_id" | "correlation_id";
|
|
10
|
-
} | {
|
|
11
|
-
kind: "no_match";
|
|
12
|
-
};
|
|
13
|
-
export interface RoutingTableOptions {
|
|
14
|
-
onCollision?: (correlation_id: string, count: number) => void;
|
|
15
|
-
}
|
|
16
|
-
export declare class RoutingTable {
|
|
17
|
-
private readonly registry;
|
|
18
|
-
private readonly opts;
|
|
19
|
-
constructor(registry: EndpointRegistry, opts?: RoutingTableOptions);
|
|
20
|
-
route(meta: InboundMessageMeta): RouteResult;
|
|
21
|
-
}
|
|
22
|
-
//# sourceMappingURL=routing-table.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"routing-table.d.ts","sourceRoot":"","sources":["../../src/broker/routing-table.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EACV,mBAAmB,EACnB,gBAAgB,EACjB,MAAM,wBAAwB,CAAC;AAEhC,MAAM,WAAW,kBAAkB;IACjC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,MAAM,WAAW,GACnB;IACE,IAAI,EAAE,UAAU,CAAC;IACjB,KAAK,EAAE,mBAAmB,CAAC;IAC3B,GAAG,EAAE,oBAAoB,GAAG,gBAAgB,CAAC;CAC9C,GACD;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC;AAEzB,MAAM,WAAW,mBAAmB;IAElC,WAAW,CAAC,EAAE,CAAC,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAC/D;AAED,qBAAa,YAAY;IAErB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,IAAI;gBADJ,QAAQ,EAAE,gBAAgB,EAC1B,IAAI,GAAE,mBAAwB;IASjD,KAAK,CAAC,IAAI,EAAE,kBAAkB,GAAG,WAAW;CAmC7C"}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
export class RoutingTable {
|
|
2
|
-
registry;
|
|
3
|
-
opts;
|
|
4
|
-
constructor(registry, opts = {}) {
|
|
5
|
-
this.registry = registry;
|
|
6
|
-
this.opts = opts;
|
|
7
|
-
}
|
|
8
|
-
route(meta) {
|
|
9
|
-
if (meta.target_endpoint_id) {
|
|
10
|
-
const entry = this.registry.get(meta.target_endpoint_id);
|
|
11
|
-
if (entry) {
|
|
12
|
-
return { kind: "endpoint", entry, via: "target_endpoint_id" };
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
if (meta.correlation_id) {
|
|
16
|
-
let matched;
|
|
17
|
-
let collisionCount = 0;
|
|
18
|
-
for (const entry of this.registry.list()) {
|
|
19
|
-
if (entry.correlation_ring.has(meta.correlation_id)) {
|
|
20
|
-
collisionCount++;
|
|
21
|
-
if (!matched) {
|
|
22
|
-
matched = entry;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
if (collisionCount > 1 && this.opts.onCollision) {
|
|
27
|
-
this.opts.onCollision(meta.correlation_id, collisionCount);
|
|
28
|
-
}
|
|
29
|
-
if (matched) {
|
|
30
|
-
return { kind: "endpoint", entry: matched, via: "correlation_id" };
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
return { kind: "no_match" };
|
|
34
|
-
}
|
|
35
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import type { RegisterRuntimeEndpointParams, RegisterRuntimeEndpointResponse, TransitionRuntimeEndpointStateParams } from "../runtime-endpoint-client.js";
|
|
2
|
-
export interface RuntimeEndpointPort {
|
|
3
|
-
register(params: RegisterRuntimeEndpointParams): Promise<RegisterRuntimeEndpointResponse>;
|
|
4
|
-
heartbeat(endpointId: string): Promise<void>;
|
|
5
|
-
unregister(endpointId: string, asNodeId?: string): Promise<void>;
|
|
6
|
-
transitionState(endpointId: string, params: TransitionRuntimeEndpointStateParams): Promise<void>;
|
|
7
|
-
}
|
|
8
|
-
//# sourceMappingURL=runtime-endpoint-port.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"runtime-endpoint-port.d.ts","sourceRoot":"","sources":["../../src/broker/runtime-endpoint-port.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EACV,6BAA6B,EAC7B,+BAA+B,EAC/B,oCAAoC,EACrC,MAAM,+BAA+B,CAAC;AAEvC,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CACN,MAAM,EAAE,6BAA6B,GACpC,OAAO,CAAC,+BAA+B,CAAC,CAAC;IAC5C,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAO7C,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAQjE,eAAe,CACb,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,oCAAoC,GAC3C,OAAO,CAAC,IAAI,CAAC,CAAC;CAClB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import type { ControlEventDispatcher } from "./control-event-dispatcher.js";
|
|
2
|
-
import type { BrokerLogger } from "./logger.js";
|
|
3
|
-
export declare const DEFAULT_BACKOFF_INITIAL_MS = 1000;
|
|
4
|
-
export declare const DEFAULT_BACKOFF_MAX_MS = 30000;
|
|
5
|
-
export interface ServicesEventClientOptions {
|
|
6
|
-
apiHost: string;
|
|
7
|
-
runtimeKey: string;
|
|
8
|
-
agentId: string;
|
|
9
|
-
dispatcher: ControlEventDispatcher;
|
|
10
|
-
logger: BrokerLogger;
|
|
11
|
-
fetchImpl?: typeof globalThis.fetch;
|
|
12
|
-
backoffInitialMs?: number;
|
|
13
|
-
backoffMaxMs?: number;
|
|
14
|
-
}
|
|
15
|
-
export interface ServicesEventClient {
|
|
16
|
-
start(): Promise<void>;
|
|
17
|
-
stop(): Promise<void>;
|
|
18
|
-
lastSeenKey(): string | undefined;
|
|
19
|
-
}
|
|
20
|
-
export declare function createServicesEventClient(opts: ServicesEventClientOptions): ServicesEventClient;
|
|
21
|
-
//# sourceMappingURL=services-event-client.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"services-event-client.d.ts","sourceRoot":"","sources":["../../src/broker/services-event-client.ts"],"names":[],"mappings":"AAmCA,OAAO,KAAK,EACV,sBAAsB,EAEvB,MAAM,+BAA+B,CAAC;AAEvC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,eAAO,MAAM,0BAA0B,OAAQ,CAAC;AAChD,eAAO,MAAM,sBAAsB,QAAS,CAAC;AAE7C,MAAM,WAAW,0BAA0B;IAEzC,OAAO,EAAE,MAAM,CAAC;IAEhB,UAAU,EAAE,MAAM,CAAC;IAEnB,OAAO,EAAE,MAAM,CAAC;IAEhB,UAAU,EAAE,sBAAsB,CAAC;IAEnC,MAAM,EAAE,YAAY,CAAC;IAErB,SAAS,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;IAEpC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,mBAAmB;IASlC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEtB,WAAW,IAAI,MAAM,GAAG,SAAS,CAAC;CACnC;AAED,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,0BAA0B,GAC/B,mBAAmB,CAuMrB"}
|
|
@@ -1,221 +0,0 @@
|
|
|
1
|
-
export const DEFAULT_BACKOFF_INITIAL_MS = 1_000;
|
|
2
|
-
export const DEFAULT_BACKOFF_MAX_MS = 30_000;
|
|
3
|
-
export function createServicesEventClient(opts) {
|
|
4
|
-
const { dispatcher, logger } = opts;
|
|
5
|
-
const fetchImpl = opts.fetchImpl ?? globalThis.fetch;
|
|
6
|
-
const backoffInitial = opts.backoffInitialMs ?? DEFAULT_BACKOFF_INITIAL_MS;
|
|
7
|
-
const backoffMax = opts.backoffMaxMs ?? DEFAULT_BACKOFF_MAX_MS;
|
|
8
|
-
let stopped = false;
|
|
9
|
-
let lastEventId;
|
|
10
|
-
let currentAbort = null;
|
|
11
|
-
let backoffMs = backoffInitial;
|
|
12
|
-
let loopPromise = null;
|
|
13
|
-
let started = false;
|
|
14
|
-
const baseUrl = makeBaseUrl(opts.apiHost);
|
|
15
|
-
const subscribeOnce = async () => {
|
|
16
|
-
const ctrl = new AbortController();
|
|
17
|
-
currentAbort = ctrl;
|
|
18
|
-
const url = new URL(`${baseUrl}/runtime/control-events`);
|
|
19
|
-
url.searchParams.set("agent_id", opts.agentId);
|
|
20
|
-
const headers = {
|
|
21
|
-
Authorization: `Bearer ${opts.runtimeKey}`,
|
|
22
|
-
Accept: "text/event-stream",
|
|
23
|
-
};
|
|
24
|
-
if (lastEventId)
|
|
25
|
-
headers["Last-Event-ID"] = lastEventId;
|
|
26
|
-
const res = await fetchImpl(url.toString(), {
|
|
27
|
-
method: "GET",
|
|
28
|
-
headers,
|
|
29
|
-
signal: ctrl.signal,
|
|
30
|
-
});
|
|
31
|
-
if (!res.ok || !res.body) {
|
|
32
|
-
throw new Error(`SSE subscribe failed: ${res.status}`);
|
|
33
|
-
}
|
|
34
|
-
backoffMs = backoffInitial;
|
|
35
|
-
const reader = res.body.pipeThrough(new TextDecoderStream()).getReader();
|
|
36
|
-
let buffer = "";
|
|
37
|
-
while (true) {
|
|
38
|
-
const { done, value } = await reader.read();
|
|
39
|
-
if (done)
|
|
40
|
-
break;
|
|
41
|
-
buffer += value.replace(/\r\n?/g, "\n");
|
|
42
|
-
let sep = buffer.indexOf("\n\n");
|
|
43
|
-
while (sep >= 0) {
|
|
44
|
-
const frame = buffer.slice(0, sep);
|
|
45
|
-
buffer = buffer.slice(sep + 2);
|
|
46
|
-
await handleFrame(frame).catch((err) => {
|
|
47
|
-
logger.warn("sse_frame_error", {
|
|
48
|
-
err: err instanceof Error ? err.message : String(err),
|
|
49
|
-
});
|
|
50
|
-
});
|
|
51
|
-
sep = buffer.indexOf("\n\n");
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
};
|
|
55
|
-
const handleFrame = async (frame) => {
|
|
56
|
-
let id;
|
|
57
|
-
const dataLines = [];
|
|
58
|
-
for (const line of frame.split("\n")) {
|
|
59
|
-
if (line === "" || line.startsWith(":"))
|
|
60
|
-
continue;
|
|
61
|
-
const colon = line.indexOf(":");
|
|
62
|
-
const field = colon === -1 ? line : line.slice(0, colon);
|
|
63
|
-
let value = colon === -1 ? "" : line.slice(colon + 1);
|
|
64
|
-
if (value.startsWith(" "))
|
|
65
|
-
value = value.slice(1);
|
|
66
|
-
if (field === "id")
|
|
67
|
-
id = value;
|
|
68
|
-
else if (field === "data")
|
|
69
|
-
dataLines.push(value);
|
|
70
|
-
}
|
|
71
|
-
if (dataLines.length === 0)
|
|
72
|
-
return;
|
|
73
|
-
const data = dataLines.join("\n");
|
|
74
|
-
if (id)
|
|
75
|
-
lastEventId = id;
|
|
76
|
-
let parsed;
|
|
77
|
-
try {
|
|
78
|
-
parsed = JSON.parse(data);
|
|
79
|
-
}
|
|
80
|
-
catch {
|
|
81
|
-
logger.warn("sse_frame_unparseable", { data: data.slice(0, 80) });
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
if (hasIdempotencyKey(parsed) && hasUnsupportedVersion(parsed)) {
|
|
85
|
-
await postAck({
|
|
86
|
-
idempotency_key: parsed.idempotency_key,
|
|
87
|
-
status: "failed",
|
|
88
|
-
detail: "unsupported_protocol_version",
|
|
89
|
-
});
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
if (!isControlEvent(parsed)) {
|
|
93
|
-
if (hasIdempotencyKey(parsed)) {
|
|
94
|
-
await postAck({
|
|
95
|
-
idempotency_key: parsed.idempotency_key,
|
|
96
|
-
status: "applied",
|
|
97
|
-
detail: "unknown_variant_dropped",
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
const outcome = await dispatcher.dispatch(parsed);
|
|
103
|
-
await postAck(outcomeToAck(parsed.idempotency_key, outcome));
|
|
104
|
-
};
|
|
105
|
-
const postAck = async (ack) => {
|
|
106
|
-
try {
|
|
107
|
-
const res = await fetchImpl(`${baseUrl}/runtime/control-ack`, {
|
|
108
|
-
method: "POST",
|
|
109
|
-
headers: {
|
|
110
|
-
Authorization: `Bearer ${opts.runtimeKey}`,
|
|
111
|
-
"Content-Type": "application/json",
|
|
112
|
-
},
|
|
113
|
-
body: JSON.stringify(ack),
|
|
114
|
-
});
|
|
115
|
-
if (!res.ok) {
|
|
116
|
-
logger.warn("ack_post_failed", {
|
|
117
|
-
status: res.status,
|
|
118
|
-
idempotency_key: ack.idempotency_key,
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
catch (err) {
|
|
123
|
-
logger.warn("ack_post_error", {
|
|
124
|
-
err: err instanceof Error ? err.message : String(err),
|
|
125
|
-
idempotency_key: ack.idempotency_key,
|
|
126
|
-
});
|
|
127
|
-
}
|
|
128
|
-
};
|
|
129
|
-
const loop = async () => {
|
|
130
|
-
while (!stopped) {
|
|
131
|
-
try {
|
|
132
|
-
await subscribeOnce();
|
|
133
|
-
}
|
|
134
|
-
catch (err) {
|
|
135
|
-
if (stopped)
|
|
136
|
-
return;
|
|
137
|
-
logger.warn("sse_reconnect", {
|
|
138
|
-
backoff_ms: backoffMs,
|
|
139
|
-
err: err instanceof Error ? err.message : String(err),
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
if (stopped)
|
|
143
|
-
return;
|
|
144
|
-
await sleep(backoffMs);
|
|
145
|
-
backoffMs = Math.min(backoffMs * 2, backoffMax);
|
|
146
|
-
}
|
|
147
|
-
};
|
|
148
|
-
return {
|
|
149
|
-
async start() {
|
|
150
|
-
if (started)
|
|
151
|
-
return;
|
|
152
|
-
started = true;
|
|
153
|
-
stopped = false;
|
|
154
|
-
loopPromise = loop();
|
|
155
|
-
},
|
|
156
|
-
async stop() {
|
|
157
|
-
stopped = true;
|
|
158
|
-
if (currentAbort) {
|
|
159
|
-
try {
|
|
160
|
-
currentAbort.abort();
|
|
161
|
-
}
|
|
162
|
-
catch {
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
if (loopPromise) {
|
|
166
|
-
await loopPromise.catch(() => { });
|
|
167
|
-
}
|
|
168
|
-
},
|
|
169
|
-
lastSeenKey() {
|
|
170
|
-
return lastEventId;
|
|
171
|
-
},
|
|
172
|
-
};
|
|
173
|
-
}
|
|
174
|
-
function outcomeToAck(idempotency_key, outcome) {
|
|
175
|
-
if (outcome.ok) {
|
|
176
|
-
if (outcome.ack_hint === "received") {
|
|
177
|
-
return { idempotency_key, status: "received" };
|
|
178
|
-
}
|
|
179
|
-
return { idempotency_key, status: "applied" };
|
|
180
|
-
}
|
|
181
|
-
return {
|
|
182
|
-
idempotency_key,
|
|
183
|
-
status: "failed",
|
|
184
|
-
detail: outcome.detail,
|
|
185
|
-
};
|
|
186
|
-
}
|
|
187
|
-
function isControlEvent(value) {
|
|
188
|
-
if (typeof value !== "object" || value === null)
|
|
189
|
-
return false;
|
|
190
|
-
const v = value;
|
|
191
|
-
if (v.version !== 1)
|
|
192
|
-
return false;
|
|
193
|
-
if (typeof v.idempotency_key !== "string")
|
|
194
|
-
return false;
|
|
195
|
-
if (typeof v.emitted_at !== "number")
|
|
196
|
-
return false;
|
|
197
|
-
if (typeof v.type !== "string")
|
|
198
|
-
return false;
|
|
199
|
-
return (v.type === "dispatch_undispatched" ||
|
|
200
|
-
v.type === "spawn_request" ||
|
|
201
|
-
v.type === "force_unregister");
|
|
202
|
-
}
|
|
203
|
-
function hasIdempotencyKey(value) {
|
|
204
|
-
return (typeof value === "object" &&
|
|
205
|
-
value !== null &&
|
|
206
|
-
typeof value.idempotency_key === "string");
|
|
207
|
-
}
|
|
208
|
-
function hasUnsupportedVersion(value) {
|
|
209
|
-
if (typeof value !== "object" || value === null)
|
|
210
|
-
return false;
|
|
211
|
-
const v = value;
|
|
212
|
-
return typeof v.version === "number" && v.version !== 1;
|
|
213
|
-
}
|
|
214
|
-
function makeBaseUrl(apiHost) {
|
|
215
|
-
const trimmed = apiHost.replace(/\/+$/, "");
|
|
216
|
-
const origin = /^https?:\/\//.test(trimmed) ? trimmed : `https://${trimmed}`;
|
|
217
|
-
return `${origin}/v1`;
|
|
218
|
-
}
|
|
219
|
-
function sleep(ms) {
|
|
220
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
221
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
export declare const DEFAULT_SPAWN_TIMEOUT_MS = 30000;
|
|
2
|
-
export declare const DEFAULT_RATE_LIMIT_WINDOW_MS = 30000;
|
|
3
|
-
export declare const DEFAULT_RATE_LIMIT_MAX = 3;
|
|
4
|
-
export interface PendingSpawn {
|
|
5
|
-
spawn_token: string;
|
|
6
|
-
expires_at: number;
|
|
7
|
-
}
|
|
8
|
-
export interface SpawnCorrelationOptions {
|
|
9
|
-
timeoutMs?: number;
|
|
10
|
-
}
|
|
11
|
-
export interface SpawnCorrelationManager {
|
|
12
|
-
track(spawn_token: string, onTimeout: () => void): void;
|
|
13
|
-
consume(spawn_token: string): PendingSpawn | undefined;
|
|
14
|
-
isTracked(spawn_token: string): boolean;
|
|
15
|
-
size(): number;
|
|
16
|
-
cancelAll(): void;
|
|
17
|
-
}
|
|
18
|
-
export declare function createSpawnCorrelationManager(opts?: SpawnCorrelationOptions): SpawnCorrelationManager;
|
|
19
|
-
export interface SpawnRateLimiter {
|
|
20
|
-
tryConsume(now?: number): boolean;
|
|
21
|
-
count(now?: number): number;
|
|
22
|
-
}
|
|
23
|
-
export interface SpawnRateLimiterOptions {
|
|
24
|
-
maxInWindow?: number;
|
|
25
|
-
windowMs?: number;
|
|
26
|
-
}
|
|
27
|
-
export declare function createSpawnRateLimiter(opts?: SpawnRateLimiterOptions): SpawnRateLimiter;
|
|
28
|
-
//# sourceMappingURL=spawn-correlation.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"spawn-correlation.d.ts","sourceRoot":"","sources":["../../src/broker/spawn-correlation.ts"],"names":[],"mappings":"AA6BA,eAAO,MAAM,wBAAwB,QAAS,CAAC;AAC/C,eAAO,MAAM,4BAA4B,QAAS,CAAC;AACnD,eAAO,MAAM,sBAAsB,IAAI,CAAC;AAExC,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAC;IAEpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,uBAAuB;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,uBAAuB;IAOtC,KAAK,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;IAMxD,OAAO,CAAC,WAAW,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAAC;IAEvD,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC;IAExC,IAAI,IAAI,MAAM,CAAC;IAEf,SAAS,IAAI,IAAI,CAAC;CACnB;AAED,wBAAgB,6BAA6B,CAC3C,IAAI,GAAE,uBAA4B,GACjC,uBAAuB,CA+CzB;AAOD,MAAM,WAAW,gBAAgB;IAE/B,UAAU,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAElC,KAAK,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,uBAAuB;IACtC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,sBAAsB,CACpC,IAAI,GAAE,uBAA4B,GACjC,gBAAgB,CA0BlB"}
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
export const DEFAULT_SPAWN_TIMEOUT_MS = 30_000;
|
|
2
|
-
export const DEFAULT_RATE_LIMIT_WINDOW_MS = 30_000;
|
|
3
|
-
export const DEFAULT_RATE_LIMIT_MAX = 3;
|
|
4
|
-
export function createSpawnCorrelationManager(opts = {}) {
|
|
5
|
-
const timeoutMs = opts.timeoutMs ?? DEFAULT_SPAWN_TIMEOUT_MS;
|
|
6
|
-
const entries = new Map();
|
|
7
|
-
const timers = new Map();
|
|
8
|
-
return {
|
|
9
|
-
track(spawn_token, onTimeout) {
|
|
10
|
-
const priorTimer = timers.get(spawn_token);
|
|
11
|
-
if (priorTimer)
|
|
12
|
-
clearTimeout(priorTimer);
|
|
13
|
-
entries.set(spawn_token, {
|
|
14
|
-
spawn_token,
|
|
15
|
-
expires_at: Date.now() + timeoutMs,
|
|
16
|
-
});
|
|
17
|
-
const handle = setTimeout(() => {
|
|
18
|
-
entries.delete(spawn_token);
|
|
19
|
-
timers.delete(spawn_token);
|
|
20
|
-
onTimeout();
|
|
21
|
-
}, timeoutMs);
|
|
22
|
-
handle.unref?.();
|
|
23
|
-
timers.set(spawn_token, handle);
|
|
24
|
-
},
|
|
25
|
-
consume(spawn_token) {
|
|
26
|
-
const entry = entries.get(spawn_token);
|
|
27
|
-
if (!entry)
|
|
28
|
-
return undefined;
|
|
29
|
-
entries.delete(spawn_token);
|
|
30
|
-
const timer = timers.get(spawn_token);
|
|
31
|
-
if (timer) {
|
|
32
|
-
clearTimeout(timer);
|
|
33
|
-
timers.delete(spawn_token);
|
|
34
|
-
}
|
|
35
|
-
return entry;
|
|
36
|
-
},
|
|
37
|
-
isTracked(spawn_token) {
|
|
38
|
-
return entries.has(spawn_token);
|
|
39
|
-
},
|
|
40
|
-
size() {
|
|
41
|
-
return entries.size;
|
|
42
|
-
},
|
|
43
|
-
cancelAll() {
|
|
44
|
-
for (const [, t] of timers)
|
|
45
|
-
clearTimeout(t);
|
|
46
|
-
timers.clear();
|
|
47
|
-
entries.clear();
|
|
48
|
-
},
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
export function createSpawnRateLimiter(opts = {}) {
|
|
52
|
-
const max = opts.maxInWindow ?? DEFAULT_RATE_LIMIT_MAX;
|
|
53
|
-
const windowMs = opts.windowMs ?? DEFAULT_RATE_LIMIT_WINDOW_MS;
|
|
54
|
-
const timestamps = [];
|
|
55
|
-
const sweep = (now) => {
|
|
56
|
-
const cutoff = now - windowMs;
|
|
57
|
-
while (timestamps.length > 0) {
|
|
58
|
-
const head = timestamps[0];
|
|
59
|
-
if (head === undefined || head >= cutoff)
|
|
60
|
-
break;
|
|
61
|
-
timestamps.shift();
|
|
62
|
-
}
|
|
63
|
-
};
|
|
64
|
-
return {
|
|
65
|
-
tryConsume(now = Date.now()) {
|
|
66
|
-
sweep(now);
|
|
67
|
-
if (timestamps.length >= max)
|
|
68
|
-
return false;
|
|
69
|
-
timestamps.push(now);
|
|
70
|
-
return true;
|
|
71
|
-
},
|
|
72
|
-
count(now = Date.now()) {
|
|
73
|
-
sweep(now);
|
|
74
|
-
return timestamps.length;
|
|
75
|
-
},
|
|
76
|
-
};
|
|
77
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
export interface SpawnCommand {
|
|
2
|
-
binary: string;
|
|
3
|
-
args: string[];
|
|
4
|
-
env?: Record<string, string>;
|
|
5
|
-
cwd?: string;
|
|
6
|
-
}
|
|
7
|
-
export interface SpawnContext {
|
|
8
|
-
prompt: string;
|
|
9
|
-
spawn_token: string;
|
|
10
|
-
cwd?: string;
|
|
11
|
-
}
|
|
12
|
-
export interface DriverAvailability {
|
|
13
|
-
available: boolean;
|
|
14
|
-
reason?: string;
|
|
15
|
-
}
|
|
16
|
-
export interface SpawnDriver {
|
|
17
|
-
readonly runtime_kind: string;
|
|
18
|
-
buildSpawnCommand(ctx: SpawnContext): SpawnCommand;
|
|
19
|
-
isAvailable(): Promise<DriverAvailability>;
|
|
20
|
-
}
|
|
21
|
-
export declare class SpawnDriverRegistry {
|
|
22
|
-
private readonly drivers;
|
|
23
|
-
register(driver: SpawnDriver): void;
|
|
24
|
-
lookup(runtime_kind: string): SpawnDriver | undefined;
|
|
25
|
-
list(): readonly string[];
|
|
26
|
-
}
|
|
27
|
-
//# sourceMappingURL=spawn-driver.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"spawn-driver.d.ts","sourceRoot":"","sources":["../../src/broker/spawn-driver.ts"],"names":[],"mappings":"AA8BA,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,EAAE,CAAC;IAEf,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAE7B,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAGD,MAAM,WAAW,YAAY;IAE3B,MAAM,EAAE,MAAM,CAAC;IAOf,WAAW,EAAE,MAAM,CAAC;IAEpB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAGD,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,OAAO,CAAC;IAGnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAOD,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,iBAAiB,CAAC,GAAG,EAAE,YAAY,GAAG,YAAY,CAAC;IACnD,WAAW,IAAI,OAAO,CAAC,kBAAkB,CAAC,CAAC;CAC5C;AAGD,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAkC;IAG1D,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI;IAUnC,MAAM,CAAC,YAAY,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS;IAKrD,IAAI,IAAI,SAAS,MAAM,EAAE;CAG1B"}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
export class SpawnDriverRegistry {
|
|
2
|
-
drivers = new Map();
|
|
3
|
-
register(driver) {
|
|
4
|
-
if (this.drivers.has(driver.runtime_kind)) {
|
|
5
|
-
throw new Error(`driver already registered for runtime_kind: ${driver.runtime_kind}`);
|
|
6
|
-
}
|
|
7
|
-
this.drivers.set(driver.runtime_kind, driver);
|
|
8
|
-
}
|
|
9
|
-
lookup(runtime_kind) {
|
|
10
|
-
return this.drivers.get(runtime_kind);
|
|
11
|
-
}
|
|
12
|
-
list() {
|
|
13
|
-
return Array.from(this.drivers.keys());
|
|
14
|
-
}
|
|
15
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import type { EndpointRegistry } from "./endpoint-registry.js";
|
|
2
|
-
export declare const TASK_HINT_MAX_LENGTH = 200;
|
|
3
|
-
export interface TaskHintHandlerOptions {
|
|
4
|
-
registry: EndpointRegistry;
|
|
5
|
-
}
|
|
6
|
-
export interface TaskHintUpdate {
|
|
7
|
-
endpoint_id: string;
|
|
8
|
-
plugin_pid: number;
|
|
9
|
-
task_hint: string;
|
|
10
|
-
}
|
|
11
|
-
export type TaskHintResult = {
|
|
12
|
-
ok: true;
|
|
13
|
-
truncated: boolean;
|
|
14
|
-
effective: string;
|
|
15
|
-
} | {
|
|
16
|
-
ok: false;
|
|
17
|
-
code: "endpoint_unknown" | "ownership_mismatch" | "task_hint_invalid";
|
|
18
|
-
message: string;
|
|
19
|
-
};
|
|
20
|
-
export declare function updateTaskHint(opts: TaskHintHandlerOptions, update: TaskHintUpdate): TaskHintResult;
|
|
21
|
-
//# sourceMappingURL=task-hint-handler.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"task-hint-handler.d.ts","sourceRoot":"","sources":["../../src/broker/task-hint-handler.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,eAAO,MAAM,oBAAoB,MAAM,CAAC;AAExC,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,gBAAgB,CAAC;CAC5B;AAED,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,cAAc,GACtB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,SAAS,EAAE,OAAO,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACnD;IACE,EAAE,EAAE,KAAK,CAAC;IACV,IAAI,EAAE,kBAAkB,GAAG,oBAAoB,GAAG,mBAAmB,CAAC;IACtE,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEN,wBAAgB,cAAc,CAC5B,IAAI,EAAE,sBAAsB,EAC5B,MAAM,EAAE,cAAc,GACrB,cAAc,CAmChB"}
|