@vimhead.dev/norn-cli 0.1.0-tip.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 (171) hide show
  1. package/README.md +13 -0
  2. package/assets/README.md +157 -0
  3. package/assets/docs/README.md +23 -0
  4. package/assets/docs/agents.md +64 -0
  5. package/assets/docs/cli.md +183 -0
  6. package/assets/docs/composition.md +76 -0
  7. package/assets/docs/persistence.md +56 -0
  8. package/assets/docs/projects.md +75 -0
  9. package/assets/docs/recovery.md +56 -0
  10. package/assets/docs/resources.md +61 -0
  11. package/assets/docs/workflows.md +57 -0
  12. package/assets/examples/agent-then-analysis/README.md +103 -0
  13. package/assets/examples/agent-then-analysis/input.json +5 -0
  14. package/assets/examples/agent-then-analysis/norn.project.json +4 -0
  15. package/assets/examples/agent-then-analysis/plugin.ts +89 -0
  16. package/assets/examples/coordinating-multiple-agents/README.md +56 -0
  17. package/assets/examples/coordinating-multiple-agents/input.json +10 -0
  18. package/assets/examples/coordinating-multiple-agents/norn.project.json +4 -0
  19. package/assets/examples/coordinating-multiple-agents/plugin.ts +102 -0
  20. package/assets/examples/coordinating-multiple-agents/queue-adapter.ts +52 -0
  21. package/assets/examples/coordinating-multiple-agents/work-queue.ts +153 -0
  22. package/assets/examples/minimal-workflow/README.md +71 -0
  23. package/assets/examples/minimal-workflow/norn.project.json +4 -0
  24. package/assets/examples/minimal-workflow/plugin.ts +29 -0
  25. package/assets/examples/shared-state/README.md +19 -0
  26. package/assets/examples/shared-state/input.json +1 -0
  27. package/assets/examples/shared-state/norn.project.json +4 -0
  28. package/assets/examples/shared-state/plugin.ts +47 -0
  29. package/assets/examples/worktree-development-loop/README.md +66 -0
  30. package/assets/examples/worktree-development-loop/index.ts +1 -0
  31. package/assets/examples/worktree-development-loop/manifest.ts +26 -0
  32. package/assets/examples/worktree-development-loop/norn.project.json +9 -0
  33. package/assets/examples/worktree-development-loop/plugin.ts +27 -0
  34. package/assets/examples/worktree-development-loop/shared/commands.ts +6 -0
  35. package/assets/examples/worktree-development-loop/state.ts +23 -0
  36. package/assets/examples/worktree-development-loop/workflows/development-loop/declaration.ts +8 -0
  37. package/assets/examples/worktree-development-loop/workflows/development-loop/execute.ts +18 -0
  38. package/assets/examples/worktree-development-loop/workflows/development-loop/index.ts +4 -0
  39. package/assets/examples/worktree-development-loop/workflows/development-loop/repository.ts +22 -0
  40. package/assets/examples/worktree-development-loop/workflows/development-loop/schema.ts +14 -0
  41. package/assets/examples/worktree-development-loop/workflows/implementation/declaration.ts +8 -0
  42. package/assets/examples/worktree-development-loop/workflows/implementation/execute.ts +54 -0
  43. package/assets/examples/worktree-development-loop/workflows/implementation/index.ts +3 -0
  44. package/assets/examples/worktree-development-loop/workflows/implementation/schema.ts +12 -0
  45. package/assets/examples/worktree-development-loop/workflows/planning/declaration.ts +8 -0
  46. package/assets/examples/worktree-development-loop/workflows/planning/execute.ts +28 -0
  47. package/assets/examples/worktree-development-loop/workflows/planning/index.ts +3 -0
  48. package/assets/examples/worktree-development-loop/workflows/planning/schema.ts +12 -0
  49. package/assets/examples/worktree-development-loop/workflows/review/declaration.ts +8 -0
  50. package/assets/examples/worktree-development-loop/workflows/review/execute.ts +53 -0
  51. package/assets/examples/worktree-development-loop/workflows/review/index.ts +10 -0
  52. package/assets/examples/worktree-development-loop/workflows/review/schema.ts +23 -0
  53. package/assets/examples/worktree-development-loop/workflows/review-router/declaration.ts +12 -0
  54. package/assets/examples/worktree-development-loop/workflows/review-router/execute.ts +51 -0
  55. package/assets/examples/worktree-development-loop/workflows/review-router/index.ts +3 -0
  56. package/assets/examples/worktree-development-loop/workflows/review-router/schema.ts +12 -0
  57. package/assets/package.json +1 -0
  58. package/assets/packages/cli/src/build-info.ts +36 -0
  59. package/assets/packages/cli/src/bun/cli.ts +16 -0
  60. package/assets/packages/cli/src/cli.ts +1135 -0
  61. package/assets/packages/cli/src/client.ts +167 -0
  62. package/assets/packages/cli/src/documentation-intro.ts +30 -0
  63. package/assets/packages/cli/src/documentation.ts +149 -0
  64. package/assets/packages/cli/src/generated-build-info.ts +12 -0
  65. package/assets/packages/cli/src/internal/agent-directory.ts +5 -0
  66. package/assets/packages/cli/src/internal/agent-response-tool.ts +96 -0
  67. package/assets/packages/cli/src/internal/agents.ts +365 -0
  68. package/assets/packages/cli/src/internal/artifacts.ts +26 -0
  69. package/assets/packages/cli/src/internal/commands.ts +180 -0
  70. package/assets/packages/cli/src/internal/documentation-bundle.ts +49 -0
  71. package/assets/packages/cli/src/internal/engine.ts +501 -0
  72. package/assets/packages/cli/src/internal/errors.ts +39 -0
  73. package/assets/packages/cli/src/internal/file-names.ts +3 -0
  74. package/assets/packages/cli/src/internal/launch-request.ts +94 -0
  75. package/assets/packages/cli/src/internal/logs.ts +41 -0
  76. package/assets/packages/cli/src/internal/metrics.ts +356 -0
  77. package/assets/packages/cli/src/internal/pi-assets.ts +95 -0
  78. package/assets/packages/cli/src/internal/resource-bindings.ts +35 -0
  79. package/assets/packages/cli/src/internal/run-lease.ts +158 -0
  80. package/assets/packages/cli/src/internal/run-log.ts +59 -0
  81. package/assets/packages/cli/src/internal/run-names.ts +36 -0
  82. package/assets/packages/cli/src/internal/run-resources.ts +23 -0
  83. package/assets/packages/cli/src/internal/run-state.ts +380 -0
  84. package/assets/packages/cli/src/internal/run-store.ts +323 -0
  85. package/assets/packages/cli/src/internal/run.ts +133 -0
  86. package/assets/packages/cli/src/internal/state-store.ts +75 -0
  87. package/assets/packages/cli/src/internal/usage.ts +70 -0
  88. package/assets/packages/cli/src/internal/workflow-registry.ts +176 -0
  89. package/assets/packages/cli/src/plugin-loader.ts +412 -0
  90. package/assets/packages/cli/src/resources.ts +67 -0
  91. package/assets/packages/core/src/agent-protocol.ts +1 -0
  92. package/assets/packages/core/src/atomic-files.ts +24 -0
  93. package/assets/packages/core/src/errors.ts +3 -0
  94. package/assets/packages/sdk/src/agent-resource-adapter.ts +11 -0
  95. package/assets/packages/sdk/src/api.ts +821 -0
  96. package/assets/packages/sdk/src/files.ts +136 -0
  97. package/assets/packages/sdk/src/index.ts +6 -0
  98. package/assets/packages/sdk/src/resources.ts +20 -0
  99. package/assets/packages/sdk/src/schema.ts +48 -0
  100. package/assets/packages/sdk/src/seer/config.ts +62 -0
  101. package/assets/packages/sdk/src/seer/index.ts +7 -0
  102. package/assets/packages/sdk/src/state-adapter.ts +75 -0
  103. package/assets/setup/providers.md +128 -0
  104. package/assets/setup/releases.md +76 -0
  105. package/assets/tests/workflow-ref.test.ts +113 -0
  106. package/bin/norn.mjs +10 -0
  107. package/dist/build-info.d.ts +30 -0
  108. package/dist/build-info.js +6 -0
  109. package/dist/cli.d.ts +2 -0
  110. package/dist/cli.js +1032 -0
  111. package/dist/client.d.ts +48 -0
  112. package/dist/client.js +118 -0
  113. package/dist/documentation-intro.d.ts +5 -0
  114. package/dist/documentation-intro.js +29 -0
  115. package/dist/documentation.d.ts +33 -0
  116. package/dist/documentation.js +132 -0
  117. package/dist/generated-build-info.d.ts +10 -0
  118. package/dist/generated-build-info.js +14 -0
  119. package/dist/internal/agent-directory.d.ts +4 -0
  120. package/dist/internal/agent-directory.js +8 -0
  121. package/dist/internal/agent-response-tool.d.ts +21 -0
  122. package/dist/internal/agent-response-tool.js +79 -0
  123. package/dist/internal/agents.d.ts +29 -0
  124. package/dist/internal/agents.js +336 -0
  125. package/dist/internal/artifacts.d.ts +10 -0
  126. package/dist/internal/artifacts.js +29 -0
  127. package/dist/internal/commands.d.ts +18 -0
  128. package/dist/internal/commands.js +147 -0
  129. package/dist/internal/documentation-bundle.d.ts +16 -0
  130. package/dist/internal/documentation-bundle.js +42 -0
  131. package/dist/internal/engine.d.ts +44 -0
  132. package/dist/internal/engine.js +399 -0
  133. package/dist/internal/errors.d.ts +14 -0
  134. package/dist/internal/errors.js +38 -0
  135. package/dist/internal/file-names.d.ts +1 -0
  136. package/dist/internal/file-names.js +7 -0
  137. package/dist/internal/launch-request.d.ts +33 -0
  138. package/dist/internal/launch-request.js +110 -0
  139. package/dist/internal/logs.d.ts +16 -0
  140. package/dist/internal/logs.js +38 -0
  141. package/dist/internal/metrics.d.ts +19 -0
  142. package/dist/internal/metrics.js +282 -0
  143. package/dist/internal/pi-assets.d.ts +13 -0
  144. package/dist/internal/pi-assets.js +94 -0
  145. package/dist/internal/resource-bindings.d.ts +13 -0
  146. package/dist/internal/resource-bindings.js +34 -0
  147. package/dist/internal/run-lease.d.ts +32 -0
  148. package/dist/internal/run-lease.js +166 -0
  149. package/dist/internal/run-log.d.ts +30 -0
  150. package/dist/internal/run-log.js +71 -0
  151. package/dist/internal/run-names.d.ts +1 -0
  152. package/dist/internal/run-names.js +144 -0
  153. package/dist/internal/run-resources.d.ts +6 -0
  154. package/dist/internal/run-resources.js +26 -0
  155. package/dist/internal/run-state.d.ts +95 -0
  156. package/dist/internal/run-state.js +323 -0
  157. package/dist/internal/run-store.d.ts +35 -0
  158. package/dist/internal/run-store.js +314 -0
  159. package/dist/internal/run.d.ts +51 -0
  160. package/dist/internal/run.js +101 -0
  161. package/dist/internal/state-store.d.ts +22 -0
  162. package/dist/internal/state-store.js +97 -0
  163. package/dist/internal/usage.d.ts +5 -0
  164. package/dist/internal/usage.js +70 -0
  165. package/dist/internal/workflow-registry.d.ts +35 -0
  166. package/dist/internal/workflow-registry.js +129 -0
  167. package/dist/plugin-loader.d.ts +55 -0
  168. package/dist/plugin-loader.js +353 -0
  169. package/dist/resources.d.ts +11 -0
  170. package/dist/resources.js +98 -0
  171. package/package.json +52 -0
