@vimhead.dev/norn-cli 0.1.0-tip.35359392805.1 → 0.1.0-tip.35436871363.1

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 (146) hide show
  1. package/assets/README.md +22 -27
  2. package/assets/docs/README.md +5 -5
  3. package/assets/docs/agents.md +48 -9
  4. package/assets/docs/cli.md +7 -7
  5. package/assets/docs/composition.md +25 -25
  6. package/assets/docs/persistence.md +34 -23
  7. package/assets/docs/projects.md +30 -18
  8. package/assets/docs/providers.md +3 -3
  9. package/assets/docs/recovery.md +13 -9
  10. package/assets/docs/schemas.md +1 -1
  11. package/assets/docs/workflows.md +105 -12
  12. package/assets/examples/agent-then-analysis/README.md +10 -10
  13. package/assets/examples/agent-then-analysis/input.json +1 -1
  14. package/assets/examples/agent-then-analysis/norn.project.json +1 -1
  15. package/assets/examples/agent-then-analysis/plugin.ts +57 -68
  16. package/assets/examples/caller-selected-continuation/README.md +15 -14
  17. package/assets/examples/caller-selected-continuation/caller.ts +37 -38
  18. package/assets/examples/caller-selected-continuation/input.json +2 -2
  19. package/assets/examples/caller-selected-continuation/norn.project.json +1 -1
  20. package/assets/examples/caller-selected-continuation/producer.ts +19 -24
  21. package/assets/examples/coordinating-multiple-agents/README.md +27 -17
  22. package/assets/examples/coordinating-multiple-agents/input.json +1 -1
  23. package/assets/examples/coordinating-multiple-agents/norn.project.json +1 -1
  24. package/assets/examples/coordinating-multiple-agents/plugin.ts +79 -60
  25. package/assets/examples/coordinating-multiple-agents/queue-tools.ts +43 -0
  26. package/assets/examples/coordinating-multiple-agents/work-queue.ts +60 -65
  27. package/assets/examples/getting-started/README.md +2 -2
  28. package/assets/examples/getting-started/norn.project.json +1 -1
  29. package/assets/examples/getting-started/plugin.ts +20 -26
  30. package/assets/examples/minimal-workflow/README.md +13 -12
  31. package/assets/examples/minimal-workflow/norn.project.json +1 -1
  32. package/assets/examples/minimal-workflow/plugin.ts +14 -25
  33. package/assets/examples/shared-state/README.md +12 -4
  34. package/assets/examples/shared-state/input.json +1 -1
  35. package/assets/examples/shared-state/norn.project.json +1 -1
  36. package/assets/examples/shared-state/plugin.ts +49 -41
  37. package/assets/examples/shared-state/shared-state.ts +56 -0
  38. package/assets/examples/shared-state/state-tools.ts +68 -0
  39. package/assets/examples/worktree-development-loop/README.md +18 -17
  40. package/assets/examples/worktree-development-loop/norn.project.json +1 -1
  41. package/assets/examples/worktree-development-loop/plugin.ts +6 -26
  42. package/assets/examples/worktree-development-loop/scope.ts +4 -0
  43. package/assets/examples/worktree-development-loop/workflows/development-loop/execute.ts +14 -15
  44. package/assets/examples/worktree-development-loop/workflows/development-loop/index.ts +3 -4
  45. package/assets/examples/worktree-development-loop/workflows/development-loop/repository.ts +5 -3
  46. package/assets/examples/worktree-development-loop/workflows/development-loop/schema.ts +2 -2
  47. package/assets/examples/worktree-development-loop/workflows/implementation/execute.ts +35 -33
  48. package/assets/examples/worktree-development-loop/workflows/implementation/index.ts +2 -3
  49. package/assets/examples/worktree-development-loop/workflows/implementation/schema.ts +6 -3
  50. package/assets/examples/worktree-development-loop/workflows/planning/execute.ts +27 -16
  51. package/assets/examples/worktree-development-loop/workflows/planning/index.ts +2 -3
  52. package/assets/examples/worktree-development-loop/workflows/planning/schema.ts +4 -2
  53. package/assets/examples/worktree-development-loop/workflows/review/execute.ts +43 -31
  54. package/assets/examples/worktree-development-loop/workflows/review/index.ts +3 -4
  55. package/assets/examples/worktree-development-loop/workflows/review/schema.ts +6 -6
  56. package/assets/examples/worktree-development-loop/workflows/review-router/execute.ts +50 -44
  57. package/assets/examples/worktree-development-loop/workflows/review-router/index.ts +2 -3
  58. package/assets/examples/worktree-development-loop/workflows/review-router/schema.ts +5 -5
  59. package/assets/package.json +1 -1
  60. package/assets/packages/cli/src/cli.ts +44 -37
  61. package/assets/packages/cli/src/client.ts +9 -16
  62. package/assets/packages/cli/src/documentation-intro.ts +1 -1
  63. package/assets/packages/cli/src/generated-build-info.ts +2 -2
  64. package/assets/packages/cli/src/internal/agent-response-tool.ts +3 -3
  65. package/assets/packages/cli/src/internal/agents.ts +24 -32
  66. package/assets/packages/cli/src/internal/commands.ts +2 -14
  67. package/assets/packages/cli/src/internal/engine.ts +63 -101
  68. package/assets/packages/cli/src/internal/errors.ts +4 -4
  69. package/assets/packages/cli/src/internal/launch-request.ts +6 -6
  70. package/assets/packages/cli/src/internal/logs.ts +1 -1
  71. package/assets/packages/cli/src/internal/run-log.ts +1 -1
  72. package/assets/packages/cli/src/internal/run-state.ts +38 -23
  73. package/assets/packages/cli/src/internal/run.ts +4 -62
  74. package/assets/packages/cli/src/internal/worker-directory.ts +17 -0
  75. package/assets/packages/cli/src/internal/workflow-registry.ts +126 -111
  76. package/assets/packages/cli/src/internal/working-directory.ts +6 -0
  77. package/assets/packages/cli/src/workflow-loader.ts +213 -0
  78. package/assets/packages/core/src/workflow-transition.ts +2 -2
  79. package/assets/packages/sdk/src/api.ts +141 -329
  80. package/assets/packages/sdk/src/index.ts +1 -4
  81. package/assets/packages/sdk/src/schema.ts +3 -3
  82. package/assets/tests/workflow-ref.test.ts +53 -55
  83. package/dist/cli.js +41 -35
  84. package/dist/client.d.ts +3 -4
  85. package/dist/client.js +3 -8
  86. package/dist/documentation-intro.js +1 -1
  87. package/dist/generated-build-info.d.ts +2 -2
  88. package/dist/generated-build-info.js +2 -2
  89. package/dist/internal/agent-response-tool.js +3 -3
  90. package/dist/internal/agents.d.ts +0 -4
  91. package/dist/internal/agents.js +30 -46
  92. package/dist/internal/commands.d.ts +0 -4
  93. package/dist/internal/commands.js +2 -10
  94. package/dist/internal/engine.d.ts +4 -8
  95. package/dist/internal/engine.js +57 -84
  96. package/dist/internal/errors.d.ts +3 -3
  97. package/dist/internal/errors.js +1 -1
  98. package/dist/internal/file-coordinator.d.ts +17 -0
  99. package/dist/internal/file-coordinator.js +162 -0
  100. package/dist/internal/launch-request.d.ts +4 -4
  101. package/dist/internal/launch-request.js +2 -2
  102. package/dist/internal/logs.d.ts +1 -1
  103. package/dist/internal/run-log.d.ts +1 -1
  104. package/dist/internal/run-state.d.ts +11 -8
  105. package/dist/internal/run-state.js +34 -22
  106. package/dist/internal/run.d.ts +3 -23
  107. package/dist/internal/run.js +4 -50
  108. package/dist/internal/worker-directory.d.ts +1 -0
  109. package/dist/internal/worker-directory.js +26 -0
  110. package/dist/internal/workflow-registry.d.ts +35 -17
  111. package/dist/internal/workflow-registry.js +110 -73
  112. package/dist/internal/working-directory.d.ts +1 -0
  113. package/dist/internal/working-directory.js +9 -0
  114. package/dist/{plugin-loader.d.ts → workflow-loader.d.ts} +7 -8
  115. package/dist/workflow-loader.js +234 -0
  116. package/package.json +2 -2
  117. package/assets/docs/resources.md +0 -61
  118. package/assets/examples/coordinating-multiple-agents/queue-adapter.ts +0 -51
  119. package/assets/examples/worktree-development-loop/manifest.ts +0 -26
  120. package/assets/examples/worktree-development-loop/state.ts +0 -23
  121. package/assets/examples/worktree-development-loop/workflows/development-loop/declaration.ts +0 -8
  122. package/assets/examples/worktree-development-loop/workflows/implementation/declaration.ts +0 -8
  123. package/assets/examples/worktree-development-loop/workflows/planning/declaration.ts +0 -8
  124. package/assets/examples/worktree-development-loop/workflows/review/declaration.ts +0 -8
  125. package/assets/examples/worktree-development-loop/workflows/review-router/declaration.ts +0 -12
  126. package/assets/packages/cli/src/internal/artifacts.ts +0 -26
  127. package/assets/packages/cli/src/internal/resource-bindings.ts +0 -35
  128. package/assets/packages/cli/src/internal/run-resources.ts +0 -23
  129. package/assets/packages/cli/src/internal/state-store.ts +0 -83
  130. package/assets/packages/cli/src/plugin-loader.ts +0 -400
  131. package/assets/packages/cli/src/resources.ts +0 -69
  132. package/assets/packages/sdk/src/agent-resource-adapter.ts +0 -11
  133. package/assets/packages/sdk/src/resources.ts +0 -20
  134. package/assets/packages/sdk/src/state-adapter.ts +0 -75
  135. package/dist/internal/artifacts.d.ts +0 -10
  136. package/dist/internal/artifacts.js +0 -29
  137. package/dist/internal/resource-bindings.d.ts +0 -13
  138. package/dist/internal/resource-bindings.js +0 -34
  139. package/dist/internal/run-resources.d.ts +0 -6
  140. package/dist/internal/run-resources.js +0 -26
  141. package/dist/internal/state-store.d.ts +0 -23
  142. package/dist/internal/state-store.js +0 -103
  143. package/dist/plugin-loader.js +0 -341
  144. package/dist/resources.d.ts +0 -11
  145. package/dist/resources.js +0 -100
  146. /package/assets/packages/{sdk/src/files.ts → cli/src/internal/file-coordinator.ts} +0 -0
