@intx/hub-sessions 0.1.2 → 0.2.2

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/LICENSE +176 -0
  2. package/README.md +84 -1
  3. package/dist/agent-repo.d.ts +89 -0
  4. package/dist/agent-repo.js +109 -0
  5. package/dist/agent-state-kind.d.ts +12 -0
  6. package/dist/agent-state-kind.js +185 -0
  7. package/dist/asset-service.d.ts +123 -0
  8. package/dist/asset-service.js +349 -0
  9. package/dist/available-skills-stanza.d.ts +21 -0
  10. package/dist/available-skills-stanza.js +32 -0
  11. package/dist/credential-push.d.ts +32 -0
  12. package/dist/credential-push.js +85 -0
  13. package/dist/event-collector-registry.d.ts +20 -0
  14. package/dist/event-collector-registry.js +115 -0
  15. package/dist/event-collector.d.ts +39 -0
  16. package/dist/event-collector.js +357 -0
  17. package/dist/hub-session-lookups.d.ts +17 -0
  18. package/dist/hub-session-lookups.js +204 -0
  19. package/dist/hub-session-orchestrator.d.ts +25 -0
  20. package/dist/hub-session-orchestrator.js +122 -0
  21. package/dist/index.d.ts +18 -0
  22. package/dist/index.js +16 -0
  23. package/dist/package-registry-kind.d.ts +70 -0
  24. package/dist/package-registry-kind.js +260 -0
  25. package/dist/repo-store/index.d.ts +4 -0
  26. package/dist/repo-store/index.js +3 -0
  27. package/dist/repo-store/store.d.ts +41 -0
  28. package/dist/repo-store/store.js +1692 -0
  29. package/dist/repo-store/subscribe-kind.d.ts +53 -0
  30. package/dist/repo-store/subscribe-kind.js +179 -0
  31. package/dist/repo-store/types.d.ts +483 -0
  32. package/dist/repo-store/types.js +42 -0
  33. package/dist/session-service.d.ts +235 -0
  34. package/dist/session-service.js +997 -0
  35. package/dist/skill-kind.d.ts +41 -0
  36. package/dist/skill-kind.js +288 -0
  37. package/dist/substrate.d.ts +8 -0
  38. package/dist/substrate.js +21 -0
  39. package/dist/workflow-kind.d.ts +21 -0
  40. package/dist/workflow-kind.js +263 -0
  41. package/dist/workflow-run-event-log.d.ts +21 -0
  42. package/dist/workflow-run-event-log.js +51 -0
  43. package/dist/workflow-run-kind.d.ts +326 -0
  44. package/dist/workflow-run-kind.js +2646 -0
  45. package/dist/workflow-run-reader.d.ts +47 -0
  46. package/dist/workflow-run-reader.js +157 -0
  47. package/dist/ws/index.d.ts +3 -0
  48. package/dist/ws/index.js +3 -0
  49. package/dist/ws/sidecar-events.d.ts +134 -0
  50. package/dist/ws/sidecar-events.js +70 -0
  51. package/dist/ws/sidecar-handler.d.ts +184 -0
  52. package/dist/ws/sidecar-handler.js +1603 -0
  53. package/dist/ws/sidecar-token-authenticator.d.ts +15 -0
  54. package/dist/ws/sidecar-token-authenticator.js +24 -0
  55. package/package.json +34 -12
  56. package/src/agent-repo.test.ts +0 -310
  57. package/src/agent-repo.ts +0 -165
  58. package/src/agent-state-kind.test.ts +0 -247
  59. package/src/agent-state-kind.ts +0 -204
  60. package/src/asset-service.test.ts +0 -540
  61. package/src/asset-service.ts +0 -378
  62. package/src/available-skills-stanza.test.ts +0 -87
  63. package/src/available-skills-stanza.ts +0 -47
  64. package/src/credential-push.ts +0 -65
  65. package/src/event-collector-registry.test.ts +0 -73
  66. package/src/event-collector-registry.ts +0 -171
  67. package/src/event-collector.test.ts +0 -1387
  68. package/src/event-collector.ts +0 -424
  69. package/src/hub-session-lookups.ts +0 -206
  70. package/src/hub-session-orchestrator.test.ts +0 -510
  71. package/src/hub-session-orchestrator.ts +0 -213
  72. package/src/index.ts +0 -78
  73. package/src/repo-store/index.ts +0 -15
  74. package/src/repo-store/store.test.ts +0 -1169
  75. package/src/repo-store/store.ts +0 -428
  76. package/src/repo-store/types.ts +0 -253
  77. package/src/session-service.test.ts +0 -895
  78. package/src/session-service.ts +0 -464
  79. package/src/skill-kind.test.ts +0 -599
  80. package/src/skill-kind.ts +0 -350
  81. package/src/ws/index.ts +0 -18
  82. package/src/ws/sidecar-events.test.ts +0 -96
  83. package/src/ws/sidecar-events.ts +0 -231
  84. package/src/ws/sidecar-handler.test.ts +0 -2217
  85. package/src/ws/sidecar-handler.ts +0 -1574
  86. package/tsconfig.json +0 -4
  87. package/tsconfig.tsbuildinfo +0 -1
