@intx/hub-sessions 0.2.2 → 0.4.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.
Files changed (87) hide show
  1. package/README.md +3 -5
  2. package/dist/agent-repo.d.ts +23 -7
  3. package/dist/agent-repo.js +19 -6
  4. package/dist/agent-state-kind.js +18 -63
  5. package/dist/asset-service.d.ts +1 -20
  6. package/dist/asset-service.js +19 -97
  7. package/dist/committed-source-tree.d.ts +10 -0
  8. package/dist/committed-source-tree.js +35 -0
  9. package/dist/credential-push.d.ts +52 -7
  10. package/dist/credential-push.js +178 -22
  11. package/dist/event-collector-registry.d.ts +3 -2
  12. package/dist/event-collector-registry.js +42 -13
  13. package/dist/event-collector.d.ts +12 -2
  14. package/dist/event-collector.js +45 -4
  15. package/dist/hub-session-lookups.d.ts +125 -7
  16. package/dist/hub-session-lookups.js +541 -86
  17. package/dist/hub-session-orchestrator.d.ts +2 -3
  18. package/dist/hub-session-orchestrator.js +22 -56
  19. package/dist/index.d.ts +19 -9
  20. package/dist/index.js +16 -7
  21. package/dist/reconciliation-scheduler.d.ts +14 -0
  22. package/dist/reconciliation-scheduler.js +55 -0
  23. package/dist/repo-store/index.d.ts +2 -1
  24. package/dist/repo-store/index.js +1 -0
  25. package/dist/repo-store/store.d.ts +1 -1
  26. package/dist/repo-store/store.js +138 -1
  27. package/dist/repo-store/subscribe-kind.d.ts +6 -3
  28. package/dist/repo-store/subscribe-kind.js +42 -77
  29. package/dist/repo-store/types.d.ts +94 -6
  30. package/dist/repo-store/user-principal-gate.d.ts +26 -0
  31. package/dist/repo-store/user-principal-gate.js +78 -0
  32. package/dist/session-service.d.ts +252 -126
  33. package/dist/session-service.js +851 -624
  34. package/dist/sidecar-allocation/capability-policy.d.ts +27 -0
  35. package/dist/sidecar-allocation/capability-policy.js +124 -0
  36. package/dist/sidecar-allocation/contracts.d.ts +101 -0
  37. package/dist/sidecar-allocation/contracts.js +26 -0
  38. package/dist/sidecar-allocation/index.d.ts +5 -0
  39. package/dist/sidecar-allocation/index.js +4 -0
  40. package/dist/sidecar-allocation/operation.d.ts +10 -0
  41. package/dist/sidecar-allocation/operation.js +54 -0
  42. package/dist/sidecar-allocation/plugin-registry.d.ts +24 -0
  43. package/dist/sidecar-allocation/plugin-registry.js +61 -0
  44. package/dist/sidecar-allocation/reconciler.d.ts +54 -0
  45. package/dist/sidecar-allocation/reconciler.js +825 -0
  46. package/dist/skill-kind.js +12 -62
  47. package/dist/substrate.d.ts +3 -3
  48. package/dist/substrate.js +1 -1
  49. package/dist/workflow-allocation-service.d.ts +64 -0
  50. package/dist/workflow-allocation-service.js +554 -0
  51. package/dist/workflow-closure-resolution.d.ts +106 -0
  52. package/dist/workflow-closure-resolution.js +123 -0
  53. package/dist/workflow-definition-ensure.d.ts +24 -0
  54. package/dist/workflow-definition-ensure.js +75 -0
  55. package/dist/workflow-dispatch-service.d.ts +42 -0
  56. package/dist/workflow-dispatch-service.js +209 -0
  57. package/dist/workflow-dispatch-settlement.d.ts +29 -0
  58. package/dist/workflow-dispatch-settlement.js +140 -0
  59. package/dist/workflow-kind.d.ts +29 -1
  60. package/dist/workflow-kind.js +143 -139
  61. package/dist/workflow-probe-gate.d.ts +286 -0
  62. package/dist/workflow-probe-gate.js +382 -0
  63. package/dist/workflow-run-kind.d.ts +239 -32
  64. package/dist/workflow-run-kind.js +874 -188
  65. package/dist/workflow-run-reader.d.ts +1 -1
  66. package/dist/workflow-run-reader.js +3 -7
  67. package/dist/workflow-run-restore.d.ts +16 -0
  68. package/dist/workflow-run-restore.js +30 -0
  69. package/dist/workflow-source-closure.d.ts +35 -0
  70. package/dist/workflow-source-closure.js +342 -0
  71. package/dist/workflow-source-pins.d.ts +8 -0
  72. package/dist/workflow-source-pins.js +14 -0
  73. package/dist/ws/index.d.ts +3 -3
  74. package/dist/ws/index.js +2 -2
  75. package/dist/ws/pending-tracker.d.ts +93 -0
  76. package/dist/ws/pending-tracker.js +132 -0
  77. package/dist/ws/sidecar-events.d.ts +139 -37
  78. package/dist/ws/sidecar-events.js +2 -2
  79. package/dist/ws/sidecar-handler.d.ts +218 -60
  80. package/dist/ws/sidecar-handler.js +1713 -732
  81. package/dist/ws/sidecar-handler.test-helpers.d.ts +38 -0
  82. package/dist/ws/sidecar-handler.test-helpers.js +95 -0
  83. package/dist/ws/sidecar-token-authenticator.d.ts +3 -1
  84. package/dist/ws/sidecar-token-authenticator.js +78 -7
  85. package/package.json +14 -13
  86. package/dist/available-skills-stanza.d.ts +0 -21
  87. package/dist/available-skills-stanza.js +0 -32
