@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
@@ -0,0 +1,17 @@
1
+ import type { DB } from "@intx/db";
2
+ import type { AgentRepoStore } from "./agent-repo.js";
3
+ import type { SidecarLookups } from "./ws/sidecar-events.js";
4
+ export type HubSessionLookupsDeps = {
5
+ db: DB["db"];
6
+ agentRepoStore: AgentRepoStore;
7
+ };
8
+ export declare function createHubSessionLookups(deps: HubSessionLookupsDeps): Required<SidecarLookups>;
9
+ /**
10
+ * Extract the instance id from an `<instanceId>@<domain>` agent address.
11
+ * Throws on any input the `@intx/types`-owned `parseAgentAddress`
12
+ * rejects: missing or leading `@`, empty domain, or an instance id
13
+ * without the canonical `ins_` prefix.
14
+ */
15
+ export declare function parseAgentId(agentAddress: string): string;
16
+ export declare function findInstance(db: DB["db"], agentAddress: string): Promise<Awaited<ReturnType<typeof db.query.agentInstance.findFirst>>>;
17
+ export declare function requireInstance(db: DB["db"], agentAddress: string): Promise<NonNullable<Awaited<ReturnType<typeof db.query.agentInstance.findFirst>>>>;
@@ -0,0 +1,204 @@
1
+ // Lookups that the sidecar wire layer issues against host state. These
2
+ // are queries (one answer per question) rather than events (broadcast
3
+ // notifications), so they live separately from the event emitter.
4
+ //
5
+ // Each lookup is a stateless DB or repo call. They are gathered into a
6
+ // single struct that the hub app passes to `createSidecarRouter` as
7
+ // `lookups`.
8
+ import { eq, and, isNull } from "drizzle-orm";
9
+ import { agentInstance, sessionMail, workflowDeployment, } from "@intx/db/schema";
10
+ import { getLogger } from "@intx/log";
11
+ import { parseAgentAddress } from "@intx/types";
12
+ import { isWorkflowDerivedAddress } from "@intx/workflow-deploy";
13
+ import { generateId } from "@intx/hub-common";
14
+ const logger = getLogger(["hub", "lookups"]);
15
+ export function createHubSessionLookups(deps) {
16
+ const { db, agentRepoStore } = deps;
17
+ return {
18
+ async lookupPublicKey(agentAddress) {
19
+ // Route by address space, not a blind two-table fallback: a
20
+ // workflow-derived address's key lives on its workflow_deployment
21
+ // row, a launched agent's on its agent_instance row, and the two
22
+ // spaces are disjoint. Routing (rather than falling back) means a
23
+ // launched agent that is missing its instance row returns null and
24
+ // fails its challenge visibly, instead of silently resolving against
25
+ // the wrong table.
26
+ if (isWorkflowDerivedAddress(agentAddress)) {
27
+ // Filter to a live ("deployed") deployment so a torn-down
28
+ // deployment's key can no longer satisfy a challenge. A null
29
+ // publicKey (deployed but not yet acked, or pre-migration) or an
30
+ // absent row returns null -- the challenge fails closed and the
31
+ // address stays unrouted rather than routing without ownership
32
+ // proof.
33
+ const row = await db
34
+ .select({ publicKey: workflowDeployment.publicKey })
35
+ .from(workflowDeployment)
36
+ .where(and(eq(workflowDeployment.address, agentAddress), eq(workflowDeployment.status, "deployed")))
37
+ .limit(1)
38
+ .then((rows) => rows[0]);
39
+ return row?.publicKey ?? null;
40
+ }
41
+ const row = await db
42
+ .select({ publicKey: agentInstance.publicKey })
43
+ .from(agentInstance)
44
+ .where(and(eq(agentInstance.address, agentAddress), isNull(agentInstance.endedAt)))
45
+ .limit(1)
46
+ .then((rows) => rows[0]);
47
+ return row?.publicKey ?? null;
48
+ },
49
+ async lookupDeployRef(agentAddress) {
50
+ const agentId = parseAgentId(agentAddress);
51
+ return agentRepoStore.getDeployRef(agentId);
52
+ },
53
+ async persistMail({ senderAddress, recipients, raw }) {
54
+ const senderInstance = await requireInstance(db, senderAddress);
55
+ if (!senderInstance.sessionId) {
56
+ throw new Error(`Instance ${senderInstance.id} has no session for address "${senderAddress}"`);
57
+ }
58
+ const createdAt = new Date();
59
+ // Outbound record on the sender's session.
60
+ const outboundId = generateId("sessionMail");
61
+ const outboundRecord = {
62
+ id: outboundId,
63
+ sessionId: senderInstance.sessionId,
64
+ instanceId: senderInstance.id,
65
+ tenantId: senderInstance.tenantId,
66
+ direction: "outbound",
67
+ status: "delivered",
68
+ raw,
69
+ createdAt,
70
+ };
71
+ // Inbound records for each recipient that has an active agent
72
+ // instance. Recipients that are not agent instances (e.g. human
73
+ // user addresses) are skipped.
74
+ const recipientResults = await Promise.all(recipients.map(async (addr) => {
75
+ const row = await findInstance(db, addr);
76
+ if (row === undefined) {
77
+ return null;
78
+ }
79
+ if (row.sessionId === null) {
80
+ logger.warn `Active instance ${row.id} for "${addr}" has no session; skipping inbound record`;
81
+ return null;
82
+ }
83
+ return { addr, instance: row, sessionId: row.sessionId };
84
+ }));
85
+ const recipientInstances = recipientResults.filter((r) => r !== null);
86
+ const inboundEntries = recipientInstances.map(({ addr, instance, sessionId }) => {
87
+ const id = generateId("sessionMail");
88
+ return {
89
+ record: {
90
+ id,
91
+ sessionId,
92
+ instanceId: instance.id,
93
+ tenantId: instance.tenantId,
94
+ direction: "inbound",
95
+ status: "delivered",
96
+ raw,
97
+ createdAt,
98
+ },
99
+ result: {
100
+ id,
101
+ direction: "inbound",
102
+ instanceId: instance.id,
103
+ address: addr,
104
+ createdAt,
105
+ },
106
+ };
107
+ });
108
+ await db
109
+ .insert(sessionMail)
110
+ .values([outboundRecord, ...inboundEntries.map((e) => e.record)]);
111
+ return [
112
+ {
113
+ id: outboundId,
114
+ direction: "outbound",
115
+ instanceId: senderInstance.id,
116
+ address: senderInstance.address,
117
+ createdAt,
118
+ },
119
+ ...inboundEntries.map((e) => e.result),
120
+ ];
121
+ },
122
+ async receiveAgentStatePack(repoId, pack, ref, commitSha) {
123
+ if (repoId.kind !== "agent-state") {
124
+ throw new Error(`hub-session lookups receiveAgentStatePack received unsupported repo kind ${JSON.stringify(repoId.kind)}`);
125
+ }
126
+ const agentAddress = repoId.id;
127
+ const agentId = parseAgentId(agentAddress);
128
+ try {
129
+ await agentRepoStore.receiveAgentStatePack({ kind: "agent-state", id: agentId }, pack, ref, commitSha);
130
+ }
131
+ catch (err) {
132
+ const msg = err instanceof Error ? err.message : String(err);
133
+ if (msg.startsWith("path_violation")) {
134
+ logger.warn `State pack rejected for ${agentAddress}: ${msg}`;
135
+ return { accepted: false, reason: "path_violation" };
136
+ }
137
+ // Any other failure from the repo subsystem reaches the
138
+ // WebSocket handler as an unhandled rejection unless we catch
139
+ // it here. Transient failures during receivePack (the agent
140
+ // directory being torn down concurrently with an in-flight
141
+ // pack write, filesystem errors mid-rename, etc.) are
142
+ // recoverable from the sender's perspective — the sender can
143
+ // re-push. Surface every such failure as a structured pack
144
+ // rejection (`corrupt` is the closest existing reason — from
145
+ // the sender's perspective the pack failed to index) and log
146
+ // the underlying error so the cause stays traceable on the
147
+ // hub side.
148
+ logger.error `State pack receive failed for ${agentAddress}: ${msg}`;
149
+ return { accepted: false, reason: "corrupt" };
150
+ }
151
+ return { accepted: true };
152
+ },
153
+ async receiveWorkflowRunPack(repoId, pack, ref, commitSha) {
154
+ if (repoId.kind !== "workflow-run") {
155
+ throw new Error(`hub-session lookups receiveWorkflowRunPack received unsupported repo kind ${JSON.stringify(repoId.kind)}`);
156
+ }
157
+ const deploymentId = repoId.id;
158
+ try {
159
+ await agentRepoStore.receiveWorkflowRunPack({ kind: "workflow-run", id: deploymentId }, pack, ref, commitSha);
160
+ }
161
+ catch (err) {
162
+ const msg = err instanceof Error ? err.message : String(err);
163
+ if (msg.startsWith("path_violation")) {
164
+ logger.warn `Workflow-run pack rejected for ${deploymentId}: ${msg}`;
165
+ return { accepted: false, reason: "path_violation" };
166
+ }
167
+ // Mirror the agent-state branch's catch-all: any other failure
168
+ // from the repo subsystem (filesystem races, kind-handler
169
+ // diagnostics surfaced as Error messages, etc.) becomes a
170
+ // structured `corrupt` rejection so the sender can re-push,
171
+ // and the underlying error is logged so the cause stays
172
+ // traceable on the hub side.
173
+ logger.error `Workflow-run pack receive failed for ${deploymentId}: ${msg}`;
174
+ return { accepted: false, reason: "corrupt" };
175
+ }
176
+ return { accepted: true };
177
+ },
178
+ };
179
+ }
180
+ /**
181
+ * Extract the instance id from an `<instanceId>@<domain>` agent address.
182
+ * Throws on any input the `@intx/types`-owned `parseAgentAddress`
183
+ * rejects: missing or leading `@`, empty domain, or an instance id
184
+ * without the canonical `ins_` prefix.
185
+ */
186
+ export function parseAgentId(agentAddress) {
187
+ const parsed = parseAgentAddress(agentAddress);
188
+ if (parsed === null) {
189
+ throw new Error(`Invalid agent address: "${agentAddress}"`);
190
+ }
191
+ return parsed.instanceId;
192
+ }
193
+ export async function findInstance(db, agentAddress) {
194
+ return db.query.agentInstance.findFirst({
195
+ where: and(eq(agentInstance.address, agentAddress), isNull(agentInstance.endedAt)),
196
+ });
197
+ }
198
+ export async function requireInstance(db, agentAddress) {
199
+ const row = await findInstance(db, agentAddress);
200
+ if (!row) {
201
+ throw new Error(`No active instance found for address "${agentAddress}"`);
202
+ }
203
+ return row;
204
+ }
@@ -0,0 +1,25 @@
1
+ import type { DB } from "@intx/db";
2
+ import type { AgentRepoStore } from "./agent-repo.js";
3
+ import type { EventCollectorRegistry } from "./event-collector-registry.js";
4
+ import type { SidecarEventEmitter } from "./ws/sidecar-events.js";
5
+ /** Subset of `SidecarRouter` the orchestrator drives outbound. The
6
+ * narrow surface keeps tests honest and decouples the orchestrator
7
+ * from the rest of the router API. */
8
+ export type HubSessionRouterFacade = {
9
+ sendPack(agentAddress: string, pack: Uint8Array, ref: string, commitSha: string): Promise<void>;
10
+ dispatchAgentEvent(agentAddress: string, event: unknown): void;
11
+ };
12
+ export type HubSessionOrchestratorDeps = {
13
+ events: SidecarEventEmitter;
14
+ router: HubSessionRouterFacade;
15
+ db: DB["db"];
16
+ eventCollectors: EventCollectorRegistry;
17
+ agentRepoStore: AgentRepoStore;
18
+ };
19
+ export type HubSessionOrchestrator = {
20
+ /** Unsubscribe all listeners. Tests use this between cases; the hub
21
+ * application doesn't need to dispose because the orchestrator's
22
+ * lifetime matches the process. */
23
+ dispose(): void;
24
+ };
25
+ export declare function createHubSessionOrchestrator(deps: HubSessionOrchestratorDeps): HubSessionOrchestrator;
@@ -0,0 +1,122 @@
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
+ // restoring the event collector on reconnect, re-deploying stale
6
+ // agents, and forwarding mail.delivered notifications back to
7
+ // 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
+ import { eq } from "drizzle-orm";
13
+ import { type } from "arktype";
14
+ import { agentInstance, workflowDeployment } from "@intx/db/schema";
15
+ import { parseMailToEmail } from "@intx/mime";
16
+ import { parseInferenceEvent } from "@intx/types/runtime";
17
+ import { getLogger } from "@intx/log";
18
+ import { isWorkflowDerivedAddress } from "@intx/workflow-deploy";
19
+ import { findInstance, parseAgentId, requireInstance, } from "./hub-session-lookups.js";
20
+ const log = getLogger(["hub", "orchestrator"]);
21
+ export function createHubSessionOrchestrator(deps) {
22
+ const { events, router, db, eventCollectors, agentRepoStore } = deps;
23
+ const unsubscribers = [];
24
+ unsubscribers.push(events.on("agent.event", ({ agentAddress, event }) => {
25
+ const validated = parseInferenceEvent(event);
26
+ if (validated instanceof type.errors) {
27
+ log.warn("Received invalid agent event for {agentAddress}: {summary}", {
28
+ agentAddress,
29
+ summary: validated.summary,
30
+ });
31
+ return;
32
+ }
33
+ eventCollectors.dispatch(agentAddress, validated);
34
+ }));
35
+ unsubscribers.push(events.on("sidecar.disconnect", ({ ownedAddresses }) => {
36
+ for (const addr of ownedAddresses) {
37
+ eventCollectors.abandon(addr);
38
+ }
39
+ }));
40
+ unsubscribers.push(events.on("mail.outbound.undelivered", ({ recipients }) => {
41
+ // The hub has no external mail transport today. Anything that
42
+ // could not be delivered locally or queued for a disconnected
43
+ // agent is dropped; log so operators can see it.
44
+ log.warn("Dropping mail with no local recipient: {recipients}", {
45
+ recipients: recipients.join(", "),
46
+ });
47
+ }));
48
+ unsubscribers.push(events.on("agent.deploy.ack", async ({ agentAddress, publicKey }) => {
49
+ // Workflow-derived addresses (the deployment-level
50
+ // `ins_<deploymentId>@<domain>` and the per-step
51
+ // `ins_<deploymentId>-<stepId>@<domain>`) have no agent_instance row;
52
+ // their public key lives on the workflow_deployment projection row,
53
+ // keyed by address. Persist it there so the reconnect ownership
54
+ // challenge can verify the deployment address. Only the
55
+ // deployment-level address has a row, so a stray per-step ack updates
56
+ // nothing. (This was previously a no-op, which is what left
57
+ // workflow-deployment addresses un-verifiable on reconnect.)
58
+ if (isWorkflowDerivedAddress(agentAddress)) {
59
+ await db
60
+ .update(workflowDeployment)
61
+ .set({ publicKey })
62
+ .where(eq(workflowDeployment.address, agentAddress));
63
+ return;
64
+ }
65
+ // A launched agent has an agent_instance row; a missing one is a bug
66
+ // to surface, not to drop silently.
67
+ const instance = await findInstance(db, agentAddress);
68
+ if (instance === undefined) {
69
+ throw new Error(`No active instance found for deploy ack on address "${agentAddress}"`);
70
+ }
71
+ await db
72
+ .update(agentInstance)
73
+ .set({ publicKey })
74
+ .where(eq(agentInstance.id, instance.id));
75
+ }));
76
+ unsubscribers.push(events.on("agent.reconnected", async ({ agentAddress }) => {
77
+ const instance = await requireInstance(db, agentAddress);
78
+ if (!instance.sessionId) {
79
+ throw new Error(`Agent "${agentAddress}" reconnected but has no active session`);
80
+ }
81
+ const sessionId = instance.sessionId;
82
+ // A supervised deployment carries its grants and sources in the
83
+ // deploy pack and refreshes them over the supervisor's IPC
84
+ // credentials snapshot at spawn and recycle, so reconnect does not
85
+ // re-push them over the wire.
86
+ const now = new Date();
87
+ if (instance.status !== "running") {
88
+ await db
89
+ .update(agentInstance)
90
+ .set({ status: "running", updatedAt: now })
91
+ .where(eq(agentInstance.id, instance.id));
92
+ }
93
+ if (!eventCollectors.has(agentAddress)) {
94
+ eventCollectors.create(agentAddress, instance.tenantId, sessionId, instance.id);
95
+ log.info("Restored event collector for reconnected agent {agentAddress}", { agentAddress });
96
+ }
97
+ }));
98
+ unsubscribers.push(events.on("deploy.ref.stale", async ({ agentAddress }) => {
99
+ const agentId = parseAgentId(agentAddress);
100
+ const { pack, commitSha, ref } = await agentRepoStore.createDeployPack(agentId);
101
+ await router.sendPack(agentAddress, pack, ref, commitSha);
102
+ log.info("Re-deployed stale agent {agentAddress}", { agentAddress });
103
+ }));
104
+ unsubscribers.push(events.on("mail.persisted", (row) => {
105
+ const parsed = parseMailToEmail(row.raw, row.id);
106
+ router.dispatchAgentEvent(row.address, {
107
+ type: "mail.delivered",
108
+ data: {
109
+ ...parsed,
110
+ id: row.id,
111
+ direction: row.direction,
112
+ receivedAt: row.createdAt.toISOString(),
113
+ },
114
+ });
115
+ }));
116
+ return {
117
+ dispose() {
118
+ for (const off of unsubscribers)
119
+ off();
120
+ },
121
+ };
122
+ }
@@ -0,0 +1,18 @@
1
+ export { createAgentRepoStore, type AgentRepoStore, type DeployContent, } from "./agent-repo.js";
2
+ export { createSessionService, SessionLaunchError, bridgeOrchestratorDeployContent, type SessionService, type DeployWorkflowDefinitionParams, type DeployWorkflowDefinitionResult, } from "./session-service.js";
3
+ export type { WorkflowDefinition } from "@intx/workflow/definition";
4
+ export { createEventCollectorRegistry, type EventCollectorRegistry, } from "./event-collector-registry.js";
5
+ export { createSidecarRouter, type SidecarRouter, type SidecarRouterConfig, type SidecarAuthIdentity, type SidecarAuthenticator, createSidecarTokenAuthenticator, type CreateSidecarTokenAuthenticatorDeps, type WsHandle, createSidecarEmitter, type SidecarEventEmitter, type SidecarEventMap, type SidecarEventType, type SidecarEventListener, type SidecarLookups, type SidecarMailPersistedPayload, type SidecarMailPersistedRow, } from "./ws/index.js";
6
+ export { createHubSessionLookups, parseAgentId, type HubSessionLookupsDeps, } from "./hub-session-lookups.js";
7
+ export { createHubSessionOrchestrator, type HubSessionOrchestrator, type HubSessionOrchestratorDeps, type HubSessionRouterFacade, } from "./hub-session-orchestrator.js";
8
+ export { pushSourceUpdates, pushSourceUpdatesSubtree } from "./credential-push.js";
9
+ export { skillKindHandler, skillAuthorize, skillFrontmatterSchema, getSkillIndex, type SkillIndexEntry, type SkillFrontmatter, type SkillPrincipal, type SkillHubPrincipal, type SkillSidecarPrincipal, } from "./skill-kind.js";
10
+ export { packageRegistryKindHandler, packageRegistryAuthorize, asTarballEntry, validateTarballPackageJSON, TARBALLS_PREFIX, TARBALL_FILENAME_PATTERN, REGISTRY_INDEX_PATH, WORKSPACE_BUILTINS_REGISTRY, } from "./package-registry-kind.js";
11
+ export { workflowKindHandler, workflowAuthorize, workflowDefinitionEnvelopeSchema, WORKFLOW_JSON_PATH, CAPABILITY_DECLARATIONS_JSON_PATH, WORKFLOW_GITIGNORE_PATH, type WorkflowPrincipal, type WorkflowHubPrincipal, type WorkflowSidecarPrincipal, } from "./workflow-kind.js";
12
+ export { workflowRunKindHandler, workflowRunAuthorize, enqueueInbox, dequeueToProcessing, readProcessingEntry, markConsumed, readOwnedMessageIds, replayProcessingToInbox, WORKFLOW_RUN_GITIGNORE_PATH, WORKFLOW_RUN_RUNS_PREFIX, WORKFLOW_RUN_EVENTS_DIR, WORKFLOW_RUN_AGENT_STATE_PREFIX, WORKFLOW_RUN_ADDRESSES_PREFIX, WORKFLOW_RUN_CONTROL_PREFIX, WORKFLOW_RUN_INBOX_DIR, WORKFLOW_RUN_PROCESSING_DIR, WORKFLOW_RUN_CONSUMED_DIR, WORKFLOW_RUN_WATERMARK_FILE, DEFAULT_CONSUMED_RETENTION_MS, type ClaimCheckEnvelope, type ConsumedEnvelope, type EnqueueInboxArgs, type EnqueueInboxResult, type DequeueToProcessingResult, type ReadProcessingEntryResult, type MarkConsumedArgs, type MarkConsumedResult, type ReplayProcessingToInboxOpts, type ReplayProcessingToInboxResult, type WorkflowRunPrincipal, type WorkflowRunHubPrincipal, type WorkflowRunSidecarPrincipal, type WorkflowRunWorkflowProcessPrincipal, type WorkflowRunSupervisorPrincipal, } from "./workflow-run-kind.js";
13
+ export { createAssetService, AssetServiceError, DEFAULT_ASSET_REF, type AssetService, type Asset, type AgentAsset, type AgentAssetWithAsset, type AccessMode, type CreateAssetParams, type PopulateAssetParams, type AttachAssetParams, type AssetServiceErrorReason, type ReadAssetBlobParams, type ListAssetBlobsParams, } from "./asset-service.js";
14
+ export { buildAvailableSkillsStanza, type AvailableSkillEntry, } from "./available-skills-stanza.js";
15
+ export { createWorkflowRunReader, type WorkflowRunReader, type WorkflowRunEvent, } from "./workflow-run-reader.js";
16
+ export { WORKFLOW_RUN_EVENTS_FILE, splitCombinedEventLog, encodeCombinedEventLog, } from "./workflow-run-event-log.js";
17
+ export type { AuthorizeFn, CreateRepoStoreConfig, InitRepoOpts, KindHandler, NewlyTerminalRun, Principal, RefEntry, RepoAction, RepoId, RepoStore, SubscribeKindEntry, SubscribeKindOpts, ValidatePushResult, WriteResult, } from "./repo-store/index.js";
18
+ export { createRepoStore, subscribeKind, UserPrincipal } from "./repo-store/index.js";
package/dist/index.js ADDED
@@ -0,0 +1,16 @@
1
+ export { createAgentRepoStore, } from "./agent-repo.js";
2
+ export { createSessionService, SessionLaunchError, bridgeOrchestratorDeployContent, } from "./session-service.js";
3
+ export { createEventCollectorRegistry, } from "./event-collector-registry.js";
4
+ export { createSidecarRouter, createSidecarTokenAuthenticator, createSidecarEmitter, } from "./ws/index.js";
5
+ export { createHubSessionLookups, parseAgentId, } from "./hub-session-lookups.js";
6
+ export { createHubSessionOrchestrator, } from "./hub-session-orchestrator.js";
7
+ export { pushSourceUpdates, pushSourceUpdatesSubtree } from "./credential-push.js";
8
+ export { skillKindHandler, skillAuthorize, skillFrontmatterSchema, getSkillIndex, } from "./skill-kind.js";
9
+ export { packageRegistryKindHandler, packageRegistryAuthorize, asTarballEntry, validateTarballPackageJSON, TARBALLS_PREFIX, TARBALL_FILENAME_PATTERN, REGISTRY_INDEX_PATH, WORKSPACE_BUILTINS_REGISTRY, } from "./package-registry-kind.js";
10
+ export { workflowKindHandler, workflowAuthorize, workflowDefinitionEnvelopeSchema, WORKFLOW_JSON_PATH, CAPABILITY_DECLARATIONS_JSON_PATH, WORKFLOW_GITIGNORE_PATH, } from "./workflow-kind.js";
11
+ export { workflowRunKindHandler, workflowRunAuthorize, enqueueInbox, dequeueToProcessing, readProcessingEntry, markConsumed, readOwnedMessageIds, replayProcessingToInbox, WORKFLOW_RUN_GITIGNORE_PATH, WORKFLOW_RUN_RUNS_PREFIX, WORKFLOW_RUN_EVENTS_DIR, WORKFLOW_RUN_AGENT_STATE_PREFIX, WORKFLOW_RUN_ADDRESSES_PREFIX, WORKFLOW_RUN_CONTROL_PREFIX, WORKFLOW_RUN_INBOX_DIR, WORKFLOW_RUN_PROCESSING_DIR, WORKFLOW_RUN_CONSUMED_DIR, WORKFLOW_RUN_WATERMARK_FILE, DEFAULT_CONSUMED_RETENTION_MS, } from "./workflow-run-kind.js";
12
+ export { createAssetService, AssetServiceError, DEFAULT_ASSET_REF, } from "./asset-service.js";
13
+ export { buildAvailableSkillsStanza, } from "./available-skills-stanza.js";
14
+ export { createWorkflowRunReader, } from "./workflow-run-reader.js";
15
+ export { WORKFLOW_RUN_EVENTS_FILE, splitCombinedEventLog, encodeCombinedEventLog, } from "./workflow-run-event-log.js";
16
+ export { createRepoStore, subscribeKind, UserPrincipal } from "./repo-store/index.js";
@@ -0,0 +1,70 @@
1
+ import type { PackageJSON } from "@intx/types/package-json";
2
+ import { type AuthorizeFn, type KindHandler } from "./repo-store/index.js";
3
+ export declare const TARBALLS_PREFIX = "tarballs/";
4
+ export declare const REGISTRY_INDEX_PATH = "package-registry.json";
5
+ /**
6
+ * Canonical asset name for the workspace's bundled package-registry —
7
+ * the in-tree `@intx/tools-*` packages live in an asset of this name
8
+ * under the workspace's root tenant. The hub's scope-routing config
9
+ * maps `@intx` to this registry, the seed script ensures the asset
10
+ * row exists, and the publish-tool-packages CLI defaults its target
11
+ * registry to this name. The constant lives at one site so a rename
12
+ * does not have to chase three independent string literals.
13
+ *
14
+ * Callers:
15
+ * - `bin/dev.ts` — orchestrator default for the registry the dev
16
+ * stack publishes the built-ins into.
17
+ * - `bin/seed.ts` — seeder that pins the workspace-builtins into
18
+ * the registry asset at boot.
19
+ * - `bin/publish-tool-packages.ts` — CLI default for the
20
+ * `--registry` flag.
21
+ *
22
+ * No test asserts that the seed's pinned built-ins actually land
23
+ * under this exact name; a mismatch between the constant and a
24
+ * caller would surface at apply time as a `tarball.missing`
25
+ * structured failure, not as a build error.
26
+ */
27
+ export declare const WORKSPACE_BUILTINS_REGISTRY = "workspace-builtins";
28
+ /**
29
+ * Filename rule for tarballs in the repo tree. Filenames must end in
30
+ * `.tgz`, start with an alphanumeric / underscore / scope-marker
31
+ * character, and otherwise contain only filename-safe characters. The
32
+ * leading-character constraint forbids hidden-style names like
33
+ * `..tgz` or `.hidden.tgz` that the filesystem treats as dotfiles —
34
+ * those would be invisible to a `readdir` shell expansion and split
35
+ * the resolver's view of the registry tree from the operator's. The
36
+ * same rule is enforced at the REST upload boundary so a push and a
37
+ * PUT cannot produce diverging contents.
38
+ */
39
+ export declare const TARBALL_FILENAME_PATTERN: RegExp;
40
+ /**
41
+ * Validates that `path` belongs to a tarball entry shape
42
+ * `tarballs/<filename>.tgz`. Returns the bare filename when valid,
43
+ * `null` otherwise.
44
+ */
45
+ export declare function asTarballEntry(path: string): string | null;
46
+ type TarballValidationOutcome = {
47
+ ok: true;
48
+ pkg: PackageJSON;
49
+ } | {
50
+ ok: false;
51
+ reason: string;
52
+ };
53
+ /**
54
+ * Open an npm-style tarball, find the top-level `package.json` entry,
55
+ * parse and validate it. Returns the typed descriptor on success; a
56
+ * structured reason otherwise. The shape validation lives inside
57
+ * `extractTarballPackageJSON`; this wrapper only translates the
58
+ * outcome into the substrate's `ValidatePushResult`-shaped reason
59
+ * strings.
60
+ */
61
+ export declare function validateTarballPackageJSON(filename: string, bytes: Uint8Array): Promise<TarballValidationOutcome>;
62
+ export declare const packageRegistryKindHandler: KindHandler;
63
+ /**
64
+ * Authorize policy for package-registry repos. Sidecars never write
65
+ * to package-registry repos (they consume contents through the
66
+ * in-process read API, not the smart-HTTP layer); only the hub and
67
+ * authenticated users with the right grant may push.
68
+ */
69
+ export declare const packageRegistryAuthorize: AuthorizeFn;
70
+ export {};