@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,76 @@
1
+ // src/adapters/openai.ts
2
+ function toOpenAITools(tools) {
3
+ return tools.map((tool) => ({
4
+ type: "function",
5
+ function: {
6
+ name: tool.name,
7
+ description: tool.description,
8
+ parameters: tool.inputSchema
9
+ }
10
+ }));
11
+ }
12
+ function toolCallsToJobCode(toolCalls, customImports = "") {
13
+ if (!toolCalls || toolCalls.length === 0) {
14
+ return "";
15
+ }
16
+ let code = `
17
+ import { tools } from './sandbox-tools';
18
+ ${customImports}
19
+ const results = [];
20
+ `;
21
+ toolCalls.forEach((call) => {
22
+ code += `
23
+ try {
24
+ const result_${call.id.replace(/-/g, "_")} = await tools.${call.function.name}(${call.function.arguments});
25
+ results.push({
26
+ toolCallId: "${call.id}",
27
+ tool: "${call.function.name}",
28
+ result: result_${call.id.replace(/-/g, "_")}
29
+ });
30
+ } catch (error) {
31
+ results.push({
32
+ toolCallId: "${call.id}",
33
+ tool: "${call.function.name}",
34
+ error: String(error)
35
+ });
36
+ }
37
+ `;
38
+ });
39
+ code += `return results;`;
40
+ return code;
41
+ }
42
+ function createCodegenTool(domainDocumentation) {
43
+ return {
44
+ type: "function",
45
+ function: {
46
+ name: "execute_sandbox_code",
47
+ description: `Execute TypeScript code in a secure sandbox environment. The code can use the following tools by importing from "./sandbox-tools":
48
+
49
+ ${domainDocumentation}
50
+
51
+ Write complete, executable TypeScript code. Use async/await for tool calls. Return results at the end.`,
52
+ parameters: {
53
+ type: "object",
54
+ properties: {
55
+ code: {
56
+ type: "string",
57
+ description: 'TypeScript code to execute. Must import tools from "./sandbox-tools" and use await for all tool calls.'
58
+ }
59
+ },
60
+ required: ["code"]
61
+ }
62
+ }
63
+ };
64
+ }
65
+ async function executeCodegenToolCall(toolCall, environment) {
66
+ if (toolCall.function.name !== "execute_sandbox_code") {
67
+ throw new Error(`Unknown tool: ${toolCall.function.name}`);
68
+ }
69
+ const args = JSON.parse(toolCall.function.arguments);
70
+ const job = await environment.submitJob(args.code);
71
+ return job.result;
72
+ }
73
+
74
+ export { createCodegenTool, executeCodegenToolCall, toOpenAITools, toolCallsToJobCode };
75
+ //# sourceMappingURL=openai.mjs.map
76
+ //# sourceMappingURL=openai.mjs.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.mjs","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"]}