@@ -0,0 +1,132 @@
1
+ // Generic pending-round-trip tracker for hub→sidecar requests.
2
+ //
3
+ // `sidecar-handler.ts` runs five request/response round-trips over the same
4
+ // websocket (session requests, agent deploys, pack transfers, undeploys,
5
+ // workflow probes). Each used to hand-roll the same lifecycle: register an
6
+ // entry in a Map keyed by request/transfer/address, arm a timeout that
7
+ // settles the entry, settle it early when the matching reply frame arrives,
8
+ // and sweep every entry owned by a connection when that connection drops.
9
+ // The sites differ only in the key, the resolved value, and the per-site
10
+ // cleanup their resolve/reject closures capture — the map + timer lifecycle
11
+ // is identical. `PendingTracker` owns that lifecycle so timeouts and
12
+ // disconnect sweeps behave uniformly and a fix to either lands in one place.
13
+ const scheduleOnGlobalTimer = (handler, ms) => {
14
+ const timer = setTimeout(handler, ms);
15
+ return () => {
16
+ clearTimeout(timer);
17
+ };
18
+ };
19
+ export class PendingTracker {
20
+ schedule;
21
+ entries = new Map();
22
+ /**
23
+ * `schedule` defaults to the global timer, which is what every production
24
+ * caller wants; it is injectable so a caller can drive the timeouts.
25
+ */
26
+ constructor(schedule = scheduleOnGlobalTimer) {
27
+ this.schedule = schedule;
28
+ }
29
+ /**
30
+ * Register a pending round-trip and arm its timeout. The entry is stored
31
+ * before the caller sends its frame, so a synchronous reply (loopback
32
+ * transports, tests) settles it. When `timeoutMs` elapses the entry is
33
+ * dropped and `reject` is invoked with `timeoutMessage` — the same
34
+ * rejection path an error reply frame uses, so per-site cleanup (routing
35
+ * rollback, address bookkeeping) runs exactly once either way.
36
+ *
37
+ * `meta` is the opaque per-entry payload settle-time ownership checks read
38
+ * off `get`; pass `undefined` when the round-trip carries none.
39
+ */
40
+ register(key, ws, options, meta) {
41
+ // Identifies the entry this call is about to register, so the handler
42
+ // below can recognize it. Allocated before `schedule`, because the
43
+ // handler closes over it and the entry itself does not exist yet.
44
+ const token = Symbol("pending-entry");
45
+ const cancelTimeout = this.schedule(() => {
46
+ // Only the entry this call registered may be timed out. The global
47
+ // timer never fires a cancelled timeout, but `schedule` is injectable
48
+ // now and a caller's implementation is not owed that guarantee -- so
49
+ // the handler checks rather than trusting cancellation to be perfect.
50
+ // The check compares `token` rather than asking whether the key is
51
+ // occupied: keys are reused (`pendingDeploys` is keyed by agent
52
+ // address), so a stale fire can find the key held by a live successor.
53
+ // Treating that as its own entry would drop the successor without
54
+ // settling it and run this already-settled entry's per-site cleanup a
55
+ // second time.
56
+ const current = this.entries.get(key);
57
+ if (current === undefined || current.token !== token)
58
+ return;
59
+ this.entries.delete(key);
60
+ options.reject(options.timeoutMessage);
61
+ }, options.timeoutMs);
62
+ this.entries.set(key, {
63
+ key,
64
+ ws,
65
+ meta,
66
+ resolve: options.resolve,
67
+ reject: options.reject,
68
+ cancelTimeout,
69
+ token,
70
+ });
71
+ }
72
+ has(key) {
73
+ return this.entries.has(key);
74
+ }
75
+ get(key) {
76
+ return this.entries.get(key);
77
+ }
78
+ /**
79
+ * Settle a pending entry as resolved. No-op when the entry is already
80
+ * gone (timed out or swept on disconnect).
81
+ */
82
+ resolve(key, value) {
83
+ const entry = this.entries.get(key);
84
+ if (entry === undefined)
85
+ return false;
86
+ entry.cancelTimeout();
87
+ this.entries.delete(key);
88
+ entry.resolve(value);
89
+ return true;
90
+ }
91
+ /**
92
+ * Settle a pending entry as rejected. No-op when the entry is already
93
+ * gone (timed out or swept on disconnect).
94
+ */
95
+ reject(key, error) {
96
+ const entry = this.entries.get(key);
97
+ if (entry === undefined)
98
+ return false;
99
+ entry.cancelTimeout();
100
+ this.entries.delete(key);
101
+ entry.reject(error);
102
+ return true;
103
+ }
104
+ /**
105
+ * Drop a pending entry without settling it. The caller rejects its own
106
+ * promise directly — used when a frame provably never reached the wire, so
107
+ * the failure must not take the normal rejection path (the deploy
108
+ * "failed to send" path, which must report `frameSent: false` and must not
109
+ * let the armed timer fire later and double-reject).
110
+ */
111
+ delete(key) {
112
+ const entry = this.entries.get(key);
113
+ if (entry === undefined)
114
+ return;
115
+ entry.cancelTimeout();
116
+ this.entries.delete(key);
117
+ }
118
+ /**
119
+ * Reject every pending entry owned by `ws` — the disconnect sweep. Each
120
+ * entry's reject closure runs its own per-site cleanup (address
121
+ * bookkeeping), identical to a frame-error rejection.
122
+ */
123
+ rejectAllForWs(ws, error) {
124
+ for (const [key, entry] of this.entries) {
125
+ if (entry.ws !== ws)
126
+ continue;
127
+ entry.cancelTimeout();
128
+ this.entries.delete(key);
129
+ entry.reject(error);
130
+ }
131
+ }
132
+ }
@@ -1,15 +1,41 @@
1
- import type { PackRejectReason, RepoId } from "@intx/types/sidecar";
2
- import type { ConnectorThreadState } from "@intx/types/runtime";
1
+ import type { PackRejectReason, RepoId, RunGrantsFrame } from "@intx/types/sidecar";
2
+ import type { ApprovalSnapshot, ConnectorThreadState } from "@intx/types/runtime";
3
+ import type { SignalKind } from "@intx/types";
3
4
  export type SidecarMailPersistedRow = {
4
5
  id: string;
5
6
  createdAt: Date;
6
7
  direction: "inbound" | "outbound";
7
- instanceId: string | null;
8
+ runId: string | null;
8
9
  address: string;
9
10
  };
