@intx/hub-sessions 0.1.2 → 0.3.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 (113) hide show
  1. package/LICENSE +176 -0
  2. package/README.md +82 -1
  3. package/dist/agent-repo.d.ts +93 -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 +189 -0
  7. package/dist/asset-service.d.ts +104 -0
  8. package/dist/asset-service.js +267 -0
  9. package/dist/committed-source-tree.d.ts +10 -0
  10. package/dist/committed-source-tree.js +35 -0
  11. package/dist/credential-push.d.ts +33 -0
  12. package/dist/credential-push.js +109 -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 +365 -0
  17. package/dist/hub-session-lookups.d.ts +135 -0
  18. package/dist/hub-session-lookups.js +663 -0
  19. package/dist/hub-session-orchestrator.d.ts +25 -0
  20. package/dist/hub-session-orchestrator.js +87 -0
  21. package/dist/index.d.ts +27 -0
  22. package/dist/index.js +24 -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 +1829 -0
  29. package/dist/repo-store/subscribe-kind.d.ts +56 -0
  30. package/dist/repo-store/subscribe-kind.js +144 -0
  31. package/dist/repo-store/types.d.ts +571 -0
  32. package/dist/repo-store/types.js +42 -0
  33. package/dist/session-service.d.ts +416 -0
  34. package/dist/session-service.js +1191 -0
  35. package/dist/sidecar-allocation/contracts.d.ts +78 -0
  36. package/dist/sidecar-allocation/contracts.js +21 -0
  37. package/dist/sidecar-allocation/index.d.ts +4 -0
  38. package/dist/sidecar-allocation/index.js +3 -0
  39. package/dist/sidecar-allocation/placement-policy.d.ts +11 -0
  40. package/dist/sidecar-allocation/placement-policy.js +21 -0
  41. package/dist/sidecar-allocation/plugin-registry.d.ts +11 -0
  42. package/dist/sidecar-allocation/plugin-registry.js +37 -0
  43. package/dist/sidecar-allocation/reconciler.d.ts +42 -0
  44. package/dist/sidecar-allocation/reconciler.js +431 -0
  45. package/dist/skill-kind.d.ts +41 -0
  46. package/dist/skill-kind.js +292 -0
  47. package/dist/substrate.d.ts +8 -0
  48. package/dist/substrate.js +21 -0
  49. package/dist/workflow-allocation-service.d.ts +58 -0
  50. package/dist/workflow-allocation-service.js +239 -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 +40 -0
  56. package/dist/workflow-dispatch-service.js +146 -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 +37 -0
  60. package/dist/workflow-kind.js +310 -0
  61. package/dist/workflow-probe-gate.d.ts +214 -0
  62. package/dist/workflow-probe-gate.js +207 -0
  63. package/dist/workflow-run-event-log.d.ts +21 -0
  64. package/dist/workflow-run-event-log.js +51 -0
  65. package/dist/workflow-run-kind.d.ts +440 -0
  66. package/dist/workflow-run-kind.js +2916 -0
  67. package/dist/workflow-run-reader.d.ts +47 -0
  68. package/dist/workflow-run-reader.js +153 -0
  69. package/dist/workflow-run-restore.d.ts +15 -0
  70. package/dist/workflow-run-restore.js +26 -0
  71. package/dist/workflow-source-closure.d.ts +35 -0
  72. package/dist/workflow-source-closure.js +342 -0
  73. package/dist/ws/index.d.ts +3 -0
  74. package/dist/ws/index.js +3 -0
  75. package/dist/ws/sidecar-events.d.ts +222 -0
  76. package/dist/ws/sidecar-events.js +72 -0
  77. package/dist/ws/sidecar-handler.d.ts +305 -0
  78. package/dist/ws/sidecar-handler.js +2537 -0
  79. package/dist/ws/sidecar-token-authenticator.d.ts +17 -0
  80. package/dist/ws/sidecar-token-authenticator.js +81 -0
  81. package/package.json +35 -12
  82. package/src/agent-repo.test.ts +0 -310
  83. package/src/agent-repo.ts +0 -165
  84. package/src/agent-state-kind.test.ts +0 -247
  85. package/src/agent-state-kind.ts +0 -204
  86. package/src/asset-service.test.ts +0 -540
  87. package/src/asset-service.ts +0 -378
  88. package/src/available-skills-stanza.test.ts +0 -87
  89. package/src/available-skills-stanza.ts +0 -47
  90. package/src/credential-push.ts +0 -65
  91. package/src/event-collector-registry.test.ts +0 -73
  92. package/src/event-collector-registry.ts +0 -171
  93. package/src/event-collector.test.ts +0 -1387
  94. package/src/event-collector.ts +0 -424
  95. package/src/hub-session-lookups.ts +0 -206
  96. package/src/hub-session-orchestrator.test.ts +0 -510
  97. package/src/hub-session-orchestrator.ts +0 -213
  98. package/src/index.ts +0 -78
  99. package/src/repo-store/index.ts +0 -15
  100. package/src/repo-store/store.test.ts +0 -1169
  101. package/src/repo-store/store.ts +0 -428
  102. package/src/repo-store/types.ts +0 -253
  103. package/src/session-service.test.ts +0 -895
  104. package/src/session-service.ts +0 -464
  105. package/src/skill-kind.test.ts +0 -599
  106. package/src/skill-kind.ts +0 -350
  107. package/src/ws/index.ts +0 -18
  108. package/src/ws/sidecar-events.test.ts +0 -96
  109. package/src/ws/sidecar-events.ts +0 -231
  110. package/src/ws/sidecar-handler.test.ts +0 -2217
  111. package/src/ws/sidecar-handler.ts +0 -1574
  112. package/tsconfig.json +0 -4
  113. package/tsconfig.tsbuildinfo +0 -1