@@ -1,213 +0,0 @@
1
- // Hub-side orchestrator for the sidecar event emitter.
2
- //
3
- // Subscribes to the sidecar router's events and runs the host-side
4
- // reactions: dispatching inference events to the event collector,
5
- // refreshing grants and credentials on reconnect, ingesting state
6
- // packs, re-deploying stale agents, persisting mail, and forwarding
7
- // mail.delivered notifications back to subscribers.
8
- //
9
- // The orchestrator depends on a narrow `HubSessionRouterFacade` rather
10
- // than the full SidecarRouter, so tests can drive subscriber behavior
11
- // with a small stub and an isolated emitter.
12
-
13
- import { eq } from "drizzle-orm";
14
- import { type } from "arktype";
15
- import type { DB } from "@intx/db";
16
- import { agentInstance } from "@intx/db/schema";
17
- import { resolveInstanceSources } from "@intx/db";
18
- import { parseMailToEmail } from "@intx/mime";
19
- import { parseInferenceEvent } from "@intx/types/runtime";
20
- import type { GrantRule, GrantStore } from "@intx/types/authz";
21
- import type { InferenceSource } from "@intx/types/runtime";
22
- import { getLogger } from "@intx/log";
23
-
24
- import type { AgentRepoStore } from "./agent-repo";
25
- import type { EventCollectorRegistry } from "./event-collector-registry";
26
- import type { SidecarEventEmitter } from "./ws/sidecar-events";
27
- import { parseAgentId, requireInstance } from "./hub-session-lookups";
28
-
29
- const log = getLogger(["hub", "orchestrator"]);
30
-
31
- /** Subset of `SidecarRouter` the orchestrator drives outbound. The
32
- * narrow surface keeps tests honest and decouples the orchestrator
33
- * from the rest of the router API. */
34
- export type HubSessionRouterFacade = {
35
- sendGrantsUpdate(agentAddress: string, grants: GrantRule[]): Promise<void>;
36
- sendSourcesUpdate(
37
- agentAddress: string,
38
- sources: InferenceSource[],
39
- defaultSource: string,
40
- ): Promise<void>;
41
- sendPack(
42
- agentAddress: string,
43
- pack: Uint8Array,
44
- ref: string,
45
- commitSha: string,
46
- ): Promise<void>;
47
- dispatchAgentEvent(agentAddress: string, event: unknown): void;
48
- };
49
-
50
- export type HubSessionOrchestratorDeps = {
51
- events: SidecarEventEmitter;
52
- router: HubSessionRouterFacade;
53
- db: DB["db"];
54
- eventCollectors: EventCollectorRegistry;
55
- grantStore: GrantStore;
56
- agentRepoStore: AgentRepoStore;
57
- };
58
-
59
- export type HubSessionOrchestrator = {
60
- /** Unsubscribe all listeners. Tests use this between cases; the hub
61
- * application doesn't need to dispose because the orchestrator's
62
- * lifetime matches the process. */
63
- dispose(): void;
64
- };
65
-
66
- export function createHubSessionOrchestrator(
67
- deps: HubSessionOrchestratorDeps,
68
- ): HubSessionOrchestrator {
69
- const { events, router, db, eventCollectors, grantStore, agentRepoStore } =
70
- deps;
71
-
72
- const unsubscribers: (() => void)[] = [];
73
-
74
- unsubscribers.push(
75
- events.on("agent.event", ({ agentAddress, event }) => {
76
- const validated = parseInferenceEvent(event);
77
- if (validated instanceof type.errors) {
78
- log.warn("Received invalid agent event for {agentAddress}: {summary}", {
79
- agentAddress,
80
- summary: validated.summary,
81
- });
82
- return;
83
- }
84
- eventCollectors.dispatch(agentAddress, validated);
85
- }),
86
- );
87
-
88
- unsubscribers.push(
89
- events.on("sidecar.disconnect", ({ agentAddresses }) => {
90
- for (const addr of agentAddresses) {
91
- eventCollectors.abandon(addr);
92
- }
93
- }),
94
- );
95
-
96
- unsubscribers.push(
97
- events.on("mail.outbound.undelivered", ({ recipients }) => {
98
- // The hub has no external mail transport today. Anything that
99
- // could not be delivered locally or queued for a disconnected
100
- // agent is dropped; log so operators can see it.
101
- log.warn("Dropping mail with no local recipient: {recipients}", {
102
- recipients: recipients.join(", "),
103
- });
104
- }),
105
- );
106
-
107
- unsubscribers.push(
108
- events.on("agent.deploy.ack", async ({ agentAddress, publicKey }) => {
109
- const instance = await requireInstance(db, agentAddress);
110
- await db
111
- .update(agentInstance)
112
- .set({ publicKey })
113
- .where(eq(agentInstance.id, instance.id));
114
- }),
115
- );
116
-
117
- unsubscribers.push(
118
- events.on("agent.reconnected", async ({ agentAddress }) => {
119
- const instance = await requireInstance(db, agentAddress);
120
-
121
- if (!instance.sessionId) {
122
- throw new Error(
123
- `Agent "${agentAddress}" reconnected but has no active session`,
124
- );
125
- }
126
- const sessionId = instance.sessionId;
127
-
128
- // Refresh grants before creating any local state. If this
129
- // fails, the address is rejected and nothing needs cleanup.
130
- const grants = await grantStore.collectGrants(
131
- instance.principalId,
132
- instance.tenantId,
133
- );
134
- await router.sendGrantsUpdate(agentAddress, grants);
135
-
136
- // Re-resolve and push credentials so the agent picks up any
137
- // rotations that happened while the sidecar was disconnected.
138
- // Fail-open: a stale credential causes runtime 401s, not a
139
- // security escalation, so we log rather than reject the
140
- // reconnect.
141
- try {
142
- const sources = await resolveInstanceSources(
143
- db,
144
- instance.tenantId,
145
- instance,
146
- );
147
- if (sources.length > 0) {
148
- const [first] = sources;
149
- if (first !== undefined) {
150
- await router.sendSourcesUpdate(agentAddress, sources, first.id);
151
- }
152
- }
153
- } catch (err: unknown) {
154
- const msg = err instanceof Error ? err.message : String(err);
155
- log.warn(
156
- "Failed to push credentials on reconnect for {agentAddress}: {msg}",
157
- { agentAddress, msg },
158
- );
159
- }
160
-
161
- const now = new Date();
162
- if (instance.status !== "running") {
163
- await db
164
- .update(agentInstance)
165
- .set({ status: "running", updatedAt: now })
166
- .where(eq(agentInstance.id, instance.id));
167
- }
168
- if (!eventCollectors.has(agentAddress)) {
169
- eventCollectors.create(
170
- agentAddress,
171
- instance.tenantId,
172
- sessionId,
173
- instance.id,
174
- );
175
- log.info(
176
- "Restored event collector for reconnected agent {agentAddress}",
177
- { agentAddress },
178
- );
179
- }
180
- }),
181
- );
182
-
183
- unsubscribers.push(
184
- events.on("deploy.ref.stale", async ({ agentAddress }) => {
185
- const agentId = parseAgentId(agentAddress);
186
- const { pack, commitSha, ref } =
187
- await agentRepoStore.createDeployPack(agentId);
188
- await router.sendPack(agentAddress, pack, ref, commitSha);
189
- log.info("Re-deployed stale agent {agentAddress}", { agentAddress });
190
- }),
191
- );
192
-
193
- unsubscribers.push(
194
- events.on("mail.persisted", (row) => {
195
- const parsed = parseMailToEmail(row.raw, row.id);
196
- router.dispatchAgentEvent(row.address, {
197
- type: "mail.delivered",
198
- data: {
199
- ...parsed,
200
- id: row.id,
201
- direction: row.direction,
202
- receivedAt: row.createdAt.toISOString(),
203
- },
204
- });
205
- }),
206
- );
207
-
208
- return {
209
- dispose() {
210
- for (const off of unsubscribers) off();
211
- },
212
- };
213
- }
package/src/index.ts DELETED
@@ -1,78 +0,0 @@
1
- export {
2
- createAgentRepoStore,
3
- type AgentRepoStore,
4
- type DeployContent,
5
- } from "./agent-repo";
6
- export {
7
- createSessionService,
8
- SessionLaunchError,
9
- type SessionService,
10
- } from "./session-service";
11
- export {
12
- createEventCollectorRegistry,
13
- type EventCollectorRegistry,
14
- } from "./event-collector-registry";
15
- export {
16
- createSidecarRouter,
17
- type SidecarRouter,
18
- type SidecarRouterConfig,
19
- type WsHandle,
20
- createSidecarEmitter,
21
- type SidecarEventEmitter,
22
- type SidecarEventMap,
23
- type SidecarEventType,
24
- type SidecarEventListener,
25
- type SidecarLookups,
26
- type SidecarMailPersistedPayload,
27
- type SidecarMailPersistedRow,
28
- } from "./ws";
29
- export {
30
- createHubSessionLookups,
31
- type HubSessionLookupsDeps,
32
- } from "./hub-session-lookups";
33
- export {
34
- createHubSessionOrchestrator,
35
- type HubSessionOrchestrator,
36
- type HubSessionOrchestratorDeps,
37
- type HubSessionRouterFacade,
38
- } from "./hub-session-orchestrator";
39
- export { pushSourceUpdates } from "./credential-push";
40
- export {
41
- skillKindHandler,
42
- skillAuthorize,
43
- skillFrontmatterSchema,
44
- getSkillIndex,
45
- type SkillIndexEntry,
46
- type SkillFrontmatter,
47
- type SkillPrincipal,
48
- type SkillHubPrincipal,
49
- type SkillSidecarPrincipal,
50
- } from "./skill-kind";
51
- export {
52
- createAssetService,
53
- AssetServiceError,
54
- type AssetService,
55
- type Asset,
56
- type AgentAsset,
57
- type AgentAssetWithAsset,
58
- type AccessMode,
59
- type CreateAssetParams,
60
- type PopulateAssetParams,
61
- type AttachAssetParams,
62
- type AssetServiceErrorReason,
63
- } from "./asset-service";
64
- export {
65
- buildAvailableSkillsStanza,
66
- type AvailableSkillEntry,
67
- } from "./available-skills-stanza";
68
- export type {
69
- CreateRepoStoreConfig,
70
- InitRepoOpts,
71
- KindHandler,
72
- Principal,
73
- RefEntry,
74
- RepoAction,
75
- RepoId,
76
- RepoStore,
77
- } from "./repo-store";
78
- export { createRepoStore, UserPrincipal } from "./repo-store";
@@ -1,15 +0,0 @@
1
- export type {
2
- AuthorizeFn,
3
- InitRepoOpts,
4
- KindHandler,
5
- Principal,
6
- RefEntry,
7
- RepoAction,
8
- RepoId,
9
- RepoKind,
10
- RepoStore,
11
- TreeContent,
12
- ValidatePushResult,
13
- } from "./types";
14
- export { UserPrincipal } from "./types";
15
- export { createRepoStore, type CreateRepoStoreConfig } from "./store";