10
11
  export type SidecarMailPersistedPayload = SidecarMailPersistedRow & {
11
12
  raw: Uint8Array;
12
13
  };
14
+ /** Authenticated connection scope attached to a workflow-run pack. */
15
+ export type WorkflowRunPackSource = {
16
+ readonly kind: "allocated";
17
+ readonly agentAddress: string;
18
+ readonly allocationId: string;
19
+ readonly anchorRunId: string;
20
+ readonly generation: number;
21
+ };
22
+ /**
23
+ * Outcome of reserving a mail-triggered run's grants. `skip` means the
24
+ * recipient names no workflow deployment; `rejected` means the deployment's
25
+ * stable run is terminal or its requirements cannot be authorized;
26
+ * `materialized` carries the canonical persisted wire rows.
27
+ */
28
+ export type MailTriggeredRunGrantsResult = {
29
+ outcome: "skip";
30
+ } | {
31
+ outcome: "rejected";
32
+ status: 403 | 409;
33
+ code: string;
34
+ message: string;
35
+ } | {
36
+ outcome: "materialized";
37
+ stepGrants: RunGrantsFrame["stepGrants"];
38
+ };
13
39
  export type SidecarEventMap = {
14
40
  /** Notification. Emitted for every agent.event frame the wire layer
15
41
  * decodes. The wire layer also forwards the event to in-process agent
@@ -21,11 +47,21 @@ export type SidecarEventMap = {
21
47
  event: unknown;
22
48
  };
23
49
  /** Notification. Emitted once when a sidecar's connection closes,
24
- * carrying every address the connection owned -- challenged session
25
- * addresses and hub-minted workflow-substrate deployment addresses
26
- * alike -- so lifecycle teardown covers both. */
50
+ * carrying every address the connection owned -- session addresses
51
+ * and hub-minted workflow-substrate deployment addresses alike --
52
+ * so lifecycle teardown covers both. */
27
53
  "sidecar.disconnect": {
28
54
  ownedAddresses: string[];
55
+ /** Present only when the closing socket was the current allocated owner. */
56
+ allocated?: {
57
+ allocationId: string;
58
+ generation: number;
59
+ };
60
+ };
61
+ /** Notification after the exact authenticated allocation generation registers. */
62
+ "sidecar.allocated.connected": {
63
+ allocationId: string;
64
+ generation: number;
29
65
  };
30
66
  /** Notification. Emitted when a mail.outbound frame from a sidecar
31
67
  * names recipients that the wire layer could not deliver locally and
@@ -40,11 +76,30 @@ export type SidecarEventMap = {
40
76
  * the rows; this event fires for each so subscribers can react
41
77
  * per-row (e.g. dispatch a delivered event). */
42
78
  "mail.persisted": SidecarMailPersistedPayload;
79
+ /** Notification after a sidecar confirms a mail trigger is in its durable
80
+ * local inbox. For a provisioned worker, `allocated` identifies the exact
81
+ * generation that acknowledged the message. This is not workflow
82
+ * settlement; the Hub retains the payload until the Git claim-check records
83
+ * consumption. */
84
+ "mail.inbound.acknowledged": {
85
+ agentAddress: string;
86
+ messageId: string;
87
+ allocated?: {
88
+ allocationId: string;
89
+ anchorRunId: string;
90
+ generation: number;
91
+ };
92
+ };
43
93
  /** Awaited. Emitted when an agent.deploy.ack frame arrives. Rejection
44
94
  * fails the pending deploy with the listener's error. */
45
95
  "agent.deploy.ack": {
46
96
  agentAddress: string;
47
97
  publicKey: string;
98
+ allocated?: {
99
+ allocationId: string;
100
+ anchorRunId: string;
101
+ generation: number;
102
+ };
48
103
  };
49
104
  /** Notification. Emitted when the sidecar reports a change to an
50
105
  * agent's connector-thread state. The wire layer caches the state
@@ -56,24 +111,6 @@ export type SidecarEventMap = {
56
111
  agentAddress: string;
57
112
  connectorState: ConnectorThreadState | null;
58
113
  };
59
- /** Awaited. Emitted per address after challenge verification
60
- * succeeds and before the disconnect queue is flushed. Rejection
61
- * rolls that address back from the routing table; earlier listeners
62
- * in registration order have already executed and their side effects
63
- * are not undone. A subsequent reconnect arriving mid-flight may
64
- * supersede this one, so listeners must be idempotent. */
65
- "agent.reconnected": {
66
- agentAddress: string;
67
- };
68
- /** Awaited. Emitted per address after the wire layer has confirmed
69
- * the sidecar's deploy ref is stale relative to the hub's current
70
- * ref. The listener's job is to push a fresh deploy pack. The wire
71
- * layer fires this only when staleness is confirmed; subscribing
72
- * without a `lookupDeployRef` configured on the router will never
73
- * deliver. */
74
- "deploy.ref.stale": {
75
- agentAddress: string;
76
- };
77
114
  };