@@ -0,0 +1,56 @@
1
+ import { type Type } from "arktype";
2
+ import type { Principal, RepoId, RepoStore } from "./types.js";
3
+ export type SubscribeKindOpts = {
4
+ signal: AbortSignal;
5
+ from: "head" | {
6
+ seq: number;
7
+ };
8
+ /**
9
+ * Workflow-event kinds to surface. Matches against the inner
10
+ * payload's `type` field after the validator narrows the blob. The
11
+ * helper yields only events whose `type` appears in this list.
12
+ */
13
+ kinds: readonly string[];
14
+ bufferLimit?: number;
15
+ };
16
+ export type SubscribeKindEntry<T> = {
17
+ /**
18
+ * Workflow-event seq parsed from the committed filename
19
+ * (`runs/<runId>/events/<seq>.json`). Distinct from the substrate's
20
+ * commit-level seq exposed by `RepoStore.subscribe`.
21
+ */
22
+ seq: number;
23
+ /**
24
+ * Owning runId, parsed from the committed blob's path. The substrate
25
+ * stores each run's event log under `runs/<runId>/events/`; the helper
26
+ * surfaces the path segment so consumers can attribute each yielded
27
+ * event to its run without re-walking the tree. Required by the
28
+ * workflow-host scheduler's live-ingest path, which routes incoming
29
+ * `TimerSet` events to per-run queue entries.
30
+ */
31
+ runId: string;
32
+ event: T;
33
+ };
34
+ /**
35
+ * Typed entrypoint over `RepoStore.subscribe` for the workflow-run
36
+ * event log. The substrate emits one ref-update envelope per commit;
37
+ * each commit may add one or more `runs/<runId>/events/<seq>.json`
38
+ * blobs. This helper loads those blobs from the new commit's tree,
39
+ * narrows each through the supplied arktype validator, applies the
40
+ * kinds filter against the inner `type` discriminator, and yields one
41
+ * `{ seq, event }` entry per matching blob.
42
+ *
43
+ * The path-layout vocabulary (the `runs/`/`events/` prefixes and the
44
+ * `<seq>.json` filename shape) lives in the workflow-run kind handler,
45
+ * which is the authority for what may land under this prefix; this
46
+ * helper imports it rather than re-encoding it. The substrate
47
+ * `subscribe` it wraps is a generic ref-tail primitive and knows
48
+ * nothing about workflow-runs.
49
+ *
50
+ * Diff scope: the helper enumerates event blobs present in the new
51
+ * commit but absent from the old commit. A commit that does not add
52
+ * any event blobs (e.g. a kind-handler-internal rewrite) produces no
53
+ * entries even if the kinds filter would otherwise match earlier
54
+ * events.
55
+ */
56
+ export declare function subscribeKind<V extends Type>(store: RepoStore, principal: Principal, repoId: RepoId, ref: string, validator: V, opts: SubscribeKindOpts): AsyncGenerator<SubscribeKindEntry<V["infer"]>, void, void>;
@@ -0,0 +1,144 @@
1
+ import { type } from "arktype";
2
+ import { requireEventSeq, WORKFLOW_RUN_EVENTS_DIR, WORKFLOW_RUN_RUNS_PREFIX, } from "../workflow-run-kind.js";
3
+ /**
4
+ * Substrate envelope shape. Imported textually rather than from
5
+ * `types.ts` so this helper has a local, validator-checked view of
6
+ * what `RepoStore.subscribe` yields and does not depend on the
7
+ * substrate's TypeScript type for runtime safety.
8
+ */
9
+ const SubstrateEvent = type({
10
+ type: "'ref.updated'",
11
+ ref: "string",
12
+ "oldSha?": "string | null",
13
+ newSha: "string",
14
+ });
15
+ const KindEnvelope = type({
16
+ type: "string",
17
+ });
18
+ /**
19
+ * Typed entrypoint over `RepoStore.subscribe` for the workflow-run
20
+ * event log. The substrate emits one ref-update envelope per commit;
21
+ * each commit may add one or more `runs/<runId>/events/<seq>.json`
22
+ * blobs. This helper loads those blobs from the new commit's tree,
23
+ * narrows each through the supplied arktype validator, applies the
24
+ * kinds filter against the inner `type` discriminator, and yields one
25
+ * `{ seq, event }` entry per matching blob.
26
+ *
27
+ * The path-layout vocabulary (the `runs/`/`events/` prefixes and the
28
+ * `<seq>.json` filename shape) lives in the workflow-run kind handler,
29
+ * which is the authority for what may land under this prefix; this
30
+ * helper imports it rather than re-encoding it. The substrate
31
+ * `subscribe` it wraps is a generic ref-tail primitive and knows
32
+ * nothing about workflow-runs.
33
+ *
34
+ * Diff scope: the helper enumerates event blobs present in the new
35
+ * commit but absent from the old commit. A commit that does not add
36
+ * any event blobs (e.g. a kind-handler-internal rewrite) produces no
37
+ * entries even if the kinds filter would otherwise match earlier
38
+ * events.
39
+ */
40
+ export async function* subscribeKind(store, principal, repoId, ref, validator, opts) {
41
+ const kindsAllowed = new Set(opts.kinds);
42
+ const subscribeOpts = {
43
+ signal: opts.signal,
44
+ from: opts.from,
45
+ };
46
+ if (opts.bufferLimit !== undefined) {
47
+ subscribeOpts.bufferLimit = opts.bufferLimit;
48
+ }
49
+ const iter = store.subscribe(principal, repoId, ref, subscribeOpts);
50
+ for await (const { event } of iter) {
51
+ const envelope = SubstrateEvent(event);
52
+ if (envelope instanceof type.errors) {
53
+ throw new Error(`subscribe_kind_envelope_invalid: ${envelope.summary}`);
54
+ }
55
+ const newReads = await store.openCommittedReadsAtCommit(principal, repoId, envelope.newSha);
56
+ // A commit a concurrent GC pruned between the ref-update event and
57
+ // this read yields nothing; the substrate surfaces that as `null`.
58
+ if (newReads === null)
59
+ continue;
60
+ const oldReads = envelope.oldSha === undefined || envelope.oldSha === null
61
+ ? null
62
+ : await store.openCommittedReadsAtCommit(principal, repoId, envelope.oldSha);
63
+ const candidates = await collectAddedEventBlobs(newReads, oldReads);
64
+ for (const candidate of candidates) {
65
+ const raw = await newReads.readBlobByOid(candidate.oid);
66
+ let parsedJson;
67
+ try {
68
+ parsedJson = JSON.parse(new TextDecoder().decode(raw));
69
+ }
70
+ catch (cause) {
71
+ throw new Error(`subscribe_kind_invalid_json: ${candidate.blobPath}`, {
72
+ cause,
73
+ });
74
+ }
75
+ const kind = KindEnvelope(parsedJson);
76
+ if (kind instanceof type.errors) {
77
+ throw new Error(`subscribe_kind_missing_type: ${candidate.blobPath}: ${kind.summary}`);
78
+ }
79
+ if (!kindsAllowed.has(kind.type))
80
+ continue;
81
+ const narrowed = validator(parsedJson);
82
+ if (narrowed instanceof type.errors) {
83
+ throw new Error(`subscribe_kind_validation_failed: ${candidate.blobPath}: ${narrowed.summary}`);
84
+ }
85
+ yield { seq: candidate.seq, runId: candidate.runId, event: narrowed };
86
+ }
87
+ }
88
+ }
89
+ /**
90
+ * Diff the `runs/<runId>/events/` subtree between the new and old commit
91
+ * reads and return the event candidates present in the new commit but
92
+ * not the old. `oldReads` is `null` for the ref's first commit (no prior
93
+ * tip) or when the prior commit is no longer in the object store, in
94
+ * which case every event in the new commit is treated as added.
95
+ * Filenames that fail the `<seq>.json` shape are surfaced as errors
96
+ * rather than silently skipped — the workflow-run kind handler's
97
+ * validatePush is the authority for what may land under this prefix, so
98
+ * an unexpected shape here is a substrate-side invariant violation.
99
+ */
100
+ async function collectAddedEventBlobs(newReads, oldReads) {
101
+ const newSet = await enumerateEventBlobs(newReads);
102
+ if (oldReads === null) {
103
+ return [...newSet.values()].sort(byRunThenSeq);
104
+ }
105
+ const oldSet = await enumerateEventBlobs(oldReads);
106
+ const out = [];
107
+ for (const [key, candidate] of newSet) {
108
+ if (oldSet.has(key))
109
+ continue;
110
+ out.push(candidate);
111
+ }
112
+ out.sort(byRunThenSeq);
113
+ return out;
114
+ }
115
+ function byRunThenSeq(a, b) {
116
+ if (a.runId < b.runId)
117
+ return -1;
118
+ if (a.runId > b.runId)
119
+ return 1;
120
+ return a.seq - b.seq;
121
+ }
122
+ async function enumerateEventBlobs(reads) {
123
+ const out = new Map();
124
+ const runs = await reads.listDir(WORKFLOW_RUN_RUNS_PREFIX);
125
+ for (const runEntry of runs) {
126
+ if (runEntry.type !== "tree")
127
+ continue;
128
+ const runId = runEntry.name;
129
+ const events = await reads.listDir(`${WORKFLOW_RUN_RUNS_PREFIX}/${runId}/${WORKFLOW_RUN_EVENTS_DIR}`);
130
+ for (const blob of events) {
131
+ if (blob.type !== "blob")
132
+ continue;
133
+ const blobPath = `${WORKFLOW_RUN_RUNS_PREFIX}/${runId}/${WORKFLOW_RUN_EVENTS_DIR}/${blob.name}`;
134
+ const seq = requireEventSeq(blob.name, blobPath);
135
+ out.set(`${runId}/${blob.name}`, {
136
+ seq,
137
+ runId,
138
+ blobPath,
139
+ oid: blob.oid,
140
+ });
141
+ }
142
+ }
143
+ return out;
144
+ }