@granular-software/sdk 0.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.
@@ -0,0 +1,72 @@
1
+ // src/adapters/anthropic.ts
2
+ function toAnthropicTools(tools) {
3
+ return tools.map((tool) => ({
4
+ name: tool.name,
5
+ description: tool.description,
6
+ input_schema: tool.inputSchema
7
+ }));
8
+ }
9
+ function toolUsesToJobCode(contentBlocks, customImports = "") {
10
+ const toolUses = contentBlocks.filter((b) => b.type === "tool_use");
11
+ if (toolUses.length === 0) {
12
+ return null;
13
+ }
14
+ let code = `
15
+ import { tools } from './sandbox-tools';
16
+ ${customImports}
17
+ const results = [];
18
+ `;
19
+ toolUses.forEach((use) => {
20
+ code += `
21
+ try {
22
+ const result_${use.id.replace(/-/g, "_")} = await tools.${use.name}(${JSON.stringify(use.input)});
23
+ results.push({
24
+ type: 'tool_result',
25
+ tool_use_id: "${use.id}",
26
+ content: result_${use.id.replace(/-/g, "_")}
27
+ });
28
+ } catch (error) {
29
+ results.push({
30
+ type: 'tool_result',
31
+ tool_use_id: "${use.id}",
32
+ content: String(error),
33
+ is_error: true
34
+ });
35
+ }
36
+ `;
37
+ });
38
+ code += `return results;`;
39
+ return code;
40
+ }
41
+ function createCodegenTool(domainDocumentation) {
42
+ return {
43
+ name: "execute_sandbox_code",
44
+ description: `Execute TypeScript code in a secure sandbox environment. The code can use the following tools by importing from "./sandbox-tools":
45
+
46
+ ${domainDocumentation}
47
+
48
+ Write complete, executable TypeScript code. Use async/await for tool calls. Return results at the end.`,
49
+ input_schema: {
50
+ type: "object",
51
+ properties: {
52
+ code: {
53
+ type: "string",
54
+ description: 'TypeScript code to execute. Must import tools from "./sandbox-tools" and use await for all tool calls.'
55
+ }
56
+ },
57
+ required: ["code"]
58
+ }
59
+ };
60
+ }
61
+ async function executeCodegenToolUse(toolUse, environment) {
62
+ if (toolUse.name !== "execute_sandbox_code") {
63
+ throw new Error(`Unknown tool: ${toolUse.name}`);
64
+ }
65
+ const input = toolUse.input;
66
+ const job = await environment.submitJob(input.code);
67
+ return job.result;
68
+ }
69
+
70
+ export { createCodegenTool, executeCodegenToolUse, toAnthropicTools, toolUsesToJobCode };
71
+ //# sourceMappingURL=anthropic.mjs.map
72
+ //# sourceMappingURL=anthropic.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/adapters/anthropic.ts"],"names":[],"mappings":";AA2BO,SAAS,iBAAiB,KAAA,EAAqD;AAClF,EAAA,OAAO,KAAA,CAAM,IAAI,CAAA,IAAA,MAAS;AAAA,IACtB,MAAM,IAAA,CAAK,IAAA;AAAA,IACX,aAAa,IAAA,CAAK,WAAA;AAAA,IAClB,cAAc,IAAA,CAAK;AAAA,GACvB,CAAE,CAAA;AACN;AASO,SAAS,iBAAA,CAAkB,aAAA,EAAqF,aAAA,GAAgB,EAAA,EAAmB;AACtJ,EAAA,MAAM,WAAW,aAAA,CAAc,MAAA,CAAO,CAAA,CAAA,KAAK,CAAA,CAAE,SAAS,UAAU,CAAA;AAEhE,EAAA,IAAI,QAAA,CAAS,WAAW,CAAA,EAAG;AACvB,IAAA,OAAO,IAAA;AAAA,EACX;AAEA,EAAA,IAAI,IAAA,GAAO;AAAA;AAAA,QAAA,EAEL,aAAa;AAAA;AAAA,IAAA,CAAA;AAInB,EAAA,QAAA,CAAS,OAAA,CAAQ,CAAC,GAAA,KAAQ;AACtB,IAAA,IAAA,IAAQ;AAAA;AAAA,yBAAA,EAEW,GAAA,CAAI,EAAA,CAAG,OAAA,CAAQ,IAAA,EAAM,GAAG,CAAC,CAAA,eAAA,EAAkB,GAAA,CAAI,IAAI,CAAA,CAAA,EAAI,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,KAAK,CAAC,CAAA;AAAA;AAAA;AAAA,8BAAA,EAG3E,IAAI,EAAE,CAAA;AAAA,gCAAA,EACJ,GAAA,CAAI,EAAA,CAAG,OAAA,CAAQ,IAAA,EAAM,GAAG,CAAC,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,8BAAA,EAK3B,IAAI,EAAE,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAAA,CAAA;AAAA,EAMlC,CAAC,CAAA;AAED,EAAA,IAAA,IAAQ,CAAA,eAAA,CAAA;AACR,EAAA,OAAO,IAAA;AACX;AAYO,SAAS,kBAAkB,mBAAA,EAAsD;AACpF,EAAA,OAAO;AAAA,IACH,IAAA,EAAM,sBAAA;AAAA,IACN,WAAA,EAAa,CAAA;;AAAA,EAEnB,mBAAmB;;AAAA,sGAAA,CAAA;AAAA,IAGb,YAAA,EAAc;AAAA,MACV,IAAA,EAAM,QAAA;AAAA,MACN,UAAA,EAAY;AAAA,QACR,IAAA,EAAM;AAAA,UACF,IAAA,EAAM,QAAA;AAAA,UACN,WAAA,EAAa;AAAA;AACjB,OACJ;AAAA,MACA,QAAA,EAAU,CAAC,MAAM;AAAA;AACrB,GACJ;AACJ;AASA,eAAsB,qBAAA,CAClB,SACA,WAAA,EACgB;AAChB,EAAA,IAAI,OAAA,CAAQ,SAAS,sBAAA,EAAwB;AACzC,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,cAAA,EAAiB,OAAA,CAAQ,IAAI,CAAA,CAAE,CAAA;AAAA,EACnD;AAEA,EAAA,MAAM,QAAQ,OAAA,CAAQ,KAAA;AACtB,EAAA,MAAM,GAAA,GAAM,MAAM,WAAA,CAAY,SAAA,CAAU,MAAM,IAAI,CAAA;AAClD,EAAA,OAAO,GAAA,CAAI,MAAA;AACf","file":"anthropic.mjs","sourcesContent":["import type { ToolWithHandler } from '../types';\n\n/**\n * Anthropic tool_use block from message response\n */\nexport interface AnthropicToolUseBlock {\n type: 'tool_use';\n id: string;\n name: string;\n input: unknown;\n}\n\n/**\n * Anthropic tool definition\n */\nexport interface AnthropicToolDefinition {\n name: string;\n description?: string;\n input_schema: Record<string, unknown>;\n}\n\n/**\n * Helper to convert Granular tools to Anthropic tool definitions\n * \n * @param tools - Array of Granular tools\n * @returns Array of Anthropic tool definitions\n */\nexport function toAnthropicTools(tools: ToolWithHandler[]): AnthropicToolDefinition[] {\n return tools.map(tool => ({\n name: tool.name,\n description: tool.description,\n input_schema: tool.inputSchema,\n }));\n}\n\n/**\n * Helper to convert Anthropic tool calls to job code for Granular\n * \n * @param contentBlocks - Array of content blocks from Anthropic response\n * @param customImports - Optional imports to add to top of job\n * @returns generated job code, or null if no tool uses found\n */\nexport function toolUsesToJobCode(contentBlocks: Array<{ type: string; id?: string; name?: string; input?: unknown }>, customImports = ''): string | null {\n const toolUses = contentBlocks.filter(b => b.type === 'tool_use') as AnthropicToolUseBlock[];\n\n if (toolUses.length === 0) {\n return null;\n }\n\n let code = `\n import { tools } from './sandbox-tools';\n ${customImports}\n const results = [];\n `;\n\n toolUses.forEach((use) => {\n code += `\n try {\n const result_${use.id.replace(/-/g, '_')} = await tools.${use.name}(${JSON.stringify(use.input)});\n results.push({ \n type: 'tool_result',\n tool_use_id: \"${use.id}\", \n content: result_${use.id.replace(/-/g, '_')} \n });\n } catch (error) {\n results.push({ \n type: 'tool_result',\n tool_use_id: \"${use.id}\", \n content: String(error),\n is_error: true\n });\n }\n `;\n });\n\n code += `return results;`;\n return code;\n}\n\n/**\n * Create a single \"codegen tool\" for LLM consumption.\n * \n * Instead of passing N individual tools to the LLM, this returns a single\n * tool that accepts TypeScript code. The LLM writes code that uses the\n * available tools, and the code is executed in the sandbox.\n * \n * @param domainDocumentation - Documentation of available tools (from environment.getDomainDocumentation())\n * @returns A single Anthropic tool definition\n */\nexport function createCodegenTool(domainDocumentation: string): AnthropicToolDefinition {\n return {\n name: 'execute_sandbox_code',\n description: `Execute TypeScript code in a secure sandbox environment. The code can use the following tools by importing from \"./sandbox-tools\":\n\n${domainDocumentation}\n\nWrite complete, executable TypeScript code. Use async/await for tool calls. Return results at the end.`,\n input_schema: {\n type: 'object',\n properties: {\n code: {\n type: 'string',\n description: 'TypeScript code to execute. Must import tools from \"./sandbox-tools\" and use await for all tool calls.',\n },\n },\n required: ['code'],\n },\n };\n}\n\n/**\n * Helper to execute a codegen tool use block.\n * \n * @param toolUse - The tool_use block from the Anthropic response\n * @param environment - The connected Granular environment\n * @returns The job result\n */\nexport async function executeCodegenToolUse(\n toolUse: AnthropicToolUseBlock,\n environment: { submitJob: (code: string) => Promise<{ result: Promise<unknown> }> }\n): Promise<unknown> {\n if (toolUse.name !== 'execute_sandbox_code') {\n throw new Error(`Unknown tool: ${toolUse.name}`);\n }\n\n const input = toolUse.input as { code: string };\n const job = await environment.submitJob(input.code);\n return job.result;\n}\n"]}
@@ -0,0 +1,31 @@
1
+ import { StructuredTool } from '@langchain/core/tools';
2
+ import { T as ToolWithHandler } from '../types-D46q5WTh.mjs';
3
+
4
+ /**
5
+ * Helper to convert LangChain tools to Granular tools.
6
+ *
7
+ * Note: Since Granular tools execute handlers in the wrapper/client process
8
+ * via reverse-RPC, we can just wrap the LangChain tool's call method directly.
9
+ *
10
+ * @param langchainTools - Array of LangChain StructuredTools
11
+ * @returns Array of Granular ToolWithHandler
12
+ */
13
+ declare function fromLangChainTools(langchainTools: StructuredTool[]): ToolWithHandler[];
14
+ /**
15
+ * Create a single "codegen tool" for LangChain agent consumption.
16
+ *
17
+ * Instead of passing N individual tools to the agent, this returns a single
18
+ * tool that accepts TypeScript code. The LLM writes code that uses the
19
+ * available tools, and the code is executed in the sandbox.
20
+ *
21
+ * @param domainDocumentation - Documentation of available tools (from environment.getDomainDocumentation())
22
+ * @param environment - The connected Granular environment
23
+ * @returns A LangChain StructuredTool
24
+ */
25
+ declare function createCodegenTool(domainDocumentation: string, environment: {
26
+ submitJob: (code: string) => Promise<{
27
+ result: Promise<unknown>;
28
+ }>;
29
+ }): ToolWithHandler;
30
+
31
+ export { createCodegenTool, fromLangChainTools };
@@ -0,0 +1,31 @@
1
+ import { StructuredTool } from '@langchain/core/tools';
2
+ import { T as ToolWithHandler } from '../types-D46q5WTh.js';
3
+
4
+ /**
5
+ * Helper to convert LangChain tools to Granular tools.
6
+ *
7
+ * Note: Since Granular tools execute handlers in the wrapper/client process
8
+ * via reverse-RPC, we can just wrap the LangChain tool's call method directly.
9
+ *
10
+ * @param langchainTools - Array of LangChain StructuredTools
11
+ * @returns Array of Granular ToolWithHandler
12
+ */
13
+ declare function fromLangChainTools(langchainTools: StructuredTool[]): ToolWithHandler[];
14
+ /**
15
+ * Create a single "codegen tool" for LangChain agent consumption.
16
+ *
17
+ * Instead of passing N individual tools to the agent, this returns a single
18
+ * tool that accepts TypeScript code. The LLM writes code that uses the
19
+ * available tools, and the code is executed in the sandbox.
20
+ *
21
+ * @param domainDocumentation - Documentation of available tools (from environment.getDomainDocumentation())
22
+ * @param environment - The connected Granular environment
23
+ * @returns A LangChain StructuredTool
24
+ */
25
+ declare function createCodegenTool(domainDocumentation: string, environment: {
26
+ submitJob: (code: string) => Promise<{
27
+ result: Promise<unknown>;
28
+ }>;
29
+ }): ToolWithHandler;
30
+
31
+ export { createCodegenTool, fromLangChainTools };
@@ -0,0 +1,49 @@
1
+ 'use strict';
2
+
3
+ var zodToJsonSchema = require('zod-to-json-schema');
4
+
5
+ // src/adapters/langchain.ts
6
+ function fromLangChainTools(langchainTools) {
7
+ return langchainTools.map((tool) => {
8
+ const jsonSchema = zodToJsonSchema.zodToJsonSchema(tool.schema);
9
+ const inputSchema = jsonSchema.properties ? jsonSchema : jsonSchema.definitions ? jsonSchema.definitions[Object.keys(jsonSchema.definitions)[0]] : jsonSchema;
10
+ return {
11
+ name: tool.name,
12
+ description: tool.description,
13
+ inputSchema,
14
+ handler: async (input) => {
15
+ return tool.invoke(input);
16
+ }
17
+ };
18
+ });
19
+ }
20
+ function createCodegenTool(domainDocumentation, environment) {
21
+ return {
22
+ name: "sess",
23
+ description: `Execute TypeScript code in a secure sandbox environment. The code can use the following tools by importing from "./sandbox-tools":
24
+
25
+ ${domainDocumentation}
26
+
27
+ Write complete, executable TypeScript code. Use async/await for tool calls. Return results at the end.`,
28
+ inputSchema: {
29
+ type: "object",
30
+ properties: {
31
+ code: {
32
+ type: "string",
33
+ description: 'TypeScript code to execute. Must import tools from "./sandbox-tools" and use await for all tool calls.'
34
+ }
35
+ },
36
+ required: ["code"]
37
+ },
38
+ handler: async (input) => {
39
+ const { code } = input;
40
+ const job = await environment.submitJob(code);
41
+ return job.result;
42
+ }
43
+ };
44
+ }
45
+
46
+ exports.createCodegenTool = createCodegenTool;
47
+ exports.fromLangChainTools = fromLangChainTools;
48
+ //# sourceMappingURL=langchain.js.map
49
+ //# sourceMappingURL=langchain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/adapters/langchain.ts"],"names":["zodToJsonSchema"],"mappings":";;;;;AAcO,SAAS,mBAAmB,cAAA,EAAqD;AACpF,EAAA,OAAO,cAAA,CAAe,GAAA,CAAI,CAAC,IAAA,KAAS;AAEhC,IAAA,MAAM,UAAA,GAAkBA,+BAAA,CAAgB,IAAA,CAAK,MAAM,CAAA;AAGnD,IAAA,MAAM,WAAA,GAAc,UAAA,CAAW,UAAA,GAAa,UAAA,GAAc,WAAW,WAAA,GAAc,UAAA,CAAW,WAAA,CAAY,MAAA,CAAO,KAAK,UAAA,CAAW,WAAW,CAAA,CAAE,CAAC,CAAC,CAAA,GAAI,UAAA;AAEpJ,IAAA,OAAO;AAAA,MACH,MAAM,IAAA,CAAK,IAAA;AAAA,MACX,aAAa,IAAA,CAAK,WAAA;AAAA,MAClB,WAAA;AAAA,MACA,OAAA,EAAS,OAAO,KAAA,KAAe;AAG3B,QAAA,OAAO,IAAA,CAAK,OAAO,KAAY,CAAA;AAAA,MACnC;AAAA,KACJ;AAAA,EACJ,CAAC,CAAA;AACL;AAaO,SAAS,iBAAA,CACZ,qBACA,WAAA,EACe;AACf,EAAA,OAAO;AAAA,IACH,IAAA,EAAM,MAAA;AAAA,IACN,WAAA,EAAa,CAAA;;AAAA,EAEnB,mBAAmB;;AAAA,sGAAA,CAAA;AAAA,IAGb,WAAA,EAAa;AAAA,MACT,IAAA,EAAM,QAAA;AAAA,MACN,UAAA,EAAY;AAAA,QACR,IAAA,EAAM;AAAA,UACF,IAAA,EAAM,QAAA;AAAA,UACN,WAAA,EAAa;AAAA;AACjB,OACJ;AAAA,MACA,QAAA,EAAU,CAAC,MAAM;AAAA,KACrB;AAAA,IACA,OAAA,EAAS,OAAO,KAAA,KAAe;AAC3B,MAAA,MAAM,EAAE,MAAK,GAAI,KAAA;AACjB,MAAA,MAAM,GAAA,GAAM,MAAM,WAAA,CAAY,SAAA,CAAU,IAAI,CAAA;AAC5C,MAAA,OAAO,GAAA,CAAI,MAAA;AAAA,IACf;AAAA,GACJ;AACJ","file":"langchain.js","sourcesContent":["import { z } from 'zod';\nimport { StructuredTool } from '@langchain/core/tools';\nimport type { ToolWithHandler } from '../types';\nimport { zodToJsonSchema } from 'zod-to-json-schema';\n\n/**\n * Helper to convert LangChain tools to Granular tools.\n * \n * Note: Since Granular tools execute handlers in the wrapper/client process\n * via reverse-RPC, we can just wrap the LangChain tool's call method directly.\n * \n * @param langchainTools - Array of LangChain StructuredTools\n * @returns Array of Granular ToolWithHandler\n */\nexport function fromLangChainTools(langchainTools: StructuredTool[]): ToolWithHandler[] {\n return langchainTools.map((tool) => {\n // Zod to JSON Schema conversion\n const jsonSchema: any = zodToJsonSchema(tool.schema);\n // Remove $schema and properties wrapper if present, simplify for tool definition\n // This is a simplified conversion, might need adjustment based on specific Zod schemas\n const inputSchema = jsonSchema.properties ? jsonSchema : (jsonSchema.definitions ? jsonSchema.definitions[Object.keys(jsonSchema.definitions)[0]] : jsonSchema);\n\n return {\n name: tool.name,\n description: tool.description,\n inputSchema: inputSchema as Record<string, unknown>,\n handler: async (input: any) => {\n // Determine if input is a string or object based on expectations\n // LangChain tools expect specific inputs\n return tool.invoke(input as any);\n },\n };\n });\n}\n\n/**\n * Create a single \"codegen tool\" for LangChain agent consumption.\n * \n * Instead of passing N individual tools to the agent, this returns a single\n * tool that accepts TypeScript code. The LLM writes code that uses the\n * available tools, and the code is executed in the sandbox.\n * \n * @param domainDocumentation - Documentation of available tools (from environment.getDomainDocumentation())\n * @param environment - The connected Granular environment\n * @returns A LangChain StructuredTool\n */\nexport function createCodegenTool(\n domainDocumentation: string,\n environment: { submitJob: (code: string) => Promise<{ result: Promise<unknown> }> }\n): ToolWithHandler {\n return {\n name: 'sess',\n description: `Execute TypeScript code in a secure sandbox environment. The code can use the following tools by importing from \"./sandbox-tools\":\n\n${domainDocumentation}\n\nWrite complete, executable TypeScript code. Use async/await for tool calls. Return results at the end.`,\n inputSchema: {\n type: 'object',\n properties: {\n code: {\n type: 'string',\n description: 'TypeScript code to execute. Must import tools from \"./sandbox-tools\" and use await for all tool calls.',\n },\n },\n required: ['code'],\n },\n handler: async (input: any) => {\n const { code } = input as { code: string };\n const job = await environment.submitJob(code);\n return job.result;\n },\n };\n}\n"]}
@@ -0,0 +1,46 @@
1
+ import { zodToJsonSchema } from 'zod-to-json-schema';
2
+
3
+ // src/adapters/langchain.ts
4
+ function fromLangChainTools(langchainTools) {
5
+ return langchainTools.map((tool) => {
6
+ const jsonSchema = zodToJsonSchema(tool.schema);
7
+ const inputSchema = jsonSchema.properties ? jsonSchema : jsonSchema.definitions ? jsonSchema.definitions[Object.keys(jsonSchema.definitions)[0]] : jsonSchema;
8
+ return {
9
+ name: tool.name,
10
+ description: tool.description,
11
+ inputSchema,
12
+ handler: async (input) => {
13
+ return tool.invoke(input);
14
+ }
15
+ };
16
+ });
17
+ }
18
+ function createCodegenTool(domainDocumentation, environment) {
19
+ return {
20
+ name: "sess",
21
+ description: `Execute TypeScript code in a secure sandbox environment. The code can use the following tools by importing from "./sandbox-tools":
22
+
23
+ ${domainDocumentation}
24
+
25
+ Write complete, executable TypeScript code. Use async/await for tool calls. Return results at the end.`,
26
+ inputSchema: {
27
+ type: "object",
28
+ properties: {
29
+ code: {
30
+ type: "string",
31
+ description: 'TypeScript code to execute. Must import tools from "./sandbox-tools" and use await for all tool calls.'
32
+ }
33
+ },
34
+ required: ["code"]
35
+ },
36
+ handler: async (input) => {
37
+ const { code } = input;
38
+ const job = await environment.submitJob(code);
39
+ return job.result;
40
+ }
41
+ };
42
+ }
43
+
44
+ export { createCodegenTool, fromLangChainTools };
45
+ //# sourceMappingURL=langchain.mjs.map
46
+ //# sourceMappingURL=langchain.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/adapters/langchain.ts"],"names":[],"mappings":";;;AAcO,SAAS,mBAAmB,cAAA,EAAqD;AACpF,EAAA,OAAO,cAAA,CAAe,GAAA,CAAI,CAAC,IAAA,KAAS;AAEhC,IAAA,MAAM,UAAA,GAAkB,eAAA,CAAgB,IAAA,CAAK,MAAM,CAAA;AAGnD,IAAA,MAAM,WAAA,GAAc,UAAA,CAAW,UAAA,GAAa,UAAA,GAAc,WAAW,WAAA,GAAc,UAAA,CAAW,WAAA,CAAY,MAAA,CAAO,KAAK,UAAA,CAAW,WAAW,CAAA,CAAE,CAAC,CAAC,CAAA,GAAI,UAAA;AAEpJ,IAAA,OAAO;AAAA,MACH,MAAM,IAAA,CAAK,IAAA;AAAA,MACX,aAAa,IAAA,CAAK,WAAA;AAAA,MAClB,WAAA;AAAA,MACA,OAAA,EAAS,OAAO,KAAA,KAAe;AAG3B,QAAA,OAAO,IAAA,CAAK,OAAO,KAAY,CAAA;AAAA,MACnC;AAAA,KACJ;AAAA,EACJ,CAAC,CAAA;AACL;AAaO,SAAS,iBAAA,CACZ,qBACA,WAAA,EACe;AACf,EAAA,OAAO;AAAA,IACH,IAAA,EAAM,MAAA;AAAA,IACN,WAAA,EAAa,CAAA;;AAAA,EAEnB,mBAAmB;;AAAA,sGAAA,CAAA;AAAA,IAGb,WAAA,EAAa;AAAA,MACT,IAAA,EAAM,QAAA;AAAA,MACN,UAAA,EAAY;AAAA,QACR,IAAA,EAAM;AAAA,UACF,IAAA,EAAM,QAAA;AAAA,UACN,WAAA,EAAa;AAAA;AACjB,OACJ;AAAA,MACA,QAAA,EAAU,CAAC,MAAM;AAAA,KACrB;AAAA,IACA,OAAA,EAAS,OAAO,KAAA,KAAe;AAC3B,MAAA,MAAM,EAAE,MAAK,GAAI,KAAA;AACjB,MAAA,MAAM,GAAA,GAAM,MAAM,WAAA,CAAY,SAAA,CAAU,IAAI,CAAA;AAC5C,MAAA,OAAO,GAAA,CAAI,MAAA;AAAA,IACf;AAAA,GACJ;AACJ","file":"langchain.mjs","sourcesContent":["import { z } from 'zod';\nimport { StructuredTool } from '@langchain/core/tools';\nimport type { ToolWithHandler } from '../types';\nimport { zodToJsonSchema } from 'zod-to-json-schema';\n\n/**\n * Helper to convert LangChain tools to Granular tools.\n * \n * Note: Since Granular tools execute handlers in the wrapper/client process\n * via reverse-RPC, we can just wrap the LangChain tool's call method directly.\n * \n * @param langchainTools - Array of LangChain StructuredTools\n * @returns Array of Granular ToolWithHandler\n */\nexport function fromLangChainTools(langchainTools: StructuredTool[]): ToolWithHandler[] {\n return langchainTools.map((tool) => {\n // Zod to JSON Schema conversion\n const jsonSchema: any = zodToJsonSchema(tool.schema);\n // Remove $schema and properties wrapper if present, simplify for tool definition\n // This is a simplified conversion, might need adjustment based on specific Zod schemas\n const inputSchema = jsonSchema.properties ? jsonSchema : (jsonSchema.definitions ? jsonSchema.definitions[Object.keys(jsonSchema.definitions)[0]] : jsonSchema);\n\n return {\n name: tool.name,\n description: tool.description,\n inputSchema: inputSchema as Record<string, unknown>,\n handler: async (input: any) => {\n // Determine if input is a string or object based on expectations\n // LangChain tools expect specific inputs\n return tool.invoke(input as any);\n },\n };\n });\n}\n\n/**\n * Create a single \"codegen tool\" for LangChain agent consumption.\n * \n * Instead of passing N individual tools to the agent, this returns a single\n * tool that accepts TypeScript code. The LLM writes code that uses the\n * available tools, and the code is executed in the sandbox.\n * \n * @param domainDocumentation - Documentation of available tools (from environment.getDomainDocumentation())\n * @param environment - The connected Granular environment\n * @returns A LangChain StructuredTool\n */\nexport function createCodegenTool(\n domainDocumentation: string,\n environment: { submitJob: (code: string) => Promise<{ result: Promise<unknown> }> }\n): ToolWithHandler {\n return {\n name: 'sess',\n description: `Execute TypeScript code in a secure sandbox environment. The code can use the following tools by importing from \"./sandbox-tools\":\n\n${domainDocumentation}\n\nWrite complete, executable TypeScript code. Use async/await for tool calls. Return results at the end.`,\n inputSchema: {\n type: 'object',\n properties: {\n code: {\n type: 'string',\n description: 'TypeScript code to execute. Must import tools from \"./sandbox-tools\" and use await for all tool calls.',\n },\n },\n required: ['code'],\n },\n handler: async (input: any) => {\n const { code } = input as { code: string };\n const job = await environment.submitJob(code);\n return job.result;\n },\n };\n}\n"]}
@@ -0,0 +1,23 @@
1
+ import { z } from 'zod';
2
+ import { T as ToolWithHandler } from '../types-D46q5WTh.mjs';
3
+
4
+ /**
5
+ * Mastra tool definition interface
6
+ */
7
+ interface MastraTool {
8
+ id: string;
9
+ description?: string;
10
+ inputSchema?: z.ZodType<unknown>;
11
+ execute?: (context: {
12
+ context: unknown;
13
+ }) => Promise<unknown>;
14
+ }
15
+ /**
16
+ * Helper to convert Mastra tools to Granular tools
17
+ *
18
+ * @param mastraTools - Array of Mastra tools
19
+ * @returns Array of Granular ToolWithHandler
20
+ */
21
+ declare function fromMastraTools(mastraTools: MastraTool[]): ToolWithHandler[];
22
+
23
+ export { type MastraTool, fromMastraTools };
@@ -0,0 +1,23 @@
1
+ import { z } from 'zod';
2
+ import { T as ToolWithHandler } from '../types-D46q5WTh.js';
3
+
4
+ /**
5
+ * Mastra tool definition interface
6
+ */
7
+ interface MastraTool {
8
+ id: string;
9
+ description?: string;
10
+ inputSchema?: z.ZodType<unknown>;
11
+ execute?: (context: {
12
+ context: unknown;
13
+ }) => Promise<unknown>;
14
+ }
15
+ /**
16
+ * Helper to convert Mastra tools to Granular tools
17
+ *
18
+ * @param mastraTools - Array of Mastra tools
19
+ * @returns Array of Granular ToolWithHandler
20
+ */
21
+ declare function fromMastraTools(mastraTools: MastraTool[]): ToolWithHandler[];
22
+
23
+ export { type MastraTool, fromMastraTools };
@@ -0,0 +1,26 @@
1
+ 'use strict';
2
+
3
+ var zodToJsonSchema = require('zod-to-json-schema');
4
+
5
+ // src/adapters/mastra.ts
6
+ function fromMastraTools(mastraTools) {
7
+ return mastraTools.map((tool) => {
8
+ const jsonSchema = tool.inputSchema ? zodToJsonSchema.zodToJsonSchema(tool.inputSchema) : {};
9
+ return {
10
+ name: tool.id,
11
+ // Mastra uses ID as name
12
+ description: tool.description || "",
13
+ inputSchema: jsonSchema,
14
+ handler: async (input) => {
15
+ if (tool.execute) {
16
+ return tool.execute({ context: input });
17
+ }
18
+ return {};
19
+ }
20
+ };
21
+ });
22
+ }
23
+
24
+ exports.fromMastraTools = fromMastraTools;
25
+ //# sourceMappingURL=mastra.js.map
26
+ //# sourceMappingURL=mastra.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/adapters/mastra.ts"],"names":["zodToJsonSchema"],"mappings":";;;;;AAoBO,SAAS,gBAAgB,WAAA,EAA8C;AAC1E,EAAA,OAAO,WAAA,CAAY,GAAA,CAAI,CAAC,IAAA,KAAS;AAC7B,IAAA,MAAM,aAAa,IAAA,CAAK,WAAA,GAAcA,gCAAgB,IAAA,CAAK,WAAW,IAAI,EAAC;AAE3E,IAAA,OAAO;AAAA,MACH,MAAM,IAAA,CAAK,EAAA;AAAA;AAAA,MACX,WAAA,EAAa,KAAK,WAAA,IAAe,EAAA;AAAA,MACjC,WAAA,EAAa,UAAA;AAAA,MACb,OAAA,EAAS,OAAO,KAAA,KAAe;AAC3B,QAAA,IAAI,KAAK,OAAA,EAAS;AACd,UAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,EAAE,OAAA,EAAS,OAAO,CAAA;AAAA,QAC1C;AACA,QAAA,OAAO,EAAC;AAAA,MACZ;AAAA,KACJ;AAAA,EACJ,CAAC,CAAA;AACL","file":"mastra.js","sourcesContent":["import { z } from 'zod';\nimport type { ToolWithHandler } from '../types';\nimport { zodToJsonSchema } from 'zod-to-json-schema';\n\n/**\n * Mastra tool definition interface\n */\nexport interface MastraTool {\n id: string;\n description?: string;\n inputSchema?: z.ZodType<unknown>;\n execute?: (context: { context: unknown }) => Promise<unknown>;\n}\n\n/**\n * Helper to convert Mastra tools to Granular tools\n * \n * @param mastraTools - Array of Mastra tools\n * @returns Array of Granular ToolWithHandler\n */\nexport function fromMastraTools(mastraTools: MastraTool[]): ToolWithHandler[] {\n return mastraTools.map((tool) => {\n const jsonSchema = tool.inputSchema ? zodToJsonSchema(tool.inputSchema) : {};\n\n return {\n name: tool.id, // Mastra uses ID as name\n description: tool.description || '',\n inputSchema: jsonSchema as Record<string, unknown>,\n handler: async (input: any) => {\n if (tool.execute) {\n return tool.execute({ context: input });\n }\n return {};\n },\n };\n });\n}\n"]}
@@ -0,0 +1,24 @@
1
+ import { zodToJsonSchema } from 'zod-to-json-schema';
2
+
3
+ // src/adapters/mastra.ts
4
+ function fromMastraTools(mastraTools) {
5
+ return mastraTools.map((tool) => {
6
+ const jsonSchema = tool.inputSchema ? zodToJsonSchema(tool.inputSchema) : {};
7
+ return {
8
+ name: tool.id,
9
+ // Mastra uses ID as name
10
+ description: tool.description || "",
11
+ inputSchema: jsonSchema,
12
+ handler: async (input) => {
13
+ if (tool.execute) {
14
+ return tool.execute({ context: input });
15
+ }
16
+ return {};
17
+ }
18
+ };
19
+ });
20
+ }
21
+
22
+ export { fromMastraTools };
23
+ //# sourceMappingURL=mastra.mjs.map
24
+ //# sourceMappingURL=mastra.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/adapters/mastra.ts"],"names":[],"mappings":";;;AAoBO,SAAS,gBAAgB,WAAA,EAA8C;AAC1E,EAAA,OAAO,WAAA,CAAY,GAAA,CAAI,CAAC,IAAA,KAAS;AAC7B,IAAA,MAAM,aAAa,IAAA,CAAK,WAAA,GAAc,gBAAgB,IAAA,CAAK,WAAW,IAAI,EAAC;AAE3E,IAAA,OAAO;AAAA,MACH,MAAM,IAAA,CAAK,EAAA;AAAA;AAAA,MACX,WAAA,EAAa,KAAK,WAAA,IAAe,EAAA;AAAA,MACjC,WAAA,EAAa,UAAA;AAAA,MACb,OAAA,EAAS,OAAO,KAAA,KAAe;AAC3B,QAAA,IAAI,KAAK,OAAA,EAAS;AACd,UAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,EAAE,OAAA,EAAS,OAAO,CAAA;AAAA,QAC1C;AACA,QAAA,OAAO,EAAC;AAAA,MACZ;AAAA,KACJ;AAAA,EACJ,CAAC,CAAA;AACL","file":"mastra.mjs","sourcesContent":["import { z } from 'zod';\nimport type { ToolWithHandler } from '../types';\nimport { zodToJsonSchema } from 'zod-to-json-schema';\n\n/**\n * Mastra tool definition interface\n */\nexport interface MastraTool {\n id: string;\n description?: string;\n inputSchema?: z.ZodType<unknown>;\n execute?: (context: { context: unknown }) => Promise<unknown>;\n}\n\n/**\n * Helper to convert Mastra tools to Granular tools\n * \n * @param mastraTools - Array of Mastra tools\n * @returns Array of Granular ToolWithHandler\n */\nexport function fromMastraTools(mastraTools: MastraTool[]): ToolWithHandler[] {\n return mastraTools.map((tool) => {\n const jsonSchema = tool.inputSchema ? zodToJsonSchema(tool.inputSchema) : {};\n\n return {\n name: tool.id, // Mastra uses ID as name\n description: tool.description || '',\n inputSchema: jsonSchema as Record<string, unknown>,\n handler: async (input: any) => {\n if (tool.execute) {\n return tool.execute({ context: input });\n }\n return {};\n },\n };\n });\n}\n"]}
@@ -0,0 +1,76 @@
1
+ import { T as ToolWithHandler } from '../types-D46q5WTh.mjs';
2
+
3
+ /**
4
+ * OpenAI tool call from chat completion response
5
+ */
6
+ interface OpenAIToolCall {
7
+ id: string;
8
+ type: 'function';
9
+ function: {
10
+ name: string;
11
+ arguments: string;
12
+ };
13
+ }
14
+ /**
15
+ * OpenAI tool definition type
16
+ */
17
+ interface OpenAIToolDefinition {
18
+ type: 'function';
19
+ function: {
20
+ name: string;
21
+ description?: string;
22
+ parameters?: Record<string, unknown>;
23
+ };
24
+ }
25
+ /**
26
+ * Helper to convert Granular tools to OpenAI tool definitions
27
+ *
28
+ * @param tools - Array of Granular tools
29
+ * @returns Array of OpenAI tool definitions
30
+ */
31
+ declare function toOpenAITools(tools: ToolWithHandler[]): OpenAIToolDefinition[];
32
+ /**
33
+ * Helper to convert OpenAI tool calls to job code for Granular
34
+ *
35
+ * @param toolCalls - Array of tool calls from OpenAI response
36
+ * @param customImports - Optional imports to add to top of job
37
+ * @returns generated job code
38
+ */
39
+ declare function toolCallsToJobCode(toolCalls: OpenAIToolCall[], customImports?: string): string;
40
+ /**
41
+ * Create a single "codegen tool" for LLM consumption.
42
+ *
43
+ * Instead of passing N individual tools to the LLM, this returns a single
44
+ * tool that accepts TypeScript code. The LLM writes code that uses the
45
+ * available tools, and the code is executed in the sandbox.
46
+ *
47
+ * @param domainDocumentation - Documentation of available tools (from environment.getDomainDocumentation())
48
+ * @returns A single OpenAI tool definition
49
+ *
50
+ * @example
51
+ * ```typescript
52
+ * const docs = await environment.getDomainDocumentation();
53
+ * const codegenTool = createCodegenTool(docs);
54
+ *
55
+ * const response = await openai.chat.completions.create({
56
+ * model: 'gpt-4',
57
+ * messages: [...],
58
+ * tools: [codegenTool],
59
+ * });
60
+ * ```
61
+ */
62
+ declare function createCodegenTool(domainDocumentation: string): OpenAIToolDefinition;
63
+ /**
64
+ * Helper to execute a codegen tool call result.
65
+ *
66
+ * @param toolCall - The tool call from the OpenAI response
67
+ * @param environment - The connected Granular environment
68
+ * @returns The job result
69
+ */
70
+ declare function executeCodegenToolCall(toolCall: OpenAIToolCall, environment: {
71
+ submitJob: (code: string) => Promise<{
72
+ result: Promise<unknown>;
73
+ }>;
74
+ }): Promise<unknown>;
75
+
76
+ export { type OpenAIToolCall, type OpenAIToolDefinition, createCodegenTool, executeCodegenToolCall, toOpenAITools, toolCallsToJobCode };
@@ -0,0 +1,76 @@
1
+ import { T as ToolWithHandler } from '../types-D46q5WTh.js';
2
+
3
+ /**
4
+ * OpenAI tool call from chat completion response
5
+ */
6
+ interface OpenAIToolCall {
7
+ id: string;
8
+ type: 'function';
9
+ function: {
10
+ name: string;
11
+ arguments: string;
12
+ };
13
+ }
14
+ /**
15
+ * OpenAI tool definition type
16
+ */
17
+ interface OpenAIToolDefinition {
18
+ type: 'function';
19
+ function: {
20
+ name: string;
21
+ description?: string;
22
+ parameters?: Record<string, unknown>;
23
+ };
24
+ }
25
+ /**
26
+ * Helper to convert Granular tools to OpenAI tool definitions
27
+ *
28
+ * @param tools - Array of Granular tools
29
+ * @returns Array of OpenAI tool definitions
30
+ */
31
+ declare function toOpenAITools(tools: ToolWithHandler[]): OpenAIToolDefinition[];
32
+ /**
33
+ * Helper to convert OpenAI tool calls to job code for Granular
34
+ *
35
+ * @param toolCalls - Array of tool calls from OpenAI response
36
+ * @param customImports - Optional imports to add to top of job
37
+ * @returns generated job code
38
+ */
39
+ declare function toolCallsToJobCode(toolCalls: OpenAIToolCall[], customImports?: string): string;
40
+ /**
41
+ * Create a single "codegen tool" for LLM consumption.
42
+ *
43
+ * Instead of passing N individual tools to the LLM, this returns a single
44
+ * tool that accepts TypeScript code. The LLM writes code that uses the
45
+ * available tools, and the code is executed in the sandbox.
46
+ *
47
+ * @param domainDocumentation - Documentation of available tools (from environment.getDomainDocumentation())
48
+ * @returns A single OpenAI tool definition
49
+ *
50
+ * @example
51
+ * ```typescript
52
+ * const docs = await environment.getDomainDocumentation();
53
+ * const codegenTool = createCodegenTool(docs);
54
+ *
55
+ * const response = await openai.chat.completions.create({
56
+ * model: 'gpt-4',
57
+ * messages: [...],
58
+ * tools: [codegenTool],
59
+ * });
60
+ * ```
61
+ */
62
+ declare function createCodegenTool(domainDocumentation: string): OpenAIToolDefinition;
63
+ /**
64
+ * Helper to execute a codegen tool call result.
65
+ *
66
+ * @param toolCall - The tool call from the OpenAI response
67
+ * @param environment - The connected Granular environment
68
+ * @returns The job result
69
+ */
70
+ declare function executeCodegenToolCall(toolCall: OpenAIToolCall, environment: {
71
+ submitJob: (code: string) => Promise<{
72
+ result: Promise<unknown>;
73
+ }>;
74
+ }): Promise<unknown>;
75
+
76
+ export { type OpenAIToolCall, type OpenAIToolDefinition, createCodegenTool, executeCodegenToolCall, toOpenAITools, toolCallsToJobCode };
@@ -0,0 +1,81 @@
1
+ 'use strict';
2
+
3
+ // src/adapters/openai.ts
4
+ function toOpenAITools(tools) {
5
+ return tools.map((tool) => ({
6
+ type: "function",
7
+ function: {
8
+ name: tool.name,
9
+ description: tool.description,
10
+ parameters: tool.inputSchema
11
+ }
12
+ }));
13
+ }
14
+ function toolCallsToJobCode(toolCalls, customImports = "") {
15
+ if (!toolCalls || toolCalls.length === 0) {
16
+ return "";
17
+ }
18
+ let code = `
19
+ import { tools } from './sandbox-tools';
20
+ ${customImports}
21
+ const results = [];
22
+ `;
23
+ toolCalls.forEach((call) => {
24
+ code += `
25
+ try {
26
+ const result_${call.id.replace(/-/g, "_")} = await tools.${call.function.name}(${call.function.arguments});
27
+ results.push({
28
+ toolCallId: "${call.id}",
29
+ tool: "${call.function.name}",
30
+ result: result_${call.id.replace(/-/g, "_")}
31
+ });
32
+ } catch (error) {
33
+ results.push({
34
+ toolCallId: "${call.id}",
35
+ tool: "${call.function.name}",
36
+ error: String(error)
37
+ });
38
+ }
39
+ `;
40
+ });
41
+ code += `return results;`;
42
+ return code;
43
+ }
44
+ function createCodegenTool(domainDocumentation) {
45
+ return {
46
+ type: "function",
47
+ function: {
48
+ name: "execute_sandbox_code",
49
+ description: `Execute TypeScript code in a secure sandbox environment. The code can use the following tools by importing from "./sandbox-tools":
50
+
51
+ ${domainDocumentation}
52
+
53
+ Write complete, executable TypeScript code. Use async/await for tool calls. Return results at the end.`,
54
+ parameters: {
55
+ type: "object",
56
+ properties: {
57
+ code: {
58
+ type: "string",
59
+ description: 'TypeScript code to execute. Must import tools from "./sandbox-tools" and use await for all tool calls.'
60
+ }
61
+ },
62
+ required: ["code"]
63
+ }
64
+ }
65
+ };
66
+ }
67
+ async function executeCodegenToolCall(toolCall, environment) {
68
+ if (toolCall.function.name !== "execute_sandbox_code") {
69
+ throw new Error(`Unknown tool: ${toolCall.function.name}`);
70
+ }
71
+ const args = JSON.parse(toolCall.function.arguments);
72
+ const job = await environment.submitJob(args.code);
73
+ return job.result;
74
+ }
75
+
76
+ exports.createCodegenTool = createCodegenTool;
77
+ exports.executeCodegenToolCall = executeCodegenToolCall;
78
+ exports.toOpenAITools = toOpenAITools;
79
+ exports.toolCallsToJobCode = toolCallsToJobCode;
80
+ //# sourceMappingURL=openai.js.map
81
+ //# sourceMappingURL=openai.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/adapters/openai.ts"],"names":[],"mappings":";;;AAgCO,SAAS,cAAc,KAAA,EAAkD;AAC5E,EAAA,OAAO,KAAA,CAAM,IAAI,CAAA,IAAA,MAAS;AAAA,IACtB,IAAA,EAAM,UAAA;AAAA,IACN,QAAA,EAAU;AAAA,MACN,MAAM,IAAA,CAAK,IAAA;AAAA,MACX,aAAa,IAAA,CAAK,WAAA;AAAA,MAClB,YAAY,IAAA,CAAK;AAAA;AACrB,GACJ,CAAE,CAAA;AACN;AASO,SAAS,kBAAA,CAAmB,SAAA,EAA6B,aAAA,GAAgB,EAAA,EAAY;AACxF,EAAA,IAAI,CAAC,SAAA,IAAa,SAAA,CAAU,MAAA,KAAW,CAAA,EAAG;AACtC,IAAA,OAAO,EAAA;AAAA,EACX;AAEA,EAAA,IAAI,IAAA,GAAO;AAAA;AAAA,QAAA,EAEL,aAAa;AAAA;AAAA,IAAA,CAAA;AAInB,EAAA,SAAA,CAAU,OAAA,CAAQ,CAAC,IAAA,KAAS;AAGxB,IAAA,IAAA,IAAQ;AAAA;AAAA,yBAAA,EAEW,IAAA,CAAK,EAAA,CAAG,OAAA,CAAQ,IAAA,EAAM,GAAG,CAAC,CAAA,eAAA,EAAkB,IAAA,CAAK,QAAA,CAAS,IAAI,CAAA,CAAA,EAAI,IAAA,CAAK,SAAS,SAAS,CAAA;AAAA;AAAA,6BAAA,EAErF,KAAK,EAAE,CAAA;AAAA,uBAAA,EACb,IAAA,CAAK,SAAS,IAAI,CAAA;AAAA,+BAAA,EACV,IAAA,CAAK,EAAA,CAAG,OAAA,CAAQ,IAAA,EAAM,GAAG,CAAC,CAAA;AAAA;AAAA;AAAA;AAAA,6BAAA,EAI5B,KAAK,EAAE,CAAA;AAAA,uBAAA,EACb,IAAA,CAAK,SAAS,IAAI,CAAA;AAAA;AAAA;AAAA;AAAA,QAAA,CAAA;AAAA,EAKvC,CAAC,CAAA;AAED,EAAA,IAAA,IAAQ,CAAA,eAAA,CAAA;AACR,EAAA,OAAO,IAAA;AACX;AAwBO,SAAS,kBAAkB,mBAAA,EAAmD;AACjF,EAAA,OAAO;AAAA,IACH,IAAA,EAAM,UAAA;AAAA,IACN,QAAA,EAAU;AAAA,MACN,IAAA,EAAM,sBAAA;AAAA,MACN,WAAA,EAAa,CAAA;;AAAA,EAEvB,mBAAmB;;AAAA,sGAAA,CAAA;AAAA,MAGT,UAAA,EAAY;AAAA,QACR,IAAA,EAAM,QAAA;AAAA,QACN,UAAA,EAAY;AAAA,UACR,IAAA,EAAM;AAAA,YACF,IAAA,EAAM,QAAA;AAAA,YACN,WAAA,EAAa;AAAA;AACjB,SACJ;AAAA,QACA,QAAA,EAAU,CAAC,MAAM;AAAA;AACrB;AACJ,GACJ;AACJ;AASA,eAAsB,sBAAA,CAClB,UACA,WAAA,EACgB;AAChB,EAAA,IAAI,QAAA,CAAS,QAAA,CAAS,IAAA,KAAS,sBAAA,EAAwB;AACnD,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,cAAA,EAAiB,QAAA,CAAS,QAAA,CAAS,IAAI,CAAA,CAAE,CAAA;AAAA,EAC7D;AAEA,EAAA,MAAM,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,QAAA,CAAS,SAAS,SAAS,CAAA;AACnD,EAAA,MAAM,GAAA,GAAM,MAAM,WAAA,CAAY,SAAA,CAAU,KAAK,IAAI,CAAA;AACjD,EAAA,OAAO,GAAA,CAAI,MAAA;AACf","file":"openai.js","sourcesContent":["import type { ToolWithHandler } from '../types';\n\n/**\n * OpenAI tool call from chat completion response\n */\nexport interface OpenAIToolCall {\n id: string;\n type: 'function';\n function: {\n name: string;\n arguments: string;\n };\n}\n\n/**\n * OpenAI tool definition type\n */\nexport interface OpenAIToolDefinition {\n type: 'function';\n function: {\n name: string;\n description?: string;\n parameters?: Record<string, unknown>;\n };\n}\n\n/**\n * Helper to convert Granular tools to OpenAI tool definitions\n * \n * @param tools - Array of Granular tools\n * @returns Array of OpenAI tool definitions\n */\nexport function toOpenAITools(tools: ToolWithHandler[]): OpenAIToolDefinition[] {\n return tools.map(tool => ({\n type: 'function',\n function: {\n name: tool.name,\n description: tool.description,\n parameters: tool.inputSchema,\n },\n }));\n}\n\n/**\n * Helper to convert OpenAI tool calls to job code for Granular\n * \n * @param toolCalls - Array of tool calls from OpenAI response\n * @param customImports - Optional imports to add to top of job\n * @returns generated job code\n */\nexport function toolCallsToJobCode(toolCalls: OpenAIToolCall[], customImports = ''): string {\n if (!toolCalls || toolCalls.length === 0) {\n return '';\n }\n\n let code = `\n import { tools } from './sandbox-tools';\n ${customImports}\n const results = [];\n `;\n\n toolCalls.forEach((call) => {\n // Safe argument parsing\n // We trust OpenAI arguments are JSON, but we stringify them again for the job\n code += `\n try {\n const result_${call.id.replace(/-/g, '_')} = await tools.${call.function.name}(${call.function.arguments});\n results.push({ \n toolCallId: \"${call.id}\", \n tool: \"${call.function.name}\", \n result: result_${call.id.replace(/-/g, '_')} \n });\n } catch (error) {\n results.push({ \n toolCallId: \"${call.id}\", \n tool: \"${call.function.name}\", \n error: String(error) \n });\n }\n `;\n });\n\n code += `return results;`;\n return code;\n}\n\n/**\n * Create a single \"codegen tool\" for LLM consumption.\n * \n * Instead of passing N individual tools to the LLM, this returns a single\n * tool that accepts TypeScript code. The LLM writes code that uses the\n * available tools, and the code is executed in the sandbox.\n * \n * @param domainDocumentation - Documentation of available tools (from environment.getDomainDocumentation())\n * @returns A single OpenAI tool definition\n * \n * @example\n * ```typescript\n * const docs = await environment.getDomainDocumentation();\n * const codegenTool = createCodegenTool(docs);\n * \n * const response = await openai.chat.completions.create({\n * model: 'gpt-4',\n * messages: [...],\n * tools: [codegenTool],\n * });\n * ```\n */\nexport function createCodegenTool(domainDocumentation: string): OpenAIToolDefinition {\n return {\n type: 'function',\n function: {\n name: 'execute_sandbox_code',\n description: `Execute TypeScript code in a secure sandbox environment. The code can use the following tools by importing from \"./sandbox-tools\":\n\n${domainDocumentation}\n\nWrite complete, executable TypeScript code. Use async/await for tool calls. Return results at the end.`,\n parameters: {\n type: 'object',\n properties: {\n code: {\n type: 'string',\n description: 'TypeScript code to execute. Must import tools from \"./sandbox-tools\" and use await for all tool calls.',\n },\n },\n required: ['code'],\n },\n },\n };\n}\n\n/**\n * Helper to execute a codegen tool call result.\n * \n * @param toolCall - The tool call from the OpenAI response\n * @param environment - The connected Granular environment\n * @returns The job result\n */\nexport async function executeCodegenToolCall(\n toolCall: OpenAIToolCall,\n environment: { submitJob: (code: string) => Promise<{ result: Promise<unknown> }> }\n): Promise<unknown> {\n if (toolCall.function.name !== 'execute_sandbox_code') {\n throw new Error(`Unknown tool: ${toolCall.function.name}`);\n }\n\n const args = JSON.parse(toolCall.function.arguments) as { code: string };\n const job = await environment.submitJob(args.code);\n return job.result;\n}\n"]}