78
115
  export type SidecarEventType = keyof SidecarEventMap;
79
116
  export type SidecarEventListener<T extends SidecarEventType> = (payload: SidecarEventMap[T]) => void | Promise<void>;
@@ -88,15 +125,19 @@ export type SidecarEventEmitter = {
88
125
  };
89
126
  export declare function createSidecarEmitter(): SidecarEventEmitter;
90
127
  export type SidecarLookups = {
91
- /** Returns the hex-encoded Ed25519 public key stored for the address,
92
- * or `null` if the address is unknown. Used during the reconnect
93
- * challenge to verify the sidecar's signature. */
94
- lookupPublicKey?: (agentAddress: string) => Promise<string | null>;
95
128
  /** Returns the hub's current deploy ref for the address, or `null` if
96
129
  * no deploy state is tracked. The wire layer compares this against
97
130
  * the sidecar's reported ref during reconnect and emits
98
131
  * `deploy.ref.stale` only on mismatch. */
99
132
  lookupDeployRef?: (agentAddress: string) => Promise<string | null>;
133
+ /** Re-resolves a reconnecting deployment's current credential delivery and
134
+ * reconciles the child, so a credential revoked, deleted, or rotated while
135
+ * the sidecar was disconnected is applied on reconnect (closing the offline
136
+ * window). Keyed by the run address. Fire-and-forget: the wire layer does not
137
+ * await it and it never throws -- a failure is logged and dropped, like the
138
+ * best-effort source-update pushes. No-ops for a run that persisted no
139
+ * credential refs. */
140
+ resyncCredentials?: (agentAddress: string) => void;
100
141
  /** Persists a delivered outbound mail frame. Returns one row per
101
142
  * persisted record; the wire layer attaches `raw` to each row and
102
143
  * emits a `mail.persisted` event. */
@@ -105,9 +146,73 @@ export type SidecarLookups = {
105
146
  recipients: string[];
106
147
  raw: Uint8Array;
107
148
  }) => Promise<SidecarMailPersistedRow[]>;
