create-langgraph-app 1.0.0 → 1.1.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/dist/create.js +81 -100
- package/package.json +1 -1
package/dist/create.js
CHANGED
|
@@ -72,17 +72,17 @@ function generateEnv(config) {
|
|
|
72
72
|
}
|
|
73
73
|
function generatePackageJson(config) {
|
|
74
74
|
const deps = {
|
|
75
|
-
"@langchain/core": "^1.1.
|
|
76
|
-
"@langchain/langgraph": "^1.2
|
|
77
|
-
"@langchain/langgraph-supervisor": "^1.0.
|
|
75
|
+
"@langchain/core": "^1.1.48",
|
|
76
|
+
"@langchain/langgraph": "^1.3.2",
|
|
77
|
+
"@langchain/langgraph-supervisor": "^1.0.3",
|
|
78
78
|
"@langchain/mcp-adapters": "^1.1.3",
|
|
79
|
-
dotenv: "^17.4.
|
|
80
|
-
fastify: "^5.8.
|
|
79
|
+
dotenv: "^17.4.2",
|
|
80
|
+
fastify: "^5.8.5",
|
|
81
81
|
langchain: "^1.3.0",
|
|
82
|
-
zod: "^4.3
|
|
82
|
+
zod: "^4.4.3",
|
|
83
83
|
};
|
|
84
84
|
if (config.patterns.includes("swarm")) {
|
|
85
|
-
deps["@langchain/langgraph-swarm"] = "^1.0.
|
|
85
|
+
deps["@langchain/langgraph-swarm"] = "^1.0.2";
|
|
86
86
|
}
|
|
87
87
|
if (config.patterns.includes("rag")) {
|
|
88
88
|
deps["@langchain/textsplitters"] = "^1.0.1";
|
|
@@ -109,10 +109,10 @@ function generatePackageJson(config) {
|
|
|
109
109
|
},
|
|
110
110
|
dependencies: Object.fromEntries(Object.entries(deps).sort(([a], [b]) => a.localeCompare(b))),
|
|
111
111
|
devDependencies: {
|
|
112
|
-
"@types/node": "^25.
|
|
113
|
-
tsx: "^4.
|
|
114
|
-
typescript: "^6.0.
|
|
115
|
-
vitest: "^4.1.
|
|
112
|
+
"@types/node": "^25.9.1",
|
|
113
|
+
tsx: "^4.22.4",
|
|
114
|
+
typescript: "^6.0.3",
|
|
115
|
+
vitest: "^4.1.8",
|
|
116
116
|
},
|
|
117
117
|
};
|
|
118
118
|
return JSON.stringify(pkg, null, 2) + "\n";
|
|
@@ -157,6 +157,7 @@ const API_KEY_MAP: Record<LlmProvider, string> = {
|
|
|
157
157
|
|
|
158
158
|
export const LLM_PROVIDER = resolveProvider();
|
|
159
159
|
|
|
160
|
+
// Fail fast: validate the selected provider's key at startup.
|
|
160
161
|
const requiredKey = API_KEY_MAP[LLM_PROVIDER];
|
|
161
162
|
if (requiredKey && !process.env[requiredKey]) {
|
|
162
163
|
throw new Error(\`\${requiredKey} is required for provider "\${LLM_PROVIDER}" but not set in .env\`);
|
|
@@ -167,47 +168,54 @@ export const LLM_TEMPERATURE = Number(process.env.LLM_TEMPERATURE ?? 0);
|
|
|
167
168
|
export const PORT = Number(process.env.PORT ?? 3000);
|
|
168
169
|
`;
|
|
169
170
|
}
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
groq: "llama-3.3-70b-versatile",
|
|
179
|
-
ollama: "llama3.2",
|
|
171
|
+
// Per-provider class + constructor shape. The generated llm.ts only imports the
|
|
172
|
+
// provider that was selected, so the scaffold depends on a single LLM SDK.
|
|
173
|
+
const PROVIDER_LLM = {
|
|
174
|
+
openai: { pkg: "@langchain/openai", className: "ChatOpenAI", modelArg: "modelName", defaultModel: "gpt-4o-mini" },
|
|
175
|
+
anthropic: { pkg: "@langchain/anthropic", className: "ChatAnthropic", modelArg: "modelName", defaultModel: "claude-sonnet-4-20250514" },
|
|
176
|
+
google: { pkg: "@langchain/google-genai", className: "ChatGoogleGenerativeAI", modelArg: "model", defaultModel: "gemini-2.0-flash" },
|
|
177
|
+
groq: { pkg: "@langchain/groq", className: "ChatGroq", modelArg: "model", defaultModel: "llama-3.3-70b-versatile" },
|
|
178
|
+
ollama: { pkg: "@langchain/ollama", className: "ChatOllama", modelArg: "model", defaultModel: "llama3.2" },
|
|
180
179
|
};
|
|
180
|
+
function generateLlmConfig(config) {
|
|
181
|
+
const p = PROVIDER_LLM[config.provider] ?? PROVIDER_LLM.openai;
|
|
182
|
+
return `import type { BaseChatModel } from "@langchain/core/language_models/chat_models";
|
|
183
|
+
import { LLM_MODEL, LLM_TEMPERATURE } from "./env";
|
|
181
184
|
|
|
182
|
-
|
|
183
|
-
const model = LLM_MODEL ?? DEFAULTS[LLM_PROVIDER] ?? DEFAULTS.openai;
|
|
184
|
-
const temperature = LLM_TEMPERATURE;
|
|
185
|
+
const DEFAULT_MODEL = "${p.defaultModel}";
|
|
185
186
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
return new ChatGroq({ modelName: model, temperature });
|
|
198
|
-
}
|
|
199
|
-
case "ollama": {
|
|
200
|
-
const { ChatOllama } = require("@langchain/ollama");
|
|
201
|
-
return new ChatOllama({ model, temperature });
|
|
202
|
-
}
|
|
203
|
-
default: {
|
|
204
|
-
const { ChatOpenAI } = require("@langchain/openai");
|
|
205
|
-
return new ChatOpenAI({ modelName: model, temperature });
|
|
206
|
-
}
|
|
207
|
-
}
|
|
187
|
+
export interface LlmOptions {
|
|
188
|
+
model?: string;
|
|
189
|
+
temperature?: number;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
async function createLlm(opts: LlmOptions = {}): Promise<BaseChatModel> {
|
|
193
|
+
const model = opts.model ?? LLM_MODEL ?? DEFAULT_MODEL;
|
|
194
|
+
const temperature = opts.temperature ?? LLM_TEMPERATURE;
|
|
195
|
+
|
|
196
|
+
const { ${p.className} } = await import("${p.pkg}");
|
|
197
|
+
return new ${p.className}({ ${p.modelArg}: model, temperature });
|
|
208
198
|
}
|
|
209
199
|
|
|
210
|
-
|
|
200
|
+
let _default: Promise<BaseChatModel> | undefined;
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Returns a chat model.
|
|
204
|
+
*
|
|
205
|
+
* Called with no options it returns a memoized, shared instance (nothing is
|
|
206
|
+
* constructed until first use). Pass options to build a distinct model, e.g. a
|
|
207
|
+
* cheap router and a strong worker:
|
|
208
|
+
*
|
|
209
|
+
* const router = await getLlm({ model: "${p.defaultModel}" });
|
|
210
|
+
* const worker = await getLlm({ model: "<a-stronger-model>" });
|
|
211
|
+
*/
|
|
212
|
+
export function getLlm(opts?: LlmOptions): Promise<BaseChatModel> {
|
|
213
|
+
if (!opts || Object.keys(opts).length === 0) {
|
|
214
|
+
_default ??= createLlm();
|
|
215
|
+
return _default;
|
|
216
|
+
}
|
|
217
|
+
return createLlm(opts);
|
|
218
|
+
}
|
|
211
219
|
`;
|
|
212
220
|
}
|
|
213
221
|
function generateAgentFactory() {
|
|
@@ -255,49 +263,12 @@ export function makeSupervisor({ checkpointer, store, ...params }: MakeSuperviso
|
|
|
255
263
|
}
|
|
256
264
|
`;
|
|
257
265
|
}
|
|
258
|
-
function generateSupervisorApp() {
|
|
259
|
-
return `import { z } from "zod";
|
|
260
|
-
import { tool } from "@langchain/core/tools";
|
|
261
|
-
import { llm } from "./config/env";
|
|
262
|
-
import { makeAgent } from "./agents/factory";
|
|
263
|
-
import { makeSupervisor } from "./agents/supervisor";
|
|
264
|
-
|
|
265
|
-
const add = tool(async ({ a, b }) => String(a + b), {
|
|
266
|
-
name: "add", description: "Add two numbers",
|
|
267
|
-
schema: z.object({ a: z.number(), b: z.number() }),
|
|
268
|
-
});
|
|
269
|
-
|
|
270
|
-
const multiply = tool(async ({ a, b }) => String(a * b), {
|
|
271
|
-
name: "multiply", description: "Multiply two numbers",
|
|
272
|
-
schema: z.object({ a: z.number(), b: z.number() }),
|
|
273
|
-
});
|
|
274
|
-
|
|
275
|
-
export function createApp() {
|
|
276
|
-
const math = makeAgent({
|
|
277
|
-
name: "math_expert", llm,
|
|
278
|
-
tools: [add, multiply],
|
|
279
|
-
system: "You are a math expert. Use tools to compute answers.",
|
|
280
|
-
});
|
|
281
|
-
|
|
282
|
-
const writer = makeAgent({
|
|
283
|
-
name: "writer", llm, tools: [],
|
|
284
|
-
system: "You write crisp, structured answers.",
|
|
285
|
-
});
|
|
286
|
-
|
|
287
|
-
return makeSupervisor({
|
|
288
|
-
agents: [math, writer], llm,
|
|
289
|
-
outputMode: "last_message",
|
|
290
|
-
supervisorName: "supervisor",
|
|
291
|
-
});
|
|
292
|
-
}
|
|
293
|
-
`;
|
|
294
|
-
}
|
|
295
266
|
// Pattern-specific: only files for selected patterns are generated
|
|
296
267
|
function getPatternFiles(config) {
|
|
297
268
|
const files = [];
|
|
298
269
|
// Always include core files
|
|
299
270
|
files.push({ path: "src/config/env.ts", content: generateEnvConfig(config) });
|
|
300
|
-
files.push({ path: "src/config/llm.ts", content: generateLlmConfig() });
|
|
271
|
+
files.push({ path: "src/config/llm.ts", content: generateLlmConfig(config) });
|
|
301
272
|
files.push({ path: "src/agents/factory.ts", content: generateAgentFactory() });
|
|
302
273
|
files.push({ path: "src/agents/supervisor.ts", content: generateSupervisorHelper() });
|
|
303
274
|
// Index file — imports vary by selected patterns
|
|
@@ -306,7 +277,7 @@ function getPatternFiles(config) {
|
|
|
306
277
|
if (config.patterns.includes("supervisor")) {
|
|
307
278
|
files.push({
|
|
308
279
|
path: "src/apps/supervisor.ts",
|
|
309
|
-
content: `import {
|
|
280
|
+
content: `import { getLlm } from "../config/llm";
|
|
310
281
|
import { z } from "zod";
|
|
311
282
|
import { tool } from "@langchain/core/tools";
|
|
312
283
|
import { makeAgent } from "../agents/factory";
|
|
@@ -317,7 +288,9 @@ const add = tool(async ({ a, b }) => String(a + b), {
|
|
|
317
288
|
schema: z.object({ a: z.number(), b: z.number() }),
|
|
318
289
|
});
|
|
319
290
|
|
|
320
|
-
export function createSupervisorApp() {
|
|
291
|
+
export async function createSupervisorApp() {
|
|
292
|
+
const llm = await getLlm();
|
|
293
|
+
|
|
321
294
|
const math = makeAgent({
|
|
322
295
|
name: "math_expert", llm,
|
|
323
296
|
tools: [add],
|
|
@@ -339,7 +312,7 @@ export function createSupervisorApp() {
|
|
|
339
312
|
});
|
|
340
313
|
imports.push(`import { createSupervisorApp } from "./apps/supervisor";`);
|
|
341
314
|
demos.push(` console.log("=== Supervisor Demo ===");
|
|
342
|
-
const supervisorApp = createSupervisorApp();
|
|
315
|
+
const supervisorApp = await createSupervisorApp();
|
|
343
316
|
const sup = await supervisorApp.invoke(
|
|
344
317
|
{ messages: [{ role: "user", content: "What is 10 + 15?" }] },
|
|
345
318
|
{ configurable: { thread_id: "demo" } }
|
|
@@ -405,7 +378,7 @@ export function createHandoffTool({ agentName, description }: { agentName: strin
|
|
|
405
378
|
});
|
|
406
379
|
files.push({
|
|
407
380
|
path: "src/apps/swarm.ts",
|
|
408
|
-
content: `import {
|
|
381
|
+
content: `import { getLlm } from "../config/llm";
|
|
409
382
|
import { z } from "zod";
|
|
410
383
|
import { tool } from "@langchain/core/tools";
|
|
411
384
|
import { makeAgent } from "../agents/factory";
|
|
@@ -422,7 +395,9 @@ const multiply = tool(async ({ a, b }) => String(a * b), {
|
|
|
422
395
|
schema: z.object({ a: z.number(), b: z.number() }),
|
|
423
396
|
});
|
|
424
397
|
|
|
425
|
-
export function createSwarmApp() {
|
|
398
|
+
export async function createSwarmApp() {
|
|
399
|
+
const llm = await getLlm();
|
|
400
|
+
|
|
426
401
|
const alice = makeAgent({
|
|
427
402
|
name: "alice", llm,
|
|
428
403
|
tools: [add, createHandoffTool({ agentName: "bob" })],
|
|
@@ -444,7 +419,7 @@ export function createSwarmApp() {
|
|
|
444
419
|
});
|
|
445
420
|
imports.push(`import { createSwarmApp } from "./apps/swarm";`);
|
|
446
421
|
demos.push(` console.log("\\n=== Swarm Demo ===");
|
|
447
|
-
const swarmApp = createSwarmApp();
|
|
422
|
+
const swarmApp = await createSwarmApp();
|
|
448
423
|
const swarm = await swarmApp.invoke(
|
|
449
424
|
{ messages: [{ role: "user", content: "add 5 and 7, then talk to bob and multiply by 3" }] },
|
|
450
425
|
{ configurable: { thread_id: "swarm-demo" } }
|
|
@@ -457,7 +432,7 @@ export function createSwarmApp() {
|
|
|
457
432
|
content: `import { z } from "zod";
|
|
458
433
|
import { tool } from "@langchain/core/tools";
|
|
459
434
|
import { interrupt } from "@langchain/langgraph";
|
|
460
|
-
import {
|
|
435
|
+
import { getLlm } from "../config/llm";
|
|
461
436
|
import { makeAgent } from "../agents/factory";
|
|
462
437
|
import { makeSupervisor } from "../agents/supervisor";
|
|
463
438
|
|
|
@@ -479,7 +454,9 @@ const deleteRecord = tool(
|
|
|
479
454
|
}
|
|
480
455
|
);
|
|
481
456
|
|
|
482
|
-
export function createInterruptApp() {
|
|
457
|
+
export async function createInterruptApp() {
|
|
458
|
+
const llm = await getLlm();
|
|
459
|
+
|
|
483
460
|
const dbAdmin = makeAgent({
|
|
484
461
|
name: "db_admin", llm,
|
|
485
462
|
tools: [deleteRecord],
|
|
@@ -497,7 +474,7 @@ export function createInterruptApp() {
|
|
|
497
474
|
imports.push(`import { Command } from "@langchain/langgraph";`);
|
|
498
475
|
imports.push(`import { createInterruptApp } from "./apps/interrupt";`);
|
|
499
476
|
demos.push(` console.log("\\n=== Human-in-the-Loop Demo ===");
|
|
500
|
-
const interruptApp = createInterruptApp();
|
|
477
|
+
const interruptApp = await createInterruptApp();
|
|
501
478
|
const hitlCfg = { configurable: { thread_id: "hitl-demo" } };
|
|
502
479
|
await interruptApp.invoke(
|
|
503
480
|
{ messages: [{ role: "user", content: "delete record rec_2" }] },
|
|
@@ -514,7 +491,7 @@ export function createInterruptApp() {
|
|
|
514
491
|
files.push({
|
|
515
492
|
path: "src/apps/analyst.ts",
|
|
516
493
|
content: `import { z } from "zod";
|
|
517
|
-
import {
|
|
494
|
+
import { getLlm } from "../config/llm";
|
|
518
495
|
import { makeAgent } from "../agents/factory";
|
|
519
496
|
import { makeSupervisor } from "../agents/supervisor";
|
|
520
497
|
|
|
@@ -524,7 +501,9 @@ const SummarySchema = z.object({
|
|
|
524
501
|
sentiment: z.enum(["positive", "negative", "neutral"]),
|
|
525
502
|
});
|
|
526
503
|
|
|
527
|
-
export function createAnalystApp() {
|
|
504
|
+
export async function createAnalystApp() {
|
|
505
|
+
const llm = await getLlm();
|
|
506
|
+
|
|
528
507
|
const analyst = makeAgent({
|
|
529
508
|
name: "analyst", llm, tools: [],
|
|
530
509
|
system: "Analyze text and produce structured summaries.",
|
|
@@ -541,7 +520,7 @@ export function createAnalystApp() {
|
|
|
541
520
|
});
|
|
542
521
|
imports.push(`import { createAnalystApp } from "./apps/analyst";`);
|
|
543
522
|
demos.push(` console.log("\\n=== Structured Output Demo ===");
|
|
544
|
-
const analystApp = createAnalystApp();
|
|
523
|
+
const analystApp = await createAnalystApp();
|
|
545
524
|
const analysis = await analystApp.invoke(
|
|
546
525
|
{ messages: [{ role: "user", content: "Analyze: Revenue grew 25% but churn increased 8%." }] },
|
|
547
526
|
{ configurable: { thread_id: "analyst-demo" } }
|
|
@@ -551,14 +530,16 @@ export function createAnalystApp() {
|
|
|
551
530
|
if (config.patterns.includes("rag")) {
|
|
552
531
|
files.push({
|
|
553
532
|
path: "src/apps/rag.ts",
|
|
554
|
-
content: `import {
|
|
533
|
+
content: `import { getLlm } from "../config/llm";
|
|
555
534
|
import { makeAgent } from "../agents/factory";
|
|
556
535
|
import { makeSupervisor } from "../agents/supervisor";
|
|
557
536
|
// TODO: Add your vector store, embeddings, and retrieval tool here.
|
|
558
537
|
// See the full starter kit for a complete RAG implementation:
|
|
559
538
|
// https://github.com/ac12644/langgraph-starter-kit
|
|
560
539
|
|
|
561
|
-
export function createRagApp() {
|
|
540
|
+
export async function createRagApp() {
|
|
541
|
+
const llm = await getLlm();
|
|
542
|
+
|
|
562
543
|
const ragAgent = makeAgent({
|
|
563
544
|
name: "rag_agent", llm, tools: [],
|
|
564
545
|
system: "You are a knowledgeable assistant. Answer questions based on your knowledge.",
|
|
@@ -574,7 +555,7 @@ export function createRagApp() {
|
|
|
574
555
|
});
|
|
575
556
|
imports.push(`import { createRagApp } from "./apps/rag";`);
|
|
576
557
|
demos.push(` console.log("\\n=== RAG Demo ===");
|
|
577
|
-
const ragApp = createRagApp();
|
|
558
|
+
const ragApp = await createRagApp();
|
|
578
559
|
const rag = await ragApp.invoke(
|
|
579
560
|
{ messages: [{ role: "user", content: "What is RAG and how does it work?" }] },
|
|
580
561
|
{ configurable: { thread_id: "rag-demo" } }
|