@swirls/looms 0.3.0 → 0.5.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 (253) hide show
  1. package/CHANGELOG.md +64 -0
  2. package/dist/actor/cell.d.ts +21 -2
  3. package/dist/actor/cell.js +15 -3
  4. package/dist/actor/host.d.ts +10 -2
  5. package/dist/actor/host.js +27 -4
  6. package/dist/actor/index.d.ts +2 -1
  7. package/dist/actor/index.js +1 -1
  8. package/dist/actor/routing.d.ts +3 -0
  9. package/dist/actor/routing.js +13 -2
  10. package/dist/agent/debugger/agent-chat.js +3 -30
  11. package/dist/agent/debugger/streaming-text.d.ts +6 -0
  12. package/dist/agent/debugger/streaming-text.js +33 -0
  13. package/dist/agent/definitions-store.d.ts +1 -1
  14. package/dist/agent/definitions-store.js +1 -1
  15. package/dist/agent/definitions.d.ts +48 -0
  16. package/dist/agent/definitions.js +44 -0
  17. package/dist/agent/effects.d.ts +184 -0
  18. package/dist/agent/effects.js +172 -40
  19. package/dist/agent/events.d.ts +89 -0
  20. package/dist/agent/events.js +25 -0
  21. package/dist/agent/module.d.ts +819 -407
  22. package/dist/agent/module.js +5 -1
  23. package/dist/agent/scope.d.ts +88 -0
  24. package/dist/agent/threads.js +39 -3
  25. package/dist/agent/types.d.ts +4 -0
  26. package/dist/approval/effects.d.ts +40 -0
  27. package/dist/approval/module.d.ts +80 -0
  28. package/dist/client/client.d.ts +468 -119
  29. package/dist/client/client.js +214 -21
  30. package/dist/client/index.d.ts +1 -1
  31. package/dist/client/sse.d.ts +1 -1
  32. package/dist/client/sse.js +2 -2
  33. package/dist/cloudflare/durable-object.d.ts +66 -2
  34. package/dist/cloudflare/durable-object.js +96 -1
  35. package/dist/cloudflare/event-store.d.ts +7 -3
  36. package/dist/cloudflare/event-store.js +16 -3
  37. package/dist/cloudflare/index.d.ts +7 -1
  38. package/dist/cloudflare/index.js +7 -1
  39. package/dist/cloudflare/memory-queue.d.ts +18 -0
  40. package/dist/cloudflare/memory-queue.js +53 -0
  41. package/dist/cloudflare/queue-consumer.d.ts +52 -0
  42. package/dist/cloudflare/queue-consumer.js +102 -0
  43. package/dist/cloudflare/queue-message.d.ts +31 -0
  44. package/dist/cloudflare/queue-message.js +33 -0
  45. package/dist/cloudflare/queue-pull.d.ts +62 -0
  46. package/dist/cloudflare/queue-pull.js +130 -0
  47. package/dist/cloudflare/queue-worker.d.ts +39 -0
  48. package/dist/cloudflare/queue-worker.js +62 -0
  49. package/dist/cloudflare/r2-blob-store.d.ts +33 -0
  50. package/dist/cloudflare/r2-blob-store.js +60 -0
  51. package/dist/cloudflare/router.d.ts +4 -1
  52. package/dist/cloudflare/router.js +8 -3
  53. package/dist/cloudflare/websocket.d.ts +27 -0
  54. package/dist/cloudflare/websocket.js +215 -0
  55. package/dist/core/attempts.d.ts +8 -0
  56. package/dist/core/attempts.js +27 -0
  57. package/dist/core/blob-offload.d.ts +21 -0
  58. package/dist/core/blob-offload.js +143 -0
  59. package/dist/core/blob-store.d.ts +45 -0
  60. package/dist/core/blob-store.js +164 -0
  61. package/dist/core/blobs.d.ts +37 -0
  62. package/dist/core/blobs.js +160 -0
  63. package/dist/core/definition-resolver.d.ts +40 -0
  64. package/dist/core/definition-resolver.js +129 -0
  65. package/dist/core/definition-store.d.ts +6 -0
  66. package/dist/core/definition-store.js +37 -1
  67. package/dist/core/effects.d.ts +86 -3
  68. package/dist/core/effects.js +99 -3
  69. package/dist/core/envelope.d.ts +9 -0
  70. package/dist/core/envelope.js +4 -0
  71. package/dist/core/event-codec.js +3 -0
  72. package/dist/core/fold.js +83 -1
  73. package/dist/core/ids.d.ts +2 -0
  74. package/dist/core/ids.js +4 -0
  75. package/dist/core/index.d.ts +10 -0
  76. package/dist/core/index.js +9 -0
  77. package/dist/core/launcher.d.ts +97 -0
  78. package/dist/core/launcher.js +67 -0
  79. package/dist/core/module-scope.d.ts +7 -3
  80. package/dist/core/module-scope.js +3 -0
  81. package/dist/core/module.d.ts +10 -0
  82. package/dist/core/projection.d.ts +5 -4
  83. package/dist/core/projection.js +4 -0
  84. package/dist/core/protocol.d.ts +36 -1
  85. package/dist/core/protocol.js +35 -0
  86. package/dist/core/published.d.ts +2 -0
  87. package/dist/core/published.js +4 -1
  88. package/dist/{react → core}/register.d.ts +9 -8
  89. package/dist/core/replay.d.ts +96 -0
  90. package/dist/core/run-context.d.ts +33 -0
  91. package/dist/core/run-context.js +23 -0
  92. package/dist/core/sqlite-store.js +57 -5
  93. package/dist/core/state.d.ts +60 -0
  94. package/dist/core/state.js +19 -0
  95. package/dist/core/store.d.ts +6 -0
  96. package/dist/core/store.js +7 -0
  97. package/dist/core/subscription.d.ts +97 -0
  98. package/dist/core/subscription.js +224 -0
  99. package/dist/core/thread.d.ts +7 -0
  100. package/dist/core/thread.js +1 -0
  101. package/dist/core/trace.d.ts +21 -0
  102. package/dist/core/trace.js +45 -0
  103. package/dist/core/worker-callback.d.ts +25 -1
  104. package/dist/debugger/app/assets/{index-CgDzWJg7.css → index-B7GdT1UA.css} +1 -1
  105. package/dist/debugger/app/assets/index-C31SnCuN.js +22 -0
  106. package/dist/debugger/app/assets/routes-DPA3O5AF.js +47 -0
  107. package/dist/debugger/app/index.html +2 -2
  108. package/dist/debugger/components/event-inspector.d.ts +3 -1
  109. package/dist/debugger/components/event-inspector.js +25 -4
  110. package/dist/debugger/components/event-stream.d.ts +4 -1
  111. package/dist/debugger/components/event-stream.js +2 -2
  112. package/dist/debugger/components/run-tree.d.ts +5 -2
  113. package/dist/debugger/components/run-tree.js +10 -4
  114. package/dist/debugger/context.d.ts +8 -1
  115. package/dist/debugger/context.js +15 -3
  116. package/dist/debugger/events/protocol-summarize.js +18 -3
  117. package/dist/debugger/index.d.ts +1 -1
  118. package/dist/debugger/index.js +1 -1
  119. package/dist/debugger/shell/debugger-shell.js +1 -1
  120. package/dist/debugger/shell/events-pane.js +4 -3
  121. package/dist/debugger/styles.css +1 -0
  122. package/dist/evaluator/definitions-store.d.ts +3 -4
  123. package/dist/evaluator/definitions-store.js +3 -3
  124. package/dist/evaluator/definitions.d.ts +4 -1
  125. package/dist/evaluator/definitions.js +5 -2
  126. package/dist/evaluator/effects.d.ts +41 -0
  127. package/dist/evaluator/effects.js +6 -2
  128. package/dist/evaluator/module.d.ts +84 -0
  129. package/dist/evaluator/module.js +7 -3
  130. package/dist/evaluator/threads.d.ts +2 -0
  131. package/dist/evaluator/threads.js +4 -0
  132. package/dist/projectors/event-log.d.ts +87 -0
  133. package/dist/projectors/event-log.js +396 -0
  134. package/dist/projectors/index-model.d.ts +12 -0
  135. package/dist/projectors/index-model.js +12 -3
  136. package/dist/projectors/memory.js +7 -0
  137. package/dist/projectors/postgres.d.ts +1 -0
  138. package/dist/projectors/postgres.js +32 -15
  139. package/dist/projectors/schema.d.ts +5 -0
  140. package/dist/projectors/schema.js +26 -1
  141. package/dist/projectors/sqlite.js +47 -19
  142. package/dist/projectors/with-projectors.d.ts +7 -1
  143. package/dist/projectors/with-projectors.js +13 -3
  144. package/dist/react/derived.d.ts +26 -8
  145. package/dist/react/derived.js +23 -26
  146. package/dist/react/index.d.ts +3 -3
  147. package/dist/react/index.js +2 -2
  148. package/dist/react/materialize.js +5 -1
  149. package/dist/react/react.d.ts +16 -9
  150. package/dist/react/react.js +47 -23
  151. package/dist/react/store.d.ts +14 -6
  152. package/dist/react/store.js +104 -12
  153. package/dist/react/tables.d.ts +4 -1
  154. package/dist/runtime/cancellation.d.ts +2 -1
  155. package/dist/runtime/cancellation.js +35 -2
  156. package/dist/runtime/child-run.d.ts +10 -0
  157. package/dist/runtime/child-run.js +58 -0
  158. package/dist/runtime/deadline-transition-planner.js +11 -2
  159. package/dist/runtime/dispatch-effect.d.ts +2 -2
  160. package/dist/runtime/dispatch-effect.js +43 -19
  161. package/dist/runtime/errors.d.ts +14 -1
  162. package/dist/runtime/errors.js +10 -0
  163. package/dist/runtime/filesystem-blob-store.d.ts +6 -0
  164. package/dist/runtime/filesystem-blob-store.js +59 -0
  165. package/dist/runtime/helpers.d.ts +15 -6
  166. package/dist/runtime/helpers.js +46 -6
  167. package/dist/runtime/index.d.ts +4 -2
  168. package/dist/runtime/index.js +3 -1
  169. package/dist/runtime/local-effect-executor.d.ts +11 -2
  170. package/dist/runtime/local-effect-executor.js +80 -4
  171. package/dist/runtime/looms.d.ts +38 -4
  172. package/dist/runtime/looms.js +17 -3
  173. package/dist/runtime/repository.d.ts +5 -4
  174. package/dist/runtime/repository.js +5 -2
  175. package/dist/runtime/retry-policy.d.ts +5 -0
  176. package/dist/runtime/retry-policy.js +10 -2
  177. package/dist/runtime/run-start.d.ts +1 -1
  178. package/dist/runtime/run-start.js +10 -0
  179. package/dist/runtime/runtime.d.ts +2 -2
  180. package/dist/runtime/runtime.js +191 -68
  181. package/dist/runtime/server/auth.d.ts +3 -0
  182. package/dist/runtime/server/fetch-handler.d.ts +2 -2
  183. package/dist/runtime/server/fetch-handler.js +35 -4
  184. package/dist/runtime/server/grant.d.ts +49 -0
  185. package/dist/runtime/server/grant.js +177 -0
  186. package/dist/runtime/server/routes/effects.js +47 -5
  187. package/dist/runtime/server/routes/runs.js +6 -1
  188. package/dist/runtime/server/run-route.d.ts +18 -0
  189. package/dist/runtime/server/run-route.js +26 -0
  190. package/dist/runtime/server.d.ts +3 -1
  191. package/dist/runtime/server.js +3 -1
  192. package/dist/runtime/sse.js +26 -4
  193. package/dist/runtime/subscription.d.ts +8 -0
  194. package/dist/runtime/subscription.js +23 -0
  195. package/dist/runtime/types.d.ts +87 -8
  196. package/dist/runtime/wake-engine.d.ts +4 -2
  197. package/dist/runtime/wake-engine.js +57 -6
  198. package/dist/runtime/worker-callbacks.d.ts +12 -2
  199. package/dist/runtime/worker-callbacks.js +102 -72
  200. package/dist/runtime/worker-effect-dispatch.d.ts +14 -5
  201. package/dist/runtime/worker-effect-dispatch.js +84 -18
  202. package/dist/schedule/debugger/index.d.ts +4 -0
  203. package/dist/schedule/debugger/index.js +11 -0
  204. package/dist/schedule/debugger/schedule-view.d.ts +3 -0
  205. package/dist/schedule/debugger/schedule-view.js +68 -0
  206. package/dist/schedule/debugger/summarize.d.ts +2 -0
  207. package/dist/schedule/debugger/summarize.js +43 -0
  208. package/dist/schedule/definitions-store.d.ts +10 -0
  209. package/dist/schedule/definitions-store.js +8 -0
  210. package/dist/schedule/definitions.d.ts +57 -0
  211. package/dist/schedule/definitions.js +30 -0
  212. package/dist/schedule/effects.d.ts +756 -0
  213. package/dist/schedule/effects.js +244 -0
  214. package/dist/schedule/ensure.d.ts +55 -0
  215. package/dist/schedule/ensure.js +109 -0
  216. package/dist/schedule/events.d.ts +116 -0
  217. package/dist/schedule/events.js +49 -0
  218. package/dist/schedule/index.d.ts +11 -0
  219. package/dist/schedule/index.js +11 -0
  220. package/dist/schedule/module.d.ts +1474 -0
  221. package/dist/schedule/module.js +22 -0
  222. package/dist/schedule/projections.d.ts +55 -0
  223. package/dist/schedule/projections.js +88 -0
  224. package/dist/schedule/scope.d.ts +121 -0
  225. package/dist/schedule/scope.js +7 -0
  226. package/dist/schedule/signals.d.ts +25 -0
  227. package/dist/schedule/signals.js +33 -0
  228. package/dist/schedule/specs.d.ts +59 -0
  229. package/dist/schedule/specs.js +231 -0
  230. package/dist/schedule/threads.d.ts +25 -0
  231. package/dist/schedule/threads.js +259 -0
  232. package/dist/testing/corpus-module.d.ts +34 -0
  233. package/dist/testing/corpus-module.js +87 -0
  234. package/dist/testing/index.d.ts +2 -0
  235. package/dist/testing/index.js +5 -6
  236. package/dist/testing/replay-corpus.d.ts +22 -0
  237. package/dist/testing/replay-corpus.js +50 -0
  238. package/dist/workflow/definitions-store.d.ts +1 -1
  239. package/dist/workflow/definitions-store.js +1 -1
  240. package/dist/workflow/definitions.d.ts +14 -0
  241. package/dist/workflow/effects.d.ts +122 -0
  242. package/dist/workflow/effects.js +16 -6
  243. package/dist/workflow/events.d.ts +42 -0
  244. package/dist/workflow/events.js +4 -0
  245. package/dist/workflow/module.d.ts +345 -32
  246. package/dist/workflow/module.js +7 -3
  247. package/dist/workflow/scope.d.ts +42 -0
  248. package/dist/workflow/threads.d.ts +72 -0
  249. package/dist/workflow/threads.js +106 -38
  250. package/package.json +11 -2
  251. package/dist/debugger/app/assets/index-BevQYa-U.js +0 -22
  252. package/dist/debugger/app/assets/routes-B17Om93i.js +0 -47
  253. /package/dist/{react → core}/register.js +0 -0