149
+ /** Resolves the hub-held public key a sender address signs with, hex-encoded,
150
+ * or `null` when the sender has no resolvable key (a run whose deploy is not
151
+ * yet acked, an address matching no known principal). The `mail.inbound` frame
152
+ * carries the result so a recipient verifies the signature locally against the
153
+ * hub-resolved key rather than the message's own spoofable From. Returns only
154
+ * the key string, not its source, so the recipient cannot branch on sender
155
+ * kind.
156
+ *
157
+ * Best-effort: this NEVER throws. A resolution fault degrades to `null`
158
+ * (logged at ERROR by the resolver), so a key-resolution problem can never
159
+ * block mail delivery. The strict, throwing resolver is `resolveSenderKey`
160
+ * in `@intx/db`; the reconnect reconciliation consumes it through
161
+ * `resolveSenderKeyStrict` below, which needs to tell a fault from a genuine
162
+ * absence. */
163
+ resolveSenderKey?: (address: string) => Promise<string | null>;
164
+ /** Strict sibling of `resolveSenderKey` for the reconnect reconciliation. The
165
+ * register/reconnect handler re-resolves each reported cached sender and acts
166
+ * on the three-way outcome the best-effort resolver collapses:
167
+ * - returns the hex key when the sender resolves -> push `sender.key.refresh`;
168
+ * - returns `null` for a CONFIRMED absence (no matching principal = a deleted
169
+ * sender) -> push `sender.key.evict`;
170
+ * - THROWS on a fault (ambiguous address, a keyless-principal invariant
171
+ * break, a DB error) -> keep the stale cached key, evict nothing.
172
+ * Never evicting on a throw is load-bearing: dropping a live key on a
173
+ * transient DB fault would be worse than doing nothing. Wraps the strict
174
+ * `resolveSenderKey` in `@intx/db` (unwrapped to the key string). Note the
175
+ * naming inversion: in `@intx/db` the STRICT resolver is `resolveSenderKey`
176
+ * and the best-effort one is `resolveFrameSenderKey`, whereas on this lookup
177
+ * type the best-effort field is `resolveSenderKey` and this is the strict
178
+ * one. */
179
+ resolveSenderKeyStrict?: (address: string) => Promise<string | null>;
180
+ /** Co-writes the `signal_correlation` routing row and the `approval` row
181
+ * for a suspending workflow agent step, in one transaction. Called from
182
+ * the `signal.correlation.register` frame handler after the wire layer has
183
+ * confirmed the sending sidecar owns `agentAddress`. Idempotent: a
184
+ * redelivered frame (reconnect, workflow-log replay, supervisor restart
185
+ * re-emitting) is a no-op, not an error. The wire layer does not carry
186
+ * `signalName`; the host derives it from `correlationId`. Resolves the
187
+ * tenancy from the workflow deployment the address names. */
188
+ registerSignalCorrelation?: (args: {
189
+ correlationId: string;
190
+ runId: string;
191
+ anchorRunId: string;
192
+ agentAddress: string;
193
+ kind: SignalKind;
194
+ approvalSnapshot: ApprovalSnapshot;
195
+ }) => Promise<void>;
196
+ /** Reserves a mail-triggered workflow run's grants from the receiving
197
+ * deployment's definition, returning a discriminated result the
198
+ * `mail.outbound` handler orders against delivery. Called for each recipient
199
+ * that is a workflow deployment. The `runId` is the deployment's stable
200
+ * address-derived run id.
201
+ *
202
+ * On `materialized`, `stepGrants` are already persisted and the caller sends
203
+ * them ahead of the inbound mail. Reservation is idempotent on the runId, so
204
+ * a redelivered inbound mail neither double-mints nor throws. On `skip` the
205
+ * address names no deployed workflow deployment, so no grants are sent and
206
+ * the mail still forwards. On `rejected` the stable run is terminal or a
207
+ * declared requirement's authority is insufficient; the caller fails the
208
+ * mail closed for that recipient. */
209
+ materializeMailTriggeredRunGrants?: (args: {
210
+ agentAddress: string;
211
+ runId: string;
212
+ }) => Promise<MailTriggeredRunGrantsResult>;
108
213
  /** Ingests a received agent-state pack and returns whether the wire
109
214
  * layer should ack or reject the pack to the sidecar. `repoId.kind`
110
- * is `"agent-state"` and `repoId.id` is the agent address. The wire
215
+ * is `"agent-state"` and `repoId.id` is the run address. The wire
111
216
  * layer dispatches on `repoId.kind` against the receive lookups
112
217
  * before calling either; this lookup must reject any pack whose
113
218
  * `repoId.kind` is not `"agent-state"`. */
