@smthrs/plugin 0.0.0-stage → 1.0.0-rc.13

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 (118) hide show
  1. package/CHANGELOG.md +79 -0
  2. package/LICENSE +21 -0
  3. package/README.md +88 -2
  4. package/dist/cjs/Config.d.ts +129 -0
  5. package/dist/cjs/Config.d.ts.map +1 -0
  6. package/dist/cjs/Config.js +115 -0
  7. package/dist/cjs/Config.js.map +7 -0
  8. package/dist/cjs/Hooks.d.ts +176 -0
  9. package/dist/cjs/Hooks.d.ts.map +1 -0
  10. package/dist/cjs/Hooks.js +34 -0
  11. package/dist/cjs/Hooks.js.map +7 -0
  12. package/dist/cjs/Kernel.d.ts +81 -0
  13. package/dist/cjs/Kernel.d.ts.map +1 -0
  14. package/dist/cjs/Kernel.js +57 -0
  15. package/dist/cjs/Kernel.js.map +7 -0
  16. package/dist/cjs/Plugin.d.ts +71 -0
  17. package/dist/cjs/Plugin.d.ts.map +1 -0
  18. package/dist/cjs/Plugin.js +25 -0
  19. package/dist/cjs/Plugin.js.map +7 -0
  20. package/dist/cjs/PluginError.d.ts +50 -0
  21. package/dist/cjs/PluginError.d.ts.map +1 -0
  22. package/dist/cjs/PluginError.js +58 -0
  23. package/dist/cjs/PluginError.js.map +7 -0
  24. package/dist/cjs/Plugins.d.ts +97 -0
  25. package/dist/cjs/Plugins.d.ts.map +1 -0
  26. package/dist/cjs/Plugins.js +169 -0
  27. package/dist/cjs/Plugins.js.map +7 -0
  28. package/dist/cjs/Resolve.d.ts +128 -0
  29. package/dist/cjs/Resolve.d.ts.map +1 -0
  30. package/dist/cjs/Resolve.js +346 -0
  31. package/dist/cjs/Resolve.js.map +7 -0
  32. package/dist/cjs/index.d.ts +83 -0
  33. package/dist/cjs/index.d.ts.map +1 -0
  34. package/dist/cjs/index.js +45 -0
  35. package/dist/cjs/index.js.map +7 -0
  36. package/dist/cjs/internal/Boundary.d.ts +96 -0
  37. package/dist/cjs/internal/Boundary.d.ts.map +1 -0
  38. package/dist/cjs/internal/Boundary.js +129 -0
  39. package/dist/cjs/internal/Boundary.js.map +7 -0
  40. package/dist/cjs/internal/mergePluginLayers.d.ts +21 -0
  41. package/dist/cjs/internal/mergePluginLayers.d.ts.map +1 -0
  42. package/dist/cjs/internal/mergePluginLayers.js +57 -0
  43. package/dist/cjs/internal/mergePluginLayers.js.map +7 -0
  44. package/dist/cjs/internal/snapshotCacheEnvironment.d.ts +23 -0
  45. package/dist/cjs/internal/snapshotCacheEnvironment.d.ts.map +1 -0
  46. package/dist/cjs/internal/snapshotCacheEnvironment.js +92 -0
  47. package/dist/cjs/internal/snapshotCacheEnvironment.js.map +7 -0
  48. package/dist/cjs/package.json +1 -0
  49. package/dist/esm/Config.d.ts +129 -0
  50. package/dist/esm/Config.d.ts.map +1 -0
  51. package/dist/esm/Config.js +160 -0
  52. package/dist/esm/Config.js.map +1 -0
  53. package/dist/esm/Hooks.d.ts +176 -0
  54. package/dist/esm/Hooks.d.ts.map +1 -0
  55. package/dist/esm/Hooks.js +56 -0
  56. package/dist/esm/Hooks.js.map +1 -0
  57. package/dist/esm/Kernel.d.ts +81 -0
  58. package/dist/esm/Kernel.d.ts.map +1 -0
  59. package/dist/esm/Kernel.js +58 -0
  60. package/dist/esm/Kernel.js.map +1 -0
  61. package/dist/esm/Plugin.d.ts +71 -0
  62. package/dist/esm/Plugin.d.ts.map +1 -0
  63. package/dist/esm/Plugin.js +20 -0
  64. package/dist/esm/Plugin.js.map +1 -0
  65. package/dist/esm/PluginError.d.ts +50 -0
  66. package/dist/esm/PluginError.d.ts.map +1 -0
  67. package/dist/esm/PluginError.js +53 -0
  68. package/dist/esm/PluginError.js.map +1 -0
  69. package/dist/esm/Plugins.d.ts +97 -0
  70. package/dist/esm/Plugins.d.ts.map +1 -0
  71. package/dist/esm/Plugins.js +190 -0
  72. package/dist/esm/Plugins.js.map +1 -0
  73. package/dist/esm/Resolve.d.ts +128 -0
  74. package/dist/esm/Resolve.d.ts.map +1 -0
  75. package/dist/esm/Resolve.js +369 -0
  76. package/dist/esm/Resolve.js.map +1 -0
  77. package/dist/esm/index.d.ts +83 -0
  78. package/dist/esm/index.d.ts.map +1 -0
  79. package/dist/esm/index.js +48 -0
  80. package/dist/esm/index.js.map +1 -0
  81. package/dist/esm/internal/Boundary.d.ts +96 -0
  82. package/dist/esm/internal/Boundary.d.ts.map +1 -0
  83. package/dist/esm/internal/Boundary.js +162 -0
  84. package/dist/esm/internal/Boundary.js.map +1 -0
  85. package/dist/esm/internal/mergePluginLayers.d.ts +21 -0
  86. package/dist/esm/internal/mergePluginLayers.d.ts.map +1 -0
  87. package/dist/esm/internal/mergePluginLayers.js +41 -0
  88. package/dist/esm/internal/mergePluginLayers.js.map +1 -0
  89. package/dist/esm/internal/snapshotCacheEnvironment.d.ts +23 -0
  90. package/dist/esm/internal/snapshotCacheEnvironment.d.ts.map +1 -0
  91. package/dist/esm/internal/snapshotCacheEnvironment.js +64 -0
  92. package/dist/esm/internal/snapshotCacheEnvironment.js.map +1 -0
  93. package/docs/README.md +133 -0
  94. package/docs/api.md +524 -0
  95. package/docs/concepts/configuration.md +111 -0
  96. package/docs/concepts/hook-kinds.md +107 -0
  97. package/docs/concepts/resolution.md +132 -0
  98. package/docs/guides/cache-identity.md +106 -0
  99. package/docs/guides/contribute-services.md +84 -0
  100. package/docs/guides/host-your-own-hooks.md +129 -0
  101. package/docs/guides/order-handlers.md +76 -0
  102. package/docs/guides/select-plugins.md +72 -0
  103. package/docs/guides/testing.md +149 -0
  104. package/docs/installation.md +75 -0
  105. package/docs/quickstart.md +152 -0
  106. package/docs/troubleshooting.md +180 -0
  107. package/package.json +179 -3
  108. package/src/Config.ts +207 -0
  109. package/src/Hooks.ts +212 -0
  110. package/src/Kernel.ts +119 -0
  111. package/src/Plugin.ts +80 -0
  112. package/src/PluginError.ts +62 -0
  113. package/src/Plugins.ts +271 -0
  114. package/src/Resolve.ts +539 -0
  115. package/src/index.ts +91 -0
  116. package/src/internal/Boundary.ts +252 -0
  117. package/src/internal/mergePluginLayers.ts +57 -0
  118. package/src/internal/snapshotCacheEnvironment.ts +78 -0
