@dawn-ai/langchain 0.0.2

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 ADDED
@@ -0,0 +1,10 @@
1
+ # @dawn-ai/langchain
2
+
3
+ LangChain backend adapter for Dawn `chain` route kind.
4
+
5
+ Public surface:
6
+ - `ChainAdapter` — `BackendAdapter` implementation for LCEL runnables
7
+ - `convertTools()` — converts Dawn tools to LangChain `DynamicStructuredTool`
8
+ - `toolLoop()` — Dawn-owned ReAct tool execution loop (no AgentExecutor dependency)
9
+
10
+ This package enables Dawn routes to use LangChain LCEL chains with filesystem-driven tool discovery and Dawn-owned execution semantics.
@@ -0,0 +1,3 @@
1
+ import type { BackendAdapter } from "@dawn-ai/sdk";
2
+ export declare const chainAdapter: BackendAdapter;
3
+ //# sourceMappingURL=chain-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chain-adapter.d.ts","sourceRoot":"","sources":["../src/chain-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAqBlD,eAAO,MAAM,YAAY,EAAE,cA+B1B,CAAA"}
@@ -0,0 +1,27 @@
1
+ function assertRunnableLike(entry) {
2
+ if (typeof entry !== "object" ||
3
+ entry === null ||
4
+ !("invoke" in entry) ||
5
+ typeof entry.invoke !== "function") {
6
+ throw new Error("Chain entry must expose invoke(input) — expected a LangChain Runnable");
7
+ }
8
+ }
9
+ export const chainAdapter = {
10
+ kind: "chain",
11
+ async execute(entry, input, context) {
12
+ assertRunnableLike(entry);
13
+ return await entry.invoke(input, { signal: context.signal });
14
+ },
15
+ async *stream(entry, input, context) {
16
+ assertRunnableLike(entry);
17
+ if (typeof entry.stream !== "function") {
18
+ yield await entry.invoke(input, { signal: context.signal });
19
+ return;
20
+ }
21
+ const streamResult = entry.stream(input, { signal: context.signal });
22
+ const iterable = streamResult instanceof Promise ? await streamResult : streamResult;
23
+ for await (const chunk of iterable) {
24
+ yield chunk;
25
+ }
26
+ },
27
+ };
@@ -0,0 +1,4 @@
1
+ export { chainAdapter } from "./chain-adapter.js";
2
+ export { convertToolToLangChain } from "./tool-converter.js";
3
+ export { executeWithToolLoop } from "./tool-loop.js";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAA;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export { chainAdapter } from "./chain-adapter.js";
2
+ export { convertToolToLangChain } from "./tool-converter.js";
3
+ export { executeWithToolLoop } from "./tool-loop.js";
@@ -0,0 +1,12 @@
1
+ import { DynamicStructuredTool } from "@langchain/core/tools";
2
+ interface DawnToolDefinition {
3
+ readonly description?: string;
4
+ readonly name: string;
5
+ readonly run: (input: unknown, context: {
6
+ readonly signal: AbortSignal;
7
+ }) => Promise<unknown> | unknown;
8
+ readonly schema?: unknown;
9
+ }
10
+ export declare function convertToolToLangChain(tool: DawnToolDefinition): DynamicStructuredTool;
11
+ export {};
12
+ //# sourceMappingURL=tool-converter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-converter.d.ts","sourceRoot":"","sources":["../src/tool-converter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAA;AAG7D,UAAU,kBAAkB;IAC1B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,GAAG,EAAE,CACZ,KAAK,EAAE,OAAO,EACd,OAAO,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;KAAE,KACtC,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAA;IAC/B,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAC1B;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,kBAAkB,GAAG,qBAAqB,CAetF"}
@@ -0,0 +1,24 @@
1
+ import { DynamicStructuredTool } from "@langchain/core/tools";
2
+ import { z } from "zod";
3
+ export function convertToolToLangChain(tool) {
4
+ const schema = isZodObject(tool.schema) ? tool.schema : z.record(z.string(), z.unknown());
5
+ // Cast through unknown to bridge the dual-Zod version type incompatibility
6
+ // (package uses zod@3.24.4; @langchain/core uses zod@3.25.x — structurally identical at runtime)
7
+ return new DynamicStructuredTool({
8
+ name: tool.name,
9
+ description: tool.description ?? "",
10
+ schema: schema,
11
+ func: async (input, _runManager, config) => {
12
+ const signal = config?.signal ?? new AbortController().signal;
13
+ const result = await tool.run(input, { signal });
14
+ return JSON.stringify(result);
15
+ },
16
+ });
17
+ }
18
+ function isZodObject(value) {
19
+ return (typeof value === "object" &&
20
+ value !== null &&
21
+ "_def" in value &&
22
+ typeof value._def === "object" &&
23
+ value._def !== null);
24
+ }
@@ -0,0 +1,18 @@
1
+ interface ToolExecutor {
2
+ readonly name: string;
3
+ readonly run: (input: unknown, context: {
4
+ readonly signal: AbortSignal;
5
+ }) => Promise<unknown> | unknown;
6
+ }
7
+ export interface ExecuteWithToolLoopOptions {
8
+ readonly chain: {
9
+ readonly invoke: (input: unknown) => Promise<unknown>;
10
+ };
11
+ readonly input: unknown;
12
+ readonly tools: readonly ToolExecutor[];
13
+ readonly signal: AbortSignal;
14
+ readonly maxIterations?: number;
15
+ }
16
+ export declare function executeWithToolLoop(options: ExecuteWithToolLoopOptions): Promise<unknown>;
17
+ export {};
18
+ //# sourceMappingURL=tool-loop.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-loop.d.ts","sourceRoot":"","sources":["../src/tool-loop.ts"],"names":[],"mappings":"AAIA,UAAU,YAAY;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,GAAG,EAAE,CACZ,KAAK,EAAE,OAAO,EACd,OAAO,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;KAAE,KACtC,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAA;CAChC;AAED,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;KAAE,CAAA;IACzE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;IACvB,QAAQ,CAAC,KAAK,EAAE,SAAS,YAAY,EAAE,CAAA;IACvC,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;IAC5B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAChC;AAED,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,0BAA0B,GAAG,OAAO,CAAC,OAAO,CAAC,CA8C/F"}
@@ -0,0 +1,48 @@
1
+ import { AIMessage, ToolMessage } from "@langchain/core/messages";
2
+ const DEFAULT_MAX_ITERATIONS = 10;
3
+ export async function executeWithToolLoop(options) {
4
+ const { chain, input, tools, signal, maxIterations = DEFAULT_MAX_ITERATIONS } = options;
5
+ const toolMap = new Map(tools.map((t) => [t.name, t]));
6
+ let currentInput = input;
7
+ for (let i = 0; i < maxIterations; i++) {
8
+ const result = await chain.invoke(currentInput);
9
+ if (!isAIMessageWithToolCalls(result)) {
10
+ return result;
11
+ }
12
+ const toolMessages = await Promise.all(result.tool_calls.map(async (call) => {
13
+ const tool = toolMap.get(call.name);
14
+ if (!tool) {
15
+ return new ToolMessage({
16
+ content: JSON.stringify({ error: `Unknown tool: ${call.name}` }),
17
+ tool_call_id: call.id ?? "",
18
+ });
19
+ }
20
+ try {
21
+ const output = await tool.run(call.args, { signal });
22
+ return new ToolMessage({
23
+ content: JSON.stringify(output),
24
+ tool_call_id: call.id ?? "",
25
+ });
26
+ }
27
+ catch (error) {
28
+ return new ToolMessage({
29
+ content: JSON.stringify({
30
+ error: error instanceof Error ? error.message : String(error),
31
+ }),
32
+ tool_call_id: call.id ?? "",
33
+ });
34
+ }
35
+ }));
36
+ currentInput = [
37
+ ...(Array.isArray(currentInput) ? currentInput : []),
38
+ result,
39
+ ...toolMessages,
40
+ ];
41
+ }
42
+ throw new Error(`Tool execution loop exceeded maximum ${maxIterations} iterations`);
43
+ }
44
+ function isAIMessageWithToolCalls(value) {
45
+ return (value instanceof AIMessage &&
46
+ Array.isArray(value.tool_calls) &&
47
+ value.tool_calls.length > 0);
48
+ }
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "@dawn-ai/langchain",
3
+ "version": "0.0.2",
4
+ "private": false,
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "homepage": "https://github.com/cacheplane/dawnai/tree/main/packages/langchain#readme",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/cacheplane/dawnai.git",
11
+ "directory": "packages/langchain"
12
+ },
13
+ "bugs": {
14
+ "url": "https://github.com/cacheplane/dawnai/issues"
15
+ },
16
+ "engines": {
17
+ "node": ">=22.12.0"
18
+ },
19
+ "files": [
20
+ "dist"
21
+ ],
22
+ "types": "./dist/index.d.ts",
23
+ "exports": {
24
+ ".": {
25
+ "types": "./dist/index.d.ts",
26
+ "default": "./dist/index.js"
27
+ }
28
+ },
29
+ "publishConfig": {
30
+ "access": "public"
31
+ },
32
+ "dependencies": {
33
+ "@dawn-ai/sdk": "0.0.2"
34
+ },
35
+ "peerDependencies": {
36
+ "@langchain/core": ">=0.3.0"
37
+ },
38
+ "devDependencies": {
39
+ "@langchain/core": "0.3.62",
40
+ "@types/node": "25.6.0",
41
+ "zod": "3.24.4",
42
+ "@dawn-ai/config-typescript": "0.0.2"
43
+ },
44
+ "scripts": {
45
+ "build": "tsc -b tsconfig.json",
46
+ "lint": "biome check --config-path ../config-biome/biome.json package.json src test tsconfig.json vitest.config.ts",
47
+ "test": "vitest --run --config vitest.config.ts",
48
+ "typecheck": "tsc --noEmit"
49
+ }
50
+ }