@@ -0,0 +1,821 @@
1
+ import type { CreateAgentSessionOptions, EventBus, PromptOptions } from "@earendil-works/pi-coding-agent";
2
+ import { z } from "zod";
3
+ import type { NornResolvedSeerModeConfig } from "./seer/config.ts";
4
+
5
+ const WORKFLOW_DECLARATION_KIND = "norn.workflow";
6
+
7
+ export type MaybePromise<T> = T | Promise<T>;
8
+ export type NornDispose = () => void;
9
+
10
+ export type NornWorkflowAnyGate = {
11
+ readonly enabled: true;
12
+ readonly fields?: readonly string[];
13
+ };
14
+
15
+ export type NornWorkflowIsolationMode = "runWorkspace" | "project";
16
+
17
+ export type NornWorkflowIsolation<Mode extends NornWorkflowIsolationMode = NornWorkflowIsolationMode> = {
18
+ readonly mode: Mode;
19
+ };
20
+
21
+ declare const nornWorkflowRefParamsBrand: unique symbol;
22
+ declare const nornWorkflowRefForwardParamsBrand: unique symbol;
23
+
24
+ type NornWorkflowRefForwardParams = Record<string, unknown> & {
25
+ readonly [nornWorkflowRefForwardParamsBrand]: true;
26
+ };
27
+
28
+ export type NornWorkflowRef<ParamsSchema extends z.ZodType = z.ZodType, Id extends string = string, ForwardParams = unknown> = Id & {
29
+ readonly [nornWorkflowRefParamsBrand]: (params: z.input<ParamsSchema> & ForwardParams) => z.input<ParamsSchema> & ForwardParams;
30
+ };
31
+
32
+ export type NornWorkflowDeclaration<
33
+ Id extends string = string,
34
+ ParamsSchema extends z.ZodType = z.ZodType,
35
+ IsolationMode extends NornWorkflowIsolationMode = NornWorkflowIsolationMode,
36
+ > = {
37
+ readonly kind: typeof WORKFLOW_DECLARATION_KIND;
38
+ readonly id: NornWorkflowRef<ParamsSchema, Id>;
39
+ readonly isEntrypoint: boolean;
40
+ readonly instructions?: string;
41
+ readonly params: ParamsSchema;
42
+ readonly gate?: NornWorkflowAnyGate;
43
+ readonly isolation: NornWorkflowIsolation<IsolationMode>;
44
+ };
45
+
46
+ export type NornAnyWorkflowDeclaration = NornWorkflowDeclaration<string, z.ZodType<any, any>>;
47
+ export type NornWorkflowTarget<ParamsSchema extends z.ZodType = z.ZodType> = NornWorkflowDeclaration<string, ParamsSchema> | NornWorkflowRef<ParamsSchema>;
48
+ export type NornWorkflowRefSchemaInput<ParamsSchema extends z.ZodType = z.ZodType> = string | {
49
+ readonly id: NornWorkflowRef<ParamsSchema>;
50
+ readonly workflow?: never;
51
+ readonly forwardParams?: never;
52
+ };
53
+ export type NornWorkflowRefSchemaOptions<ParamsSchema extends z.ZodType = z.ZodType> = {
54
+ readonly params?: ParamsSchema;
55
+ };
56
+ export type NornWorkflowRefInput<ParamsSchema extends z.ZodType> =
57
+ | NornWorkflowRefSchemaInput<ParamsSchema>
58
+ | {
59
+ readonly workflow: NornWorkflowRefSchemaInput<z.ZodType<any, any>>;
60
+ readonly forwardParams: Record<string, unknown>;
61
+ };
62
+ export type NornWorkflowRefOutput<ParamsSchema extends z.ZodType> = {
63
+ readonly workflow: NornWorkflowRef<ParamsSchema, string, NornWorkflowRefForwardParams>;
64
+ readonly forwardParams: NornWorkflowRefForwardParams;
65
+ };
66
+
67
+ export type NornWorkflowParamsInput<TWorkflow extends NornAnyWorkflowDeclaration> = z.input<TWorkflow["params"]>;
68
+ export type NornWorkflowParams<TWorkflow extends NornAnyWorkflowDeclaration> = z.output<TWorkflow["params"]>;
69
+ export type NornWorkflowTargetParamsInput<TWorkflow extends NornWorkflowTarget<any>> = TWorkflow extends NornWorkflowDeclaration<string, infer ParamsSchema>
70
+ ? z.input<ParamsSchema>
71
+ : TWorkflow extends NornWorkflowRef<infer ParamsSchema, string, infer ForwardParams>
72
+ ? z.input<ParamsSchema> & ForwardParams
73
+ : never;
74
+
75
+ export type NornWorkflowGate<ParamsSchema extends z.ZodType> = unknown extends z.input<ParamsSchema>
76
+ ? NornWorkflowAnyGate
77
+ : z.input<ParamsSchema> extends Record<string, unknown>
78
+ ? {
79
+ readonly enabled: true;
80
+ readonly fields?: readonly Extract<keyof z.input<ParamsSchema>, string>[];
81
+ }
82
+ : {
83
+ readonly enabled: true;
84
+ readonly fields?: never;
85
+ };
86
+
87
+ type NornWorkflowInstructions =
88
+ | { readonly isEntrypoint: true; readonly instructions: string }
89
+ | { readonly isEntrypoint: false; readonly instructions?: string };
90
+
91
+ export type NornWorkflowDefinition<
92
+ Id extends string | undefined = string | undefined,
93
+ ParamsSchema extends z.ZodType = z.ZodType,
94
+ IsolationMode extends NornWorkflowIsolationMode = NornWorkflowIsolationMode,
95
+ > = {
96
+ readonly id?: Id;
97
+ readonly params: ParamsSchema;
98
+ readonly gate?: NornWorkflowGate<ParamsSchema>;
99
+ readonly isolation?: NornWorkflowIsolation<IsolationMode>;
100
+ } & NornWorkflowInstructions;
101
+
102
+ export type NornAnyWorkflowDefinition = {
103
+ readonly id?: string;
104
+ readonly params: z.ZodType;
105
+ readonly gate?: NornWorkflowAnyGate;
106
+ readonly isolation?: NornWorkflowIsolation;
107
+ } & NornWorkflowInstructions;
108
+
109
+ export type NornWorkflowStateDefinition<T = unknown, Id extends string = string> = {
110
+ readonly id: Id;
111
+ readonly description?: string;
112
+ readonly schema: z.ZodType<T>;
113
+ };
114
+
115
+ export type NornWorkflowStateDefinitionInput<T = unknown, Id extends string | undefined = string | undefined> = {
116
+ readonly id?: Id;
117
+ readonly description?: string;
118
+ readonly schema: z.ZodType<T>;
119
+ };
120
+
121
+ export type NornWorkflowPluginWorkflows = Record<string, NornAnyWorkflowDefinition>;
122
+ export type NornWorkflowPluginStateTree = { readonly [key: string]: NornWorkflowPluginStateTreeNode };
123
+ export type NornWorkflowPluginStateTreeNode = z.ZodType | NornWorkflowStateDefinitionInput | NornWorkflowPluginStateTree;
124
+
125
+ type JoinPath<Head extends string, Parts extends readonly string[]> = Parts extends readonly []
126
+ ? Head
127
+ : Parts extends readonly [infer First extends string, ...infer Rest extends string[]]
128
+ ? JoinPath<`${Head}.${First}`, Rest>
129
+ : string;
130
+
131
+ type NornInvalidGateFields<TWorkflow> = TWorkflow extends { readonly params: infer ParamsSchema extends z.ZodType; readonly gate: { readonly fields: infer Fields extends readonly string[] } }
132
+ ? Exclude<Fields[number], Extract<keyof z.input<ParamsSchema>, string>>
133
+ : never;
134
+
135
+ type NornValidatedWorkflowGate<TWorkflow> = [NornInvalidGateFields<TWorkflow>] extends [never]
136
+ ? unknown
137
+ : { readonly gate: { readonly fields: readonly Extract<keyof z.input<TWorkflow extends { readonly params: infer ParamsSchema extends z.ZodType } ? ParamsSchema : z.ZodType>, string>[] } };
138
+
139
+ export type NornValidatedWorkflowGates<Workflows> = {
140
+ readonly [Key in keyof Workflows]: NornValidatedWorkflowGate<Workflows[Key]>;
141
+ };
142
+
143
+ export type NornQualifiedPluginWorkflow<
144
+ PluginId extends string,
145
+ WorkflowKey extends string,
146
+ TWorkflow extends NornAnyWorkflowDefinition,
147
+ > = TWorkflow extends { readonly params: infer ParamsSchema extends z.ZodType }
148
+ ? NornWorkflowDeclaration<
149
+ TWorkflow extends { readonly id: infer ExplicitId extends string } ? ExplicitId : `${PluginId}.${WorkflowKey}`,
150
+ ParamsSchema,
151
+ TWorkflow extends { readonly isolation: { readonly mode: infer IsolationMode extends NornWorkflowIsolationMode } } ? IsolationMode : "runWorkspace"
152
+ >
153
+ : never;
154
+
155
+ export type NornQualifiedPluginWorkflows<PluginId extends string, Workflows extends NornWorkflowPluginWorkflows> = {
156
+ readonly [Key in keyof Workflows]: NornQualifiedPluginWorkflow<PluginId, Key & string, Workflows[Key]>;
157
+ };
158
+
159
+ export type NornQualifiedPluginStates<PluginId extends string, States, Path extends readonly string[] = []> = {
160
+ readonly [Key in keyof States]: States[Key] extends z.ZodType
161
+ ? NornWorkflowStateDefinition<z.output<States[Key]>, JoinPath<PluginId, [...Path, Key & string]>>
162
+ : States[Key] extends NornWorkflowStateDefinitionInput<infer Value>
163
+ ? NornWorkflowStateDefinition<
164
+ Value,
165
+ States[Key] extends { readonly id: infer ExplicitId extends string } ? ExplicitId : JoinPath<PluginId, [...Path, Key & string]>
166
+ >
167
+ : States[Key] extends NornWorkflowPluginStateTree
168
+ ? NornQualifiedPluginStates<PluginId, States[Key], [...Path, Key & string]>
169
+ : never;
170
+ };
171
+
172
+ export type NornWorkflowPluginManifest<
173
+ PluginId extends string = string,
174
+ ConfigSchema extends z.ZodType | undefined = z.ZodType | undefined,
175
+ Workflows extends Record<string, NornAnyWorkflowDeclaration> = Record<string, NornAnyWorkflowDeclaration>,
176
+ States = undefined,
177
+ > = {
178
+ readonly id: PluginId;
179
+ readonly config?: ConfigSchema;
180
+ readonly workflows: Workflows;
181
+ readonly states: States;
182
+ };
183
+
184
+ export type NornAnyWorkflowPluginManifest = NornWorkflowPluginManifest<string, z.ZodType | undefined, Record<string, NornAnyWorkflowDeclaration>, unknown>;
185
+
186
+ export type NornWorkflowPluginConfigSchema<TManifest extends NornAnyWorkflowPluginManifest> = TManifest extends { readonly config?: infer ConfigSchema extends z.ZodType | undefined }
187
+ ? ConfigSchema
188
+ : undefined;
189
+
190
+ export type NornWorkflowPluginConfig<TManifest extends NornAnyWorkflowPluginManifest> = NonNullable<NornWorkflowPluginConfigSchema<TManifest>> extends z.ZodType
191
+ ? z.output<NonNullable<NornWorkflowPluginConfigSchema<TManifest>>>
192
+ : undefined;
193
+
194
+ export type NornDefinePluginManifestInput<
195
+ PluginId extends string,
196
+ ConfigSchema extends z.ZodType | undefined,
197
+ Workflows extends NornWorkflowPluginWorkflows,
198
+ States extends NornWorkflowPluginStateTree | undefined,
199
+ > = {
200
+ readonly id: PluginId;
201
+ readonly config?: ConfigSchema;
202
+ readonly workflows: Workflows & NornValidatedWorkflowGates<Workflows>;
203
+ readonly states?: States;
204
+ };
205
+
206
+ export function definePluginManifest<
207
+ const PluginId extends string,
208
+ const ConfigSchema extends z.ZodType | undefined = undefined,
209
+ const Workflows extends NornWorkflowPluginWorkflows = NornWorkflowPluginWorkflows,
210
+ const States extends NornWorkflowPluginStateTree | undefined = undefined,
211
+ >(
212
+ input: NornDefinePluginManifestInput<PluginId, ConfigSchema, Workflows, States>,
213
+ ): NornWorkflowPluginManifest<
214
+ PluginId,
215
+ ConfigSchema,
216
+ NornQualifiedPluginWorkflows<PluginId, Workflows>,
217
+ States extends NornWorkflowPluginStateTree ? NornQualifiedPluginStates<PluginId, States> : undefined
218
+ > {
219
+ assertLocalDeclarationId(input.id, "plugin");
220
+ const declaredIds = new Set<string>();
221
+ const workflows = Object.fromEntries(
222
+ Object.entries(input.workflows).map(([key, workflow]) => [key, qualifyWorkflow(input.id, key, workflow, declaredIds)]),
223
+ ) as NornQualifiedPluginWorkflows<PluginId, Workflows>;
224
+ return {
225
+ id: input.id,
226
+ config: input.config,
227
+ workflows,
228
+ states: qualifyStateTree(input.id, input.states, [], declaredIds) as States extends NornWorkflowPluginStateTree ? NornQualifiedPluginStates<PluginId, States> : undefined,
229
+ };
230
+ }
231
+
232
+ export type NornRunNext = {
233
+ readonly type: "next";
234
+ readonly workflowId: string;
235
+ readonly params: unknown;
236
+ };
237
+
238
+ export type NornRunOutcomeMetadata = {
239
+ readonly summary?: string;
240
+ readonly artifacts?: Record<string, NornArtifactRef>;
241
+ readonly logs?: Record<string, NornLogRef>;
242
+ readonly data?: Record<string, unknown>;
243
+ };
244
+
245
+ export type NornRunComplete = {
246
+ readonly type: "complete";
247
+ readonly metadata?: NornRunOutcomeMetadata;
248
+ };
249
+
250
+ export type NornRunFail = {
251
+ readonly type: "fail";
252
+ readonly metadata: NornRunOutcomeMetadata & { readonly summary: string };
253
+ };
254
+
255
+ export type NornWorkflowExecutionResult = NornRunNext | NornRunComplete | NornRunFail;
256
+
257
+ export type NornRunFor<TWorkflow extends NornAnyWorkflowDeclaration> = TWorkflow extends { readonly isolation: { readonly mode: "project" } }
258
+ ? NornProjectRun
259
+ : NornRun;
260
+
261
+ export type NornWorkflowGateImplementation<TWorkflow extends NornAnyWorkflowDeclaration, TConfig> = {
262
+ describe(
263
+ run: NornRunFor<TWorkflow>,
264
+ params: NornWorkflowParams<TWorkflow>,
265
+ config: TConfig,
266
+ ): MaybePromise<string>;
267
+ };
268
+
269
+ export type NornWorkflowImplementation<TWorkflow extends NornAnyWorkflowDeclaration, TConfig = unknown> = {
270
+ readonly gate?: NornWorkflowGateImplementation<TWorkflow, TConfig>;
271
+ execute(
272
+ run: NornRunFor<TWorkflow>,
273
+ params: NornWorkflowParams<TWorkflow>,
274
+ config: TConfig,
275
+ ): MaybePromise<NornWorkflowExecutionResult>;
276
+ };
277
+
278
+ export type NornRunStartOptions = {
279
+ readonly id?: string;
280
+ readonly name?: string;
281
+ readonly configOverride?: unknown;
282
+ };
283
+
284
+ export type NornStartedRunResult = {
285
+ readonly status: "running";
286
+ readonly id: string;
287
+ readonly name: string;
288
+ readonly path: string;
289
+ readonly workspace: string;
290
+ readonly cwd: string;
291
+ readonly workflowId: string;
292
+ };
293
+
294
+ export type NornCompletedRunResult = {
295
+ readonly status: "completed";
296
+ readonly id: string;
297
+ readonly name: string;
298
+ readonly workspace: string;
299
+ readonly cwd: string;
300
+ readonly workflowId: string;
301
+ readonly metadata?: NornRunOutcomeMetadata;
302
+ };
303
+
304
+ export type NornFailedRunResult = {
305
+ readonly status: "failed";
306
+ readonly id: string;
307
+ readonly name: string;
308
+ readonly workspace: string;
309
+ readonly cwd: string;
310
+ readonly workflowId: string;
311
+ readonly metadata: NornRunOutcomeMetadata & { readonly summary: string };
312
+ };
313
+
314
+ export type NornStoppedRunResult = {
315
+ readonly status: "stopped";
316
+ readonly id: string;
317
+ readonly name: string;
318
+ readonly workspace: string;
319
+ readonly cwd: string;
320
+ readonly workflowId: string;
321
+ };
322
+
323
+ export type NornRunInterruption = {
324
+ readonly workflowId: string;
325
+ readonly params: unknown;
326
+ readonly description: string;
327
+ readonly fields?: readonly string[];
328
+ };
329
+
330
+ export type NornInterruptedRunResult = {
331
+ readonly status: "interrupted";
332
+ readonly id: string;
333
+ readonly name: string;
334
+ readonly workspace: string;
335
+ readonly cwd: string;
336
+ readonly workflowId: string;
337
+ readonly interruption: NornRunInterruption;
338
+ };
339
+
340
+ export type NornRunResult = NornStartedRunResult | NornCompletedRunResult | NornFailedRunResult | NornStoppedRunResult | NornInterruptedRunResult;
341
+
342
+ export type NornRunStatus = "running" | "interrupted" | "stopped" | "pendingResume" | "completed" | "failed";
343
+ export type NornRunHealth = "healthy" | "unhealthy";
344
+
345
+ export type NornRunOutcomeInfo = {
346
+ readonly workflowId: string;
347
+ readonly completedAt: string;
348
+ readonly status: "completed" | "failed";
349
+ readonly metadata?: NornRunOutcomeMetadata;
350
+ };
351
+
352
+ export type NornRunFailureInfo = {
353
+ readonly workflowId: string;
354
+ readonly error: string;
355
+ readonly metadata?: NornRunOutcomeMetadata;
356
+ readonly failedAt: string;
357
+ };
358
+
359
+ export type NornRunInfo = {
360
+ readonly version: number;
361
+ readonly id: string;
362
+ readonly name: string;
363
+ readonly path: string;
364
+ readonly entrypointWorkflowId: string;
365
+ readonly currentWorkflowId?: string;
366
+ readonly status: NornRunStatus;
367
+ readonly health: NornRunHealth;
368
+ readonly interruption?: NornRunInterruption;
369
+ readonly outcome?: NornRunOutcomeInfo;
370
+ readonly failed?: NornRunFailureInfo;
371
+ readonly startedAt: string;
372
+ readonly updatedAt: string;
373
+ };
374
+
375
+ export type DeletedNornRunInfo = {
376
+ readonly id: string;
377
+ readonly name: string;
378
+ readonly path: string;
379
+ };
380
+
381
+ export type NornRunCheckpoint = {
382
+ readonly id: string;
383
+ readonly path: string;
384
+ readonly index: number;
385
+ readonly message: string;
386
+ readonly createdAt: string;
387
+ };
388
+
389
+ export type NornWorkflowStateReader = {
390
+ get<T>(state: NornWorkflowStateDefinition<T>): Promise<T>;
391
+ getOptional<T>(state: NornWorkflowStateDefinition<T>): Promise<T | undefined>;
392
+ };
393
+
394
+ export type NornWorkflowState = NornWorkflowStateReader & {
395
+ set<T>(state: NornWorkflowStateDefinition<T>, value: T): Promise<void>;
396
+ };
397
+
398
+ export type NornWorkflowPluginContext = {
399
+ readonly cwd: string;
400
+ readonly state: NornWorkflowState;
401
+ };
402
+
403
+ export type NornWorkflowPluginImplementation<TManifest extends NornAnyWorkflowPluginManifest> = {
404
+ readonly workflows: {
405
+ readonly [Key in keyof TManifest["workflows"]]: NornWorkflowImplementation<TManifest["workflows"][Key], NornWorkflowPluginConfig<TManifest>>;
406
+ };
407
+ };
408
+
409
+ export type NornWorkflowPluginImplementationFactory<TManifest extends NornAnyWorkflowPluginManifest> = (
410
+ context: NornWorkflowPluginContext,
411
+ ) => NornWorkflowPluginImplementation<TManifest>;
412
+
413
+ export type NornWorkflowPluginImplementationInput<TManifest extends NornAnyWorkflowPluginManifest> =
414
+ | NornWorkflowPluginImplementation<TManifest>
415
+ | NornWorkflowPluginImplementationFactory<TManifest>;
416
+
417
+ export type NornWorkflowPlugin<TManifest extends NornAnyWorkflowPluginManifest = NornAnyWorkflowPluginManifest> = {
418
+ readonly manifest: TManifest;
419
+ readonly implementation: NornWorkflowPluginImplementationInput<TManifest>;
420
+ };
421
+
422
+ export function definePlugin<TManifest extends NornAnyWorkflowPluginManifest>(
423
+ manifest: TManifest,
424
+ implementation: NornWorkflowPluginImplementationInput<TManifest>,
425
+ ): NornWorkflowPlugin<TManifest> {
426
+ return { manifest, implementation };
427
+ }
428
+
429
+ export type NornCommandRunInput = {
430
+ readonly label: string;
431
+ readonly command: string | readonly [string, ...string[]];
432
+ readonly cwd?: string;
433
+ readonly env?: Record<string, string>;
434
+ readonly timeoutMs?: number;
435
+ };
436
+
437
+ export const artifactRefSchema = z.object({
438
+ path: z.string(),
439
+ });
440
+
441
+ export type NornArtifactRef = z.output<typeof artifactRefSchema>;
442
+
443
+ const emptyWorkflowRefParamsSchema = z.object({});
444
+
445
+ export function workflowRefSchema(): z.ZodType<
446
+ NornWorkflowRefOutput<typeof emptyWorkflowRefParamsSchema>,
447
+ NornWorkflowRefInput<typeof emptyWorkflowRefParamsSchema>
448
+ >;
449
+ export function workflowRefSchema(options: {
450
+ readonly params?: undefined;
451
+ }): z.ZodType<
452
+ NornWorkflowRefOutput<typeof emptyWorkflowRefParamsSchema>,
453
+ NornWorkflowRefInput<typeof emptyWorkflowRefParamsSchema>
454
+ >;
455
+ export function workflowRefSchema<ParamsSchema extends z.ZodType>(options: NornWorkflowRefSchemaOptions<ParamsSchema>): z.ZodType<
456
+ NornWorkflowRefOutput<ParamsSchema>,
457
+ NornWorkflowRefInput<ParamsSchema>
458
+ >;
459
+ export function workflowRefSchema(options?: NornWorkflowRefSchemaOptions): z.ZodType {
460
+ const contributedParams = options?.params ?? emptyWorkflowRefParamsSchema;
461
+ const targetSchema = z.union([
462
+ z.string().min(1),
463
+ z.object({ id: z.string().min(1) }),
464
+ ]).transform((target) => typeof target === "string" ? target : target.id);
465
+ return z.union([
466
+ targetSchema,
467
+ z.object({ workflow: targetSchema, forwardParams: z.record(z.string(), z.unknown()) }),
468
+ ]).transform((reference) => typeof reference === "string"
469
+ ? { workflow: reference, forwardParams: {} }
470
+ : reference).meta({
471
+ "x-norn-workflow-ref": {
472
+ get contributedParamsSchema() {
473
+ return z.toJSONSchema(contributedParams, { io: "input" });
474
+ },
475
+ },
476
+ });
477
+ }
478
+
479
+ export type NornLogRef = {
480
+ readonly id: string;
481
+ };
482
+
483
+ export type NornCommandRunResult = {
484
+ readonly label: string;
485
+ readonly command: string | readonly [string, ...string[]];
486
+ readonly cwd: string;
487
+ readonly exitCode: number | null;
488
+ readonly stdoutTail: string;
489
+ readonly stderrTail: string;
490
+ readonly killed: boolean;
491
+ readonly stdoutLog: NornLogRef;
492
+ readonly stderrLog: NornLogRef;
493
+ };
494
+
495
+ export type NornAgentBeforeSessionStartContext = {
496
+ readonly events: EventBus;
497
+ };
498
+
499
+ export type NornAgentCreateSessionInput = {
500
+ readonly resourceAdapters?: readonly import("./agent-resource-adapter.ts").NornAgentResourceAdapter[];
501
+ readonly label: string;
502
+ readonly cwd?: string;
503
+ readonly tools?: string[];
504
+ readonly beforeSessionStart?: (context: NornAgentBeforeSessionStartContext) => MaybePromise<void>;
505
+ readonly model?: CreateAgentSessionOptions["model"];
506
+ readonly thinkingLevel?: CreateAgentSessionOptions["thinkingLevel"];
507
+ readonly systemPrompt?: string;
508
+ readonly appendSystemPrompt?: readonly string[];
509
+ };
510
+
511
+ export type NornAgentPromptInput<ResponseSchema extends z.ZodType> = {
512
+ readonly prompt: string;
513
+ readonly response: ResponseSchema;
514
+ readonly maxAttempts?: number;
515
+ readonly options?: PromptOptions;
516
+ };
517
+
518
+ export type NornAgentSinglePromptInput<ResponseSchema extends z.ZodType> = NornAgentCreateSessionInput & NornAgentPromptInput<ResponseSchema>;
519
+
520
+ export type NornAgentSessionEvents = EventBus;
521
+
522
+ export type NornAgentUsageCost = {
523
+ readonly input: number;
524
+ readonly output: number;
525
+ readonly cacheRead: number;
526
+ readonly cacheWrite: number;
527
+ readonly total: number;
528
+ };
529
+
530
+ export type NornAgentUsage = {
531
+ readonly input: number;
532
+ readonly output: number;
533
+ readonly cacheRead: number;
534
+ readonly cacheWrite: number;
535
+ readonly reasoning?: number;
536
+ readonly totalTokens: number;
537
+ readonly cost: NornAgentUsageCost;
538
+ };
539
+
540
+ export type NornAgentMetrics = {
541
+ readonly index: number;
542
+ readonly label: string;
543
+ readonly status: "running" | "completed" | "failed";
544
+ readonly startedAt: string;
545
+ readonly endedAt?: string;
546
+ readonly wallMs: number;
547
+ readonly attempts?: number;
548
+ readonly usage: NornAgentUsage;
549
+ };
550
+
551
+ export type NornCommandMetrics = {
552
+ readonly index: number;
553
+ readonly label: string;
554
+ readonly status: "running" | "completed" | "failed";
555
+ readonly startedAt: string;
556
+ readonly endedAt?: string;
557
+ readonly wallMs: number;
558
+ readonly exitCode?: number | null;
559
+ readonly killed?: boolean;
560
+ };
561
+
562
+ export type NornWorkflowMetrics = {
563
+ readonly index: number;
564
+ readonly workflowId: string;
565
+ readonly status: "running" | "completed" | "failed" | "transitioned";
566
+ readonly startedAt: string;
567
+ readonly endedAt?: string;
568
+ readonly wallMs: number;
569
+ readonly ownMs: number;
570
+ readonly agentsMs: number;
571
+ readonly commandsMs: number;
572
+ readonly agentUsage: NornAgentUsage;
573
+ readonly agents: readonly NornAgentMetrics[];
574
+ readonly commands: readonly NornCommandMetrics[];
575
+ };
576
+
577
+ export type NornRunMetrics = {
578
+ readonly status: NornRunStatus;
579
+ readonly startedAt: string;
580
+ readonly endedAt?: string;
581
+ readonly wallMs: number;
582
+ readonly activeMs: number;
583
+ readonly gateWaitMs: number;
584
+ readonly workflowsMs: number;
585
+ readonly workflowOwnMs: number;
586
+ readonly agentsMs: number;
587
+ readonly commandsMs: number;
588
+ readonly agentUsage: NornAgentUsage;
589
+ readonly workflows: readonly NornWorkflowMetrics[];
590
+ };
591
+
592
+ export type NornAgentRunRawAttempt = {
593
+ readonly attempt: number;
594
+ readonly text: string;
595
+ readonly messages: unknown[];
596
+ readonly responseToolCalled: boolean;
597
+ readonly usage: NornAgentUsage;
598
+ readonly toolResponse?: unknown;
599
+ readonly sessionFile?: string;
600
+ readonly error?: string;
601
+ };
602
+
603
+ export type NornAgentRunResult<ResponseSchema extends z.ZodType> = {
604
+ readonly label: string;
605
+ readonly cwd: string;
606
+ readonly response: z.output<ResponseSchema>;
607
+ readonly usage: NornAgentUsage;
608
+ readonly raw: {
609
+ readonly text: string;
610
+ readonly messages: unknown[];
611
+ readonly responseToolCalled: boolean;
612
+ readonly usage: NornAgentUsage;
613
+ readonly toolResponse?: unknown;
614
+ readonly sessionFile?: string;
615
+ readonly attempts: readonly NornAgentRunRawAttempt[];
616
+ };
617
+ };
618
+
619
+ export type NornAgentSession = {
620
+ readonly label: string;
621
+ readonly cwd: string;
622
+ readonly events: NornAgentSessionEvents;
623
+ prompt<ResponseSchema extends z.ZodType>(input: NornAgentPromptInput<ResponseSchema>): Promise<z.output<ResponseSchema>>;
624
+ dispose(): Promise<void>;
625
+ };
626
+
627
+ export type NornRun = NornRunBase;
628
+
629
+ export type NornProjectRun = NornRunBase & {
630
+ projectRoot: string;
631
+ projectPath(relativePath: string): string;
632
+ };
633
+
634
+ type NornRunBase = {
635
+ id: string;
636
+ workspace: string;
637
+ cwd: string;
638
+ path(relativePath: string): string;
639
+ next<TWorkflow extends NornWorkflowTarget<any>>(workflow: TWorkflow, params: NornWorkflowTargetParamsInput<TWorkflow>): NornRunNext;
640
+ complete(metadata?: NornRunOutcomeMetadata): NornRunComplete;
641
+ fail(metadata: NornRunOutcomeMetadata & { readonly summary: string }): NornRunFail;
642
+ resources: import("./resources.ts").NornResources;
643
+ state: NornWorkflowState;
644
+ artifacts: {
645
+ write(path: string, content: string): Promise<NornArtifactRef>;
646
+ read(ref: NornArtifactRef): Promise<string>;
647
+ };
648
+ logs: {
649
+ read(log: NornLogRef): Promise<string>;
650
+ };
651
+ commands: {
652
+ run(input: NornCommandRunInput): Promise<NornCommandRunResult>;
653
+ };
654
+ agents: {
655
+ createSession(input: NornAgentCreateSessionInput): Promise<NornAgentSession>;
656
+ prompt<ResponseSchema extends z.ZodType>(input: NornAgentSinglePromptInput<ResponseSchema>): Promise<z.output<ResponseSchema>>;
657
+ };
658
+ };
659
+
660
+ export type NornWorkflowPluginInfo = {
661
+ readonly id: string;
662
+ readonly path?: string;
663
+ readonly configPath?: string;
664
+ };
665
+
666
+ export type NornJsonSchema = Record<string, unknown>;
667
+
668
+ export type NornWorkflowGateInfo = {
669
+ readonly enabled: true;
670
+ readonly fields?: readonly string[];
671
+ };
672
+
673
+ export type NornRegisteredWorkflowInfo = {
674
+ readonly id: string;
675
+ readonly instructions?: string;
676
+ readonly isEntrypoint: boolean;
677
+ readonly isolation: NornWorkflowIsolation;
678
+ readonly plugin?: NornWorkflowPluginInfo;
679
+ };
680
+
681
+ export type NornInspectedWorkflowInfo = NornRegisteredWorkflowInfo & {
682
+ readonly paramsSchema: NornJsonSchema;
683
+ readonly gate: NornWorkflowGateInfo | null;
684
+ };
685
+
686
+ export type NornPluginDiagnostic = {
687
+ readonly configPath: string;
688
+ readonly pluginPath: string;
689
+ readonly pluginId: string | null;
690
+ readonly workflowId: string | null;
691
+ readonly stage: "import" | "declaration" | "config" | "implementation" | "duplicate" | "schema";
692
+ readonly message: string;
693
+ readonly issues: readonly { readonly path: readonly (string | number)[]; readonly code: string; readonly message: string }[];
694
+ };
695
+
696
+ export type NornProjectLoadStatus = {
697
+ readonly isComplete: boolean;
698
+ readonly diagnostics: readonly NornPluginDiagnostic[];
699
+ };
700
+
701
+ export type NornWorkflowCatalogInfo = NornProjectLoadStatus & {
702
+ readonly workflows: readonly NornRegisteredWorkflowInfo[];
703
+ };
704
+
705
+ export type NornWorkflowInspection = NornProjectLoadStatus & {
706
+ readonly workflow: NornInspectedWorkflowInfo | null;
707
+ };
708
+
709
+ export type NornProjectInspection = NornProjectLoadStatus & {
710
+ readonly project: NornProjectInfo;
711
+ };
712
+
713
+ export type NornProjectPluginInfo = NornWorkflowPluginInfo & {
714
+ readonly configSchema: NornJsonSchema | null;
715
+ readonly config: unknown;
716
+ };
717
+
718
+ export type NornProjectInfo = {
719
+ readonly cwd: string;
720
+ readonly projectPath: string;
721
+ readonly projectRoot: string;
722
+ readonly configPath: string;
723
+ readonly configRoot: string;
724
+ readonly configFiles: readonly string[];
725
+ readonly plugins: readonly NornProjectPluginInfo[];
726
+ readonly seerMode: NornResolvedSeerModeConfig | null;
727
+ };
728
+
729
+ function assertLocalDeclarationId(id: string, kind: "plugin" | "workflow" | "state"): void {
730
+ if (id.length === 0) throw new Error(`Workflow ${kind} id must not be empty`);
731
+ if (id.includes(".")) throw new Error(`Workflow ${kind} id must not contain dots: ${id}`);
732
+ }
733
+
734
+ function resolveDeclarationId(pluginId: string, path: readonly string[], explicitId: string | undefined, kind: "workflow" | "state", declaredIds: Set<string>): string {
735
+ for (const segment of path) assertLocalDeclarationId(segment, kind);
736
+ const id = explicitId ?? [pluginId, ...path].join(".");
737
+ if (explicitId !== undefined) assertPluginQualifiedId(pluginId, explicitId, kind);
738
+ if (declaredIds.has(id)) throw new Error(`Duplicate Norn ${kind} id: ${id}`);
739
+ declaredIds.add(id);
740
+ return id;
741
+ }
742
+
743
+ function assertPluginQualifiedId(pluginId: string, id: string, kind: "workflow" | "state"): void {
744
+ if (!id.startsWith(`${pluginId}.`)) throw new Error(`Explicit Norn ${kind} id must start with ${pluginId}.: ${id}`);
745
+ if (id.length === pluginId.length + 1) throw new Error(`Explicit Norn ${kind} id must not be empty after ${pluginId}.`);
746
+ }
747
+
748
+ function qualifyWorkflow<PluginId extends string, TWorkflow extends NornAnyWorkflowDefinition>(
749
+ pluginId: PluginId,
750
+ key: string,
751
+ workflow: TWorkflow,
752
+ declaredIds: Set<string>,
753
+ ): NornQualifiedPluginWorkflow<PluginId, string, TWorkflow> {
754
+ const id = resolveDeclarationId(pluginId, [key], workflow.id, "workflow", declaredIds);
755
+ return { kind: WORKFLOW_DECLARATION_KIND, ...workflow, id, isolation: workflow.isolation ?? { mode: "runWorkspace" } } as unknown as NornQualifiedPluginWorkflow<PluginId, string, TWorkflow>;
756
+ }
757
+
758
+ function qualifyStateTree(pluginId: string, node: NornWorkflowPluginStateTreeNode | undefined, path: readonly string[], declaredIds: Set<string>): unknown {
759
+ if (!node) return undefined;
760
+ if (isZodSchema(node)) return { id: resolveDeclarationId(pluginId, path, undefined, "state", declaredIds), schema: node };
761
+ if (isWorkflowStateDefinitionInput(node)) {
762
+ return { ...node, id: resolveDeclarationId(pluginId, path, node.id, "state", declaredIds) };
763
+ }
764
+ return Object.fromEntries(Object.entries(node).map(([key, child]) => [key, qualifyStateTree(pluginId, child, [...path, key], declaredIds)]));
765
+ }
766
+
767
+ export function isWorkflowDeclaration(value: unknown): value is NornAnyWorkflowDeclaration {
768
+ if (!value || typeof value !== "object") return false;
769
+ const candidate = value as { kind?: unknown; id?: unknown; instructions?: unknown; isEntrypoint?: unknown; params?: unknown; isolation?: { mode?: unknown } };
770
+ return (
771
+ candidate.kind === WORKFLOW_DECLARATION_KIND &&
772
+ typeof candidate.id === "string" &&
773
+ candidate.id.length > 0 &&
774
+ (candidate.instructions === undefined || typeof candidate.instructions === "string") &&
775
+ typeof candidate.isEntrypoint === "boolean" &&
776
+ Boolean(candidate.params) &&
777
+ (candidate.isolation?.mode === "runWorkspace" || candidate.isolation?.mode === "project")
778
+ );
779
+ }
780
+
781
+ function isWorkflowStateDefinitionInput(value: unknown): value is NornWorkflowStateDefinitionInput<unknown> {
782
+ if (!value || typeof value !== "object") return false;
783
+ const candidate = value as { id?: unknown; schema?: unknown };
784
+ return (candidate.id === undefined || typeof candidate.id === "string") && isZodSchema(candidate.schema);
785
+ }
786
+
787
+ function isZodSchema(value: unknown): value is z.ZodType {
788
+ return Boolean(value && typeof value === "object" && typeof (value as { safeParse?: unknown }).safeParse === "function");
789
+ }
790
+
791
+ export function isWorkflowPlugin(value: unknown): value is NornWorkflowPlugin {
792
+ if (!value || typeof value !== "object") return false;
793
+ const candidate = value as { manifest?: unknown; implementation?: unknown };
794
+ return isWorkflowPluginManifest(candidate.manifest) && Boolean(candidate.implementation);
795
+ }
796
+
797
+ export function isWorkflowPluginManifest(value: unknown): value is NornAnyWorkflowPluginManifest {
798
+ if (!value || typeof value !== "object") return false;
799
+ const candidate = value as { id?: unknown; workflows?: unknown };
800
+ if (typeof candidate.id !== "string" || candidate.id.length === 0) return false;
801
+ if (!candidate.workflows || typeof candidate.workflows !== "object") return false;
802
+ return Object.values(candidate.workflows).every(isWorkflowDeclaration);
803
+ }
804
+
805
+ export function isWorkflowNext(value: unknown): value is NornRunNext {
806
+ if (!value || typeof value !== "object") return false;
807
+ const candidate = value as { type?: unknown; workflowId?: unknown; params?: unknown };
808
+ return candidate.type === "next" && typeof candidate.workflowId === "string" && candidate.workflowId.length > 0;
809
+ }
810
+
811
+ export function isWorkflowComplete(value: unknown): value is NornRunComplete {
812
+ if (!value || typeof value !== "object") return false;
813
+ const candidate = value as { type?: unknown };
814
+ return candidate.type === "complete";
815
+ }
816
+
817
+ export function isWorkflowFail(value: unknown): value is NornRunFail {
818
+ if (!value || typeof value !== "object") return false;
819
+ const candidate = value as { type?: unknown; metadata?: { summary?: unknown } };
820
+ return candidate.type === "fail" && typeof candidate.metadata?.summary === "string" && candidate.metadata.summary.length > 0;
821
+ }