@perstack/runtime 0.0.8 → 0.0.10

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/dist/index.js CHANGED
@@ -1,7 +1,1582 @@
1
- import {existsSync}from'fs';import {readFile,writeFile,mkdir,readdir}from'fs/promises';import pe from'path';import {createId}from'@paralleldrive/cuid2';import ko from'smol-toml';import {setup,assign,createActor}from'xstate';import {z as z$1,ZodError}from'zod';import {anthropic}from'@ai-sdk/anthropic';import {google}from'@ai-sdk/google';import {openai}from'@ai-sdk/openai';import {Client}from'@modelcontextprotocol/sdk/client/index.js';import {SSEClientTransport}from'@modelcontextprotocol/sdk/client/sse.js';import {StdioClientTransport}from'@modelcontextprotocol/sdk/client/stdio.js';import {McpError}from'@modelcontextprotocol/sdk/types.js';import {generateText,jsonSchema}from'ai';import {dedent}from'ts-dedent';var ft="claude-4-sonnet-20250514",ge=["claude-4-opus-20250514","claude-4-sonnet-20250514","claude-3-7-sonnet-20250219","claude-3-5-sonnet-latest","claude-3-5-sonnet-20241022","claude-3-5-sonnet-20240620","claude-3-5-haiku-latest","claude-3-5-haiku-20241022"],ue=["gemini-2.5-pro-preview-05-06","gemini-2.5-pro-exp-03-25","gemini-2.5-flash-preview-04-17","gemini-2.0-pro-exp-02-05","gemini-2.0-flash-thinking-exp-01-21","gemini-2.0-flash","gemini-2.0-flash-001","gemini-2.0-flash-live-001","gemini-2.0-flash-lite","gemini-2.0-flash-exp","gemini-1.5-pro","gemini-1.5-pro-latest","gemini-1.5-pro-001","gemini-1.5-pro-002","gemini-1.5-flash","gemini-1.5-flash-latest","gemini-1.5-flash-001","gemini-1.5-flash-002","gemini-1.5-flash-8b","gemini-1.5-flash-8b-latest","gemini-1.5-flash-8b-001"],de=["o4-mini","o4-mini-2025-04-16","o3","o3-2025-04-16","o3-mini","o3-mini-2025-01-31","o1","o1-2024-12-17","o1-mini","o1-mini-2024-09-12","gpt-4.5-preview","gpt-4.5-preview-2025-02-27","gpt-4.1","gpt-4.1-2025-04-14","gpt-4.1-mini","gpt-4.1-mini-2025-04-14","gpt-4.1-nano","gpt-4.1-nano-2025-04-14","gpt-4o","gpt-4o-2024-05-13","gpt-4o-2024-08-06","gpt-4o-2024-11-20","gpt-4o-audio-preview","gpt-4o-audio-preview-2024-10-01","gpt-4o-audio-preview-2024-12-17","gpt-4o-search-preview","gpt-4o-search-preview-2025-03-11","gpt-4o-mini-search-preview","gpt-4o-mini-search-preview-2025-03-11","gpt-4o-mini","gpt-4o-mini-2024-07-18"],ht=Object.fromEntries([...ge,...ue,...de].map(e=>[e,{default:e===ft,model:e}]));function te(){let e=Object.values(ht).find(t=>t.default);if(!e)throw new Error("No default model found");return e.model}function z(e){let t=e??te();if(ge.includes(t))return anthropic(t);if(ue.includes(t))return google(t);if(de.includes(t))return openai(t);throw new Error(`Unsupported model: ${t}`)}var I=z$1.object({id:z$1.string()}),A=I.extend({type:z$1.literal("textPart"),text:z$1.string()}),yt=I.extend({type:z$1.literal("imageUrlPart"),url:z$1.string().url(),mimeType:z$1.string()}),fe=I.extend({type:z$1.literal("imageInlinePart"),encodedData:z$1.string(),mimeType:z$1.string()}),xt=I.extend({type:z$1.literal("imageBinaryPart"),data:z$1.string(),mimeType:z$1.string()}),kt=I.extend({type:z$1.literal("fileUrlPart"),url:z$1.string().url(),mimeType:z$1.string()}),Tt=I.extend({type:z$1.literal("fileInlinePart"),encodedData:z$1.string(),mimeType:z$1.string()}),Rt=I.extend({type:z$1.literal("fileBinaryPart"),data:z$1.string(),mimeType:z$1.string()}),St=I.extend({type:z$1.literal("toolCallPart"),toolCallId:z$1.string(),toolName:z$1.string(),args:z$1.unknown()}),Pt=I.extend({type:z$1.literal("toolResultPart"),toolCallId:z$1.string(),toolName:z$1.string(),contents:z$1.array(z$1.union([A,fe])),isError:z$1.boolean().optional()}),L=z$1.object({id:z$1.string()}),Ct=L.extend({type:z$1.literal("instructionMessage"),contents:z$1.array(A),cache:z$1.boolean().optional()}),vt=L.extend({type:z$1.literal("userMessage"),contents:z$1.array(z$1.union([A,yt,fe,xt,kt,Tt,Rt])),cache:z$1.boolean().optional()}),wt=L.extend({type:z$1.literal("expertMessage"),contents:z$1.array(z$1.union([A,St])),cache:z$1.boolean().optional()}),It=L.extend({type:z$1.literal("toolMessage"),contents:z$1.array(Pt),cache:z$1.boolean().optional()}),he=z$1.union([Ct,vt,wt,It]);var Mt=/^(@[a-z0-9][a-z0-9_-]*\/)?[a-z0-9][a-z0-9_-]*$/,bt=/^(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-[\w.-]+)?(?:\+[\w.-]+)?$/,Et=/^[a-z0-9][a-z0-9_-]*$/,D=/^((?:@[a-z0-9][a-z0-9_\.-]*\/)?[a-z0-9][a-z0-9_\.-]*)(?:@((?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-[\w.-]+)?(?:\+[\w.-]+)?)|@([a-z0-9][a-z0-9_\.-]*))?$/,Uo=/^[a-z0-9][a-z0-9._-]*$/,$t=214;function jo(e){let t=e.match(D);if(!t)throw new Error(`Invalid expert key format: ${e}`);let[o,r,a,i]=t;return {key:o,name:r,version:a,tag:i}}var G=z$1.object({type:z$1.literal("mcpStdioSkill"),name:z$1.string(),description:z$1.string().optional(),rule:z$1.string().optional(),pick:z$1.array(z$1.string()).optional().default([]),omit:z$1.array(z$1.string()).optional().default([]),command:z$1.string(),packageName:z$1.string().optional(),args:z$1.array(z$1.string()).optional().default([]),requiredEnv:z$1.array(z$1.string()).optional().default([])}),K=z$1.object({type:z$1.literal("mcpSseSkill"),name:z$1.string(),description:z$1.string().optional(),rule:z$1.string().optional(),pick:z$1.array(z$1.string()).optional().default([]),omit:z$1.array(z$1.string()).optional().default([]),endpoint:z$1.string()}),ye=z$1.object({name:z$1.string(),description:z$1.string().optional(),inputJsonSchema:z$1.string()}),q=z$1.object({type:z$1.literal("interactiveSkill"),name:z$1.string(),description:z$1.string().optional(),rule:z$1.string().optional(),tools:z$1.record(z$1.string(),ye.omit({name:true})).transform(e=>Object.fromEntries(Object.entries(e).map(([t,o])=>[t,ye.parse({...o,name:t})])))}),J=z$1.object({key:z$1.string().regex(D).min(1),name:z$1.string().regex(Mt).min(1).max($t),version:z$1.string().regex(bt),description:z$1.string().min(1).max(1024*2).optional(),instruction:z$1.string().min(1).max(1024*20),skills:z$1.record(z$1.string(),z$1.discriminatedUnion("type",[G.omit({name:true}),K.omit({name:true}),q.omit({name:true})])).optional().default({"@perstack/base":{type:"mcpStdioSkill",description:"Base skill",command:"npx",args:["-y","@perstack/base"]}}).transform(e=>Object.fromEntries(Object.entries(e).map(([t,o])=>[t,z$1.discriminatedUnion("type",[G,K,q]).parse({...o,name:t})]))),delegates:z$1.array(z$1.string().regex(D).min(1)).optional().default([]),tags:z$1.array(z$1.string().regex(Et).min(1)).optional().default([])}),Nt=z$1.object({promptTokens:z$1.number(),completionTokens:z$1.number(),totalTokens:z$1.number(),cacheCreationInputTokens:z$1.number(),cacheReadInputTokens:z$1.number()}),Ft=z$1.enum(["init","proceeding","completed","stoppedByInteractiveTool","stoppedByDelegate","stoppedByExceededMaxSteps","stoppedByError"]),oe=z$1.object({id:z$1.string(),runId:z$1.string(),status:Ft,stepNumber:z$1.number(),messages:z$1.array(he),expert:z$1.object({key:z$1.string(),name:z$1.string(),version:z$1.string()}),delegateTo:z$1.object({expert:z$1.object({key:z$1.string(),name:z$1.string(),version:z$1.string()}),toolCallId:z$1.string(),toolName:z$1.string(),query:z$1.string()}).optional(),delegatedBy:z$1.object({expert:z$1.object({key:z$1.string(),name:z$1.string(),version:z$1.string()}),toolCallId:z$1.string(),toolName:z$1.string(),checkpointId:z$1.string()}).optional(),usage:Nt}),ke=z$1.object({setting:z$1.object({runId:z$1.string().optional().transform(e=>e??createId()),expertKey:z$1.string().regex(D).min(1),input:z$1.object({text:z$1.string().optional(),interactiveToolCallResult:z$1.object({toolCallId:z$1.string(),toolName:z$1.string(),text:z$1.string()}).optional()}),experts:z$1.record(z$1.string().regex(D).min(1),J.omit({key:true})).optional().default({}).transform(e=>Object.fromEntries(Object.entries(e).map(([t,o])=>[t,J.parse({...o,key:t})]))),model:z$1.string().optional().default(te()),temperature:z$1.number().min(0).max(1).optional().default(.3),maxSteps:z$1.number().min(1).optional(),maxRetries:z$1.number().min(0).optional().default(10),workspace:z$1.string().optional(),startedAt:z$1.number().optional().default(Date.now()),updatedAt:z$1.number().optional().default(Date.now())}),checkpoint:oe.optional()});function k(e){return (t,o,r)=>({type:e,id:createId(),expertKey:o.expert.key,timestamp:Date.now(),runId:t.runId,stepNumber:o.stepNumber,...r})}var ne=k("startRun"),Te=k("startGeneration"),re=k("retry"),Re=k("callTool"),Se=k("callInteractiveTool"),Pe=k("callDelegate"),Ce=k("resolveToolResult"),ve=k("resolveThought"),we=k("resolvePdfFile"),Ie=k("resolveImageFile"),Me=k("attemptCompletion"),$=k("finishToolCall"),be=k("completeRun"),Ee=k("stopRunByInteractiveTool"),$e=k("stopRunByDelegate"),Ne=k("stopRunByExceededMaxSteps"),Fe=k("continueToNextStep");async function De(e,t){let o=O(e),a=(await readdir(o,{withFileTypes:true}).then(s=>s.filter(u=>u.isFile()&&u.name.startsWith("checkpoint-")))).find(s=>s.name.endsWith(`-${t}.json`));if(!a)throw new Error(`checkpoint not found: ${e} ${t}`);let i=`${o}/${a.name}`,c=await readFile(i,"utf8");return oe.parse(JSON.parse(c))}async function Oe(e,t){let{id:o,runId:r,stepNumber:a}=e,i=O(r),c=`${i}/checkpoint-${t}-${a}-${o}.json`;await mkdir(i,{recursive:true}),await writeFile(c,JSON.stringify(e,null,2));}async function Be(e){let{timestamp:t,runId:o,stepNumber:r,type:a}=e,i=O(o),c=`${i}/event-${t}-${r}-${a}.json`;await mkdir(i,{recursive:true}),await writeFile(c,JSON.stringify(e,null,2));}var _e={version:"0.0.8"};var m=console.info,ze=console.debug,g=e=>{let t=new Date().toISOString(),o=e.stepNumber,r=e.expertKey;return `${t} ${o} ${r}`};async function se(e){switch(await Be(e),e.type){case "startRun":{m(`${g(e)} \u{1F99C} Perstack@${_e.version} started`);let{inputMessages:t}=e;for(let o of t)o.type==="userMessage"?Ot(o):o.type==="toolMessage"&&Bt(o);break}case "startGeneration":{m(`${g(e)} \u{1F99C} Generating tool call`);break}case "retry":{B(e),m(`${g(e)} \u{1F99C} Retrying tool call generation`);break}case "callTool":{if(B(e),m(`${g(e)} \u{1F99C} Calling tool`),e.toolCall.skillName==="@perstack/base")switch(e.toolCall.toolName){case "think":{let t=e.toolCall.args.thought;m(`${g(e)} \u{1F4AD} Thought Updated:`),ze(t);break}case "readPdfFile":{let t=e.toolCall.args.path;m(`${g(e)} \u{1F4C4} Reading PDF: ${t}`);break}case "readImageFile":{let t=e.toolCall.args.path;m(`${g(e)} \u{1F5BC}\uFE0F Reading Image: ${t}`);break}default:{m(`${g(e)} \u{1F527} Tool: ${e.toolCall.skillName}/${e.toolCall.toolName}`),m(`${g(e)} \u{1F527} Args: ${e.toolCall.args}`);break}}else m(`${g(e)} \u{1F527} Tool: ${e.toolCall.skillName}/${e.toolCall.toolName}`),m(`${g(e)} \u{1F527} Args: ${e.toolCall.args}`);break}case "callInteractiveTool":{B(e),m(`${g(e)} \u{1F99C} Calling interactive tool`),m(`${g(e)} \u{1F527} Tool: ${e.toolCall.skillName}/${e.toolCall.toolName}`),m(`${g(e)} \u{1F527} Args: ${e.toolCall.args}`);break}case "callDelegate":{B(e),m(`${g(e)} \u{1F99C} Calling delegate`),m(`${g(e)} \u{1F527} Tool: ${e.toolCall.toolName}`),m(`${g(e)} \u{1F527} Args: ${e.toolCall.args}`);break}case "resolveToolResult":{if(m(`${g(e)} \u{1F527} Resolved Tool Result`),e.toolResult.skillName==="@perstack/base")switch(e.toolResult.toolName){case "todo":{let t=e.toolResult.result.find(r=>r.type==="textPart")?.text,{todos:o}=JSON.parse(t??"{}");m(`${g(e)} \u{1F4C4} Todo:`);for(let r of o)ze(`${r.completed?"[x]":"[ ]"} ${r.id}: ${r.title}`);break}default:{m(`${g(e)} \u{1F527} Tool: ${e.toolResult.skillName}/${e.toolResult.toolName}`),m(`${g(e)} \u{1F527} Result: ${e.toolResult.result}`);break}}else m(`${g(e)} \u{1F527} Tool: ${e.toolResult.skillName}/${e.toolResult.toolName}`),m(`${g(e)} \u{1F527} Result: ${e.toolResult.result}`);break}case "resolveThought":{m(`${g(e)} \u{1F4AD} Resolved Thought:`,e.toolResult);break}case "resolvePdfFile":{m(`${g(e)} \u{1F4C4} Resolved PDF:`,e.toolResult);break}case "resolveImageFile":{m(`${g(e)} \u{1F5BC}\uFE0F Resolved Image:`,e.toolResult);break}case "attemptCompletion":{m(`${g(e)} \u2705 Attempting completion`);break}case "completeRun":{B(e),m(`${g(e)} \u{1F99C} Completing run`),m(`${g(e)} \u{1F99C} Result:`,e.text);break}case "stopRunByInteractiveTool":{m(`${g(e)} \u{1F99C} Stopping run by interactive tool`);break}case "stopRunByDelegate":{m(`${g(e)} \u{1F99C} Stopping run by delegate`);break}case "stopRunByExceededMaxSteps":{m(`${g(e)} \u{1F99C} Stopping run by exceeded max steps`);break}case "continueToNextStep":{m(`${g(e)} \u{1F99C} Continuing to next step`);break}}}function Ot(e){let t=new Date().toISOString(),o=e.contents;for(let r of o)r.type==="textPart"?m(`${t} \u{1F4AC} User: ${r.text}`):r.type==="imageUrlPart"?m(`${t} \u{1F5BC}\uFE0F User: ${r.url}`):r.type==="imageInlinePart"?m(`${t} \u{1F5BC}\uFE0F User: Inline image`):r.type==="imageBinaryPart"?m(`${t} \u{1F5BC}\uFE0F User: Binary image`):r.type==="fileUrlPart"?m(`${t} \u{1F4C4} User: ${r.url}`):r.type==="fileInlinePart"?m(`${t} \u{1F4C4} User: Inline file`):r.type==="fileBinaryPart"&&m(`${t} \u{1F4C4} User: Binary file`);}function Bt(e){let t=new Date().toISOString(),o=e.contents;for(let r of o)if(r.type==="toolResultPart"){let{contents:a}=r;for(let i of a)i.type==="textPart"?m(`${t} \u{1F4AC} Tool Result: ${i.text}`):i.type==="imageInlinePart"&&m(`${t} \u{1F5BC}\uFE0F Tool Result: Inline image`);}}function B(e){let t=[`In: ${e.usage.promptTokens.toLocaleString()}`,`Out: ${e.usage.completionTokens.toLocaleString()}`,`Total: ${e.usage.totalTokens.toLocaleString()}`,`Cache-read: ${e.usage.cacheReadInputTokens.toLocaleString()}`,`Cache-write: ${e.usage.cacheCreationInputTokens.toLocaleString()}`].join(", ");m(`${g(e)} \u{1F4CA} Tokens usage: ${t}`);let o=[`In: ${e.usage.promptTokens.toLocaleString()}`,`Out: ${e.usage.completionTokens.toLocaleString()}`,`Total: ${e.usage.totalTokens.toLocaleString()}`,`Cache-read: ${e.usage.cacheReadInputTokens.toLocaleString()}`,`Cache-write: ${e.usage.cacheCreationInputTokens.toLocaleString()}`].join(", ");m(`${g(e)} \u{1F4CA} Total usage: ${o}`);}var V=class{listeners=[];subscribe(t){this.listeners.push(t);}async emit(t){for(let o of this.listeners)await o({...t,id:createId(),timestamp:Date.now()});}};var zt=z$1.object({name:z$1.string(),version:z$1.string(),minRuntimeVersion:z$1.string(),description:z$1.string(),instruction:z$1.string(),skills:z$1.record(z$1.string(),z$1.discriminatedUnion("type",[G.omit({name:true}),K.omit({name:true}),q.omit({name:true})])),delegates:z$1.array(z$1.string()),tags:z$1.array(z$1.string()),status:z$1.string(),owner:z$1.object({name:z$1.string()}),createdAt:z$1.string().datetime(),updatedAt:z$1.string().datetime()}),Ae=z$1.object({data:z$1.object({expert:zt})});var Y=class{baseUrl;registry;apiKey;constructor(t){this.baseUrl=t?.baseUrl??process.env.PERSTACK_API_BASE_URL??"https://api.perstack.ai",this.apiKey=t?.apiKey??process.env.PERSTACK_API_KEY,this.registry=new ae(this);}},ae=class{client;endpoint;constructor(t){this.client=t,this.endpoint="/api/registry/v1/experts";}async get(t){let o=encodeURIComponent(t),r=new URL(`${this.endpoint}/${o}`,this.client.baseUrl),a={"Content-Type":"application/json",Authorization:`Bearer ${this.client.apiKey}`},i=await fetch(r.toString(),{headers:a});if(!i.ok)throw new Error(`Registry returned non-200 status code: ${i.status}, reason: ${i.statusText}`);let c=await i.json();return Ae.parse(c)}};async function ie(e,t){if(t[e])return t[e];let o=new Y,{data:r}=await o.registry.get(e),a=J.parse({...r.expert,key:e});return t[e]=a,a}var _=class{_toolDefinitions=[];_initialized=false;name;type;skill;interactiveSkill;expert;_mcpClient;_params;constructor(t){switch(this._params=t,this.type=t.type,t.type){case "mcp":this.name=t.skill.name,this.skill=t.skill;break;case "interactive":this.name=t.interactiveSkill.name,this.interactiveSkill=t.interactiveSkill;break;case "delegate":this.name=t.expert.name,this.expert=t.expert;break}}async init(){switch(this._params.type){case "mcp":{await this._initMcpSkill(this._params);break}case "interactive":{await this._initInteractiveSkill(this._params);break}case "delegate":{await this._initDelegate(this._params);break}}}async _initMcpSkill(t){switch(this._mcpClient=new Client({name:`${t.skill.name}-mcp-client`,version:"1.0.0"}),t.skill.type){case "mcpStdioSkill":{if(!t.skill.command)throw new Error(`Skill ${t.skill.name} has no command`);let{command:r,args:a}=this._getCommandArgs(t.skill),i=new StdioClientTransport({command:r,args:a,env:Object.fromEntries(Object.entries(process.env).filter(([c,s])=>s!==void 0&&s!=="").map(([c,s])=>[c,s]))});await this._mcpClient.connect(i);break}case "mcpSseSkill":{if(!t.skill.endpoint)throw new Error(`Skill ${t.skill.name} has no endpoint`);let r=new SSEClientTransport(new URL(t.skill.endpoint));await this._mcpClient.connect(r);break}}let{tools:o}=await this._mcpClient.listTools();this._toolDefinitions=o.map(r=>({skillName:t.skill.name,name:r.name,description:r.description,inputSchema:r.inputSchema,interactive:false})),this._initialized=true;}_getCommandArgs(t){let{name:o,command:r,packageName:a,args:i}=t;if(!a&&(!i||i.length===0))throw new Error(`Skill ${o} has no packageName or args. Please provide one of them.`);if(a&&i&&i.length>0)throw new Error(`Skill ${o} has both packageName and args. Please provide only one of them.`);let c=i?[...i]:[a];return r==="npx"&&!c.includes("-y")&&c.unshift("-y"),{command:r,args:c}}async _initInteractiveSkill(t){this._toolDefinitions=Object.values(t.interactiveSkill.tools).map(o=>({skillName:t.interactiveSkill.name,name:o.name,description:o.description,inputSchema:JSON.parse(o.inputJsonSchema),interactive:true})),this._initialized=true;}async _initDelegate(t){this._toolDefinitions=[{skillName:t.expert.name,name:t.expert.name.split("/").pop()??t.expert.name,description:t.expert.description,inputSchema:{type:"object",properties:{query:{type:"string"}},required:["query"]},interactive:false}],this._initialized=true;}async close(){this._mcpClient&&await this._mcpClient.close();}async getToolDefinitions(){if(!this._initialized)throw new Error(`${this.name} is not initialized`);if(this._params.type==="mcp"){let t=this._params.skill.omit??[],o=this._params.skill.pick??[];return this._toolDefinitions.filter(r=>t.length>0?!t.includes(r.name):true).filter(r=>o.length>0?o.includes(r.name):true)}return this._toolDefinitions}async callTool(t,o){switch(this._params.type){case "mcp":{if(!this._mcpClient)throw new Error(`${this.name} is not initialized`);try{let r=await this._mcpClient.callTool({name:t,arguments:o});return this._convertToolResult(r,t,o)}catch(r){return this._handleToolError(r,t)}}case "interactive":return [];case "delegate":return []}}_handleToolError(t,o){if(t instanceof McpError)return [{type:"textPart",text:`Error calling tool ${o}: ${t.message}`,id:createId()}];if(t instanceof ZodError)return [{type:"textPart",text:`Invalid tool call arguments: ${t}`,id:createId()}];throw t}_convertToolResult(t,o,r){return !t.content||t.content.length===0?[{type:"textPart",text:`Tool ${o} returned nothing with arguments: ${JSON.stringify(r)}`,id:createId()}]:t.content.filter(a=>a.type!=="audio"&&a.type!=="resource_link").map(a=>this._convertPart(a))}_convertPart(t){switch(t.type){case "text":return !t.text||t.text===""?{type:"textPart",text:"Error: No content",id:createId()}:{type:"textPart",text:t.text,id:createId()};case "image":if(!t.data||!t.mimeType)throw new Error("Image part must have both data and mimeType");return {type:"imageInlinePart",encodedData:t.data,mimeType:t.mimeType,id:createId()};case "resource":if(!t.resource)throw new Error("Resource part must have resource content");return this._convertResource(t.resource)}}_convertResource(t){if(!t.mimeType)throw new Error(`Resource ${JSON.stringify(t)} has no mimeType`);if(t.text&&typeof t.text=="string")return {type:"textPart",text:t.text,id:createId()};if(t.blob&&typeof t.blob=="string")return {type:"fileInlinePart",encodedData:t.blob,mimeType:t.mimeType,id:createId()};throw new Error(`Unsupported resource type: ${JSON.stringify(t)}`)}};async function Le(e,t){let o={},{skills:r}=e;r["@perstack/base"]||(r["@perstack/base"]={type:"mcpStdioSkill",name:"@perstack/base",description:"The base skill for Perstack",pick:[],omit:[],command:"npx",args:["-y","@perstack/base"],requiredEnv:[]});let a=await Promise.all(Object.values(r).filter(s=>s.type==="mcpStdioSkill"||s.type==="mcpSseSkill").map(async s=>{let u=new _({type:"mcp",skill:s});return await u.init(),u})),i=await Promise.all(Object.values(r).filter(s=>s.type==="interactiveSkill").map(async s=>{let u=new _({type:"interactive",interactiveSkill:s});return await u.init(),u})),c=await Promise.all(e.delegates.map(async s=>{let u=t[s],h=new _({type:"delegate",expert:u});return await h.init(),h}));for(let s of a)o[s.name]=s;for(let s of i)o[s.name]=s;for(let s of c)o[s.name]=s;return o}async function Ge(e){for(let t of Object.values(e))await t.close();}async function N(e,t){for(let o of Object.values(e)){let r=await o.getToolDefinitions();for(let a of r)if(a.name===t)return o}throw new Error(`Tool ${t} not found`)}async function Ke(e){let t={};for(let o of Object.values(e)){let r=await o.getToolDefinitions();for(let a of r)t[a.name]={description:a.description,parameters:jsonSchema(a.inputSchema)};}return t}async function qe({setting:e,checkpoint:t,step:o,skillManagers:r}){if(!o?.toolCall)throw new Error("No tool call found");let{id:a,toolName:i,args:c}=o.toolCall,s=await N(r,i);if(!s||!s.expert)throw new Error(`Delegation error: skill manager "${i}" not found`);if(!c||!c.query||typeof c.query!="string")throw new Error("Delegation error: query is undefined");return $e(e,t,{checkpoint:{...t,status:"stoppedByDelegate",delegateTo:{expert:{key:s.expert.key,name:s.expert.name,version:s.expert.version},toolCallId:a,toolName:i,query:c.query}},step:{...o,finishedAt:new Date().getTime()}})}async function Je({setting:e,checkpoint:t,step:o}){return Ee(e,t,{checkpoint:{...t,status:"stoppedByInteractiveTool"},step:{...o,finishedAt:new Date().getTime()}})}async function Ve({setting:e,checkpoint:t,step:o,skillManagers:r}){if(!o?.toolCall)throw new Error("No tool call found");let{id:a,skillName:i,toolName:c,args:s}=o.toolCall,u=await N(r,c);if(u.type!=="mcp")throw new Error(`Incorrect SkillType, required MCP, got ${u.type}`);let h=await u.callTool(c,s),d={id:a,skillName:i,toolName:c,result:h};if(i==="@perstack/base"){if(c==="think")return ve(e,t,{toolResult:d});if(c==="attemptCompletion")return Me(e,t,{toolResult:d});if(c==="readPdfFile")return we(e,t,{toolResult:d});if(c==="readImageFile")return Ie(e,t,{toolResult:d})}return Ce(e,t,{toolResult:d})}async function Ye({setting:e,checkpoint:t,step:o}){return e.maxSteps!==void 0&&t.stepNumber>e.maxSteps?Ne(e,t,{checkpoint:{...t,status:"stoppedByExceededMaxSteps"},step:{...o,finishedAt:new Date().getTime()}}):Fe(e,t,{checkpoint:{...t},step:{...o,finishedAt:new Date().getTime()},nextCheckpoint:{...t,id:createId(),stepNumber:t.stepNumber+1}})}function F(e){return {type:"userMessage",contents:e.map(t=>({...t,id:createId()})),id:createId()}}function U(e){return {type:"expertMessage",contents:e.map(t=>({...t,id:createId()})),id:createId()}}function C(e){return {type:"toolMessage",contents:e.map(t=>({...t,contents:t.contents.map(o=>({...o,id:createId()})),id:createId()})),id:createId()}}function W(e){switch(e.type){case "instructionMessage":return {role:"system",content:Wt(e.contents),providerOptions:e.cache?{anthropic:{cacheControl:{type:"ephemeral"}}}:void 0};case "userMessage":return {role:"user",content:Ht(e.contents),providerOptions:e.cache?{anthropic:{cacheControl:{type:"ephemeral"}}}:void 0};case "expertMessage":return {role:"assistant",content:Qt(e.contents),providerOptions:e.cache?{anthropic:{cacheControl:{type:"ephemeral"}}}:void 0};case "toolMessage":return {role:"tool",content:Zt(e.contents),providerOptions:e.cache?{anthropic:{cacheControl:{type:"ephemeral"}}}:void 0}}}function Wt(e){return e.reduce((t,o)=>dedent`
2
- ${t}
3
- ${o.text}
4
- `.trim(),"")}function Ht(e){return e.map(t=>{switch(t.type){case "textPart":return We(t);case "imageUrlPart":return Xt(t);case "imageInlinePart":return eo(t);case "imageBinaryPart":return to(t);case "fileUrlPart":return oo(t);case "fileInlinePart":return no(t);case "fileBinaryPart":return ro(t)}})}function Qt(e){return e.map(t=>{switch(t.type){case "textPart":return We(t);case "toolCallPart":return so(t)}})}function Zt(e){return e.map(t=>{switch(t.type){case "toolResultPart":return ao(t)}})}function We(e){return {type:"text",text:e.text}}function Xt(e){return {type:"image",image:e.url,mimeType:e.mimeType}}function eo(e){return {type:"image",image:e.encodedData,mimeType:e.mimeType}}function to(e){return {type:"image",image:e.data,mimeType:e.mimeType}}function oo(e){return {type:"file",data:e.url,mimeType:e.mimeType}}function no(e){return {type:"file",data:e.encodedData,mimeType:e.mimeType}}function ro(e){return {type:"file",data:e.data,mimeType:e.mimeType}}function so(e){return {type:"tool-call",toolCallId:e.toolCallId,toolName:e.toolName,args:e.args}}function ao(e){return {type:"tool-result",toolCallId:e.toolCallId,toolName:e.toolName,result:e.contents,experimental_content:e.contents.map(t=>{switch(t.type){case "textPart":return {type:"text",text:t.text};case "imageInlinePart":return {type:"image",data:t.encodedData,mimeType:t.mimeType}}}),isError:e.isError}}function H(){return {promptTokens:0,completionTokens:0,totalTokens:0,cacheCreationInputTokens:0,cacheReadInputTokens:0}}function Q(e){let t=0,o=0;if(e.providerMetadata?.anthropic){let r=e.providerMetadata.anthropic;t=r.cacheCreationInputTokens||0,o=r.cacheReadInputTokens||0;}return {promptTokens:e.usage.promptTokens,completionTokens:e.usage.completionTokens,totalTokens:e.usage.totalTokens,cacheCreationInputTokens:t,cacheReadInputTokens:o}}function v(e,t){return {promptTokens:e.promptTokens+t.promptTokens,completionTokens:e.completionTokens+t.completionTokens,totalTokens:e.totalTokens+t.totalTokens,cacheCreationInputTokens:e.cacheCreationInputTokens+t.cacheCreationInputTokens,cacheReadInputTokens:e.cacheReadInputTokens+t.cacheReadInputTokens}}async function He({setting:e,checkpoint:t,step:o}){if(!o?.toolCall||!o?.toolResult)throw new Error("No tool call or tool result found");let{id:r,toolName:a}=o.toolCall,{result:i}=o.toolResult,c=C([{type:"toolResultPart",toolCallId:r,toolName:a,contents:i.filter(f=>f.type==="textPart"||f.type==="imageInlinePart")}]),s=z(e.model),{messages:u}=t,h=await generateText({model:s,messages:[...u,c].map(W),temperature:e.temperature,maxRetries:e.maxRetries}),d=Q(h),{text:P}=h,R=[c,U(P?[{type:"textPart",text:P}]:[])];return be(e,t,{checkpoint:{...t,messages:[...u,...R],usage:v(t.usage,d),status:"completed"},step:{...o,newMessages:[...o.newMessages,...R],finishedAt:new Date().getTime(),usage:v(o.usage,d)},text:P,usage:d})}async function Qe({setting:e,checkpoint:t,skillManagers:o}){let{messages:r}=t,a=z(e.model),i=await generateText({model:a,messages:r.map(W),temperature:e.temperature,maxRetries:e.maxRetries,tools:await Ke(o),toolChoice:"required"}),c=Q(i),{text:s,toolCalls:u,finishReason:h}=i,d=u[0];if(!d)return re(e,t,{newMessages:[U(s?[{type:"textPart",text:s}]:[]),F([{type:"textPart",text:"You must generate a tool call. Try again."}])],usage:c});if(h!=="tool-calls")switch(h){case "length":return re(e,t,{newMessages:[U([{type:"toolCallPart",toolCallId:d.toolCallId,toolName:d.toolName,args:d.args}]),C([{type:"toolResultPart",toolCallId:d.toolCallId,toolName:d.toolName,contents:[{type:"textPart",text:"Error: Generation length exceeded"}]}])],usage:c});default:throw new Error(`Unexpected finish reason: ${h}`)}let P=[{type:"toolCallPart",toolCallId:d.toolCallId,toolName:d.toolName,args:d.args}];s&&P.push({type:"textPart",text:s});let R=await N(o,d.toolName),f={newMessage:U(P),toolCall:{id:d.toolCallId,skillName:R.name,toolName:d.toolName,args:d.args},usage:c};switch(R.type){case "mcp":return Re(e,t,f);case "interactive":return Se(e,t,f);case "delegate":return Pe(e,t,f)}}var po=dedent`
1
+ import { existsSync } from 'fs';
2
+ import { readFile, writeFile, mkdir, readdir } from 'fs/promises';
3
+ import path from 'path';
4
+ import { createId } from '@paralleldrive/cuid2';
5
+ import TOML from 'smol-toml';
6
+ import { setup, assign, createActor } from 'xstate';
7
+ import { z, ZodError } from 'zod';
8
+ import { anthropic } from '@ai-sdk/anthropic';
9
+ import { google } from '@ai-sdk/google';
10
+ import { openai } from '@ai-sdk/openai';
11
+ import { Client } from '@modelcontextprotocol/sdk/client/index.js';
12
+ import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';
13
+ import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
14
+ import { McpError } from '@modelcontextprotocol/sdk/types.js';
15
+ import { generateText, jsonSchema } from 'ai';
16
+ import { dedent } from 'ts-dedent';
17
+
18
+ // src/runtime.ts
19
+ var DefaultModel = "claude-4-sonnet-20250514";
20
+ var AnthropicModels = [
21
+ "claude-4-opus-20250514",
22
+ "claude-4-sonnet-20250514",
23
+ "claude-3-7-sonnet-20250219",
24
+ "claude-3-5-sonnet-latest",
25
+ "claude-3-5-sonnet-20241022",
26
+ "claude-3-5-sonnet-20240620",
27
+ "claude-3-5-haiku-latest",
28
+ "claude-3-5-haiku-20241022"
29
+ // "claude-3-opus-latest", - No pdf support
30
+ // "claude-3-opus-20240229", - No pdf support
31
+ // "claude-3-sonnet-20240229", - No pdf support
32
+ // "claude-3-haiku-20240307", - No pdf support
33
+ ];
34
+ var GoogleModels = [
35
+ "gemini-2.5-pro-preview-05-06",
36
+ "gemini-2.5-pro-exp-03-25",
37
+ "gemini-2.5-flash-preview-04-17",
38
+ "gemini-2.0-pro-exp-02-05",
39
+ "gemini-2.0-flash-thinking-exp-01-21",
40
+ "gemini-2.0-flash",
41
+ "gemini-2.0-flash-001",
42
+ "gemini-2.0-flash-live-001",
43
+ "gemini-2.0-flash-lite",
44
+ "gemini-2.0-flash-exp",
45
+ "gemini-1.5-pro",
46
+ "gemini-1.5-pro-latest",
47
+ "gemini-1.5-pro-001",
48
+ "gemini-1.5-pro-002",
49
+ "gemini-1.5-flash",
50
+ "gemini-1.5-flash-latest",
51
+ "gemini-1.5-flash-001",
52
+ "gemini-1.5-flash-002",
53
+ "gemini-1.5-flash-8b",
54
+ "gemini-1.5-flash-8b-latest",
55
+ "gemini-1.5-flash-8b-001"
56
+ // "gemini-exp-1206", - Unclear model spec
57
+ // "gemma-3-27b-it", - Unclear model spec
58
+ // "learnlm-1.5-pro-experimental", - Unclear model spec
59
+ ];
60
+ var OpenAIModels = [
61
+ "o4-mini",
62
+ "o4-mini-2025-04-16",
63
+ "o3",
64
+ "o3-2025-04-16",
65
+ "o3-mini",
66
+ "o3-mini-2025-01-31",
67
+ "o1",
68
+ "o1-2024-12-17",
69
+ "o1-mini",
70
+ "o1-mini-2024-09-12",
71
+ // "o1-preview", - No tool support
72
+ // "o1-preview-2024-09-12", - No tool support
73
+ "gpt-4.5-preview",
74
+ "gpt-4.5-preview-2025-02-27",
75
+ "gpt-4.1",
76
+ "gpt-4.1-2025-04-14",
77
+ "gpt-4.1-mini",
78
+ "gpt-4.1-mini-2025-04-14",
79
+ "gpt-4.1-nano",
80
+ "gpt-4.1-nano-2025-04-14",
81
+ "gpt-4o",
82
+ "gpt-4o-2024-05-13",
83
+ "gpt-4o-2024-08-06",
84
+ "gpt-4o-2024-11-20",
85
+ "gpt-4o-audio-preview",
86
+ "gpt-4o-audio-preview-2024-10-01",
87
+ "gpt-4o-audio-preview-2024-12-17",
88
+ "gpt-4o-search-preview",
89
+ "gpt-4o-search-preview-2025-03-11",
90
+ "gpt-4o-mini-search-preview",
91
+ "gpt-4o-mini-search-preview-2025-03-11",
92
+ "gpt-4o-mini",
93
+ "gpt-4o-mini-2024-07-18"
94
+ // "gpt-4-turbo", - Legacy model
95
+ // "gpt-4-turbo-2024-04-09", - Legacy model
96
+ // "gpt-4-turbo-preview", - Legacy model
97
+ // "gpt-4-0125-preview", - No image input support
98
+ // "gpt-4-1106-preview", - No image input support
99
+ // "gpt-4", - No image input support
100
+ // "gpt-4-0613", - No image input support
101
+ // "gpt-3.5-turbo-0125", - Legacy model
102
+ // "gpt-3.5-turbo", - Legacy model
103
+ // "gpt-3.5-turbo-1106", - Legacy model
104
+ // "chatgpt-4o-latest", - No tool support
105
+ ];
106
+ var SupportedModels = Object.fromEntries(
107
+ [...AnthropicModels, ...GoogleModels, ...OpenAIModels].map((model) => [
108
+ model,
109
+ { default: model === DefaultModel, model }
110
+ ])
111
+ );
112
+ function getDefaultModelName() {
113
+ const model = Object.values(SupportedModels).find((model2) => model2.default);
114
+ if (!model) {
115
+ throw new Error("No default model found");
116
+ }
117
+ return model.model;
118
+ }
119
+ function getModel(modelId) {
120
+ const unwrappedModelId = modelId ?? getDefaultModelName();
121
+ if (AnthropicModels.includes(unwrappedModelId)) {
122
+ return anthropic(unwrappedModelId);
123
+ }
124
+ if (GoogleModels.includes(unwrappedModelId)) {
125
+ return google(unwrappedModelId);
126
+ }
127
+ if (OpenAIModels.includes(unwrappedModelId)) {
128
+ return openai(unwrappedModelId);
129
+ }
130
+ throw new Error(`Unsupported model: ${unwrappedModelId}`);
131
+ }
132
+ var BasePartSchema = z.object({
133
+ id: z.string()
134
+ });
135
+ var TextPartSchema = BasePartSchema.extend({
136
+ type: z.literal("textPart"),
137
+ text: z.string()
138
+ });
139
+ var ImageUrlPartSchema = BasePartSchema.extend({
140
+ type: z.literal("imageUrlPart"),
141
+ url: z.string().url(),
142
+ mimeType: z.string()
143
+ });
144
+ var ImageInlinePartSchema = BasePartSchema.extend({
145
+ type: z.literal("imageInlinePart"),
146
+ encodedData: z.string(),
147
+ mimeType: z.string()
148
+ });
149
+ var ImageBinaryPartSchema = BasePartSchema.extend({
150
+ type: z.literal("imageBinaryPart"),
151
+ data: z.string(),
152
+ mimeType: z.string()
153
+ });
154
+ var FileUrlPartSchema = BasePartSchema.extend({
155
+ type: z.literal("fileUrlPart"),
156
+ url: z.string().url(),
157
+ mimeType: z.string()
158
+ });
159
+ var FileInlinePartSchema = BasePartSchema.extend({
160
+ type: z.literal("fileInlinePart"),
161
+ encodedData: z.string(),
162
+ mimeType: z.string()
163
+ });
164
+ var FileBinaryPartSchema = BasePartSchema.extend({
165
+ type: z.literal("fileBinaryPart"),
166
+ data: z.string(),
167
+ mimeType: z.string()
168
+ });
169
+ var ToolCallPartSchema = BasePartSchema.extend({
170
+ type: z.literal("toolCallPart"),
171
+ toolCallId: z.string(),
172
+ toolName: z.string(),
173
+ args: z.unknown()
174
+ });
175
+ var ToolResultPartSchema = BasePartSchema.extend({
176
+ type: z.literal("toolResultPart"),
177
+ toolCallId: z.string(),
178
+ toolName: z.string(),
179
+ contents: z.array(z.union([TextPartSchema, ImageInlinePartSchema])),
180
+ isError: z.boolean().optional()
181
+ });
182
+ var BaseMessageSchema = z.object({
183
+ id: z.string()
184
+ });
185
+ var InstructionMessageSchema = BaseMessageSchema.extend({
186
+ type: z.literal("instructionMessage"),
187
+ contents: z.array(TextPartSchema),
188
+ cache: z.boolean().optional()
189
+ });
190
+ var UserMessageSchema = BaseMessageSchema.extend({
191
+ type: z.literal("userMessage"),
192
+ contents: z.array(
193
+ z.union([
194
+ TextPartSchema,
195
+ ImageUrlPartSchema,
196
+ ImageInlinePartSchema,
197
+ ImageBinaryPartSchema,
198
+ FileUrlPartSchema,
199
+ FileInlinePartSchema,
200
+ FileBinaryPartSchema
201
+ ])
202
+ ),
203
+ cache: z.boolean().optional()
204
+ });
205
+ var ExpertMessageSchema = BaseMessageSchema.extend({
206
+ type: z.literal("expertMessage"),
207
+ contents: z.array(z.union([TextPartSchema, ToolCallPartSchema])),
208
+ cache: z.boolean().optional()
209
+ });
210
+ var ToolMessageSchema = BaseMessageSchema.extend({
211
+ type: z.literal("toolMessage"),
212
+ contents: z.array(ToolResultPartSchema),
213
+ cache: z.boolean().optional()
214
+ });
215
+ var MessageSchema = z.union([
216
+ InstructionMessageSchema,
217
+ UserMessageSchema,
218
+ ExpertMessageSchema,
219
+ ToolMessageSchema
220
+ ]);
221
+
222
+ // src/schemas/runtime.ts
223
+ var expertNameRegex = /^(@[a-z0-9][a-z0-9_-]*\/)?[a-z0-9][a-z0-9_-]*$/;
224
+ var versionRegex = /^(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-[\w.-]+)?(?:\+[\w.-]+)?$/;
225
+ var tagNameRegex = /^[a-z0-9][a-z0-9_-]*$/;
226
+ var expertKeyRegex = /^((?:@[a-z0-9][a-z0-9_\.-]*\/)?[a-z0-9][a-z0-9_\.-]*)(?:@((?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-[\w.-]+)?(?:\+[\w.-]+)?)|@([a-z0-9][a-z0-9_\.-]*))?$/;
227
+ var skillNameRegex = /^[a-z0-9][a-z0-9._-]*$/;
228
+ var maxNameLength = 214;
229
+ function parseExpertKey(expertKey) {
230
+ const match = expertKey.match(expertKeyRegex);
231
+ if (!match) {
232
+ throw new Error(`Invalid expert key format: ${expertKey}`);
233
+ }
234
+ const [key, name, version, tag] = match;
235
+ return {
236
+ key,
237
+ name,
238
+ version,
239
+ tag
240
+ };
241
+ }
242
+ var McpStdioSkillSchema = z.object({
243
+ type: z.literal("mcpStdioSkill"),
244
+ name: z.string(),
245
+ description: z.string().optional(),
246
+ rule: z.string().optional(),
247
+ pick: z.array(z.string()).optional().default([]),
248
+ omit: z.array(z.string()).optional().default([]),
249
+ command: z.string(),
250
+ packageName: z.string().optional(),
251
+ args: z.array(z.string()).optional().default([]),
252
+ requiredEnv: z.array(z.string()).optional().default([])
253
+ });
254
+ var McpSseSkillSchema = z.object({
255
+ type: z.literal("mcpSseSkill"),
256
+ name: z.string(),
257
+ description: z.string().optional(),
258
+ rule: z.string().optional(),
259
+ pick: z.array(z.string()).optional().default([]),
260
+ omit: z.array(z.string()).optional().default([]),
261
+ endpoint: z.string()
262
+ });
263
+ var InteractiveToolSchema = z.object({
264
+ name: z.string(),
265
+ description: z.string().optional(),
266
+ inputJsonSchema: z.string()
267
+ });
268
+ var InteractiveSkillSchema = z.object({
269
+ type: z.literal("interactiveSkill"),
270
+ name: z.string(),
271
+ description: z.string().optional(),
272
+ rule: z.string().optional(),
273
+ tools: z.record(z.string(), InteractiveToolSchema.omit({ name: true })).transform((tools) => {
274
+ return Object.fromEntries(
275
+ Object.entries(tools).map(([key, toolWithoutName]) => [
276
+ key,
277
+ InteractiveToolSchema.parse({ ...toolWithoutName, name: key })
278
+ ])
279
+ );
280
+ })
281
+ });
282
+ var ExpertSchema = z.object({
283
+ key: z.string().regex(expertKeyRegex).min(1),
284
+ name: z.string().regex(expertNameRegex).min(1).max(maxNameLength),
285
+ version: z.string().regex(versionRegex),
286
+ description: z.string().min(1).max(1024 * 2).optional(),
287
+ instruction: z.string().min(1).max(1024 * 20),
288
+ skills: z.record(
289
+ z.string(),
290
+ z.discriminatedUnion("type", [
291
+ McpStdioSkillSchema.omit({ name: true }),
292
+ McpSseSkillSchema.omit({ name: true }),
293
+ InteractiveSkillSchema.omit({ name: true })
294
+ ])
295
+ ).optional().default({
296
+ "@perstack/base": {
297
+ type: "mcpStdioSkill",
298
+ description: "Base skill",
299
+ command: "npx",
300
+ args: ["-y", "@perstack/base"]
301
+ }
302
+ }).transform((skills) => {
303
+ return Object.fromEntries(
304
+ Object.entries(skills).map(([key, skillWithoutName]) => [
305
+ key,
306
+ z.discriminatedUnion("type", [
307
+ McpStdioSkillSchema,
308
+ McpSseSkillSchema,
309
+ InteractiveSkillSchema
310
+ ]).parse({ ...skillWithoutName, name: key })
311
+ ])
312
+ );
313
+ }),
314
+ delegates: z.array(z.string().regex(expertKeyRegex).min(1)).optional().default([]),
315
+ tags: z.array(z.string().regex(tagNameRegex).min(1)).optional().default([])
316
+ });
317
+ var UsageSchema = z.object({
318
+ promptTokens: z.number(),
319
+ completionTokens: z.number(),
320
+ totalTokens: z.number(),
321
+ cacheCreationInputTokens: z.number(),
322
+ cacheReadInputTokens: z.number()
323
+ });
324
+ var CheckpointStatusSchema = z.enum([
325
+ "init",
326
+ "proceeding",
327
+ "completed",
328
+ "stoppedByInteractiveTool",
329
+ "stoppedByDelegate",
330
+ "stoppedByExceededMaxSteps",
331
+ "stoppedByError"
332
+ ]);
333
+ var CheckpointSchema = z.object({
334
+ id: z.string(),
335
+ runId: z.string(),
336
+ status: CheckpointStatusSchema,
337
+ stepNumber: z.number(),
338
+ messages: z.array(MessageSchema),
339
+ expert: z.object({
340
+ key: z.string(),
341
+ name: z.string(),
342
+ version: z.string()
343
+ }),
344
+ delegateTo: z.object({
345
+ expert: z.object({
346
+ key: z.string(),
347
+ name: z.string(),
348
+ version: z.string()
349
+ }),
350
+ toolCallId: z.string(),
351
+ toolName: z.string(),
352
+ query: z.string()
353
+ }).optional(),
354
+ delegatedBy: z.object({
355
+ expert: z.object({
356
+ key: z.string(),
357
+ name: z.string(),
358
+ version: z.string()
359
+ }),
360
+ toolCallId: z.string(),
361
+ toolName: z.string(),
362
+ checkpointId: z.string()
363
+ }).optional(),
364
+ usage: UsageSchema
365
+ });
366
+ var RunParamsSchema = z.object({
367
+ setting: z.object({
368
+ runId: z.string().optional().transform((value) => value ?? createId()),
369
+ expertKey: z.string().regex(expertKeyRegex).min(1),
370
+ input: z.object({
371
+ text: z.string().optional(),
372
+ interactiveToolCallResult: z.object({
373
+ toolCallId: z.string(),
374
+ toolName: z.string(),
375
+ text: z.string()
376
+ }).optional()
377
+ }),
378
+ experts: z.record(z.string().regex(expertKeyRegex).min(1), ExpertSchema.omit({ key: true })).optional().default({}).transform(
379
+ (experts) => Object.fromEntries(
380
+ Object.entries(experts).map(([key, expertWithoutKey]) => [
381
+ key,
382
+ ExpertSchema.parse({
383
+ ...expertWithoutKey,
384
+ key
385
+ })
386
+ ])
387
+ )
388
+ ),
389
+ model: z.string().optional().default(getDefaultModelName()),
390
+ temperature: z.number().min(0).max(1).optional().default(0.3),
391
+ maxSteps: z.number().min(1).optional(),
392
+ maxRetries: z.number().min(0).optional().default(10),
393
+ /** Optional workspace directory path. If provided, sets WORKSPACE_DIR environment variable for skill execution. */
394
+ workspace: z.string().optional(),
395
+ startedAt: z.number().optional().default(Date.now()),
396
+ updatedAt: z.number().optional().default(Date.now())
397
+ }),
398
+ checkpoint: CheckpointSchema.optional()
399
+ });
400
+ function createEvent(type) {
401
+ return (setting, checkpoint, data) => {
402
+ return {
403
+ type,
404
+ id: createId(),
405
+ expertKey: checkpoint.expert.key,
406
+ timestamp: Date.now(),
407
+ runId: setting.runId,
408
+ stepNumber: checkpoint.stepNumber,
409
+ ...data
410
+ };
411
+ };
412
+ }
413
+ var startRun = createEvent("startRun");
414
+ var startGeneration = createEvent("startGeneration");
415
+ var retry = createEvent("retry");
416
+ var callTool = createEvent("callTool");
417
+ var callInteractiveTool = createEvent("callInteractiveTool");
418
+ var callDelegate = createEvent("callDelegate");
419
+ var resolveToolResult = createEvent("resolveToolResult");
420
+ var resolveThought = createEvent("resolveThought");
421
+ var resolvePdfFile = createEvent("resolvePdfFile");
422
+ var resolveImageFile = createEvent("resolveImageFile");
423
+ var attemptCompletion = createEvent("attemptCompletion");
424
+ var finishToolCall = createEvent("finishToolCall");
425
+ var completeRun = createEvent("completeRun");
426
+ var stopRunByInteractiveTool = createEvent("stopRunByInteractiveTool");
427
+ var stopRunByDelegate = createEvent("stopRunByDelegate");
428
+ var stopRunByExceededMaxSteps = createEvent("stopRunByExceededMaxSteps");
429
+ var continueToNextStep = createEvent("continueToNextStep");
430
+
431
+ // src/default-store.ts
432
+ async function defaultRetrieveCheckpoint(runId, checkpointId) {
433
+ const runDir = getRunDir(runId);
434
+ const checkpointFiles = await readdir(runDir, { withFileTypes: true }).then(
435
+ (files) => files.filter((file) => file.isFile() && file.name.startsWith("checkpoint-"))
436
+ );
437
+ const checkpointFile = checkpointFiles.find((file) => file.name.endsWith(`-${checkpointId}.json`));
438
+ if (!checkpointFile) {
439
+ throw new Error(`checkpoint not found: ${runId} ${checkpointId}`);
440
+ }
441
+ const checkpointPath = `${runDir}/${checkpointFile.name}`;
442
+ const checkpoint = await readFile(checkpointPath, "utf8");
443
+ return CheckpointSchema.parse(JSON.parse(checkpoint));
444
+ }
445
+ async function defaultStoreCheckpoint(checkpoint, timestamp) {
446
+ const { id, runId, stepNumber } = checkpoint;
447
+ const runDir = getRunDir(runId);
448
+ const checkpointPath = `${runDir}/checkpoint-${timestamp}-${stepNumber}-${id}.json`;
449
+ await mkdir(runDir, { recursive: true });
450
+ await writeFile(checkpointPath, JSON.stringify(checkpoint, null, 2));
451
+ }
452
+ async function defaultStoreEvent(event) {
453
+ const { timestamp, runId, stepNumber, type } = event;
454
+ const runDir = getRunDir(runId);
455
+ const eventPath = `${runDir}/event-${timestamp}-${stepNumber}-${type}.json`;
456
+ await mkdir(runDir, { recursive: true });
457
+ await writeFile(eventPath, JSON.stringify(event, null, 2));
458
+ }
459
+
460
+ // package.json
461
+ var package_default = {
462
+ version: "0.0.10"};
463
+
464
+ // src/events/default-event-listener.ts
465
+ var log = console.info;
466
+ var debug = console.debug;
467
+ var header = (e) => {
468
+ const t = (/* @__PURE__ */ new Date()).toISOString();
469
+ const stepNumber = e.stepNumber;
470
+ const key = e.expertKey;
471
+ return `${t} ${stepNumber} ${key}`;
472
+ };
473
+ async function defaultEventListener(e) {
474
+ await defaultStoreEvent(e);
475
+ switch (e.type) {
476
+ case "startRun": {
477
+ log(`${header(e)} \u{1F99C} Perstack@${package_default.version} started`);
478
+ const { inputMessages } = e;
479
+ for (const message of inputMessages) {
480
+ if (message.type === "userMessage") {
481
+ logUserMessage(message);
482
+ } else if (message.type === "toolMessage") {
483
+ logToolMessage(message);
484
+ }
485
+ }
486
+ break;
487
+ }
488
+ case "startGeneration": {
489
+ log(`${header(e)} \u{1F99C} Generating tool call`);
490
+ break;
491
+ }
492
+ case "retry": {
493
+ logUsage(e);
494
+ log(`${header(e)} \u{1F99C} Retrying tool call generation`);
495
+ break;
496
+ }
497
+ case "callTool": {
498
+ logUsage(e);
499
+ log(`${header(e)} \u{1F99C} Calling tool`);
500
+ if (e.toolCall.skillName === "@perstack/base") {
501
+ switch (e.toolCall.toolName) {
502
+ case "think": {
503
+ const thought = e.toolCall.args.thought;
504
+ log(`${header(e)} \u{1F4AD} Thought Updated:`);
505
+ debug(thought);
506
+ break;
507
+ }
508
+ case "readPdfFile": {
509
+ const path2 = e.toolCall.args.path;
510
+ log(`${header(e)} \u{1F4C4} Reading PDF: ${path2}`);
511
+ break;
512
+ }
513
+ case "readImageFile": {
514
+ const path2 = e.toolCall.args.path;
515
+ log(`${header(e)} \u{1F5BC}\uFE0F Reading Image: ${path2}`);
516
+ break;
517
+ }
518
+ default: {
519
+ log(`${header(e)} \u{1F527} Tool: ${e.toolCall.skillName}/${e.toolCall.toolName}`);
520
+ log(`${header(e)} \u{1F527} Args: ${e.toolCall.args}`);
521
+ break;
522
+ }
523
+ }
524
+ } else {
525
+ log(`${header(e)} \u{1F527} Tool: ${e.toolCall.skillName}/${e.toolCall.toolName}`);
526
+ log(`${header(e)} \u{1F527} Args: ${e.toolCall.args}`);
527
+ }
528
+ break;
529
+ }
530
+ case "callInteractiveTool": {
531
+ logUsage(e);
532
+ log(`${header(e)} \u{1F99C} Calling interactive tool`);
533
+ log(`${header(e)} \u{1F527} Tool: ${e.toolCall.skillName}/${e.toolCall.toolName}`);
534
+ log(`${header(e)} \u{1F527} Args: ${e.toolCall.args}`);
535
+ break;
536
+ }
537
+ case "callDelegate": {
538
+ logUsage(e);
539
+ log(`${header(e)} \u{1F99C} Calling delegate`);
540
+ log(`${header(e)} \u{1F527} Tool: ${e.toolCall.toolName}`);
541
+ log(`${header(e)} \u{1F527} Args: ${e.toolCall.args}`);
542
+ break;
543
+ }
544
+ case "resolveToolResult": {
545
+ log(`${header(e)} \u{1F527} Resolved Tool Result`);
546
+ if (e.toolResult.skillName === "@perstack/base") {
547
+ switch (e.toolResult.toolName) {
548
+ case "todo": {
549
+ const text = e.toolResult.result.find((r) => r.type === "textPart")?.text;
550
+ const { todos } = JSON.parse(text ?? "{}");
551
+ log(`${header(e)} \u{1F4C4} Todo:`);
552
+ for (const todo of todos) {
553
+ debug(`${todo.completed ? "[x]" : "[ ]"} ${todo.id}: ${todo.title}`);
554
+ }
555
+ break;
556
+ }
557
+ default: {
558
+ log(`${header(e)} \u{1F527} Tool: ${e.toolResult.skillName}/${e.toolResult.toolName}`);
559
+ log(`${header(e)} \u{1F527} Result: ${e.toolResult.result}`);
560
+ break;
561
+ }
562
+ }
563
+ } else {
564
+ log(`${header(e)} \u{1F527} Tool: ${e.toolResult.skillName}/${e.toolResult.toolName}`);
565
+ log(`${header(e)} \u{1F527} Result: ${e.toolResult.result}`);
566
+ }
567
+ break;
568
+ }
569
+ case "resolveThought": {
570
+ log(`${header(e)} \u{1F4AD} Resolved Thought:`, e.toolResult);
571
+ break;
572
+ }
573
+ case "resolvePdfFile": {
574
+ log(`${header(e)} \u{1F4C4} Resolved PDF:`, e.toolResult);
575
+ break;
576
+ }
577
+ case "resolveImageFile": {
578
+ log(`${header(e)} \u{1F5BC}\uFE0F Resolved Image:`, e.toolResult);
579
+ break;
580
+ }
581
+ case "attemptCompletion": {
582
+ log(`${header(e)} \u2705 Attempting completion`);
583
+ break;
584
+ }
585
+ case "completeRun": {
586
+ logUsage(e);
587
+ log(`${header(e)} \u{1F99C} Completing run`);
588
+ log(`${header(e)} \u{1F99C} Result:`, e.text);
589
+ break;
590
+ }
591
+ case "stopRunByInteractiveTool": {
592
+ log(`${header(e)} \u{1F99C} Stopping run by interactive tool`);
593
+ break;
594
+ }
595
+ case "stopRunByDelegate": {
596
+ log(`${header(e)} \u{1F99C} Stopping run by delegate`);
597
+ break;
598
+ }
599
+ case "stopRunByExceededMaxSteps": {
600
+ log(`${header(e)} \u{1F99C} Stopping run by exceeded max steps`);
601
+ break;
602
+ }
603
+ case "continueToNextStep": {
604
+ log(`${header(e)} \u{1F99C} Continuing to next step`);
605
+ break;
606
+ }
607
+ }
608
+ }
609
+ function logUserMessage(message) {
610
+ const t = (/* @__PURE__ */ new Date()).toISOString();
611
+ const contents = message.contents;
612
+ for (const content of contents) {
613
+ if (content.type === "textPart") {
614
+ log(`${t} \u{1F4AC} User: ${content.text}`);
615
+ } else if (content.type === "imageUrlPart") {
616
+ log(`${t} \u{1F5BC}\uFE0F User: ${content.url}`);
617
+ } else if (content.type === "imageInlinePart") {
618
+ log(`${t} \u{1F5BC}\uFE0F User: Inline image`);
619
+ } else if (content.type === "imageBinaryPart") {
620
+ log(`${t} \u{1F5BC}\uFE0F User: Binary image`);
621
+ } else if (content.type === "fileUrlPart") {
622
+ log(`${t} \u{1F4C4} User: ${content.url}`);
623
+ } else if (content.type === "fileInlinePart") {
624
+ log(`${t} \u{1F4C4} User: Inline file`);
625
+ } else if (content.type === "fileBinaryPart") {
626
+ log(`${t} \u{1F4C4} User: Binary file`);
627
+ }
628
+ }
629
+ }
630
+ function logToolMessage(message) {
631
+ const t = (/* @__PURE__ */ new Date()).toISOString();
632
+ const contents = message.contents;
633
+ for (const content of contents) {
634
+ if (content.type === "toolResultPart") {
635
+ const { contents: contents2 } = content;
636
+ for (const content2 of contents2) {
637
+ if (content2.type === "textPart") {
638
+ log(`${t} \u{1F4AC} Tool Result: ${content2.text}`);
639
+ } else if (content2.type === "imageInlinePart") {
640
+ log(`${t} \u{1F5BC}\uFE0F Tool Result: Inline image`);
641
+ }
642
+ }
643
+ }
644
+ }
645
+ }
646
+ function logUsage(e) {
647
+ const usageByGeneration = [
648
+ `In: ${e.usage.promptTokens.toLocaleString()}`,
649
+ `Out: ${e.usage.completionTokens.toLocaleString()}`,
650
+ `Total: ${e.usage.totalTokens.toLocaleString()}`,
651
+ `Cache-read: ${e.usage.cacheReadInputTokens.toLocaleString()}`,
652
+ `Cache-write: ${e.usage.cacheCreationInputTokens.toLocaleString()}`
653
+ ].join(", ");
654
+ log(`${header(e)} \u{1F4CA} Tokens usage: ${usageByGeneration}`);
655
+ const usageByRun = [
656
+ `In: ${e.usage.promptTokens.toLocaleString()}`,
657
+ `Out: ${e.usage.completionTokens.toLocaleString()}`,
658
+ `Total: ${e.usage.totalTokens.toLocaleString()}`,
659
+ `Cache-read: ${e.usage.cacheReadInputTokens.toLocaleString()}`,
660
+ `Cache-write: ${e.usage.cacheCreationInputTokens.toLocaleString()}`
661
+ ].join(", ");
662
+ log(`${header(e)} \u{1F4CA} Total usage: ${usageByRun}`);
663
+ }
664
+ var RunEventEmitter = class {
665
+ listeners = [];
666
+ subscribe(listener) {
667
+ this.listeners.push(listener);
668
+ }
669
+ async emit(event) {
670
+ for (const listener of this.listeners) {
671
+ await listener({
672
+ ...event,
673
+ id: createId(),
674
+ timestamp: Date.now()
675
+ });
676
+ }
677
+ }
678
+ };
679
+ var RegistryV1ExpertSchema = z.object({
680
+ name: z.string(),
681
+ version: z.string(),
682
+ minRuntimeVersion: z.string(),
683
+ description: z.string(),
684
+ instruction: z.string(),
685
+ skills: z.record(
686
+ z.string(),
687
+ z.discriminatedUnion("type", [
688
+ McpStdioSkillSchema.omit({ name: true }),
689
+ McpSseSkillSchema.omit({ name: true }),
690
+ InteractiveSkillSchema.omit({ name: true })
691
+ ])
692
+ ),
693
+ delegates: z.array(z.string()),
694
+ tags: z.array(z.string()),
695
+ status: z.string(),
696
+ owner: z.object({ name: z.string() }),
697
+ createdAt: z.string().datetime(),
698
+ updatedAt: z.string().datetime()
699
+ });
700
+ var RegistryV1ExpertsGetResponseSchema = z.object({
701
+ data: z.object({
702
+ expert: RegistryV1ExpertSchema
703
+ })
704
+ });
705
+
706
+ // src/api-clinent.ts
707
+ var Perstack = class {
708
+ baseUrl;
709
+ registry;
710
+ apiKey;
711
+ constructor(params) {
712
+ this.baseUrl = params?.baseUrl ?? process.env.PERSTACK_API_BASE_URL ?? "https://api.perstack.ai";
713
+ this.apiKey = params?.apiKey ?? process.env.PERSTACK_API_KEY;
714
+ this.registry = new RegistryClientV1(this);
715
+ }
716
+ };
717
+ var RegistryClientV1 = class {
718
+ client;
719
+ endpoint;
720
+ constructor(client) {
721
+ this.client = client;
722
+ this.endpoint = "/api/registry/v1/experts";
723
+ }
724
+ async get(expertKey) {
725
+ const safeExpertKey = encodeURIComponent(expertKey);
726
+ const url = new URL(`${this.endpoint}/${safeExpertKey}`, this.client.baseUrl);
727
+ const headers = {
728
+ "Content-Type": "application/json",
729
+ Authorization: `Bearer ${this.client.apiKey}`
730
+ };
731
+ const result = await fetch(url.toString(), { headers });
732
+ if (!result.ok) {
733
+ throw new Error(
734
+ `Registry returned non-200 status code: ${result.status}, reason: ${result.statusText}`
735
+ );
736
+ }
737
+ const json = await result.json();
738
+ return RegistryV1ExpertsGetResponseSchema.parse(json);
739
+ }
740
+ };
741
+
742
+ // src/resolve-expert-to-run.ts
743
+ async function resolveExpertToRun(expertKey, experts) {
744
+ if (experts[expertKey]) {
745
+ return experts[expertKey];
746
+ }
747
+ const client = new Perstack();
748
+ const { data } = await client.registry.get(expertKey);
749
+ const expert = ExpertSchema.parse({
750
+ ...data.expert,
751
+ key: expertKey
752
+ });
753
+ experts[expertKey] = expert;
754
+ return expert;
755
+ }
756
+ var SkillManager = class {
757
+ _toolDefinitions = [];
758
+ _initialized = false;
759
+ name;
760
+ type;
761
+ skill;
762
+ interactiveSkill;
763
+ expert;
764
+ _mcpClient;
765
+ _params;
766
+ constructor(params) {
767
+ this._params = params;
768
+ this.type = params.type;
769
+ switch (params.type) {
770
+ case "mcp":
771
+ this.name = params.skill.name;
772
+ this.skill = params.skill;
773
+ break;
774
+ case "interactive":
775
+ this.name = params.interactiveSkill.name;
776
+ this.interactiveSkill = params.interactiveSkill;
777
+ break;
778
+ case "delegate":
779
+ this.name = params.expert.name;
780
+ this.expert = params.expert;
781
+ break;
782
+ }
783
+ }
784
+ async init() {
785
+ switch (this._params.type) {
786
+ case "mcp": {
787
+ await this._initMcpSkill(this._params);
788
+ break;
789
+ }
790
+ case "interactive": {
791
+ await this._initInteractiveSkill(this._params);
792
+ break;
793
+ }
794
+ case "delegate": {
795
+ await this._initDelegate(this._params);
796
+ break;
797
+ }
798
+ }
799
+ }
800
+ async _initMcpSkill(params) {
801
+ this._mcpClient = new Client({
802
+ name: `${params.skill.name}-mcp-client`,
803
+ version: "1.0.0"
804
+ });
805
+ switch (params.skill.type) {
806
+ case "mcpStdioSkill": {
807
+ if (!params.skill.command) {
808
+ throw new Error(`Skill ${params.skill.name} has no command`);
809
+ }
810
+ const { command, args } = this._getCommandArgs(params.skill);
811
+ console.error(command, args);
812
+ const transport = new StdioClientTransport({
813
+ command,
814
+ args,
815
+ env: Object.fromEntries(
816
+ Object.entries(process.env).filter(([_, value]) => value !== void 0 && value !== "").map(([key, value]) => [key, value])
817
+ )
818
+ });
819
+ await this._mcpClient.connect(transport);
820
+ break;
821
+ }
822
+ case "mcpSseSkill": {
823
+ if (!params.skill.endpoint) {
824
+ throw new Error(`Skill ${params.skill.name} has no endpoint`);
825
+ }
826
+ const transport = new SSEClientTransport(new URL(params.skill.endpoint));
827
+ await this._mcpClient.connect(transport);
828
+ break;
829
+ }
830
+ }
831
+ const { tools } = await this._mcpClient.listTools();
832
+ this._toolDefinitions = tools.map((tool) => ({
833
+ skillName: params.skill.name,
834
+ name: tool.name,
835
+ description: tool.description,
836
+ inputSchema: tool.inputSchema,
837
+ interactive: false
838
+ }));
839
+ this._initialized = true;
840
+ }
841
+ _getCommandArgs(skill) {
842
+ const { name, command, packageName, args } = skill;
843
+ if (!packageName && (!args || args.length === 0)) {
844
+ throw new Error(`Skill ${name} has no packageName or args. Please provide one of them.`);
845
+ }
846
+ if (packageName && args && args.length > 0) {
847
+ throw new Error(
848
+ `Skill ${name} has both packageName and args. Please provide only one of them.`
849
+ );
850
+ }
851
+ let newArgs = args && args.length > 0 ? args : [packageName];
852
+ if (command === "npx" && !newArgs.includes("-y")) {
853
+ newArgs = ["-y", ...newArgs];
854
+ }
855
+ return { command, args: newArgs };
856
+ }
857
+ async _initInteractiveSkill(params) {
858
+ this._toolDefinitions = Object.values(params.interactiveSkill.tools).map((tool) => ({
859
+ skillName: params.interactiveSkill.name,
860
+ name: tool.name,
861
+ description: tool.description,
862
+ inputSchema: JSON.parse(tool.inputJsonSchema),
863
+ interactive: true
864
+ }));
865
+ this._initialized = true;
866
+ }
867
+ async _initDelegate(params) {
868
+ this._toolDefinitions = [
869
+ {
870
+ skillName: params.expert.name,
871
+ name: params.expert.name.split("/").pop() ?? params.expert.name,
872
+ description: params.expert.description,
873
+ inputSchema: {
874
+ type: "object",
875
+ properties: { query: { type: "string" } },
876
+ required: ["query"]
877
+ },
878
+ interactive: false
879
+ }
880
+ ];
881
+ this._initialized = true;
882
+ }
883
+ async close() {
884
+ if (this._mcpClient) {
885
+ await this._mcpClient.close();
886
+ }
887
+ }
888
+ async getToolDefinitions() {
889
+ if (!this._initialized) {
890
+ throw new Error(`${this.name} is not initialized`);
891
+ }
892
+ if (this._params.type === "mcp") {
893
+ const omit = this._params.skill.omit ?? [];
894
+ const pick = this._params.skill.pick ?? [];
895
+ return this._toolDefinitions.filter((tool) => omit.length > 0 ? !omit.includes(tool.name) : true).filter((tool) => pick.length > 0 ? pick.includes(tool.name) : true);
896
+ }
897
+ return this._toolDefinitions;
898
+ }
899
+ async callTool(toolName, input) {
900
+ switch (this._params.type) {
901
+ case "mcp": {
902
+ if (!this._mcpClient) {
903
+ throw new Error(`${this.name} is not initialized`);
904
+ }
905
+ try {
906
+ const result = await this._mcpClient.callTool({
907
+ name: toolName,
908
+ arguments: input
909
+ });
910
+ return this._convertToolResult(result, toolName, input);
911
+ } catch (error) {
912
+ return this._handleToolError(error, toolName);
913
+ }
914
+ }
915
+ case "interactive": {
916
+ return [];
917
+ }
918
+ case "delegate": {
919
+ return [];
920
+ }
921
+ }
922
+ }
923
+ _handleToolError(error, toolName) {
924
+ if (error instanceof McpError) {
925
+ return [
926
+ {
927
+ type: "textPart",
928
+ text: `Error calling tool ${toolName}: ${error.message}`,
929
+ id: createId()
930
+ }
931
+ ];
932
+ }
933
+ if (error instanceof ZodError) {
934
+ return [{ type: "textPart", text: `Invalid tool call arguments: ${error}`, id: createId() }];
935
+ }
936
+ throw error;
937
+ }
938
+ _convertToolResult(result, toolName, input) {
939
+ if (!result.content || result.content.length === 0) {
940
+ return [
941
+ {
942
+ type: "textPart",
943
+ text: `Tool ${toolName} returned nothing with arguments: ${JSON.stringify(input)}`,
944
+ id: createId()
945
+ }
946
+ ];
947
+ }
948
+ return result.content.filter((part) => part.type !== "audio" && part.type !== "resource_link").map((part) => this._convertPart(part));
949
+ }
950
+ _convertPart(part) {
951
+ switch (part.type) {
952
+ case "text":
953
+ if (!part.text || part.text === "") {
954
+ return { type: "textPart", text: "Error: No content", id: createId() };
955
+ }
956
+ return { type: "textPart", text: part.text, id: createId() };
957
+ case "image":
958
+ if (!part.data || !part.mimeType) {
959
+ throw new Error("Image part must have both data and mimeType");
960
+ }
961
+ return {
962
+ type: "imageInlinePart",
963
+ encodedData: part.data,
964
+ mimeType: part.mimeType,
965
+ id: createId()
966
+ };
967
+ case "resource":
968
+ if (!part.resource) {
969
+ throw new Error("Resource part must have resource content");
970
+ }
971
+ return this._convertResource(part.resource);
972
+ }
973
+ }
974
+ _convertResource(resource) {
975
+ if (!resource.mimeType) {
976
+ throw new Error(`Resource ${JSON.stringify(resource)} has no mimeType`);
977
+ }
978
+ if (resource.text && typeof resource.text === "string") {
979
+ return { type: "textPart", text: resource.text, id: createId() };
980
+ }
981
+ if (resource.blob && typeof resource.blob === "string") {
982
+ return {
983
+ type: "fileInlinePart",
984
+ encodedData: resource.blob,
985
+ mimeType: resource.mimeType,
986
+ id: createId()
987
+ };
988
+ }
989
+ throw new Error(`Unsupported resource type: ${JSON.stringify(resource)}`);
990
+ }
991
+ };
992
+ async function getSkillManagers(expert, experts) {
993
+ const skillManagers = {};
994
+ const { skills } = expert;
995
+ if (!skills["@perstack/base"]) {
996
+ skills["@perstack/base"] = {
997
+ type: "mcpStdioSkill",
998
+ name: "@perstack/base",
999
+ description: "The base skill for Perstack",
1000
+ pick: [],
1001
+ omit: [],
1002
+ command: "npx",
1003
+ args: ["-y", "@perstack/base"],
1004
+ requiredEnv: []
1005
+ };
1006
+ }
1007
+ const mcpSkillManagers = await Promise.all(
1008
+ Object.values(skills).filter((skill) => skill.type === "mcpStdioSkill" || skill.type === "mcpSseSkill").map(async (skill) => {
1009
+ const skillManager = new SkillManager({
1010
+ type: "mcp",
1011
+ skill
1012
+ });
1013
+ await skillManager.init();
1014
+ return skillManager;
1015
+ })
1016
+ );
1017
+ const interactiveSkillManagers = await Promise.all(
1018
+ Object.values(skills).filter((skill) => skill.type === "interactiveSkill").map(async (interactiveSkill) => {
1019
+ const skillManager = new SkillManager({
1020
+ type: "interactive",
1021
+ interactiveSkill
1022
+ });
1023
+ await skillManager.init();
1024
+ return skillManager;
1025
+ })
1026
+ );
1027
+ const delegateSkillManagers = await Promise.all(
1028
+ expert.delegates.map(async (delegateExpertName) => {
1029
+ const delegate = experts[delegateExpertName];
1030
+ const skillManager = new SkillManager({
1031
+ type: "delegate",
1032
+ expert: delegate
1033
+ });
1034
+ await skillManager.init();
1035
+ return skillManager;
1036
+ })
1037
+ );
1038
+ for (const skillManager of mcpSkillManagers) {
1039
+ skillManagers[skillManager.name] = skillManager;
1040
+ }
1041
+ for (const skillManager of interactiveSkillManagers) {
1042
+ skillManagers[skillManager.name] = skillManager;
1043
+ }
1044
+ for (const skillManager of delegateSkillManagers) {
1045
+ skillManagers[skillManager.name] = skillManager;
1046
+ }
1047
+ return skillManagers;
1048
+ }
1049
+ async function closeSkillManagers(skillManagers) {
1050
+ for (const skillManager of Object.values(skillManagers)) {
1051
+ await skillManager.close();
1052
+ }
1053
+ }
1054
+ async function getSkillManagerByToolName(skillManagers, toolName) {
1055
+ for (const skillManager of Object.values(skillManagers)) {
1056
+ const toolDefinitions = await skillManager.getToolDefinitions();
1057
+ for (const toolDefinition of toolDefinitions) {
1058
+ if (toolDefinition.name === toolName) {
1059
+ return skillManager;
1060
+ }
1061
+ }
1062
+ }
1063
+ throw new Error(`Tool ${toolName} not found`);
1064
+ }
1065
+ async function getToolSet(skillManagers) {
1066
+ const tools = {};
1067
+ for (const skillManager of Object.values(skillManagers)) {
1068
+ const toolDefinitions = await skillManager.getToolDefinitions();
1069
+ for (const toolDefinition of toolDefinitions) {
1070
+ tools[toolDefinition.name] = {
1071
+ description: toolDefinition.description,
1072
+ parameters: jsonSchema(toolDefinition.inputSchema)
1073
+ };
1074
+ }
1075
+ }
1076
+ return tools;
1077
+ }
1078
+
1079
+ // src/states/calling-delegate.ts
1080
+ async function callingDelegateLogic({
1081
+ setting,
1082
+ checkpoint,
1083
+ step,
1084
+ skillManagers
1085
+ }) {
1086
+ if (!step?.toolCall) {
1087
+ throw new Error("No tool call found");
1088
+ }
1089
+ const { id, toolName, args } = step.toolCall;
1090
+ const skillManager = await getSkillManagerByToolName(skillManagers, toolName);
1091
+ if (!skillManager || !skillManager.expert) {
1092
+ throw new Error(`Delegation error: skill manager "${toolName}" not found`);
1093
+ }
1094
+ if (!args || !args.query || typeof args.query !== "string") {
1095
+ throw new Error("Delegation error: query is undefined");
1096
+ }
1097
+ return stopRunByDelegate(setting, checkpoint, {
1098
+ checkpoint: {
1099
+ ...checkpoint,
1100
+ status: "stoppedByDelegate",
1101
+ delegateTo: {
1102
+ expert: {
1103
+ key: skillManager.expert.key,
1104
+ name: skillManager.expert.name,
1105
+ version: skillManager.expert.version
1106
+ },
1107
+ toolCallId: id,
1108
+ toolName,
1109
+ query: args.query
1110
+ }
1111
+ },
1112
+ step: {
1113
+ ...step,
1114
+ finishedAt: (/* @__PURE__ */ new Date()).getTime()
1115
+ }
1116
+ });
1117
+ }
1118
+
1119
+ // src/states/calling-interactive-tool.ts
1120
+ async function callingInteractiveToolLogic({
1121
+ setting,
1122
+ checkpoint,
1123
+ step
1124
+ }) {
1125
+ return stopRunByInteractiveTool(setting, checkpoint, {
1126
+ checkpoint: {
1127
+ ...checkpoint,
1128
+ status: "stoppedByInteractiveTool"
1129
+ },
1130
+ step: {
1131
+ ...step,
1132
+ finishedAt: (/* @__PURE__ */ new Date()).getTime()
1133
+ }
1134
+ });
1135
+ }
1136
+
1137
+ // src/states/calling-tool.ts
1138
+ async function callingToolLogic({
1139
+ setting,
1140
+ checkpoint,
1141
+ step,
1142
+ skillManagers
1143
+ }) {
1144
+ if (!step?.toolCall) {
1145
+ throw new Error("No tool call found");
1146
+ }
1147
+ const { id, skillName, toolName, args } = step.toolCall;
1148
+ const skillManager = await getSkillManagerByToolName(skillManagers, toolName);
1149
+ if (skillManager.type !== "mcp") {
1150
+ throw new Error(`Incorrect SkillType, required MCP, got ${skillManager.type}`);
1151
+ }
1152
+ const result = await skillManager.callTool(toolName, args);
1153
+ const toolResult = { id, skillName, toolName, result };
1154
+ if (skillName === "@perstack/base") {
1155
+ if (toolName === "think") {
1156
+ return resolveThought(setting, checkpoint, { toolResult });
1157
+ }
1158
+ if (toolName === "attemptCompletion") {
1159
+ return attemptCompletion(setting, checkpoint, { toolResult });
1160
+ }
1161
+ if (toolName === "readPdfFile") {
1162
+ return resolvePdfFile(setting, checkpoint, { toolResult });
1163
+ }
1164
+ if (toolName === "readImageFile") {
1165
+ return resolveImageFile(setting, checkpoint, { toolResult });
1166
+ }
1167
+ }
1168
+ return resolveToolResult(setting, checkpoint, { toolResult });
1169
+ }
1170
+ async function finishingStepLogic({
1171
+ setting,
1172
+ checkpoint,
1173
+ step
1174
+ }) {
1175
+ if (setting.maxSteps !== void 0 && checkpoint.stepNumber > setting.maxSteps) {
1176
+ return stopRunByExceededMaxSteps(setting, checkpoint, {
1177
+ checkpoint: {
1178
+ ...checkpoint,
1179
+ status: "stoppedByExceededMaxSteps"
1180
+ },
1181
+ step: {
1182
+ ...step,
1183
+ finishedAt: (/* @__PURE__ */ new Date()).getTime()
1184
+ }
1185
+ });
1186
+ }
1187
+ return continueToNextStep(setting, checkpoint, {
1188
+ checkpoint: {
1189
+ ...checkpoint
1190
+ },
1191
+ step: {
1192
+ ...step,
1193
+ finishedAt: (/* @__PURE__ */ new Date()).getTime()
1194
+ },
1195
+ nextCheckpoint: {
1196
+ ...checkpoint,
1197
+ id: createId(),
1198
+ stepNumber: checkpoint.stepNumber + 1
1199
+ }
1200
+ });
1201
+ }
1202
+ function createUserMessage(contents) {
1203
+ return {
1204
+ type: "userMessage",
1205
+ contents: contents.map((part) => ({
1206
+ ...part,
1207
+ id: createId()
1208
+ })),
1209
+ id: createId()
1210
+ };
1211
+ }
1212
+ function createExpertMessage(contents) {
1213
+ return {
1214
+ type: "expertMessage",
1215
+ contents: contents.map((part) => ({
1216
+ ...part,
1217
+ id: createId()
1218
+ })),
1219
+ id: createId()
1220
+ };
1221
+ }
1222
+ function createToolMessage(contents) {
1223
+ return {
1224
+ type: "toolMessage",
1225
+ contents: contents.map((part) => ({
1226
+ ...part,
1227
+ contents: part.contents.map((part2) => ({
1228
+ ...part2,
1229
+ id: createId()
1230
+ })),
1231
+ id: createId()
1232
+ })),
1233
+ id: createId()
1234
+ };
1235
+ }
1236
+ function messageToCoreMessage(message) {
1237
+ switch (message.type) {
1238
+ case "instructionMessage":
1239
+ return {
1240
+ role: "system",
1241
+ content: instructionContentsToCoreContent(message.contents),
1242
+ providerOptions: message.cache ? {
1243
+ anthropic: { cacheControl: { type: "ephemeral" } }
1244
+ } : void 0
1245
+ };
1246
+ case "userMessage":
1247
+ return {
1248
+ role: "user",
1249
+ content: userContentsToCoreContent(message.contents),
1250
+ providerOptions: message.cache ? {
1251
+ anthropic: { cacheControl: { type: "ephemeral" } }
1252
+ } : void 0
1253
+ };
1254
+ case "expertMessage":
1255
+ return {
1256
+ role: "assistant",
1257
+ content: expertContentsToCoreContent(message.contents),
1258
+ providerOptions: message.cache ? {
1259
+ anthropic: { cacheControl: { type: "ephemeral" } }
1260
+ } : void 0
1261
+ };
1262
+ case "toolMessage":
1263
+ return {
1264
+ role: "tool",
1265
+ content: toolContentsToCoreContent(message.contents),
1266
+ providerOptions: message.cache ? {
1267
+ anthropic: { cacheControl: { type: "ephemeral" } }
1268
+ } : void 0
1269
+ };
1270
+ }
1271
+ }
1272
+ function instructionContentsToCoreContent(contents) {
1273
+ return contents.reduce((acc, part) => {
1274
+ return dedent`
1275
+ ${acc}
1276
+ ${part.text}
1277
+ `.trim();
1278
+ }, "");
1279
+ }
1280
+ function userContentsToCoreContent(contents) {
1281
+ return contents.map((part) => {
1282
+ switch (part.type) {
1283
+ case "textPart":
1284
+ return textPartToCoreTextPart(part);
1285
+ case "imageUrlPart":
1286
+ return imageUrlPartToCoreImagePart(part);
1287
+ case "imageInlinePart":
1288
+ return imageInlinePartToCoreImagePart(part);
1289
+ case "imageBinaryPart":
1290
+ return imageBinaryPartToCoreImagePart(part);
1291
+ case "fileUrlPart":
1292
+ return fileUrlPartToCoreFilePart(part);
1293
+ case "fileInlinePart":
1294
+ return fileInlinePartToCoreFilePart(part);
1295
+ case "fileBinaryPart":
1296
+ return fileBinaryPartToCoreFilePart(part);
1297
+ }
1298
+ });
1299
+ }
1300
+ function expertContentsToCoreContent(contents) {
1301
+ return contents.map((part) => {
1302
+ switch (part.type) {
1303
+ case "textPart":
1304
+ return textPartToCoreTextPart(part);
1305
+ case "toolCallPart":
1306
+ return toolCallPartToCoreToolCallPart(part);
1307
+ }
1308
+ });
1309
+ }
1310
+ function toolContentsToCoreContent(contents) {
1311
+ return contents.map((part) => {
1312
+ switch (part.type) {
1313
+ case "toolResultPart":
1314
+ return toolResultPartToCoreToolResultPart(part);
1315
+ }
1316
+ });
1317
+ }
1318
+ function textPartToCoreTextPart(part) {
1319
+ return {
1320
+ type: "text",
1321
+ text: part.text
1322
+ };
1323
+ }
1324
+ function imageUrlPartToCoreImagePart(part) {
1325
+ return {
1326
+ type: "image",
1327
+ image: part.url,
1328
+ mimeType: part.mimeType
1329
+ };
1330
+ }
1331
+ function imageInlinePartToCoreImagePart(part) {
1332
+ return {
1333
+ type: "image",
1334
+ image: part.encodedData,
1335
+ mimeType: part.mimeType
1336
+ };
1337
+ }
1338
+ function imageBinaryPartToCoreImagePart(part) {
1339
+ return {
1340
+ type: "image",
1341
+ image: part.data,
1342
+ mimeType: part.mimeType
1343
+ };
1344
+ }
1345
+ function fileUrlPartToCoreFilePart(part) {
1346
+ return {
1347
+ type: "file",
1348
+ data: part.url,
1349
+ mimeType: part.mimeType
1350
+ };
1351
+ }
1352
+ function fileInlinePartToCoreFilePart(part) {
1353
+ return {
1354
+ type: "file",
1355
+ data: part.encodedData,
1356
+ mimeType: part.mimeType
1357
+ };
1358
+ }
1359
+ function fileBinaryPartToCoreFilePart(part) {
1360
+ return {
1361
+ type: "file",
1362
+ data: part.data,
1363
+ mimeType: part.mimeType
1364
+ };
1365
+ }
1366
+ function toolCallPartToCoreToolCallPart(part) {
1367
+ return {
1368
+ type: "tool-call",
1369
+ toolCallId: part.toolCallId,
1370
+ toolName: part.toolName,
1371
+ args: part.args
1372
+ };
1373
+ }
1374
+ function toolResultPartToCoreToolResultPart(part) {
1375
+ return {
1376
+ type: "tool-result",
1377
+ toolCallId: part.toolCallId,
1378
+ toolName: part.toolName,
1379
+ result: part.contents,
1380
+ experimental_content: part.contents.map((part2) => {
1381
+ switch (part2.type) {
1382
+ case "textPart":
1383
+ return {
1384
+ type: "text",
1385
+ text: part2.text
1386
+ };
1387
+ case "imageInlinePart":
1388
+ return {
1389
+ type: "image",
1390
+ data: part2.encodedData,
1391
+ mimeType: part2.mimeType
1392
+ };
1393
+ }
1394
+ }),
1395
+ isError: part.isError
1396
+ };
1397
+ }
1398
+
1399
+ // src/usage.ts
1400
+ function createEmptyUsage() {
1401
+ return {
1402
+ promptTokens: 0,
1403
+ completionTokens: 0,
1404
+ totalTokens: 0,
1405
+ cacheCreationInputTokens: 0,
1406
+ cacheReadInputTokens: 0
1407
+ };
1408
+ }
1409
+ function usageFromGenerateTextResult(result) {
1410
+ let cacheCreationInputTokens = 0;
1411
+ let cacheReadInputTokens = 0;
1412
+ if (result.providerMetadata?.anthropic) {
1413
+ const anthropicMetadata = result.providerMetadata.anthropic;
1414
+ cacheCreationInputTokens = anthropicMetadata.cacheCreationInputTokens || 0;
1415
+ cacheReadInputTokens = anthropicMetadata.cacheReadInputTokens || 0;
1416
+ }
1417
+ return {
1418
+ promptTokens: result.usage.promptTokens,
1419
+ completionTokens: result.usage.completionTokens,
1420
+ totalTokens: result.usage.totalTokens,
1421
+ cacheCreationInputTokens,
1422
+ cacheReadInputTokens
1423
+ };
1424
+ }
1425
+ function sumUsage(a, b) {
1426
+ return {
1427
+ promptTokens: a.promptTokens + b.promptTokens,
1428
+ completionTokens: a.completionTokens + b.completionTokens,
1429
+ totalTokens: a.totalTokens + b.totalTokens,
1430
+ cacheCreationInputTokens: a.cacheCreationInputTokens + b.cacheCreationInputTokens,
1431
+ cacheReadInputTokens: a.cacheReadInputTokens + b.cacheReadInputTokens
1432
+ };
1433
+ }
1434
+
1435
+ // src/states/generating-run-result.ts
1436
+ async function generatingRunResultLogic({
1437
+ setting,
1438
+ checkpoint,
1439
+ step
1440
+ }) {
1441
+ if (!step?.toolCall || !step?.toolResult) {
1442
+ throw new Error("No tool call or tool result found");
1443
+ }
1444
+ const { id, toolName } = step.toolCall;
1445
+ const { result } = step.toolResult;
1446
+ const toolMessage = createToolMessage([
1447
+ {
1448
+ type: "toolResultPart",
1449
+ toolCallId: id,
1450
+ toolName,
1451
+ contents: result.filter(
1452
+ (part) => part.type === "textPart" || part.type === "imageInlinePart"
1453
+ )
1454
+ }
1455
+ ]);
1456
+ const model = getModel(setting.model);
1457
+ const { messages } = checkpoint;
1458
+ const generationResult = await generateText({
1459
+ model,
1460
+ messages: [...messages, toolMessage].map(messageToCoreMessage),
1461
+ temperature: setting.temperature,
1462
+ maxRetries: setting.maxRetries
1463
+ });
1464
+ const usage = usageFromGenerateTextResult(generationResult);
1465
+ const { text } = generationResult;
1466
+ const newMessages = [toolMessage, createExpertMessage(text ? [{ type: "textPart", text }] : [])];
1467
+ return completeRun(setting, checkpoint, {
1468
+ checkpoint: {
1469
+ ...checkpoint,
1470
+ messages: [...messages, ...newMessages],
1471
+ usage: sumUsage(checkpoint.usage, usage),
1472
+ status: "completed"
1473
+ },
1474
+ step: {
1475
+ ...step,
1476
+ newMessages: [...step.newMessages, ...newMessages],
1477
+ finishedAt: (/* @__PURE__ */ new Date()).getTime(),
1478
+ usage: sumUsage(step.usage, usage)
1479
+ },
1480
+ text,
1481
+ usage
1482
+ });
1483
+ }
1484
+ async function generatingToolCallLogic({
1485
+ setting,
1486
+ checkpoint,
1487
+ skillManagers
1488
+ }) {
1489
+ const { messages } = checkpoint;
1490
+ const model = getModel(setting.model);
1491
+ const result = await generateText({
1492
+ model,
1493
+ messages: messages.map(messageToCoreMessage),
1494
+ temperature: setting.temperature,
1495
+ maxRetries: setting.maxRetries,
1496
+ tools: await getToolSet(skillManagers),
1497
+ toolChoice: "required"
1498
+ });
1499
+ const usage = usageFromGenerateTextResult(result);
1500
+ const { text, toolCalls, finishReason } = result;
1501
+ const toolCall = toolCalls[0];
1502
+ if (!toolCall) {
1503
+ return retry(setting, checkpoint, {
1504
+ newMessages: [
1505
+ createExpertMessage(text ? [{ type: "textPart", text }] : []),
1506
+ createUserMessage([
1507
+ {
1508
+ type: "textPart",
1509
+ text: "You must generate a tool call. Try again."
1510
+ }
1511
+ ])
1512
+ ],
1513
+ usage
1514
+ });
1515
+ }
1516
+ if (finishReason !== "tool-calls") {
1517
+ switch (finishReason) {
1518
+ case "length": {
1519
+ return retry(setting, checkpoint, {
1520
+ newMessages: [
1521
+ createExpertMessage([
1522
+ {
1523
+ type: "toolCallPart",
1524
+ toolCallId: toolCall.toolCallId,
1525
+ toolName: toolCall.toolName,
1526
+ args: toolCall.args
1527
+ }
1528
+ ]),
1529
+ createToolMessage([
1530
+ {
1531
+ type: "toolResultPart",
1532
+ toolCallId: toolCall.toolCallId,
1533
+ toolName: toolCall.toolName,
1534
+ contents: [{ type: "textPart", text: "Error: Generation length exceeded" }]
1535
+ }
1536
+ ])
1537
+ ],
1538
+ usage
1539
+ });
1540
+ }
1541
+ default:
1542
+ throw new Error(`Unexpected finish reason: ${finishReason}`);
1543
+ }
1544
+ }
1545
+ const contents = [
1546
+ {
1547
+ type: "toolCallPart",
1548
+ toolCallId: toolCall.toolCallId,
1549
+ toolName: toolCall.toolName,
1550
+ args: toolCall.args
1551
+ }
1552
+ ];
1553
+ if (text) {
1554
+ contents.push({
1555
+ type: "textPart",
1556
+ text
1557
+ });
1558
+ }
1559
+ const skillManager = await getSkillManagerByToolName(skillManagers, toolCall.toolName);
1560
+ const eventPayload = {
1561
+ newMessage: createExpertMessage(contents),
1562
+ toolCall: {
1563
+ id: toolCall.toolCallId,
1564
+ skillName: skillManager.name,
1565
+ toolName: toolCall.toolName,
1566
+ args: toolCall.args
1567
+ },
1568
+ usage
1569
+ };
1570
+ switch (skillManager.type) {
1571
+ case "mcp":
1572
+ return callTool(setting, checkpoint, eventPayload);
1573
+ case "interactive":
1574
+ return callInteractiveTool(setting, checkpoint, eventPayload);
1575
+ case "delegate":
1576
+ return callDelegate(setting, checkpoint, eventPayload);
1577
+ }
1578
+ }
1579
+ var metaInstruction = dedent`
5
1580
  IMPORTANT:
