@aerostack/sdk-langchain 0.10.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 (36) hide show
  1. package/README.md +62 -0
  2. package/dist/commonjs/__tests__/converter.test.d.ts +2 -0
  3. package/dist/commonjs/__tests__/converter.test.d.ts.map +1 -0
  4. package/dist/commonjs/__tests__/converter.test.js +125 -0
  5. package/dist/commonjs/__tests__/converter.test.js.map +1 -0
  6. package/dist/commonjs/__tests__/index.test.d.ts +2 -0
  7. package/dist/commonjs/__tests__/index.test.d.ts.map +1 -0
  8. package/dist/commonjs/__tests__/index.test.js +20 -0
  9. package/dist/commonjs/__tests__/index.test.js.map +1 -0
  10. package/dist/commonjs/converter.d.ts +22 -0
  11. package/dist/commonjs/converter.d.ts.map +1 -0
  12. package/dist/commonjs/converter.js +72 -0
  13. package/dist/commonjs/converter.js.map +1 -0
  14. package/dist/commonjs/index.d.ts +69 -0
  15. package/dist/commonjs/index.d.ts.map +1 -0
  16. package/dist/commonjs/index.js +80 -0
  17. package/dist/commonjs/index.js.map +1 -0
  18. package/dist/commonjs/package.json +3 -0
  19. package/dist/esm/__tests__/converter.test.d.ts +2 -0
  20. package/dist/esm/__tests__/converter.test.d.ts.map +1 -0
  21. package/dist/esm/__tests__/converter.test.js +123 -0
  22. package/dist/esm/__tests__/converter.test.js.map +1 -0
  23. package/dist/esm/__tests__/index.test.d.ts +2 -0
  24. package/dist/esm/__tests__/index.test.d.ts.map +1 -0
  25. package/dist/esm/__tests__/index.test.js +18 -0
  26. package/dist/esm/__tests__/index.test.js.map +1 -0
  27. package/dist/esm/converter.d.ts +22 -0
  28. package/dist/esm/converter.d.ts.map +1 -0
  29. package/dist/esm/converter.js +68 -0
  30. package/dist/esm/converter.js.map +1 -0
  31. package/dist/esm/index.d.ts +69 -0
  32. package/dist/esm/index.d.ts.map +1 -0
  33. package/dist/esm/index.js +74 -0
  34. package/dist/esm/index.js.map +1 -0
  35. package/dist/esm/package.json +3 -0
  36. package/package.json +66 -0