@@ -1,9 +1,9 @@
1
- import type { CreateAgentSessionOptions, EventBus, PromptOptions } from "@earendil-works/pi-coding-agent";
2
- import { Type, type Static, type StaticDecode, type StaticEncode, type TCodec, type TSchema } from "typebox";
1
+ import type { CreateAgentSessionOptions, EventBus, PromptOptions, ToolDefinition } from "@earendil-works/pi-coding-agent";
2
+ import { Type, type StaticDecode, type StaticEncode, type TCodec, type TSchema } from "typebox";
3
3
  import type { TLocalizedValidationError } from "typebox/error";
4
4
  import { createWorkflowTransition } from "@vimhead.dev/norn-core/workflow-transition";
5
5
  import { Value } from "typebox/value";
6
- import { isPlainObject, jsonValueSchema } from "./schema.ts";
6
+ import { assertWorkflowMetadata, isPlainObject, jsonValueSchema } from "./schema.ts";
7
7
 
8
8
  const WORKFLOW_DECLARATION_KIND = "norn.workflow";
9
9
 
@@ -15,43 +15,50 @@ export type NornWorkflowAnyGate = {
15
15
  readonly fields?: readonly string[];
16
16
  };
17
17
 
18
- export type NornWorkflowIsolationMode = "runWorkspace" | "project";
18
+ export type NornWorkflowPaths = {
19
+ /** Absolute project root. Excluded from run checkpoints and rollback. */
20
+ readonly project: string;
19
21
 
20
- export type NornWorkflowIsolation<Mode extends NornWorkflowIsolationMode = NornWorkflowIsolationMode> = {
21
- readonly mode: Mode;
22
+ /** Absolute, initially empty workspace. Saved in run checkpoints and restored on rollback. */
23
+ readonly workspace: string;
22
24
  };
23
25
 
24
26
  export type NornWorkflowDeclaration<
25
27
  Id extends string = string,
26
- ParamsSchema extends TSchema = TSchema,
27
- IsolationMode extends NornWorkflowIsolationMode = NornWorkflowIsolationMode,
28
+ ArgsSchema extends TSchema = TSchema,
29
+ ConfigSchema extends TSchema | undefined = TSchema | undefined,
30
+ Scope extends NornWorkflowScopeInfo | undefined = NornWorkflowScopeInfo | undefined,
28
31
  > = {
29
- (params: StaticEncode<ParamsSchema>): NornRunNext;
32
+ (args: StaticEncode<ArgsSchema>): NornRunNext;
30
33
  readonly kind: typeof WORKFLOW_DECLARATION_KIND;
31
34
  readonly id: Id;
32
35
  readonly isEntrypoint: boolean;
33
36
  readonly instructions?: string;
34
- readonly params: ParamsSchema;
35
- readonly gate?: NornWorkflowAnyGate;
36
- readonly isolation: NornWorkflowIsolation<IsolationMode>;
37
+ readonly args: ArgsSchema;
38
+ readonly gate?: NornWorkflowGate<ArgsSchema> & {
39
+ describe?(context: NornWorkflowContext<ArgsSchema, ConfigSchema, Scope>): MaybePromise<string>;
40
+ };
41
+ readonly config?: ConfigSchema;
42
+ readonly scope: Scope;
43
+ execute(context: NornWorkflowContext<ArgsSchema, ConfigSchema, Scope>): MaybePromise<WorkflowResult>;
37
44
  };
38
45
 
39
- export type NornAnyWorkflowDeclaration = Pick<NornWorkflowDeclaration, keyof NornWorkflowDeclaration> & ((params: never) => NornRunNext);
40
- export type NornWorkflowRefSchemaOptions<ParamsSchema extends TSchema = TSchema> = {
41
- readonly params?: ParamsSchema;
46
+ export type NornAnyWorkflowDeclaration = Pick<NornWorkflowDeclaration, keyof NornWorkflowDeclaration> & ((args: never) => NornRunNext);
47
+ export type NornWorkflowRefSchemaOptions<ArgsSchema extends TSchema = TSchema> = {
48
+ readonly args?: ArgsSchema;
42
49
  };
43
50
  export type NornWorkflowRefInput = StaticEncode<typeof workflowReferenceInputSchema>;
44
- export type NornWorkflowRefOutput<ParamsSchema extends TSchema> = (params: StaticEncode<ParamsSchema> & object) => NornRunNext;
51
+ export type NornWorkflowRefOutput<ArgsSchema extends TSchema> = (args: StaticEncode<ArgsSchema> & object) => NornRunNext;
45
52
 
46
- export type NornWorkflowParamsInput<TWorkflow extends NornAnyWorkflowDeclaration> = StaticEncode<TWorkflow["params"]>;
47
- export type NornWorkflowParams<TWorkflow extends NornAnyWorkflowDeclaration> = StaticDecode<TWorkflow["params"]>;
53
+ export type NornWorkflowArgsInput<TWorkflow extends NornAnyWorkflowDeclaration> = StaticEncode<TWorkflow["args"]>;
54
+ export type NornWorkflowArgs<TWorkflow extends NornAnyWorkflowDeclaration> = StaticDecode<TWorkflow["args"]>;
48
55
 
49
- export type NornWorkflowGate<ParamsSchema extends TSchema> = unknown extends StaticEncode<ParamsSchema>
56
+ export type NornWorkflowGate<ArgsSchema extends TSchema> = unknown extends StaticEncode<ArgsSchema>
50
57
  ? NornWorkflowAnyGate
51
- : StaticEncode<ParamsSchema> extends Record<string, unknown>
58
+ : StaticEncode<ArgsSchema> extends Record<string, unknown>
52
59
  ? {
53
60
  readonly enabled: true;
54
- readonly fields?: readonly Extract<keyof StaticEncode<ParamsSchema>, string>[];
61
+ readonly fields?: readonly Extract<keyof StaticEncode<ArgsSchema>, string>[];
55
62
  }
56
63
  : {
57
64
  readonly enabled: true;
@@ -62,154 +69,95 @@ type NornWorkflowInstructions =
62
69
  | { readonly isEntrypoint: true; readonly instructions: string }
63
70
  | { readonly isEntrypoint: false; readonly instructions?: string };
64
71
 
65
- export type NornWorkflowDefinition<
66
- Id extends string | undefined = string | undefined,
67
- ParamsSchema extends TSchema = TSchema,
68
- IsolationMode extends NornWorkflowIsolationMode = NornWorkflowIsolationMode,
69
- > = {
70
- readonly id?: Id;
71
- readonly params: ParamsSchema;
72
- readonly gate?: NornWorkflowGate<ParamsSchema>;
73
- readonly isolation?: NornWorkflowIsolation<IsolationMode>;
74
- } & NornWorkflowInstructions;
75
-
76
- export type NornAnyWorkflowDefinition = {
77
- readonly id?: string;
78
- readonly params: TSchema;
79
- readonly gate?: NornWorkflowAnyGate;
80
- readonly isolation?: NornWorkflowIsolation;
81
- } & NornWorkflowInstructions;
82
-
83
- export type NornWorkflowStateDefinition<Schema extends TSchema = TSchema, Id extends string = string> = {
84
- readonly id: Id;
85
- readonly description?: string;
86
- readonly schema: Schema;
87
- };
88
-
89
- export type NornWorkflowStateDefinitionInput<Schema extends TSchema = TSchema, Id extends string | undefined = string | undefined> = {
90
- readonly id?: Id;
91
- readonly description?: string;
92
- readonly schema: Schema;
93
- };
94
-
95
- export type NornWorkflowPluginWorkflows = Record<string, NornAnyWorkflowDefinition>;
96
- export type NornWorkflowPluginStateTree = { readonly [key: string]: NornWorkflowPluginStateTreeNode };
97
- type NornStateSchema = TSchema & ({ readonly "~kind": string } | { readonly "~unsafe": unknown });
98
- export type NornWorkflowPluginStateTreeNode = NornStateSchema | NornWorkflowStateDefinitionInput | NornWorkflowPluginStateTree;
99
-
100
- type JoinPath<Head extends string, Parts extends readonly string[]> = Parts extends readonly []
101
- ? Head
102
- : Parts extends readonly [infer First extends string, ...infer Rest extends string[]]
103
- ? JoinPath<`${Head}.${First}`, Rest>
104
- : string;
105
-
106
- type NornInvalidGateFields<TWorkflow> = TWorkflow extends { readonly params: infer ParamsSchema extends TSchema; readonly gate: { readonly fields: infer Fields extends readonly string[] } }
107
- ? Exclude<Fields[number], Extract<keyof StaticEncode<ParamsSchema>, string>>
108
- : never;
109
-
110
- type NornValidatedWorkflowGate<TWorkflow> = [NornInvalidGateFields<TWorkflow>] extends [never]
111
- ? unknown
112
- : { readonly gate: { readonly fields: readonly Extract<keyof StaticEncode<TWorkflow extends { readonly params: infer ParamsSchema extends TSchema } ? ParamsSchema : TSchema>, string>[] } };
113
-
114
- export type NornValidatedWorkflowGates<Workflows> = {
115
- readonly [Key in keyof Workflows]: NornValidatedWorkflowGate<Workflows[Key]>;
116
- };
117
-
118
- export type NornQualifiedPluginWorkflow<
119
- PluginId extends string,
120
- WorkflowKey extends string,
121
- TWorkflow extends NornAnyWorkflowDefinition,
122
- > = TWorkflow extends { readonly params: infer ParamsSchema extends TSchema }
123
- ? NornWorkflowDeclaration<
124
- TWorkflow extends { readonly id: infer ExplicitId extends string } ? ExplicitId : `${PluginId}.${WorkflowKey}`,
125
- ParamsSchema,
126
- TWorkflow extends { readonly isolation: { readonly mode: infer IsolationMode extends NornWorkflowIsolationMode } } ? IsolationMode : "runWorkspace"
127
- >
128
- : never;
129
-
130
- export type NornQualifiedPluginWorkflows<PluginId extends string, Workflows extends NornWorkflowPluginWorkflows> = {
131
- readonly [Key in keyof Workflows]: NornQualifiedPluginWorkflow<PluginId, Key & string, Workflows[Key]>;
132
- };
133
-
134
- export type NornQualifiedPluginStates<PluginId extends string, States, Path extends readonly string[] = []> = {
135
- readonly [Key in keyof States]: States[Key] extends NornStateSchema
136
- ? NornWorkflowStateDefinition<States[Key], JoinPath<PluginId, [...Path, Key & string]>>
137
- : States[Key] extends NornWorkflowStateDefinitionInput<infer Schema extends NornStateSchema>
138
- ? NornWorkflowStateDefinition<Schema, States[Key] extends { readonly id: infer Id extends string } ? Id : JoinPath<PluginId, [...Path, Key & string]>>
139
- : States[Key] extends NornWorkflowPluginStateTree
140
- ? NornQualifiedPluginStates<PluginId, States[Key], [...Path, Key & string]>
141
- : never;
142
- };
72
+ type WorkflowConfig<Schema extends TSchema | undefined> = Schema extends TSchema ? StaticDecode<Schema> : undefined;
143
73
 
144
- export type NornWorkflowPluginManifest<
145
- PluginId extends string = string,
74
+ export type NornWorkflowContext<
75
+ ArgsSchema extends TSchema = TSchema,
146
76
  ConfigSchema extends TSchema | undefined = TSchema | undefined,
147
- Workflows extends Record<string, NornAnyWorkflowDeclaration> = Record<string, NornAnyWorkflowDeclaration>,
148
- States = undefined,
77
+ Scope extends NornWorkflowScopeInfo | undefined = NornWorkflowScopeInfo | undefined,
78
+ > = {
79
+ readonly args: StaticDecode<ArgsSchema>;
80
+ readonly config: WorkflowConfig<ConfigSchema>;
81
+ readonly paths: NornWorkflowPaths;
82
+ readonly run: NornRun;
83
+ } & (Scope extends NornWorkflowScopeInfo ? {
84
+ readonly scope: { readonly id: Scope["id"]; readonly config: WorkflowConfig<Scope["config"]> };
85
+ } : {});
86
+
87
+ export type NornWorkflowDefinition<
88
+ Id extends string = string,
89
+ ArgsSchema extends TSchema = TSchema,
90
+ ConfigSchema extends TSchema | undefined = undefined,
91
+ Scope extends NornWorkflowScopeInfo | undefined = undefined,
149
92
  > = {
150
- readonly id: PluginId;
93
+ readonly id: Id;
94
+ readonly args: ArgsSchema;
151
95
  readonly config?: ConfigSchema;
152
- readonly workflows: Workflows;
153
- readonly states: States;
154
- };
96
+ readonly gate?: NornWorkflowGate<ArgsSchema> & {
97
+ describe?(context: NornWorkflowContext<ArgsSchema, ConfigSchema, Scope>): MaybePromise<string>;
98
+ };
99
+ execute(context: NornWorkflowContext<ArgsSchema, ConfigSchema, Scope>): MaybePromise<WorkflowResult>;
100
+ } & NornWorkflowInstructions;
155
101
 
156
- export type NornAnyWorkflowPluginManifest = NornWorkflowPluginManifest<string, TSchema | undefined, Record<string, NornAnyWorkflowDeclaration>, unknown>;
102
+ export type NornWorkflowScopeInfo = {
103
+ readonly id: string;
104
+ readonly config?: TSchema;
105
+ };
157
106
 
158
- export type NornWorkflowPluginConfigSchema<TManifest extends NornAnyWorkflowPluginManifest> = TManifest extends { readonly config?: infer ConfigSchema extends TSchema | undefined }
159
- ? ConfigSchema
160
- : undefined;
107
+ export type NornWorkflowScope<Id extends string, ConfigSchema extends TSchema | undefined> = {
108
+ readonly id: Id;
109
+ readonly config: ConfigSchema;
110
+ workflow<const LocalId extends string, ArgsSchema extends TSchema, LocalConfig extends TSchema | undefined = undefined>(
111
+ definition: NornWorkflowDefinition<LocalId, ArgsSchema, LocalConfig, { readonly id: Id; readonly config: ConfigSchema }>,
112
+ ): NornWorkflowDeclaration<`${Id}.${LocalId}`, ArgsSchema, LocalConfig, { readonly id: Id; readonly config: ConfigSchema }>;
113
+ };
114
+
115
+ export function workflow<
116
+ const Id extends string,
117
+ ArgsSchema extends TSchema,
118
+ ConfigSchema extends TSchema | undefined = undefined,
119
+ >(definition: NornWorkflowDefinition<Id, ArgsSchema, ConfigSchema>): NornWorkflowDeclaration<Id, ArgsSchema, ConfigSchema, undefined> {
120
+ return createWorkflow({ definition, scope: undefined });
121
+ }
161
122
 
162
- export type NornWorkflowPluginConfig<TManifest extends NornAnyWorkflowPluginManifest> = NornWorkflowPluginConfigSchema<TManifest> extends undefined
163
- ? undefined
164
- : StaticDecode<NonNullable<NornWorkflowPluginConfigSchema<TManifest>>>;
123
+ function createWorkflow<Id extends string, ArgsSchema extends TSchema, ConfigSchema extends TSchema | undefined, Scope extends NornWorkflowScopeInfo | undefined>(
124
+ input: { readonly definition: NornWorkflowDefinition<Id, ArgsSchema, ConfigSchema, Scope>; readonly scope: Scope },
125
+ ): NornWorkflowDeclaration<Id, ArgsSchema, ConfigSchema, Scope> {
126
+ const { definition, scope } = input;
127
+ assertDeclarationId(definition.id);
128
+ const callable = (args: StaticEncode<ArgsSchema>): NornRunNext => createWorkflowTransition({ workflowId: definition.id, args });
129
+ const result = Object.assign(callable, definition, {
130
+ kind: WORKFLOW_DECLARATION_KIND,
131
+ scope,
132
+ }) as NornWorkflowDeclaration<Id, ArgsSchema, ConfigSchema, Scope>;
133
+ if (!isWorkflowDeclaration(result)) throw new Error(`Invalid workflow definition: ${definition.id}`);
134
+ assertWorkflowMetadata(result);
135
+ return result;
136
+ }
165
137
 
166
- export type NornDefinePluginManifestInput<
167
- PluginId extends string,
168
- ConfigSchema extends TSchema | undefined,
169
- Workflows extends NornWorkflowPluginWorkflows,
170
- States extends NornWorkflowPluginStateTree | undefined,
171
- > = {
172
- readonly id: PluginId;
173
- readonly config?: ConfigSchema;
174
- readonly workflows: Workflows & NornValidatedWorkflowGates<Workflows>;
175
- readonly states?: States;
176
- };
177
-
178
- export function definePluginManifest<
179
- const PluginId extends string,
180
- const ConfigSchema extends TSchema | undefined = undefined,
181
- const Workflows extends NornWorkflowPluginWorkflows = NornWorkflowPluginWorkflows,
182
- const States extends NornWorkflowPluginStateTree | undefined = undefined,
183
- >(
184
- input: NornDefinePluginManifestInput<PluginId, ConfigSchema, Workflows, States>,
185
- ): NornWorkflowPluginManifest<
186
- PluginId,
187
- ConfigSchema,
188
- NornQualifiedPluginWorkflows<PluginId, Workflows>,
189
- States extends NornWorkflowPluginStateTree ? NornQualifiedPluginStates<PluginId, States> : undefined
190
- > {
191
- assertLocalDeclarationId(input.id, "plugin");
192
- const declaredIds = new Set<string>();
193
- const workflows = Object.fromEntries(
194
- Object.entries(input.workflows).map(([key, workflow]) => [key, qualifyWorkflow(input.id, key, workflow, declaredIds)]),
195
- ) as NornQualifiedPluginWorkflows<PluginId, Workflows>;
138
+ export function workflowScope<const Id extends string, ConfigSchema extends TSchema | undefined = undefined>(
139
+ input: { readonly id: Id; readonly config?: ConfigSchema },
140
+ ): NornWorkflowScope<Id, ConfigSchema> {
141
+ assertDeclarationId(input.id);
142
+ const scope = { id: input.id, config: input.config as ConfigSchema };
196
143
  return {
197
144
  id: input.id,
198
- config: input.config,
199
- workflows,
200
- states: qualifyStateTree(input.id, input.states, [], declaredIds) as States extends NornWorkflowPluginStateTree ? NornQualifiedPluginStates<PluginId, States> : undefined,
145
+ config: input.config as ConfigSchema,
146
+ workflow(definition) {
147
+ assertDeclarationId(definition.id);
148
+ return createWorkflow({ definition: { ...definition, id: `${input.id}.${definition.id}` }, scope });
149
+ },
201
150
  };
202
151
  }
203
152
 
204
153
  export type NornRunNext = {
205
154
  readonly type: "next";
206
155
  readonly workflowId: string;
207
- readonly params: unknown;
156
+ readonly args: unknown;
208
157
  };
209
158
 
210
159
  export type NornRunOutcomeMetadata = {
211
160
  readonly summary?: string;
212
- readonly artifacts?: Record<string, NornArtifactRef>;
213
161
  readonly logs?: Record<string, NornLogRef>;
214
162
  readonly data?: Record<string, unknown>;
215
163
  };
@@ -224,28 +172,7 @@ export type NornRunFail = {
224
172
  readonly metadata: NornRunOutcomeMetadata & { readonly summary: string };
225
173
  };
226
174
 
227
- export type NornWorkflowExecutionResult = NornRunNext | NornRunComplete | NornRunFail;
228
-
229
- export type NornRunFor<TWorkflow extends NornAnyWorkflowDeclaration> = TWorkflow extends { readonly isolation: { readonly mode: "project" } }
230
- ? NornProjectRun
231
- : NornRun;
232
-
233
- export type NornWorkflowGateImplementation<TWorkflow extends NornAnyWorkflowDeclaration, TConfig> = {
234
- describe(
235
- run: NornRunFor<TWorkflow>,
236
- params: NornWorkflowParams<TWorkflow>,
237
- config: TConfig,
238
- ): MaybePromise<string>;
239
- };
240
-
241
- export type NornWorkflowImplementation<TWorkflow extends NornAnyWorkflowDeclaration, TConfig = unknown> = {
242
- readonly gate?: NornWorkflowGateImplementation<TWorkflow, TConfig>;
243
- execute(
244
- run: NornRunFor<TWorkflow>,
245
- params: NornWorkflowParams<TWorkflow>,
246
- config: TConfig,
247
- ): MaybePromise<NornWorkflowExecutionResult>;
248
- };
175
+ export type WorkflowResult = NornRunNext | NornRunComplete | NornRunFail;
249
176
 
250
177
  export type NornRunStartOptions = {
251
178
  readonly id?: string;
@@ -294,7 +221,7 @@ export type NornStoppedRunResult = {
294
221
 
295
222
  export type NornRunInterruption = {
296
223
  readonly workflowId: string;
297
- readonly params: unknown;
224
+ readonly args: unknown;
298
225
  readonly description: string;
299
226
  readonly fields?: readonly string[];
300
227
  };
@@ -333,6 +260,7 @@ export type NornRunInfo = {
333
260
  readonly id: string;
334
261
  readonly name: string;
335
262
  readonly path: string;
263
+ readonly paths: NornWorkflowPaths;
336
264
  readonly entrypointWorkflowId: string;
337
265
  readonly currentWorkflowId?: string;
338
266
  readonly status: NornRunStatus;
@@ -358,78 +286,32 @@ export type NornRunCheckpoint = {
358
286
  readonly createdAt: string;
359
287
  };
360
288
 
361
- export type NornWorkflowStateReader = {
362
- get<Schema extends TSchema>(state: NornWorkflowStateDefinition<Schema>): Promise<Static<Schema>>;
363
- getOptional<Schema extends TSchema>(state: NornWorkflowStateDefinition<Schema>): Promise<Static<Schema> | undefined>;
364
- };
365
-
366
- export type NornWorkflowState = NornWorkflowStateReader & {
367
- set<Schema extends TSchema>(state: NornWorkflowStateDefinition<Schema>, value: NoInfer<Static<Schema>>): Promise<void>;
368
- };
369
-
370
- export type NornWorkflowPluginContext = {
371
- readonly cwd: string;
372
- readonly state: NornWorkflowState;
373
- };
374
-
375
- export type NornWorkflowPluginImplementation<TManifest extends NornAnyWorkflowPluginManifest> = {
376
- readonly workflows: {
377
- readonly [Key in keyof TManifest["workflows"]]: NornWorkflowImplementation<TManifest["workflows"][Key], NornWorkflowPluginConfig<TManifest>>;
378
- };
379
- };
380
-
381
- export type NornWorkflowPluginImplementationFactory<TManifest extends NornAnyWorkflowPluginManifest> = (
382
- context: NornWorkflowPluginContext,
383
- ) => NornWorkflowPluginImplementation<TManifest>;
384
-
385
- export type NornWorkflowPluginImplementationInput<TManifest extends NornAnyWorkflowPluginManifest> =
386
- | NornWorkflowPluginImplementation<TManifest>
387
- | NornWorkflowPluginImplementationFactory<TManifest>;
388
-
389
- export type NornWorkflowPlugin<TManifest extends NornAnyWorkflowPluginManifest = NornAnyWorkflowPluginManifest> = {
390
- readonly manifest: TManifest;
391
- readonly implementation: NornWorkflowPluginImplementationInput<TManifest>;
392
- };
393
-
394
- export function definePlugin<TManifest extends NornAnyWorkflowPluginManifest>(
395
- manifest: TManifest,
396
- implementation: NornWorkflowPluginImplementationInput<TManifest>,
397
- ): NornWorkflowPlugin<TManifest> {
398
- return { manifest, implementation };
399
- }
400
-
401
289
  export type NornCommandRunInput = {
402
290
  readonly label: string;
403
291
  readonly command: string | readonly [string, ...string[]];
404
- readonly cwd?: string;
292
+ readonly cwd: string;
405
293
  readonly env?: Record<string, string>;
406
294
  readonly timeoutMs?: number;
407
295
  };
408
296
 
409
- export const artifactRefSchema = Type.Object({
410
- path: Type.String(),
411
- });
412
-
413
- export type NornArtifactRef = StaticDecode<typeof artifactRefSchema>;
414
-
415
- const emptyWorkflowRefParamsSchema = Type.Object({});
297
+ const emptyWorkflowRefArgsSchema = Type.Object({});
416
298
  const workflowReferenceInputSchema = Type.Union([
417
299
  Type.String({ minLength: 1 }),
418
- Type.Object({ workflow: Type.String({ minLength: 1 }), forwardParams: Type.Record(Type.String(), Type.Unknown()) }),
300
+ Type.Object({ workflow: Type.String({ minLength: 1 }), forwardArgs: Type.Record(Type.String(), Type.Unknown()) }),
419
301
  ]);
420
302
 
421
- export function workflowRefSchema<ParamsSchema extends TSchema = typeof emptyWorkflowRefParamsSchema>(options?: NornWorkflowRefSchemaOptions<ParamsSchema>): TCodec<typeof workflowReferenceInputSchema, NornWorkflowRefOutput<ParamsSchema>> {
422
- const contributionSchema = options?.params ?? emptyWorkflowRefParamsSchema;
303
+ export function workflowRefSchema<ArgsSchema extends TSchema = typeof emptyWorkflowRefArgsSchema>(options?: NornWorkflowRefSchemaOptions<ArgsSchema>): TCodec<typeof workflowReferenceInputSchema, NornWorkflowRefOutput<ArgsSchema>> {
304
+ const contributionSchema = options?.args ?? emptyWorkflowRefArgsSchema;
423
305
  return Type.With(Type.Decode(workflowReferenceInputSchema, reference => {
424
306
  const workflowId = typeof reference === "string" ? reference : reference.workflow;
425
- const forwardParams = typeof reference === "string" ? {} : reference.forwardParams;
426
- return (params: StaticEncode<ParamsSchema> & object): NornRunNext => {
427
- Value.Assert(contributionSchema, params);
428
- if (!isPlainObject(params)) throw new Error("Workflow reference contributions must be objects");
429
- Value.Assert(jsonValueSchema, params);
430
- return createWorkflowTransition({ workflowId, params: { ...forwardParams, ...params } });
307
+ const forwardArgs = typeof reference === "string" ? {} : reference.forwardArgs;
308
+ return (args: StaticEncode<ArgsSchema> & object): NornRunNext => {
309
+ Value.Assert(contributionSchema, args);
310
+ if (!isPlainObject(args)) throw new Error("Workflow reference contributions must be objects");
311
+ Value.Assert(jsonValueSchema, args);
312
+ return createWorkflowTransition({ workflowId, args: { ...forwardArgs, ...args } });
431
313
  };
432
- }), { "x-norn-workflow-ref": { contributedParamsSchema: contributionSchema } });
314
+ }), { "x-norn-workflow-ref": { contributedArgsSchema: contributionSchema } });
433
315
  }
434
316
 
435
317
  export type NornLogRef = {
@@ -453,9 +335,9 @@ export type NornAgentBeforeSessionStartContext = {
453
335
  };
454
336
 
455
337
  export type NornAgentCreateSessionInput = {
456
- readonly resourceAdapters?: readonly import("./agent-resource-adapter.ts").NornAgentResourceAdapter[];
338
+ readonly customTools?: readonly ToolDefinition[];
457
339
  readonly label: string;
458
- readonly cwd?: string;
340
+ readonly cwd: string;
459
341
  readonly tools?: string[];
460
342
  readonly beforeSessionStart?: (context: NornAgentBeforeSessionStartContext) => MaybePromise<void>;
461
343
  readonly model?: CreateAgentSessionOptions["model"];
@@ -580,27 +462,11 @@ export type NornAgentSession = {
580
462
  dispose(): Promise<void>;
581
463
  };
582
464
 
583
- export type NornRun = NornRunBase;
584
-
585
- export type NornProjectRun = NornRunBase & {
586
- projectRoot: string;
587
- projectPath(relativePath: string): string;
588
- };
589
-
590
- type NornRunBase = {
465
+ export type NornRun = {
591
466
  id: string;
592
- workspace: string;
593
- cwd: string;
594
- path(relativePath: string): string;
595
- next(workflowId: string, params: unknown): NornRunNext;
467
+ next(workflowId: string, args: unknown): NornRunNext;
596
468
  complete(metadata?: NornRunOutcomeMetadata): NornRunComplete;
597
469
  fail(metadata: NornRunOutcomeMetadata & { readonly summary: string }): NornRunFail;
598
- resources: import("./resources.ts").NornResources;
599
- state: NornWorkflowState;
600
- artifacts: {
601
- write(path: string, content: string): Promise<NornArtifactRef>;
602
- read(ref: NornArtifactRef): Promise<string>;
603
- };
604
470
  logs: {
605
471
  read(log: NornLogRef): Promise<string>;
606
472
  };
@@ -613,10 +479,9 @@ type NornRunBase = {
613
479
  };
614
480
  };
615
481
 
616
- export type NornWorkflowPluginInfo = {
617
- readonly id: string;
618
- readonly path?: string;
619
- readonly configPath?: string;
482
+ export type NornWorkflowSource = {
483
+ readonly path: string;
484
+ readonly configPath: string;
620
485
  };
621
486
 
622
487
  export type NornJsonSchema = Record<string, unknown>;
@@ -630,28 +495,31 @@ export type NornRegisteredWorkflowInfo = {
630
495
  readonly id: string;
631
496
  readonly instructions?: string;
632
497
  readonly isEntrypoint: boolean;
633
- readonly isolation: NornWorkflowIsolation;
634
- readonly plugin?: NornWorkflowPluginInfo;
498
+ readonly scope?: { readonly id: string };
499
+ readonly source?: NornWorkflowSource;
500
+ readonly configKey: string;
635
501
  };
636
502
 
637
503
  export type NornInspectedWorkflowInfo = NornRegisteredWorkflowInfo & {
638
- readonly paramsSchema: NornJsonSchema;
504
+ readonly scope?: { readonly id: string; readonly configKey: string; readonly configSchema: NornJsonSchema | null };
505
+ readonly argsSchema: NornJsonSchema;
506
+ readonly configSchema: NornJsonSchema | null;
639
507
  readonly gate: NornWorkflowGateInfo | null;
640
508
  };
641
509
 
642
- export type NornPluginDiagnostic = {
510
+ export type NornWorkflowDiagnostic = {
643
511
  readonly configPath: string;
644
- readonly pluginPath: string;
645
- readonly pluginId: string | null;
512
+ readonly modulePath: string;
513
+ readonly scopeId: string | null;
646
514
  readonly workflowId: string | null;
647
- readonly stage: "import" | "declaration" | "config" | "implementation" | "duplicate" | "schema";
515
+ readonly stage: "import" | "declaration" | "config" | "duplicate" | "schema";
648
516
  readonly message: string;
649
517
  readonly issues: readonly TLocalizedValidationError[];
650
518
  };
651
519
 
652
520
  export type NornProjectLoadStatus = {
653
521
  readonly isComplete: boolean;
654
- readonly diagnostics: readonly NornPluginDiagnostic[];
522
+ readonly diagnostics: readonly NornWorkflowDiagnostic[];
655
523
  };
656
524
 
657
525
  export type NornWorkflowCatalogInfo = NornProjectLoadStatus & {
@@ -666,7 +534,9 @@ export type NornProjectInspection = NornProjectLoadStatus & {
666
534
  readonly project: NornProjectInfo;
667
535
  };
668
536
 
669
- export type NornProjectPluginInfo = NornWorkflowPluginInfo & {
537
+ export type NornProjectConfigurationInfo = {
538
+ readonly key: string;
539
+ readonly scopeId: string | null;
670
540
  readonly configSchema: NornJsonSchema | null;
671
541
  readonly config: unknown;
672
542
  };
@@ -678,89 +548,31 @@ export type NornProjectInfo = {
678
548
  readonly configPath: string;
679
549
  readonly configRoot: string;
680
550
  readonly configFiles: readonly string[];
681
- readonly plugins: readonly NornProjectPluginInfo[];
551
+ readonly configurations: readonly NornProjectConfigurationInfo[];
552
+ readonly modules: readonly NornWorkflowSource[];
682
553
  };
683
554
 
684
- function assertLocalDeclarationId(id: string, kind: "plugin" | "workflow" | "state"): void {
685
- if (id.length === 0) throw new Error(`Workflow ${kind} id must not be empty`);
686
- if (id.includes(".")) throw new Error(`Workflow ${kind} id must not contain dots: ${id}`);
687
- }
688
-
689
- function resolveDeclarationId(pluginId: string, path: readonly string[], explicitId: string | undefined, kind: "workflow" | "state", declaredIds: Set<string>): string {
690
- for (const segment of path) assertLocalDeclarationId(segment, kind);
691
- const id = explicitId ?? [pluginId, ...path].join(".");
692
- if (explicitId !== undefined) assertPluginQualifiedId(pluginId, explicitId, kind);
693
- if (declaredIds.has(id)) throw new Error(`Duplicate Norn ${kind} id: ${id}`);
694
- declaredIds.add(id);
695
- return id;
696
- }
697
-
698
- function assertPluginQualifiedId(pluginId: string, id: string, kind: "workflow" | "state"): void {
699
- if (!id.startsWith(`${pluginId}.`)) throw new Error(`Explicit Norn ${kind} id must start with ${pluginId}.: ${id}`);
700
- if (id.length === pluginId.length + 1) throw new Error(`Explicit Norn ${kind} id must not be empty after ${pluginId}.`);
701
- }
702
-
703
- function qualifyWorkflow<PluginId extends string, TWorkflow extends NornAnyWorkflowDefinition>(
704
- pluginId: PluginId,
705
- key: string,
706
- workflow: TWorkflow,
707
- declaredIds: Set<string>,
708
- ): NornQualifiedPluginWorkflow<PluginId, string, TWorkflow> {
709
- const id = resolveDeclarationId(pluginId, [key], workflow.id, "workflow", declaredIds);
710
- const declaration = (params: unknown): NornRunNext => createWorkflowTransition({ workflowId: id, params });
711
- return Object.assign(declaration, { ...workflow, kind: WORKFLOW_DECLARATION_KIND, id, isolation: workflow.isolation ?? { mode: "runWorkspace" } }) as unknown as NornQualifiedPluginWorkflow<PluginId, string, TWorkflow>;
712
- }
713
-
714
- function qualifyStateTree(pluginId: string, node: unknown, path: readonly string[], declaredIds: Set<string>): unknown {
715
- if (node === undefined) return undefined;
716
- if (isTypeboxSchema(node)) return { id: resolveDeclarationId(pluginId, path, undefined, "state", declaredIds), schema: node };
717
- if (path.length > 0 && isWorkflowStateDefinitionInput(node)) {
718
- return { ...node, id: resolveDeclarationId(pluginId, path, node.id, "state", declaredIds) };
719
- }
720
- if (!isPlainObject(node)) throw new Error(`Invalid state declaration: ${[pluginId, ...path].join(".")}`);
721
- return Object.fromEntries(Object.entries(node).map(([key, child]) => [key, qualifyStateTree(pluginId, child, [...path, key], declaredIds)]));
555
+ function assertDeclarationId(id: string): void {
556
+ if (typeof id !== "string" || id.trim().length === 0 || id.split(".").some(segment => segment.length === 0)) throw new Error(`Invalid workflow or scope id: ${id}`);
722
557
  }
723
558
 
724
559
  export function isWorkflowDeclaration(value: unknown): value is NornAnyWorkflowDeclaration {
725
560
  if (typeof value !== "function") return false;
726
- const candidate = value as { kind?: unknown; id?: unknown; instructions?: unknown; isEntrypoint?: unknown; params?: unknown; isolation?: { mode?: unknown } };
561
+ const candidate = value as { kind?: unknown; id?: unknown; instructions?: unknown; isEntrypoint?: unknown; args?: unknown; execute?: unknown };
727
562
  return (
728
563
  candidate.kind === WORKFLOW_DECLARATION_KIND &&
729
564
  typeof candidate.id === "string" &&
730
565
  candidate.id.length > 0 &&
731
566
  (candidate.instructions === undefined || typeof candidate.instructions === "string") &&
732
567
  typeof candidate.isEntrypoint === "boolean" &&
733
- Boolean(candidate.params) &&
734
- (candidate.isolation?.mode === "runWorkspace" || candidate.isolation?.mode === "project")
568
+ Boolean(candidate.args) &&
569
+ typeof candidate.execute === "function"
735
570
  );
736
571
  }
737
572
 
738
- function isTypeboxSchema(value: unknown): value is NornStateSchema {
739
- return Type.IsUnsafe(value) || Boolean(value && typeof value === "object" && "~kind" in value && typeof value["~kind"] === "string");
740
- }
741
-
742
- function isWorkflowStateDefinitionInput(value: unknown): value is NornWorkflowStateDefinitionInput {
743
- if (!isPlainObject(value)) return false;
744
- return (value.id === undefined || typeof value.id === "string") && isTypeboxSchema(value.schema);
745
- }
746
-
747
- export function isWorkflowPlugin(value: unknown): value is NornWorkflowPlugin {
748
- if (!value || typeof value !== "object") return false;
749
- const candidate = value as { manifest?: unknown; implementation?: unknown };
750
- return isWorkflowPluginManifest(candidate.manifest) && Boolean(candidate.implementation);
751
- }
752
-
753
- export function isWorkflowPluginManifest(value: unknown): value is NornAnyWorkflowPluginManifest {
754
- if (!value || typeof value !== "object") return false;
755
- const candidate = value as { id?: unknown; workflows?: unknown };
756
- if (typeof candidate.id !== "string" || candidate.id.length === 0) return false;
757
- if (!candidate.workflows || typeof candidate.workflows !== "object") return false;
758
- return Object.values(candidate.workflows).every(isWorkflowDeclaration);
759
- }
760
-
761
573
  export function isWorkflowNext(value: unknown): value is NornRunNext {
762
574
  if (!value || typeof value !== "object") return false;
763
- const candidate = value as { type?: unknown; workflowId?: unknown; params?: unknown };
575
+ const candidate = value as { type?: unknown; workflowId?: unknown; args?: unknown };
764
576
  return candidate.type === "next" && typeof candidate.workflowId === "string" && candidate.workflowId.length > 0;
765
577
  }
766
578
 
@@ -1,5 +1,2 @@
1
+ export type { CreateAgentSessionOptions, EventBus, PromptOptions, ToolDefinition } from "@earendil-works/pi-coding-agent";
1
2
  export * from "./api.ts";
2
- export { NornFileCoordinator } from "./files.ts";
3
- export * from "./resources.ts";
4
- export * from "./agent-resource-adapter.ts";
5
- export * from "./state-adapter.ts";