6
1581
  You are NOT an "interactive" AI agent.
7
1582
  From the start of the agent loop until the completion of the task,
@@ -41,40 +1616,857 @@ import {existsSync}from'fs';import {readFile,writeFile,mkdir,readdir}from'fs/pro
41
1616
  - 専門家である以上、ユーザーが期待する以上の品質のアウトプットを行ってください
42
1617
 
43
1618
  Environment information:
44
- - Current time is ${new Date().toISOString()}
1619
+ - Current time is ${(/* @__PURE__ */ new Date()).toISOString()}
45
1620
  - Current working directory is ${process.cwd()}
46
- `;function Xe(e,t){let o=dedent`
1621
+ `;
1622
+ function createInstructionMessage(expert, experts) {
1623
+ const instruction = dedent`
47
1624
  You are Perstack, an AI expert that tackles tasks requested by users by utilizing all available tools.
48
1625
 
49
1626
  (The following information describes your nature and role as an AI, the mechanisms of the AI system, and other meta-cognitive aspects.)
50
1627
 
51
- ${po}
1628
+ ${metaInstruction}
52
1629
 
53
1630
  ---
54
1631
  (The following describes the objective, steps, rules, etc. regarding your expert task.)
55
1632
 
56
- ${e.instruction}
1633
+ ${expert.instruction}
57
1634
 
