@crewx/sdk 0.8.2-rc.1 → 0.8.2-rc.3

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.
@@ -1,4 +1,4 @@
1
- import {existsSync,mkdirSync,writeFileSync,appendFileSync}from'fs';import*as x from'path';import {join,dirname,basename}from'path';import {homedir}from'os';import U from'better-sqlite3';import {createHash}from'crypto';var l=class{detach(s){}};function S(i){let s=t=>String(t).padStart(2,"0");return `${i.getFullYear()}${s(i.getMonth()+1)}${s(i.getDate())}T${s(i.getHours())}${s(i.getMinutes())}${s(i.getSeconds())}`}var h=class extends l{name="file-logger";unsubs=[];logFiles=new Map;logsDir;version;constructor(s){super(),this.logsDir=join(s?.workspaceRoot??process.cwd(),".crewx","logs"),this.version=s?.version??"unknown";}attach(s){this.unsubs.push(s.on("task:start",t=>{try{existsSync(this.logsDir)||mkdirSync(this.logsDir,{recursive:!0});let r=S(t.timestamp),a=join(this.logsDir,`${r}_${t.traceId}.log`);this.logFiles.set(t.traceId,a);let o=`=== TASK LOG: ${t.traceId} ===
1
+ import {existsSync,mkdirSync,writeFileSync,appendFileSync}from'fs';import*as x from'path';import {join,dirname,basename}from'path';import {homedir}from'os';import F from'better-sqlite3';import {createHash}from'crypto';var l=class{detach(s){}};function y(i){let s=t=>String(t).padStart(2,"0");return `${i.getFullYear()}${s(i.getMonth()+1)}${s(i.getDate())}T${s(i.getHours())}${s(i.getMinutes())}${s(i.getSeconds())}`}var h=class extends l{name="file-logger";unsubs=[];logFiles=new Map;logsDir;version;constructor(s){super(),this.logsDir=join(s?.workspaceRoot??process.cwd(),".crewx","logs"),this.version=s?.version??"unknown";}attach(s){this.unsubs.push(s.on("task:start",t=>{try{existsSync(this.logsDir)||mkdirSync(this.logsDir,{recursive:!0});let r=y(t.timestamp),a=join(this.logsDir,`${r}_${t.traceId}.log`);this.logFiles.set(t.traceId,a);let o=`=== TASK LOG: ${t.traceId} ===
2
2
  CrewX Version: ${this.version}
3
3
  Mode: ${t.mode}
4
4
  Agent: ${t.agentRef}
@@ -8,7 +8,7 @@ Message: ${t.message}
8
8
  `;writeFileSync(a,o,{encoding:"utf8",mode:384});}catch{}}),s.on("task:output",t=>{try{let r=this.logFiles.get(t.traceId);if(!r)return;let a=new Date().toISOString();appendFileSync(r,`[${a}] STDOUT: ${t.output}
9
9
  `,"utf8");}catch{}}),s.on("task:end",t=>{try{let r=this.logFiles.get(t.traceId);if(!r)return;let a=new Date().toLocaleString(),o=t.error?`failed: ${t.error.message}`:"completed successfully",u=`[${a}] INFO: Task ${o} in ${t.durationMs}ms
10
10
  [${a}] INFO: Process closed with exit code: ${t.error?1:0}
11
- `;appendFileSync(r,u,"utf8"),this.logFiles.delete(t.traceId);}catch{}}));}detach(s){this.unsubs.forEach(t=>t()),this.unsubs=[],this.logFiles.clear();}};function L(i){let s=x.resolve(i);return process.platform==="win32"&&(s=s.replace(/\\/g,"/"),s=s.replace(/^([A-Z]):/,(t,r)=>`${r.toLowerCase()}:`)),s.length>1&&!/^[a-zA-Z]:\/$/.test(s)&&(s=s.replace(/\/+$/,"")),s}function C(i){let s=L(i);return createHash("sha256").update(s).digest("hex")}var T=class extends l{name="sqlite-tracing";db=null;unsubs=[];dbPath;version;constructor(s){super(),this.dbPath=join(s?.dbRoot??homedir(),".crewx","crewx.db"),this.version=s?.version??"unknown";}attach(s){let t=dirname(this.dbPath);if(existsSync(t)||mkdirSync(t,{recursive:true}),this.db=new U(this.dbPath),this.db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='tasks'").get()!==void 0){let e=this.db.prepare("PRAGMA table_info(tasks)").all(),n=d=>e.some(m=>m.name===d);n("parent_task_id")||this.db.exec("ALTER TABLE tasks ADD COLUMN parent_task_id TEXT"),n("caller_agent_id")||this.db.exec("ALTER TABLE tasks ADD COLUMN caller_agent_id TEXT"),n("trace_id")||this.db.exec("ALTER TABLE tasks ADD COLUMN trace_id TEXT");}let a=process.cwd(),o=existsSync(join(a,"crewx.yaml"))||existsSync(join(a,"crewx.yml")),u=o?C(a):null,b=o?basename(a):null,f=process.argv.join(" ");this.unsubs.push(s.on("task:start",e=>{try{let n=process.env.CREWX_CALLER_AGENT_ID||null,d=process.env.CREWX_PARENT_TASK_ID||null,m=process.env.CREWX_TRACE_ID||e.traceId,v=e.metadata?JSON.stringify(e.metadata):JSON.stringify({provider:e.provider??"cli/claude"});this.db.prepare(`INSERT OR IGNORE INTO tasks
11
+ `;appendFileSync(r,u,"utf8"),this.logFiles.delete(t.traceId);}catch{}}));}detach(s){this.unsubs.forEach(t=>t()),this.unsubs=[],this.logFiles.clear();}};function R(i){let s=x.resolve(i);return process.platform==="win32"&&(s=s.replace(/\\/g,"/"),s=s.replace(/^([A-Z]):/,(t,r)=>`${r.toLowerCase()}:`)),s.length>1&&!/^[a-zA-Z]:\/$/.test(s)&&(s=s.replace(/\/+$/,"")),s}function C(i){let s=R(i);return createHash("sha256").update(s).digest("hex")}var T=class extends l{name="sqlite-tracing";db=null;unsubs=[];dbPath;version;constructor(s){super(),this.dbPath=join(s?.dbRoot??homedir(),".crewx","crewx.db"),this.version=s?.version??"unknown";}attach(s){let t=dirname(this.dbPath);if(existsSync(t)||mkdirSync(t,{recursive:true}),this.db=new F(this.dbPath),this.db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='tasks'").get()!==void 0){let e=this.db.prepare("PRAGMA table_info(tasks)").all(),n=d=>e.some(m=>m.name===d);n("parent_task_id")||this.db.exec("ALTER TABLE tasks ADD COLUMN parent_task_id TEXT"),n("caller_agent_id")||this.db.exec("ALTER TABLE tasks ADD COLUMN caller_agent_id TEXT"),n("trace_id")||this.db.exec("ALTER TABLE tasks ADD COLUMN trace_id TEXT");}let a=process.cwd(),o=existsSync(join(a,"crewx.yaml"))||existsSync(join(a,"crewx.yml")),u=o?C(a):null,S=o?basename(a):null,f=process.argv.join(" ");this.unsubs.push(s.on("task:start",e=>{try{let n=process.env.CREWX_CALLER_AGENT_ID||null,d=process.env.CREWX_PARENT_TASK_ID||null,m=process.env.CREWX_TRACE_ID||e.traceId,v=e.metadata?JSON.stringify(e.metadata):JSON.stringify({provider:e.provider??"cli/claude"});this.db.prepare(`INSERT OR IGNORE INTO tasks
12
12
  (id, agent_id, prompt, mode, status, pid, started_at,
13
13
  crewx_version, platform,
14
14
  model, rendered_prompt, command, coding_agent_command,
@@ -18,7 +18,7 @@ Message: ${t.message}
18
18
  ?, ?,
19
19
  ?, ?, ?, ?,
20
20
  ?, ?,
21
- ?, ?, ?, ?, ?)`).run(e.traceId,e.agentRef.replace(/^@/,""),e.message,e.mode,e.pid??null,e.timestamp.toISOString(),this.version,e.platform??"cli",e.model??null,e.renderedPrompt??null,f,e.codingAgentCommand??null,e.workspaceId??u,e.workspaceName??b,n,d,m,v,e.threadId??null);}catch{}}),s.on("task:output",e=>{try{let n=this.db.prepare("SELECT logs FROM tasks WHERE id=?").get(e.traceId),d=n?.logs?JSON.parse(n.logs):[];d.push({timestamp:e.timestamp.toISOString(),level:e.level??"stdout",message:e.output}),this.db.prepare("UPDATE tasks SET logs=? WHERE id=?").run(JSON.stringify(d),e.traceId);}catch{}}),s.on("task:end",e=>{try{let n=e.error?"failed":"success";this.db.prepare(`UPDATE tasks
21
+ ?, ?, ?, ?, ?)`).run(e.traceId,e.agentRef.replace(/^@/,""),e.message,e.mode,e.pid??null,e.timestamp.toISOString(),this.version,e.platform??"cli",e.model??null,e.renderedPrompt??null,f,e.codingAgentCommand??null,e.workspaceId??u,e.workspaceName??S,n,d,m,v,e.threadId??null);}catch{}}),s.on("task:output",e=>{try{let n=this.db.prepare("SELECT logs FROM tasks WHERE id=?").get(e.traceId),d=n?.logs?JSON.parse(n.logs):[];d.push({timestamp:e.timestamp.toISOString(),level:e.level??"stdout",message:e.output}),this.db.prepare("UPDATE tasks SET logs=? WHERE id=?").run(JSON.stringify(d),e.traceId);}catch{}}),s.on("task:end",e=>{try{let n=e.error?"failed":"success";this.db.prepare(`UPDATE tasks
22
22
  SET status=?, result=?, error=?,
23
23
  completed_at=?, duration_ms=?,
24
24
  exit_code=?,
@@ -40,13 +40,14 @@ Message: ${t.message}
40
40
  )
41
41
  `,X=["id","thread_id","prompt","result","started_at","trace_id","status","parent_task_id","agent_id"];function q(i){return i.replace(/<conversation_history[^>]*>[\s\S]*?<\/conversation_history>/g,"").split(`
42
42
  `).filter(a=>!(a.startsWith("Loaded ")&&a.includes("layouts from")||a.includes("[dotenv@")||a.includes("[Nest]")&&a.includes("DEBUG")||a.startsWith("Registered custom layout:")||a.startsWith("Updated custom layout:"))).join(`
43
- `).trim()}function j(i){if(!i)return "";let s=i;try{let t=JSON.parse(s);Array.isArray(t)?s=t.filter(r=>r?.type==="text"&&r?.text).map(r=>r.text).join(`
44
- `):t&&typeof t=="object"&&t.result!==void 0&&(s=t.result||"");}catch{s=q(s);}return s}var g=class{db;constructor(s){let t=s??join(homedir(),".crewx","crewx.db");this.db=new U(t),this.init();}init(){this.db.pragma("journal_mode = WAL"),this.db.exec(H);}async ensureThread(s,t,r){let a=this.db.prepare("SELECT platform FROM threads WHERE id = ?").get(s);if(a){if(a.platform!==t)throw new Error(`Thread '${s}' already exists with platform '${a.platform}' \u2014 cannot change to '${t}' (platform is immutable)`);r&&this.db.prepare("UPDATE threads SET workspace_id = COALESCE(workspace_id, ?) WHERE id = ?").run(r,s);return}let o=new Date().toISOString();this.db.prepare("INSERT INTO threads (id, platform, workspace_id, message_count, created_at, updated_at) VALUES (?, ?, ?, 0, ?, ?)").run(s,t,r??null,o,o);}async fetchHistory(s,t){let r=t?.limit??100,a=["thread_id = ?","(parent_task_id IS NULL OR parent_task_id = '')","(status IN ('done', 'completed', 'success') OR status IS NULL)"],o=[s];t?.currentTraceId&&(a.push("trace_id != ?"),o.push(t.currentTraceId));let u=a.join(" AND "),f=`SELECT ${X.join(", ")} FROM tasks WHERE ${u} ORDER BY started_at ASC LIMIT ?`;o.push(r);let e=this.db.prepare(f).all(...o),n=this.db.prepare("SELECT platform, title, first_message, last_message, message_count, updated_at FROM threads WHERE id = ?").get(s),d=n?.platform??"cli",m=this.rowsToMessages(e);return {threadId:s,platform:d,messages:m,metadata:{title:n?.title??void 0,firstMessage:n?.first_message??void 0,lastMessage:n?.last_message??void 0,messageCount:n?.message_count??0,updatedAt:n?.updated_at?new Date(n.updated_at).getTime():void 0}}}async saveUserMessage(s,t,r,a){let o=new Date().toISOString();this.db.prepare(`UPDATE threads
43
+ `).trim()}function B(i){if(!i)return "";let s=i;try{let t=JSON.parse(s);Array.isArray(t)?s=t.filter(r=>r?.type==="text"&&r?.text).map(r=>r.text).join(`
44
+ `):t&&typeof t=="object"&&t.result!==void 0&&(s=t.result||"");}catch{s=q(s);}return s}var g=class{db;constructor(s){let t=s??join(homedir(),".crewx","crewx.db");this.db=new F(t),this.init();}init(){this.db.pragma("journal_mode = WAL"),this.db.exec(H),this.migrateThreadsTable();}migrateThreadsTable(){this.db.prepare("PRAGMA table_info(threads)").all().some(t=>t.name==="title_locked")||this.db.exec("ALTER TABLE threads ADD COLUMN title_locked INTEGER NOT NULL DEFAULT 0");}updateThread(s,t){t.title!==void 0&&this.db.prepare("UPDATE threads SET title = ?, title_locked = 1, updated_at = ? WHERE id = ?").run(t.title,new Date().toISOString(),s);}async ensureThread(s,t,r){let a=this.db.prepare("SELECT platform FROM threads WHERE id = ?").get(s);if(a){if(a.platform!==t)throw new Error(`Thread '${s}' already exists with platform '${a.platform}' \u2014 cannot change to '${t}' (platform is immutable)`);r&&this.db.prepare("UPDATE threads SET workspace_id = COALESCE(workspace_id, ?) WHERE id = ?").run(r,s);return}let o=new Date().toISOString();this.db.prepare("INSERT INTO threads (id, platform, workspace_id, message_count, created_at, updated_at) VALUES (?, ?, ?, 0, ?, ?)").run(s,t,r??null,o,o);}async fetchHistory(s,t){let r=t?.limit??100,a=["thread_id = ?","(parent_task_id IS NULL OR parent_task_id = '')","(status IN ('done', 'completed', 'success') OR status IS NULL)"],o=[s];t?.currentTraceId&&(a.push("trace_id != ?"),o.push(t.currentTraceId));let u=a.join(" AND "),f=`SELECT ${X.join(", ")} FROM tasks WHERE ${u} ORDER BY started_at ASC LIMIT ?`;o.push(r);let e=this.db.prepare(f).all(...o),n=this.db.prepare("SELECT platform, title, first_message, last_message, message_count, updated_at FROM threads WHERE id = ?").get(s),d=n?.platform??"cli",m=this.rowsToMessages(e);return {threadId:s,platform:d,messages:m,metadata:{title:n?.title??void 0,firstMessage:n?.first_message??void 0,lastMessage:n?.last_message??void 0,messageCount:n?.message_count??0,updatedAt:n?.updated_at?new Date(n.updated_at).getTime():void 0}}}async saveUserMessage(s,t,r,a){let o=new Date().toISOString();this.db.prepare(`UPDATE threads
45
45
  SET first_message = COALESCE(first_message, ?),
46
+ title = CASE WHEN title_locked = 0 AND title IS NULL THEN substr(?, 1, 60) ELSE title END,
46
47
  last_message = ?,
47
48
  message_count = message_count + 1,
48
49
  updated_at = ?
49
- WHERE id = ?`).run(t,t,o,s);}async saveAssistantMessage(s,t,r,a){let o=new Date().toISOString();this.db.prepare(`UPDATE threads
50
+ WHERE id = ?`).run(t,t,t,o,s);}async saveAssistantMessage(s,t,r,a){let o=new Date().toISOString();this.db.prepare(`UPDATE threads
50
51
  SET last_message = ?,
51
52
  updated_at = ?
52
- WHERE id = ?`).run(t,o,s);}close(){this.db.close();}rowsToMessages(s){let t=[];for(let r of s){r.prompt&&t.push({id:`${r.id}-user`,text:r.prompt,isAssistant:false,timestamp:new Date(r.started_at).getTime()});let a=j(r.result);a&&t.push({id:`${r.id}-assistant`,text:a,isAssistant:true,timestamp:new Date(r.started_at).getTime()});}return t}};var y=class extends l{name="conversation";_provider;unsubStart=null;unsubEnd=null;constructor(s){super(),this._provider=new g(s?.dbPath);}get conversationProvider(){return this._provider}attach(s){this.unsubStart=s.on("task:start",async t=>{if(!t.threadId)return;let r=t.platform??"cli";try{await this._provider.ensureThread(t.threadId,r,t.workspaceId),await this._provider.saveUserMessage(t.threadId,t.message??"");}catch{}}),this.unsubEnd=s.on("task:end",async t=>{if(!t.result)return;let r=t.metadata?.threadId;if(!r)return;let a=t.agentRef?.replace(/^@/,"")??"";try{await this._provider.saveAssistantMessage(r,t.result,a);}catch{}});}detach(s){this.unsubStart?.(),this.unsubStart=null,this.unsubEnd?.(),this.unsubEnd=null,this._provider.close?.();}};export{y as ConversationPlugin,h as FileLoggerPlugin,T as SqliteTracingPlugin};
53
+ WHERE id = ?`).run(t,o,s);}close(){this.db.close();}rowsToMessages(s){let t=[];for(let r of s){r.prompt&&t.push({id:`${r.id}-user`,text:r.prompt,isAssistant:false,timestamp:new Date(r.started_at).getTime()});let a=B(r.result);a&&t.push({id:`${r.id}-assistant`,text:a,isAssistant:true,timestamp:new Date(r.started_at).getTime()});}return t}};var b=class extends l{name="conversation";_provider;unsubStart=null;unsubEnd=null;constructor(s){super(),this._provider=new g(s?.dbPath);}get conversationProvider(){return this._provider}attach(s){this.unsubStart=s.on("task:start",async t=>{if(!t.threadId)return;let r=t.platform??"cli";try{await this._provider.ensureThread(t.threadId,r,t.workspaceId),await this._provider.saveUserMessage(t.threadId,t.message??"");}catch{}}),this.unsubEnd=s.on("task:end",async t=>{if(!t.result)return;let r=t.metadata?.threadId;if(!r)return;let a=t.agentRef?.replace(/^@/,"")??"";try{await this._provider.saveAssistantMessage(r,t.result,a);}catch{}});}detach(s){this.unsubStart?.(),this.unsubStart=null,this.unsubEnd?.(),this.unsubEnd=null,this._provider.close?.();}};export{b as ConversationPlugin,h as FileLoggerPlugin,T as SqliteTracingPlugin};
@@ -95,6 +95,7 @@ export declare class Crewx extends TypedEventEmitter {
95
95
  private _extractLayoutProps;
96
96
  private _getConversationProvider;
97
97
  private _fetchHistoryMessages;
98
+ private _resolveTimeoutConfig;
98
99
  private emitToolEvents;
99
100
  private tryParseJson;
100
101
  query(agentRef: string, message: string, options?: QueryOptions): Promise<QueryResult>;
@@ -1,2 +1,2 @@
1
- import {load}from'js-yaml';import {z}from'zod';var m=class extends Error{constructor(e,n){let r=n.length>0?` Available: ${n.join(", ")}`:"";super(`Agent not found: "${e}".${r}`),this.name="AgentNotFoundError";}},I={claude:{id:"claude",provider:"cli/claude"},gemini:{id:"gemini",provider:"cli/gemini"},copilot:{id:"copilot",provider:"cli/copilot"},codex:{id:"codex",provider:"cli/codex"}};function x(a,e){let n=a.startsWith("@")?a.slice(1):a,r=e.find(t=>t.id===n);if(r)return r;let i=I[n];if(i)return i;throw new m(a,e.map(t=>t.id))}var l=class extends Error{constructor(n,r){super(n);this.providerStr=r;this.name="ProviderError";}providerStr},O=new Map;function P(a,e){O.set(a,e);}function w(a){let e=a.split("/");if(e.length!==2)throw new l(`Invalid provider format: "${a}". Expected namespace/id (e.g., api/webllm)`,a);let[n,r]=e,i=O.get(n);if(i)return i(r,a);throw new l(`Unsupported provider namespace: "${n}". Register a factory with registerProviderFactory('${n}', factory).`,a)}var j=new Function("u","return import(u)"),C=class a{_agents;_config;_tools=new Map;_apiProviders=new Map;constructor(e,n){this._agents=new Map(e.map(r=>[r.id,r])),this._config=n;}static async fromConfig(e,n){let r=new a(e.agents??[],e),i=e.agents??[],t=s=>Array.isArray(s.provider)?s.provider[0]:s.provider,c=i.filter(s=>t(s)==="api/webllm"),g=i.filter(s=>t(s)==="api/openrouter");if(c.length>0&&await r._initWebLLM(c,n?.onProgress),g.length>0){if(!n?.openrouterApiKey)throw new Error("openrouterApiKey is required when using api/openrouter provider");r._initOpenRouter(g,n.openrouterApiKey);}return r._apiProviders.size>0&&P("api",(s,d)=>{let p=r._apiProviders.get(s);if(!p)throw new l(`Unknown api provider: ${s}`,d);return p}),r}async _initWebLLM(e,n){if(typeof navigator>"u"||!navigator.gpu)throw new Error("WebGPU is not available. Chrome 113+ or Edge 113+ required.");let r=await j("https://esm.run/@mlc-ai/web-llm"),i=e[0]?.inline?.model??"gemma-2-2b-it-q4f16_1-MLC",t=await r.CreateMLCEngine(i,{initProgressCallback:n?g=>n(g):void 0}),c=[];this._apiProviders.set("webllm",{async query(g,s){let d=[];s?.systemPrompt&&d.push({role:"system",content:s.systemPrompt}),d.push(...c),d.push({role:"user",content:g});let p="",u=await t.chat.completions.create({messages:d,stream:true,temperature:.7,max_tokens:4096});for await(let y of u){let v=y.choices?.[0]?.delta?.content??"";p+=v,s?.onOutput&&s.onOutput(p,"stdout");}return c.push({role:"user",content:g}),c.push({role:"assistant",content:p}),p},async execute(g,s){return this.query(g,s)}});}_initOpenRouter(e,n){let r=e[0]?.inline?.model??"google/gemma-2-2b-it",i=[];this._apiProviders.set("openrouter",{async query(t,c){let g=[];c?.systemPrompt&&g.push({role:"system",content:c.systemPrompt}),g.push(...i),g.push({role:"user",content:t});let s=await fetch("https://openrouter.ai/api/v1/chat/completions",{method:"POST",headers:{Authorization:`Bearer ${n}`,"Content-Type":"application/json"},body:JSON.stringify({model:c?.model||r,messages:g,stream:true})});if(!s.ok){let v=await s.text();throw new Error(`OpenRouter API error (${s.status}): ${v}`)}let d=s.body.getReader(),p=new TextDecoder,u="",y="";for(;;){let{done:v,value:M}=await d.read();if(v)break;y+=p.decode(M,{stream:true});let b=y.split(`
2
- `);y=b.pop();for(let _ of b){let h=_.trim();if(!h||!h.startsWith("data: "))continue;let k=h.slice(6);if(k!=="[DONE]")try{let R=JSON.parse(k).choices?.[0]?.delta?.content??"";u+=R,R&&c?.onOutput&&c.onOutput(u,"stdout");}catch{}}}return i.push({role:"user",content:t}),i.push({role:"assistant",content:u}),u},async execute(t,c){return this.query(t,c)}});}get agents(){return this._agents}get config(){return this._config}get tools(){return this._tools}registerTool(e,n){this._tools.set(e,{name:e,...n});}async query(e,n,r){let i=Date.now(),t;try{t=x(e,Array.from(this._agents.values()));}catch(p){if(p instanceof m)return {ok:false,data:"",error:{code:"AGENT_NOT_FOUND",message:p.message},meta:{agentId:e.replace(/^@/,""),provider:"",durationMs:Date.now()-i}};throw p}let c=Array.isArray(t.provider)?t.provider[0]??"api/default":t.provider,g=r?.provider??c,s=r?.model??t.inline?.model,d;try{d=w(g);}catch(p){return {ok:false,data:"",error:{code:"PROVIDER_ERROR",message:p.message},meta:{agentId:t.id,provider:g,model:s,durationMs:Date.now()-i}}}try{return {ok:!0,data:await d.query(n,{model:s,context:r?.context,systemPrompt:t.inline?.system_prompt??t.inline?.prompt,onOutput:r?.onOutput?u=>r.onOutput(u):void 0}),meta:{agentId:t.id,provider:g,model:s,durationMs:Date.now()-i}}}catch(p){return {ok:false,data:"",error:{code:"QUERY_FAILED",message:p.message},meta:{agentId:t.id,provider:g,model:s,durationMs:Date.now()-i}}}}async execute(e,n,r){let i=Date.now(),t;try{t=x(e,Array.from(this._agents.values()));}catch(p){if(p instanceof m)return {ok:false,data:"",error:{code:"AGENT_NOT_FOUND",message:p.message},meta:{agentId:e.replace(/^@/,""),provider:"",durationMs:Date.now()-i}};throw p}let c=Array.isArray(t.provider)?t.provider[0]??"api/default":t.provider,g=r?.provider??c,s=r?.model??t.inline?.model,d;try{d=w(g);}catch(p){return {ok:false,data:"",error:{code:"PROVIDER_ERROR",message:p.message},meta:{agentId:t.id,provider:g,model:s,durationMs:Date.now()-i}}}try{return {ok:!0,data:await d.execute(n,{model:s,context:r?.context,systemPrompt:t.inline?.system_prompt??t.inline?.prompt}),meta:{agentId:t.id,provider:g,model:s,durationMs:Date.now()-i}}}catch(p){return {ok:false,data:"",error:{code:"EXECUTE_FAILED",message:p.message},meta:{agentId:t.id,provider:g,model:s,durationMs:Date.now()-i}}}}};var F=z.object({model:z.string().optional(),system_prompt:z.string().optional(),prompt:z.string().optional(),layout:z.union([z.string(),z.object({id:z.string(),props:z.record(z.unknown()).optional()}),z.object({props:z.record(z.unknown())}),z.object({template:z.string()})]).optional()}).catchall(z.unknown()),D=z.object({id:z.string(),name:z.string().optional(),role:z.string().optional(),team:z.string().optional(),provider:z.union([z.string(),z.array(z.string())]),working_directory:z.string().optional(),description:z.string().optional(),tags:z.array(z.string()).optional(),inline:F.optional()}).catchall(z.unknown()),E=z.object({agents:z.array(D).optional(),hooks:z.array(z.unknown()).optional(),settings:z.record(z.unknown()).optional(),skills:z.unknown().optional(),layouts:z.record(z.unknown()).optional(),documents:z.record(z.unknown()).optional()}).catchall(z.unknown());var f=class extends Error{constructor(n,r){super(n);this.cause=r;this.name="ConfigLoadError";}cause};function Q(a){if(!a||typeof a!="string"||!a.trim())throw new f("YAML content must be a non-empty string");let e;try{e=load(a);}catch(i){throw new f(`YAML parse error: ${i.message}`,i)}let n=$(e),r=E.safeParse(n);if(!r.success)throw new f(`Config validation error: ${r.error.message}`);return r.data}function $(a){if(!a||typeof a!="object")return {agents:[]};let e=a;if(e.agents&&typeof e.agents=="object"&&!Array.isArray(e.agents)){let n=e.agents,r=Object.entries(n).map(([i,t])=>({id:i,...t&&typeof t=="object"?t:{}}));return {...e,agents:r}}return e.agents?e:{...e,agents:[]}}var B="crewx:fs:",A=class{prefix;store;constructor(e){this.prefix=e?.prefix??B,this.store=e?.storage??new Map;}async readFile(e){let n=this.toKey(e),r=this.store.get(n);if(r===void 0)throw new Error(`BrowserFsAdapter: file not found: ${e}`);return r}async exists(e){return this.store.has(this.toKey(e))}resolvePath(...e){let n=e.map(c=>c.replace(/\\/g,"/")).join("/").replace(/\/+/g,"/"),r=n.split("/"),i=[];for(let c of r)c==="."||c===""||(c===".."?i.pop():i.push(c));let t=i.join("/");return n.startsWith("/")?`/${t}`:t}isAbsolute(e){return e.startsWith("/")}setItem(e,n){this.store.set(this.toKey(e),n);}removeItem(e){this.store.delete(this.toKey(e));}keys(){return Array.from(this.store.keys()).filter(e=>e.startsWith(this.prefix)).map(e=>e.slice(this.prefix.length))}toKey(e){return `${this.prefix}${e.replace(/\\/g,"/")}`}};export{A as BrowserFsAdapter,f as ConfigLoadError,C as Crewx,l as ProviderError,w as createProvider,Q as parseYamlContent,P as registerProviderFactory};
1
+ import {load}from'js-yaml';import {z}from'zod';var m=class extends Error{constructor(e,n){let t=n.length>0?` Available: ${n.join(", ")}`:"";super(`Agent not found: "${e}".${t}`),this.name="AgentNotFoundError";}},I={claude:{id:"claude",provider:"cli/claude"},gemini:{id:"gemini",provider:"cli/gemini"},copilot:{id:"copilot",provider:"cli/copilot"},codex:{id:"codex",provider:"cli/codex"}};function x(a,e){let n=a.startsWith("@")?a.slice(1):a,t=e.find(o=>o.id===n);if(t)return t;let i=I[n];if(i)return i;throw new m(a,e.map(o=>o.id))}var l=class extends Error{constructor(n,t){super(n);this.providerStr=t;this.name="ProviderError";}providerStr};var O=new Map;function P(a,e){O.set(a,e);}function w(a){let e=a.split("/");if(e.length!==2)throw new l(`Invalid provider format: "${a}". Expected namespace/id (e.g., api/webllm)`,a);let[n,t]=e,i=O.get(n);if(i)return i(t,a);throw new l(`Unsupported provider namespace: "${n}". Register a factory with registerProviderFactory('${n}', factory).`,a)}var j=new Function("u","return import(u)"),C=class a{_agents;_config;_tools=new Map;_apiProviders=new Map;constructor(e,n){this._agents=new Map(e.map(t=>[t.id,t])),this._config=n;}static async fromConfig(e,n){let t=new a(e.agents??[],e),i=e.agents??[],o=s=>Array.isArray(s.provider)?s.provider[0]:s.provider,c=i.filter(s=>o(s)==="api/webllm"),g=i.filter(s=>o(s)==="api/openrouter");if(c.length>0&&await t._initWebLLM(c,n?.onProgress),g.length>0){if(!n?.openrouterApiKey)throw new Error("openrouterApiKey is required when using api/openrouter provider");t._initOpenRouter(g,n.openrouterApiKey);}return t._apiProviders.size>0&&P("api",(s,d)=>{let p=t._apiProviders.get(s);if(!p)throw new l(`Unknown api provider: ${s}`,d);return p}),t}async _initWebLLM(e,n){if(typeof navigator>"u"||!navigator.gpu)throw new Error("WebGPU is not available. Chrome 113+ or Edge 113+ required.");let t=await j("https://esm.run/@mlc-ai/web-llm"),i=e[0]?.inline?.model??"gemma-2-2b-it-q4f16_1-MLC",o=await t.CreateMLCEngine(i,{initProgressCallback:n?g=>n(g):void 0}),c=[];this._apiProviders.set("webllm",{async query(g,s){let d=[];s?.systemPrompt&&d.push({role:"system",content:s.systemPrompt}),d.push(...c),d.push({role:"user",content:g});let p="",u=await o.chat.completions.create({messages:d,stream:true,temperature:.7,max_tokens:4096});for await(let y of u){let v=y.choices?.[0]?.delta?.content??"";p+=v,s?.onOutput&&s.onOutput(p,"stdout");}return c.push({role:"user",content:g}),c.push({role:"assistant",content:p}),p},async execute(g,s){return this.query(g,s)}});}_initOpenRouter(e,n){let t=e[0]?.inline?.model??"google/gemma-2-2b-it",i=[];this._apiProviders.set("openrouter",{async query(o,c){let g=[];c?.systemPrompt&&g.push({role:"system",content:c.systemPrompt}),g.push(...i),g.push({role:"user",content:o});let s=await fetch("https://openrouter.ai/api/v1/chat/completions",{method:"POST",headers:{Authorization:`Bearer ${n}`,"Content-Type":"application/json"},body:JSON.stringify({model:c?.model||t,messages:g,stream:true})});if(!s.ok){let v=await s.text();throw new Error(`OpenRouter API error (${s.status}): ${v}`)}let d=s.body.getReader(),p=new TextDecoder,u="",y="";for(;;){let{done:v,value:M}=await d.read();if(v)break;y+=p.decode(M,{stream:true});let b=y.split(`
2
+ `);y=b.pop();for(let _ of b){let h=_.trim();if(!h||!h.startsWith("data: "))continue;let k=h.slice(6);if(k!=="[DONE]")try{let R=JSON.parse(k).choices?.[0]?.delta?.content??"";u+=R,R&&c?.onOutput&&c.onOutput(u,"stdout");}catch{}}}return i.push({role:"user",content:o}),i.push({role:"assistant",content:u}),u},async execute(o,c){return this.query(o,c)}});}get agents(){return this._agents}get config(){return this._config}get tools(){return this._tools}registerTool(e,n){this._tools.set(e,{name:e,...n});}async query(e,n,t){let i=Date.now(),o;try{o=x(e,Array.from(this._agents.values()));}catch(p){if(p instanceof m)return {ok:false,data:"",error:{code:"AGENT_NOT_FOUND",message:p.message},meta:{agentId:e.replace(/^@/,""),provider:"",durationMs:Date.now()-i}};throw p}let c=Array.isArray(o.provider)?o.provider[0]??"api/default":o.provider,g=t?.provider??c,s=t?.model??o.inline?.model,d;try{d=w(g);}catch(p){return {ok:false,data:"",error:{code:"PROVIDER_ERROR",message:p.message},meta:{agentId:o.id,provider:g,model:s,durationMs:Date.now()-i}}}try{return {ok:!0,data:await d.query(n,{model:s,context:t?.context,systemPrompt:o.inline?.system_prompt??o.inline?.prompt,onOutput:t?.onOutput?u=>t.onOutput(u):void 0}),meta:{agentId:o.id,provider:g,model:s,durationMs:Date.now()-i}}}catch(p){return {ok:false,data:"",error:{code:"QUERY_FAILED",message:p.message},meta:{agentId:o.id,provider:g,model:s,durationMs:Date.now()-i}}}}async execute(e,n,t){let i=Date.now(),o;try{o=x(e,Array.from(this._agents.values()));}catch(p){if(p instanceof m)return {ok:false,data:"",error:{code:"AGENT_NOT_FOUND",message:p.message},meta:{agentId:e.replace(/^@/,""),provider:"",durationMs:Date.now()-i}};throw p}let c=Array.isArray(o.provider)?o.provider[0]??"api/default":o.provider,g=t?.provider??c,s=t?.model??o.inline?.model,d;try{d=w(g);}catch(p){return {ok:false,data:"",error:{code:"PROVIDER_ERROR",message:p.message},meta:{agentId:o.id,provider:g,model:s,durationMs:Date.now()-i}}}try{return {ok:!0,data:await d.execute(n,{model:s,context:t?.context,systemPrompt:o.inline?.system_prompt??o.inline?.prompt}),meta:{agentId:o.id,provider:g,model:s,durationMs:Date.now()-i}}}catch(p){return {ok:false,data:"",error:{code:"EXECUTE_FAILED",message:p.message},meta:{agentId:o.id,provider:g,model:s,durationMs:Date.now()-i}}}}};var F=z.object({model:z.string().optional(),system_prompt:z.string().optional(),prompt:z.string().optional(),layout:z.union([z.string(),z.object({id:z.string(),props:z.record(z.unknown()).optional()}),z.object({props:z.record(z.unknown())}),z.object({template:z.string()})]).optional()}).catchall(z.unknown()),D=z.object({include:z.array(z.string()).optional()}).optional(),T=z.object({id:z.string(),name:z.string().optional(),role:z.string().optional(),team:z.string().optional(),provider:z.union([z.string(),z.array(z.string())]),working_directory:z.string().optional(),description:z.string().optional(),tags:z.array(z.string()).optional(),inline:F.optional(),timeoutMs:z.number().optional(),idleTimeoutMs:z.number().optional(),skills:D}).catchall(z.unknown()),E=z.object({agents:z.array(T).optional(),hooks:z.array(z.unknown()).optional(),settings:z.record(z.unknown()).optional(),skills:z.unknown().optional(),layouts:z.record(z.unknown()).optional(),documents:z.record(z.unknown()).optional()}).catchall(z.unknown());var f=class extends Error{constructor(n,t){super(n);this.cause=t;this.name="ConfigLoadError";}cause};function $(a){if(!a||typeof a!="string"||!a.trim())throw new f("YAML content must be a non-empty string");let e;try{e=load(a);}catch(i){throw new f(`YAML parse error: ${i.message}`,i)}let n=S(e),t=E.safeParse(n);if(!t.success)throw new f(`Config validation error: ${t.error.message}`);return t.data}function S(a){if(!a||typeof a!="object")return {agents:[]};let e=a;if(e.agents&&typeof e.agents=="object"&&!Array.isArray(e.agents)){let n=e.agents,t=Object.entries(n).map(([i,o])=>({id:i,...o&&typeof o=="object"?o:{}}));return {...e,agents:t}}return e.agents?e:{...e,agents:[]}}var B="crewx:fs:",A=class{prefix;store;constructor(e){this.prefix=e?.prefix??B,this.store=e?.storage??new Map;}async readFile(e){let n=this.toKey(e),t=this.store.get(n);if(t===void 0)throw new Error(`BrowserFsAdapter: file not found: ${e}`);return t}async exists(e){return this.store.has(this.toKey(e))}resolvePath(...e){let n=e.map(c=>c.replace(/\\/g,"/")).join("/").replace(/\/+/g,"/"),t=n.split("/"),i=[];for(let c of t)c==="."||c===""||(c===".."?i.pop():i.push(c));let o=i.join("/");return n.startsWith("/")?`/${o}`:o}isAbsolute(e){return e.startsWith("/")}setItem(e,n){this.store.set(this.toKey(e),n);}removeItem(e){this.store.delete(this.toKey(e));}keys(){return Array.from(this.store.keys()).filter(e=>e.startsWith(this.prefix)).map(e=>e.slice(this.prefix.length))}toKey(e){return `${this.prefix}${e.replace(/\\/g,"/")}`}};export{A as BrowserFsAdapter,f as ConfigLoadError,C as Crewx,l as ProviderError,w as createProvider,$ as parseYamlContent,P as registerProviderFactory};
package/dist/index.d.ts CHANGED
@@ -19,8 +19,10 @@ export { BrowserFsAdapter } from './platform/BrowserFsAdapter';
19
19
  export { truncateHelper, lengthHelper, escapeHandlebarsHelper, formatFileSizeHelper, formatTimestampHelper, } from './template/helpers/p1p2';
20
20
  export { setAuditVerbose } from './template/helpers/exec';
21
21
  export type { AgentConfig, CrewxProjectConfig, CrewxOptions, QueryOptions, QueryResult, ExecuteOptions, ExecuteResult, YamlHookEntry, GuideRule, } from './types';
22
+ export { AgentSkillsSchema } from './types';
22
23
  export { loadYamlFile, parseYamlContent, ConfigLoadError } from './config/loader';
23
24
  export { resolveAgent, AgentNotFoundError } from './agent/resolver';
25
+ export { resolveAgentSkills } from './agent/resolve-skills';
24
26
  export { createProvider, ProviderError, ClientToolCallRequiredError, registerProviderFactory } from './provider/bridge';
25
27
  export type { ProviderRuntime, ProviderQueryOptions, ProviderFactory, ClientToolCall, ContinuationState } from './provider/bridge';
26
28
  export { VercelProviderRuntime } from './provider/vercel-runtime';