@@ -118,14 +223,11 @@ export type SidecarLookups = {
118
223
  reason: PackRejectReason;
119
224
  }>;
120
225
  /** Ingests a received workflow-run pack and returns whether the wire
121
- * layer should ack or reject the pack to the sidecar. `repoId.kind`
122
- * is `"workflow-run"` and `repoId.id` is the deployment id (which the
123
- * hub-side substrate maps to a `WorkflowRunSupervisorPrincipal`
124
- * during the receivePack call). The wire layer dispatches on
125
- * `repoId.kind` against the receive lookups before calling either;
126
- * this lookup must reject any pack whose `repoId.kind` is not
127
- * `"workflow-run"`. */
128
- receiveWorkflowRunPack?: (repoId: RepoId, pack: Uint8Array, ref: string, commitSha: string) => Promise<{
226
+ * layer should ack or reject the pack to the sidecar. `source` is derived
227
+ * from the authenticated socket, never from the frame. The lookup must
228
+ * revalidate that source against durable deployment/allocation ownership
229
+ * before advancing the Git ref. */
230
+ receiveWorkflowRunPack?: (repoId: RepoId, pack: Uint8Array, ref: string, commitSha: string, source: WorkflowRunPackSource) => Promise<{
129
231
  accepted: true;
130
232
  } | {
131
233
  accepted: false;
@@ -24,11 +24,11 @@ export function createSidecarEmitter() {
24
24
  const listeners = {
25
25
  "agent.event": new Set(),
26
26
  "sidecar.disconnect": new Set(),
27
+ "sidecar.allocated.connected": new Set(),
27
28
  "mail.outbound.undelivered": new Set(),
28
29
  "mail.persisted": new Set(),
30
+ "mail.inbound.acknowledged": new Set(),
29
31
  "agent.deploy.ack": new Set(),
30
- "agent.reconnected": new Set(),
31
- "deploy.ref.stale": new Set(),
32
32
  "connector.state.changed": new Set(),
33
33
  };
34
34
  function on(type, listener) {