package/src/Hooks.ts ADDED
@@ -0,0 +1,212 @@
1
+ /**
2
+ * The typed hook surface: hook kinds, the hook entry shape, and the shared
3
+ * kernel's base hook catalog.
4
+ *
5
+ * The public package contract is documented at
6
+ * {@link https://smithers.sh/docs/reference/api/plugin}. The shared catalog is limited to
7
+ * `config` and `configResolved`;
8
+ * `@smthrs/agent` adds only `cellRegistry`, `cellFlows`, and
9
+ * `cellModelRequest`. Durable-core lifecycle policy is not a hook catalog.
10
+ *
11
+ * `FlowsHooks` is **open for augmentation, closed for dispatch**: a host
12
+ * declares its hooks with `declare module "@smthrs/plugin"`, supplies the
13
+ * matching runtime catalog, and dispatches only that bounded set.
14
+ *
15
+ * @since 1.0.0-rc.0
16
+ */
17
+
18
+ import type * as Effect from "effect/Effect"
19
+
20
+ /**
21
+ * Dispatch semantics of a hook, fixed by the core.
22
+ *
23
+ * @category models
24
+ * @since 1.0.0-rc.0
25
+ */
26
+ export type HookKind = "sequential" | "parallel" | "first" | "waterfall"
27
+
28
+ declare const HookTypeId: unique symbol
29
+
30
+ /**
31
+ * Phantom carrier that records a hook's kind and handler type in the type
32
+ * system without adding anything at runtime.
33
+ *
34
+ * @category models
35
+ * @since 1.0.0-rc.0
36
+ */
37
+ export interface HookMeta<K extends HookKind, F> {
38
+ readonly [HookTypeId]?: { readonly kind: K; readonly handler: F }
39
+ }
40
+
41
+ /**
42
+ * The object form of a hook entry: Vite's per-hook ordering object, verbatim.
43
+ *
44
+ * @category models
45
+ * @since 1.0.0-rc.0
46
+ */
47
+ export interface HookObject<F> {
48
+ readonly order?: "pre" | "post" | undefined
49
+ readonly handler: F
50
+ }
51
+
52
+ /**
53
+ * A hook entry is either the bare handler or `{ order?, handler }`.
54
+ *
55
+ * @category models
56
+ * @since 1.0.0-rc.0
57
+ */
58
+ export type HookEntry<K extends HookKind, F> = (F | HookObject<F>) & HookMeta<K, F>
59
+
60
+ /**
61
+ * Every handler runs, in resolved order, one at a time.
62
+ *
63
+ * @category models
64
+ * @since 1.0.0-rc.0
65
+ */
66
+ export type SequentialHook<F> = HookEntry<"sequential", F>
67
+
68
+ /**
69
+ * Every handler runs concurrently; results are ignored and failures are
70
+ * returned to the caller rather than failing it.
71
+ *
72
+ * @category models
73
+ * @since 1.0.0-rc.0
74
+ */
75
+ export type ParallelHook<F> = HookEntry<"parallel", F>
76
+
77
+ /**
78
+ * Handlers run in order until one returns `Option.some`.
79
+ *
80
+ * @category models
81
+ * @since 1.0.0-rc.0
82
+ */
83
+ export type FirstHook<F> = HookEntry<"first", F>
84
+
85
+ /**
86
+ * Each handler receives the previous handler's output.
87
+ *
88
+ * @category models
89
+ * @since 1.0.0-rc.0
90
+ */
91
+ export type WaterfallHook<F> = HookEntry<"waterfall", F>
92
+
93
+ /**
94
+ * Extracts the declared kind of a hook entry type.
95
+ *
96
+ * @category type-level
97
+ * @since 1.0.0-rc.0
98
+ */
99
+ export type KindOf<T> = T extends HookMeta<infer K, any> ? K : never
100
+
101
+ /**
102
+ * The runtime catalog a host supplies for a hook interface: each hook name
103
+ * mapped to its kind. A name declared in `H` must carry the kind its type
104
+ * declares. Names outside `H` are admitted with any kind, because the type
105
+ * system cannot enumerate an augmentable interface; resolution checks them
106
+ * at runtime and dispatch refuses a kind that disagrees with the catalog.
107
+ *
108
+ * @category type-level
109
+ * @since 1.0.0-rc.0
110
+ */
111
+ export type HookCatalog<H> =
112
+ & { readonly [K in keyof H & string]?: KindOf<H[K]> }
113
+ & { readonly [name: string]: HookKind | undefined }
114
+
115
+ /**
116
+ * Extracts the handler type of a hook entry type.
117
+ *
118
+ * @category type-level
119
+ * @since 1.0.0-rc.0
120
+ */
121
+ export type HandlerOf<T> = T extends HookMeta<any, infer F> ? F : never
122
+
123
+ /**
124
+ * Selects the hook names of a given kind from a hook interface.
125
+ *
126
+ * @category type-level
127
+ * @since 1.0.0-rc.0
128
+ */
129
+ export type KeysOfKind<H, K extends HookKind> =
130
+ & {
131
+ [P in keyof H]: KindOf<H[P]> extends K ? P : never
132
+ }[keyof H]
133
+ & string
134
+
135
+ /**
136
+ * Extracts the positional argument tuple accepted by a hook entry.
137
+ *
138
+ * @category type-level
139
+ * @since 1.0.0-rc.0
140
+ */
141
+ export type ArgsOf<T> = HandlerOf<T> extends (...args: infer A) => any ? A : never
142
+
143
+ /**
144
+ * Extracts the Effect returned by a hook entry.
145
+ *
146
+ * @category type-level
147
+ * @since 1.0.0-rc.0
148
+ */
149
+ export type ReturnOf<T> = HandlerOf<T> extends (...args: any) => infer R ? R : never
150
+
151
+ /**
152
+ * Extracts the success value returned by a hook entry's Effect.
153
+ *
154
+ * @category type-level
155
+ * @since 1.0.0-rc.0
156
+ */
157
+ export type SuccessOf<T> = ReturnOf<T> extends Effect.Effect<infer A, any, any> ? A : never
158
+
159
+ /**
160
+ * Extracts the context required by a hook entry's Effect.
161
+ *
162
+ * @category type-level
163
+ * @since 1.0.0-rc.0
164
+ */
165
+ export type ContextOf<T> = ReturnOf<T> extends Effect.Effect<any, any, infer R> ? R : never
166
+
167
+ /**
168
+ * Runtime catalog of the shared kernel's hook names and kinds.
169
+ *
170
+ * The type system cannot enumerate an augmentable interface, so this constant
171
+ * is what the `unknown_hook` guard checks against. A host passes its own
172
+ * superset to {@link resolve}. The cell harness adds only the hooks it
173
+ * dispatches; lifecycle and engine-policy hooks do not belong here.
174
+ *
175
+ * @category models
176
+ * @since 1.0.0-rc.0
177
+ */
178
+ const sharedHooks: { config: "waterfall"; configResolved: "parallel" } = Object.create(null)
179
+ Object.defineProperties(sharedHooks, {
180
+ config: { value: "waterfall", enumerable: true },
181
+ configResolved: { value: "parallel", enumerable: true }
182
+ })
183
+ /**
184
+ * Frozen runtime catalog for the shared configuration hooks.
185
+ *
186
+ * @category models
187
+ * @since 1.0.0-rc.0
188
+ */
189
+ export const engineHooks: Readonly<{
190
+ readonly config: "waterfall"
191
+ readonly configResolved: "parallel"
192
+ }> = Object.freeze(sharedHooks)
193
+
194
+ /**
195
+ * Normalizes a hook entry to its handler.
196
+ *
197
+ * @category utils
198
+ * @since 1.0.0-rc.0
199
+ */
200
+ export const handlerOf = (entry: unknown): (...args: Array<any>) => unknown =>
201
+ typeof entry === "function"
202
+ ? entry as (...args: Array<any>) => unknown
203
+ : (entry as HookObject<(...args: Array<any>) => unknown>).handler
204
+
205
+ /**
206
+ * Reads the per-hook `order` of a hook entry.
207
+ *
208
+ * @category utils
209
+ * @since 1.0.0-rc.0
210
+ */
211
+ export const orderOf = (entry: unknown): "pre" | "post" | undefined =>
212
+ typeof entry === "function" ? undefined : (entry as HookObject<unknown>).order
package/src/Kernel.ts ADDED
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Startup: resolve the plugin list, run the config pipeline, hand back a
3
+ * dispatcher, a frozen config, and the merged layer.
4
+ *
5
+ * The public package contract is documented at
6
+ * {@link https://smithers.sh/docs/reference/api/plugin}, with the shipped host catalog in
7
+ * `packages/smithers/agent/src/CellPlugin.ts`. D14 in
8
+ * `docs/pages/design-decisions.md` keeps durable policy outside these hooks.
9
+ *
10
+ * Order of operations, per the spec:
11
+ *
12
+ * 1. flatten / filter / validate / order the plugin list;
13
+ * 2. `config` waterfall: each plugin may return a partial to deep-merge;
14
+ * 3. decode and freeze into a `ResolvedConfig` (`config_invalid` on failure);
15
+ * 4. `configResolved` parallel: observers capture the final config;
16
+ * 5. plugin `layer`s merge left-to-right.
17
+ *
18
+ * @since 1.0.0-rc.0
19
+ */
20
+
21
+ import * as Effect from "effect/Effect"
22
+ import type * as Layer from "effect/Layer"
23
+ import type { FlowsConfig, ResolvedConfig } from "./Config.ts"
24
+ import * as Config from "./Config.ts"
25
+ import type { ContextOf } from "./Hooks.ts"
26
+ import type { FlowsHooks } from "./index.ts"
27
+ import type { PluginInput } from "./Plugin.ts"
28
+ import type { PluginError } from "./PluginError.ts"
29
+ import * as Plugins from "./Plugins.ts"
30
+ import * as Resolve from "./Resolve.ts"
31
+
32
+ /**
33
+ * Everything startup produces from a plugin list and a raw config.
34
+ *
35
+ * `observerErrors` carries `configResolved` failures: parallel observers are
36
+ * lossy by contract, so they are reported rather than fatal.
37
+ *
38
+ * @category models
39
+ * @since 1.0.0-rc.0
40
+ */
41
+ export interface Kernel<H = FlowsHooks> {
42
+ readonly plugins: Plugins.Service<H>
43
+ readonly config: ResolvedConfig
44
+ readonly layer: Layer.Layer<any, PluginError, any>
45
+ readonly observerErrors: ReadonlyArray<PluginError>
46
+ }
47
+
48
+ type HookAt<H, K extends string> = K extends keyof H ? H[K] : never
49
+
50
+ /**
51
+ * The services a hook interface's `config` hook requires at startup. `never`
52
+ * for the shared `FlowsHooks`, whose startup hooks are context-free.
53
+ *
54
+ * @category type-level
55
+ * @since 1.0.0-rc.0
56
+ */
57
+ export type ConfigContext<H> = ContextOf<HookAt<H, "config">>
58
+
59
+ /**
60
+ * The services a hook interface's startup hooks require: the union of the
61
+ * `config` and `configResolved` requirements. `Kernel.make` cannot supply
62
+ * them itself, so they surface in its Effect and the caller provides them.
63
+ *
64
+ * @category type-level
65
+ * @since 1.0.0-rc.0
66
+ */
67
+ export type StartupContext<H> = ConfigContext<H> | ContextOf<HookAt<H, "configResolved">>
68
+
69
+ /**
70
+ * Snapshots the config before dispatching the `config` waterfall, then
71
+ * admits the result as a frozen `ResolvedConfig`.
72
+ *
73
+ * @category constructors
74
+ * @since 1.0.0-rc.0
75
+ */
76
+ export const runConfig = <H = FlowsHooks>(
77
+ plugins: Plugins.Service<H>,
78
+ config: FlowsConfig
79
+ ): Effect.Effect<ResolvedConfig, PluginError, ConfigContext<H>> =>
80
+ Effect.gen(function*() {
81
+ const initial = yield* Config.snapshot(config)
82
+ const merged = yield* (plugins.waterfall as unknown as (
83
+ hook: string,
84
+ initial: FlowsConfig,
85
+ merge: (previous: FlowsConfig, patch: unknown) => FlowsConfig
86
+ ) => Effect.Effect<FlowsConfig, PluginError, ConfigContext<H>>)("config", initial, Config.merge)
87
+ return yield* Config.resolve(merged)
88
+ })
89
+
90
+ /**
91
+ * Resolves plugins, executes the config pipeline, and merges plugin layers.
92
+ * The positional `config` is the kernel's only pre-resolution configuration;
93
+ * the options object cannot declare a second source, and a `config` key
94
+ * supplied anyway fails with `invalid_plugin` at `$options.config`.
95
+ *
96
+ * @category constructors
97
+ * @since 1.0.0-rc.0
98
+ */
99
+ export const make = <H = FlowsHooks>(
100
+ input: PluginInput<NoInfer<H>>,
101
+ config: FlowsConfig = {},
102
+ options: Omit<Resolve.Options<NoInfer<H>>, "config"> = {}
103
+ ): Effect.Effect<Kernel<H>, PluginError, StartupContext<H>> =>
104
+ Effect.gen(function*() {
105
+ const initial = yield* Config.snapshot(config)
106
+ const resolved = yield* Resolve.resolve<H>(input, options, initial)
107
+ const dispatcher = Plugins.make<H>(resolved)
108
+ const frozen = yield* runConfig(dispatcher, initial)
109
+ const observerErrors = yield* (dispatcher.parallel as unknown as (
110
+ hook: string,
111
+ value: ResolvedConfig
112
+ ) => Effect.Effect<ReadonlyArray<PluginError>, never, StartupContext<H>>)("configResolved", frozen)
113
+ return Object.freeze({
114
+ plugins: dispatcher,
115
+ config: frozen,
116
+ layer: Resolve.layer(resolved),
117
+ observerErrors
118
+ })
119
+ })
package/src/Plugin.ts ADDED
@@ -0,0 +1,80 @@
1
+ /**
2
+ * The plugin object: a plain record produced by a factory function.
3
+ *
4
+ * The public package contract is documented at
5
+ * {@link https://smithers.sh/docs/reference/api/plugin}. The shipped consumer is the
6
+ * assembled cell host in `@smthrs/agent`;
7
+ * durable-core policy continues to use Effect services and constructor
8
+ * options rather than plugin lifecycle hooks.
9
+ *
10
+ * @since 1.0.0-rc.0
11
+ */
12
+
13
+ import type * as Layer from "effect/Layer"
14
+ import type { FlowsConfig } from "./Config.ts"
15
+ import type { FlowsHooks } from "./index.ts"
16
+
17
+ /**
18
+ * Conditional-inclusion predicate, mirroring Vite's `apply`.
19
+ *
20
+ * `"engine"` and `"harness"` select the matching plugin-kernel host. The
21
+ * assembled cell host resolves as `"harness"`; this does not make `"engine"` an
22
+ * engine-lifecycle hook registration.
23
+ *
24
+ * @category models
25
+ * @since 1.0.0-rc.0
26
+ */
27
+ export type Apply = "engine" | "harness" | ((config: FlowsConfig) => boolean)
28
+
29
+ /**
30
+ * A flows plugin.
31
+ *
32
+ * Generic over the hook interface so a harness can hold plugins typed against
33
+ * its augmented `FlowsHooks` without any inheritance machinery.
34
+ *
35
+ * @category models
36
+ * @since 1.0.0-rc.0
37
+ */
38
+ export interface FlowsPlugin<H = FlowsHooks> {
39
+ /** Required, unique. Convention: `flows-plugin-<thing>`. */
40
+ readonly name: string
41
+ /**
42
+ * Semantic identity folded into sealed cache keys. Required when the host
43
+ * declares a cache environment. `Action.CacheEnvironment` is complete by
44
+ * contract, so a versionless composition is refused instead of claiming an
45
+ * ambiguous cross-run identity.
46
+ */
47
+ readonly version?: string | undefined
48
+ /** Ordering group; omitted means `"normal"`. */
49
+ readonly enforce?: "pre" | "post" | undefined
50
+ /** Conditional inclusion. */
51
+ readonly apply?: Apply | undefined
52
+ /** Services this plugin contributes to the engine environment. */
53
+ readonly layer?: Layer.Layer<never, any, any> | undefined
54
+ /** Typed hooks; only keys declared in the hook interface compile. */
55
+ readonly hooks?: Partial<H> | undefined
56
+ }
57
+
58
+ /**
59
+ * What a `plugins` array may contain: plugins, falsy entries, and arrays nested
60
+ * up to `Resolve.maximumPluginDepth`: so a preset is just a function returning
61
+ * plugins.
62
+ *
63
+ * @category models
64
+ * @since 1.0.0-rc.0
65
+ */
66
+ export type PluginInput<H = FlowsHooks> =
67
+ | FlowsPlugin<H>
68
+ | false
69
+ | null
70
+ | undefined
71
+ | ReadonlyArray<PluginInput<H>>
72
+
73
+ /**
74
+ * Identity constructor that pins a plugin literal to `FlowsPlugin` so excess
75
+ * hook keys are rejected at the definition site.
76
+ *
77
+ * @category constructors
78
+ * @since 1.0.0-rc.0
79
+ */
80
+ export const make = <H = FlowsHooks>(plugin: FlowsPlugin<H>): FlowsPlugin<H> => plugin
@@ -0,0 +1,62 @@
1
+ /**
2
+ * The single typed failure of the plugin kernel.
3
+ *
4
+ * The public package contract is documented at
5
+ * {@link https://smithers.sh/docs/reference/api/plugin}; D14 in
6
+ * `docs/pages/design-decisions.md` bounds it to host-owned cell hooks.
7
+ *
8
+ * @since 1.0.0-rc.0
9
+ */
10
+
11
+ import * as Schema from "effect/Schema"
12
+
13
+ /**
14
+ * Closed set of plugin-system failure codes.
15
+ *
16
+ * @category models
17
+ * @since 1.0.0-rc.0
18
+ */
19
+ export const PluginErrorCode = Schema.Literals([
20
+ "duplicate_name",
21
+ "unknown_hook",
22
+ "hook_kind_mismatch",
23
+ "invalid_plugin",
24
+ "apply_failed",
25
+ "config_invalid",
26
+ "cache_environment_invalid",
27
+ "invalid_hook_result",
28
+ "resource_limit",
29
+ "hook_failed",
30
+ "layer_failed"
31
+ ])
32
+
33
+ /**
34
+ * Closed set of plugin-system failure codes.
35
+ *
36
+ * @category models
37
+ * @since 1.0.0-rc.0
38
+ */
39
+ export type PluginErrorCode = typeof PluginErrorCode.Type
40
+
41
+ /**
42
+ * Failure raised by plugin resolution, hook dispatch, config execution, or
43
+ * layer construction.
44
+ *
45
+ * Parallel observer failures never fail the caller; they are returned from
46
+ * `Plugins.parallel` with this same shape so they can be journalled on the
47
+ * lossy telemetry channel.
48
+ *
49
+ * `cause` is the plugin's unredacted failure and may hold secrets; hosts
50
+ * redact it before logging, persisting, or transmitting the error.
51
+ *
52
+ * @category errors
53
+ * @since 1.0.0-rc.0
54
+ */
55
+ export class PluginError extends Schema.TaggedError<PluginError>()("flows/plugin/PluginError", {
56
+ code: PluginErrorCode,
57
+ message: Schema.String,
58
+ plugin: Schema.optional(Schema.String),
59
+ hook: Schema.optional(Schema.String),
60
+ path: Schema.optional(Schema.String),
61
+ cause: Schema.optional(Schema.Unknown)
62
+ }) {}