package/README.md ADDED
@@ -0,0 +1,62 @@
1
+ # @aerostack/sdk-langchain
2
+
3
+ Use [Aerostack](https://aerostack.dev) workspace tools as [LangChain.js](https://js.langchain.com/) tools.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install @aerostack/sdk-langchain @langchain/core
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```typescript
14
+ import { ChatOpenAI } from '@langchain/openai';
15
+ import { createReactAgent } from '@langchain/langgraph/prebuilt';
16
+ import { getTools } from '@aerostack/sdk-langchain';
17
+
18
+ const { tools } = await getTools({ workspace: 'my-workspace', token: 'mwt_...' });
19
+
20
+ const agent = createReactAgent({
21
+ llm: new ChatOpenAI({ model: 'gpt-4o' }),
22
+ tools,
23
+ });
24
+
25
+ const result = await agent.invoke({
26
+ messages: [{ role: 'user', content: 'Create a GitHub issue for the login bug' }],
27
+ });
28
+ ```
29
+
30
+ ## Direct Tool Binding
31
+
32
+ ```typescript
33
+ import { ChatAnthropic } from '@langchain/anthropic';
34
+ import { getTools } from '@aerostack/sdk-langchain';
35
+
36
+ const { tools } = await getTools({ workspace: 'my-workspace', token: 'mwt_...' });
37
+ const model = new ChatAnthropic({ model: 'claude-sonnet-4-20250514' }).bindTools(tools);
38
+ ```
39
+
40
+ ## Factory Pattern
41
+
42
+ ```typescript
43
+ import { createAerostackLangChain } from '@aerostack/sdk-langchain';
44
+
45
+ const aero = createAerostackLangChain({ workspace: 'my-workspace', token: 'mwt_...' });
46
+ const { tools } = await aero.tools();
47
+ ```
48
+
49
+ ## API
50
+
51
+ ### `getTools(config)` → `Promise<ToolSetResult>`
52
+
53
+ Fetches tools from the workspace. Each tool auto-executes via the workspace gateway. Returns `{ tools, raw }`.
54
+
55
+ ### `createAerostackLangChain(config)` → `AerostackLangChainClient`
56
+
57
+ Creates a reusable client that shares a single WorkspaceClient instance.
58
+
59
+ ## Requirements
60
+
61
+ - `@langchain/core` >= 0.2.0
62
+ - An Aerostack workspace with a token (`mwt_...`)
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=converter.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"converter.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/converter.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,125 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const vitest_1 = require("vitest");
4
+ const converter_js_1 = require("../converter.js");
5
+ const core_1 = require("@aerostack/core");
6
+ function mockClient(callToolResult, shouldThrow = false) {
7
+ return {
8
+ callTool: shouldThrow
9
+ ? vitest_1.vi.fn().mockRejectedValue(callToolResult)
10
+ : vitest_1.vi.fn().mockResolvedValue(callToolResult),
11
+ };
12
+ }
13
+ (0, vitest_1.describe)('convertTools', () => {
14
+ (0, vitest_1.it)('converts MCP tools to LangChain DynamicStructuredTool array', () => {
15
+ const mcpTools = [
16
+ {
17
+ name: 'github__create_issue',
18
+ description: 'Create a GitHub issue',
19
+ inputSchema: {
20
+ type: 'object',
21
+ properties: { title: { type: 'string' } },
22
+ required: ['title'],
23
+ },
24
+ },
25
+ {
26
+ name: 'slack__post_message',
27
+ description: 'Post to Slack',
28
+ },
29
+ ];
30
+ const client = mockClient({});
31
+ const tools = (0, converter_js_1.convertTools)(mcpTools, client);
32
+ (0, vitest_1.expect)(tools).toHaveLength(2);
33
+ (0, vitest_1.expect)(tools[0].name).toBe('github__create_issue');
34
+ (0, vitest_1.expect)(tools[0].description).toBe('Create a GitHub issue');
35
+ (0, vitest_1.expect)(tools[1].name).toBe('slack__post_message');
36
+ });
37
+ (0, vitest_1.it)('handles tools with no description', () => {
38
+ const mcpTools = [
39
+ { name: 'my_tool', inputSchema: { type: 'object', properties: {} } },
40
+ ];
41
+ const client = mockClient({});
42
+ const tools = (0, converter_js_1.convertTools)(mcpTools, client);
43
+ (0, vitest_1.expect)(tools[0].name).toBe('my_tool');
44
+ (0, vitest_1.expect)(tools[0].description).toBe('my_tool tool');
45
+ });
46
+ (0, vitest_1.it)('skips tools with empty names', () => {
47
+ const mcpTools = [
48
+ { name: '', description: 'Bad' },
49
+ { name: 'good', description: 'Good' },
50
+ ];
51
+ const client = mockClient({});
52
+ const tools = (0, converter_js_1.convertTools)(mcpTools, client);
53
+ (0, vitest_1.expect)(tools).toHaveLength(1);
54
+ (0, vitest_1.expect)(tools[0].name).toBe('good');
55
+ });
56
+ (0, vitest_1.it)('handles empty tools array', () => {
57
+ const client = mockClient({});
58
+ (0, vitest_1.expect)((0, converter_js_1.convertTools)([], client)).toEqual([]);
59
+ });
60
+ (0, vitest_1.it)('tool invoke calls WorkspaceClient.callTool', async () => {
61
+ const mcpTools = [
62
+ {
63
+ name: 'test_tool',
64
+ description: 'Test',
65
+ inputSchema: { type: 'object', properties: { x: { type: 'number' } } },
66
+ },
67
+ ];
68
+ const client = mockClient({
69
+ content: [{ type: 'text', text: 'result123' }],
70
+ });
71
+ const tools = (0, converter_js_1.convertTools)(mcpTools, client);
72
+ const result = await tools[0].invoke({ x: 42 });
73
+ (0, vitest_1.expect)(client.callTool).toHaveBeenCalledWith('test_tool', { x: 42 });
74
+ (0, vitest_1.expect)(result).toBe('result123');
75
+ });
76
+ (0, vitest_1.it)('tool handles AerostackError gracefully', async () => {
77
+ const err = new core_1.AerostackError('Server down', 503, -32603, 'req-1');
78
+ const client = mockClient(err, true);
79
+ const mcpTools = [
80
+ { name: 'failing_tool', description: 'Fails' },
81
+ ];
82
+ const tools = (0, converter_js_1.convertTools)(mcpTools, client);
83
+ const result = await tools[0].invoke({});
84
+ (0, vitest_1.expect)(result).toContain('Error (-32603)');
85
+ (0, vitest_1.expect)(result).toContain('Server down');
86
+ });
87
+ (0, vitest_1.it)('tool handles generic errors', async () => {
88
+ const client = mockClient(new Error('Network timeout'), true);
89
+ const mcpTools = [
90
+ { name: 'timeout_tool', description: 'Timeouts' },
91
+ ];
92
+ const tools = (0, converter_js_1.convertTools)(mcpTools, client);
93
+ const result = await tools[0].invoke({});
94
+ (0, vitest_1.expect)(result).toBe('Error: Network timeout');
95
+ });
96
+ });
97
+ (0, vitest_1.describe)('formatToolResult', () => {
98
+ (0, vitest_1.it)('formats single text content', () => {
99
+ (0, vitest_1.expect)((0, converter_js_1.formatToolResult)({
100
+ content: [{ type: 'text', text: 'Hello' }],
101
+ })).toBe('Hello');
102
+ });
103
+ (0, vitest_1.it)('concatenates multiple text blocks', () => {
104
+ (0, vitest_1.expect)((0, converter_js_1.formatToolResult)({
105
+ content: [
106
+ { type: 'text', text: 'Line 1' },
107
+ { type: 'text', text: 'Line 2' },
108
+ ],
109
+ })).toBe('Line 1\nLine 2');
110
+ });
111
+ (0, vitest_1.it)('prefixes error results', () => {
112
+ (0, vitest_1.expect)((0, converter_js_1.formatToolResult)({
113
+ content: [{ type: 'text', text: 'Failed' }],
114
+ isError: true,
115
+ })).toBe('Error: Failed');
116
+ });
117
+ (0, vitest_1.it)('handles empty content', () => {
118
+ (0, vitest_1.expect)((0, converter_js_1.formatToolResult)({ content: [] })).toBe('Success (no output)');
119
+ (0, vitest_1.expect)((0, converter_js_1.formatToolResult)({})).toBe('Success (no output)');
120
+ });
121
+ (0, vitest_1.it)('handles empty content with isError', () => {
122
+ (0, vitest_1.expect)((0, converter_js_1.formatToolResult)({ content: [], isError: true })).toBe('Error: Tool returned no content');
123
+ });
124
+ });
125
+ //# sourceMappingURL=converter.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"converter.test.js","sourceRoot":"","sources":["../../../src/__tests__/converter.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/index.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const vitest_1 = require("vitest");
4
+ const index_js_1 = require("../index.js");
5
+ (0, vitest_1.describe)('createAerostackLangChain', () => {
6
+ (0, vitest_1.it)('returns an object with tools() and workspaceClient', () => {
7
+ const client = (0, index_js_1.createAerostackLangChain)({
8
+ workspace: 'test-ws',
9
+ token: 'mwt_test',
10
+ });
11
+ (0, vitest_1.expect)(client.tools).toBeTypeOf('function');
12
+ (0, vitest_1.expect)(client.workspaceClient).toBeDefined();
13
+ });
14
+ });
15
+ (0, vitest_1.describe)('getTools', () => {
16
+ (0, vitest_1.it)('is exported as a function', () => {
17
+ (0, vitest_1.expect)(index_js_1.getTools).toBeTypeOf('function');
18
+ });
19
+ });
20
+ //# sourceMappingURL=index.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.test.js","sourceRoot":"","sources":["../../../src/__tests__/index.test.ts"],"names":[],"mappings":";;AAAA,mCAA8C;AAC9C,0CAAiE;AAEjE,IAAA,iBAAQ,EAAC,0BAA0B,EAAE,GAAG,EAAE;IACtC,IAAA,WAAE,EAAC,oDAAoD,EAAE,GAAG,EAAE;QAC1D,MAAM,MAAM,GAAG,IAAA,mCAAwB,EAAC;YACpC,SAAS,EAAE,SAAS;YACpB,KAAK,EAAE,UAAU;SACpB,CAAC,CAAC;QAEH,IAAA,eAAM,EAAC,MAAM,CAAC,KAAK,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;QAC5C,IAAA,eAAM,EAAC,MAAM,CAAC,eAAe,CAAC,CAAC,WAAW,EAAE,CAAC;IACjD,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC;AAEH,IAAA,iBAAQ,EAAC,UAAU,EAAE,GAAG,EAAE;IACtB,IAAA,WAAE,EAAC,2BAA2B,EAAE,GAAG,EAAE;QACjC,IAAA,eAAM,EAAC,mBAAQ,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Converts Aerostack McpTool definitions to LangChain.js tool format.
3
+ */
4
+ import { DynamicStructuredTool } from '@langchain/core/tools';
5
+ import { WorkspaceClient } from '@aerostack/core';
6
+ import type { McpTool, McpToolResult } from '@aerostack/core';
7
+ /**
8
+ * Convert McpTool array to LangChain DynamicStructuredTool array.
9
+ *
10
+ * Each tool gets a function that proxies through WorkspaceClient.callTool().
11
+ * Pass the resulting array directly to `createReactAgent({ tools })` or
12
+ * `model.bindTools(tools)`.
13
+ *
14
+ * @param mcpTools - Tools from WorkspaceClient.listTools()
15
+ * @param client - WorkspaceClient instance for executing tool calls
16
+ */
17
+ export declare function convertTools(mcpTools: McpTool[], client: WorkspaceClient): DynamicStructuredTool[];
18
+ /**
19
+ * Flatten McpToolResult content array into a single string.
20
+ */
21
+ export declare function formatToolResult(result: McpToolResult): string;
22
+ //# sourceMappingURL=converter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"converter.d.ts","sourceRoot":"","sources":["../../src/converter.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAkB,MAAM,iBAAiB,CAAC;AAClE,OAAO,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAE9D;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CACxB,QAAQ,EAAE,OAAO,EAAE,EACnB,MAAM,EAAE,eAAe,GACxB,qBAAqB,EAAE,CAiCzB;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAkB9D"}
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.convertTools = convertTools;
4
+ exports.formatToolResult = formatToolResult;
5
+ /**
6
+ * Converts Aerostack McpTool definitions to LangChain.js tool format.
7
+ */
8
+ const tools_1 = require("@langchain/core/tools");
9
+ const core_1 = require("@aerostack/core");
10
+ /**
11
+ * Convert McpTool array to LangChain DynamicStructuredTool array.
12
+ *
13
+ * Each tool gets a function that proxies through WorkspaceClient.callTool().
14
+ * Pass the resulting array directly to `createReactAgent({ tools })` or
15
+ * `model.bindTools(tools)`.
16
+ *
17
+ * @param mcpTools - Tools from WorkspaceClient.listTools()
18
+ * @param client - WorkspaceClient instance for executing tool calls
19
+ */
20
+ function convertTools(mcpTools, client) {
21
+ const tools = [];
22
+ for (const mcpTool of mcpTools) {
23
+ if (!mcpTool.name)
24
+ continue;
25
+ const schema = mcpTool.inputSchema
26
+ ? mcpTool.inputSchema
27
+ : { type: 'object', properties: {} };
28
+ tools.push(new tools_1.DynamicStructuredTool({
29
+ name: mcpTool.name,
30
+ description: mcpTool.description ?? `${mcpTool.name} tool`,
31
+ schema,
32
+ func: async (args) => {
33
+ try {
34
+ const result = await client.callTool(mcpTool.name, args);
35
+ return formatToolResult(result);
36
+ }
37
+ catch (err) {
38
+ if (err instanceof core_1.AerostackError) {
39
+ return `Error (${err.rpcCode}): ${err.message}`;
40
+ }
41
+ return err instanceof Error
42
+ ? `Error: ${err.message}`
43
+ : 'Error: Unknown error executing tool';
44
+ }
45
+ },
46
+ }));
47
+ }
48
+ return tools;
49
+ }
50
+ /**
51
+ * Flatten McpToolResult content array into a single string.
52
+ */
53
+ function formatToolResult(result) {
54
+ if (!result.content || result.content.length === 0) {
55
+ return result.isError ? 'Error: Tool returned no content' : 'Success (no output)';
56
+ }
57
+ const parts = [];
58
+ for (const block of result.content) {
59
+ if (block.text) {
60
+ parts.push(block.text);
61
+ }
62
+ else if (block.data) {
63
+ parts.push(`[${block.mimeType ?? 'binary'} data: ${block.data.length} chars base64]`);
64
+ }
65
+ else {
66
+ parts.push(JSON.stringify(block));
67
+ }
68
+ }
69
+ const text = parts.join('\n');
70
+ return result.isError ? `Error: ${text}` : text;
71
+ }
72
+ //# sourceMappingURL=converter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"converter.js","sourceRoot":"","sources":["../../src/converter.ts"],"names":[],"mappings":";;AAiBA,oCAoCC;AAKD,4CAkBC;AA5ED;;GAEG;AACH,iDAA8D;AAC9D,0CAAkE;AAGlE;;;;;;;;;GASG;AACH,SAAgB,YAAY,CACxB,QAAmB,EACnB,MAAuB;IAEvB,MAAM,KAAK,GAA4B,EAAE,CAAC;IAE1C,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC7B,IAAI,CAAC,OAAO,CAAC,IAAI;YAAE,SAAS;QAE5B,MAAM,MAAM,GAAG,OAAO,CAAC,WAAW;YAC9B,CAAC,CAAE,OAAO,CAAC,WAAuC;YAClD,CAAC,CAAC,EAAE,IAAI,EAAE,QAAiB,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC;QAElD,KAAK,CAAC,IAAI,CACN,IAAI,6BAAqB,CAAC;YACtB,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,GAAG,OAAO,CAAC,IAAI,OAAO;YAC1D,MAAM;YACN,IAAI,EAAE,KAAK,EAAE,IAA6B,EAAE,EAAE;gBAC1C,IAAI,CAAC;oBACD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;oBACzD,OAAO,gBAAgB,CAAC,MAAM,CAAC,CAAC;gBACpC,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACX,IAAI,GAAG,YAAY,qBAAc,EAAE,CAAC;wBAChC,OAAO,UAAU,GAAG,CAAC,OAAO,MAAM,GAAG,CAAC,OAAO,EAAE,CAAC;oBACpD,CAAC;oBACD,OAAO,GAAG,YAAY,KAAK;wBACvB,CAAC,CAAC,UAAU,GAAG,CAAC,OAAO,EAAE;wBACzB,CAAC,CAAC,qCAAqC,CAAC;gBAChD,CAAC;YACL,CAAC;SACJ,CAAC,CACL,CAAC;IACN,CAAC;IAED,OAAO,KAAK,CAAC;AACjB,CAAC;AAED;;GAEG;AACH,SAAgB,gBAAgB,CAAC,MAAqB;IAClD,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjD,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,iCAAiC,CAAC,CAAC,CAAC,qBAAqB,CAAC;IACtF,CAAC;IAED,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACjC,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;YACb,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC3B,CAAC;aAAM,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;YACpB,KAAK,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,QAAQ,IAAI,QAAQ,UAAU,KAAK,CAAC,IAAI,CAAC,MAAM,gBAAgB,CAAC,CAAC;QAC1F,CAAC;aAAM,CAAC;YACJ,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;QACtC,CAAC;IACL,CAAC;IAED,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9B,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AACpD,CAAC"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * @aerostack/sdk-langchain — Use Aerostack workspace tools as LangChain.js tools.
3
+ *
4
+ * @example
5
+ * ```ts
6
+ * import { ChatOpenAI } from '@langchain/openai';
7
+ * import { createReactAgent } from '@langchain/langgraph/prebuilt';
8
+ * import { getTools } from '@aerostack/sdk-langchain';
9
+ *
10
+ * const tools = await getTools({ workspace: 'my-workspace', token: 'mwt_...' });
11
+ *
12
+ * const agent = createReactAgent({
13
+ * llm: new ChatOpenAI({ model: 'gpt-4o' }),
14
+ * tools,
15
+ * });
16
+ *
17
+ * const result = await agent.invoke({
18
+ * messages: [{ role: 'user', content: 'Create a GitHub issue for the login bug' }],
19
+ * });
20
+ * ```
21
+ *
22
+ * @example Direct tool binding
23
+ * ```ts
24
+ * import { ChatAnthropic } from '@langchain/anthropic';
25
+ * import { getTools } from '@aerostack/sdk-langchain';
26
+ *
27
+ * const tools = await getTools({ workspace: 'my-workspace', token: 'mwt_...' });
28
+ * const model = new ChatAnthropic({ model: 'claude-sonnet-4-20250514' }).bindTools(tools);
29
+ * ```
30
+ */
31
+ import type { DynamicStructuredTool } from '@langchain/core/tools';
32
+ import { WorkspaceClient } from '@aerostack/core';
33
+ import type { McpTool } from '@aerostack/core';
34
+ export { formatToolResult } from './converter.js';
35
+ export interface WorkspaceConfig {
36
+ /** Workspace slug */
37
+ workspace: string;
38
+ /** Workspace token (mwt_...) */
39
+ token: string;
40
+ /** Override gateway base URL */
41
+ baseUrl?: string;
42
+ }
43
+ /** Result from getTools. */
44
+ export interface ToolSetResult {
45
+ /** LangChain tools — pass to createReactAgent({ tools }) or model.bindTools(tools) */
46
+ tools: DynamicStructuredTool[];
47
+ /** Raw MCP tools from the workspace for inspection */
48
+ raw: McpTool[];
49
+ }
50
+ /**
51
+ * Fetch tools from an Aerostack workspace and convert to LangChain format.
52
+ *
53
+ * Each tool includes a function that calls the workspace gateway,
54
+ * so you just pass the tools to an agent or bind them to a model.
55
+ */
56
+ export declare function getTools(config: WorkspaceConfig): Promise<ToolSetResult>;
57
+ export interface AerostackLangChainClient {
58
+ /** Fetch and convert workspace tools to LangChain format. */
59
+ tools(): Promise<ToolSetResult>;
60
+ /** Access the underlying WorkspaceClient for advanced use. */
61
+ readonly workspaceClient: WorkspaceClient;
62
+ }
63
+ /**
64
+ * Create a reusable Aerostack LangChain client.
65
+ *
66
+ * Reuses a single WorkspaceClient instance across tool calls.
67
+ */
68
+ export declare function createAerostackLangChain(config: WorkspaceConfig): AerostackLangChainClient;
69
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAG/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAElD,MAAM,WAAW,eAAe;IAC5B,qBAAqB;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,gCAAgC;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,gCAAgC;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,4BAA4B;AAC5B,MAAM,WAAW,aAAa;IAC1B,sFAAsF;IACtF,KAAK,EAAE,qBAAqB,EAAE,CAAC;IAC/B,sDAAsD;IACtD,GAAG,EAAE,OAAO,EAAE,CAAC;CAClB;AAcD;;;;;GAKG;AACH,wBAAsB,QAAQ,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,aAAa,CAAC,CAK9E;AAMD,MAAM,WAAW,wBAAwB;IACrC,6DAA6D;IAC7D,KAAK,IAAI,OAAO,CAAC,aAAa,CAAC,CAAC;IAChC,8DAA8D;IAC9D,QAAQ,CAAC,eAAe,EAAE,eAAe,CAAC;CAC7C;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,eAAe,GAAG,wBAAwB,CAc1F"}
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ /**
3
+ * @aerostack/sdk-langchain — Use Aerostack workspace tools as LangChain.js tools.
4
+ *
5
+ * @example
6
+ * ```ts
7
+ * import { ChatOpenAI } from '@langchain/openai';
8
+ * import { createReactAgent } from '@langchain/langgraph/prebuilt';
9
+ * import { getTools } from '@aerostack/sdk-langchain';
10
+ *
11
+ * const tools = await getTools({ workspace: 'my-workspace', token: 'mwt_...' });
12
+ *
13
+ * const agent = createReactAgent({
14
+ * llm: new ChatOpenAI({ model: 'gpt-4o' }),
15
+ * tools,
16
+ * });
17
+ *
18
+ * const result = await agent.invoke({
19
+ * messages: [{ role: 'user', content: 'Create a GitHub issue for the login bug' }],
20
+ * });
21
+ * ```
22
+ *
23
+ * @example Direct tool binding
24
+ * ```ts
25
+ * import { ChatAnthropic } from '@langchain/anthropic';
26
+ * import { getTools } from '@aerostack/sdk-langchain';
27
+ *
28
+ * const tools = await getTools({ workspace: 'my-workspace', token: 'mwt_...' });
29
+ * const model = new ChatAnthropic({ model: 'claude-sonnet-4-20250514' }).bindTools(tools);
30
+ * ```
31
+ */
32
+ Object.defineProperty(exports, "__esModule", { value: true });
33
+ exports.formatToolResult = void 0;
34
+ exports.getTools = getTools;
35
+ exports.createAerostackLangChain = createAerostackLangChain;
36
+ const core_1 = require("@aerostack/core");
37
+ const converter_js_1 = require("./converter.js");
38
+ var converter_js_2 = require("./converter.js");
39
+ Object.defineProperty(exports, "formatToolResult", { enumerable: true, get: function () { return converter_js_2.formatToolResult; } });
40
+ function createWorkspaceClient(config) {
41
+ return new core_1.WorkspaceClient({
42
+ slug: config.workspace,
43
+ token: config.token,
44
+ baseUrl: config.baseUrl,
45
+ });
46
+ }
47
+ // ---------------------------------------------------------------------------
48
+ // Standalone function
49
+ // ---------------------------------------------------------------------------
50
+ /**
51
+ * Fetch tools from an Aerostack workspace and convert to LangChain format.
52
+ *
53
+ * Each tool includes a function that calls the workspace gateway,
54
+ * so you just pass the tools to an agent or bind them to a model.
55
+ */
56
+ async function getTools(config) {
57
+ const client = createWorkspaceClient(config);
58
+ const raw = await client.listTools();
59
+ const tools = (0, converter_js_1.convertTools)(raw, client);
60
+ return { tools, raw };
61
+ }
62
+ /**
63
+ * Create a reusable Aerostack LangChain client.
64
+ *
65
+ * Reuses a single WorkspaceClient instance across tool calls.
66
+ */
67
+ function createAerostackLangChain(config) {
68
+ const wsClient = createWorkspaceClient(config);
69
+ return {
70
+ async tools() {
71
+ const raw = await wsClient.listTools();
72
+ const tools = (0, converter_js_1.convertTools)(raw, wsClient);
73
+ return { tools, raw };
74
+ },
75
+ get workspaceClient() {
76
+ return wsClient;
77
+ },
78
+ };
79
+ }
80
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;;;AA4CH,4BAKC;AAkBD,4DAcC;AA9ED,0CAAkD;AAElD,iDAA8C;AAE9C,+CAAkD;AAAzC,gHAAA,gBAAgB,OAAA;AAmBzB,SAAS,qBAAqB,CAAC,MAAuB;IAClD,OAAO,IAAI,sBAAe,CAAC;QACvB,IAAI,EAAE,MAAM,CAAC,SAAS;QACtB,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,OAAO,EAAE,MAAM,CAAC,OAAO;KAC1B,CAAC,CAAC;AACP,CAAC;AAED,8EAA8E;AAC9E,sBAAsB;AACtB,8EAA8E;AAE9E;;;;;GAKG;AACI,KAAK,UAAU,QAAQ,CAAC,MAAuB;IAClD,MAAM,MAAM,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAC7C,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,SAAS,EAAE,CAAC;IACrC,MAAM,KAAK,GAAG,IAAA,2BAAY,EAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IACxC,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;AAC1B,CAAC;AAaD;;;;GAIG;AACH,SAAgB,wBAAwB,CAAC,MAAuB;IAC5D,MAAM,QAAQ,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAE/C,OAAO;QACH,KAAK,CAAC,KAAK;YACP,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,SAAS,EAAE,CAAC;YACvC,MAAM,KAAK,GAAG,IAAA,2BAAY,EAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;YAC1C,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;QAC1B,CAAC;QAED,IAAI,eAAe;YACf,OAAO,QAAQ,CAAC;QACpB,CAAC;KACJ,CAAC;AACN,CAAC"}
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "commonjs"
3
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=converter.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"converter.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/converter.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,123 @@
1
+ import { describe, it, expect, vi } from 'vitest';
2
+ import { convertTools, formatToolResult } from '../converter.js';
3
+ import { AerostackError } from '@aerostack/core';
4
+ function mockClient(callToolResult, shouldThrow = false) {
5
+ return {
6
+ callTool: shouldThrow
7
+ ? vi.fn().mockRejectedValue(callToolResult)
8
+ : vi.fn().mockResolvedValue(callToolResult),
9
+ };
10
+ }
11
+ describe('convertTools', () => {
12
+ it('converts MCP tools to LangChain DynamicStructuredTool array', () => {
13
+ const mcpTools = [
14
+ {
15
+ name: 'github__create_issue',
16
+ description: 'Create a GitHub issue',
17
+ inputSchema: {
18
+ type: 'object',
19
+ properties: { title: { type: 'string' } },
20
+ required: ['title'],
21
+ },
22
+ },
23
+ {
24
+ name: 'slack__post_message',
25
+ description: 'Post to Slack',
26
+ },
27
+ ];
28
+ const client = mockClient({});
29
+ const tools = convertTools(mcpTools, client);
30
+ expect(tools).toHaveLength(2);
31
+ expect(tools[0].name).toBe('github__create_issue');
32
+ expect(tools[0].description).toBe('Create a GitHub issue');
33
+ expect(tools[1].name).toBe('slack__post_message');
34
+ });
35
+ it('handles tools with no description', () => {
36
+ const mcpTools = [
37
+ { name: 'my_tool', inputSchema: { type: 'object', properties: {} } },
38
+ ];
39
+ const client = mockClient({});
40
+ const tools = convertTools(mcpTools, client);
41
+ expect(tools[0].name).toBe('my_tool');
42
+ expect(tools[0].description).toBe('my_tool tool');
43
+ });
44
+ it('skips tools with empty names', () => {
45
+ const mcpTools = [
46
+ { name: '', description: 'Bad' },
47
+ { name: 'good', description: 'Good' },
48
+ ];
49
+ const client = mockClient({});
50
+ const tools = convertTools(mcpTools, client);
51
+ expect(tools).toHaveLength(1);
52
+ expect(tools[0].name).toBe('good');
53
+ });
54
+ it('handles empty tools array', () => {
55
+ const client = mockClient({});
56
+ expect(convertTools([], client)).toEqual([]);
57
+ });
58
+ it('tool invoke calls WorkspaceClient.callTool', async () => {
59
+ const mcpTools = [
60
+ {
61
+ name: 'test_tool',
62
+ description: 'Test',
63
+ inputSchema: { type: 'object', properties: { x: { type: 'number' } } },
64
+ },
65
+ ];
66
+ const client = mockClient({
67
+ content: [{ type: 'text', text: 'result123' }],
68
+ });
69
+ const tools = convertTools(mcpTools, client);
70
+ const result = await tools[0].invoke({ x: 42 });
71
+ expect(client.callTool).toHaveBeenCalledWith('test_tool', { x: 42 });
72
+ expect(result).toBe('result123');
73
+ });
74
+ it('tool handles AerostackError gracefully', async () => {
75
+ const err = new AerostackError('Server down', 503, -32603, 'req-1');
76
+ const client = mockClient(err, true);
77
+ const mcpTools = [
78
+ { name: 'failing_tool', description: 'Fails' },
79
+ ];
80
+ const tools = convertTools(mcpTools, client);
81
+ const result = await tools[0].invoke({});
82
+ expect(result).toContain('Error (-32603)');
83
+ expect(result).toContain('Server down');
84
+ });
85
+ it('tool handles generic errors', async () => {
86
+ const client = mockClient(new Error('Network timeout'), true);
87
+ const mcpTools = [
88
+ { name: 'timeout_tool', description: 'Timeouts' },
89
+ ];
90
+ const tools = convertTools(mcpTools, client);
91
+ const result = await tools[0].invoke({});
92
+ expect(result).toBe('Error: Network timeout');
93
+ });
94
+ });
95
+ describe('formatToolResult', () => {
96
+ it('formats single text content', () => {
97
+ expect(formatToolResult({
98
+ content: [{ type: 'text', text: 'Hello' }],
99
+ })).toBe('Hello');
100
+ });
101
+ it('concatenates multiple text blocks', () => {
102
+ expect(formatToolResult({
103
+ content: [
104
+ { type: 'text', text: 'Line 1' },
105
+ { type: 'text', text: 'Line 2' },
106
+ ],
107
+ })).toBe('Line 1\nLine 2');
108
+ });
109
+ it('prefixes error results', () => {
110
+ expect(formatToolResult({
111
+ content: [{ type: 'text', text: 'Failed' }],
112
+ isError: true,
113
+ })).toBe('Error: Failed');
114
+ });
115
+ it('handles empty content', () => {
116
+ expect(formatToolResult({ content: [] })).toBe('Success (no output)');
117
+ expect(formatToolResult({})).toBe('Success (no output)');
118
+ });
119
+ it('handles empty content with isError', () => {
120
+ expect(formatToolResult({ content: [], isError: true })).toBe('Error: Tool returned no content');
121
+ });
122
+ });
123
+ //# sourceMappingURL=converter.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"converter.test.js","sourceRoot":"","sources":["../../../src/__tests__/converter.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/index.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,18 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { getTools, createAerostackLangChain } from '../index.js';
3
+ describe('createAerostackLangChain', () => {
4
+ it('returns an object with tools() and workspaceClient', () => {
5
+ const client = createAerostackLangChain({
6
+ workspace: 'test-ws',
7
+ token: 'mwt_test',
8
+ });
9
+ expect(client.tools).toBeTypeOf('function');
10
+ expect(client.workspaceClient).toBeDefined();
11
+ });
12
+ });
13
+ describe('getTools', () => {
14
+ it('is exported as a function', () => {
15
+ expect(getTools).toBeTypeOf('function');
16
+ });
17
+ });
18
+ //# sourceMappingURL=index.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.test.js","sourceRoot":"","sources":["../../../src/__tests__/index.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAEjE,QAAQ,CAAC,0BAA0B,EAAE,GAAG,EAAE;IACtC,EAAE,CAAC,oDAAoD,EAAE,GAAG,EAAE;QAC1D,MAAM,MAAM,GAAG,wBAAwB,CAAC;YACpC,SAAS,EAAE,SAAS;YACpB,KAAK,EAAE,UAAU;SACpB,CAAC,CAAC;QAEH,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;QAC5C,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,WAAW,EAAE,CAAC;IACjD,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,UAAU,EAAE,GAAG,EAAE;IACtB,EAAE,CAAC,2BAA2B,EAAE,GAAG,EAAE;QACjC,MAAM,CAAC,QAAQ,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Converts Aerostack McpTool definitions to LangChain.js tool format.
3
+ */
4
+ import { DynamicStructuredTool } from '@langchain/core/tools';
5
+ import { WorkspaceClient } from '@aerostack/core';
6
+ import type { McpTool, McpToolResult } from '@aerostack/core';
7
+ /**
8
+ * Convert McpTool array to LangChain DynamicStructuredTool array.
9
+ *
10
+ * Each tool gets a function that proxies through WorkspaceClient.callTool().
11
+ * Pass the resulting array directly to `createReactAgent({ tools })` or
12
+ * `model.bindTools(tools)`.
13
+ *
14
+ * @param mcpTools - Tools from WorkspaceClient.listTools()
15
+ * @param client - WorkspaceClient instance for executing tool calls
16
+ */
17
+ export declare function convertTools(mcpTools: McpTool[], client: WorkspaceClient): DynamicStructuredTool[];
18
+ /**
19
+ * Flatten McpToolResult content array into a single string.
20
+ */
21
+ export declare function formatToolResult(result: McpToolResult): string;
22
+ //# sourceMappingURL=converter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"converter.d.ts","sourceRoot":"","sources":["../../src/converter.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAkB,MAAM,iBAAiB,CAAC;AAClE,OAAO,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAE9D;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CACxB,QAAQ,EAAE,OAAO,EAAE,EACnB,MAAM,EAAE,eAAe,GACxB,qBAAqB,EAAE,CAiCzB;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAkB9D"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Converts Aerostack McpTool definitions to LangChain.js tool format.
3
+ */
4
+ import { DynamicStructuredTool } from '@langchain/core/tools';
5
+ import { AerostackError } from '@aerostack/core';
6
+ /**
7
+ * Convert McpTool array to LangChain DynamicStructuredTool array.
8
+ *
9
+ * Each tool gets a function that proxies through WorkspaceClient.callTool().
10
+ * Pass the resulting array directly to `createReactAgent({ tools })` or
11
+ * `model.bindTools(tools)`.
12
+ *
13
+ * @param mcpTools - Tools from WorkspaceClient.listTools()
14
+ * @param client - WorkspaceClient instance for executing tool calls
15
+ */
16
+ export function convertTools(mcpTools, client) {
17
+ const tools = [];
18
+ for (const mcpTool of mcpTools) {
19
+ if (!mcpTool.name)
20
+ continue;
21
+ const schema = mcpTool.inputSchema
22
+ ? mcpTool.inputSchema
23
+ : { type: 'object', properties: {} };
24
+ tools.push(new DynamicStructuredTool({
25
+ name: mcpTool.name,
26
+ description: mcpTool.description ?? `${mcpTool.name} tool`,
27
+ schema,
28
+ func: async (args) => {
29
+ try {
30
+ const result = await client.callTool(mcpTool.name, args);
31
+ return formatToolResult(result);
32
+ }
33
+ catch (err) {
34
+ if (err instanceof AerostackError) {
35
+ return `Error (${err.rpcCode}): ${err.message}`;
36
+ }
37
+ return err instanceof Error
38
+ ? `Error: ${err.message}`
39
+ : 'Error: Unknown error executing tool';
40
+ }
41
+ },
42
+ }));
43
+ }
44
+ return tools;
45
+ }
46
+ /**
47
+ * Flatten McpToolResult content array into a single string.
48
+ */
49
+ export function formatToolResult(result) {
50
+ if (!result.content || result.content.length === 0) {
51
+ return result.isError ? 'Error: Tool returned no content' : 'Success (no output)';
52
+ }
53
+ const parts = [];
54
+ for (const block of result.content) {
55
+ if (block.text) {
56
+ parts.push(block.text);
57
+ }
58
+ else if (block.data) {
59
+ parts.push(`[${block.mimeType ?? 'binary'} data: ${block.data.length} chars base64]`);
60
+ }
61
+ else {
62
+ parts.push(JSON.stringify(block));
63
+ }
64
+ }
65
+ const text = parts.join('\n');
66
+ return result.isError ? `Error: ${text}` : text;
67
+ }
68
+ //# sourceMappingURL=converter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"converter.js","sourceRoot":"","sources":["../../src/converter.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAmB,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGlE;;;;;;;;;GASG;AACH,MAAM,UAAU,YAAY,CACxB,QAAmB,EACnB,MAAuB;IAEvB,MAAM,KAAK,GAA4B,EAAE,CAAC;IAE1C,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC7B,IAAI,CAAC,OAAO,CAAC,IAAI;YAAE,SAAS;QAE5B,MAAM,MAAM,GAAG,OAAO,CAAC,WAAW;YAC9B,CAAC,CAAE,OAAO,CAAC,WAAuC;YAClD,CAAC,CAAC,EAAE,IAAI,EAAE,QAAiB,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC;QAElD,KAAK,CAAC,IAAI,CACN,IAAI,qBAAqB,CAAC;YACtB,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,GAAG,OAAO,CAAC,IAAI,OAAO;YAC1D,MAAM;YACN,IAAI,EAAE,KAAK,EAAE,IAA6B,EAAE,EAAE;gBAC1C,IAAI,CAAC;oBACD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;oBACzD,OAAO,gBAAgB,CAAC,MAAM,CAAC,CAAC;gBACpC,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACX,IAAI,GAAG,YAAY,cAAc,EAAE,CAAC;wBAChC,OAAO,UAAU,GAAG,CAAC,OAAO,MAAM,GAAG,CAAC,OAAO,EAAE,CAAC;oBACpD,CAAC;oBACD,OAAO,GAAG,YAAY,KAAK;wBACvB,CAAC,CAAC,UAAU,GAAG,CAAC,OAAO,EAAE;wBACzB,CAAC,CAAC,qCAAqC,CAAC;gBAChD,CAAC;YACL,CAAC;SACJ,CAAC,CACL,CAAC;IACN,CAAC;IAED,OAAO,KAAK,CAAC;AACjB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAqB;IAClD,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjD,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,iCAAiC,CAAC,CAAC,CAAC,qBAAqB,CAAC;IACtF,CAAC;IAED,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACjC,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;YACb,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC3B,CAAC;aAAM,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;YACpB,KAAK,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,QAAQ,IAAI,QAAQ,UAAU,KAAK,CAAC,IAAI,CAAC,MAAM,gBAAgB,CAAC,CAAC;QAC1F,CAAC;aAAM,CAAC;YACJ,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;QACtC,CAAC;IACL,CAAC;IAED,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9B,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AACpD,CAAC"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * @aerostack/sdk-langchain — Use Aerostack workspace tools as LangChain.js tools.
3
+ *
4
+ * @example
5
+ * ```ts
6
+ * import { ChatOpenAI } from '@langchain/openai';
7
+ * import { createReactAgent } from '@langchain/langgraph/prebuilt';
8
+ * import { getTools } from '@aerostack/sdk-langchain';
9
+ *
10
+ * const tools = await getTools({ workspace: 'my-workspace', token: 'mwt_...' });
11
+ *
12
+ * const agent = createReactAgent({
13
+ * llm: new ChatOpenAI({ model: 'gpt-4o' }),
14
+ * tools,
15
+ * });
16
+ *
17
+ * const result = await agent.invoke({
18
+ * messages: [{ role: 'user', content: 'Create a GitHub issue for the login bug' }],
19
+ * });
20
+ * ```
21
+ *
22
+ * @example Direct tool binding
23
+ * ```ts
24
+ * import { ChatAnthropic } from '@langchain/anthropic';
25
+ * import { getTools } from '@aerostack/sdk-langchain';
26
+ *
27
+ * const tools = await getTools({ workspace: 'my-workspace', token: 'mwt_...' });
28
+ * const model = new ChatAnthropic({ model: 'claude-sonnet-4-20250514' }).bindTools(tools);
29
+ * ```
30
+ */
31
+ import type { DynamicStructuredTool } from '@langchain/core/tools';
32
+ import { WorkspaceClient } from '@aerostack/core';
33
+ import type { McpTool } from '@aerostack/core';
34
+ export { formatToolResult } from './converter.js';
35
+ export interface WorkspaceConfig {
36
+ /** Workspace slug */
37
+ workspace: string;
38
+ /** Workspace token (mwt_...) */
39
+ token: string;
40
+ /** Override gateway base URL */
41
+ baseUrl?: string;
42
+ }
43
+ /** Result from getTools. */
44
+ export interface ToolSetResult {
45
+ /** LangChain tools — pass to createReactAgent({ tools }) or model.bindTools(tools) */
46
+ tools: DynamicStructuredTool[];
47
+ /** Raw MCP tools from the workspace for inspection */
48
+ raw: McpTool[];
49
+ }
50
+ /**
51
+ * Fetch tools from an Aerostack workspace and convert to LangChain format.
52
+ *
53
+ * Each tool includes a function that calls the workspace gateway,
54
+ * so you just pass the tools to an agent or bind them to a model.
55
+ */
56
+ export declare function getTools(config: WorkspaceConfig): Promise<ToolSetResult>;
57
+ export interface AerostackLangChainClient {
58
+ /** Fetch and convert workspace tools to LangChain format. */
59
+ tools(): Promise<ToolSetResult>;
60
+ /** Access the underlying WorkspaceClient for advanced use. */
61
+ readonly workspaceClient: WorkspaceClient;
62
+ }
63
+ /**
64
+ * Create a reusable Aerostack LangChain client.
65
+ *
66
+ * Reuses a single WorkspaceClient instance across tool calls.
67
+ */
68
+ export declare function createAerostackLangChain(config: WorkspaceConfig): AerostackLangChainClient;
69
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAG/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAElD,MAAM,WAAW,eAAe;IAC5B,qBAAqB;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,gCAAgC;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,gCAAgC;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,4BAA4B;AAC5B,MAAM,WAAW,aAAa;IAC1B,sFAAsF;IACtF,KAAK,EAAE,qBAAqB,EAAE,CAAC;IAC/B,sDAAsD;IACtD,GAAG,EAAE,OAAO,EAAE,CAAC;CAClB;AAcD;;;;;GAKG;AACH,wBAAsB,QAAQ,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,aAAa,CAAC,CAK9E;AAMD,MAAM,WAAW,wBAAwB;IACrC,6DAA6D;IAC7D,KAAK,IAAI,OAAO,CAAC,aAAa,CAAC,CAAC;IAChC,8DAA8D;IAC9D,QAAQ,CAAC,eAAe,EAAE,eAAe,CAAC;CAC7C;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,eAAe,GAAG,wBAAwB,CAc1F"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * @aerostack/sdk-langchain — Use Aerostack workspace tools as LangChain.js tools.
3
+ *
4
+ * @example
5
+ * ```ts
6
+ * import { ChatOpenAI } from '@langchain/openai';
7
+ * import { createReactAgent } from '@langchain/langgraph/prebuilt';
8
+ * import { getTools } from '@aerostack/sdk-langchain';
9
+ *
10
+ * const tools = await getTools({ workspace: 'my-workspace', token: 'mwt_...' });
11
+ *
12
+ * const agent = createReactAgent({
13
+ * llm: new ChatOpenAI({ model: 'gpt-4o' }),
14
+ * tools,
15
+ * });
16
+ *
17
+ * const result = await agent.invoke({
18
+ * messages: [{ role: 'user', content: 'Create a GitHub issue for the login bug' }],
19
+ * });
20
+ * ```
21
+ *
22
+ * @example Direct tool binding
23
+ * ```ts
24
+ * import { ChatAnthropic } from '@langchain/anthropic';
25
+ * import { getTools } from '@aerostack/sdk-langchain';
26
+ *
27
+ * const tools = await getTools({ workspace: 'my-workspace', token: 'mwt_...' });
28
+ * const model = new ChatAnthropic({ model: 'claude-sonnet-4-20250514' }).bindTools(tools);
29
+ * ```
30
+ */
31
+ import { WorkspaceClient } from '@aerostack/core';
32
+ import { convertTools } from './converter.js';
33
+ export { formatToolResult } from './converter.js';
34
+ function createWorkspaceClient(config) {
35
+ return new WorkspaceClient({
36
+ slug: config.workspace,
37
+ token: config.token,
38
+ baseUrl: config.baseUrl,
39
+ });
40
+ }
41
+ // ---------------------------------------------------------------------------
42
+ // Standalone function
43
+ // ---------------------------------------------------------------------------
44
+ /**
45
+ * Fetch tools from an Aerostack workspace and convert to LangChain format.
46
+ *
47
+ * Each tool includes a function that calls the workspace gateway,
48
+ * so you just pass the tools to an agent or bind them to a model.
49
+ */
50
+ export async function getTools(config) {
51
+ const client = createWorkspaceClient(config);
52
+ const raw = await client.listTools();
53
+ const tools = convertTools(raw, client);
54
+ return { tools, raw };
55
+ }
56
+ /**
57
+ * Create a reusable Aerostack LangChain client.
58
+ *
59
+ * Reuses a single WorkspaceClient instance across tool calls.
60
+ */
61
+ export function createAerostackLangChain(config) {
62
+ const wsClient = createWorkspaceClient(config);
63
+ return {
64
+ async tools() {
65
+ const raw = await wsClient.listTools();
66
+ const tools = convertTools(raw, wsClient);
67
+ return { tools, raw };
68
+ },
69
+ get workspaceClient() {
70
+ return wsClient;
71
+ },
72
+ };
73
+ }
74
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAElD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAmBlD,SAAS,qBAAqB,CAAC,MAAuB;IAClD,OAAO,IAAI,eAAe,CAAC;QACvB,IAAI,EAAE,MAAM,CAAC,SAAS;QACtB,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,OAAO,EAAE,MAAM,CAAC,OAAO;KAC1B,CAAC,CAAC;AACP,CAAC;AAED,8EAA8E;AAC9E,sBAAsB;AACtB,8EAA8E;AAE9E;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,MAAuB;IAClD,MAAM,MAAM,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAC7C,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,SAAS,EAAE,CAAC;IACrC,MAAM,KAAK,GAAG,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IACxC,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;AAC1B,CAAC;AAaD;;;;GAIG;AACH,MAAM,UAAU,wBAAwB,CAAC,MAAuB;IAC5D,MAAM,QAAQ,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAE/C,OAAO;QACH,KAAK,CAAC,KAAK;YACP,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,SAAS,EAAE,CAAC;YACvC,MAAM,KAAK,GAAG,YAAY,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;YAC1C,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;QAC1B,CAAC;QAED,IAAI,eAAe;YACf,OAAO,QAAQ,CAAC;QACpB,CAAC;KACJ,CAAC;AACN,CAAC"}
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "module"
3
+ }
package/package.json ADDED
@@ -0,0 +1,66 @@
1
+ {
2
+ "name": "@aerostack/sdk-langchain",
3
+ "version": "0.10.1",
4
+ "description": "Use Aerostack workspace tools as LangChain.js tools",
5
+ "author": "Aerostack",
6
+ "license": "MIT",
7
+ "type": "module",
8
+ "tshy": {
9
+ "sourceDialects": [
10
+ "@aerostack/sdk-langchain/source"
11
+ ],
12
+ "exports": {
13
+ ".": "./src/index.ts",
14
+ "./package.json": "./package.json"
15
+ }
16
+ },
17
+ "sideEffects": false,
18
+ "scripts": {
19
+ "lint": "eslint --cache --max-warnings=0 src",
20
+ "build": "tshy",
21
+ "test": "vitest run",
22
+ "prepublishOnly": "npm run build"
23
+ },
24
+ "dependencies": {
25
+ "@aerostack/core": "^0.10.1"
26
+ },
27
+ "peerDependencies": {
28
+ "@langchain/core": ">=0.2.0"
29
+ },
30
+ "peerDependenciesMeta": {
31
+ "@langchain/core": {
32
+ "optional": false
33
+ }
34
+ },
35
+ "devDependencies": {
36
+ "@langchain/core": "^0.3.0",
37
+ "tshy": "^2.0.0",
38
+ "typescript": "~5.8.3",
39
+ "vitest": "^3.2.1",
40
+ "zod": "^3.25.0"
41
+ },
42
+ "exports": {
43
+ ".": {
44
+ "import": {
45
+ "@aerostack/sdk-langchain/source": "./src/index.ts",
46
+ "types": "./dist/esm/index.d.ts",
47
+ "default": "./dist/esm/index.js"
48
+ },
49
+ "require": {
50
+ "types": "./dist/commonjs/index.d.ts",
51
+ "default": "./dist/commonjs/index.js"
52
+ }
53
+ },
54
+ "./package.json": "./package.json"
55
+ },
56
+ "main": "./dist/commonjs/index.js",
57
+ "types": "./dist/commonjs/index.d.ts",
58
+ "module": "./dist/esm/index.js",
59
+ "files": [
60
+ "dist",
61
+ "README.md"
62
+ ],
63
+ "publishConfig": {
64
+ "access": "public"
65
+ }
66
+ }