@lhi/n8m 0.1.2 → 0.2.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.
package/README.md CHANGED
@@ -1,12 +1,15 @@
1
1
  # n8m: The Agentic CLI for n8n
2
2
 
3
- > Generate, modify, test, and deploy n8n workflows from the command line using AI.
3
+ > Generate, modify, test, and deploy n8n workflows from the command line using
4
+ > AI.
4
5
 
5
6
  [![TypeScript](https://badgen.net/badge/Built%20with/TypeScript/blue)](https://typescriptlang.org/)
6
7
  [![oclif](https://badgen.net/badge/CLI/oclif/purple)](https://oclif.io/)
7
8
  [![n8n](https://badgen.net/badge/n8n/Compatible/orange)](https://n8n.io)
8
9
 
9
- **Stop clicking. Start shipping.** `n8m` is an open-source CLI that wraps your n8n instance with an agentic AI layer. Describe what you want in plain English — the agent designs, builds, validates, and deploys it.
10
+ **Stop clicking. Start shipping.** `n8m` is an open-source CLI that wraps your
11
+ n8n instance with an agentic AI layer. Describe what you want in plain English —
12
+ the agent designs, builds, validates, and deploys it.
10
13
 
11
14
  No account. No server. Bring your own AI key and your n8n instance.
12
15
 
@@ -26,7 +29,8 @@ npm install -g n8m
26
29
 
27
30
  ### 1. Configure your AI provider
28
31
 
29
- `n8m` stores credentials in `~/.n8m/config.json` so they persist across sessions — including `npx` invocations.
32
+ `n8m` stores credentials in `~/.n8m/config.json` so they persist across sessions
33
+ — including `npx` invocations.
30
34
 
31
35
  ```bash
32
36
  # OpenAI
@@ -42,13 +46,14 @@ npx n8m config --ai-provider gemini --ai-key AIza...
42
46
  npx n8m config --ai-base-url http://localhost:11434/v1 --ai-key ollama --ai-model llama3
43
47
  ```
44
48
 
45
- You can also use environment variables or a `.env` file — env vars take priority over stored config:
49
+ You can also use environment variables or a `.env` file — env vars take priority
50
+ over stored config:
46
51
 
47
- | Variable | Description |
48
- |---|---|
49
- | `AI_PROVIDER` | Preset: `openai`, `anthropic`, or `gemini` |
50
- | `AI_API_KEY` | API key for your provider |
51
- | `AI_MODEL` | Override the model (optional) |
52
+ | Variable | Description |
53
+ | ------------- | -------------------------------------------------------- |
54
+ | `AI_PROVIDER` | Preset: `openai`, `anthropic`, or `gemini` |
55
+ | `AI_API_KEY` | API key for your provider |
56
+ | `AI_MODEL` | Override the model (optional) |
52
57
  | `AI_BASE_URL` | Custom base URL for any OpenAI-compatible API (optional) |
53
58
 
54
59
  Default models per provider: `gpt-4o` · `claude-sonnet-4-6` · `gemini-2.5-flash`
@@ -59,7 +64,8 @@ Default models per provider: `gpt-4o` · `claude-sonnet-4-6` · `gemini-2.5-flas
59
64
  npx n8m config --n8n-url https://your-n8n.example.com --n8n-key <your-n8n-api-key>
60
65
  ```
61
66
 
62
- Credentials are saved locally to `~/.n8m/config.json`. You can also use environment variables `N8N_API_URL` and `N8N_API_KEY` instead.
67
+ Credentials are saved locally to `~/.n8m/config.json`. You can also use
68
+ environment variables `N8N_API_URL` and `N8N_API_KEY` instead.
63
69
 
64
70
  ---
65
71
 
@@ -67,7 +73,8 @@ Credentials are saved locally to `~/.n8m/config.json`. You can also use environm
67
73
 
68
74
  ### `n8m create` — Generate a workflow
69
75
 
70
- Describe what you want and the agentic pipeline designs, builds, and validates it.
76
+ Describe what you want and the agentic pipeline designs, builds, and validates
77
+ it.
71
78
 
72
79
  ```bash
73
80
  n8m create "Send a Slack message whenever a new row is added to a Google Sheet"
@@ -80,11 +87,17 @@ n8m create --multiline
80
87
  ```
81
88
 
82
89
  The agent runs through three stages:
90
+
83
91
  1. **Architect** — designs the blueprint and identifies required nodes
84
92
  2. **Engineer** — generates the workflow JSON
85
93
  3. **QA** — validates the result; loops back to Engineer if issues are found
86
94
 
87
- The finished workflow is saved as a local JSON file (default: `./workflows/`).
95
+ The finished workflow is saved as an organized project folder (default:
96
+ `./workflows/<project-slug>/`). Each project folder contains:
97
+
98
+ - `workflow.json`: The generated n8n workflow.
99
+ - `README.md`: Automatic documentation including a Mermaid.js diagram and an
100
+ AI-generated summary.
88
101
 
89
102
  ---
90
103
 
@@ -103,13 +116,34 @@ n8m modify
103
116
  n8m modify --multiline
104
117
  ```
105
118
 
106
- After modification you'll be prompted to save locally, deploy to your instance, or run a test.
119
+ After modification you'll be prompted to save locally (organized into its
120
+ project folder), deploy to your instance, or run a test.
121
+
122
+ ---
123
+
124
+ ### `n8m doc` — Generate documentation
125
+
126
+ Generate visual and text documentation for existing local or remote workflows.
127
+
128
+ ```bash
129
+ # Document a local workflow file
130
+ n8m doc ./workflows/my-workflow.json
131
+
132
+ # Browse and select from local files + remote instance
133
+ n8m doc
134
+ ```
135
+
136
+ - Generates a `README.md` in the workflow's project directory.
137
+ - Includes a **Mermaid.js** flowchart of the workflow logic.
138
+ - Includes an **AI-generated summary** of the nodes and execution flow.
139
+ - Automatically organizes loose `.json` files into project folders.
107
140
 
108
141
  ---
109
142
 
110
143
  ### `n8m test` — Validate and auto-repair a workflow
111
144
 
112
- Deploys a workflow ephemerally to your instance, validates it, and purges it when done. If validation fails, the repair loop kicks in automatically.
145
+ Deploys a workflow ephemerally to your instance, validates it, and purges it
146
+ when done. If validation fails, the repair loop kicks in automatically.
113
147
 
114
148
  ```bash
115
149
  # Test a local file
@@ -122,6 +156,7 @@ n8m test
122
156
  - Resolves and deploys sub-workflow dependencies automatically
123
157
  - Patches node IDs after ephemeral deployment
124
158
  - After a passing test, prompts to deploy or save the validated/repaired version
159
+ - **Auto-documents**: Generates or updates the project `README.md` upon saving.
125
160
  - All temporary assets are deleted on exit
126
161
 
127
162
  ---
@@ -141,19 +176,22 @@ n8m deploy ./workflows/my-flow.json --activate
141
176
 
142
177
  ### `n8m resume` — Resume a paused session
143
178
 
144
- The agent can pause mid-run for human review (HITL). Resume it with its thread ID.
179
+ The agent can pause mid-run for human review (HITL). Resume it with its thread
180
+ ID.
145
181
 
146
182
  ```bash
147
183
  n8m resume <thread-id>
148
184
  ```
149
185
 
150
- Sessions are persisted to a local SQLite database, so they survive crashes and restarts.
186
+ Sessions are persisted to a local SQLite database, so they survive crashes and
187
+ restarts.
151
188
 
152
189
  ---
153
190
 
154
191
  ### `n8m prune` — Clean up your instance
155
192
 
156
- Removes duplicate workflows and leftover test artifacts (`[n8m:test:*]` prefixed names).
193
+ Removes duplicate workflows and leftover test artifacts (`[n8m:test:*]` prefixed
194
+ names).
157
195
 
158
196
  ```bash
159
197
  # Preview what would be deleted
@@ -167,7 +205,8 @@ n8m prune --force
167
205
 
168
206
  ### `n8m config` — Manage configuration
169
207
 
170
- All credentials are saved to `~/.n8m/config.json` and persist across sessions (including `npx` invocations).
208
+ All credentials are saved to `~/.n8m/config.json` and persist across sessions
209
+ (including `npx` invocations).
171
210
 
172
211
  ```bash
173
212
  # Set AI provider
@@ -209,13 +248,23 @@ Developer → n8m create "..."
209
248
  └──────┬──────┘ └─────────────┘
210
249
  │ passed
211
250
 
212
- ./workflows/output.json
251
+
252
+ ./workflows/<slug>/
253
+ ├── workflow.json
254
+ └── README.md (with Mermaid diagram)
213
255
  ```
214
256
 
215
257
  - **Local first**: credentials and workflow files live on your machine
258
+ - **Organized Projects**: Workflows are grouped into folders with auto-generated
259
+ documentation
216
260
  - **SQLite persistence**: session state survives interruptions
217
261
  - **HITL pauses**: the agent stops for your review before committing
218
- - **Bring your own AI**: works with OpenAI, Claude, Gemini, Ollama, or any OpenAI-compatible API
262
+ - **Bring your own AI**: works with OpenAI, Claude, Gemini, Ollama, or any
263
+ OpenAI-compatible API
264
+
265
+ > **For developers**: See the [Developer Guide](docs/DEVELOPER_GUIDE.md) for a
266
+ > deep-dive into the agentic graph internals, RAG implementation, how to add new
267
+ > agent nodes, and how to extend the CLI.
219
268
 
220
269
  ---
221
270
 
@@ -235,6 +284,14 @@ npm run dev
235
284
 
236
285
  ---
237
286
 
287
+ ## Sponsors
288
+
289
+ ### Partially Sponsored By
290
+
291
+ [The Daily Caller](https://dailycaller.com)
292
+
293
+ ---
294
+
238
295
  ## Roadmap
239
296
 
240
297
  - [x] Agentic graph (Architect → Engineer → QA)
@@ -242,6 +299,12 @@ npm run dev
242
299
  - [x] HITL interrupts and resume
243
300
  - [x] Sub-workflow dependency resolution in tests
244
301
  - [x] Open source — no account required
245
- - [x] Multi-provider AI support (OpenAI, Claude, Gemini, Ollama, any OpenAI-compatible API)
302
+ - [x] Multi-provider AI support (OpenAI, Claude, Gemini, Ollama, any
303
+ OpenAI-compatible API)
304
+ - [x] Automatic documentation generation (Mermaid + AI Summary)
305
+ - [x] Project-based folder organization
306
+ - [x] AI-driven test scenario generation (`--ai-scenarios`)
307
+ - [x] Static node type reference & fallback mechanism
308
+ - [x] Multi-workflow project generation support
246
309
  - [ ] Native n8n canvas integration
247
310
  - [ ] Multi-agent collaboration on a single goal
package/bin/dev.js CHANGED
@@ -1,5 +1,13 @@
1
1
  #!/usr/bin/env node --loader ts-node/esm --no-warnings=ExperimentalWarning
2
2
 
3
+ import { fileURLToPath } from 'url';
4
+ import { dirname, join } from 'path';
5
+ import { config } from 'dotenv';
6
+
7
+ // Load .env from the package root regardless of the user's cwd
8
+ const __dirname = dirname(fileURLToPath(import.meta.url));
9
+ config({ path: join(__dirname, '..', '.env') });
10
+
3
11
  import {execute} from '@oclif/core'
4
12
 
5
13
  await execute({development: true, dir: import.meta.url})
package/bin/run.js CHANGED
@@ -1,5 +1,11 @@
1
1
  #!/usr/bin/env node
2
- import 'dotenv/config';
2
+ import { fileURLToPath } from 'url';
3
+ import { dirname, join } from 'path';
4
+ import { config } from 'dotenv';
5
+
6
+ // Load .env from the package root regardless of the user's cwd
7
+ const __dirname = dirname(fileURLToPath(import.meta.url));
8
+ config({ path: join(__dirname, '..', '.env') });
3
9
 
4
10
  import {execute} from '@oclif/core'
5
11
 
@@ -13,6 +13,8 @@ export declare const graph: import("@langchain/langgraph").CompiledStateGraph<{
13
13
  candidates: any[];
14
14
  customTools: Record<string, string>;
15
15
  collaborationLog: string[];
16
+ userFeedback: string;
17
+ testScenarios: any[];
16
18
  }, {
17
19
  userGoal?: string | undefined;
18
20
  spec?: any;
@@ -27,6 +29,8 @@ export declare const graph: import("@langchain/langgraph").CompiledStateGraph<{
27
29
  candidates?: any[] | undefined;
28
30
  customTools?: Record<string, string> | undefined;
29
31
  collaborationLog?: string[] | undefined;
32
+ userFeedback?: string | undefined;
33
+ testScenarios?: any[] | undefined;
30
34
  }, "__start__" | "architect" | "engineer" | "reviewer" | "supervisor" | "qa", {
31
35
  userGoal: {
32
36
  (): import("@langchain/langgraph").LastValue<string>;
@@ -77,6 +81,16 @@ export declare const graph: import("@langchain/langgraph").CompiledStateGraph<{
77
81
  candidates: import("@langchain/langgraph").BinaryOperatorAggregate<any[], any[]>;
78
82
  customTools: import("@langchain/langgraph").BinaryOperatorAggregate<Record<string, string>, Record<string, string>>;
79
83
  collaborationLog: import("@langchain/langgraph").BinaryOperatorAggregate<string[], string[]>;
84
+ userFeedback: {
85
+ (): import("@langchain/langgraph").LastValue<string>;
86
+ (annotation: import("@langchain/langgraph").SingleReducer<string, string>): import("@langchain/langgraph").BinaryOperatorAggregate<string, string>;
87
+ Root: <S extends import("@langchain/langgraph").StateDefinition>(sd: S) => import("@langchain/langgraph").AnnotationRoot<S>;
88
+ };
89
+ testScenarios: {
90
+ (): import("@langchain/langgraph").LastValue<any[]>;
91
+ (annotation: import("@langchain/langgraph").SingleReducer<any[], any[]>): import("@langchain/langgraph").BinaryOperatorAggregate<any[], any[]>;
92
+ Root: <S extends import("@langchain/langgraph").StateDefinition>(sd: S) => import("@langchain/langgraph").AnnotationRoot<S>;
93
+ };
80
94
  }, {
81
95
  userGoal: {
82
96
  (): import("@langchain/langgraph").LastValue<string>;
@@ -127,11 +141,33 @@ export declare const graph: import("@langchain/langgraph").CompiledStateGraph<{
127
141
  candidates: import("@langchain/langgraph").BinaryOperatorAggregate<any[], any[]>;
128
142
  customTools: import("@langchain/langgraph").BinaryOperatorAggregate<Record<string, string>, Record<string, string>>;
129
143
  collaborationLog: import("@langchain/langgraph").BinaryOperatorAggregate<string[], string[]>;
144
+ userFeedback: {
145
+ (): import("@langchain/langgraph").LastValue<string>;
146
+ (annotation: import("@langchain/langgraph").SingleReducer<string, string>): import("@langchain/langgraph").BinaryOperatorAggregate<string, string>;
147
+ Root: <S extends import("@langchain/langgraph").StateDefinition>(sd: S) => import("@langchain/langgraph").AnnotationRoot<S>;
148
+ };
149
+ testScenarios: {
150
+ (): import("@langchain/langgraph").LastValue<any[]>;
151
+ (annotation: import("@langchain/langgraph").SingleReducer<any[], any[]>): import("@langchain/langgraph").BinaryOperatorAggregate<any[], any[]>;
152
+ Root: <S extends import("@langchain/langgraph").StateDefinition>(sd: S) => import("@langchain/langgraph").AnnotationRoot<S>;
153
+ };
130
154
  }, import("@langchain/langgraph").StateDefinition, {
131
155
  architect: {
132
- spec: any;
133
- strategies: any[];
134
- needsClarification: any;
156
+ spec: import("../services/ai.service.js").WorkflowSpec;
157
+ strategies: {
158
+ strategyName: string;
159
+ aiModel: string;
160
+ suggestedName: string;
161
+ description: string;
162
+ nodes: {
163
+ type: string;
164
+ purpose: string;
165
+ config?: any;
166
+ }[];
167
+ questions?: string[];
168
+ aiProvider?: string;
169
+ }[];
170
+ needsClarification: boolean | undefined;
135
171
  collaborationLog: string[];
136
172
  };
137
173
  engineer: {
@@ -141,8 +177,8 @@ export declare const graph: import("@langchain/langgraph").CompiledStateGraph<{
141
177
  workflowJson?: undefined;
142
178
  candidates?: undefined;
143
179
  } | {
144
- workflowJson: any;
145
180
  candidates: any[];
181
+ workflowJson?: undefined;
146
182
  };
147
183
  reviewer: import("@langchain/langgraph").UpdateType<{
148
184
  userGoal: {
@@ -194,6 +230,16 @@ export declare const graph: import("@langchain/langgraph").CompiledStateGraph<{
194
230
  candidates: import("@langchain/langgraph").BinaryOperatorAggregate<any[], any[]>;
195
231
  customTools: import("@langchain/langgraph").BinaryOperatorAggregate<Record<string, string>, Record<string, string>>;
196
232
  collaborationLog: import("@langchain/langgraph").BinaryOperatorAggregate<string[], string[]>;
233
+ userFeedback: {
234
+ (): import("@langchain/langgraph").LastValue<string>;
235
+ (annotation: import("@langchain/langgraph").SingleReducer<string, string>): import("@langchain/langgraph").BinaryOperatorAggregate<string, string>;
236
+ Root: <S extends import("@langchain/langgraph").StateDefinition>(sd: S) => import("@langchain/langgraph").AnnotationRoot<S>;
237
+ };
238
+ testScenarios: {
239
+ (): import("@langchain/langgraph").LastValue<any[]>;
240
+ (annotation: import("@langchain/langgraph").SingleReducer<any[], any[]>): import("@langchain/langgraph").BinaryOperatorAggregate<any[], any[]>;
241
+ Root: <S extends import("@langchain/langgraph").StateDefinition>(sd: S) => import("@langchain/langgraph").AnnotationRoot<S>;
242
+ };
197
243
  }>;
198
244
  supervisor: {
199
245
  workflowJson?: undefined;
@@ -252,6 +298,16 @@ export declare const graph: import("@langchain/langgraph").CompiledStateGraph<{
252
298
  candidates: import("@langchain/langgraph").BinaryOperatorAggregate<any[], any[]>;
253
299
  customTools: import("@langchain/langgraph").BinaryOperatorAggregate<Record<string, string>, Record<string, string>>;
254
300
  collaborationLog: import("@langchain/langgraph").BinaryOperatorAggregate<string[], string[]>;
301
+ userFeedback: {
302
+ (): import("@langchain/langgraph").LastValue<string>;
303
+ (annotation: import("@langchain/langgraph").SingleReducer<string, string>): import("@langchain/langgraph").BinaryOperatorAggregate<string, string>;
304
+ Root: <S extends import("@langchain/langgraph").StateDefinition>(sd: S) => import("@langchain/langgraph").AnnotationRoot<S>;
305
+ };
306
+ testScenarios: {
307
+ (): import("@langchain/langgraph").LastValue<any[]>;
308
+ (annotation: import("@langchain/langgraph").SingleReducer<any[], any[]>): import("@langchain/langgraph").BinaryOperatorAggregate<any[], any[]>;
309
+ Root: <S extends import("@langchain/langgraph").StateDefinition>(sd: S) => import("@langchain/langgraph").AnnotationRoot<S>;
310
+ };
255
311
  }>;
256
312
  }, unknown, unknown>;
257
313
  /**
@@ -310,6 +366,16 @@ export declare const runAgenticWorkflow: (goal: string, initialState?: Partial<t
310
366
  candidates: import("@langchain/langgraph").BinaryOperatorAggregate<any[], any[]>;
311
367
  customTools: import("@langchain/langgraph").BinaryOperatorAggregate<Record<string, string>, Record<string, string>>;
312
368
  collaborationLog: import("@langchain/langgraph").BinaryOperatorAggregate<string[], string[]>;
369
+ userFeedback: {
370
+ (): import("@langchain/langgraph").LastValue<string>;
371
+ (annotation: import("@langchain/langgraph").SingleReducer<string, string>): import("@langchain/langgraph").BinaryOperatorAggregate<string, string>;
372
+ Root: <S extends import("@langchain/langgraph").StateDefinition>(sd: S) => import("@langchain/langgraph").AnnotationRoot<S>;
373
+ };
374
+ testScenarios: {
375
+ (): import("@langchain/langgraph").LastValue<any[]>;
376
+ (annotation: import("@langchain/langgraph").SingleReducer<any[], any[]>): import("@langchain/langgraph").BinaryOperatorAggregate<any[], any[]>;
377
+ Root: <S extends import("@langchain/langgraph").StateDefinition>(sd: S) => import("@langchain/langgraph").AnnotationRoot<S>;
378
+ };
313
379
  }>>;
314
380
  /**
315
381
  * Run the Agentic Workflow with Streaming
@@ -318,9 +384,21 @@ export declare const runAgenticWorkflow: (goal: string, initialState?: Partial<t
318
384
  */
319
385
  export declare const runAgenticWorkflowStream: (goal: string, threadId?: string) => Promise<import("@langchain/core/utils/stream").IterableReadableStream<{
320
386
  architect?: {
321
- spec: any;
322
- strategies: any[];
323
- needsClarification: any;
387
+ spec: import("../services/ai.service.js").WorkflowSpec;
388
+ strategies: {
389
+ strategyName: string;
390
+ aiModel: string;
391
+ suggestedName: string;
392
+ description: string;
393
+ nodes: {
394
+ type: string;
395
+ purpose: string;
396
+ config?: any;
397
+ }[];
398
+ questions?: string[];
399
+ aiProvider?: string;
400
+ }[];
401
+ needsClarification: boolean | undefined;
324
402
  collaborationLog: string[];
325
403
  } | undefined;
326
404
  engineer?: {
@@ -330,8 +408,8 @@ export declare const runAgenticWorkflowStream: (goal: string, threadId?: string)
330
408
  workflowJson?: undefined;
331
409
  candidates?: undefined;
332
410
  } | {
333
- workflowJson: any;
334
411
  candidates: any[];
412
+ workflowJson?: undefined;
335
413
  } | undefined;
336
414
  reviewer?: import("@langchain/langgraph").UpdateType<{
337
415
  userGoal: {
@@ -383,6 +461,16 @@ export declare const runAgenticWorkflowStream: (goal: string, threadId?: string)
383
461
  candidates: import("@langchain/langgraph").BinaryOperatorAggregate<any[], any[]>;
384
462
  customTools: import("@langchain/langgraph").BinaryOperatorAggregate<Record<string, string>, Record<string, string>>;
385
463
  collaborationLog: import("@langchain/langgraph").BinaryOperatorAggregate<string[], string[]>;
464
+ userFeedback: {
465
+ (): import("@langchain/langgraph").LastValue<string>;
466
+ (annotation: import("@langchain/langgraph").SingleReducer<string, string>): import("@langchain/langgraph").BinaryOperatorAggregate<string, string>;
467
+ Root: <S extends import("@langchain/langgraph").StateDefinition>(sd: S) => import("@langchain/langgraph").AnnotationRoot<S>;
468
+ };
469
+ testScenarios: {
470
+ (): import("@langchain/langgraph").LastValue<any[]>;
471
+ (annotation: import("@langchain/langgraph").SingleReducer<any[], any[]>): import("@langchain/langgraph").BinaryOperatorAggregate<any[], any[]>;
472
+ Root: <S extends import("@langchain/langgraph").StateDefinition>(sd: S) => import("@langchain/langgraph").AnnotationRoot<S>;
473
+ };
386
474
  }> | undefined;
387
475
  supervisor?: {
388
476
  workflowJson?: undefined;
@@ -441,6 +529,16 @@ export declare const runAgenticWorkflowStream: (goal: string, threadId?: string)
441
529
  candidates: import("@langchain/langgraph").BinaryOperatorAggregate<any[], any[]>;
442
530
  customTools: import("@langchain/langgraph").BinaryOperatorAggregate<Record<string, string>, Record<string, string>>;
443
531
  collaborationLog: import("@langchain/langgraph").BinaryOperatorAggregate<string[], string[]>;
532
+ userFeedback: {
533
+ (): import("@langchain/langgraph").LastValue<string>;
534
+ (annotation: import("@langchain/langgraph").SingleReducer<string, string>): import("@langchain/langgraph").BinaryOperatorAggregate<string, string>;
535
+ Root: <S extends import("@langchain/langgraph").StateDefinition>(sd: S) => import("@langchain/langgraph").AnnotationRoot<S>;
536
+ };
537
+ testScenarios: {
538
+ (): import("@langchain/langgraph").LastValue<any[]>;
539
+ (annotation: import("@langchain/langgraph").SingleReducer<any[], any[]>): import("@langchain/langgraph").BinaryOperatorAggregate<any[], any[]>;
540
+ Root: <S extends import("@langchain/langgraph").StateDefinition>(sd: S) => import("@langchain/langgraph").AnnotationRoot<S>;
541
+ };
444
542
  }> | undefined;
445
543
  }>>;
446
544
  /**
@@ -496,4 +594,14 @@ export declare const resumeAgenticWorkflow: (threadId: string, input?: any) => P
496
594
  candidates: import("@langchain/langgraph").BinaryOperatorAggregate<any[], any[]>;
497
595
  customTools: import("@langchain/langgraph").BinaryOperatorAggregate<Record<string, string>, Record<string, string>>;
498
596
  collaborationLog: import("@langchain/langgraph").BinaryOperatorAggregate<string[], string[]>;
597
+ userFeedback: {
598
+ (): import("@langchain/langgraph").LastValue<string>;
599
+ (annotation: import("@langchain/langgraph").SingleReducer<string, string>): import("@langchain/langgraph").BinaryOperatorAggregate<string, string>;
600
+ Root: <S extends import("@langchain/langgraph").StateDefinition>(sd: S) => import("@langchain/langgraph").AnnotationRoot<S>;
601
+ };
602
+ testScenarios: {
603
+ (): import("@langchain/langgraph").LastValue<any[]>;
604
+ (annotation: import("@langchain/langgraph").SingleReducer<any[], any[]>): import("@langchain/langgraph").BinaryOperatorAggregate<any[], any[]>;
605
+ Root: <S extends import("@langchain/langgraph").StateDefinition>(sd: S) => import("@langchain/langgraph").AnnotationRoot<S>;
606
+ };
499
607
  }>>;
@@ -53,7 +53,7 @@ const workflow = new StateGraph(TeamState)
53
53
  // Compile the graph with persistence and interrupts
54
54
  export const graph = workflow.compile({
55
55
  checkpointer: checkpointer,
56
- interruptBefore: ["qa"],
56
+ interruptBefore: ["engineer", "qa"],
57
57
  });
58
58
  /**
59
59
  * Run the Agentic Workflow
@@ -1,7 +1,19 @@
1
1
  import { TeamState } from "../state.js";
2
2
  export declare const architectNode: (state: typeof TeamState.State) => Promise<{
3
- spec: any;
4
- strategies: any[];
5
- needsClarification: any;
3
+ spec: import("../../services/ai.service.js").WorkflowSpec;
4
+ strategies: {
5
+ strategyName: string;
6
+ aiModel: string;
7
+ suggestedName: string;
8
+ description: string;
9
+ nodes: {
10
+ type: string;
11
+ purpose: string;
12
+ config?: any;
13
+ }[];
14
+ questions?: string[];
15
+ aiProvider?: string;
16
+ }[];
17
+ needsClarification: boolean | undefined;
6
18
  collaborationLog: string[];
7
19
  }>;
@@ -33,9 +33,18 @@ export const architectNode = async (state) => {
33
33
  // Multi-agent collaboration: generate an alternative strategy in parallel with the primary.
34
34
  // Both are handed off to separate Engineer agents that run concurrently.
35
35
  const alternativeSpec = await aiService.generateAlternativeSpec(state.userGoal, spec);
36
+ const alternativeModel = aiService.getAlternativeModel();
36
37
  const strategies = [
37
- { ...spec, strategyName: "Primary Strategy" },
38
- { ...alternativeSpec, strategyName: "Alternative Strategy" },
38
+ {
39
+ ...spec,
40
+ strategyName: "Primary Strategy",
41
+ aiModel: aiService.getDefaultModel()
42
+ },
43
+ {
44
+ ...alternativeSpec,
45
+ strategyName: "Alternative Strategy",
46
+ aiModel: alternativeModel
47
+ },
39
48
  ];
40
49
  const logEntry = `Architect: Generated 2 strategies — "${strategies[0].suggestedName}" (primary) and "${strategies[1].suggestedName}" (alternative)`;
41
50
  console.log(`[Architect] ${logEntry}`);
@@ -6,6 +6,6 @@ export declare const engineerNode: (state: typeof TeamState.State) => Promise<{
6
6
  workflowJson?: undefined;
7
7
  candidates?: undefined;
8
8
  } | {
9
- workflowJson: any;
10
9
  candidates: any[];
10
+ workflowJson?: undefined;
11
11
  }>;