agency-lang 0.0.61 → 0.0.63
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@ Agent Definition Language
|
|
|
6
6
|
Add agency to a project:
|
|
7
7
|
|
|
8
8
|
```bash
|
|
9
|
-
pnpm add agency-lang
|
|
9
|
+
pnpm add agency-lang zod
|
|
10
10
|
```
|
|
11
11
|
|
|
12
12
|
You can then start using the agency script on your files:
|
|
@@ -22,12 +22,6 @@ agency run infile.agency
|
|
|
22
22
|
agency infile.agency
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
-
Note that the generated files use a couple of other libraries that you will need to install as well:
|
|
26
|
-
|
|
27
|
-
```bash
|
|
28
|
-
pnpm i nanoid zod smoltalk
|
|
29
|
-
```
|
|
30
|
-
|
|
31
25
|
## troubleshooting
|
|
32
26
|
### Weird undefined error
|
|
33
27
|
|
package/dist/lib/index.d.ts
CHANGED
package/dist/lib/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const template = "import { fileURLToPath } from \"url\";\nimport process from \"process\";\nimport { z } from \"zod\";\nimport * as readline from \"readline\";\nimport fs from \"fs\";\nimport { StatelogClient, SimpleMachine, goToNode } from \"agency-lang\";\nimport { nanoid } from \"nanoid\";\nimport * as smoltalk from \"agency-lang\";\n\n/* Code to log to statelog */\nconst statelogHost = \"{{{logHost:string}}}\";\nconst __traceId = nanoid();\nconst statelogConfig = {\n host: statelogHost,\n traceId: __traceId,\n apiKey: process.env.STATELOG_API_KEY || \"\",\n projectId: \"{{{logProjectId:string}}}\",\n debugMode: {{{logDebugMode:boolean}}},\n};\nconst __statelogClient = new StatelogClient(statelogConfig);\n\n/* Code for Smoltalk client */\nconst __model = \"{{{clientDefaultModel:string}}}\";\n\nconst __getClientWithConfig = (config = {}) => {\n const defaultConfig = {\n openAiApiKey: process.env.OPENAI_API_KEY || \"\",\n googleApiKey: process.env.GEMINI_API_KEY || \"\",\n model: __model,\n logLevel: \"{{{clientLogLevel:string}}}\",\n };\n\n return smoltalk.getClient({ ...defaultConfig, ...config });\n};\n\nlet __client = __getClientWithConfig();\n\n/* Code for SimpleMachine graph */\n\n// enable debug logging\nconst graphConfig = {\n debug: {\n log: true,\n logData: false,\n },\n statelog: statelogConfig,\n};\n\nconst graph = new SimpleMachine(graphConfig);\n\n/******** builtins ********/\n\nconst not = (val) => !val;\nconst eq = (a, b) => a === b;\nconst neq = (a, b) => a !== b;\nconst lt = (a, b) => a < b;\nconst lte = (a, b) => a <= b;\nconst gt = (a, b) => a > b;\nconst gte = (a, b) => a >= b;\nconst and = (a, b) => a && b;\nconst or = (a, b) => a || b;\nconst head = (arr) => arr[0];\nconst tail = (arr) => arr.slice(1);\nconst empty = (arr) => arr.length === 0;\n\nasync function _builtinFetch(url, args = {}) {\n const result = await fetch(url, args);\n try {\n const text = await result.text();\n return text;\n } catch (e) {\n throw new Error(`Failed to get text from ${url}: ${e}`);\n }\n}\n\nasync function _builtinFetchJSON(url, args = {}) {\n const result = await fetch(url, args);\n try {\n const json = await result.json();\n return json;\n } catch (e) {\n throw new Error(`Failed to parse JSON from ${url}: ${e}`);\n }\n}\n\nfunction _builtinInput(prompt) {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n return new Promise((resolve) => {\n rl.question(prompt, (answer) => {\n rl.close();\n resolve(answer);\n });\n });\n}\n\nfunction _builtinRead(filename) {\n const data = fs.readFileSync(filename);\n const contents = data.toString(\"utf8\");\n return contents;\n}\n\n/*\n * @param filePath The absolute or relative path to the image file.\n * @returns The Base64 string, or null if an error occurs.\n */\nfunction _builtinReadImage(filePath) {\n const data = fs.readFileSync(filePath); // Synchronous file reading\n const base64String = data.toString(\"base64\");\n return base64String;\n}\n\nfunction _builtinSleep(seconds) {\n return new Promise((resolve) => {\n setTimeout(resolve, seconds * 1000);\n });\n}\n\nfunction printJSON(obj) {\n console.log(JSON.stringify(obj, null, 2));\n}\n\nexport const __readSkillTool = {\n name: \"readSkill\",\n description: `Skills provide specialized knowledge and instructions for particular scenarios.\nUse this tool when you need enhanced guidance for a specific type of task.\n\nArgs:\n filepath: The name of the skill to read.\n\nReturns:\n The skill content with specialized instructions, or an error message\n if the skill is not found.\n`,\n schema: z.object({\"filepath\": z.string(), })\n};\n\nexport function readSkill({filepath}) {\n return _builtinRead(filepath);\n}\n\n/******** for internal agency use only ********/\n\nfunction __createReturnObject(result) {\n return structuredClone({\n messages: result.messages.toJSON(),\n data: result.data,\n tokens: __stateStack.globals.__tokenStats\n });\n}\n\n\n\n/******** interrupts ********/\n\nexport function interrupt(data) {\n return {\n type: \"interrupt\",\n data,\n };\n}\n\nexport function isInterrupt(obj) {\n return obj && obj.type === \"interrupt\";\n}\n\nexport async function respondToInterrupt(\n _interrupt,\n _interruptResponse,\n metadata = {},\n) {\n const interrupt = structuredClone(_interrupt);\n const interruptResponse = structuredClone(_interruptResponse);\n\n __stateStack = StateStack.fromJSON(interrupt.__state || {});\n __stateStack.deserializeMode();\n\n const messages = (__stateStack.interruptData.messages || []).map(\n (json) => {\n // create message objects from JSON\n return smoltalk.messageFromJSON(json);\n },\n );\n __stateStack.interruptData.messages = messages;\n __stateStack.interruptData.interruptResponse = interruptResponse;\n\n if (interruptResponse.type === \"approve\" && interruptResponse.newArguments) {\n __stateStack.interruptData.toolCall = {\n ...__stateStack.interruptData.toolCall,\n arguments: {\n ...__stateStack.interruptData.toolCall.arguments,\n ...interruptResponse.newArguments,\n },\n };\n // Error:\n // TypeError: Cannot set property arguments of #<ToolCall> which has only a getter\n // toolCall.arguments = { ...toolCall.arguments, ...interruptResponse.newArguments };\n //\n // const lastMessage = __stateStack.interruptData.messages[__stateStack.interruptData.messages.length - 1];\n // if (lastMessage && lastMessage.role === \"assistant\") {\n // const toolCall = lastMessage.toolCalls?.[lastMessage.toolCalls.length - 1];\n // if (toolCall) {\n // toolCall.arguments = { ...toolCall.arguments, ...interruptResponse.newArguments };\n // }\n // }\n }\n\n // start at the last node we visited\n const nodesTraversed = __stateStack.interruptData.nodesTraversed || [];\n const nodeName = nodesTraversed[nodesTraversed.length - 1];\n const __result = await graph.run(nodeName, {\n messages: messages,\n __metadata: {\n graph: graph,\n statelogClient: __statelogClient,\n __stateStack: __stateStack,\n __callbacks: metadata.callbacks,\n },\n\n // restore args from the state stack\n data: \"<from-stack>\",\n });\n return __createReturnObject(__result);\n}\n\nexport async function approveInterrupt(\n interrupt,\n metadata = {},\n) {\n return await respondToInterrupt(interrupt, { type: \"approve\" }, metadata);\n}\n\nexport async function modifyInterrupt(\n interrupt,\n newArguments,\n metadata = {},\n) {\n return await respondToInterrupt(\n interrupt,\n { type: \"approve\", newArguments },\n metadata,\n );\n}\n\nexport async function rejectInterrupt(\n interrupt,\n metadata = {},\n) {\n return await respondToInterrupt(interrupt, { type: \"reject\" }, metadata);\n}\n\n/****** StateStack and related functions for serializing/deserializing execution state during interrupts ********/\n\n// See docs for notes on how this works.\nclass StateStack {\n stack = [];\n mode = \"serialize\";\n globals = {};\n other = {};\n interruptData = {};\n\n deserializeStackLength = 0;\n\n constructor(\n stack = [],\n mode = \"serialize\",\n ) {\n this.stack = stack;\n this.mode = mode;\n }\n\n getNewState() {\n if (this.mode === \"deserialize\" && this.deserializeStackLength <= 0) {\n console.log(\"Forcing mode to serialize, nothing left to deserialize\");\n this.mode = \"serialize\";\n }\n if (this.mode === \"serialize\") {\n const newState = {\n args: {},\n locals: {},\n step: 0,\n };\n this.stack.push(newState);\n return newState;\n } else if (this.mode === \"deserialize\") {\n this.deserializeStackLength -= 1;\n const item = this.stack.shift();\n this.stack.push(item);\n return item;\n }\n return null;\n }\n\n deserializeMode() {\n this.mode = \"deserialize\";\n this.deserializeStackLength = this.stack.length;\n }\n\n pop() {\n return this.stack.pop();\n }\n\n toJSON() {\n return structuredClone({\n stack: this.stack,\n globals: this.globals,\n other: this.other,\n interruptData: this.interruptData,\n mode: this.mode,\n deserializeStackLength: this.deserializeStackLength,\n });\n }\n\n static fromJSON(json) {\n const stateStack = new StateStack([], \"serialize\");\n stateStack.stack = json.stack || [];\n stateStack.globals = json.globals || {};\n stateStack.other = json.other || {};\n stateStack.interruptData = json.interruptData || {};\n stateStack.mode = json.mode || \"serialize\";\n stateStack.deserializeStackLength = json.deserializeStackLength || 0;\n return stateStack;\n }\n}\n\nlet __stateStack = new StateStack();\n\n__stateStack.globals.__tokenStats = {\n usage: {\n inputTokens: 0,\n outputTokens: 0,\n cachedInputTokens: 0,\n totalTokens: 0,\n },\n cost: {\n inputCost: 0,\n outputCost: 0,\n totalCost: 0,\n currency: \"USD\",\n },\n};\n\nfunction __updateTokenStats(\n usage,\n cost,\n) {\n if (!usage || !cost) return;\n const tokenStats = __stateStack.globals.__tokenStats;\n tokenStats.usage.inputTokens += usage.inputTokens || 0;\n tokenStats.usage.outputTokens += usage.outputTokens || 0;\n tokenStats.usage.cachedInputTokens += usage.cachedInputTokens || 0;\n tokenStats.usage.totalTokens += usage.totalTokens || 0;\n\n tokenStats.cost.inputCost += cost.inputCost || 0;\n tokenStats.cost.outputCost += cost.outputCost || 0;\n tokenStats.cost.totalCost += cost.totalCost || 0;\n}\n\n/**** Streaming callback and lock ****/\nfunction isGenerator(variable) {\n const toString = Object.prototype.toString.call(variable);\n return (\n toString === \"[object Generator]\" || toString === \"[object AsyncGenerator]\"\n );\n}\n\nlet __callbacks = {};\n\nasync function __callHook(name, data) {\n if (__callbacks[name]) {\n await __callbacks[name](data);\n }\n}\n\nlet onStreamLock = false;\n\nfunction __cloneArray(arr) {\n if (arr == undefined) return [];\n return [...arr];\n}\n\nconst handleStreamingResponse = async (__completion) => {\n if (isGenerator(__completion)) {\n if (!__callbacks.onStream) {\n console.log(\n \"No onStream callback provided for streaming response, returning response synchronously\",\n );\n statelogClient.debug(\n \"Got streaming response but no onStream callback provided, returning response synchronously\",\n {\n prompt: __prompt,\n callbacks: Object.keys(__callbacks),\n },\n );\n let syncResult = \"\";\n for await (const chunk of __completion) {\n switch (chunk.type) {\n case \"tool_call\":\n __toolCalls.push(chunk.toolCall);\n break;\n case \"done\":\n syncResult = chunk.result;\n break;\n case \"error\":\n console.error(`Error in LLM response stream: ${chunk.error}`);\n break;\n default:\n break;\n }\n }\n __completion = { success: true, value: syncResult };\n } else {\n // try to acquire lock\n let count = 0;\n // wait 60 seconds to acquire lock\n while (onStreamLock && count < 10 * 60) {\n await _builtinSleep(0.1);\n count++;\n }\n if (onStreamLock) {\n console.log(`Couldn't acquire lock, ${count}`);\n }\n onStreamLock = true;\n\n for await (const chunk of __completion) {\n switch (chunk.type) {\n case \"text\":\n __callbacks.onStream({ type: \"text\", text: chunk.text });\n break;\n case \"tool_call\":\n __toolCalls.push(chunk.toolCall);\n __callbacks.onStream({\n type: \"tool_call\",\n toolCall: chunk.toolCall,\n });\n break;\n case \"done\":\n __callbacks.onStream({ type: \"done\", result: chunk.result });\n __completion = { success: true, value: chunk.result };\n break;\n case \"error\":\n __callbacks.onStream({ type: \"error\", error: chunk.error });\n break;\n }\n }\n\n onStreamLock = false;\n }\n }\n};\n\n\n/**** Message thread handling ****/\n\nclass MessageThread {\n messages = [];\n children = [];\n\n constructor(messages = []) {\n this.messages = messages;\n this.children = [];\n }\n\n addMessage(message) {\n this.messages.push(message);\n }\n\n cloneMessages() {\n return this.messages.map(m => m.toJSON()).map(m => smoltalk.messageFromJSON(m));\n }\n\n getMessages() {\n return this.messages;\n }\n\n setMessages(messages) {\n this.messages = messages;\n }\n\n newChild() {\n const child = new MessageThread();\n this.children.push(child);\n return child;\n }\n\n newSubthreadChild() {\n const child = new MessageThread(this.cloneMessages());\n this.children.push(child);\n return child;\n }\n\n toJSON() {\n return {\n messages: this.messages.map(m => m.toJSON()),\n children: this.children.map((child) => child.toJSON()),\n };\n }\n}";
|
|
1
|
+
export declare const template = "import { fileURLToPath } from \"url\";\nimport process from \"process\";\nimport { z } from \"zod\";\nimport * as readline from \"readline\";\nimport fs from \"fs\";\nimport { StatelogClient, SimpleMachine, goToNode, nanoid } from \"agency-lang\";\nimport * as smoltalk from \"agency-lang\";\n\n/* Code to log to statelog */\nconst statelogHost = \"{{{logHost:string}}}\";\nconst __traceId = nanoid();\nconst statelogConfig = {\n host: statelogHost,\n traceId: __traceId,\n apiKey: process.env.STATELOG_API_KEY || \"\",\n projectId: \"{{{logProjectId:string}}}\",\n debugMode: {{{logDebugMode:boolean}}},\n};\nconst __statelogClient = new StatelogClient(statelogConfig);\n\n/* Code for Smoltalk client */\nconst __model = \"{{{clientDefaultModel:string}}}\";\n\nconst __getClientWithConfig = (config = {}) => {\n const defaultConfig = {\n openAiApiKey: process.env.OPENAI_API_KEY || \"\",\n googleApiKey: process.env.GEMINI_API_KEY || \"\",\n model: __model,\n logLevel: \"{{{clientLogLevel:string}}}\",\n };\n\n return smoltalk.getClient({ ...defaultConfig, ...config });\n};\n\nlet __client = __getClientWithConfig();\n\n/* Code for SimpleMachine graph */\n\n// enable debug logging\nconst graphConfig = {\n debug: {\n log: true,\n logData: false,\n },\n statelog: statelogConfig,\n};\n\nconst graph = new SimpleMachine(graphConfig);\n\n/******** builtins ********/\n\nconst not = (val) => !val;\nconst eq = (a, b) => a === b;\nconst neq = (a, b) => a !== b;\nconst lt = (a, b) => a < b;\nconst lte = (a, b) => a <= b;\nconst gt = (a, b) => a > b;\nconst gte = (a, b) => a >= b;\nconst and = (a, b) => a && b;\nconst or = (a, b) => a || b;\nconst head = (arr) => arr[0];\nconst tail = (arr) => arr.slice(1);\nconst empty = (arr) => arr.length === 0;\n\nasync function _builtinFetch(url, args = {}) {\n const result = await fetch(url, args);\n try {\n const text = await result.text();\n return text;\n } catch (e) {\n throw new Error(`Failed to get text from ${url}: ${e}`);\n }\n}\n\nasync function _builtinFetchJSON(url, args = {}) {\n const result = await fetch(url, args);\n try {\n const json = await result.json();\n return json;\n } catch (e) {\n throw new Error(`Failed to parse JSON from ${url}: ${e}`);\n }\n}\n\nfunction _builtinInput(prompt) {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n return new Promise((resolve) => {\n rl.question(prompt, (answer) => {\n rl.close();\n resolve(answer);\n });\n });\n}\n\nfunction _builtinRead(filename) {\n const data = fs.readFileSync(filename);\n const contents = data.toString(\"utf8\");\n return contents;\n}\n\n/*\n * @param filePath The absolute or relative path to the image file.\n * @returns The Base64 string, or null if an error occurs.\n */\nfunction _builtinReadImage(filePath) {\n const data = fs.readFileSync(filePath); // Synchronous file reading\n const base64String = data.toString(\"base64\");\n return base64String;\n}\n\nfunction _builtinSleep(seconds) {\n return new Promise((resolve) => {\n setTimeout(resolve, seconds * 1000);\n });\n}\n\nfunction printJSON(obj) {\n console.log(JSON.stringify(obj, null, 2));\n}\n\nexport const __readSkillTool = {\n name: \"readSkill\",\n description: `Skills provide specialized knowledge and instructions for particular scenarios.\nUse this tool when you need enhanced guidance for a specific type of task.\n\nArgs:\n filepath: The name of the skill to read.\n\nReturns:\n The skill content with specialized instructions, or an error message\n if the skill is not found.\n`,\n schema: z.object({\"filepath\": z.string(), })\n};\n\nexport function readSkill({filepath}) {\n return _builtinRead(filepath);\n}\n\n/******** for internal agency use only ********/\n\nfunction __createReturnObject(result) {\n return structuredClone({\n messages: result.messages.toJSON(),\n data: result.data,\n tokens: __stateStack.globals.__tokenStats\n });\n}\n\n\n\n/******** interrupts ********/\n\nexport function interrupt(data) {\n return {\n type: \"interrupt\",\n data,\n };\n}\n\nexport function isInterrupt(obj) {\n return obj && obj.type === \"interrupt\";\n}\n\nexport async function respondToInterrupt(\n _interrupt,\n _interruptResponse,\n metadata = {},\n) {\n const interrupt = structuredClone(_interrupt);\n const interruptResponse = structuredClone(_interruptResponse);\n\n __stateStack = StateStack.fromJSON(interrupt.__state || {});\n __stateStack.deserializeMode();\n\n const messages = (__stateStack.interruptData.messages || []).map(\n (json) => {\n // create message objects from JSON\n return smoltalk.messageFromJSON(json);\n },\n );\n __stateStack.interruptData.messages = messages;\n __stateStack.interruptData.interruptResponse = interruptResponse;\n\n if (interruptResponse.type === \"approve\" && interruptResponse.newArguments) {\n __stateStack.interruptData.toolCall = {\n ...__stateStack.interruptData.toolCall,\n arguments: {\n ...__stateStack.interruptData.toolCall.arguments,\n ...interruptResponse.newArguments,\n },\n };\n // Error:\n // TypeError: Cannot set property arguments of #<ToolCall> which has only a getter\n // toolCall.arguments = { ...toolCall.arguments, ...interruptResponse.newArguments };\n //\n // const lastMessage = __stateStack.interruptData.messages[__stateStack.interruptData.messages.length - 1];\n // if (lastMessage && lastMessage.role === \"assistant\") {\n // const toolCall = lastMessage.toolCalls?.[lastMessage.toolCalls.length - 1];\n // if (toolCall) {\n // toolCall.arguments = { ...toolCall.arguments, ...interruptResponse.newArguments };\n // }\n // }\n }\n\n // start at the last node we visited\n const nodesTraversed = __stateStack.interruptData.nodesTraversed || [];\n const nodeName = nodesTraversed[nodesTraversed.length - 1];\n const __result = await graph.run(nodeName, {\n messages: messages,\n __metadata: {\n graph: graph,\n statelogClient: __statelogClient,\n __stateStack: __stateStack,\n __callbacks: metadata.callbacks,\n },\n\n // restore args from the state stack\n data: \"<from-stack>\",\n });\n return __createReturnObject(__result);\n}\n\nexport async function approveInterrupt(\n interrupt,\n metadata = {},\n) {\n return await respondToInterrupt(interrupt, { type: \"approve\" }, metadata);\n}\n\nexport async function modifyInterrupt(\n interrupt,\n newArguments,\n metadata = {},\n) {\n return await respondToInterrupt(\n interrupt,\n { type: \"approve\", newArguments },\n metadata,\n );\n}\n\nexport async function rejectInterrupt(\n interrupt,\n metadata = {},\n) {\n return await respondToInterrupt(interrupt, { type: \"reject\" }, metadata);\n}\n\n/****** StateStack and related functions for serializing/deserializing execution state during interrupts ********/\n\n// See docs for notes on how this works.\nclass StateStack {\n stack = [];\n mode = \"serialize\";\n globals = {};\n other = {};\n interruptData = {};\n\n deserializeStackLength = 0;\n\n constructor(\n stack = [],\n mode = \"serialize\",\n ) {\n this.stack = stack;\n this.mode = mode;\n }\n\n getNewState() {\n if (this.mode === \"deserialize\" && this.deserializeStackLength <= 0) {\n console.log(\"Forcing mode to serialize, nothing left to deserialize\");\n this.mode = \"serialize\";\n }\n if (this.mode === \"serialize\") {\n const newState = {\n args: {},\n locals: {},\n step: 0,\n };\n this.stack.push(newState);\n return newState;\n } else if (this.mode === \"deserialize\") {\n this.deserializeStackLength -= 1;\n const item = this.stack.shift();\n this.stack.push(item);\n return item;\n }\n return null;\n }\n\n deserializeMode() {\n this.mode = \"deserialize\";\n this.deserializeStackLength = this.stack.length;\n }\n\n pop() {\n return this.stack.pop();\n }\n\n toJSON() {\n return structuredClone({\n stack: this.stack,\n globals: this.globals,\n other: this.other,\n interruptData: this.interruptData,\n mode: this.mode,\n deserializeStackLength: this.deserializeStackLength,\n });\n }\n\n static fromJSON(json) {\n const stateStack = new StateStack([], \"serialize\");\n stateStack.stack = json.stack || [];\n stateStack.globals = json.globals || {};\n stateStack.other = json.other || {};\n stateStack.interruptData = json.interruptData || {};\n stateStack.mode = json.mode || \"serialize\";\n stateStack.deserializeStackLength = json.deserializeStackLength || 0;\n return stateStack;\n }\n}\n\nlet __stateStack = new StateStack();\n\n__stateStack.globals.__tokenStats = {\n usage: {\n inputTokens: 0,\n outputTokens: 0,\n cachedInputTokens: 0,\n totalTokens: 0,\n },\n cost: {\n inputCost: 0,\n outputCost: 0,\n totalCost: 0,\n currency: \"USD\",\n },\n};\n\nfunction __updateTokenStats(\n usage,\n cost,\n) {\n if (!usage || !cost) return;\n const tokenStats = __stateStack.globals.__tokenStats;\n tokenStats.usage.inputTokens += usage.inputTokens || 0;\n tokenStats.usage.outputTokens += usage.outputTokens || 0;\n tokenStats.usage.cachedInputTokens += usage.cachedInputTokens || 0;\n tokenStats.usage.totalTokens += usage.totalTokens || 0;\n\n tokenStats.cost.inputCost += cost.inputCost || 0;\n tokenStats.cost.outputCost += cost.outputCost || 0;\n tokenStats.cost.totalCost += cost.totalCost || 0;\n}\n\n/**** Streaming callback and lock ****/\nfunction isGenerator(variable) {\n const toString = Object.prototype.toString.call(variable);\n return (\n toString === \"[object Generator]\" || toString === \"[object AsyncGenerator]\"\n );\n}\n\nlet __callbacks = {};\n\nasync function __callHook(name, data) {\n if (__callbacks[name]) {\n await __callbacks[name](data);\n }\n}\n\nlet onStreamLock = false;\n\nfunction __cloneArray(arr) {\n if (arr == undefined) return [];\n return [...arr];\n}\n\nconst handleStreamingResponse = async (__completion) => {\n if (isGenerator(__completion)) {\n if (!__callbacks.onStream) {\n console.log(\n \"No onStream callback provided for streaming response, returning response synchronously\",\n );\n statelogClient.debug(\n \"Got streaming response but no onStream callback provided, returning response synchronously\",\n {\n prompt: __prompt,\n callbacks: Object.keys(__callbacks),\n },\n );\n let syncResult = \"\";\n for await (const chunk of __completion) {\n switch (chunk.type) {\n case \"tool_call\":\n __toolCalls.push(chunk.toolCall);\n break;\n case \"done\":\n syncResult = chunk.result;\n break;\n case \"error\":\n console.error(`Error in LLM response stream: ${chunk.error}`);\n break;\n default:\n break;\n }\n }\n __completion = { success: true, value: syncResult };\n } else {\n // try to acquire lock\n let count = 0;\n // wait 60 seconds to acquire lock\n while (onStreamLock && count < 10 * 60) {\n await _builtinSleep(0.1);\n count++;\n }\n if (onStreamLock) {\n console.log(`Couldn't acquire lock, ${count}`);\n }\n onStreamLock = true;\n\n for await (const chunk of __completion) {\n switch (chunk.type) {\n case \"text\":\n __callbacks.onStream({ type: \"text\", text: chunk.text });\n break;\n case \"tool_call\":\n __toolCalls.push(chunk.toolCall);\n __callbacks.onStream({\n type: \"tool_call\",\n toolCall: chunk.toolCall,\n });\n break;\n case \"done\":\n __callbacks.onStream({ type: \"done\", result: chunk.result });\n __completion = { success: true, value: chunk.result };\n break;\n case \"error\":\n __callbacks.onStream({ type: \"error\", error: chunk.error });\n break;\n }\n }\n\n onStreamLock = false;\n }\n }\n};\n\n\n/**** Message thread handling ****/\n\nclass MessageThread {\n messages = [];\n children = [];\n\n constructor(messages = []) {\n this.messages = messages;\n this.children = [];\n }\n\n addMessage(message) {\n this.messages.push(message);\n }\n\n cloneMessages() {\n return this.messages.map(m => m.toJSON()).map(m => smoltalk.messageFromJSON(m));\n }\n\n getMessages() {\n return this.messages;\n }\n\n setMessages(messages) {\n this.messages = messages;\n }\n\n newChild() {\n const child = new MessageThread();\n this.children.push(child);\n return child;\n }\n\n newSubthreadChild() {\n const child = new MessageThread(this.cloneMessages());\n this.children.push(child);\n return child;\n }\n\n toJSON() {\n return {\n messages: this.messages.map(m => m.toJSON()),\n children: this.children.map((child) => child.toJSON()),\n };\n }\n}";
|
|
2
2
|
export type TemplateType = {
|
|
3
3
|
logHost: string;
|
|
4
4
|
logProjectId: string;
|
|
@@ -7,8 +7,7 @@ import process from "process";
|
|
|
7
7
|
import { z } from "zod";
|
|
8
8
|
import * as readline from "readline";
|
|
9
9
|
import fs from "fs";
|
|
10
|
-
import { StatelogClient, SimpleMachine, goToNode } from "agency-lang";
|
|
11
|
-
import { nanoid } from "nanoid";
|
|
10
|
+
import { StatelogClient, SimpleMachine, goToNode, nanoid } from "agency-lang";
|
|
12
11
|
import * as smoltalk from "agency-lang";
|
|
13
12
|
|
|
14
13
|
/* Code to log to statelog */
|