@zibby/skills 0.1.10 → 0.1.11
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/function-skill.js +1 -1
- package/dist/index.js +4 -4
- package/dist/package.json +3 -3
- package/dist/skill-installer.js +1 -1
- package/dist/test-runner.js +1 -1
- package/package.json +3 -3
package/dist/function-skill.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createRequire as i}from"module";import{fileURLToPath as a}from"url";import{registerHandlers as u}from"@zibby/core/function-skill-registry.js";import{registerSkill as c}from"@zibby/workflow";var p=i(import.meta.url);function f(){try{return p.resolve("@zibby/core/function-bridge.js")}catch{return null}}var m=import.meta.url;function h(){let e=Error.prepareStackTrace;try{Error.prepareStackTrace=(l,o)=>o;let t=new Error().stack;for(let l=2;l<t.length;l++){let o=t[l].getFileName();if(o&&o!==m&&!o.startsWith("node:"))return o.startsWith("file://")?a(o):o}return null}finally{Error.prepareStackTrace=e}}function y(e){if(!e||typeof e!="object")return{type:"object",properties:{},required:[]};let r={},t=[];for(let[l,o]of Object.entries(e))if(typeof o=="string")r[l]={type:o},t.push(l);else{let{required:s,...n}=o;r[l]=n,s!==!1&&t.push(l)}return{type:"object",properties:r,required:t}}function v(e,r,t){if(typeof t.handler!="function")throw new Error(`Skill "${e}" must have a handler function`);let l={[e]:t.handler},o=[{name:e,description:t.description||"",input_schema:y(t.input)}];return u(e,l,o),{id:e,type:"function",serverName:e,allowedTools:[`mcp__${e}__*`],description:t.description||`Function skill: ${e}`,envKeys:[],tools:o,resolve(){let s=f();return s?{command:"node",args:[s,r,e]}:null}}}function k(e,r){return{id:e,type:"mcp",serverName:r.serverName||e,allowedTools:r.allowedTools||[`mcp__${r.serverName||e}__*`],description:r.description||`MCP skill: ${e}`,envKeys:r.envKeys||[],tools:r.tools||[],resolve:r.resolve,...r.cursorKey&&{cursorKey:r.cursorKey},...r.sessionEnvKey&&{sessionEnvKey:r.sessionEnvKey}}}function d(e,r){let t;if("handler"in r){if(typeof r.handler!="function")throw new Error(`Skill "${e}" must have a handler function`);let l=h();if(!l)throw new Error(`Could not resolve caller file for skill "${e}".`);t=v(e,l,r)}else if(typeof r.resolve=="function")t=k(e,r);else throw new Error(`Skill "${e}" must have either a handler (function skill) or resolve (MCP skill).`);return c(t),t}var S=d;export{S as functionSkill,d as skill};
|
|
1
|
+
import{createRequire as i}from"module";import{fileURLToPath as a}from"url";import{registerHandlers as u}from"@zibby/core/function-skill-registry.js";import{registerSkill as c}from"@zibby/agent-workflow";var p=i(import.meta.url);function f(){try{return p.resolve("@zibby/core/function-bridge.js")}catch{return null}}var m=import.meta.url;function h(){let e=Error.prepareStackTrace;try{Error.prepareStackTrace=(l,o)=>o;let t=new Error().stack;for(let l=2;l<t.length;l++){let o=t[l].getFileName();if(o&&o!==m&&!o.startsWith("node:"))return o.startsWith("file://")?a(o):o}return null}finally{Error.prepareStackTrace=e}}function y(e){if(!e||typeof e!="object")return{type:"object",properties:{},required:[]};let r={},t=[];for(let[l,o]of Object.entries(e))if(typeof o=="string")r[l]={type:o},t.push(l);else{let{required:s,...n}=o;r[l]=n,s!==!1&&t.push(l)}return{type:"object",properties:r,required:t}}function v(e,r,t){if(typeof t.handler!="function")throw new Error(`Skill "${e}" must have a handler function`);let l={[e]:t.handler},o=[{name:e,description:t.description||"",input_schema:y(t.input)}];return u(e,l,o),{id:e,type:"function",serverName:e,allowedTools:[`mcp__${e}__*`],description:t.description||`Function skill: ${e}`,envKeys:[],tools:o,resolve(){let s=f();return s?{command:"node",args:[s,r,e]}:null}}}function k(e,r){return{id:e,type:"mcp",serverName:r.serverName||e,allowedTools:r.allowedTools||[`mcp__${r.serverName||e}__*`],description:r.description||`MCP skill: ${e}`,envKeys:r.envKeys||[],tools:r.tools||[],resolve:r.resolve,...r.cursorKey&&{cursorKey:r.cursorKey},...r.sessionEnvKey&&{sessionEnvKey:r.sessionEnvKey}}}function d(e,r){let t;if("handler"in r){if(typeof r.handler!="function")throw new Error(`Skill "${e}" must have a handler function`);let l=h();if(!l)throw new Error(`Could not resolve caller file for skill "${e}".`);t=v(e,l,r)}else if(typeof r.resolve=="function")t=k(e,r);else throw new Error(`Skill "${e}" must have either a handler (function skill) or resolve (MCP skill).`);return c(t),t}var S=d;export{S as functionSkill,d as skill};
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{registerSkill as E}from"@zibby/workflow";import{createRequire as Yt}from"module";import{join as Zt}from"path";var Vt=Yt(import.meta.url);function Qt(){if(process.env.MCP_BROWSER_PATH)return process.env.MCP_BROWSER_PATH;try{return Vt.resolve("@zibby/mcp-browser/dist/bin/mcp-browser-zibby.js")}catch{return null}}var Te="1280x720",Ce="1280x720";function Xt({headless:r}={}){if(r===!0)return!0;if(r===!1)return!1;let t=process.env.ZIBBY_HEADLESS;return t==="1"||String(t).toLowerCase()==="true"}function Ee(r,t){let e=(r||[]).filter(s=>s!=="--headless");return t?[...e,"--headless"]:e}var xe={id:"browser",serverName:"playwright",cursorKey:"playwright-official",allowedTools:["mcp__playwright__*"],sessionEnvKey:"ZIBBY_SESSION_INFO",description:"Playwright Browser MCP Server",envKeys:[],tools:[],promptFragment:`Execute this test using the browser tools available to you. You MUST make actual browser tool calls \u2014 do not fabricate results.
|
|
1
|
+
import{registerSkill as E}from"@zibby/agent-workflow";import{createRequire as Yt}from"module";import{join as Zt}from"path";var Vt=Yt(import.meta.url);function Qt(){if(process.env.MCP_BROWSER_PATH)return process.env.MCP_BROWSER_PATH;try{return Vt.resolve("@zibby/mcp-browser/dist/bin/mcp-browser-zibby.js")}catch{return null}}var Te="1280x720",Ce="1280x720";function Xt({headless:r}={}){if(r===!0)return!0;if(r===!1)return!1;let t=process.env.ZIBBY_HEADLESS;return t==="1"||String(t).toLowerCase()==="true"}function Ee(r,t){let e=(r||[]).filter(s=>s!=="--headless");return t?[...e,"--headless"]:e}var xe={id:"browser",serverName:"playwright",cursorKey:"playwright-official",allowedTools:["mcp__playwright__*"],sessionEnvKey:"ZIBBY_SESSION_INFO",description:"Playwright Browser MCP Server",envKeys:[],tools:[],promptFragment:`Execute this test using the browser tools available to you. You MUST make actual browser tool calls \u2014 do not fabricate results.
|
|
2
2
|
If you DO NOT have access to browser tools \u2192 return {"success": false, "steps": [], "browserClosed": false, "notes": "No browser tools available"}.
|
|
3
3
|
DO NOT return success: true unless you ACTUALLY called browser tools.`,resolve({sessionPath:r,workspace:t,nodeName:e,headless:s}={}){let n=Qt(),i=r&&e?Zt(r,e):null,o=i||r||t||"test-results",a=Xt({headless:s}),c={};return i&&(c.ZIBBY_NODE_SESSION_PATH=i),r&&(c.ZIBBY_SESSION_PATH=r),n?{command:"node",args:Ee([n,"--isolated",`--save-video=${Te}`,`--viewport-size=${Ce}`,`--output-dir=${o}`],a),env:c}:{command:"npx",args:Ee(["-y","@playwright/mcp","--isolated",`--save-video=${Te}`,`--viewport-size=${Ce}`,"--output-dir",o],a),env:c}}};import{createRequire as es}from"module";import{resolveIntegrationToken as ts,clearTokenCache as ss}from"@zibby/core/backend-client.js";var rs=es(import.meta.url);function ns(){if(process.env.MCP_JIRA_PATH)return process.env.MCP_JIRA_PATH;try{return rs.resolve("@zibby/mcp-jira/index.js")}catch{return null}}var is=new Set(["paragraph","heading","bulletList","orderedList","listItem","blockquote","codeBlock","rule","table","tableRow","tableCell","tableHeader","mediaSingle","panel"]);function os(r,t){if(!t||!t.length)return r;let e=r;for(let s of t)s.type==="strong"?e=`**${e}**`:s.type==="em"?e=`_${e}_`:s.type==="code"?e=`\`${e}\``:s.type==="strike"?e=`~~${e}~~`:s.type==="link"&&s.attrs?.href&&(e=`[${e}](${s.attrs.href})`);return e}function X(r,t=0){if(!Array.isArray(r))return"";let e=[];for(let s of r){if(s.type==="text"){e.push(os(s.text||"",s.marks));continue}if(s.type==="hardBreak"){e.push(`
|
|
4
4
|
`);continue}if(s.type==="rule"){e.push(`
|
|
@@ -141,7 +141,7 @@ AFTER completing the test, you MUST call memory_save_insight at least once:
|
|
|
141
141
|
1. Go to Settings \u2192 Integrations (https://studio.zibby.app/integrations)
|
|
142
142
|
2. Click "Connect Sentry" and authorize
|
|
143
143
|
3. After OAuth completes, ask me to install Sentry again`},runner:{description:"Run zibby test workflows from chat (parallel supported)",envKeys:[],setupInstructions:"Ready to use. Runs zibby test workflows as background processes \u2014 each with its own browser and session."},browser:{description:"Playwright browser automation (navigate, click, fill, screenshot)",envKeys:[],setupInstructions:"Ready to use. Starts a Playwright browser for web automation."},memory:{description:"Test memory database (Dolt) \u2014 history, selectors, insights",envKeys:[],setupInstructions:"Ready to use. Requires Dolt (https://docs.dolthub.com/introduction/installation) and a memory DB via `zibby init --mem`."},"chat-memory":{description:"Persistent chat memory \u2014 remembers facts, decisions, and task history across sessions (Dolt-backed)",envKeys:[],setupInstructions:'Ready to use. Requires Dolt installed. Tables auto-create on first use. Install with: "add chat memory" or "install chat-memory".'},git:{description:"Clone and explore git repositories locally for codebase analysis",envKeys:[],setupInstructions:"Ready to use. Clone repos with git_checkout, explore with git_explore. Auto-authenticates with GitHub/GitLab tokens."}};function Ss(){let r=["## Available Skills"];for(let[t,e]of Object.entries(B)){let s=e.integrationProvider?`integration: ${e.integrationProvider}`:"ready";r.push(`- ${t}: ${e.description} [${s}]`)}return r.push(""),r.push("Use the install_skill / uninstall_skill / list_available_skills tools to manage skills."),r.push(`Zibby third party Integration settings page: ${ye()}`),r.push(""),r.push("## Tool-First Policy (mandatory)"),r.push("CRITICAL RULES \u2014 follow these strictly:"),r.push("1. When user asks to do something and a matching skill is available but not installed, IMMEDIATELY call install_skill. Never ask for credentials or confirmation first."),r.push(`2. If install_skill succeeds, the skill's tools are now available. Use them RIGHT AWAY in the same turn \u2014 don't just say "it's connected", actually call the tools.`),r.push("3. If install_skill reports needsIntegration, tell the user to connect via the integration URL and try again after."),r.push("4. When the relevant skill is already installed, use its tools directly \u2014 don't ask for IDs or keys. Each skill's own instructions explain the workflow."),r.push("5. If a task needs multiple skills (e.g. data from one + execution from another), install all of them, then follow each skill's workflow instructions."),r.join(`
|
|
144
|
-
`)}function vs(){if(process.env.ZIBBY_USER_TOKEN)return process.env.ZIBBY_USER_TOKEN;try{let r=ws(ks(),".zibby","config.json");return hs(r)&&JSON.parse(_s(r,"utf-8")).sessionToken||null}catch{return null}}function Ns(){return(process.env.ZIBBY_API_URL||process.env.ZIBBY_PROD_API_URL||"https://api-prod.zibby.app").replace(/\/$/,"")}function ye(){return`${(process.env.ZIBBY_FRONTEND_URL||process.env.ZIBBY_PROD_FRONTEND_URL||"https://studio.zibby.app").replace(/\/$/,"")}/integrations`}function Os(r){try{let t=process.platform;return bs(t==="darwin"?"open":t==="win32"?"cmd":"xdg-open",t==="win32"?["/c","start","",r]:[r],{detached:!0,stdio:"ignore"}).unref(),!0}catch{return!1}}async function $s(){let r=vs();if(!r)return{checked:!1,statuses:null,reason:"no-session-token"};try{let t=await fetch(`${Ns()}/integrations/status`,{method:"GET",headers:{Authorization:`Bearer ${r}`}});return t.ok?{checked:!0,statuses:await t.json()||{},reason:null}:{checked:!1,statuses:null,reason:`status-${t.status}`}}catch{return{checked:!1,statuses:null,reason:"network-error"}}}function Pe(r,t){if(!t||!r)return{connected:null};let e=r[t];return!e||typeof e.connected!="boolean"?{connected:null,details:e||null}:{connected:e.connected,details:e}}var Be={id:"skill-installer",description:"Live skill installation for chat sessions",envKeys:[],catalog:B,promptFragment:Ss,tools:[{name:"install_skill",description:"Install a skill into the current chat session so its tools become available",input_schema:{type:"object",properties:{skillId:{type:"string",description:'Skill identifier to install (e.g. "jira", "github", "browser", "memory")'}},required:["skillId"]}},{name:"uninstall_skill",description:"Remove a skill from the current chat session",input_schema:{type:"object",properties:{skillId:{type:"string",description:"Skill identifier to remove"}},required:["skillId"]}},{name:"list_available_skills",description:"List all skills that can be installed, with their env-var readiness status",input_schema:{type:"object",properties:{}}}],async handleToolCall(r,t,e){let{activeSkills:s}=e,n=await $s();if(r==="list_available_skills"){let i=Object.entries(B).map(([o,a])=>{let c=s.includes(o),l=Pe(n.statuses,a.integrationProvider);return{id:o,description:a.description,installed:c,integrationProvider:a.integrationProvider||void 0,integrationConnected:l.connected,setupInstructions:l.connected===!1?a.setupInstructions:void 0}});return JSON.stringify({skills:i})}if(r==="install_skill"){let{skillId:i}=t;if(!i)return JSON.stringify({ok:!1,error:"skillId is required"});if(s.includes(i)){let u=B[i],{getSkill:p}=await import("@zibby/workflow"),m=(p(i)?.tools||[]).map(f=>f.name);return JSON.stringify({ok:!0,alreadyInstalled:!0,skillId:i,description:u?.description,availableTools:m,integrationUrl:u?.integrationProvider?ye():void 0,hint:`${i} is already active. Tools available: ${m.join(", ")}. Use them directly.`})}if(!B[i])return JSON.stringify({ok:!1,error:`Unknown skill "${i}". Available: ${Object.keys(B).join(", ")}`});let o=B[i];if(o.integrationProvider){let u=Pe(n.statuses,o.integrationProvider),p=ye();if(n.checked&&u.connected===!1){let y=Os(p);return JSON.stringify({ok:!1,error:`${o.integrationProvider} is not connected for this Zibby account yet`,needsIntegration:!0,integrationUrl:p,openedBrowser:y,setupInstructions:`Please connect ${o.integrationProvider} first at ${p}. After you finish OAuth, ask me to install ${i} again.`})}}s.push(i);let{getSkill:a}=await import("@zibby/workflow"),l=(a(i)?.tools||[]).map(u=>u.name);return JSON.stringify({ok:!0,installed:i,description:o.description,availableTools:l,hint:`${i} is now active. You now have these tools: ${l.join(", ")}. Use them immediately to help the user \u2014 don't just confirm installation.`})}if(r==="uninstall_skill"){let{skillId:i}=t;if(!i)return JSON.stringify({ok:!1,error:"skillId is required"});if(i==="skill-installer")return JSON.stringify({ok:!1,error:"Cannot uninstall the skill installer"});let o=s.indexOf(i);return o===-1?JSON.stringify({ok:!1,error:`${i} is not installed`}):(s.splice(o,1),JSON.stringify({ok:!0,uninstalled:i}))}return JSON.stringify({error:`Unknown tool: ${r}`})},resolve(){return null}};import{readFileSync as Rs,readdirSync as Is,statSync as We,writeFileSync as js,mkdirSync as As}from"fs";import{join as ze,resolve as Ts,relative as Cs}from"path";import{execSync as Ge}from"child_process";var Fe=256*1024,Es=64*1024,He={id:"core-tools",description:"File read/write, directory listing, shell commands, open URLs, wait for async operations",envKeys:[],tools:[{name:"read_file",description:"Read the contents of a file. Returns the text content.",input_schema:{type:"object",properties:{path:{type:"string",description:"File path (relative to cwd or absolute)"}},required:["path"]}},{name:"write_file",description:"Write content to a file. Creates parent directories if needed.",input_schema:{type:"object",properties:{path:{type:"string",description:"File path (relative to cwd or absolute)"},content:{type:"string",description:"Content to write"}},required:["path","content"]}},{name:"list_directory",description:"List files and directories in a path. Returns names with type indicators (/ for dirs).",input_schema:{type:"object",properties:{path:{type:"string",description:"Directory path (relative to cwd or absolute). Defaults to cwd."}}}},{name:"run_command",description:"Run a shell command and return its output. Use for grep, git, npm, etc.",input_schema:{type:"object",properties:{command:{type:"string",description:"Shell command to execute"},cwd:{type:"string",description:"Working directory (optional, defaults to project root)"}},required:["command"]}},{name:"open_url",description:"Open a URL in the user's default browser. Use for OAuth flows, documentation, integration setup pages.",input_schema:{type:"object",properties:{url:{type:"string",description:"URL to open"}},required:["url"]}},{name:"wait",description:"Wait for N seconds. Use this for async operations (tests, builds, deploys) \u2014 wait, then check status again.",input_schema:{type:"object",properties:{seconds:{type:"number",description:"Seconds to wait (default: 5, max: 300)"},reason:{type:"string",description:"Why waiting (for logging/clarity)"}}}}],async handleToolCall(r,t,e){let s=e?.options?.workspace||process.cwd();try{switch(r){case"read_file":return xs(t,s);case"write_file":return Ls(t,s);case"list_directory":return Js(t,s);case"run_command":return Ds(t,s);case"open_url":return Ms(t);case"wait":return await Us(t,e?.options?.signal);default:return JSON.stringify({error:`Unknown tool: ${r}`})}}catch(n){return JSON.stringify({error:n.message})}},resolve(){return null}};function te(r,t){return Ts(t,r)}function xs(r,t){let e=te(r.path,t),s=We(e);return s.size>Fe?JSON.stringify({error:`File too large (${(s.size/1024).toFixed(0)}KB). Max: ${Fe/1024}KB`}):Rs(e,"utf-8")}function Ls(r,t){let e=te(r.path,t),s=ze(e,"..");return As(s,{recursive:!0}),js(e,r.content,"utf-8"),JSON.stringify({ok:!0,path:Cs(t,e)})}function Js(r,t){let e=te(r.path||".",t);return Is(e).map(n=>{try{return We(ze(e,n)).isDirectory()?`${n}/`:n}catch{return n}}).join(`
|
|
144
|
+
`)}function vs(){if(process.env.ZIBBY_USER_TOKEN)return process.env.ZIBBY_USER_TOKEN;try{let r=ws(ks(),".zibby","config.json");return hs(r)&&JSON.parse(_s(r,"utf-8")).sessionToken||null}catch{return null}}function Ns(){return(process.env.ZIBBY_API_URL||process.env.ZIBBY_PROD_API_URL||"https://api-prod.zibby.app").replace(/\/$/,"")}function ye(){return`${(process.env.ZIBBY_FRONTEND_URL||process.env.ZIBBY_PROD_FRONTEND_URL||"https://studio.zibby.app").replace(/\/$/,"")}/integrations`}function Os(r){try{let t=process.platform;return bs(t==="darwin"?"open":t==="win32"?"cmd":"xdg-open",t==="win32"?["/c","start","",r]:[r],{detached:!0,stdio:"ignore"}).unref(),!0}catch{return!1}}async function $s(){let r=vs();if(!r)return{checked:!1,statuses:null,reason:"no-session-token"};try{let t=await fetch(`${Ns()}/integrations/status`,{method:"GET",headers:{Authorization:`Bearer ${r}`}});return t.ok?{checked:!0,statuses:await t.json()||{},reason:null}:{checked:!1,statuses:null,reason:`status-${t.status}`}}catch{return{checked:!1,statuses:null,reason:"network-error"}}}function Pe(r,t){if(!t||!r)return{connected:null};let e=r[t];return!e||typeof e.connected!="boolean"?{connected:null,details:e||null}:{connected:e.connected,details:e}}var Be={id:"skill-installer",description:"Live skill installation for chat sessions",envKeys:[],catalog:B,promptFragment:Ss,tools:[{name:"install_skill",description:"Install a skill into the current chat session so its tools become available",input_schema:{type:"object",properties:{skillId:{type:"string",description:'Skill identifier to install (e.g. "jira", "github", "browser", "memory")'}},required:["skillId"]}},{name:"uninstall_skill",description:"Remove a skill from the current chat session",input_schema:{type:"object",properties:{skillId:{type:"string",description:"Skill identifier to remove"}},required:["skillId"]}},{name:"list_available_skills",description:"List all skills that can be installed, with their env-var readiness status",input_schema:{type:"object",properties:{}}}],async handleToolCall(r,t,e){let{activeSkills:s}=e,n=await $s();if(r==="list_available_skills"){let i=Object.entries(B).map(([o,a])=>{let c=s.includes(o),l=Pe(n.statuses,a.integrationProvider);return{id:o,description:a.description,installed:c,integrationProvider:a.integrationProvider||void 0,integrationConnected:l.connected,setupInstructions:l.connected===!1?a.setupInstructions:void 0}});return JSON.stringify({skills:i})}if(r==="install_skill"){let{skillId:i}=t;if(!i)return JSON.stringify({ok:!1,error:"skillId is required"});if(s.includes(i)){let u=B[i],{getSkill:p}=await import("@zibby/agent-workflow"),m=(p(i)?.tools||[]).map(f=>f.name);return JSON.stringify({ok:!0,alreadyInstalled:!0,skillId:i,description:u?.description,availableTools:m,integrationUrl:u?.integrationProvider?ye():void 0,hint:`${i} is already active. Tools available: ${m.join(", ")}. Use them directly.`})}if(!B[i])return JSON.stringify({ok:!1,error:`Unknown skill "${i}". Available: ${Object.keys(B).join(", ")}`});let o=B[i];if(o.integrationProvider){let u=Pe(n.statuses,o.integrationProvider),p=ye();if(n.checked&&u.connected===!1){let y=Os(p);return JSON.stringify({ok:!1,error:`${o.integrationProvider} is not connected for this Zibby account yet`,needsIntegration:!0,integrationUrl:p,openedBrowser:y,setupInstructions:`Please connect ${o.integrationProvider} first at ${p}. After you finish OAuth, ask me to install ${i} again.`})}}s.push(i);let{getSkill:a}=await import("@zibby/agent-workflow"),l=(a(i)?.tools||[]).map(u=>u.name);return JSON.stringify({ok:!0,installed:i,description:o.description,availableTools:l,hint:`${i} is now active. You now have these tools: ${l.join(", ")}. Use them immediately to help the user \u2014 don't just confirm installation.`})}if(r==="uninstall_skill"){let{skillId:i}=t;if(!i)return JSON.stringify({ok:!1,error:"skillId is required"});if(i==="skill-installer")return JSON.stringify({ok:!1,error:"Cannot uninstall the skill installer"});let o=s.indexOf(i);return o===-1?JSON.stringify({ok:!1,error:`${i} is not installed`}):(s.splice(o,1),JSON.stringify({ok:!0,uninstalled:i}))}return JSON.stringify({error:`Unknown tool: ${r}`})},resolve(){return null}};import{readFileSync as Rs,readdirSync as Is,statSync as We,writeFileSync as js,mkdirSync as As}from"fs";import{join as ze,resolve as Ts,relative as Cs}from"path";import{execSync as Ge}from"child_process";var Fe=256*1024,Es=64*1024,He={id:"core-tools",description:"File read/write, directory listing, shell commands, open URLs, wait for async operations",envKeys:[],tools:[{name:"read_file",description:"Read the contents of a file. Returns the text content.",input_schema:{type:"object",properties:{path:{type:"string",description:"File path (relative to cwd or absolute)"}},required:["path"]}},{name:"write_file",description:"Write content to a file. Creates parent directories if needed.",input_schema:{type:"object",properties:{path:{type:"string",description:"File path (relative to cwd or absolute)"},content:{type:"string",description:"Content to write"}},required:["path","content"]}},{name:"list_directory",description:"List files and directories in a path. Returns names with type indicators (/ for dirs).",input_schema:{type:"object",properties:{path:{type:"string",description:"Directory path (relative to cwd or absolute). Defaults to cwd."}}}},{name:"run_command",description:"Run a shell command and return its output. Use for grep, git, npm, etc.",input_schema:{type:"object",properties:{command:{type:"string",description:"Shell command to execute"},cwd:{type:"string",description:"Working directory (optional, defaults to project root)"}},required:["command"]}},{name:"open_url",description:"Open a URL in the user's default browser. Use for OAuth flows, documentation, integration setup pages.",input_schema:{type:"object",properties:{url:{type:"string",description:"URL to open"}},required:["url"]}},{name:"wait",description:"Wait for N seconds. Use this for async operations (tests, builds, deploys) \u2014 wait, then check status again.",input_schema:{type:"object",properties:{seconds:{type:"number",description:"Seconds to wait (default: 5, max: 300)"},reason:{type:"string",description:"Why waiting (for logging/clarity)"}}}}],async handleToolCall(r,t,e){let s=e?.options?.workspace||process.cwd();try{switch(r){case"read_file":return xs(t,s);case"write_file":return Ls(t,s);case"list_directory":return Js(t,s);case"run_command":return Ds(t,s);case"open_url":return Ms(t);case"wait":return await Us(t,e?.options?.signal);default:return JSON.stringify({error:`Unknown tool: ${r}`})}}catch(n){return JSON.stringify({error:n.message})}},resolve(){return null}};function te(r,t){return Ts(t,r)}function xs(r,t){let e=te(r.path,t),s=We(e);return s.size>Fe?JSON.stringify({error:`File too large (${(s.size/1024).toFixed(0)}KB). Max: ${Fe/1024}KB`}):Rs(e,"utf-8")}function Ls(r,t){let e=te(r.path,t),s=ze(e,"..");return As(s,{recursive:!0}),js(e,r.content,"utf-8"),JSON.stringify({ok:!0,path:Cs(t,e)})}function Js(r,t){let e=te(r.path||".",t);return Is(e).map(n=>{try{return We(ze(e,n)).isDirectory()?`${n}/`:n}catch{return n}}).join(`
|
|
145
145
|
`)}function Ds(r,t){let e=r.cwd?te(r.cwd,t):t;return Ge(r.command,{cwd:e,encoding:"utf-8",timeout:3e4,maxBuffer:Es,stdio:["pipe","pipe","pipe"]})||"(no output)"}function Ms(r){let{url:t}=r;if(!t||!t.startsWith("http://")&&!t.startsWith("https://"))return JSON.stringify({error:"Invalid URL \u2014 must start with http:// or https://"});let e=process.platform,s=e==="darwin"?"open":e==="win32"?"start":"xdg-open";try{return Ge(`${s} "${t}"`,{stdio:"ignore",timeout:5e3}),JSON.stringify({ok:!0,opened:t})}catch{return JSON.stringify({ok:!1,error:`Could not open browser. Please visit: ${t}`})}}async function Us(r,t){let e=Math.min(Math.max(r.seconds||5,1),300),s=r.reason||"async operation",n=500,i=Date.now()+e*1e3;for(;Date.now()<i;){if(t?.aborted)return JSON.stringify({ok:!0,waited:Math.round((e*1e3-(i-Date.now()))/1e3),reason:s,interrupted:!0});await new Promise(o=>setTimeout(o,Math.min(n,i-Date.now())))}return JSON.stringify({ok:!0,waited:e,reason:s})}import{resolveIntegrationToken as Ze}from"@zibby/core/backend-client.js";async function Ye(r,t={}){let{token:e,organizationSlug:s}=await Ze("sentry"),n=`https://sentry.io/api/0/organizations/${s}${r}`,i=await fetch(n,{method:t.method||"GET",headers:{Authorization:`Bearer ${e}`,"Content-Type":"application/json"}});if(!i.ok){let o=await i.text().catch(()=>"");throw new Error(`Sentry API ${i.status}: ${o.slice(0,300)}`)}return i.json()}var Ve={id:"sentry",description:"Sentry error tracking \u2014 projects, issues, events",envKeys:[],promptFragment:`## Sentry (connected)
|
|
146
146
|
You have access to the user's Sentry. Use these tools:
|
|
147
147
|
- sentry_list_projects: List projects in the organization
|
|
@@ -304,7 +304,7 @@ ${"#".repeat(i)} ${n.trim()}
|
|
|
304
304
|
${n}
|
|
305
305
|
`):e.push(n)}return e.join("").replace(/\n{3,}/g,`
|
|
306
306
|
|
|
307
|
-
`)}function Zs(r){return r==null||r===""?"":typeof r=="string"?r.trim():typeof r=="object"&&Array.isArray(r.content)?re(r.content).trim():""}async function Vs(r){let{getSkill:t}=await import("@zibby/workflow"),e=t("jira");if(!e||typeof e.handleToolCall!="function")return null;try{let s=await e.handleToolCall("jira_get_issue",{issueKey:r}),n=JSON.parse(s);if(n?.error)return null;let i=await e.handleToolCall("jira_get_comments",{issueKey:r,maxResults:50}),o=JSON.parse(i);if(o?.error)return null;let a=Zs(n.description),c=[];a&&c.push(a);let l=Array.isArray(o.comments)?o.comments:[];if(l.length>0){let p=l.map(y=>String(y.body||"").trim()).filter(Boolean).join(`
|
|
307
|
+
`)}function Zs(r){return r==null||r===""?"":typeof r=="string"?r.trim():typeof r=="object"&&Array.isArray(r.content)?re(r.content).trim():""}async function Vs(r){let{getSkill:t}=await import("@zibby/agent-workflow"),e=t("jira");if(!e||typeof e.handleToolCall!="function")return null;try{let s=await e.handleToolCall("jira_get_issue",{issueKey:r}),n=JSON.parse(s);if(n?.error)return null;let i=await e.handleToolCall("jira_get_comments",{issueKey:r,maxResults:50}),o=JSON.parse(i);if(o?.error)return null;let a=Zs(n.description),c=[];a&&c.push(a);let l=Array.isArray(o.comments)?o.comments:[];if(l.length>0){let p=l.map(y=>String(y.body||"").trim()).filter(Boolean).join(`
|
|
308
308
|
|
|
309
309
|
`);p&&c.push(p)}let u=c.join(`
|
|
310
310
|
|
|
@@ -643,4 +643,4 @@ ${m}
|
|
|
643
643
|
}
|
|
644
644
|
`;H(S(o,"graph.mjs"),f,"utf-8");let k={name:n,description:e.description||`${i} workflow`,entryClass:i,triggers:{api:!0}};H(S(o,"workflow.json"),`${JSON.stringify(k,null,2)}
|
|
645
645
|
`,"utf-8");let h=["graph.mjs","workflow.json","nodes/index.mjs",...c.map(g=>`nodes/${g.replace(/_/g,"-")}.mjs`)];return{workflowDir:Ut(r,o),files:h,className:i,slug:n}}async function Kr(r){let{name:t,description:e,nodes:s,edges:n}=r;if(!t||!Kt.test(t.toLowerCase()))return JSON.stringify({error:`Invalid workflow name "${t}". Must be kebab-case, 2-64 chars, lowercase letters/numbers/hyphens.`});if(!s||s.length===0)return JSON.stringify({error:"At least one node is required."});let i={name:t.toLowerCase(),description:e||`${Pt(t.toLowerCase())} workflow`,nodes:s.map(o=>({name:o.name.replace(/-/g,"_"),description:o.description||`Process ${o.name}`,inputFields:o.inputFields||[],outputFields:o.outputFields||[]})),edges:n||[]};if(i.edges.length===0&&i.nodes.length>0){for(let o=0;o<i.nodes.length-1;o++)i.edges.push({from:i.nodes[o].name,to:i.nodes[o+1].name});i.edges.push({from:i.nodes[i.nodes.length-1].name,to:"END"})}return JSON.stringify({ok:!0,spec:i,message:`Workflow "${i.name}" designed with ${i.nodes.length} node(s). Call build_workflow to generate the code.`,preview:{nodes:i.nodes.map(o=>o.name),flow:i.edges.map(o=>o.condition?`${o.from} \u2192(if ${o.condition})\u2192 ${o.to}`:`${o.from} \u2192 ${o.to}`)}})}async function Pr(r,t){let{name:e,spec:s}=r,n=(e||s?.name||"").toLowerCase();if(!n||!Kt.test(n))return JSON.stringify({error:`Invalid workflow name "${n}".`});if(!s||!s.nodes||s.nodes.length===0)return JSON.stringify({error:"spec with nodes is required. Call design_workflow first."});let i=S(t,".zibby","workflows",n);if(M(i))return JSON.stringify({error:`Workflow "${n}" already exists at .zibby/workflows/${n}/. Delete it first or choose a different name.`});let o=await Wt(s,t),a=qr(t,n,s,o);return JSON.stringify({ok:!0,...a,message:`Workflow "${n}" created at ${a.workflowDir}/`,nextSteps:[`Test locally: zibby start ${n}`,`Deploy to cloud: zibby deploy ${n} --project <project-id>`,`Tail logs: zibby logs --workflow ${n} --project <project-id>`]})}async function Br(r,t){let{workflowName:e,nodeName:s,description:n,inputFields:i,outputFields:o}=r,a=(e||"").toLowerCase(),c=(s||"").replace(/-/g,"_"),l=S(t,".zibby","workflows",a);if(!M(l))return JSON.stringify({error:`Workflow "${a}" not found. Create it first with build_workflow.`});let u={name:a,description:"",nodes:[{name:c,description:n||`Process ${c}`,inputFields:i||[],outputFields:o||[]}],edges:[]},y=(await Wt(u,t)).nodes?.[c]?.code;if(!y)return JSON.stringify({error:"Failed to generate node code."});let m=S(l,"nodes"),f=`${c.replace(/_/g,"-")}.mjs`;H(S(m,f),y,"utf-8");let k=S(m,"index.mjs"),h=V(c),g=`export { ${h} } from './${c.replace(/_/g,"-")}.mjs';
|
|
646
|
-
`,_=M(k)?Q(k,"utf-8"):"";return _.includes(h)||H(k,_+g,"utf-8"),JSON.stringify({ok:!0,file:`nodes/${f}`,exportName:h,message:`Node "${c}" added. Update graph.mjs to wire it into the graph.`})}async function Fr(r,t){let{name:e,projectId:s}=r,n=(e||"").toLowerCase();if(!n)return JSON.stringify({error:"Workflow name is required."});if(!s)return JSON.stringify({error:"projectId is required."});let i=S(t,".zibby","workflows",n);if(!M(i))return JSON.stringify({error:`Workflow "${n}" not found at .zibby/workflows/${n}/`});try{let{execSync:o}=await import("child_process"),a=o(`node "${S(t,"packages/cli/bin/zibby.js")}" deploy ${n} --project ${s}`,{cwd:t,encoding:"utf-8",timeout:3e4,stdio:["pipe","pipe","pipe"]});return JSON.stringify({ok:!0,output:a.trim()})}catch{try{let{execSync:a}=await import("child_process"),c=a(`npx zibby deploy ${n} --project ${s}`,{cwd:t,encoding:"utf-8",timeout:3e4,stdio:["pipe","pipe","pipe"]});return JSON.stringify({ok:!0,output:c.trim()})}catch(a){return JSON.stringify({error:`Deploy failed: ${a.message}`})}}}function Wr(r){let t=S(r,".zibby","workflows");if(!M(t))return JSON.stringify({workflows:[],message:"No workflows found. Use build_workflow to create one."});let s=Ie(t).filter(n=>{try{return Mt(S(t,n)).isDirectory()}catch{return!1}}).map(n=>{let i=S(t,n,"workflow.json"),o={};try{o=JSON.parse(Q(i,"utf-8"))}catch{}let a=S(t,n,"nodes"),c=0;try{c=Ie(a).filter(l=>l.endsWith(".mjs")&&l!=="index.mjs").length}catch{}return{name:n,description:o.description||"",nodeCount:c,path:Ut(r,S(t,n))}});return JSON.stringify({workflows:s})}var zt={id:"workflow-builder",description:"Build, scaffold, and deploy custom AI workflows via conversation",envKeys:[],promptFragment:xr,tools:[{name:"design_workflow",description:"Design a workflow spec (nodes, edges, descriptions) for the user to review before building. Call this after understanding requirements.",input_schema:{type:"object",properties:{name:{type:"string",description:"Workflow name in kebab-case (e.g., ticket-triage)"},description:{type:"string",description:"What the workflow does"},nodes:{type:"array",items:{type:"object",properties:{name:{type:"string",description:"Node name in snake_case (e.g., classify_ticket)"},description:{type:"string",description:"What this node does \u2014 be specific about input/output"},inputFields:{type:"array",items:{type:"string"},description:"Key fields this node reads from state"},outputFields:{type:"array",items:{type:"string"},description:"Key fields this node produces"}},required:["name","description"]},description:"Workflow nodes (processing steps)"},edges:{type:"array",items:{type:"object",properties:{from:{type:"string",description:"Source node name"},to:{type:"string",description:'Target node name (or "END")'},condition:{type:"string",description:"JS expression for conditional routing (optional)"}},required:["from","to"]},description:"Edges connecting nodes. If omitted, nodes are wired linearly."}},required:["name","description","nodes"]}},{name:"build_workflow",description:"Generate real workflow code on disk from a design spec. Uses the configured AI agent for high-quality code generation.",input_schema:{type:"object",properties:{name:{type:"string",description:"Workflow name (from design_workflow)"},spec:{type:"object",description:"The full spec object returned by design_workflow",properties:{name:{type:"string"},description:{type:"string"},nodes:{type:"array",items:{type:"object"}},edges:{type:"array",items:{type:"object"}}}}},required:["name","spec"]}},{name:"add_node",description:"Add a new node to an existing workflow. Generates the node file and updates the barrel export.",input_schema:{type:"object",properties:{workflowName:{type:"string",description:"Existing workflow name (kebab-case)"},nodeName:{type:"string",description:"New node name (snake_case)"},description:{type:"string",description:"What this node does"},inputFields:{type:"array",items:{type:"string"},description:"Fields read from state"},outputFields:{type:"array",items:{type:"string"},description:"Fields produced"}},required:["workflowName","nodeName","description"]}},{name:"deploy_workflow",description:"Deploy a workflow to Zibby Cloud. Returns the trigger URL.",input_schema:{type:"object",properties:{name:{type:"string",description:"Workflow name to deploy"},projectId:{type:"string",description:"Target project ID"}},required:["name","projectId"]}},{name:"list_workflows",description:"List all local workflows in .zibby/workflows/.",input_schema:{type:"object",properties:{}}},{name:"explore_framework_docs",description:"Read Zibby framework documentation on demand. Call this before building complex workflows or when you need details on advanced patterns (middleware, conditional routing, skills, deployment, CLI commands).",input_schema:{type:"object",properties:{topic:{type:"string",description:'Doc topic to read (e.g., "workflow", "custom-workflows", "cli-reference", "packages/core", "packages/skills", "integrations/jira"). Call with no topic to list all available docs.'}}}}],async handleToolCall(r,t,e){let s=e?.options?.workspace||process.cwd();try{switch(r){case"design_workflow":return await Kr(t);case"build_workflow":return await Pr(t,s);case"add_node":return await Br(t,s);case"deploy_workflow":return await Fr(t,s);case"list_workflows":return Wr(s);case"explore_framework_docs":{let n=(t.topic||"").trim();if(!n){let o=Dt();return JSON.stringify({available:o,hint:"Call again with a topic to read its content."})}let i=Ft(n);if(!i){let o=Dt();return JSON.stringify({error:`Doc "${n}" not found.`,available:o})}return JSON.stringify({topic:n,content:i})}default:return JSON.stringify({error:`Unknown tool: ${r}`})}}catch(n){return JSON.stringify({error:n.message})}},resolve(){return null}};import{createRequire as zr}from"module";import{fileURLToPath as Gr}from"url";import{registerHandlers as Hr}from"@zibby/core/function-skill-registry.js";import{registerSkill as Yr}from"@zibby/workflow";var Zr=zr(import.meta.url);function Vr(){try{return Zr.resolve("@zibby/core/function-bridge.js")}catch{return null}}var Qr=import.meta.url;function Xr(){let r=Error.prepareStackTrace;try{Error.prepareStackTrace=(s,n)=>n;let e=new Error().stack;for(let s=2;s<e.length;s++){let n=e[s].getFileName();if(n&&n!==Qr&&!n.startsWith("node:"))return n.startsWith("file://")?Gr(n):n}return null}finally{Error.prepareStackTrace=r}}function en(r){if(!r||typeof r!="object")return{type:"object",properties:{},required:[]};let t={},e=[];for(let[s,n]of Object.entries(r))if(typeof n=="string")t[s]={type:n},e.push(s);else{let{required:i,...o}=n;t[s]=o,i!==!1&&e.push(s)}return{type:"object",properties:t,required:e}}function tn(r,t,e){if(typeof e.handler!="function")throw new Error(`Skill "${r}" must have a handler function`);let s={[r]:e.handler},n=[{name:r,description:e.description||"",input_schema:en(e.input)}];return Hr(r,s,n),{id:r,type:"function",serverName:r,allowedTools:[`mcp__${r}__*`],description:e.description||`Function skill: ${r}`,envKeys:[],tools:n,resolve(){let i=Vr();return i?{command:"node",args:[i,t,r]}:null}}}function sn(r,t){return{id:r,type:"mcp",serverName:t.serverName||r,allowedTools:t.allowedTools||[`mcp__${t.serverName||r}__*`],description:t.description||`MCP skill: ${r}`,envKeys:t.envKeys||[],tools:t.tools||[],resolve:t.resolve,...t.cursorKey&&{cursorKey:t.cursorKey},...t.sessionEnvKey&&{sessionEnvKey:t.sessionEnvKey}}}function Gt(r,t){let e;if("handler"in t){if(typeof t.handler!="function")throw new Error(`Skill "${r}" must have a handler function`);let s=Xr();if(!s)throw new Error(`Could not resolve caller file for skill "${r}".`);e=tn(r,s,t)}else if(typeof t.resolve=="function")e=sn(r,t);else throw new Error(`Skill "${r}" must have either a handler (function skill) or resolve (MCP skill).`);return Yr(e),e}var rn=Gt;import{registerSkill as bi,getSkill as Si,hasSkill as vi,getAllSkills as Ni,listSkillIds as Oi}from"@zibby/workflow";E(xe);E(De);E(Ue);E(fe);E(Ve);E(Ke);E(dt);E(ht);E(Be);E(He);E(Et);E(zt);E({...fe,id:"slack_notify"});var hi={BROWSER:"browser",JIRA:"jira",GITHUB:"github",GIT:"git",SLACK:"slack",SENTRY:"sentry",MEMORY:"memory",RUNNER:"runner",SKILL_INSTALLER:"skill-installer",CORE_TOOLS:"core-tools",CHAT_MEMORY:"chat-memory",WORKFLOW_BUILDER:"workflow-builder"};export{hi as SKILLS,xe as browserSkill,Et as chatMemorySkill,He as coreToolsSkill,rn as functionSkill,Ni as getAllSkills,Si as getSkill,ht as gitSkill,Ue as githubSkill,vi as hasSkill,De as jiraSkill,Oi as listSkillIds,Ke as memorySkill,bi as registerSkill,dt as runnerSkill,Ve as sentrySkill,Gt as skill,Be as skillInstallerSkill,fe as slackSkill,dt as testRunnerSkill,zt as workflowBuilderSkill};
|
|
646
|
+
`,_=M(k)?Q(k,"utf-8"):"";return _.includes(h)||H(k,_+g,"utf-8"),JSON.stringify({ok:!0,file:`nodes/${f}`,exportName:h,message:`Node "${c}" added. Update graph.mjs to wire it into the graph.`})}async function Fr(r,t){let{name:e,projectId:s}=r,n=(e||"").toLowerCase();if(!n)return JSON.stringify({error:"Workflow name is required."});if(!s)return JSON.stringify({error:"projectId is required."});let i=S(t,".zibby","workflows",n);if(!M(i))return JSON.stringify({error:`Workflow "${n}" not found at .zibby/workflows/${n}/`});try{let{execSync:o}=await import("child_process"),a=o(`node "${S(t,"packages/cli/bin/zibby.js")}" deploy ${n} --project ${s}`,{cwd:t,encoding:"utf-8",timeout:3e4,stdio:["pipe","pipe","pipe"]});return JSON.stringify({ok:!0,output:a.trim()})}catch{try{let{execSync:a}=await import("child_process"),c=a(`npx zibby deploy ${n} --project ${s}`,{cwd:t,encoding:"utf-8",timeout:3e4,stdio:["pipe","pipe","pipe"]});return JSON.stringify({ok:!0,output:c.trim()})}catch(a){return JSON.stringify({error:`Deploy failed: ${a.message}`})}}}function Wr(r){let t=S(r,".zibby","workflows");if(!M(t))return JSON.stringify({workflows:[],message:"No workflows found. Use build_workflow to create one."});let s=Ie(t).filter(n=>{try{return Mt(S(t,n)).isDirectory()}catch{return!1}}).map(n=>{let i=S(t,n,"workflow.json"),o={};try{o=JSON.parse(Q(i,"utf-8"))}catch{}let a=S(t,n,"nodes"),c=0;try{c=Ie(a).filter(l=>l.endsWith(".mjs")&&l!=="index.mjs").length}catch{}return{name:n,description:o.description||"",nodeCount:c,path:Ut(r,S(t,n))}});return JSON.stringify({workflows:s})}var zt={id:"workflow-builder",description:"Build, scaffold, and deploy custom AI workflows via conversation",envKeys:[],promptFragment:xr,tools:[{name:"design_workflow",description:"Design a workflow spec (nodes, edges, descriptions) for the user to review before building. Call this after understanding requirements.",input_schema:{type:"object",properties:{name:{type:"string",description:"Workflow name in kebab-case (e.g., ticket-triage)"},description:{type:"string",description:"What the workflow does"},nodes:{type:"array",items:{type:"object",properties:{name:{type:"string",description:"Node name in snake_case (e.g., classify_ticket)"},description:{type:"string",description:"What this node does \u2014 be specific about input/output"},inputFields:{type:"array",items:{type:"string"},description:"Key fields this node reads from state"},outputFields:{type:"array",items:{type:"string"},description:"Key fields this node produces"}},required:["name","description"]},description:"Workflow nodes (processing steps)"},edges:{type:"array",items:{type:"object",properties:{from:{type:"string",description:"Source node name"},to:{type:"string",description:'Target node name (or "END")'},condition:{type:"string",description:"JS expression for conditional routing (optional)"}},required:["from","to"]},description:"Edges connecting nodes. If omitted, nodes are wired linearly."}},required:["name","description","nodes"]}},{name:"build_workflow",description:"Generate real workflow code on disk from a design spec. Uses the configured AI agent for high-quality code generation.",input_schema:{type:"object",properties:{name:{type:"string",description:"Workflow name (from design_workflow)"},spec:{type:"object",description:"The full spec object returned by design_workflow",properties:{name:{type:"string"},description:{type:"string"},nodes:{type:"array",items:{type:"object"}},edges:{type:"array",items:{type:"object"}}}}},required:["name","spec"]}},{name:"add_node",description:"Add a new node to an existing workflow. Generates the node file and updates the barrel export.",input_schema:{type:"object",properties:{workflowName:{type:"string",description:"Existing workflow name (kebab-case)"},nodeName:{type:"string",description:"New node name (snake_case)"},description:{type:"string",description:"What this node does"},inputFields:{type:"array",items:{type:"string"},description:"Fields read from state"},outputFields:{type:"array",items:{type:"string"},description:"Fields produced"}},required:["workflowName","nodeName","description"]}},{name:"deploy_workflow",description:"Deploy a workflow to Zibby Cloud. Returns the trigger URL.",input_schema:{type:"object",properties:{name:{type:"string",description:"Workflow name to deploy"},projectId:{type:"string",description:"Target project ID"}},required:["name","projectId"]}},{name:"list_workflows",description:"List all local workflows in .zibby/workflows/.",input_schema:{type:"object",properties:{}}},{name:"explore_framework_docs",description:"Read Zibby framework documentation on demand. Call this before building complex workflows or when you need details on advanced patterns (middleware, conditional routing, skills, deployment, CLI commands).",input_schema:{type:"object",properties:{topic:{type:"string",description:'Doc topic to read (e.g., "workflow", "custom-workflows", "cli-reference", "packages/core", "packages/skills", "integrations/jira"). Call with no topic to list all available docs.'}}}}],async handleToolCall(r,t,e){let s=e?.options?.workspace||process.cwd();try{switch(r){case"design_workflow":return await Kr(t);case"build_workflow":return await Pr(t,s);case"add_node":return await Br(t,s);case"deploy_workflow":return await Fr(t,s);case"list_workflows":return Wr(s);case"explore_framework_docs":{let n=(t.topic||"").trim();if(!n){let o=Dt();return JSON.stringify({available:o,hint:"Call again with a topic to read its content."})}let i=Ft(n);if(!i){let o=Dt();return JSON.stringify({error:`Doc "${n}" not found.`,available:o})}return JSON.stringify({topic:n,content:i})}default:return JSON.stringify({error:`Unknown tool: ${r}`})}}catch(n){return JSON.stringify({error:n.message})}},resolve(){return null}};import{createRequire as zr}from"module";import{fileURLToPath as Gr}from"url";import{registerHandlers as Hr}from"@zibby/core/function-skill-registry.js";import{registerSkill as Yr}from"@zibby/agent-workflow";var Zr=zr(import.meta.url);function Vr(){try{return Zr.resolve("@zibby/core/function-bridge.js")}catch{return null}}var Qr=import.meta.url;function Xr(){let r=Error.prepareStackTrace;try{Error.prepareStackTrace=(s,n)=>n;let e=new Error().stack;for(let s=2;s<e.length;s++){let n=e[s].getFileName();if(n&&n!==Qr&&!n.startsWith("node:"))return n.startsWith("file://")?Gr(n):n}return null}finally{Error.prepareStackTrace=r}}function en(r){if(!r||typeof r!="object")return{type:"object",properties:{},required:[]};let t={},e=[];for(let[s,n]of Object.entries(r))if(typeof n=="string")t[s]={type:n},e.push(s);else{let{required:i,...o}=n;t[s]=o,i!==!1&&e.push(s)}return{type:"object",properties:t,required:e}}function tn(r,t,e){if(typeof e.handler!="function")throw new Error(`Skill "${r}" must have a handler function`);let s={[r]:e.handler},n=[{name:r,description:e.description||"",input_schema:en(e.input)}];return Hr(r,s,n),{id:r,type:"function",serverName:r,allowedTools:[`mcp__${r}__*`],description:e.description||`Function skill: ${r}`,envKeys:[],tools:n,resolve(){let i=Vr();return i?{command:"node",args:[i,t,r]}:null}}}function sn(r,t){return{id:r,type:"mcp",serverName:t.serverName||r,allowedTools:t.allowedTools||[`mcp__${t.serverName||r}__*`],description:t.description||`MCP skill: ${r}`,envKeys:t.envKeys||[],tools:t.tools||[],resolve:t.resolve,...t.cursorKey&&{cursorKey:t.cursorKey},...t.sessionEnvKey&&{sessionEnvKey:t.sessionEnvKey}}}function Gt(r,t){let e;if("handler"in t){if(typeof t.handler!="function")throw new Error(`Skill "${r}" must have a handler function`);let s=Xr();if(!s)throw new Error(`Could not resolve caller file for skill "${r}".`);e=tn(r,s,t)}else if(typeof t.resolve=="function")e=sn(r,t);else throw new Error(`Skill "${r}" must have either a handler (function skill) or resolve (MCP skill).`);return Yr(e),e}var rn=Gt;import{registerSkill as bi,getSkill as Si,hasSkill as vi,getAllSkills as Ni,listSkillIds as Oi}from"@zibby/agent-workflow";E(xe);E(De);E(Ue);E(fe);E(Ve);E(Ke);E(dt);E(ht);E(Be);E(He);E(Et);E(zt);E({...fe,id:"slack_notify"});var hi={BROWSER:"browser",JIRA:"jira",GITHUB:"github",GIT:"git",SLACK:"slack",SENTRY:"sentry",MEMORY:"memory",RUNNER:"runner",SKILL_INSTALLER:"skill-installer",CORE_TOOLS:"core-tools",CHAT_MEMORY:"chat-memory",WORKFLOW_BUILDER:"workflow-builder"};export{hi as SKILLS,xe as browserSkill,Et as chatMemorySkill,He as coreToolsSkill,rn as functionSkill,Ni as getAllSkills,Si as getSkill,ht as gitSkill,Ue as githubSkill,vi as hasSkill,De as jiraSkill,Oi as listSkillIds,Ke as memorySkill,bi as registerSkill,dt as runnerSkill,Ve as sentrySkill,Gt as skill,Be as skillInstallerSkill,fe as slackSkill,dt as testRunnerSkill,zt as workflowBuilderSkill};
|
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zibby/skills",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.11",
|
|
4
4
|
"description": "Built-in skill definitions for Zibby test automation framework",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -46,10 +46,10 @@
|
|
|
46
46
|
"node": ">=18.0.0"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@zibby/workflow": "^0.1.
|
|
49
|
+
"@zibby/agent-workflow": "^0.1.2"
|
|
50
50
|
},
|
|
51
51
|
"peerDependencies": {
|
|
52
|
-
"@zibby/core": ">=0.1.
|
|
52
|
+
"@zibby/core": ">=0.1.44"
|
|
53
53
|
},
|
|
54
54
|
"optionalDependencies": {
|
|
55
55
|
"@zibby/mcp-browser": "^0.1.8",
|
package/dist/skill-installer.js
CHANGED
|
@@ -11,4 +11,4 @@ import{existsSync as m,readFileSync as b}from"fs";import{homedir as v}from"os";i
|
|
|
11
11
|
1. Go to Settings \u2192 Integrations (https://studio.zibby.app/integrations)
|
|
12
12
|
2. Click "Connect Sentry" and authorize
|
|
13
13
|
3. After OAuth completes, ask me to install Sentry again`},runner:{description:"Run zibby test workflows from chat (parallel supported)",envKeys:[],setupInstructions:"Ready to use. Runs zibby test workflows as background processes \u2014 each with its own browser and session."},browser:{description:"Playwright browser automation (navigate, click, fill, screenshot)",envKeys:[],setupInstructions:"Ready to use. Starts a Playwright browser for web automation."},memory:{description:"Test memory database (Dolt) \u2014 history, selectors, insights",envKeys:[],setupInstructions:"Ready to use. Requires Dolt (https://docs.dolthub.com/introduction/installation) and a memory DB via `zibby init --mem`."},"chat-memory":{description:"Persistent chat memory \u2014 remembers facts, decisions, and task history across sessions (Dolt-backed)",envKeys:[],setupInstructions:'Ready to use. Requires Dolt installed. Tables auto-create on first use. Install with: "add chat memory" or "install chat-memory".'},git:{description:"Clone and explore git repositories locally for codebase analysis",envKeys:[],setupInstructions:"Ready to use. Clone repos with git_checkout, explore with git_explore. Auto-authenticates with GitHub/GitLab tokens."}};function S(){let t=["## Available Skills"];for(let[s,n]of Object.entries(r)){let o=n.integrationProvider?`integration: ${n.integrationProvider}`:"ready";t.push(`- ${s}: ${n.description} [${o}]`)}return t.push(""),t.push("Use the install_skill / uninstall_skill / list_available_skills tools to manage skills."),t.push(`Zibby third party Integration settings page: ${p()}`),t.push(""),t.push("## Tool-First Policy (mandatory)"),t.push("CRITICAL RULES \u2014 follow these strictly:"),t.push("1. When user asks to do something and a matching skill is available but not installed, IMMEDIATELY call install_skill. Never ask for credentials or confirmation first."),t.push(`2. If install_skill succeeds, the skill's tools are now available. Use them RIGHT AWAY in the same turn \u2014 don't just say "it's connected", actually call the tools.`),t.push("3. If install_skill reports needsIntegration, tell the user to connect via the integration URL and try again after."),t.push("4. When the relevant skill is already installed, use its tools directly \u2014 don't ask for IDs or keys. Each skill's own instructions explain the workflow."),t.push("5. If a task needs multiple skills (e.g. data from one + execution from another), install all of them, then follow each skill's workflow instructions."),t.join(`
|
|
14
|
-
`)}function _(){if(process.env.ZIBBY_USER_TOKEN)return process.env.ZIBBY_USER_TOKEN;try{let t=I(v(),".zibby","config.json");return m(t)&&JSON.parse(b(t,"utf-8")).sessionToken||null}catch{return null}}function O(){return(process.env.ZIBBY_API_URL||process.env.ZIBBY_PROD_API_URL||"https://api-prod.zibby.app").replace(/\/$/,"")}function p(){return`${(process.env.ZIBBY_FRONTEND_URL||process.env.ZIBBY_PROD_FRONTEND_URL||"https://studio.zibby.app").replace(/\/$/,"")}/integrations`}function P(t){try{let s=process.platform;return w(s==="darwin"?"open":s==="win32"?"cmd":"xdg-open",s==="win32"?["/c","start","",t]:[t],{detached:!0,stdio:"ignore"}).unref(),!0}catch{return!1}}async function R(){let t=_();if(!t)return{checked:!1,statuses:null,reason:"no-session-token"};try{let s=await fetch(`${O()}/integrations/status`,{method:"GET",headers:{Authorization:`Bearer ${t}`}});return s.ok?{checked:!0,statuses:await s.json()||{},reason:null}:{checked:!1,statuses:null,reason:`status-${s.status}`}}catch{return{checked:!1,statuses:null,reason:"network-error"}}}function g(t,s){if(!s||!t)return{connected:null};let n=t[s];return!n||typeof n.connected!="boolean"?{connected:null,details:n||null}:{connected:n.connected,details:n}}var j={id:"skill-installer",description:"Live skill installation for chat sessions",envKeys:[],catalog:r,promptFragment:S,tools:[{name:"install_skill",description:"Install a skill into the current chat session so its tools become available",input_schema:{type:"object",properties:{skillId:{type:"string",description:'Skill identifier to install (e.g. "jira", "github", "browser", "memory")'}},required:["skillId"]}},{name:"uninstall_skill",description:"Remove a skill from the current chat session",input_schema:{type:"object",properties:{skillId:{type:"string",description:"Skill identifier to remove"}},required:["skillId"]}},{name:"list_available_skills",description:"List all skills that can be installed, with their env-var readiness status",input_schema:{type:"object",properties:{}}}],async handleToolCall(t,s,n){let{activeSkills:o}=n,d=await R();if(t==="list_available_skills"){let e=Object.entries(r).map(([i,a])=>{let h=o.includes(i),c=g(d.statuses,a.integrationProvider);return{id:i,description:a.description,installed:h,integrationProvider:a.integrationProvider||void 0,integrationConnected:c.connected,setupInstructions:c.connected===!1?a.setupInstructions:void 0}});return JSON.stringify({skills:e})}if(t==="install_skill"){let{skillId:e}=s;if(!e)return JSON.stringify({ok:!1,error:"skillId is required"});if(o.includes(e)){let l=r[e],{getSkill:u}=await import("@zibby/workflow"),k=(u(e)?.tools||[]).map(y=>y.name);return JSON.stringify({ok:!0,alreadyInstalled:!0,skillId:e,description:l?.description,availableTools:k,integrationUrl:l?.integrationProvider?p():void 0,hint:`${e} is already active. Tools available: ${k.join(", ")}. Use them directly.`})}if(!r[e])return JSON.stringify({ok:!1,error:`Unknown skill "${e}". Available: ${Object.keys(r).join(", ")}`});let i=r[e];if(i.integrationProvider){let l=g(d.statuses,i.integrationProvider),u=p();if(d.checked&&l.connected===!1){let f=P(u);return JSON.stringify({ok:!1,error:`${i.integrationProvider} is not connected for this Zibby account yet`,needsIntegration:!0,integrationUrl:u,openedBrowser:f,setupInstructions:`Please connect ${i.integrationProvider} first at ${u}. After you finish OAuth, ask me to install ${e} again.`})}}o.push(e);let{getSkill:a}=await import("@zibby/workflow"),c=(a(e)?.tools||[]).map(l=>l.name);return JSON.stringify({ok:!0,installed:e,description:i.description,availableTools:c,hint:`${e} is now active. You now have these tools: ${c.join(", ")}. Use them immediately to help the user \u2014 don't just confirm installation.`})}if(t==="uninstall_skill"){let{skillId:e}=s;if(!e)return JSON.stringify({ok:!1,error:"skillId is required"});if(e==="skill-installer")return JSON.stringify({ok:!1,error:"Cannot uninstall the skill installer"});let i=o.indexOf(e);return i===-1?JSON.stringify({ok:!1,error:`${e} is not installed`}):(o.splice(i,1),JSON.stringify({ok:!0,uninstalled:e}))}return JSON.stringify({error:`Unknown tool: ${t}`})},resolve(){return null}};export{j as skillInstallerSkill};
|
|
14
|
+
`)}function _(){if(process.env.ZIBBY_USER_TOKEN)return process.env.ZIBBY_USER_TOKEN;try{let t=I(v(),".zibby","config.json");return m(t)&&JSON.parse(b(t,"utf-8")).sessionToken||null}catch{return null}}function O(){return(process.env.ZIBBY_API_URL||process.env.ZIBBY_PROD_API_URL||"https://api-prod.zibby.app").replace(/\/$/,"")}function p(){return`${(process.env.ZIBBY_FRONTEND_URL||process.env.ZIBBY_PROD_FRONTEND_URL||"https://studio.zibby.app").replace(/\/$/,"")}/integrations`}function P(t){try{let s=process.platform;return w(s==="darwin"?"open":s==="win32"?"cmd":"xdg-open",s==="win32"?["/c","start","",t]:[t],{detached:!0,stdio:"ignore"}).unref(),!0}catch{return!1}}async function R(){let t=_();if(!t)return{checked:!1,statuses:null,reason:"no-session-token"};try{let s=await fetch(`${O()}/integrations/status`,{method:"GET",headers:{Authorization:`Bearer ${t}`}});return s.ok?{checked:!0,statuses:await s.json()||{},reason:null}:{checked:!1,statuses:null,reason:`status-${s.status}`}}catch{return{checked:!1,statuses:null,reason:"network-error"}}}function g(t,s){if(!s||!t)return{connected:null};let n=t[s];return!n||typeof n.connected!="boolean"?{connected:null,details:n||null}:{connected:n.connected,details:n}}var j={id:"skill-installer",description:"Live skill installation for chat sessions",envKeys:[],catalog:r,promptFragment:S,tools:[{name:"install_skill",description:"Install a skill into the current chat session so its tools become available",input_schema:{type:"object",properties:{skillId:{type:"string",description:'Skill identifier to install (e.g. "jira", "github", "browser", "memory")'}},required:["skillId"]}},{name:"uninstall_skill",description:"Remove a skill from the current chat session",input_schema:{type:"object",properties:{skillId:{type:"string",description:"Skill identifier to remove"}},required:["skillId"]}},{name:"list_available_skills",description:"List all skills that can be installed, with their env-var readiness status",input_schema:{type:"object",properties:{}}}],async handleToolCall(t,s,n){let{activeSkills:o}=n,d=await R();if(t==="list_available_skills"){let e=Object.entries(r).map(([i,a])=>{let h=o.includes(i),c=g(d.statuses,a.integrationProvider);return{id:i,description:a.description,installed:h,integrationProvider:a.integrationProvider||void 0,integrationConnected:c.connected,setupInstructions:c.connected===!1?a.setupInstructions:void 0}});return JSON.stringify({skills:e})}if(t==="install_skill"){let{skillId:e}=s;if(!e)return JSON.stringify({ok:!1,error:"skillId is required"});if(o.includes(e)){let l=r[e],{getSkill:u}=await import("@zibby/agent-workflow"),k=(u(e)?.tools||[]).map(y=>y.name);return JSON.stringify({ok:!0,alreadyInstalled:!0,skillId:e,description:l?.description,availableTools:k,integrationUrl:l?.integrationProvider?p():void 0,hint:`${e} is already active. Tools available: ${k.join(", ")}. Use them directly.`})}if(!r[e])return JSON.stringify({ok:!1,error:`Unknown skill "${e}". Available: ${Object.keys(r).join(", ")}`});let i=r[e];if(i.integrationProvider){let l=g(d.statuses,i.integrationProvider),u=p();if(d.checked&&l.connected===!1){let f=P(u);return JSON.stringify({ok:!1,error:`${i.integrationProvider} is not connected for this Zibby account yet`,needsIntegration:!0,integrationUrl:u,openedBrowser:f,setupInstructions:`Please connect ${i.integrationProvider} first at ${u}. After you finish OAuth, ask me to install ${e} again.`})}}o.push(e);let{getSkill:a}=await import("@zibby/agent-workflow"),c=(a(e)?.tools||[]).map(l=>l.name);return JSON.stringify({ok:!0,installed:e,description:i.description,availableTools:c,hint:`${e} is now active. You now have these tools: ${c.join(", ")}. Use them immediately to help the user \u2014 don't just confirm installation.`})}if(t==="uninstall_skill"){let{skillId:e}=s;if(!e)return JSON.stringify({ok:!1,error:"skillId is required"});if(e==="skill-installer")return JSON.stringify({ok:!1,error:"Cannot uninstall the skill installer"});let i=o.indexOf(e);return i===-1?JSON.stringify({ok:!1,error:`${e} is not installed`}):(o.splice(i,1),JSON.stringify({ok:!0,uninstalled:e}))}return JSON.stringify({error:`Unknown tool: ${t}`})},resolve(){return null}};export{j as skillInstallerSkill};
|
package/dist/test-runner.js
CHANGED
|
@@ -156,7 +156,7 @@ ${"#".repeat(o)} ${i.trim()}
|
|
|
156
156
|
${i}
|
|
157
157
|
`):e.push(i)}return e.join("").replace(/\n{3,}/g,`
|
|
158
158
|
|
|
159
|
-
`)}function me(s){return s==null||s===""?"":typeof s=="string"?s.trim():typeof s=="object"&&Array.isArray(s.content)?E(s.content).trim():""}async function ye(s){let{getSkill:n}=await import("@zibby/workflow"),e=n("jira");if(!e||typeof e.handleToolCall!="function")return null;try{let t=await e.handleToolCall("jira_get_issue",{issueKey:s}),i=JSON.parse(t);if(i?.error)return null;let o=await e.handleToolCall("jira_get_comments",{issueKey:s,maxResults:50}),d=JSON.parse(o);if(d?.error)return null;let u=me(i.description),r=[];u&&r.push(u);let l=Array.isArray(d.comments)?d.comments:[];if(l.length>0){let p=l.map(g=>String(g.body||"").trim()).filter(Boolean).join(`
|
|
159
|
+
`)}function me(s){return s==null||s===""?"":typeof s=="string"?s.trim():typeof s=="object"&&Array.isArray(s.content)?E(s.content).trim():""}async function ye(s){let{getSkill:n}=await import("@zibby/agent-workflow"),e=n("jira");if(!e||typeof e.handleToolCall!="function")return null;try{let t=await e.handleToolCall("jira_get_issue",{issueKey:s}),i=JSON.parse(t);if(i?.error)return null;let o=await e.handleToolCall("jira_get_comments",{issueKey:s,maxResults:50}),d=JSON.parse(o);if(d?.error)return null;let u=me(i.description),r=[];u&&r.push(u);let l=Array.isArray(d.comments)?d.comments:[];if(l.length>0){let p=l.map(g=>String(g.body||"").trim()).filter(Boolean).join(`
|
|
160
160
|
|
|
161
161
|
`);p&&r.push(p)}let c=r.join(`
|
|
162
162
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zibby/skills",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.11",
|
|
4
4
|
"description": "Built-in skill definitions for Zibby test automation framework",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -46,10 +46,10 @@
|
|
|
46
46
|
"node": ">=18.0.0"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@zibby/workflow": "^0.1.
|
|
49
|
+
"@zibby/agent-workflow": "^0.1.2"
|
|
50
50
|
},
|
|
51
51
|
"peerDependencies": {
|
|
52
|
-
"@zibby/core": ">=0.1.
|
|
52
|
+
"@zibby/core": ">=0.1.44"
|
|
53
53
|
},
|
|
54
54
|
"optionalDependencies": {
|
|
55
55
|
"@zibby/mcp-browser": "^0.1.8",
|