@@ -0,0 +1,97 @@
1
+ import { Context, Effect, Schema } from 'effect';
2
+ import type { EventInput } from './envelope';
3
+ import type { RunAttributes, SecretContext } from './run-context';
4
+ import type { TraceContext } from './trace';
5
+ import type { JsonValue, RunStatus } from './types';
6
+ export declare const ChildCloseSchema: Schema.Union<readonly [Schema.Literal<"terminate">, Schema.Literal<"wait">]>;
7
+ export type ChildClose = Schema.Schema.Type<typeof ChildCloseSchema>;
8
+ /** The effect that launched a run, recorded on the launched run's `runtime.run.started`. */
9
+ export declare const RunLaunchSourceSchema: Schema.Struct<{
10
+ readonly runId: Schema.String;
11
+ readonly threadId: Schema.String;
12
+ readonly effectId: Schema.String;
13
+ /** The event in `runId` that requested the launching effect. */
14
+ readonly causationId: Schema.String;
15
+ readonly causationSeq: Schema.Finite;
16
+ }>;
17
+ export type RunLaunchSource = Schema.Schema.Type<typeof RunLaunchSourceSchema>;
18
+ export declare function readRunLaunchSource(value: JsonValue | undefined): RunLaunchSource | null;
19
+ /** Arguments for starting a run without waiting for it to finish. */
20
+ export interface LaunchRunArgs {
21
+ readonly runId?: string;
22
+ readonly kind: string;
23
+ readonly definitionName: string;
24
+ readonly definitionVersion?: string;
25
+ readonly input?: JsonValue;
26
+ readonly threadId?: string;
27
+ readonly idempotencyKey?: string;
28
+ /** Set by the runtime when an effect launches. A value passed by the effect is replaced. */
29
+ readonly launchedBy?: RunLaunchSource;
30
+ /**
31
+ * Groups runs launched from the same root run. The runtime sets it to the launching run's
32
+ * correlation id, or to the launching run's id when that run has none.
33
+ */
34
+ readonly correlationId?: string;
35
+ /**
36
+ * What the launching run does with this child when the launching run closes.
37
+ * `terminate` cancels the child. `wait` lets the child finish cancelling first.
38
+ */
39
+ readonly close?: ChildClose;
40
+ readonly attributes?: RunAttributes;
41
+ readonly secrets?: SecretContext;
42
+ /** Defaults to the launching run's trace context. */
43
+ readonly trace?: TraceContext;
44
+ }
45
+ /** Enough of a run to decide whether a previous fire is still in progress. */
46
+ export interface RunStatusSnapshot {
47
+ readonly status: RunStatus;
48
+ }
49
+ /**
50
+ * Starts runs and reads their status from inside an effect. A single-store host launches into its
51
+ * own runtime. An actor host launches into the cell that owns `runId`.
52
+ */
53
+ export interface RunLauncher {
54
+ readonly launch: (args: LaunchRunArgs) => Effect.Effect<void, Error>;
55
+ readonly status: (runId: string) => Effect.Effect<RunStatusSnapshot | null, Error>;
56
+ /**
57
+ * Append events to a run and wake it. When that run is already waking, the wake coalesces
58
+ * instead of waiting, so a child can notify its parent from inside the parent's wake.
59
+ */
60
+ readonly signal: (runId: string, events: readonly EventInput[], options?: {
61
+ readonly idempotencyKey?: string;
62
+ }) => Effect.Effect<void, Error>;
63
+ readonly cancel: (runId: string) => Effect.Effect<void, Error>;
64
+ }
65
+ declare const RunLauncherTag_base: Context.ServiceClass<RunLauncherTag, "looms/RunLauncher", RunLauncher>;
66
+ export declare class RunLauncherTag extends RunLauncherTag_base {
67
+ }
68
+ declare const RunLauncherError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
69
+ readonly _tag: "RunLauncherError";
70
+ } & Readonly<A>;
71
+ export declare class RunLauncherError extends RunLauncherError_base<{
72
+ readonly message: string;
73
+ readonly cause?: unknown;
74
+ }> {
75
+ }
76
+ export declare function runLauncherError(cause: unknown): RunLauncherError;
77
+ declare const RunLauncherUnavailableError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
78
+ readonly _tag: "RunLauncherUnavailableError";
79
+ } & Readonly<A>;
80
+ export declare class RunLauncherUnavailableError extends RunLauncherUnavailableError_base<{
81
+ readonly message: string;
82
+ }> {
83
+ constructor();
84
+ }
85
+ /** Fails both operations. Actor cells and Durable Objects use this unless a launcher is configured. */
86
+ export declare const unavailableRunLauncher: RunLauncher;
87
+ /** Adapts a per-`runId` RPC or cell lookup into a `RunLauncher`. */
88
+ export declare function createRemoteRunLauncher(target: {
89
+ readonly launch: (runId: string, args: LaunchRunArgs) => Promise<void>;
90
+ readonly status: (runId: string) => Promise<RunStatusSnapshot | null>;
91
+ readonly accept: (runId: string, events: readonly EventInput[], options?: {
92
+ readonly idempotencyKey?: string;
93
+ readonly coalesce?: boolean;
94
+ }) => Promise<void>;
95
+ readonly cancel: (runId: string) => Promise<void>;
96
+ }): RunLauncher;
97
+ export {};
@@ -0,0 +1,67 @@
1
+ import { Context, Data, Effect, Option, Schema } from 'effect';
2
+ export const ChildCloseSchema = Schema.Union([Schema.Literal('terminate'), Schema.Literal('wait')]);
3
+ /** The effect that launched a run, recorded on the launched run's `runtime.run.started`. */
4
+ export const RunLaunchSourceSchema = Schema.Struct({
5
+ runId: Schema.String,
6
+ threadId: Schema.String,
7
+ effectId: Schema.String,
8
+ /** The event in `runId` that requested the launching effect. */
9
+ causationId: Schema.String,
10
+ causationSeq: Schema.Finite,
11
+ });
12
+ const decodeRunLaunchSource = Schema.decodeUnknownOption(RunLaunchSourceSchema);
13
+ export function readRunLaunchSource(value) {
14
+ return value === undefined ? null : Option.getOrNull(decodeRunLaunchSource(value));
15
+ }
16
+ export class RunLauncherTag extends Context.Service()('looms/RunLauncher') {
17
+ }
18
+ export class RunLauncherError extends Data.TaggedError('RunLauncherError') {
19
+ }
20
+ export function runLauncherError(cause) {
21
+ return new RunLauncherError({
22
+ message: cause instanceof Error ? cause.message : String(cause),
23
+ cause,
24
+ });
25
+ }
26
+ export class RunLauncherUnavailableError extends Data.TaggedError('RunLauncherUnavailableError') {
27
+ constructor() {
28
+ super({
29
+ message: 'No RunLauncher is configured. Pass launcher when hosting schedules in an actor cell or Durable Object.',
30
+ });
31
+ this.name = 'RunLauncherUnavailableError';
32
+ }
33
+ }
34
+ /** Fails both operations. Actor cells and Durable Objects use this unless a launcher is configured. */
35
+ export const unavailableRunLauncher = {
36
+ launch: () => Effect.fail(new RunLauncherUnavailableError()),
37
+ status: () => Effect.fail(new RunLauncherUnavailableError()),
38
+ signal: () => Effect.fail(new RunLauncherUnavailableError()),
39
+ cancel: () => Effect.fail(new RunLauncherUnavailableError()),
40
+ };
41
+ /** Adapts a per-`runId` RPC or cell lookup into a `RunLauncher`. */
42
+ export function createRemoteRunLauncher(target) {
43
+ return {
44
+ launch: (args) => {
45
+ const runId = args.runId;
46
+ if (!runId) {
47
+ return Effect.fail(new RunLauncherError({ message: 'RunLauncher.launch requires runId' }));
48
+ }
49
+ return Effect.tryPromise({
50
+ try: () => target.launch(runId, { ...args, runId }),
51
+ catch: runLauncherError,
52
+ });
53
+ },
54
+ status: (runId) => Effect.tryPromise({
55
+ try: () => target.status(runId),
56
+ catch: runLauncherError,
57
+ }),
58
+ signal: (runId, events, options) => Effect.tryPromise({
59
+ try: () => target.accept(runId, events, { ...options, coalesce: true }),
60
+ catch: runLauncherError,
61
+ }),
62
+ cancel: (runId) => Effect.tryPromise({
63
+ try: () => target.cancel(runId),
64
+ catch: runLauncherError,
65
+ }),
66
+ };
67
+ }
@@ -3,7 +3,8 @@ import { type CatalogEntries, type EventCatalog, type EventInputOf, type EventsO
3
3
  import type { EventsOf, ProtocolEvents } from './compose';
4
4
  import { type EffectDefinition, type EffectExecution, type EffectHandlerResult, type EmitEffect, type RetryPolicy, type RuntimeEffect, type ScopedEffectContext } from './effects';
5
5
  import type { EventEnvelope, EventInput } from './envelope';
6
- import { type AnyRuntimeModule, type EffectMiddleware, type RuntimeModule, type DefinitionRef, type RuntimeModuleDependency, type SignalInterruptRule } from './module';
6
+ import type { RunLauncherTag } from './launcher';
7
+ import { type AnyRuntimeModule, type DefinitionHost, type EffectMiddleware, type RuntimeModule, type DefinitionRef, type RuntimeModuleDependency, type SignalInterruptRule } from './module';
7
8
  import { type ProjectionDefinition } from './projection';
8
9
  import type { InferDefinedSchema, InferSchemaOutput, SchemaInput } from './schema';
9
10
  import { type StartContext, type ThreadContext, type ThreadDefinition } from './thread';
@@ -18,9 +19,9 @@ export interface DefineModuleOptions<TNamespace extends string, TEvents extends
18
19
  export type ScopeUniverse<TEvents extends EventCatalog | undefined, TObserves extends readonly EventCatalog[] | undefined> = ProtocolEvents | (TEvents extends EventCatalog ? EventsOfCatalog<TEvents> : never) | (TObserves extends readonly EventCatalog[] ? EventsOfCatalog<TObserves[number]> : never);
19
20
  export type EffectRequirementsOf<TEffects> = TEffects extends {
20
21
  readonly [key: string]: EffectDefinition<any, any, any>;
21
- } ? {
22
+ } ? Exclude<{
22
23
  [K in keyof TEffects]: TEffects[K] extends EffectDefinition<any, infer R, any> ? R : never;
23
- }[keyof TEffects] : never;
24
+ }[keyof TEffects], RunLauncherTag> : never;
24
25
  export type ModuleServicesConfig<TR> = [TR] extends [never] ? {
25
26
  readonly services?: () => Layer.Layer<any>;
26
27
  } : {
@@ -36,6 +37,7 @@ export interface ModuleScope<TNamespace extends string, U extends EventEnvelope<
36
37
  readonly kind: string;
37
38
  readonly shape?: undefined;
38
39
  readonly input?: TInputSchema;
40
+ readonly forgetsCompletedEffects?: boolean;
39
41
  initialState(ctx: StartContext<InferDefinedSchema<TInputSchema>>): S;
40
42
  step(state: S, event: U, ctx: ThreadContext): S;
41
43
  effects?(state: S, ctx: ThreadContext): RuntimeEffect[];
@@ -44,6 +46,7 @@ export interface ModuleScope<TNamespace extends string, U extends EventEnvelope<
44
46
  readonly kind: string;
45
47
  readonly shape: TShape;
46
48
  readonly input?: TInputSchema;
49
+ readonly forgetsCompletedEffects?: boolean;
47
50
  initialState(ctx: StartContext<InferDefinedSchema<TInputSchema>>): InferSchemaOutput<TShape>;
48
51
  step(state: NoInfer<InferSchemaOutput<TShape>>, event: U, ctx: ThreadContext): InferSchemaOutput<TShape>;
49
52
  effects?(state: NoInfer<InferSchemaOutput<TShape>>, ctx: ThreadContext): RuntimeEffect[];
@@ -95,6 +98,7 @@ export declare function defineModule<const N extends string, E extends EventCata
95
98
  readonly definitions?: readonly DefinitionRef[];
96
99
  readonly middleware?: readonly EffectMiddleware[];
97
100
  readonly interruptsOnSignal?: SignalInterruptRule;
101
+ readonly bindHost?: (host: DefinitionHost) => void;
98
102
  } & ModuleServicesConfig<EffectRequirementsOf<FX>>): RuntimeModule<N, Extract<ModuleCatalog<N, E>, EventCatalog>, FX, TH, PR> & {
99
103
  readonly effects: FX;
100
104
  readonly threads: TH;
@@ -78,5 +78,8 @@ export function defineModule(options, setup) {
78
78
  if (members.interruptsOnSignal) {
79
79
  module.interruptsOnSignal = members.interruptsOnSignal;
80
80
  }
81
+ if (members.bindHost) {
82
+ module.bindHost = members.bindHost;
83
+ }
81
84
  return module;
82
85
  }
@@ -1,5 +1,6 @@
1
1
  import type { Context, Effect, Layer } from 'effect';
2
2
  import type { EventCatalog } from './catalog';
3
+ import type { DefinitionResolver } from './definition-resolver';
3
4
  import type { EffectContext, EffectDefinition, RuntimeEffect } from './effects';
4
5
  import type { EventInput } from './envelope';
5
6
  import type { ProjectionDefinition } from './projection';
@@ -14,6 +15,10 @@ export type EffectMiddleware = (effect: RuntimeEffect, ctx: EffectContext, next:
14
15
  * descendants. Return an empty array when the event interrupts nothing.
15
16
  */
16
17
  export type SignalInterruptRule = (event: EventInput) => readonly string[];
18
+ /** Passed to a module once, before its services layer is constructed. */
19
+ export interface DefinitionHost {
20
+ readonly definitionResolver: DefinitionResolver;
21
+ }
17
22
  export interface RuntimeModuleDependency {
18
23
  readonly namespace: string;
19
24
  readonly protocolVersion?: string;
@@ -70,6 +75,11 @@ export interface RuntimeModule<TNamespace extends string = string, TEvents exten
70
75
  readonly interruptsOnSignal?: SignalInterruptRule;
71
76
  /** Host-side services this module's effect handlers need (an LLM, a definition lookup, a DB pool). */
72
77
  readonly services?: () => Layer.Layer<TServices>;
78
+ /**
79
+ * Receives the host's definition resolver before `services()` runs.
80
+ * Modules that look definitions up during fold share one store with this resolver.
81
+ */
82
+ readonly bindHost?: (host: DefinitionHost) => void;
73
83
  }
74
84
  export declare function defineRuntimeModule<TNamespace extends string, TEvents extends EventCatalog, TEffects extends {
75
85
  readonly [key: string]: EffectDefinition;
@@ -1,5 +1,6 @@
1
1
  import { Schema, Stream, type Effect } from 'effect';
2
2
  import type { EventEnvelope } from './envelope';
3
+ import type { AnyEventEnvelope, RegisteredEvent } from './register';
3
4
  import type { InferSchemaOutput, SchemaInput } from './schema';
4
5
  import type { RunState, ThreadRecord } from './state';
5
6
  export interface ProjectionDefinition<S = unknown> {
@@ -8,17 +9,17 @@ export interface ProjectionDefinition<S = unknown> {
8
9
  initialState: S;
9
10
  reduce(state: S, event: EventEnvelope): S;
10
11
  }
11
- export declare function defineProjection<S = unknown>(def: {
12
+ export declare function defineProjection<S = unknown, TEvent extends AnyEventEnvelope = RegisteredEvent>(def: {
12
13
  readonly name: string;
13
14
  readonly shape?: undefined;
14
15
  readonly initialState: S;
15
- reduce(state: S, event: EventEnvelope): S;
16
+ reduce(state: S, event: TEvent): S;
16
17
  }): ProjectionDefinition<S>;
17
- export declare function defineProjection<TShape extends SchemaInput>(def: {
18
+ export declare function defineProjection<TShape extends SchemaInput, TEvent extends AnyEventEnvelope = RegisteredEvent>(def: {
18
19
  readonly name: string;
19
20
  readonly shape: TShape;
20
21
  readonly initialState: InferSchemaOutput<TShape>;
21
- reduce(state: NoInfer<InferSchemaOutput<TShape>>, event: EventEnvelope): InferSchemaOutput<TShape>;
22
+ reduce(state: NoInfer<InferSchemaOutput<TShape>>, event: TEvent): InferSchemaOutput<TShape>;
22
23
  }): ProjectionDefinition<InferSchemaOutput<TShape>>;
23
24
  export declare function foldProjection<S>(projection: ProjectionDefinition<S>, events: readonly EventEnvelope[], initial?: S): S;
24
25
  /** Fold a projection over events, skipping ephemeral ones. */
@@ -175,12 +175,16 @@ export function toThreadTree(state) {
175
175
  rootThreadId: state.rootThreadId,
176
176
  startIdentity: null,
177
177
  forkedFrom: null,
178
+ attributes: {},
178
179
  threads: state.records,
179
180
  waits: {},
180
181
  outstandingEffects: [],
181
182
  effectExecutions: {},
182
183
  completedEffectIds: [],
183
184
  processedIdempotencyKeys: [],
185
+ launchedRuns: [],
186
+ closeWaiting: false,
187
+ childCloseSent: false,
184
188
  });
185
189
  }
186
190
  export function treeFromRun(state) {
@@ -9,6 +9,18 @@ export declare const protocolCatalog: import("./catalog").EventCatalog<"runtime"
9
9
  readonly definitionVersion: Schema.withDecodingDefaultKey<Schema.String, never>;
10
10
  readonly input: Schema.Codec<Schema.Json, Schema.Json, never, never>;
11
11
  readonly requestedThreadId: Schema.optional<Schema.NullOr<Schema.String>>;
12
+ readonly launchedBy: Schema.optional<Schema.Struct<{
13
+ readonly runId: Schema.String;
14
+ readonly threadId: Schema.String;
15
+ readonly effectId: Schema.String;
16
+ readonly causationId: Schema.String;
17
+ readonly causationSeq: Schema.Finite;
18
+ }>>;
19
+ readonly attributes: Schema.optional<Schema.$Record<Schema.String, Schema.String>>;
20
+ readonly trace: Schema.optional<Schema.Struct<{
21
+ readonly traceparent: Schema.String;
22
+ readonly tracestate: Schema.optional<Schema.String>;
23
+ }>>;
12
24
  }>;
13
25
  'run.completed': Schema.Struct<{
14
26
  readonly output: Schema.NullOr<Schema.Codec<Schema.Json, Schema.Json, never, never>>;
@@ -17,6 +29,24 @@ export declare const protocolCatalog: import("./catalog").EventCatalog<"runtime"
17
29
  'run.cancelled': Schema.Struct<{
18
30
  readonly reason: Schema.optional<Schema.String>;
19
31
  }>;
32
+ 'run.launched': Schema.Struct<{
33
+ readonly runId: Schema.String;
34
+ readonly kind: Schema.String;
35
+ readonly definitionName: Schema.String;
36
+ readonly definitionVersion: Schema.withDecodingDefaultKey<Schema.String, never>;
37
+ /** In the payload, not the envelope: an envelope `effectId` would complete the effect. */
38
+ readonly effectId: Schema.String;
39
+ readonly close: Schema.withDecodingDefaultKey<Schema.Union<readonly [Schema.Literal<"terminate">, Schema.Literal<"wait">]>, never>;
40
+ }>;
41
+ 'child.settled': Schema.Struct<{
42
+ readonly runId: Schema.String;
43
+ readonly status: Schema.Union<readonly [Schema.Literal<"completed">, Schema.Literal<"failed">, Schema.Literal<"cancelled">]>;
44
+ readonly output: Schema.NullOr<Schema.Codec<Schema.Json, Schema.Json, never, never>>;
45
+ readonly error: Schema.NullOr<Schema.String>;
46
+ }>;
47
+ 'child.close.requested': Schema.Struct<{
48
+ readonly policy: Schema.Union<readonly [Schema.Literal<"terminate">, Schema.Literal<"wait">]>;
49
+ }>;
20
50
  'run.forked': Schema.Struct<{
21
51
  readonly sourceRunId: Schema.String;
22
52
  readonly sourceSeq: Schema.Finite;
@@ -81,6 +111,8 @@ export declare const protocolCatalog: import("./catalog").EventCatalog<"runtime"
81
111
  'effect.failed': Schema.Struct<{
82
112
  readonly effectId: Schema.String;
83
113
  readonly error: Schema.String;
114
+ readonly nonRetryable: Schema.optional<Schema.Boolean>;
115
+ readonly retryAfterMs: Schema.optional<Schema.Finite>;
84
116
  }>;
85
117
  'effect.attempt.started': Schema.Struct<{
86
118
  readonly effectId: Schema.String;
@@ -106,6 +138,8 @@ export declare const protocolCatalog: import("./catalog").EventCatalog<"runtime"
106
138
  readonly attempt: Schema.Finite;
107
139
  readonly heartbeatAt: Schema.Finite;
108
140
  readonly deadlineAt: Schema.NullOr<Schema.Finite>;
141
+ /** Progress the next attempt should resume from. Absent on heartbeats that only extend the deadline. */
142
+ readonly details: Schema.optional<Schema.Codec<Schema.Json, Schema.Json, never, never>>;
109
143
  }>;
110
144
  'effect.cancel.requested': Schema.Struct<{
111
145
  readonly effectId: Schema.String;
@@ -147,10 +181,11 @@ export declare const protocolCatalog: import("./catalog").EventCatalog<"runtime"
147
181
  }>;
148
182
  export type ProtocolEvent = EventsOfCatalog<typeof protocolCatalog>;
149
183
  export type ProtocolEventInput = EventInputOf<typeof protocolCatalog>;
150
- export declare const PROTOCOL_TYPES: readonly ['runtime.run.started', 'runtime.run.completed', 'runtime.run.cancelled', 'runtime.run.forked', 'runtime.fork.elided', 'runtime.thread.started', 'runtime.thread.completed', 'runtime.thread.failed', 'runtime.thread.cancelled', 'runtime.thread.cancel.requested', 'runtime.wait.registered', 'runtime.wait.satisfied', 'runtime.timer.set', 'runtime.timer.fired', 'runtime.effect.failed', 'runtime.effect.attempt.started', 'runtime.effect.queued', 'runtime.effect.dispatched', 'runtime.effect.worker.started', 'runtime.effect.heartbeat', 'runtime.effect.cancel.requested', 'runtime.effect.cancelled', 'runtime.effect.completed', 'runtime.effect.timed_out', 'runtime.effect.ambiguous', 'runtime.effect.retry.scheduled', 'runtime.snapshot.taken', 'runtime.signal.received'];
184
+ export declare const PROTOCOL_TYPES: readonly ['runtime.run.started', 'runtime.run.completed', 'runtime.run.cancelled', 'runtime.run.launched', 'runtime.child.settled', 'runtime.child.close.requested', 'runtime.run.forked', 'runtime.fork.elided', 'runtime.thread.started', 'runtime.thread.completed', 'runtime.thread.failed', 'runtime.thread.cancelled', 'runtime.thread.cancel.requested', 'runtime.wait.registered', 'runtime.wait.satisfied', 'runtime.timer.set', 'runtime.timer.fired', 'runtime.effect.failed', 'runtime.effect.attempt.started', 'runtime.effect.queued', 'runtime.effect.dispatched', 'runtime.effect.worker.started', 'runtime.effect.heartbeat', 'runtime.effect.cancel.requested', 'runtime.effect.cancelled', 'runtime.effect.completed', 'runtime.effect.timed_out', 'runtime.effect.ambiguous', 'runtime.effect.retry.scheduled', 'runtime.snapshot.taken', 'runtime.signal.received'];
151
185
  export type ProtocolEventType = (typeof PROTOCOL_TYPES)[number];
152
186
  export declare function isProtocolType(type: string): type is ProtocolEventType;
153
187
  export type RunStartedPayload = Schema.Schema.Type<(typeof protocolCatalog.entries)['run.started']>;
188
+ export type RunLaunchedPayload = Schema.Schema.Type<(typeof protocolCatalog.entries)['run.launched']>;
154
189
  export type RunCompletedPayload = Schema.Schema.Type<(typeof protocolCatalog.entries)['run.completed']>;
155
190
  export type ThreadStartedPayload = Schema.Schema.Type<(typeof protocolCatalog.entries)['thread.started']>;
156
191
  export type ThreadCompletedPayload = Schema.Schema.Type<(typeof protocolCatalog.entries)['thread.completed']>;
@@ -2,7 +2,10 @@ import { Effect, Schema } from 'effect';
2
2
  import { defineEventCatalog } from './catalog.js';
3
3
  import { WaitConditionSchema } from './effects.js';
4
4
  import { JsonValueSchema } from './envelope.js';
5
+ import { RunLaunchSourceSchema } from './launcher.js';
5
6
  import { DEFAULT_DEFINITION_VERSION } from './module.js';
7
+ import { RunAttributesSchema } from './run-context.js';
8
+ import { TraceContextSchema } from './trace.js';
6
9
  const DefinitionVersionSchema = Schema.String.pipe(Schema.withDecodingDefaultKey(Effect.succeed(DEFAULT_DEFINITION_VERSION)));
7
10
  export const protocolCatalog = defineEventCatalog('runtime', {
8
11
  'run.started': Schema.Struct({
@@ -12,6 +15,9 @@ export const protocolCatalog = defineEventCatalog('runtime', {
12
15
  definitionVersion: DefinitionVersionSchema,
13
16
  input: JsonValueSchema,
14
17
  requestedThreadId: Schema.optional(Schema.NullOr(Schema.String)),
18
+ launchedBy: Schema.optional(RunLaunchSourceSchema),
19
+ attributes: Schema.optional(RunAttributesSchema),
20
+ trace: Schema.optional(TraceContextSchema),
15
21
  }),
16
22
  'run.completed': Schema.Struct({
17
23
  output: Schema.NullOr(JsonValueSchema),
@@ -20,6 +26,28 @@ export const protocolCatalog = defineEventCatalog('runtime', {
20
26
  'run.cancelled': Schema.Struct({
21
27
  reason: Schema.optional(Schema.String),
22
28
  }),
29
+ 'run.launched': Schema.Struct({
30
+ runId: Schema.String,
31
+ kind: Schema.String,
32
+ definitionName: Schema.String,
33
+ definitionVersion: DefinitionVersionSchema,
34
+ /** In the payload, not the envelope: an envelope `effectId` would complete the effect. */
35
+ effectId: Schema.String,
36
+ close: Schema.Union([Schema.Literal('terminate'), Schema.Literal('wait')]).pipe(Schema.withDecodingDefaultKey(Effect.succeed('terminate'))),
37
+ }),
38
+ 'child.settled': Schema.Struct({
39
+ runId: Schema.String,
40
+ status: Schema.Union([
41
+ Schema.Literal('completed'),
42
+ Schema.Literal('failed'),
43
+ Schema.Literal('cancelled'),
44
+ ]),
45
+ output: Schema.NullOr(JsonValueSchema),
46
+ error: Schema.NullOr(Schema.String),
47
+ }),
48
+ 'child.close.requested': Schema.Struct({
49
+ policy: Schema.Union([Schema.Literal('terminate'), Schema.Literal('wait')]),
50
+ }),
23
51
  'run.forked': Schema.Struct({
24
52
  sourceRunId: Schema.String,
25
53
  sourceSeq: Schema.Finite,
@@ -79,6 +107,8 @@ export const protocolCatalog = defineEventCatalog('runtime', {
79
107
  'effect.failed': Schema.Struct({
80
108
  effectId: Schema.String,
81
109
  error: Schema.String,
110
+ nonRetryable: Schema.optional(Schema.Boolean),
111
+ retryAfterMs: Schema.optional(Schema.Finite),
82
112
  }),
83
113
  'effect.attempt.started': Schema.Struct({
84
114
  effectId: Schema.String,
@@ -104,6 +134,8 @@ export const protocolCatalog = defineEventCatalog('runtime', {
104
134
  attempt: Schema.Finite,
105
135
  heartbeatAt: Schema.Finite,
106
136
  deadlineAt: Schema.NullOr(Schema.Finite),
137
+ /** Progress the next attempt should resume from. Absent on heartbeats that only extend the deadline. */
138
+ details: Schema.optional(JsonValueSchema),
107
139
  }),
108
140
  'effect.cancel.requested': Schema.Struct({
109
141
  effectId: Schema.String,
@@ -147,6 +179,9 @@ export const PROTOCOL_TYPES = [
147
179
  'runtime.run.started',
148
180
  'runtime.run.completed',
149
181
  'runtime.run.cancelled',
182
+ 'runtime.run.launched',
183
+ 'runtime.child.settled',
184
+ 'runtime.child.close.requested',
150
185
  'runtime.run.forked',
151
186
  'runtime.fork.elided',
152
187
  'runtime.thread.started',
@@ -30,6 +30,7 @@ export declare const RunSummarySchema: Schema.Struct<{
30
30
  readonly status: Schema.Union<readonly [Schema.Literal<"running">, Schema.Literal<"completed">, Schema.Literal<"failed">, Schema.Literal<"cancelled">]>;
31
31
  readonly kind: Schema.NullOr<Schema.String>;
32
32
  readonly definitionName: Schema.NullOr<Schema.String>;
33
+ readonly attributes: Schema.withDecodingDefaultKey<Schema.$Record<Schema.String, Schema.String>, never>;
33
34
  }>;
34
35
  export type RunSummary = Schema.Schema.Type<typeof RunSummarySchema>;
35
36
  export declare function summarizeRun(state: RunState): RunSummary;
@@ -39,5 +40,6 @@ export declare const RunSummariesSchema: Schema.Struct<{
39
40
  readonly status: Schema.Union<readonly [Schema.Literal<"running">, Schema.Literal<"completed">, Schema.Literal<"failed">, Schema.Literal<"cancelled">]>;
40
41
  readonly kind: Schema.NullOr<Schema.String>;
41
42
  readonly definitionName: Schema.NullOr<Schema.String>;
43
+ readonly attributes: Schema.withDecodingDefaultKey<Schema.$Record<Schema.String, Schema.String>, never>;
42
44
  }>>;
43
45
  }>;
@@ -1,5 +1,6 @@
1
- import { Schema } from 'effect';
1
+ import { Effect, Schema } from 'effect';
2
2
  import { JsonValueSchema } from './envelope.js';
3
+ import { RunAttributesSchema } from './run-context.js';
3
4
  import { jsonSchemaOfInput } from './schema.js';
4
5
  import { RunStateSchema } from './state.js';
5
6
  /** A registered definition as `GET /definitions` publishes it. */
@@ -30,6 +31,7 @@ export const RunSummarySchema = Schema.Struct({
30
31
  status: RunStateSchema.fields.status,
31
32
  kind: Schema.NullOr(Schema.String),
32
33
  definitionName: Schema.NullOr(Schema.String),
34
+ attributes: RunAttributesSchema.pipe(Schema.withDecodingDefaultKey(Effect.succeed({}))),
33
35
  });
34
36
  export function summarizeRun(state) {
35
37
  return {
@@ -37,6 +39,7 @@ export function summarizeRun(state) {
37
39
  status: state.status,
38
40
  kind: state.startIdentity?.kind ?? null,
39
41
  definitionName: state.startIdentity?.definitionName ?? null,
42
+ attributes: state.attributes ?? {},
40
43
  };
41
44
  }
42
45
  export const RunSummariesSchema = Schema.Struct({
@@ -1,11 +1,12 @@
1
- import type { EventEnvelope, EventsOf } from '@swirls/looms/core';
1
+ import type { EventsOf } from './compose';
2
+ import type { EventEnvelope } from './envelope';
2
3
  /** Looser event bound so catalog-inferred payloads (including Schema.Type) are accepted. */
3
4
  export type AnyEventEnvelope = EventEnvelope<string, any>;
4
5
  /**
5
- * Application-level type registry for Looms React/client stores.
6
+ * Application-level type registry for Looms.
6
7
  *
7
- * Augment this interface in your app to bind the event catalog used by
8
- * `useRunEvents`, `createLoomsStore`, and related hooks:
8
+ * Augment this interface once to bind your event union. `defineProjection` reducers and the
9
+ * `@swirls/looms/react` hooks and stores use it as their default event type:
9
10
  *
10
11
  * ```ts
11
12
  * declare module '@swirls/looms/react' {
@@ -15,7 +16,7 @@ export type AnyEventEnvelope = EventEnvelope<string, any>;
15
16
  * }
16
17
  * ```
17
18
  *
18
- * You may register either:
19
+ * Augmenting `@swirls/looms/core` works the same way. You may register either:
19
20
  * - `events`: an explicit event union
20
21
  * - `modules`: a module array / creator function (via `EventsOf`)
21
22
  * - `catalog`: an event catalog or catalog array (via `EventsOf`)
@@ -24,8 +25,8 @@ export interface LoomsRegister {
24
25
  }
25
26
  export type RegisteredEvent = LoomsRegister extends {
26
27
  events: infer E;
27
- } ? E & AnyEventEnvelope : LoomsRegister extends {
28
+ } ? Extract<E, AnyEventEnvelope> : LoomsRegister extends {
28
29
  modules: infer M;
29
- } ? EventsOf<M> & AnyEventEnvelope : LoomsRegister extends {
30
+ } ? Extract<EventsOf<M>, AnyEventEnvelope> : LoomsRegister extends {
30
31
  catalog: infer C;
31
- } ? EventsOf<C> & AnyEventEnvelope : EventEnvelope;
32
+ } ? Extract<EventsOf<C>, AnyEventEnvelope> : EventEnvelope;