@masons/agent-network 0.5.29 → 0.5.31
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/broker/broker-daemon.d.ts +13 -3
- package/dist/broker/broker-daemon.d.ts.map +1 -1
- package/dist/broker/broker-daemon.js +294 -52
- package/dist/broker/closed-endpoint-lookup.d.ts +25 -0
- package/dist/broker/closed-endpoint-lookup.d.ts.map +1 -0
- package/dist/broker/closed-endpoint-lookup.js +59 -0
- package/dist/broker/control-event-dispatcher.d.ts +20 -0
- package/dist/broker/control-event-dispatcher.d.ts.map +1 -0
- package/dist/broker/control-event-dispatcher.js +45 -0
- package/dist/broker/control-event-types.d.ts +30 -0
- package/dist/broker/control-event-types.d.ts.map +1 -0
- package/dist/broker/control-event-types.js +1 -0
- package/dist/broker/endpoint-registry.d.ts +17 -1
- package/dist/broker/endpoint-registry.d.ts.map +1 -1
- package/dist/broker/endpoint-registry.js +39 -0
- package/dist/broker/endpoint-state-machine.d.ts +40 -0
- package/dist/broker/endpoint-state-machine.d.ts.map +1 -0
- package/dist/broker/endpoint-state-machine.js +92 -0
- package/dist/broker/entry.d.ts +11 -0
- package/dist/broker/entry.d.ts.map +1 -1
- package/dist/broker/entry.js +108 -5
- package/dist/broker/grace-timer.d.ts +9 -0
- package/dist/broker/grace-timer.d.ts.map +1 -0
- package/dist/broker/grace-timer.js +34 -0
- package/dist/broker/ipc-server.d.ts +8 -1
- package/dist/broker/ipc-server.d.ts.map +1 -1
- package/dist/broker/ipc-server.js +31 -0
- package/dist/broker/paths.d.ts +1 -0
- package/dist/broker/paths.d.ts.map +1 -1
- package/dist/broker/paths.js +2 -0
- package/dist/broker/plugin-liveness.d.ts +2 -0
- package/dist/broker/plugin-liveness.d.ts.map +1 -0
- package/dist/broker/plugin-liveness.js +15 -0
- package/dist/broker/reconnecting-buffer.d.ts +23 -0
- package/dist/broker/reconnecting-buffer.d.ts.map +1 -0
- package/dist/broker/reconnecting-buffer.js +107 -0
- package/dist/broker/routing-table.d.ts.map +1 -1
- package/dist/broker/routing-table.js +1 -1
- package/dist/broker/runtime-endpoint-port.d.ts +2 -1
- package/dist/broker/runtime-endpoint-port.d.ts.map +1 -1
- package/dist/broker/undispatched-inbox.d.ts +26 -0
- package/dist/broker/undispatched-inbox.d.ts.map +1 -0
- package/dist/broker/undispatched-inbox.js +53 -0
- package/dist/runtime-endpoint-client.d.ts +7 -0
- package/dist/runtime-endpoint-client.d.ts.map +1 -1
- package/dist/runtime-endpoint-client.js +11 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"control-event-types.d.ts","sourceRoot":"","sources":["../../src/broker/control-event-types.ts"],"names":[],"mappings":"AAgBA,MAAM,MAAM,YAAY,GACpB,yBAAyB,GACzB,iBAAiB,GACjB,oBAAoB,CAAC;AAGzB,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,uBAAuB,CAAC;IAC9B,OAAO,EAAE,CAAC,CAAC;IACX,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAGD,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,eAAe,CAAC;IACtB,OAAO,EAAE,CAAC,CAAC;IACX,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,gBAAgB,CAAC;CAC1B;AAGD,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,kBAAkB,CAAC;IACzB,OAAO,EAAE,CAAC,CAAC;IACX,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;CAChB;AAGD,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,IAAI,GAAG,OAAO,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -13,8 +13,9 @@ export interface BrokerEndpointEntry {
|
|
|
13
13
|
agent_id: string;
|
|
14
14
|
plugin_pid: number;
|
|
15
15
|
ipc_ws: WebSocket;
|
|
16
|
-
state: "active";
|
|
16
|
+
state: "active" | "reconnecting";
|
|
17
17
|
state_since: Date;
|
|
18
|
+
grace_deadline?: Date;
|
|
18
19
|
display_metadata: DisplayMetadata;
|
|
19
20
|
correlation_ring: CorrelationRingBuffer;
|
|
20
21
|
}
|
|
@@ -30,7 +31,22 @@ export declare class EndpointRegistry {
|
|
|
30
31
|
register(args: RegisterArgs): BrokerEndpointEntry;
|
|
31
32
|
get(endpoint_id: string): BrokerEndpointEntry | undefined;
|
|
32
33
|
unregister(endpoint_id: string): BrokerEndpointEntry | undefined;
|
|
34
|
+
markReconnecting(endpoint_id: string, grace_deadline: Date): BrokerEndpointEntry;
|
|
35
|
+
markActive(endpoint_id: string, new_ws: WebSocket): BrokerEndpointEntry;
|
|
33
36
|
preconditionForReattach(endpoint_id: string, plugin_pid: number): BrokerEndpointEntry | undefined;
|
|
37
|
+
getReattachStatus(endpoint_id: string, plugin_pid: number): {
|
|
38
|
+
ok: true;
|
|
39
|
+
entry: BrokerEndpointEntry;
|
|
40
|
+
} | {
|
|
41
|
+
ok: false;
|
|
42
|
+
reason: "endpoint_unknown";
|
|
43
|
+
} | {
|
|
44
|
+
ok: false;
|
|
45
|
+
reason: "reattach_pid_mismatch";
|
|
46
|
+
} | {
|
|
47
|
+
ok: false;
|
|
48
|
+
reason: "endpoint_not_reconnecting";
|
|
49
|
+
};
|
|
34
50
|
list(): BrokerEndpointEntry[];
|
|
35
51
|
size(): number;
|
|
36
52
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"endpoint-registry.d.ts","sourceRoot":"","sources":["../../src/broker/endpoint-registry.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"endpoint-registry.d.ts","sourceRoot":"","sources":["../../src/broker/endpoint-registry.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,SAAS,MAAM,IAAI,CAAC;AAChC,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAG9D,MAAM,WAAW,eAAe;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,SAAS,CAAC;IAClB,KAAK,EAAE,QAAQ,GAAG,cAAc,CAAC;IACjC,WAAW,EAAE,IAAI,CAAC;IAElB,cAAc,CAAC,EAAE,IAAI,CAAC;IACtB,gBAAgB,EAAE,eAAe,CAAC;IAClC,gBAAgB,EAAE,qBAAqB,CAAC;CACzC;AAED,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,SAAS,CAAC;IAClB,gBAAgB,EAAE,eAAe,CAAC;CACnC;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA0C;IAG/D,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG,mBAAmB;IAkBjD,GAAG,CAAC,WAAW,EAAE,MAAM,GAAG,mBAAmB,GAAG,SAAS;IAKzD,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,mBAAmB,GAAG,SAAS;IAWhE,gBAAgB,CACd,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,IAAI,GACnB,mBAAmB;IAoBtB,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,GAAG,mBAAmB;IA8BvE,uBAAuB,CACrB,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,GACjB,mBAAmB,GAAG,SAAS;IAYlC,iBAAiB,CACf,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,GAEhB;QAAE,EAAE,EAAE,IAAI,CAAC;QAAC,KAAK,EAAE,mBAAmB,CAAA;KAAE,GACxC;QAAE,EAAE,EAAE,KAAK,CAAC;QAAC,MAAM,EAAE,kBAAkB,CAAA;KAAE,GACzC;QAAE,EAAE,EAAE,KAAK,CAAC;QAAC,MAAM,EAAE,uBAAuB,CAAA;KAAE,GAC9C;QAAE,EAAE,EAAE,KAAK,CAAC;QAAC,MAAM,EAAE,2BAA2B,CAAA;KAAE;IAWtD,IAAI,IAAI,mBAAmB,EAAE;IAK7B,IAAI,IAAI,MAAM;CAGf"}
|
|
@@ -27,14 +27,53 @@ export class EndpointRegistry {
|
|
|
27
27
|
this.byId.delete(endpoint_id);
|
|
28
28
|
return entry;
|
|
29
29
|
}
|
|
30
|
+
markReconnecting(endpoint_id, grace_deadline) {
|
|
31
|
+
const entry = this.byId.get(endpoint_id);
|
|
32
|
+
if (!entry) {
|
|
33
|
+
throw new Error(`unknown endpoint_id: ${endpoint_id}`);
|
|
34
|
+
}
|
|
35
|
+
if (entry.state !== "active") {
|
|
36
|
+
throw new Error(`markReconnecting requires state=active, got state=${entry.state}`);
|
|
37
|
+
}
|
|
38
|
+
entry.state = "reconnecting";
|
|
39
|
+
entry.state_since = new Date();
|
|
40
|
+
entry.grace_deadline = grace_deadline;
|
|
41
|
+
return entry;
|
|
42
|
+
}
|
|
43
|
+
markActive(endpoint_id, new_ws) {
|
|
44
|
+
const entry = this.byId.get(endpoint_id);
|
|
45
|
+
if (!entry) {
|
|
46
|
+
throw new Error(`unknown endpoint_id: ${endpoint_id}`);
|
|
47
|
+
}
|
|
48
|
+
if (entry.state !== "reconnecting") {
|
|
49
|
+
throw new Error(`markActive requires state=reconnecting, got state=${entry.state}`);
|
|
50
|
+
}
|
|
51
|
+
entry.state = "active";
|
|
52
|
+
entry.state_since = new Date();
|
|
53
|
+
entry.grace_deadline = undefined;
|
|
54
|
+
entry.ipc_ws = new_ws;
|
|
55
|
+
return entry;
|
|
56
|
+
}
|
|
30
57
|
preconditionForReattach(endpoint_id, plugin_pid) {
|
|
31
58
|
const entry = this.byId.get(endpoint_id);
|
|
32
59
|
if (!entry)
|
|
33
60
|
return undefined;
|
|
34
61
|
if (entry.plugin_pid !== plugin_pid)
|
|
35
62
|
return undefined;
|
|
63
|
+
if (entry.state !== "reconnecting")
|
|
64
|
+
return undefined;
|
|
36
65
|
return entry;
|
|
37
66
|
}
|
|
67
|
+
getReattachStatus(endpoint_id, plugin_pid) {
|
|
68
|
+
const entry = this.byId.get(endpoint_id);
|
|
69
|
+
if (!entry)
|
|
70
|
+
return { ok: false, reason: "endpoint_unknown" };
|
|
71
|
+
if (entry.plugin_pid !== plugin_pid)
|
|
72
|
+
return { ok: false, reason: "reattach_pid_mismatch" };
|
|
73
|
+
if (entry.state !== "reconnecting")
|
|
74
|
+
return { ok: false, reason: "endpoint_not_reconnecting" };
|
|
75
|
+
return { ok: true, entry };
|
|
76
|
+
}
|
|
38
77
|
list() {
|
|
39
78
|
return Array.from(this.byId.values());
|
|
40
79
|
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export declare const DEFAULT_GRACE_MS: number;
|
|
2
|
+
export type EndpointState = "active" | "reconnecting" | "closed";
|
|
3
|
+
export type TransitionEvent = {
|
|
4
|
+
type: "register";
|
|
5
|
+
} | {
|
|
6
|
+
type: "ipc_close";
|
|
7
|
+
plugin_alive: boolean;
|
|
8
|
+
} | {
|
|
9
|
+
type: "reattach";
|
|
10
|
+
} | {
|
|
11
|
+
type: "grace_expired";
|
|
12
|
+
} | {
|
|
13
|
+
type: "explicit_unregister";
|
|
14
|
+
};
|
|
15
|
+
export type TransitionEffect = {
|
|
16
|
+
type: "start_grace_timer";
|
|
17
|
+
deadline_ms: number;
|
|
18
|
+
} | {
|
|
19
|
+
type: "cancel_grace_timer";
|
|
20
|
+
} | {
|
|
21
|
+
type: "emit_state";
|
|
22
|
+
state: EndpointState;
|
|
23
|
+
reason: string;
|
|
24
|
+
} | {
|
|
25
|
+
type: "drain_buffer";
|
|
26
|
+
} | {
|
|
27
|
+
type: "remove_from_registry";
|
|
28
|
+
} | {
|
|
29
|
+
type: "delete_buffer";
|
|
30
|
+
};
|
|
31
|
+
export interface TransitionResult {
|
|
32
|
+
next: EndpointState;
|
|
33
|
+
effects: readonly TransitionEffect[];
|
|
34
|
+
ignored?: boolean;
|
|
35
|
+
}
|
|
36
|
+
export interface TransitionOptions {
|
|
37
|
+
graceMs?: number;
|
|
38
|
+
}
|
|
39
|
+
export declare function transition(current: EndpointState, event: TransitionEvent, opts?: TransitionOptions): TransitionResult;
|
|
40
|
+
//# sourceMappingURL=endpoint-state-machine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"endpoint-state-machine.d.ts","sourceRoot":"","sources":["../../src/broker/endpoint-state-machine.ts"],"names":[],"mappings":"AA2BA,eAAO,MAAM,gBAAgB,QAAiB,CAAC;AAE/C,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,cAAc,GAAG,QAAQ,CAAC;AAEjE,MAAM,MAAM,eAAe,GACvB;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,GAOpB;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,YAAY,EAAE,OAAO,CAAA;CAAE,GAE5C;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,GAEpB;IAAE,IAAI,EAAE,eAAe,CAAA;CAAE,GAEzB;IAAE,IAAI,EAAE,qBAAqB,CAAA;CAAE,CAAC;AAEpC,MAAM,MAAM,gBAAgB,GACxB;IAAE,IAAI,EAAE,mBAAmB,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAClD;IAAE,IAAI,EAAE,oBAAoB,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,KAAK,EAAE,aAAa,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC5D;IAAE,IAAI,EAAE,cAAc,CAAA;CAAE,GACxB;IAAE,IAAI,EAAE,sBAAsB,CAAA;CAAE,GAChC;IAAE,IAAI,EAAE,eAAe,CAAA;CAAE,CAAC;AAE9B,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,aAAa,CAAC;IACpB,OAAO,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAMrC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IAEhC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAQD,wBAAgB,UAAU,CACxB,OAAO,EAAE,aAAa,EACtB,KAAK,EAAE,eAAe,EACtB,IAAI,GAAE,iBAAsB,GAC3B,gBAAgB,CAiGlB"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
export const DEFAULT_GRACE_MS = 10 * 60 * 1000;
|
|
2
|
+
export function transition(current, event, opts = {}) {
|
|
3
|
+
const graceMs = opts.graceMs ?? DEFAULT_GRACE_MS;
|
|
4
|
+
switch (current) {
|
|
5
|
+
case "active": {
|
|
6
|
+
switch (event.type) {
|
|
7
|
+
case "ipc_close":
|
|
8
|
+
if (event.plugin_alive) {
|
|
9
|
+
return {
|
|
10
|
+
next: "reconnecting",
|
|
11
|
+
effects: [
|
|
12
|
+
{ type: "start_grace_timer", deadline_ms: graceMs },
|
|
13
|
+
{
|
|
14
|
+
type: "emit_state",
|
|
15
|
+
state: "reconnecting",
|
|
16
|
+
reason: "ipc_close",
|
|
17
|
+
},
|
|
18
|
+
],
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
return {
|
|
22
|
+
next: "closed",
|
|
23
|
+
effects: [
|
|
24
|
+
{ type: "emit_state", state: "closed", reason: "plugin_exit" },
|
|
25
|
+
{ type: "delete_buffer" },
|
|
26
|
+
{ type: "remove_from_registry" },
|
|
27
|
+
],
|
|
28
|
+
};
|
|
29
|
+
case "explicit_unregister":
|
|
30
|
+
return {
|
|
31
|
+
next: "closed",
|
|
32
|
+
effects: [
|
|
33
|
+
{
|
|
34
|
+
type: "emit_state",
|
|
35
|
+
state: "closed",
|
|
36
|
+
reason: "explicit_unregister",
|
|
37
|
+
},
|
|
38
|
+
{ type: "delete_buffer" },
|
|
39
|
+
{ type: "remove_from_registry" },
|
|
40
|
+
],
|
|
41
|
+
};
|
|
42
|
+
case "register":
|
|
43
|
+
case "reattach":
|
|
44
|
+
case "grace_expired":
|
|
45
|
+
return { next: "active", effects: [], ignored: true };
|
|
46
|
+
}
|
|
47
|
+
return { next: current, effects: [], ignored: true };
|
|
48
|
+
}
|
|
49
|
+
case "reconnecting": {
|
|
50
|
+
switch (event.type) {
|
|
51
|
+
case "reattach":
|
|
52
|
+
return {
|
|
53
|
+
next: "active",
|
|
54
|
+
effects: [
|
|
55
|
+
{ type: "cancel_grace_timer" },
|
|
56
|
+
{ type: "drain_buffer" },
|
|
57
|
+
{ type: "emit_state", state: "active", reason: "reattach" },
|
|
58
|
+
],
|
|
59
|
+
};
|
|
60
|
+
case "grace_expired":
|
|
61
|
+
return {
|
|
62
|
+
next: "closed",
|
|
63
|
+
effects: [
|
|
64
|
+
{ type: "emit_state", state: "closed", reason: "grace_timeout" },
|
|
65
|
+
{ type: "delete_buffer" },
|
|
66
|
+
{ type: "remove_from_registry" },
|
|
67
|
+
],
|
|
68
|
+
};
|
|
69
|
+
case "explicit_unregister":
|
|
70
|
+
return {
|
|
71
|
+
next: "closed",
|
|
72
|
+
effects: [
|
|
73
|
+
{ type: "cancel_grace_timer" },
|
|
74
|
+
{
|
|
75
|
+
type: "emit_state",
|
|
76
|
+
state: "closed",
|
|
77
|
+
reason: "explicit_unregister",
|
|
78
|
+
},
|
|
79
|
+
{ type: "delete_buffer" },
|
|
80
|
+
{ type: "remove_from_registry" },
|
|
81
|
+
],
|
|
82
|
+
};
|
|
83
|
+
case "ipc_close":
|
|
84
|
+
case "register":
|
|
85
|
+
return { next: "reconnecting", effects: [], ignored: true };
|
|
86
|
+
}
|
|
87
|
+
return { next: current, effects: [], ignored: true };
|
|
88
|
+
}
|
|
89
|
+
case "closed":
|
|
90
|
+
return { next: "closed", effects: [], ignored: true };
|
|
91
|
+
}
|
|
92
|
+
}
|
package/dist/broker/entry.d.ts
CHANGED
|
@@ -1,2 +1,13 @@
|
|
|
1
|
+
import { type BrokerLogger } from "./logger.js";
|
|
2
|
+
import type { RuntimeEndpointPort } from "./runtime-endpoint-port.js";
|
|
3
|
+
interface ResolvedCredentials {
|
|
4
|
+
accountId: string;
|
|
5
|
+
connectorUrl: string;
|
|
6
|
+
token: string;
|
|
7
|
+
apiHost: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function resolveCredentialsFromFile(filePath: string, accountId: string, envApiHost: string | undefined): Promise<ResolvedCredentials>;
|
|
10
|
+
export declare function buildApiPort(apiHost: string, runtimeKey: string, logger: BrokerLogger): RuntimeEndpointPort;
|
|
1
11
|
export declare function main(): Promise<void>;
|
|
12
|
+
export {};
|
|
2
13
|
//# sourceMappingURL=entry.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entry.d.ts","sourceRoot":"","sources":["../../src/broker/entry.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"entry.d.ts","sourceRoot":"","sources":["../../src/broker/entry.ts"],"names":[],"mappings":"AA0EA,OAAO,EAAE,KAAK,YAAY,EAAsB,MAAM,aAAa,CAAC;AAEpE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAItE,UAAU,mBAAmB;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAUD,wBAAsB,0BAA0B,CAC9C,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,GAAG,SAAS,GAC7B,OAAO,CAAC,mBAAmB,CAAC,CA8F9B;AAyDD,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,YAAY,GACnB,mBAAmB,CAkErB;AAYD,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAgD1C"}
|
package/dist/broker/entry.js
CHANGED
|
@@ -1,13 +1,70 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
1
2
|
import { pathToFileURL } from "node:url";
|
|
2
3
|
import { readConfig } from "../config-fs.js";
|
|
3
4
|
import { DEFAULT_API_HOST } from "../platform-client.js";
|
|
4
|
-
import { heartbeatRuntimeEndpoint, registerRuntimeEndpoint, unregisterRuntimeEndpoint, } from "../runtime-endpoint-client.js";
|
|
5
|
+
import { heartbeatRuntimeEndpoint, registerRuntimeEndpoint, transitionRuntimeEndpointState, unregisterRuntimeEndpoint, } from "../runtime-endpoint-client.js";
|
|
5
6
|
import { startBrokerDaemon } from "./broker-daemon.js";
|
|
6
7
|
import { ConnectorWS } from "./connector-ws.js";
|
|
7
8
|
import { createBrokerLogger } from "./logger.js";
|
|
8
9
|
import { resolveBrokerPaths } from "./paths.js";
|
|
9
10
|
const DEFAULT_ACCOUNT_ID = "default";
|
|
10
|
-
async function
|
|
11
|
+
export async function resolveCredentialsFromFile(filePath, accountId, envApiHost) {
|
|
12
|
+
let raw;
|
|
13
|
+
try {
|
|
14
|
+
raw = await readFile(filePath, "utf8");
|
|
15
|
+
}
|
|
16
|
+
catch (err) {
|
|
17
|
+
const code = err.code;
|
|
18
|
+
if (code === "ENOENT") {
|
|
19
|
+
throw new Error(`MASONS_BROKER_CREDENTIALS_FILE points to non-existent path: ${filePath}`);
|
|
20
|
+
}
|
|
21
|
+
throw new Error(`failed to read MASONS_BROKER_CREDENTIALS_FILE at ${filePath}: ` +
|
|
22
|
+
(err instanceof Error ? err.message : String(err)));
|
|
23
|
+
}
|
|
24
|
+
let parsed;
|
|
25
|
+
try {
|
|
26
|
+
parsed = JSON.parse(raw);
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
throw new Error(`MASONS_BROKER_CREDENTIALS_FILE at ${filePath} is not valid JSON: ` +
|
|
30
|
+
(err instanceof Error ? err.message : String(err)));
|
|
31
|
+
}
|
|
32
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
33
|
+
throw new Error(`MASONS_BROKER_CREDENTIALS_FILE at ${filePath}: top-level must be an object`);
|
|
34
|
+
}
|
|
35
|
+
const accounts = parsed.accounts;
|
|
36
|
+
if (typeof accounts !== "object" ||
|
|
37
|
+
accounts === null ||
|
|
38
|
+
Array.isArray(accounts)) {
|
|
39
|
+
throw new Error(`MASONS_BROKER_CREDENTIALS_FILE at ${filePath}: missing or invalid "accounts" object`);
|
|
40
|
+
}
|
|
41
|
+
const accountRaw = accounts[accountId];
|
|
42
|
+
if (typeof accountRaw !== "object" ||
|
|
43
|
+
accountRaw === null ||
|
|
44
|
+
Array.isArray(accountRaw)) {
|
|
45
|
+
const available = Object.keys(accounts).join(", ") || "<none>";
|
|
46
|
+
throw new Error(`MASONS_BROKER_CREDENTIALS_FILE at ${filePath}: account "${accountId}" not found (available: ${available})`);
|
|
47
|
+
}
|
|
48
|
+
const acct = accountRaw;
|
|
49
|
+
const connectorUrl = typeof acct.connectorUrl === "string" ? acct.connectorUrl : null;
|
|
50
|
+
const token = typeof acct.token === "string" ? acct.token : null;
|
|
51
|
+
if (!connectorUrl) {
|
|
52
|
+
throw new Error(`MASONS_BROKER_CREDENTIALS_FILE at ${filePath}: account "${accountId}" missing required field "connectorUrl"`);
|
|
53
|
+
}
|
|
54
|
+
if (!token) {
|
|
55
|
+
throw new Error(`MASONS_BROKER_CREDENTIALS_FILE at ${filePath}: account "${accountId}" missing required field "token"`);
|
|
56
|
+
}
|
|
57
|
+
if (acct.apiHost !== undefined && typeof acct.apiHost !== "string") {
|
|
58
|
+
throw new Error(`MASONS_BROKER_CREDENTIALS_FILE at ${filePath}: account "${accountId}" optional field "apiHost" must be a string when present`);
|
|
59
|
+
}
|
|
60
|
+
if (acct.handle !== undefined && typeof acct.handle !== "string") {
|
|
61
|
+
throw new Error(`MASONS_BROKER_CREDENTIALS_FILE at ${filePath}: account "${accountId}" optional field "handle" must be a string when present`);
|
|
62
|
+
}
|
|
63
|
+
const apiHost = envApiHost ??
|
|
64
|
+
(typeof acct.apiHost === "string" ? acct.apiHost : DEFAULT_API_HOST);
|
|
65
|
+
return { accountId, connectorUrl, token, apiHost };
|
|
66
|
+
}
|
|
67
|
+
async function resolveCredentialsFromOpenClawConfig(accountId, envApiHost) {
|
|
11
68
|
const config = await readConfig();
|
|
12
69
|
const channels = config.channels;
|
|
13
70
|
const network = channels?.["agent-network"];
|
|
@@ -19,11 +76,19 @@ async function resolveCredentials(accountId, envApiHost) {
|
|
|
19
76
|
const token = typeof account?.token === "string" ? account.token : null;
|
|
20
77
|
if (!connectorUrl || !token) {
|
|
21
78
|
throw new Error(`agent-network credentials missing for account "${accountId}"; ` +
|
|
22
|
-
"run setup before lazy-spawning the broker"
|
|
79
|
+
"run setup before lazy-spawning the broker " +
|
|
80
|
+
"(or set MASONS_BROKER_CREDENTIALS_FILE for Plugin hosts)");
|
|
23
81
|
}
|
|
24
82
|
return { accountId, connectorUrl, token, apiHost };
|
|
25
83
|
}
|
|
26
|
-
function
|
|
84
|
+
async function resolveCredentials(accountId, envApiHost) {
|
|
85
|
+
const credentialsFile = process.env.MASONS_BROKER_CREDENTIALS_FILE;
|
|
86
|
+
if (credentialsFile) {
|
|
87
|
+
return resolveCredentialsFromFile(credentialsFile, accountId, envApiHost);
|
|
88
|
+
}
|
|
89
|
+
return resolveCredentialsFromOpenClawConfig(accountId, envApiHost);
|
|
90
|
+
}
|
|
91
|
+
export function buildApiPort(apiHost, runtimeKey, logger) {
|
|
27
92
|
return {
|
|
28
93
|
async register(params) {
|
|
29
94
|
return registerRuntimeEndpoint({ apiHost }, runtimeKey, params);
|
|
@@ -34,8 +99,46 @@ function buildApiPort(apiHost, runtimeKey) {
|
|
|
34
99
|
async unregister(endpointId, asNodeId) {
|
|
35
100
|
await unregisterRuntimeEndpoint({ apiHost }, runtimeKey, endpointId, asNodeId);
|
|
36
101
|
},
|
|
102
|
+
async transitionState(endpointId, params) {
|
|
103
|
+
try {
|
|
104
|
+
await transitionRuntimeEndpointState({ apiHost }, runtimeKey, endpointId, params);
|
|
105
|
+
}
|
|
106
|
+
catch (err) {
|
|
107
|
+
const status = errorStatus(err);
|
|
108
|
+
if (status === 404) {
|
|
109
|
+
logger.info("transitionState_404_degraded", {
|
|
110
|
+
endpoint_id: endpointId,
|
|
111
|
+
state: params.state,
|
|
112
|
+
reason: params.reason,
|
|
113
|
+
note: "apps/api state endpoint not yet shipped (PR-B1 in flight); state propagation skipped",
|
|
114
|
+
});
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
await sleep(500);
|
|
118
|
+
try {
|
|
119
|
+
await transitionRuntimeEndpointState({ apiHost }, runtimeKey, endpointId, params);
|
|
120
|
+
}
|
|
121
|
+
catch (err2) {
|
|
122
|
+
logger.warn("transitionState_failed", {
|
|
123
|
+
endpoint_id: endpointId,
|
|
124
|
+
state: params.state,
|
|
125
|
+
reason: params.reason,
|
|
126
|
+
err: err2 instanceof Error ? err2.message : String(err2),
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
},
|
|
37
131
|
};
|
|
38
132
|
}
|
|
133
|
+
function errorStatus(err) {
|
|
134
|
+
if (typeof err !== "object" || err === null)
|
|
135
|
+
return null;
|
|
136
|
+
const status = err.status;
|
|
137
|
+
return typeof status === "number" ? status : null;
|
|
138
|
+
}
|
|
139
|
+
function sleep(ms) {
|
|
140
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
141
|
+
}
|
|
39
142
|
export async function main() {
|
|
40
143
|
const accountId = process.env.MASONS_BROKER_ACCOUNT_ID ?? DEFAULT_ACCOUNT_ID;
|
|
41
144
|
const envApiHost = process.env.MASONS_BROKER_API_HOST;
|
|
@@ -55,7 +158,7 @@ export async function main() {
|
|
|
55
158
|
url: creds.connectorUrl,
|
|
56
159
|
token: creds.token,
|
|
57
160
|
});
|
|
58
|
-
const apiPort = buildApiPort(creds.apiHost, creds.token);
|
|
161
|
+
const apiPort = buildApiPort(creds.apiHost, creds.token, logger);
|
|
59
162
|
const broker = await startBrokerDaemon({
|
|
60
163
|
paths,
|
|
61
164
|
asNodeId,
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface GraceTimerManager {
|
|
2
|
+
start(endpoint_id: string, ms: number, onExpire: () => void): void;
|
|
3
|
+
cancel(endpoint_id: string): void;
|
|
4
|
+
has(endpoint_id: string): boolean;
|
|
5
|
+
cancelAll(): void;
|
|
6
|
+
active(): readonly string[];
|
|
7
|
+
}
|
|
8
|
+
export declare function createGraceTimerManager(): GraceTimerManager;
|
|
9
|
+
//# sourceMappingURL=grace-timer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grace-timer.d.ts","sourceRoot":"","sources":["../../src/broker/grace-timer.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,iBAAiB;IAGhC,KAAK,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;IAEnE,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAElC,GAAG,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC;IAElC,SAAS,IAAI,IAAI,CAAC;IAElB,MAAM,IAAI,SAAS,MAAM,EAAE,CAAC;CAC7B;AAED,wBAAgB,uBAAuB,IAAI,iBAAiB,CAmC3D"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export function createGraceTimerManager() {
|
|
2
|
+
const timers = new Map();
|
|
3
|
+
return {
|
|
4
|
+
start(endpoint_id, ms, onExpire) {
|
|
5
|
+
const existing = timers.get(endpoint_id);
|
|
6
|
+
if (existing)
|
|
7
|
+
clearTimeout(existing);
|
|
8
|
+
const handle = setTimeout(() => {
|
|
9
|
+
timers.delete(endpoint_id);
|
|
10
|
+
onExpire();
|
|
11
|
+
}, ms);
|
|
12
|
+
handle.unref?.();
|
|
13
|
+
timers.set(endpoint_id, handle);
|
|
14
|
+
},
|
|
15
|
+
cancel(endpoint_id) {
|
|
16
|
+
const handle = timers.get(endpoint_id);
|
|
17
|
+
if (handle) {
|
|
18
|
+
clearTimeout(handle);
|
|
19
|
+
timers.delete(endpoint_id);
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
has(endpoint_id) {
|
|
23
|
+
return timers.has(endpoint_id);
|
|
24
|
+
},
|
|
25
|
+
cancelAll() {
|
|
26
|
+
for (const [, handle] of timers)
|
|
27
|
+
clearTimeout(handle);
|
|
28
|
+
timers.clear();
|
|
29
|
+
},
|
|
30
|
+
active() {
|
|
31
|
+
return Array.from(timers.keys());
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
}
|
|
@@ -5,8 +5,15 @@ export interface IPCServerHandlers {
|
|
|
5
5
|
heartbeatEndpoint(endpoint_id: string): Promise<void>;
|
|
6
6
|
unregisterEndpoint(endpoint_id: string): Promise<void>;
|
|
7
7
|
send(body: SendBody): Promise<SendResponse>;
|
|
8
|
-
reattachEndpoint(endpoint_id: string, plugin_pid: number, ipcWs: WebSocket): Promise<
|
|
8
|
+
reattachEndpoint(endpoint_id: string, plugin_pid: number, ipcWs: WebSocket): Promise<ReattachResponse>;
|
|
9
|
+
listUndispatched(): Promise<UndispatchedListResponse>;
|
|
10
|
+
dispatch(undispatched_id: string, target_endpoint_id: string): Promise<void>;
|
|
9
11
|
}
|
|
12
|
+
export interface ReattachResponse {
|
|
13
|
+
restored: true;
|
|
14
|
+
reconnecting_buffer_count: number;
|
|
15
|
+
}
|
|
16
|
+
export type UndispatchedListResponse = import("./undispatched-inbox.js").UndispatchedMessage[];
|
|
10
17
|
export interface RegisterEndpointBody {
|
|
11
18
|
agent_id: string;
|
|
12
19
|
plugin_pid: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ipc-server.d.ts","sourceRoot":"","sources":["../../src/broker/ipc-server.ts"],"names":[],"mappings":"AAyBA,OAAO,EAAE,KAAK,OAAO,EAAE,SAAS,EAAmB,MAAM,IAAI,CAAC;AAE9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAQhD,MAAM,WAAW,iBAAiB;IAEhC,gBAAgB,CACd,IAAI,EAAE,oBAAoB,EAC1B,KAAK,EAAE,SAAS,GACf,OAAO,CAAC,wBAAwB,CAAC,CAAC;IAErC,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEtD,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvD,IAAI,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"ipc-server.d.ts","sourceRoot":"","sources":["../../src/broker/ipc-server.ts"],"names":[],"mappings":"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"}
|
|
@@ -94,6 +94,17 @@ async function routeHttp(req, res, bearerToken, handlers, logger) {
|
|
|
94
94
|
sendJson(res, 200, { ok: true });
|
|
95
95
|
return;
|
|
96
96
|
}
|
|
97
|
+
const reattachMatch = /^\/v1\/endpoint\/([^/]+)\/reattach$/.exec(url);
|
|
98
|
+
if (method === "POST" && reattachMatch && reattachMatch[1]) {
|
|
99
|
+
const body = await readJson(req);
|
|
100
|
+
const pid = typeof body.plugin_pid === "number" ? body.plugin_pid : Number.NaN;
|
|
101
|
+
if (!Number.isFinite(pid) || pid <= 0) {
|
|
102
|
+
throw new BrokerHttpError(400, "plugin_pid_invalid", "plugin_pid is required and must be a positive number");
|
|
103
|
+
}
|
|
104
|
+
const out = await handlers.reattachEndpoint(decodeURIComponent(reattachMatch[1]), pid, null);
|
|
105
|
+
sendJson(res, 200, out);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
97
108
|
const unregisterMatch = /^\/v1\/endpoint\/([^/]+)$/.exec(url);
|
|
98
109
|
if (method === "DELETE" && unregisterMatch && unregisterMatch[1]) {
|
|
99
110
|
await handlers.unregisterEndpoint(decodeURIComponent(unregisterMatch[1]));
|
|
@@ -106,6 +117,26 @@ async function routeHttp(req, res, bearerToken, handlers, logger) {
|
|
|
106
117
|
sendJson(res, 200, out);
|
|
107
118
|
return;
|
|
108
119
|
}
|
|
120
|
+
if (method === "GET" && url === "/v1/undispatched") {
|
|
121
|
+
const items = await handlers.listUndispatched();
|
|
122
|
+
sendJson(res, 200, { items });
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
if (method === "POST" && url === "/v1/dispatch") {
|
|
126
|
+
const body = await readJson(req);
|
|
127
|
+
const uid = typeof body.undispatched_id === "string"
|
|
128
|
+
? body.undispatched_id
|
|
129
|
+
: undefined;
|
|
130
|
+
const tid = typeof body.target_endpoint_id === "string"
|
|
131
|
+
? body.target_endpoint_id
|
|
132
|
+
: undefined;
|
|
133
|
+
if (!uid || !tid) {
|
|
134
|
+
throw new BrokerHttpError(400, "dispatch_body_invalid", "POST /v1/dispatch requires { undispatched_id, target_endpoint_id }");
|
|
135
|
+
}
|
|
136
|
+
await handlers.dispatch(uid, tid);
|
|
137
|
+
sendJson(res, 200, { ok: true });
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
109
140
|
sendJson(res, 404, { error: "not_found", path: url });
|
|
110
141
|
}
|
|
111
142
|
catch (err) {
|
package/dist/broker/paths.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export interface BrokerPaths {
|
|
|
5
5
|
discoveryFile: string;
|
|
6
6
|
discoveryDir: string;
|
|
7
7
|
logDir: string;
|
|
8
|
+
buffersDir: string;
|
|
8
9
|
}
|
|
9
10
|
export declare function resolveBrokerPaths(principal: string, runtimeToken: string, opts?: BrokerPathOptions): BrokerPaths;
|
|
10
11
|
//# sourceMappingURL=paths.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/broker/paths.ts"],"names":[],"mappings":"AAgCA,MAAM,WAAW,iBAAiB;IAEhC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IAE1B,aAAa,EAAE,MAAM,CAAC;IAEtB,YAAY,EAAE,MAAM,CAAC;IAErB,MAAM,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/broker/paths.ts"],"names":[],"mappings":"AAgCA,MAAM,WAAW,iBAAiB;IAEhC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IAE1B,aAAa,EAAE,MAAM,CAAC;IAEtB,YAAY,EAAE,MAAM,CAAC;IAErB,MAAM,EAAE,MAAM,CAAC;IAQf,UAAU,EAAE,MAAM,CAAC;CACpB;AASD,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,EACpB,IAAI,GAAE,iBAAsB,GAC3B,WAAW,CAgCb"}
|
package/dist/broker/paths.js
CHANGED
|
@@ -17,10 +17,12 @@ export function resolveBrokerPaths(principal, runtimeToken, opts = {}) {
|
|
|
17
17
|
.slice(0, AGENT_IDENTITY_HEX_LEN);
|
|
18
18
|
const discoveryDir = join(userData, "runtime-broker", sanitizeSegment(principal), agentIdentity);
|
|
19
19
|
const logDir = join(userData, "runtime-broker", "log");
|
|
20
|
+
const buffersDir = join(discoveryDir, "buffers");
|
|
20
21
|
return {
|
|
21
22
|
discoveryFile: join(discoveryDir, "discovery.json"),
|
|
22
23
|
discoveryDir,
|
|
23
24
|
logDir,
|
|
25
|
+
buffersDir,
|
|
24
26
|
};
|
|
25
27
|
}
|
|
26
28
|
function sanitizeSegment(segment) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-liveness.d.ts","sourceRoot":"","sources":["../../src/broker/plugin-liveness.ts"],"names":[],"mappings":"AAyBA,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAiBzD"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export function isPluginAlive(plugin_pid) {
|
|
2
|
+
if (!Number.isFinite(plugin_pid) || plugin_pid <= 0) {
|
|
3
|
+
return false;
|
|
4
|
+
}
|
|
5
|
+
try {
|
|
6
|
+
process.kill(plugin_pid, 0);
|
|
7
|
+
return true;
|
|
8
|
+
}
|
|
9
|
+
catch (err) {
|
|
10
|
+
const code = err.code;
|
|
11
|
+
if (code === "ESRCH")
|
|
12
|
+
return false;
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|