58
1635
  ---
59
1636
  (The following is an overview of each skill and the rules for calling tools.)
60
1637
 
61
- ${co(e)}
1638
+ ${getSkillRules(expert)}
62
1639
 
63
1640
  ---
64
1641
  (The following is an overview of each delegate expert and the rules for calling tools.)
65
1642
 
66
1643
  You can delegate tasks to the following experts by calling delegate expert name as a tool:
67
1644
 
68
- ${mo(e,t)}
69
- `;return {type:"instructionMessage",contents:[{id:createId(),type:"textPart",text:o}],id:createId(),cache:true}}function co(e){return Object.values(e.skills).reduce((t,o)=>o.rule?dedent`
70
- ${t}
1645
+ ${getDelegateRules(expert, experts)}
1646
+ `;
1647
+ return {
1648
+ type: "instructionMessage",
1649
+ contents: [
1650
+ {
1651
+ id: createId(),
1652
+ type: "textPart",
1653
+ text: instruction
1654
+ }
1655
+ ],
1656
+ id: createId(),
1657
+ cache: true
1658
+ };
1659
+ }
1660
+ function getSkillRules(expert) {
1661
+ return Object.values(expert.skills).reduce((acc, skill) => {
1662
+ if (!skill.rule) {
1663
+ return acc;
1664
+ }
1665
+ return dedent`
1666
+ ${acc}
1667
+
1668
+ "${skill.name}" skill rules:
1669
+ ${skill.rule}
1670
+ `.trim();
1671
+ }, "");
1672
+ }
1673
+ function getDelegateRules(expert, experts) {
1674
+ return expert.delegates.reduce((acc, delegateExpertName) => {
1675
+ const delegate = experts[delegateExpertName];
1676
+ if (!delegate) {
1677
+ return acc;
1678
+ }
1679
+ return dedent`
1680
+ ${acc}
1681
+
1682
+ About "${delegate.name}":
1683
+ ${delegate.description}
1684
+ `.trim();
1685
+ }, "");
1686
+ }
1687
+
1688
+ // src/states/init.ts
1689
+ async function initLogic({
1690
+ setting,
1691
+ checkpoint
1692
+ }) {
1693
+ const { expertKey, experts } = setting;
1694
+ const expert = experts[expertKey];
1695
+ switch (checkpoint.status) {
1696
+ case "init":
1697
+ return startRun(setting, checkpoint, {
1698
+ initialCheckpoint: checkpoint,
1699
+ inputMessages: [createInstructionMessage(expert, experts), getInputMessage(setting.input)]
1700
+ });
1701
+ default:
1702
+ return startRun(setting, checkpoint, {
1703
+ initialCheckpoint: checkpoint,
1704
+ inputMessages: [getInputMessage(setting.input)]
1705
+ });
1706
+ }
1707
+ }
1708
+ function getInputMessage(input) {
1709
+ if (input.text) {
1710
+ return createUserMessage([{ type: "textPart", text: input.text }]);
1711
+ }
1712
+ if (input.interactiveToolCallResult) {
1713
+ return createToolMessage([
1714
+ {
1715
+ type: "toolResultPart",
1716
+ toolCallId: input.interactiveToolCallResult.toolCallId,
1717
+ toolName: input.interactiveToolCallResult.toolName,
1718
+ contents: [{ type: "textPart", text: input.interactiveToolCallResult.text }]
1719
+ }
1720
+ ]);
1721
+ }
1722
+ throw new Error("Input message is undefined");
1723
+ }
1724
+
1725
+ // src/states/preparing-for-step.ts
1726
+ async function preparingForStepLogic({
1727
+ setting,
1728
+ checkpoint
1729
+ }) {
1730
+ return startGeneration(setting, checkpoint, {
1731
+ messages: checkpoint.messages
1732
+ });
1733
+ }
1734
+ async function resolvingImageFileLogic({
1735
+ setting,
1736
+ checkpoint,
1737
+ step
1738
+ }) {
1739
+ if (!step?.toolCall || !step?.toolResult) {
1740
+ throw new Error("No tool call or tool result found");
1741
+ }
1742
+ const { id, toolName } = step.toolCall;
1743
+ const { result } = step.toolResult;
1744
+ const textParts = result.filter((part) => part.type === "textPart");
1745
+ const files = [];
1746
+ for (const textPart of textParts) {
1747
+ let imageInfo;
1748
+ try {
1749
+ imageInfo = JSON.parse(textPart.text);
1750
+ } catch {
1751
+ files.push({
1752
+ type: "textPart",
1753
+ text: textPart.text
1754
+ });
1755
+ continue;
1756
+ }
1757
+ const { path: path2, mimeType, size } = imageInfo;
1758
+ const file = await readFile(path2).then((buffer) => ({
1759
+ encodedData: buffer.toString("base64"),
1760
+ mimeType,
1761
+ size
1762
+ }));
1763
+ files.push({
1764
+ type: "imageInlinePart",
1765
+ encodedData: file.encodedData,
1766
+ mimeType: file.mimeType
1767
+ });
1768
+ }
1769
+ return finishToolCall(setting, checkpoint, {
1770
+ newMessages: [
1771
+ createToolMessage([
1772
+ {
1773
+ type: "toolResultPart",
1774
+ toolCallId: id,
1775
+ toolName,
1776
+ contents: files
1777
+ }
1778
+ ])
1779
+ ]
1780
+ });
1781
+ }
1782
+ async function resolvingPdfFileLogic({
1783
+ setting,
1784
+ checkpoint,
1785
+ step
1786
+ }) {
1787
+ if (!step?.toolCall || !step?.toolResult) {
1788
+ throw new Error("No tool call or tool result found");
1789
+ }
1790
+ const { id, toolName } = step.toolCall;
1791
+ const { result } = step.toolResult;
1792
+ const textParts = result.filter((part) => part.type === "textPart");
1793
+ const files = [];
1794
+ for (const textPart of textParts) {
1795
+ let pdfInfo;
1796
+ try {
1797
+ pdfInfo = JSON.parse(textPart.text);
1798
+ } catch {
1799
+ files.push({
1800
+ type: "textPart",
1801
+ text: textPart.text
1802
+ });
1803
+ continue;
1804
+ }
1805
+ const { path: path2, mimeType, size } = pdfInfo;
1806
+ const file = await readFile(path2).then((buffer) => ({
1807
+ encodedData: buffer.toString("base64"),
1808
+ mimeType,
1809
+ size
1810
+ }));
1811
+ files.push({
1812
+ type: "fileInlinePart",
1813
+ encodedData: file.encodedData,
1814
+ mimeType: file.mimeType
1815
+ });
1816
+ }
1817
+ return finishToolCall(setting, checkpoint, {
1818
+ newMessages: [
1819
+ createToolMessage([
1820
+ {
1821
+ type: "toolResultPart",
1822
+ toolCallId: id,
1823
+ toolName,
1824
+ contents: [
1825
+ {
1826
+ type: "textPart",
1827
+ text: "User uploads PDF file as follows."
1828
+ }
1829
+ ]
1830
+ }
1831
+ ]),
1832
+ createUserMessage(files)
1833
+ ]
1834
+ });
1835
+ }
1836
+
1837
+ // src/states/resolving-tool-result.ts
1838
+ async function resolvingToolResultLogic({
1839
+ setting,
1840
+ checkpoint,
1841
+ step
1842
+ }) {
1843
+ if (!step?.toolCall || !step?.toolResult) {
1844
+ throw new Error("No tool call or tool result found");
1845
+ }
1846
+ const { id, toolName } = step.toolCall;
1847
+ const { result } = step.toolResult;
1848
+ return finishToolCall(setting, checkpoint, {
1849
+ newMessages: [
1850
+ createToolMessage([
1851
+ {
1852
+ type: "toolResultPart",
1853
+ toolCallId: id,
1854
+ toolName,
1855
+ contents: result.filter(
1856
+ (part) => part.type === "textPart" || part.type === "imageInlinePart"
1857
+ )
1858
+ }
1859
+ ])
1860
+ ]
1861
+ });
1862
+ }
1863
+
1864
+ // src/states/resolving-thought.ts
1865
+ async function resolvingThoughtLogic(context) {
1866
+ return resolvingToolResultLogic(context);
1867
+ }
1868
+
1869
+ // src/runtime-state-machine.ts
1870
+ var runtimeStateMachine = setup({
1871
+ types: {
1872
+ input: {},
1873
+ context: {},
1874
+ events: {}
1875
+ }
1876
+ }).createMachine({
1877
+ /** @xstate-layout N4IgpgJg5mDOIC5QCUCuA7AdASXQSwBcBiWAgQwCcC10BtABgF1FQAHAe1kL3fRZAAeiAKz0AzJgDsAJgAsksZNlixs+gDZZAGhABPRIszCAjGIAcY4crPHhJyQF8HOmpgAKFMK0p50UAGLsFADKBF4k5FQA4mDoYBRkBDx0TPwcXEm8-EIIZmaymPRK8saSopL00tI6+gjq9JjSltLG9HnqZkqdTi4YmDFxCUl+ACrs7AA2AMJkExNEngQUugzMSCDp3FnrOcam0pgAnHbS9GeSZsIq6jWIh2KHUsYd9MbSwl2S6j0grgPxiV8UDGkxmcyIAGNZhMQRNVmlOFs+DtEPt1Jg3odpGVbFcrLcENIzOjbGYipIZMpnmYfn9YgDhsDxtNoZDobgwgkIUkAG5gWHw9abTLI0C7ImSTDqYTY2S45TCCwE54HUr1WRXSqHcRVWl9f5DIGwsHzKFzAAiYAmYCgiTAgrYiJF2VRYnoj1ehwskkOZTEz2EBMMJnMFnezxUF2+zl+fRNRuZCzgkz5sOQcFQEwIDo2TuSLoQpWJUvowl9Flk0sqBLlZik2Mkpjyan90d6WHjo0TnlgKf5AAt2KgoP3s6khXntmLUT6JL6PkoFJX1MZtHoRKIpdrK3sqorpG3Yx3oQnJknexM+W4IAAzfx4a054X5lGFn2PMTYlSyWQH32WAl1DKKV1Q6L1V1EWQ9WPOZT3mHs+2wABbMgYHvR9x0dDIX2nN8zEeOVjGORsmgsMQCTJYRMGJORwP9MwDxpGNXE7Jkz0SMIkNYAgpnYLjrRFJ9J1FQQZzJTBPxUfDDjlN1OgJIkSUVUtDlXCpsUPVx0wvHk4O0zNiBvXw8FgftjWhITsKnUTCU-SU92JMlfSaGtjDrGQKSbfJxGeaDMG0lMjUHYdRyIIz8FM8y5kspECyabFGneRz3RkN011qOwGnUbcVzeJKDz8gLLyBa87wfMAwuMyLmRNGLnVfeL7KSl5nPI9c6mA9RQPwmwNVLQrk2KvxkNQsB0Iq8KTLMmqLMw3MrJEnJGsSxUWtSgkfSU-JDmIqNKj8g1AT8Gh9KzSE+NYASwBoOqcJs+K61sDo5SKBifwU4tSRUtTKi+KDmLjE9hvQTkyG5PBU0TUh2FYGgACFdA5AFwchyZbus3YyklYRst-DUlDEaU2tqFUMS+NyPmlPZDiAvzWMta1bTCCIYfh3QGZtO10cWmcLiOQnG3qHHiSDbGvM-Ex1EjYk-PvCL+yBUJwghXhhlQfl2AAOTAAQCCV1hubiqxjCMRUZXMGSvVUZV6A1LcuorDp8I0WWqoVvx9ZZ2GMARgBRAQITASBIAAWTIAR9dgQ2Gs0Ki8nyK4bCuDVRZNzRwxse4GK6pwY3QdgIDgfgaARBaCxUBosU0cw5TLUiCQAWlkR4nPdbVCeyld-vbHB8AIUvYtfRQ6yr6xa6xcwCTLaiadj1dKxk1phD8jwvB8PxAhCMJWAH+rcKAyuyVaa5Wi+KeW9njV59xpeDvpQ0u1BaFd7u3Y2keDpO7LW2FDLc+Z6AnsPEO4ZYAxghMOCL8MaojsJKYi8cHZ5C9EGNoRg1CdH3GcZeYD-KDV0o-CYp1+4TjLg1cQkp-SfjDE9Ew1R2o-hNnsUs1MfR-UuANHSQUhwjmIVhQeuFTg-ilF8GUblTgKDoRlBQhQJEaiJMnfCHDAp+FKuNKBPNCSlgaOIeQttWxS0DO1bKdY9HvH9D+FotMcFFXwVAEaaFyrqLirbBo1M7KvFUDJCiRJGgalUM3LEMk5R30GEdKAJ0MxZicWQlQEklAyillWVoZgUF1isG0MoDEsF0yBnYkGyNeQa0mNE3CtgiIYnEEBToFwvS+mVPkU20l8JWG1OIHJsE-AcyZmAEpNlbBqEwLo7yVRbY3HatPfCXUOgfCsGSTQmk+hyymorbevSloykeFYCkrxfqrmJiIaRRQ7JbP8Q8PyoQYasEgGsxA2JWiNB-jjdQTRqb1IkP6OwRF8KMSAbnBwQA */
1878
+ id: "Run",
1879
+ initial: "Init",
1880
+ context: ({ input }) => ({
1881
+ setting: input.setting,
1882
+ checkpoint: input.initialCheckpoint,
1883
+ eventListener: input.eventListener,
1884
+ skillManagers: input.skillManagers
1885
+ }),
1886
+ states: {
1887
+ Init: {
1888
+ on: {
1889
+ startRun: {
1890
+ target: "PreparingForStep",
1891
+ actions: assign({
1892
+ checkpoint: ({ event }) => ({
1893
+ ...event.initialCheckpoint,
1894
+ messages: [...event.initialCheckpoint.messages, ...event.inputMessages],
1895
+ status: "proceeding"
1896
+ })
1897
+ })
1898
+ }
1899
+ }
1900
+ },
1901
+ PreparingForStep: {
1902
+ on: {
1903
+ startGeneration: {
1904
+ target: "GeneratingToolCall",
1905
+ actions: assign({
1906
+ step: ({ context, event }) => ({
1907
+ stepNumber: context.checkpoint.stepNumber,
1908
+ newMessages: [],
1909
+ usage: createEmptyUsage(),
1910
+ startedAt: event.timestamp
1911
+ })
1912
+ })
1913
+ }
1914
+ }
1915
+ },
1916
+ GeneratingToolCall: {
1917
+ on: {
1918
+ retry: {
1919
+ target: "FinishingStep",
1920
+ actions: assign({
1921
+ checkpoint: ({ context, event }) => ({
1922
+ ...context.checkpoint,
1923
+ messages: [...context.checkpoint.messages, ...event.newMessages],
1924
+ usage: sumUsage(context.checkpoint.usage, event.usage)
1925
+ }),
1926
+ step: ({ context, event }) => ({
1927
+ ...context.step,
1928
+ newMessages: event.newMessages,
1929
+ usage: sumUsage(context.step.usage, event.usage)
1930
+ })
1931
+ })
1932
+ },
1933
+ callTool: {
1934
+ target: "CallingTool",
1935
+ actions: assign({
1936
+ checkpoint: ({ context, event }) => ({
1937
+ ...context.checkpoint,
1938
+ messages: [...context.checkpoint.messages, event.newMessage],
1939
+ usage: sumUsage(context.checkpoint.usage, event.usage)
1940
+ }),
1941
+ step: ({ context, event }) => ({
1942
+ ...context.step,
1943
+ newMessages: [event.newMessage],
1944
+ toolCall: event.toolCall,
1945
+ usage: sumUsage(context.step.usage, event.usage)
1946
+ })
1947
+ })
1948
+ },
1949
+ callInteractiveTool: {
1950
+ target: "CallingInteractiveTool",
1951
+ actions: assign({
1952
+ checkpoint: ({ context, event }) => ({
1953
+ ...context.checkpoint,
1954
+ messages: [...context.checkpoint.messages, event.newMessage],
1955
+ usage: sumUsage(context.checkpoint.usage, event.usage)
1956
+ }),
1957
+ step: ({ context, event }) => ({
1958
+ ...context.step,
1959
+ newMessages: [event.newMessage],
1960
+ toolCall: event.toolCall,
1961
+ usage: sumUsage(context.step.usage, event.usage)
1962
+ })
1963
+ })
1964
+ },
1965
+ callDelegate: {
1966
+ target: "CallingDelegate",
1967
+ actions: assign({
1968
+ checkpoint: ({ context, event }) => ({
1969
+ ...context.checkpoint,
1970
+ messages: [...context.checkpoint.messages, event.newMessage],
1971
+ usage: sumUsage(context.checkpoint.usage, event.usage)
1972
+ }),
1973
+ step: ({ context, event }) => ({
1974
+ ...context.step,
1975
+ newMessages: [event.newMessage],
1976
+ toolCall: event.toolCall,
1977
+ usage: sumUsage(context.step.usage, event.usage)
1978
+ })
1979
+ })
1980
+ }
1981
+ }
1982
+ },
1983
+ CallingTool: {
1984
+ on: {
1985
+ resolveToolResult: {
1986
+ target: "ResolvingToolResult",
1987
+ actions: assign({
1988
+ step: ({ context, event }) => ({
1989
+ ...context.step,
1990
+ toolResult: event.toolResult
1991
+ })
1992
+ })
1993
+ },
1994
+ resolveThought: {
1995
+ target: "ResolvingThought",
1996
+ actions: assign({
1997
+ step: ({ context, event }) => ({
1998
+ ...context.step,
1999
+ toolResult: event.toolResult
2000
+ })
2001
+ })
2002
+ },
2003
+ resolvePdfFile: {
2004
+ target: "ResolvingPdfFile",
2005
+ actions: assign({
2006
+ step: ({ context, event }) => ({
2007
+ ...context.step,
2008
+ toolResult: event.toolResult
2009
+ })
2010
+ })
2011
+ },
2012
+ resolveImageFile: {
2013
+ target: "ResolvingImageFile",
2014
+ actions: assign({
2015
+ step: ({ context, event }) => ({
2016
+ ...context.step,
2017
+ toolResult: event.toolResult
2018
+ })
2019
+ })
2020
+ },
2021
+ attemptCompletion: {
2022
+ target: "GeneratingRunResult",
2023
+ actions: assign({
2024
+ step: ({ context, event }) => ({
2025
+ ...context.step,
2026
+ toolResult: event.toolResult
2027
+ })
2028
+ })
2029
+ }
2030
+ }
2031
+ },
2032
+ ResolvingToolResult: {
2033
+ on: {
2034
+ finishToolCall: {
2035
+ target: "FinishingStep",
2036
+ actions: assign({
2037
+ checkpoint: ({ context, event }) => ({
2038
+ ...context.checkpoint,
2039
+ messages: [...context.checkpoint.messages, ...event.newMessages]
2040
+ }),
2041
+ step: ({ context, event }) => ({
2042
+ ...context.step,
2043
+ newMessages: [...context.step.newMessages, ...event.newMessages]
2044
+ })
2045
+ })
2046
+ }
2047
+ }
2048
+ },
2049
+ ResolvingThought: {
2050
+ on: {
2051
+ finishToolCall: {
2052
+ target: "FinishingStep",
2053
+ actions: assign({
2054
+ checkpoint: ({ context, event }) => ({
2055
+ ...context.checkpoint,
2056
+ messages: [...context.checkpoint.messages, ...event.newMessages]
2057
+ }),
2058
+ step: ({ context, event }) => ({
2059
+ ...context.step,
2060
+ newMessages: [...context.step.newMessages, ...event.newMessages]
2061
+ })
2062
+ })
2063
+ }
2064
+ }
2065
+ },
2066
+ ResolvingPdfFile: {
2067
+ on: {
2068
+ finishToolCall: {
2069
+ target: "FinishingStep",
2070
+ actions: assign({
2071
+ checkpoint: ({ context, event }) => ({
2072
+ ...context.checkpoint,
2073
+ messages: [...context.checkpoint.messages, ...event.newMessages]
2074
+ }),
2075
+ step: ({ context, event }) => ({
2076
+ ...context.step,
2077
+ newMessages: [...context.step.newMessages, ...event.newMessages]
2078
+ })
2079
+ })
2080
+ }
2081
+ }
2082
+ },
2083
+ ResolvingImageFile: {
2084
+ on: {
2085
+ finishToolCall: {
2086
+ target: "FinishingStep",
2087
+ actions: assign({
2088
+ checkpoint: ({ context, event }) => ({
2089
+ ...context.checkpoint,
2090
+ messages: [...context.checkpoint.messages, ...event.newMessages]
2091
+ }),
2092
+ step: ({ context, event }) => ({
2093
+ ...context.step,
2094
+ newMessages: [...context.step.newMessages, ...event.newMessages]
2095
+ })
2096
+ })
2097
+ }
2098
+ }
2099
+ },
2100
+ GeneratingRunResult: {
2101
+ on: {
2102
+ completeRun: {
2103
+ target: "Stopped",
2104
+ actions: assign({
2105
+ checkpoint: ({ event }) => event.checkpoint,
2106
+ step: ({ event }) => event.step
2107
+ })
2108
+ }
2109
+ }
2110
+ },
2111
+ CallingInteractiveTool: {
2112
+ on: {
2113
+ stopRunByInteractiveTool: {
2114
+ target: "Stopped",
2115
+ actions: assign({
2116
+ checkpoint: ({ event }) => event.checkpoint,
2117
+ step: ({ event }) => event.step
2118
+ })
2119
+ }
2120
+ }
2121
+ },
2122
+ CallingDelegate: {
2123
+ on: {
2124
+ stopRunByDelegate: {
2125
+ target: "Stopped",
2126
+ actions: assign({
2127
+ checkpoint: ({ event }) => event.checkpoint,
2128
+ step: ({ event }) => event.step
2129
+ })
2130
+ }
2131
+ }
2132
+ },
2133
+ FinishingStep: {
2134
+ on: {
2135
+ continueToNextStep: {
2136
+ target: "PreparingForStep",
2137
+ actions: assign({
2138
+ checkpoint: ({ event }) => event.nextCheckpoint,
2139
+ step: ({ event }) => event.step
2140
+ }),
2141
+ reenter: true
2142
+ },
2143
+ stopRunByExceededMaxSteps: {
2144
+ target: "Stopped",
2145
+ actions: assign({
2146
+ checkpoint: ({ event }) => event.checkpoint,
2147
+ step: ({ event }) => event.step
2148
+ })
2149
+ }
2150
+ }
2151
+ },
2152
+ Stopped: {
2153
+ type: "final"
2154
+ }
2155
+ }
2156
+ });
2157
+ var StateMachineLogics = {
2158
+ Init: initLogic,
2159
+ PreparingForStep: preparingForStepLogic,
2160
+ GeneratingToolCall: generatingToolCallLogic,
2161
+ CallingTool: callingToolLogic,
2162
+ ResolvingToolResult: resolvingToolResultLogic,
2163
+ ResolvingThought: resolvingThoughtLogic,
2164
+ ResolvingPdfFile: resolvingPdfFileLogic,
2165
+ ResolvingImageFile: resolvingImageFileLogic,
2166
+ GeneratingRunResult: generatingRunResultLogic,
2167
+ CallingInteractiveTool: callingInteractiveToolLogic,
2168
+ CallingDelegate: callingDelegateLogic,
2169
+ FinishingStep: finishingStepLogic
2170
+ };
2171
+ var PerstackConfigSchema = z.object({
2172
+ model: z.string().optional(),
2173
+ temperature: z.number().optional(),
2174
+ maxSteps: z.number().optional(),
2175
+ maxRetries: z.number().optional(),
2176
+ experts: z.record(
2177
+ z.string(),
2178
+ z.object({
2179
+ version: z.string().optional(),
2180
+ minRuntimeVersion: z.string().optional(),
2181
+ description: z.string().optional(),
2182
+ instruction: z.string(),
2183
+ skills: z.record(
2184
+ z.string(),
2185
+ z.discriminatedUnion("type", [
2186
+ z.object({
2187
+ type: z.literal("mcpStdioSkill"),
2188
+ description: z.string().optional(),
2189
+ rule: z.string().optional(),
2190
+ pick: z.array(z.string()).optional(),
2191
+ omit: z.array(z.string()).optional(),
2192
+ command: z.string(),
2193
+ packageName: z.string().optional(),
2194
+ args: z.array(z.string()).optional(),
2195
+ requiredEnv: z.array(z.string()).optional()
2196
+ }),
2197
+ z.object({
2198
+ type: z.literal("mcpSseSkill"),
2199
+ description: z.string().optional(),
2200
+ rule: z.string().optional(),
2201
+ pick: z.array(z.string()).optional(),
2202
+ omit: z.array(z.string()).optional(),
2203
+ endpoint: z.string()
2204
+ }),
2205
+ z.object({
2206
+ type: z.literal("interactiveSkill"),
2207
+ description: z.string().optional(),
2208
+ rule: z.string().optional(),
2209
+ tools: z.record(
2210
+ z.string(),
2211
+ z.object({
2212
+ description: z.string().optional(),
2213
+ inputJsonSchema: z.string()
2214
+ })
2215
+ )
2216
+ })
2217
+ ])
2218
+ ).optional(),
2219
+ delegates: z.array(z.string()).optional()
2220
+ })
2221
+ ).optional()
2222
+ });
71
2223
 
72
- "${o.name}" skill rules:
73
- ${o.rule}
74
- `.trim():t,"")}function mo(e,t){return e.delegates.reduce((o,r)=>{let a=t[r];return a?dedent`
75
- ${o}
2224
+ // src/runtime.ts
2225
+ async function run(runInput, options) {
2226
+ const runParams = RunParamsSchema.parse(runInput);
2227
+ const eventListener = options?.eventListener ?? defaultEventListener;
2228
+ const retrieveCheckpoint = options?.retrieveCheckpoint ?? defaultRetrieveCheckpoint;
2229
+ const storeCheckpoint = options?.storeCheckpoint ?? defaultStoreCheckpoint;
2230
+ const eventEmitter = new RunEventEmitter();
2231
+ eventEmitter.subscribe(eventListener);
2232
+ let { setting, checkpoint } = runParams;
2233
+ if (setting.workspace) {
2234
+ if (!path.isAbsolute(setting.workspace)) {
2235
+ throw new Error(`Workspace path must be absolute: ${setting.workspace}`);
2236
+ }
2237
+ process.chdir(setting.workspace);
2238
+ }
2239
+ await storeRunSetting(setting);
2240
+ while (true) {
2241
+ const { expertToRun, experts } = await setupExperts(setting);
2242
+ printRunSetting(expertToRun.name, experts, setting);
2243
+ const skillManagers = await getSkillManagers(expertToRun, experts);
2244
+ const runActor = createActor(runtimeStateMachine, {
2245
+ input: {
2246
+ setting: {
2247
+ ...setting,
2248
+ experts
2249
+ },
2250
+ initialCheckpoint: checkpoint ?? {
2251
+ id: createId(),
2252
+ runId: setting.runId,
2253
+ expert: {
2254
+ key: setting.expertKey,
2255
+ name: expertToRun.name,
2256
+ version: expertToRun.version
2257
+ },
2258
+ stepNumber: 1,
2259
+ status: "init",
2260
+ messages: [],
2261
+ usage: createEmptyUsage()
2262
+ },
2263
+ eventListener,
2264
+ skillManagers
2265
+ }
2266
+ });
2267
+ const runResultCheckpoint = await new Promise((resolve, reject) => {
2268
+ runActor.subscribe(async (runState) => {
2269
+ try {
2270
+ if (runState.value === "Stopped") {
2271
+ const { checkpoint: checkpoint2, skillManagers: skillManagers2 } = runState.context;
2272
+ if (!checkpoint2) {
2273
+ throw new Error("Checkpoint is undefined");
2274
+ }
2275
+ await closeSkillManagers(skillManagers2);
2276
+ resolve(checkpoint2);
2277
+ } else {
2278
+ const event = await StateMachineLogics[runState.value](runState.context);
2279
+ if ("checkpoint" in event) {
2280
+ await storeCheckpoint(event.checkpoint, event.timestamp);
2281
+ }
2282
+ await eventEmitter.emit(event);
2283
+ runActor.send(event);
2284
+ }
2285
+ } catch (error) {
2286
+ reject(error);
2287
+ }
2288
+ });
2289
+ runActor.start();
2290
+ });
2291
+ switch (runResultCheckpoint.status) {
2292
+ case "completed": {
2293
+ if (runResultCheckpoint.delegatedBy) {
2294
+ const { messages, delegatedBy } = runResultCheckpoint;
2295
+ const { expert, toolCallId, toolName, checkpointId } = delegatedBy;
2296
+ const delegateResultMessage = messages[messages.length - 1];
2297
+ if (delegateResultMessage.type !== "expertMessage") {
2298
+ throw new Error("Delegation error: delegation result message is incorrect");
2299
+ }
2300
+ const delegateText = delegateResultMessage.contents.find(
2301
+ (content) => content.type === "textPart"
2302
+ );
2303
+ if (!delegateText) {
2304
+ throw new Error("Delegation error: delegation result message does not contain a text");
2305
+ }
2306
+ setting = {
2307
+ ...setting,
2308
+ expertKey: expert.key,
2309
+ input: {
2310
+ interactiveToolCallResult: {
2311
+ toolCallId,
2312
+ toolName,
2313
+ text: delegateText.text
2314
+ }
2315
+ }
2316
+ };
2317
+ checkpoint = {
2318
+ ...await retrieveCheckpoint(setting.runId, checkpointId),
2319
+ id: createId(),
2320
+ stepNumber: runResultCheckpoint.stepNumber + 1,
2321
+ usage: runResultCheckpoint.usage
2322
+ };
2323
+ break;
2324
+ }
2325
+ return runResultCheckpoint;
2326
+ }
2327
+ case "stoppedByInteractiveTool": {
2328
+ return runResultCheckpoint;
2329
+ }
2330
+ case "stoppedByDelegate": {
2331
+ if (!runResultCheckpoint.delegateTo) {
2332
+ throw new Error("Delegation error: delegate to is undefined");
2333
+ }
2334
+ const { expert, toolCallId, toolName, query } = runResultCheckpoint.delegateTo;
2335
+ setting = {
2336
+ ...setting,
2337
+ expertKey: expert.key,
2338
+ input: {
2339
+ text: query
2340
+ }
2341
+ };
2342
+ checkpoint = {
2343
+ id: createId(),
2344
+ runId: setting.runId,
2345
+ status: "init",
2346
+ stepNumber: runResultCheckpoint.stepNumber + 1,
2347
+ messages: [],
2348
+ expert: {
2349
+ key: expert.key,
2350
+ name: expert.name,
2351
+ version: expert.version
2352
+ },
2353
+ delegatedBy: {
2354
+ expert: {
2355
+ key: expertToRun.key,
2356
+ name: expertToRun.name,
2357
+ version: expertToRun.version
2358
+ },
2359
+ toolCallId,
2360
+ toolName,
2361
+ checkpointId: runResultCheckpoint.id
2362
+ },
2363
+ usage: runResultCheckpoint.usage
2364
+ };
2365
+ break;
2366
+ }
2367
+ case "stoppedByExceededMaxSteps": {
2368
+ return runResultCheckpoint;
2369
+ }
2370
+ case "stoppedByError": {
2371
+ return runResultCheckpoint;
2372
+ }
2373
+ default:
2374
+ throw new Error("Run stopped by unknown reason");
2375
+ }
2376
+ }
2377
+ }
2378
+ async function setupExperts(setting) {
2379
+ const { expertKey } = setting;
2380
+ const experts = { ...setting.experts };
2381
+ const expertToRun = await resolveExpertToRun(expertKey, experts);
2382
+ for (const delegateName of expertToRun.delegates) {
2383
+ const delegate = await resolveExpertToRun(delegateName, experts);
2384
+ if (!delegate) {
2385
+ throw new Error(`Delegate ${delegateName} not found`);
2386
+ }
2387
+ }
2388
+ return { expertToRun, experts };
2389
+ }
2390
+ function printRunSetting(expertName, experts, setting) {
2391
+ console.log("\u{1F99C} Starting Perstack \u{1F99C}");
2392
+ console.log(`Expert To Run: ${expertName}`);
2393
+ console.log(`Experts: ${Object.keys(experts).join(", ")}`);
2394
+ console.log(`Model: ${setting.model}`);
2395
+ console.log(`Temperature: ${setting.temperature}`);
2396
+ console.log(`Max Steps: ${setting.maxSteps}`);
2397
+ console.log(`Max Retries: ${setting.maxRetries}`);
2398
+ if (setting.input.text) {
2399
+ console.log(`Query: ${setting.input.text}`);
2400
+ }
2401
+ if (setting.input.interactiveToolCallResult) {
2402
+ console.log(`Tool: ${setting.input.interactiveToolCallResult.toolName}`);
2403
+ console.log(`Tool Call ID: ${setting.input.interactiveToolCallResult.toolCallId}`);
2404
+ console.log(`Tool Result: ${setting.input.interactiveToolCallResult.text}`);
2405
+ }
2406
+ }
2407
+ async function storeRunSetting(setting) {
2408
+ const runDir = getRunDir(setting.runId);
2409
+ if (existsSync(runDir)) {
2410
+ const runSettingPath = path.resolve(runDir, "run-setting.json");
2411
+ const runSetting = JSON.parse(await readFile(runSettingPath, "utf-8"));
2412
+ runSetting.updatedAt = Date.now();
2413
+ await writeFile(runSettingPath, JSON.stringify(runSetting, null, 2), "utf-8");
2414
+ } else {
2415
+ await mkdir(runDir, { recursive: true });
2416
+ await writeFile(
2417
+ path.resolve(runDir, "run-setting.json"),
2418
+ JSON.stringify(setting, null, 2),
2419
+ "utf-8"
2420
+ );
2421
+ }
2422
+ }
2423
+ function getRunDir(runId) {
2424
+ return `${process.cwd()}/perstack/runs/${runId}`;
2425
+ }
2426
+ async function parseConfig(config) {
2427
+ const toml = TOML.parse(config ?? "");
2428
+ return PerstackConfigSchema.parse(toml);
2429
+ }
2430
+ var RunInputSchema = z.object({
2431
+ expertKey: z.string(),
2432
+ query: z.string(),
2433
+ options: z.object({
2434
+ config: z.string().optional(),
2435
+ model: z.string().optional(),
2436
+ temperature: z.string().optional().transform((value) => {
2437
+ if (value === void 0) {
2438
+ return void 0;
2439
+ }
2440
+ const parsedValue = Number.parseFloat(value);
2441
+ if (Number.isNaN(parsedValue)) {
2442
+ return void 0;
2443
+ }
2444
+ return parsedValue;
2445
+ }),
2446
+ maxSteps: z.string().optional().transform((value) => {
2447
+ if (value === void 0) {
2448
+ return void 0;
2449
+ }
2450
+ const parsedValue = Number.parseInt(value);
2451
+ if (Number.isNaN(parsedValue)) {
2452
+ return void 0;
2453
+ }
2454
+ return parsedValue;
2455
+ }),
2456
+ maxRetries: z.string().optional().transform((value) => {
2457
+ if (value === void 0) {
2458
+ return void 0;
2459
+ }
2460
+ const parsedValue = Number.parseInt(value);
2461
+ if (Number.isNaN(parsedValue)) {
2462
+ return void 0;
2463
+ }
2464
+ return parsedValue;
2465
+ }),
2466
+ runId: z.string().optional()
2467
+ })
2468
+ });
76
2469
 
77
- About "${a.name}":
78
- ${a.description}
79
- `.trim():o},"")}async function tt({setting:e,checkpoint:t}){let{expertKey:o,experts:r}=e,a=r[o];switch(t.status){case "init":return ne(e,t,{initialCheckpoint:t,inputMessages:[Xe(a,r),et(e.input)]});default:return ne(e,t,{initialCheckpoint:t,inputMessages:[et(e.input)]})}}function et(e){if(e.text)return F([{type:"textPart",text:e.text}]);if(e.interactiveToolCallResult)return C([{type:"toolResultPart",toolCallId:e.interactiveToolCallResult.toolCallId,toolName:e.interactiveToolCallResult.toolName,contents:[{type:"textPart",text:e.interactiveToolCallResult.text}]}]);throw new Error("Input message is undefined")}async function ot({setting:e,checkpoint:t}){return Te(e,t,{messages:t.messages})}async function nt({setting:e,checkpoint:t,step:o}){if(!o?.toolCall||!o?.toolResult)throw new Error("No tool call or tool result found");let{id:r,toolName:a}=o.toolCall,{result:i}=o.toolResult,c=i.filter(u=>u.type==="textPart"),s=[];for(let u of c){let h;try{h=JSON.parse(u.text);}catch{s.push({type:"textPart",text:u.text});continue}let{path:d,mimeType:P,size:R}=h,f=await readFile(d).then(S=>({encodedData:S.toString("base64"),mimeType:P,size:R}));s.push({type:"imageInlinePart",encodedData:f.encodedData,mimeType:f.mimeType});}return $(e,t,{newMessages:[C([{type:"toolResultPart",toolCallId:r,toolName:a,contents:s}])]})}async function rt({setting:e,checkpoint:t,step:o}){if(!o?.toolCall||!o?.toolResult)throw new Error("No tool call or tool result found");let{id:r,toolName:a}=o.toolCall,{result:i}=o.toolResult,c=i.filter(u=>u.type==="textPart"),s=[];for(let u of c){let h;try{h=JSON.parse(u.text);}catch{s.push({type:"textPart",text:u.text});continue}let{path:d,mimeType:P,size:R}=h,f=await readFile(d).then(S=>({encodedData:S.toString("base64"),mimeType:P,size:R}));s.push({type:"fileInlinePart",encodedData:f.encodedData,mimeType:f.mimeType});}return $(e,t,{newMessages:[C([{type:"toolResultPart",toolCallId:r,toolName:a,contents:[{type:"textPart",text:"User uploads PDF file as follows."}]}]),F(s)]})}async function X({setting:e,checkpoint:t,step:o}){if(!o?.toolCall||!o?.toolResult)throw new Error("No tool call or tool result found");let{id:r,toolName:a}=o.toolCall,{result:i}=o.toolResult;return $(e,t,{newMessages:[C([{type:"toolResultPart",toolCallId:r,toolName:a,contents:i.filter(c=>c.type==="textPart"||c.type==="imageInlinePart")}])]})}async function st(e){return X(e)}var at=setup({types:{input:{},context:{},events:{}}}).createMachine({id:"Run",initial:"Init",context:({input:e})=>({setting:e.setting,checkpoint:e.initialCheckpoint,eventListener:e.eventListener,skillManagers:e.skillManagers}),states:{Init:{on:{startRun:{target:"PreparingForStep",actions:assign({checkpoint:({event:e})=>({...e.initialCheckpoint,messages:[...e.initialCheckpoint.messages,...e.inputMessages],status:"proceeding"})})}}},PreparingForStep:{on:{startGeneration:{target:"GeneratingToolCall",actions:assign({step:({context:e,event:t})=>({stepNumber:e.checkpoint.stepNumber,newMessages:[],usage:H(),startedAt:t.timestamp})})}}},GeneratingToolCall:{on:{retry:{target:"FinishingStep",actions:assign({checkpoint:({context:e,event:t})=>({...e.checkpoint,messages:[...e.checkpoint.messages,...t.newMessages],usage:v(e.checkpoint.usage,t.usage)}),step:({context:e,event:t})=>({...e.step,newMessages:t.newMessages,usage:v(e.step.usage,t.usage)})})},callTool:{target:"CallingTool",actions:assign({checkpoint:({context:e,event:t})=>({...e.checkpoint,messages:[...e.checkpoint.messages,t.newMessage],usage:v(e.checkpoint.usage,t.usage)}),step:({context:e,event:t})=>({...e.step,newMessages:[t.newMessage],toolCall:t.toolCall,usage:v(e.step.usage,t.usage)})})},callInteractiveTool:{target:"CallingInteractiveTool",actions:assign({checkpoint:({context:e,event:t})=>({...e.checkpoint,messages:[...e.checkpoint.messages,t.newMessage],usage:v(e.checkpoint.usage,t.usage)}),step:({context:e,event:t})=>({...e.step,newMessages:[t.newMessage],toolCall:t.toolCall,usage:v(e.step.usage,t.usage)})})},callDelegate:{target:"CallingDelegate",actions:assign({checkpoint:({context:e,event:t})=>({...e.checkpoint,messages:[...e.checkpoint.messages,t.newMessage],usage:v(e.checkpoint.usage,t.usage)}),step:({context:e,event:t})=>({...e.step,newMessages:[t.newMessage],toolCall:t.toolCall,usage:v(e.step.usage,t.usage)})})}}},CallingTool:{on:{resolveToolResult:{target:"ResolvingToolResult",actions:assign({step:({context:e,event:t})=>({...e.step,toolResult:t.toolResult})})},resolveThought:{target:"ResolvingThought",actions:assign({step:({context:e,event:t})=>({...e.step,toolResult:t.toolResult})})},resolvePdfFile:{target:"ResolvingPdfFile",actions:assign({step:({context:e,event:t})=>({...e.step,toolResult:t.toolResult})})},resolveImageFile:{target:"ResolvingImageFile",actions:assign({step:({context:e,event:t})=>({...e.step,toolResult:t.toolResult})})},attemptCompletion:{target:"GeneratingRunResult",actions:assign({step:({context:e,event:t})=>({...e.step,toolResult:t.toolResult})})}}},ResolvingToolResult:{on:{finishToolCall:{target:"FinishingStep",actions:assign({checkpoint:({context:e,event:t})=>({...e.checkpoint,messages:[...e.checkpoint.messages,...t.newMessages]}),step:({context:e,event:t})=>({...e.step,newMessages:[...e.step.newMessages,...t.newMessages]})})}}},ResolvingThought:{on:{finishToolCall:{target:"FinishingStep",actions:assign({checkpoint:({context:e,event:t})=>({...e.checkpoint,messages:[...e.checkpoint.messages,...t.newMessages]}),step:({context:e,event:t})=>({...e.step,newMessages:[...e.step.newMessages,...t.newMessages]})})}}},ResolvingPdfFile:{on:{finishToolCall:{target:"FinishingStep",actions:assign({checkpoint:({context:e,event:t})=>({...e.checkpoint,messages:[...e.checkpoint.messages,...t.newMessages]}),step:({context:e,event:t})=>({...e.step,newMessages:[...e.step.newMessages,...t.newMessages]})})}}},ResolvingImageFile:{on:{finishToolCall:{target:"FinishingStep",actions:assign({checkpoint:({context:e,event:t})=>({...e.checkpoint,messages:[...e.checkpoint.messages,...t.newMessages]}),step:({context:e,event:t})=>({...e.step,newMessages:[...e.step.newMessages,...t.newMessages]})})}}},GeneratingRunResult:{on:{completeRun:{target:"Stopped",actions:assign({checkpoint:({event:e})=>e.checkpoint,step:({event:e})=>e.step})}}},CallingInteractiveTool:{on:{stopRunByInteractiveTool:{target:"Stopped",actions:assign({checkpoint:({event:e})=>e.checkpoint,step:({event:e})=>e.step})}}},CallingDelegate:{on:{stopRunByDelegate:{target:"Stopped",actions:assign({checkpoint:({event:e})=>e.checkpoint,step:({event:e})=>e.step})}}},FinishingStep:{on:{continueToNextStep:{target:"PreparingForStep",actions:assign({checkpoint:({event:e})=>e.nextCheckpoint,step:({event:e})=>e.step}),reenter:true},stopRunByExceededMaxSteps:{target:"Stopped",actions:assign({checkpoint:({event:e})=>e.checkpoint,step:({event:e})=>e.step})}}},Stopped:{type:"final"}}}),it={Init:tt,PreparingForStep:ot,GeneratingToolCall:Qe,CallingTool:Ve,ResolvingToolResult:X,ResolvingThought:st,ResolvingPdfFile:rt,ResolvingImageFile:nt,GeneratingRunResult:He,CallingInteractiveTool:Je,CallingDelegate:qe,FinishingStep:Ye};var lt=z$1.object({model:z$1.string().optional(),temperature:z$1.number().optional(),maxSteps:z$1.number().optional(),maxRetries:z$1.number().optional(),experts:z$1.record(z$1.string(),z$1.object({version:z$1.string().optional(),minRuntimeVersion:z$1.string().optional(),description:z$1.string().optional(),instruction:z$1.string(),skills:z$1.record(z$1.string(),z$1.discriminatedUnion("type",[z$1.object({type:z$1.literal("mcpStdioSkill"),description:z$1.string().optional(),rule:z$1.string().optional(),pick:z$1.array(z$1.string()).optional(),omit:z$1.array(z$1.string()).optional(),command:z$1.string(),packageName:z$1.string().optional(),args:z$1.array(z$1.string()).optional(),requiredEnv:z$1.array(z$1.string()).optional()}),z$1.object({type:z$1.literal("mcpSseSkill"),description:z$1.string().optional(),rule:z$1.string().optional(),pick:z$1.array(z$1.string()).optional(),omit:z$1.array(z$1.string()).optional(),endpoint:z$1.string()}),z$1.object({type:z$1.literal("interactiveSkill"),description:z$1.string().optional(),rule:z$1.string().optional(),tools:z$1.record(z$1.string(),z$1.object({description:z$1.string().optional(),inputJsonSchema:z$1.string()}))})])).optional(),delegates:z$1.array(z$1.string()).optional()})).optional()});async function Br(e,t){let o=ke.parse(e),r=t?.eventListener??se,a=t?.retrieveCheckpoint??De,i=t?.storeCheckpoint??Oe,c=new V;c.subscribe(r);let{setting:s,checkpoint:u}=o;if(s.workspace){if(!pe.isAbsolute(s.workspace))throw new Error(`Workspace path must be absolute: ${s.workspace}`);process.chdir(s.workspace);}for(await Po(s);;){let{expertToRun:h,experts:d}=await Ro(s);So(h.name,d,s);let P=await Le(h,d),R=createActor(at,{input:{setting:{...s,experts:d},initialCheckpoint:u??{id:createId(),runId:s.runId,expert:{key:s.expertKey,name:h.name,version:h.version},stepNumber:1,status:"init",messages:[],usage:H()},eventListener:r,skillManagers:P}}),f=await new Promise((S,j)=>{R.subscribe(async M=>{try{if(M.value==="Stopped"){let{checkpoint:T,skillManagers:ee}=M.context;if(!T)throw new Error("Checkpoint is undefined");await Ge(ee),S(T);}else {let T=await it[M.value](M.context);"checkpoint"in T&&await i(T.checkpoint,T.timestamp),await c.emit(T),R.send(T);}}catch(T){j(T);}}),R.start();});switch(f.status){case "completed":{if(f.delegatedBy){let{messages:S,delegatedBy:j}=f,{expert:M,toolCallId:T,toolName:ee,checkpointId:ct}=j,ce=S[S.length-1];if(ce.type!=="expertMessage")throw new Error("Delegation error: delegation result message is incorrect");let me=ce.contents.find(mt=>mt.type==="textPart");if(!me)throw new Error("Delegation error: delegation result message does not contain a text");s={...s,expertKey:M.key,input:{interactiveToolCallResult:{toolCallId:T,toolName:ee,text:me.text}}},u={...await a(s.runId,ct),id:createId(),stepNumber:f.stepNumber+1,usage:f.usage};break}return f}case "stoppedByInteractiveTool":return f;case "stoppedByDelegate":{if(!f.delegateTo)throw new Error("Delegation error: delegate to is undefined");let{expert:S,toolCallId:j,toolName:M,query:T}=f.delegateTo;s={...s,expertKey:S.key,input:{text:T}},u={id:createId(),runId:s.runId,status:"init",stepNumber:f.stepNumber+1,messages:[],expert:{key:S.key,name:S.name,version:S.version},delegatedBy:{expert:{key:h.key,name:h.name,version:h.version},toolCallId:j,toolName:M,checkpointId:f.id},usage:f.usage};break}case "stoppedByExceededMaxSteps":return f;case "stoppedByError":return f;default:throw new Error("Run stopped by unknown reason")}}}async function Ro(e){let{expertKey:t}=e,o={...e.experts},r=await ie(t,o);for(let a of r.delegates)if(!await ie(a,o))throw new Error(`Delegate ${a} not found`);return {expertToRun:r,experts:o}}function So(e,t,o){console.log("\u{1F99C} Starting Perstack \u{1F99C}"),console.log(`Expert To Run: ${e}`),console.log(`Experts: ${Object.keys(t).join(", ")}`),console.log(`Model: ${o.model}`),console.log(`Temperature: ${o.temperature}`),console.log(`Max Steps: ${o.maxSteps}`),console.log(`Max Retries: ${o.maxRetries}`),o.input.text&&console.log(`Query: ${o.input.text}`),o.input.interactiveToolCallResult&&(console.log(`Tool: ${o.input.interactiveToolCallResult.toolName}`),console.log(`Tool Call ID: ${o.input.interactiveToolCallResult.toolCallId}`),console.log(`Tool Result: ${o.input.interactiveToolCallResult.text}`));}async function Po(e){let t=O(e.runId);if(existsSync(t)){let o=pe.resolve(t,"run-setting.json"),r=JSON.parse(await readFile(o,"utf-8"));r.updatedAt=Date.now(),await writeFile(o,JSON.stringify(r,null,2),"utf-8");}else await mkdir(t,{recursive:true}),await writeFile(pe.resolve(t,"run-setting.json"),JSON.stringify(e,null,2),"utf-8");}function O(e){return `${process.cwd()}/perstack/runs/${e}`}async function _r(e){let t=ko.parse(e??"");return lt.parse(t)}var Lr=z$1.object({expertKey:z$1.string(),query:z$1.string(),options:z$1.object({config:z$1.string().optional(),model:z$1.string().optional(),temperature:z$1.string().optional().transform(e=>{if(e===void 0)return;let t=Number.parseFloat(e);if(!Number.isNaN(t))return t}),maxSteps:z$1.string().optional().transform(e=>{if(e===void 0)return;let t=Number.parseInt(e);if(!Number.isNaN(t))return t}),maxRetries:z$1.string().optional().transform(e=>{if(e===void 0)return;let t=Number.parseInt(e);if(!Number.isNaN(t))return t}),runId:z$1.string().optional()})});export{oe as CheckpointSchema,Ft as CheckpointStatusSchema,wt as ExpertMessageSchema,J as ExpertSchema,Rt as FileBinaryPartSchema,Tt as FileInlinePartSchema,kt as FileUrlPartSchema,xt as ImageBinaryPartSchema,fe as ImageInlinePartSchema,yt as ImageUrlPartSchema,Ct as InstructionMessageSchema,q as InteractiveSkillSchema,ye as InteractiveToolSchema,K as McpSseSkillSchema,G as McpStdioSkillSchema,he as MessageSchema,lt as PerstackConfigSchema,Ae as RegistryV1ExpertsGetResponseSchema,Lr as RunInputSchema,ke as RunParamsSchema,it as StateMachineLogics,A as TextPartSchema,St as ToolCallPartSchema,It as ToolMessageSchema,Pt as ToolResultPartSchema,Nt as UsageSchema,vt as UserMessageSchema,Me as attemptCompletion,Pe as callDelegate,Se as callInteractiveTool,Re as callTool,be as completeRun,Fe as continueToNextStep,k as createEvent,se as defaultEventListener,D as expertKeyRegex,Mt as expertNameRegex,$ as finishToolCall,O as getRunDir,$t as maxNameLength,_r as parseConfig,jo as parseExpertKey,Ie as resolveImageFile,we as resolvePdfFile,ve as resolveThought,Ce as resolveToolResult,re as retry,Br as run,at as runtimeStateMachine,Uo as skillNameRegex,Te as startGeneration,ne as startRun,$e as stopRunByDelegate,Ne as stopRunByExceededMaxSteps,Ee as stopRunByInteractiveTool,Et as tagNameRegex,bt as versionRegex};//# sourceMappingURL=index.js.map
2470
+ export { CheckpointSchema, CheckpointStatusSchema, ExpertMessageSchema, ExpertSchema, FileBinaryPartSchema, FileInlinePartSchema, FileUrlPartSchema, ImageBinaryPartSchema, ImageInlinePartSchema, ImageUrlPartSchema, InstructionMessageSchema, InteractiveSkillSchema, InteractiveToolSchema, McpSseSkillSchema, McpStdioSkillSchema, MessageSchema, PerstackConfigSchema, RegistryV1ExpertsGetResponseSchema, RunInputSchema, RunParamsSchema, StateMachineLogics, TextPartSchema, ToolCallPartSchema, ToolMessageSchema, ToolResultPartSchema, UsageSchema, UserMessageSchema, attemptCompletion, callDelegate, callInteractiveTool, callTool, completeRun, continueToNextStep, createEvent, defaultEventListener, expertKeyRegex, expertNameRegex, finishToolCall, getRunDir, maxNameLength, parseConfig, parseExpertKey, resolveImageFile, resolvePdfFile, resolveThought, resolveToolResult, retry, run, runtimeStateMachine, skillNameRegex, startGeneration, startRun, stopRunByDelegate, stopRunByExceededMaxSteps, stopRunByInteractiveTool, tagNameRegex, versionRegex };
2471
+ //# sourceMappingURL=index.js.map
80
2472
  //# sourceMappingURL=index.js.map