@crewx/sdk 0.9.0-rc.53 → 0.9.0-rc.55
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/config/canonicalize-agent-options.d.ts +1 -0
- package/dist/config/model-compat.d.ts +16 -0
- package/dist/config/models.generated.d.ts +8 -0
- package/dist/config/pricing.d.ts +6 -3
- package/dist/config/pricing.generated.d.ts +4 -0
- package/dist/config/pricing.types.d.ts +4 -0
- package/dist/esm/index.js +48 -48
- package/dist/esm/plugins/index.js +30 -30
- package/dist/esm/publish/index.js +1 -1
- package/dist/esm/repository/index.js +5 -5
- package/dist/esm/testing/index.js +1 -1
- package/dist/index.browser.d.ts +2 -0
- package/dist/index.browser.js +4 -4
- package/dist/index.d.ts +5 -3
- package/dist/index.js +50 -50
- package/dist/plugins/index.js +38 -38
- package/dist/provider/acp/meta.d.ts +5 -0
- package/dist/provider/cli/adapter.types.d.ts +2 -0
- package/dist/provider/cli/meta.d.ts +3 -0
- package/dist/provider/models.d.ts +8 -3
- package/dist/publish/index.js +1 -1
- package/dist/repository/index.js +12 -12
- package/dist/testing/index.js +1 -1
- package/dist/utils/timestamp.d.ts +1 -0
- package/package.json +1 -1
- package/templates/agents/default.yaml +2 -2
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import*as F from'path';import F__default,{join,dirname}from'path';import {fileURLToPath}from'url';import {existsSync,mkdirSync,writeFileSync,appendFileSync,readFileSync}from'fs';import ae,{homedir}from'os';import {createHash}from'crypto';import {sql,eq,desc,and,isNull,lt,or,notLike,like,asc,inArray,gte,isNotNull,ne}from'drizzle-orm';import {sqliteTable,text,integer,real,index,unique,uniqueIndex,primaryKey}from'drizzle-orm/sqlite-core';var dt=(d=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(d,{get:(t,n)=>(typeof require<"u"?require:t)[n]}):d)(function(d){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+d+'" is not supported')});var
|
|
1
|
+
import*as F from'path';import F__default,{join,dirname}from'path';import {fileURLToPath}from'url';import {existsSync,mkdirSync,writeFileSync,appendFileSync,readFileSync}from'fs';import ae,{homedir}from'os';import {createHash}from'crypto';import {sql,eq,desc,and,isNull,lt,or,notLike,like,asc,inArray,gte,isNotNull,ne}from'drizzle-orm';import {sqliteTable,text,integer,real,index,unique,uniqueIndex,primaryKey}from'drizzle-orm/sqlite-core';var dt=(d=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(d,{get:(t,n)=>(typeof require<"u"?require:t)[n]}):d)(function(d){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+d+'" is not supported')});var Qt=()=>fileURLToPath(import.meta.url),Zt=()=>F__default.dirname(Qt()),k=Zt();var j=class{detach(t){}};function Ot(d){let t=n=>String(n).padStart(2,"0");return `${d.getFullYear()}${t(d.getMonth()+1)}${t(d.getDate())}T${t(d.getHours())}${t(d.getMinutes())}${t(d.getSeconds())}`}function wt(d){let t=d.toISOString();return `${t.slice(0,10)} ${t.slice(11,19)} UTC`}var Et=class extends j{name="file-logger";unsubs=[];logFiles=new Map;logsDir;version;constructor(t){super(),this.logsDir=join(t?.workspaceRoot??process.cwd(),".crewx","logs"),this.version=t?.version??"unknown";}attach(t){this.unsubs.push(t.on("task:start",n=>{try{existsSync(this.logsDir)||mkdirSync(this.logsDir,{recursive:!0});let s=Ot(n.timestamp),r=join(this.logsDir,`${s}_${n.traceId}.log`);this.logFiles.set(n.traceId,r);let o=`=== TASK LOG: ${n.traceId} ===
|
|
2
2
|
CrewX Version: ${this.version}
|
|
3
3
|
Mode: ${n.mode}
|
|
4
4
|
Agent: ${n.agentRef}
|
|
5
|
-
Started: ${n.timestamp
|
|
5
|
+
Started: ${wt(n.timestamp)}
|
|
6
6
|
Message: ${n.message}
|
|
7
7
|
|
|
8
8
|
`;writeFileSync(r,o,{encoding:"utf8",mode:384});}catch{}}),t.on("task:output",n=>{try{let s=this.logFiles.get(n.traceId);if(!s)return;let r=new Date().toISOString();appendFileSync(s,`[${r}] STDOUT: ${n.output}
|
|
9
|
-
`,"utf8");}catch{}}),t.on("task:end",n=>{try{let s=this.logFiles.get(n.traceId);if(!s)return;let r=new Date
|
|
9
|
+
`,"utf8");}catch{}}),t.on("task:end",n=>{try{let s=this.logFiles.get(n.traceId);if(!s)return;let r=wt(new Date),o=n.error?`failed: ${n.error.message}`:"completed successfully",i=`[${r}] INFO: Task ${o} in ${n.durationMs}ms
|
|
10
10
|
[${r}] INFO: Process closed with exit code: ${n.error?1:0}
|
|
11
|
-
`;appendFileSync(s,
|
|
11
|
+
`;appendFileSync(s,i,"utf8"),this.logFiles.delete(n.traceId);}catch{}}));}detach(t){this.unsubs.forEach(n=>n()),this.unsubs=[],this.logFiles.clear();}};function re(d){let t=F.resolve(d);return process.platform==="win32"&&(t=t.replace(/\\/g,"/"),t=t.replace(/^([A-Z]):/,(n,s)=>`${s.toLowerCase()}:`)),t.length>1&&!/^[a-zA-Z]:\/$/.test(t)&&(t=t.replace(/\/+$/,"")),t}function $t(d){let t=re(d);return createHash("sha256").update(t).digest("hex")}var nt=class{resolveDbPath(){return process.env.CREWX_DB?process.env.CREWX_DB:process.env.CREWX_TRACES_DB?process.env.CREWX_TRACES_DB:join(ae.homedir(),".crewx","crewx.db")}resolveDbPaths(){return [this.resolveDbPath()]}isMissingTableError(t){return t instanceof Error&&/no such table:/i.test(t.message)}dbExists(t){return existsSync(t??this.resolveDbPath())}};function b(d){let t=dt("better-sqlite3"),{drizzle:n}=dt("drizzle-orm/better-sqlite3"),s=new t(d);return s.exec("PRAGMA journal_mode = WAL"),s.exec("PRAGMA busy_timeout = 5000"),s.exec("PRAGMA foreign_keys = ON"),s.exec("PRAGMA analysis_limit = 400"),s.exec("PRAGMA optimize"),{db:n(s),runRaw:(r,o=[])=>s.prepare(r).run(...o),close:()=>s.close()}}var Lt=new Set,de={agent_id:"TEXT",status:"TEXT DEFAULT 'running'",started_at:"TEXT",trace_id:"TEXT",parent_task_id:"TEXT",crewx_version:"TEXT",pid:"INTEGER",thread_id:"TEXT",workspace_id:"TEXT",workspace_ref:"TEXT",workspace_name:"TEXT",project_id:"TEXT",project_name:"TEXT"};function St(d,t){return (d.get(`SELECT count(*) as cnt FROM sqlite_master WHERE type='table' AND name='${t}'`)?.cnt??0)>0}function le(d,t){if(t>0||!St(d,"tasks"))return;let n=d.all("PRAGMA table_info(tasks)"),s=new Set(n.map(r=>r.name));for(let[r,o]of Object.entries(de))s.has(r)||d.run(`ALTER TABLE tasks ADD COLUMN ${r} ${o}`);}var ce={"0002_normalize_task_names":{workspace_name:"TEXT",project_name:"TEXT"}};function ue(d,t,n){if(!St(d,"__drizzle_migrations")||!St(d,"tasks"))return;let s=d.all(n`SELECT hash FROM __drizzle_migrations`),r=new Set(s.map(i=>i.hash)),o=JSON.parse(readFileSync(F__default.join(t,"meta/_journal.json"),"utf-8"));for(let i of o.entries){let a=ce[i.tag];if(!a)continue;let c=F__default.join(t,`${i.tag}.sql`);if(!existsSync(c))continue;let l=readFileSync(c,"utf-8"),u=createHash("sha256").update(l).digest("hex");if(r.has(u))continue;let h=d.all("PRAGMA table_info(tasks)"),g=new Set(h.map(y=>y.name));for(let[y,C]of Object.entries(a))g.has(y)||(d.run(`ALTER TABLE tasks ADD COLUMN ${y} ${C}`),g.add(y));}}function pe(d,t,n){let s=d.all(n`SELECT hash FROM __drizzle_migrations`),r=new Set(s.map(i=>i.hash)),o=JSON.parse(readFileSync(F__default.join(t,"meta/_journal.json"),"utf-8"));for(let i of o.entries){let a=F__default.join(t,`${i.tag}.sql`);if(!existsSync(a))continue;let c=readFileSync(a,"utf-8"),l=createHash("sha256").update(c).digest("hex");if(r.has(l))continue;let u=/ALTER\s+TABLE\s+[`"]?(\w+)[`"]?\s+ADD\s+[`"]?(\w+)[`"]?/gi,h=[],g;for(;(g=u.exec(c))!==null;)h.push({table:g[1],column:g[2]});if(h.length===0||!c.split(/-->\s*statement-breakpoint/).map(N=>N.trim()).filter(Boolean).every(N=>/^ALTER\s+TABLE\s+.+\s+ADD\s+/i.test(N)))continue;h.every(({table:N,column:$})=>d.all(`PRAGMA table_info("${N}")`).some(B=>B.name===$))&&d.run(n`INSERT INTO __drizzle_migrations (hash, created_at) VALUES (${l}, ${i.when})`);}}function _e(d){let{migrate:t}=dt("drizzle-orm/better-sqlite3/migrator"),{sql:n}=dt("drizzle-orm"),s=[F__default.join(k,"../migrations"),F__default.join(k,"migrations"),F__default.join(k,"../../../../drizzle/migrations"),F__default.join(process.cwd(),"drizzle/migrations")],r=s.find(l=>existsSync(F__default.join(l,"meta/_journal.json")));if(!r)throw new Error(`migrations folder not found. Searched:
|
|
12
12
|
${s.join(`
|
|
13
|
-
`)}`);let o=d.get(n`SELECT count(*) as cnt FROM sqlite_master WHERE type='table' AND name='__drizzle_migrations'`),a=0;o?.cnt&&(a=d.get(n`SELECT count(*) as cnt FROM __drizzle_migrations`)?.cnt??0),de(d,a),o?.cnt&&(ue(d,r,n),ce(d,r,n)),t(d,{migrationsFolder:r});let c=(d.get(n`SELECT count(*) as cnt FROM __drizzle_migrations`)?.cnt??0)-a;if(c>0){let l=o?.cnt?"Database migrated":"Database initialized";console.error(`[crewx] ${l} (${c} migration${c>1?"s":""} applied).`);}}function ct(d,t){It.has(t)||(_e(d),It.add(t));}var p=class extends Error{code;cause;constructor(t,n,s){super(n),this.name="RepositoryError",this.code=t,this.cause=s,Object.setPrototypeOf(this,new.target.prototype);}};var st=sqliteTable("workspaces",{id:text("id").primaryKey(),slug:text("slug").notNull().unique(),name:text("name").notNull(),workspace_path:text("workspace_path"),description:text("description"),is_active:integer("is_active").notNull().default(1),created_at:text("created_at").notNull(),updated_at:text("updated_at").notNull()});var e=sqliteTable("tasks",{id:text("id").primaryKey(),agent_id:text("agent_id").notNull(),user_id:text("user_id"),prompt:text("prompt").notNull(),mode:text("mode").notNull().default("execute"),status:text("status").notNull().default("running"),result:text("result"),error:text("error"),started_at:text("started_at").notNull(),completed_at:text("completed_at"),duration_ms:integer("duration_ms"),metadata:text("metadata"),workspace_id:text("workspace_id"),trace_id:text("trace_id"),parent_task_id:text("parent_task_id"),caller_agent_id:text("caller_agent_id"),model:text("model"),platform:text("platform").default("cli"),crewx_version:text("crewx_version"),input_tokens:integer("input_tokens").default(0),output_tokens:integer("output_tokens").default(0),cost_usd:real("cost_usd").default(0),pid:integer("pid"),rendered_prompt:text("rendered_prompt"),command:text("command"),coding_agent_command:text("coding_agent_command"),exit_code:integer("exit_code"),logs:text("logs"),thread_id:text("thread_id"),workspace_ref:text("workspace_ref"),project_id:text("project_id"),project_ref:text("project_ref"),cached_input_tokens:integer("cached_input_tokens").default(0),run_epoch:integer("run_epoch").default(0)},d=>({idx_tasks_agent_id:index("idx_tasks_agent_id").on(d.agent_id),idx_tasks_status:index("idx_tasks_status").on(d.status),idx_tasks_started_at:index("idx_tasks_started_at").on(d.started_at),idx_tasks_trace_id:index("idx_tasks_trace_id").on(d.trace_id),idx_tasks_parent_task_id:index("idx_tasks_parent_task_id").on(d.parent_task_id),idx_tasks_crewx_version:index("idx_tasks_crewx_version").on(d.crewx_version),idx_tasks_pid:index("idx_tasks_pid").on(d.pid),idx_tasks_thread_id:index("idx_tasks_thread_id").on(d.thread_id),idx_tasks_workspace_id:index("idx_tasks_workspace_id").on(d.workspace_id),idx_tasks_workspace_ref:index("idx_tasks_workspace_ref").on(d.workspace_ref),idx_tasks_project_id:index("idx_tasks_project_id").on(d.project_id),idx_tasks_ws_started:index("idx_tasks_ws_started").on(d.workspace_id,d.started_at)}));var _=sqliteTable("threads",{id:text("id").primaryKey(),workspace_id:text("workspace_id").references(()=>st.id,{onDelete:"set null"}),platform:text("platform").notNull().default("cli"),title:text("title"),first_message:text("first_message"),last_message:text("last_message"),message_count:integer("message_count").notNull().default(0),created_at:text("created_at").notNull(),updated_at:text("updated_at").notNull(),metadata:text("metadata"),title_locked:integer("title_locked").notNull().default(0),pinned:integer("pinned").notNull().default(0),starred:integer("starred").notNull().default(0)},d=>({idx_threads_updated_at:index("idx_threads_updated_at").on(d.updated_at),idx_threads_workspace_id:index("idx_threads_workspace_id").on(d.workspace_id),idx_threads_ws_updated:index("idx_threads_ws_updated").on(d.workspace_id,d.updated_at),idx_threads_title:index("idx_threads_title").on(d.title)}));var Ee=sqliteTable("spans",{id:text("id").primaryKey(),task_id:text("task_id").references(()=>e.id,{onDelete:"set null"}),parent_span_id:text("parent_span_id").references(()=>Ee.id,{onDelete:"set null"}),name:text("name").notNull(),kind:text("kind").notNull().default("internal"),status:text("status").notNull().default("ok"),started_at:text("started_at").notNull(),completed_at:text("completed_at"),duration_ms:integer("duration_ms"),input:text("input"),output:text("output"),error:text("error"),attributes:text("attributes")},d=>({idx_spans_task_id:index("idx_spans_task_id").on(d.task_id),idx_spans_parent_span_id:index("idx_spans_parent_span_id").on(d.parent_span_id)}));sqliteTable("tool_calls",{id:text("id").primaryKey(),task_id:text("task_id").references(()=>e.id,{onDelete:"cascade"}),session_id:text("session_id"),tool_name:text("tool_name").notNull(),files:text("files"),input:text("input"),output:text("output"),duration_ms:integer("duration_ms"),timestamp:text("timestamp").notNull()},d=>({idx_tool_calls_task_id:index("idx_tool_calls_task_id").on(d.task_id),idx_tool_calls_tool_name:index("idx_tool_calls_tool_name").on(d.tool_name),idx_tool_calls_timestamp:index("idx_tool_calls_timestamp").on(d.timestamp)}));sqliteTable("thread_boxes",{id:text("id").primaryKey(),thread_id:text("thread_id").notNull().references(()=>_.id,{onDelete:"cascade"}),seq:integer("seq").notNull(),first_task_id:text("first_task_id").notNull(),mid_task_id:text("mid_task_id").notNull(),last_task_id:text("last_task_id").notNull(),task_count:integer("task_count").notNull(),summary:text("summary"),source_tokens:integer("source_tokens").notNull(),summary_tokens:integer("summary_tokens"),created_at:text("created_at").notNull()},d=>({idx_thread_boxes_thread_id:index("idx_thread_boxes_thread_id").on(d.thread_id),idx_thread_boxes_seq:index("idx_thread_boxes_seq").on(d.thread_id,d.seq),uniq_thread_boxes_thread_seq:unique().on(d.thread_id,d.seq)}));sqliteTable("request_logs",{id:text("id").primaryKey(),path:text("path").notNull(),method:text("method").notNull(),status_code:integer("status_code").notNull(),duration_ms:integer("duration_ms").notNull(),ip:text("ip"),request_headers:text("request_headers"),response_headers:text("response_headers"),request_body:text("request_body"),response_body:text("response_body"),query:text("query"),user_id:text("user_id"),project_id:text("project_id"),partition_key:text("partition_key").notNull(),timestamp:text("timestamp").notNull().default(sql`(datetime('now'))`),metadata:text("metadata")},d=>({idx_request_logs_timestamp:index("idx_request_logs_timestamp").on(d.timestamp),idx_request_logs_path:index("idx_request_logs_path").on(d.path),idx_request_logs_status_code:index("idx_request_logs_status_code").on(d.status_code),idx_request_logs_partition_key:index("idx_request_logs_partition_key").on(d.partition_key)}));sqliteTable("usage_limit_snapshots",{id:text("id").primaryKey(),provider:text("provider").notNull(),account_ref:text("account_ref").notNull().default("default"),limit_window:text("limit_window").notNull(),bucket_start:text("bucket_start").notNull(),captured_at:text("captured_at").notNull(),used_percent:integer("used_percent").notNull(),remaining_percent:integer("remaining_percent").notNull(),resets_at:text("resets_at"),source:text("source").notNull(),metadata:text("metadata")},d=>({uniq_usage_limit_snapshots_bucket:uniqueIndex("uniq_usage_limit_snapshots_bucket").on(d.provider,d.account_ref,d.limit_window,d.bucket_start),idx_usage_limit_snapshots_window_bucket:index("idx_usage_limit_snapshots_window_bucket").on(d.limit_window,d.bucket_start),idx_usage_limit_snapshots_provider_window_bucket:index("idx_usage_limit_snapshots_provider_window_bucket").on(d.provider,d.limit_window,d.bucket_start)}));sqliteTable("usage_reports",{id:text("id").primaryKey(),workspace_id:text("workspace_id").notNull(),month:text("month").notNull(),generated_at:text("generated_at").notNull(),source_range:text("source_range").notNull(),tier:text("tier").notNull(),total_tokens:integer("total_tokens").notNull(),total_cost_usd:real("total_cost_usd").notNull(),payload:text("payload").notNull(),payload_hash:text("payload_hash"),signature:text("signature"),signed_at:text("signed_at"),issuer:text("issuer")},d=>({uniq_usage_reports_ws_month:uniqueIndex("uniq_usage_reports_ws_month").on(d.workspace_id,d.month)}));sqliteTable("notifications",{id:text("id").primaryKey(),workspace_id:text("workspace_id").notNull(),agent_id:text("agent_id"),task_id:text("task_id"),thread_id:text("thread_id"),source:text("source").notNull().default("agent"),level:text("level").notNull().default("info"),title:text("title").notNull(),body:text("body"),target_user_id:text("target_user_id"),created_at:text("created_at").notNull(),metadata:text("metadata")},d=>({idx_notifications_ws_created:index("idx_notifications_ws_created").on(d.workspace_id,sql`${d.created_at} DESC`)}));sqliteTable("notification_reads",{notification_id:text("notification_id").notNull(),user_id:text("user_id").notNull(),read_at:text("read_at").notNull()},d=>({pk:primaryKey({columns:[d.notification_id,d.user_id]})}));sqliteTable("agent_suggestions",{id:text("id").primaryKey(),workspace_id:text("workspace_id").notNull(),agent_id:text("agent_id").notNull(),task_id:text("task_id"),type:text("type").notNull(),status:text("status").notNull().default("pending"),payload:text("payload").notNull(),applied_commit_sha:text("applied_commit_sha"),created_at:text("created_at").notNull(),updated_at:text("updated_at").notNull()},d=>({idx_agent_suggestions_ws_agent:index("idx_agent_suggestions_ws_agent").on(d.workspace_id,d.agent_id),idx_agent_suggestions_ws_created:index("idx_agent_suggestions_ws_created").on(d.workspace_id,d.created_at)}));function zt(d){let t=d.toLowerCase().trim();t=t.replace(/\[[^\]]*\]$/g,"");let n=t.lastIndexOf("/");return n>=0&&(t=t.slice(n+1)),t=t.replace(/-\d{8}$/,""),t}var G="2026-05-09",ze="0.8.9-rc.13",X=10,Y=parseInt(ze.split("rc.")[1]),We=new Set(["workflow","mcp"]),Wt=600*1e3,mt=class extends nt{dbPath;pidNullObservedSince=new Map;constructor(t={}){super(),t.dbPath?this.dbPath=t.dbPath:t.dbRoot&&(this.dbPath=join(t.dbRoot,".crewx","crewx.db"));}resolveDbPath(){return this.dbPath?this.dbPath:super.resolveDbPath()}openHandle(t){let n=this.resolveDbPath();if(t){let r=dirname(n);existsSync(r)||mkdirSync(r,{recursive:true});}else if(!existsSync(n))throw new p("NOT_FOUND","Database not found");let s=R(n);if(t)try{ct(s.db,n);}catch(r){throw s.close(),r}return s}startTask(t){let n=this.openHandle(true);try{n.db.insert(e).values({id:t.id,agent_id:t.agentId,prompt:t.prompt,mode:t.mode,status:t.status,started_at:t.startedAt,pid:t.pid??null,parent_task_id:t.parentTaskId??null,caller_agent_id:t.callerAgentId??null,trace_id:t.traceId??null,command:t.command??null,metadata:t.metadata??null,workspace_id:t.workspaceId??null,platform:t.platform??"cli",crewx_version:t.crewxVersion??null,thread_id:t.threadId??null,model:t.model??null,rendered_prompt:t.renderedPrompt??null,coding_agent_command:t.codingAgentCommand??null}).onConflictDoUpdate({target:e.id,set:{pid:sql`COALESCE(excluded.pid, ${e.pid})`},setWhere:eq(e.status,"running")}).run();}catch(s){throw s instanceof p?s:new p("DB_ERROR","Failed to start task",s)}finally{n.close();}}finishTask(t){let n=this.openHandle(true);try{let s=t.runEpoch??null;n.runRaw(`UPDATE tasks SET status=?, result=?, error=?, completed_at=?, duration_ms=?,
|
|
13
|
+
`)}`);let o=d.get(n`SELECT count(*) as cnt FROM sqlite_master WHERE type='table' AND name='__drizzle_migrations'`),i=0;o?.cnt&&(i=d.get(n`SELECT count(*) as cnt FROM __drizzle_migrations`)?.cnt??0),le(d,i),o?.cnt&&(pe(d,r,n),ue(d,r,n)),t(d,{migrationsFolder:r});let c=(d.get(n`SELECT count(*) as cnt FROM __drizzle_migrations`)?.cnt??0)-i;if(c>0){let l=o?.cnt?"Database migrated":"Database initialized";console.error(`[crewx] ${l} (${c} migration${c>1?"s":""} applied).`);}}function ct(d,t){Lt.has(t)||(_e(d),Lt.add(t));}var _=class extends Error{code;cause;constructor(t,n,s){super(n),this.name="RepositoryError",this.code=t,this.cause=s,Object.setPrototypeOf(this,new.target.prototype);}};var st=sqliteTable("workspaces",{id:text("id").primaryKey(),slug:text("slug").notNull().unique(),name:text("name").notNull(),workspace_path:text("workspace_path"),description:text("description"),is_active:integer("is_active").notNull().default(1),created_at:text("created_at").notNull(),updated_at:text("updated_at").notNull()});var e=sqliteTable("tasks",{id:text("id").primaryKey(),agent_id:text("agent_id").notNull(),user_id:text("user_id"),prompt:text("prompt").notNull(),mode:text("mode").notNull().default("execute"),status:text("status").notNull().default("running"),result:text("result"),error:text("error"),started_at:text("started_at").notNull(),completed_at:text("completed_at"),duration_ms:integer("duration_ms"),metadata:text("metadata"),workspace_id:text("workspace_id"),trace_id:text("trace_id"),parent_task_id:text("parent_task_id"),caller_agent_id:text("caller_agent_id"),model:text("model"),platform:text("platform").default("cli"),crewx_version:text("crewx_version"),input_tokens:integer("input_tokens").default(0),output_tokens:integer("output_tokens").default(0),cost_usd:real("cost_usd").default(0),pid:integer("pid"),rendered_prompt:text("rendered_prompt"),command:text("command"),coding_agent_command:text("coding_agent_command"),exit_code:integer("exit_code"),logs:text("logs"),thread_id:text("thread_id"),workspace_ref:text("workspace_ref"),project_id:text("project_id"),project_ref:text("project_ref"),cached_input_tokens:integer("cached_input_tokens").default(0),run_epoch:integer("run_epoch").default(0)},d=>({idx_tasks_agent_id:index("idx_tasks_agent_id").on(d.agent_id),idx_tasks_status:index("idx_tasks_status").on(d.status),idx_tasks_started_at:index("idx_tasks_started_at").on(d.started_at),idx_tasks_trace_id:index("idx_tasks_trace_id").on(d.trace_id),idx_tasks_parent_task_id:index("idx_tasks_parent_task_id").on(d.parent_task_id),idx_tasks_crewx_version:index("idx_tasks_crewx_version").on(d.crewx_version),idx_tasks_pid:index("idx_tasks_pid").on(d.pid),idx_tasks_thread_id:index("idx_tasks_thread_id").on(d.thread_id),idx_tasks_workspace_id:index("idx_tasks_workspace_id").on(d.workspace_id),idx_tasks_workspace_ref:index("idx_tasks_workspace_ref").on(d.workspace_ref),idx_tasks_project_id:index("idx_tasks_project_id").on(d.project_id),idx_tasks_ws_started:index("idx_tasks_ws_started").on(d.workspace_id,d.started_at)}));var p=sqliteTable("threads",{id:text("id").primaryKey(),workspace_id:text("workspace_id").references(()=>st.id,{onDelete:"set null"}),platform:text("platform").notNull().default("cli"),title:text("title"),first_message:text("first_message"),last_message:text("last_message"),message_count:integer("message_count").notNull().default(0),created_at:text("created_at").notNull(),updated_at:text("updated_at").notNull(),metadata:text("metadata"),title_locked:integer("title_locked").notNull().default(0),pinned:integer("pinned").notNull().default(0),starred:integer("starred").notNull().default(0)},d=>({idx_threads_updated_at:index("idx_threads_updated_at").on(d.updated_at),idx_threads_workspace_id:index("idx_threads_workspace_id").on(d.workspace_id),idx_threads_ws_updated:index("idx_threads_ws_updated").on(d.workspace_id,d.updated_at),idx_threads_title:index("idx_threads_title").on(d.title)}));var Se=sqliteTable("spans",{id:text("id").primaryKey(),task_id:text("task_id").references(()=>e.id,{onDelete:"set null"}),parent_span_id:text("parent_span_id").references(()=>Se.id,{onDelete:"set null"}),name:text("name").notNull(),kind:text("kind").notNull().default("internal"),status:text("status").notNull().default("ok"),started_at:text("started_at").notNull(),completed_at:text("completed_at"),duration_ms:integer("duration_ms"),input:text("input"),output:text("output"),error:text("error"),attributes:text("attributes")},d=>({idx_spans_task_id:index("idx_spans_task_id").on(d.task_id),idx_spans_parent_span_id:index("idx_spans_parent_span_id").on(d.parent_span_id)}));sqliteTable("tool_calls",{id:text("id").primaryKey(),task_id:text("task_id").references(()=>e.id,{onDelete:"cascade"}),session_id:text("session_id"),tool_name:text("tool_name").notNull(),files:text("files"),input:text("input"),output:text("output"),duration_ms:integer("duration_ms"),timestamp:text("timestamp").notNull()},d=>({idx_tool_calls_task_id:index("idx_tool_calls_task_id").on(d.task_id),idx_tool_calls_tool_name:index("idx_tool_calls_tool_name").on(d.tool_name),idx_tool_calls_timestamp:index("idx_tool_calls_timestamp").on(d.timestamp)}));sqliteTable("thread_boxes",{id:text("id").primaryKey(),thread_id:text("thread_id").notNull().references(()=>p.id,{onDelete:"cascade"}),seq:integer("seq").notNull(),first_task_id:text("first_task_id").notNull(),mid_task_id:text("mid_task_id").notNull(),last_task_id:text("last_task_id").notNull(),task_count:integer("task_count").notNull(),summary:text("summary"),source_tokens:integer("source_tokens").notNull(),summary_tokens:integer("summary_tokens"),created_at:text("created_at").notNull()},d=>({idx_thread_boxes_thread_id:index("idx_thread_boxes_thread_id").on(d.thread_id),idx_thread_boxes_seq:index("idx_thread_boxes_seq").on(d.thread_id,d.seq),uniq_thread_boxes_thread_seq:unique().on(d.thread_id,d.seq)}));sqliteTable("request_logs",{id:text("id").primaryKey(),path:text("path").notNull(),method:text("method").notNull(),status_code:integer("status_code").notNull(),duration_ms:integer("duration_ms").notNull(),ip:text("ip"),request_headers:text("request_headers"),response_headers:text("response_headers"),request_body:text("request_body"),response_body:text("response_body"),query:text("query"),user_id:text("user_id"),project_id:text("project_id"),partition_key:text("partition_key").notNull(),timestamp:text("timestamp").notNull().default(sql`(datetime('now'))`),metadata:text("metadata")},d=>({idx_request_logs_timestamp:index("idx_request_logs_timestamp").on(d.timestamp),idx_request_logs_path:index("idx_request_logs_path").on(d.path),idx_request_logs_status_code:index("idx_request_logs_status_code").on(d.status_code),idx_request_logs_partition_key:index("idx_request_logs_partition_key").on(d.partition_key)}));sqliteTable("usage_limit_snapshots",{id:text("id").primaryKey(),provider:text("provider").notNull(),account_ref:text("account_ref").notNull().default("default"),limit_window:text("limit_window").notNull(),bucket_start:text("bucket_start").notNull(),captured_at:text("captured_at").notNull(),used_percent:integer("used_percent").notNull(),remaining_percent:integer("remaining_percent").notNull(),resets_at:text("resets_at"),source:text("source").notNull(),metadata:text("metadata")},d=>({uniq_usage_limit_snapshots_bucket:uniqueIndex("uniq_usage_limit_snapshots_bucket").on(d.provider,d.account_ref,d.limit_window,d.bucket_start),idx_usage_limit_snapshots_window_bucket:index("idx_usage_limit_snapshots_window_bucket").on(d.limit_window,d.bucket_start),idx_usage_limit_snapshots_provider_window_bucket:index("idx_usage_limit_snapshots_provider_window_bucket").on(d.provider,d.limit_window,d.bucket_start)}));sqliteTable("usage_reports",{id:text("id").primaryKey(),workspace_id:text("workspace_id").notNull(),month:text("month").notNull(),generated_at:text("generated_at").notNull(),source_range:text("source_range").notNull(),tier:text("tier").notNull(),total_tokens:integer("total_tokens").notNull(),total_cost_usd:real("total_cost_usd").notNull(),payload:text("payload").notNull(),payload_hash:text("payload_hash"),signature:text("signature"),signed_at:text("signed_at"),issuer:text("issuer")},d=>({uniq_usage_reports_ws_month:uniqueIndex("uniq_usage_reports_ws_month").on(d.workspace_id,d.month)}));sqliteTable("notifications",{id:text("id").primaryKey(),workspace_id:text("workspace_id").notNull(),agent_id:text("agent_id"),task_id:text("task_id"),thread_id:text("thread_id"),source:text("source").notNull().default("agent"),level:text("level").notNull().default("info"),title:text("title").notNull(),body:text("body"),target_user_id:text("target_user_id"),created_at:text("created_at").notNull(),metadata:text("metadata")},d=>({idx_notifications_ws_created:index("idx_notifications_ws_created").on(d.workspace_id,sql`${d.created_at} DESC`)}));sqliteTable("notification_reads",{notification_id:text("notification_id").notNull(),user_id:text("user_id").notNull(),read_at:text("read_at").notNull()},d=>({pk:primaryKey({columns:[d.notification_id,d.user_id]})}));sqliteTable("agent_suggestions",{id:text("id").primaryKey(),workspace_id:text("workspace_id").notNull(),agent_id:text("agent_id").notNull(),task_id:text("task_id"),type:text("type").notNull(),status:text("status").notNull().default("pending"),payload:text("payload").notNull(),applied_commit_sha:text("applied_commit_sha"),created_at:text("created_at").notNull(),updated_at:text("updated_at").notNull()},d=>({idx_agent_suggestions_ws_agent:index("idx_agent_suggestions_ws_agent").on(d.workspace_id,d.agent_id),idx_agent_suggestions_ws_created:index("idx_agent_suggestions_ws_created").on(d.workspace_id,d.created_at)}));function Wt(d){let t=d.toLowerCase().trim();t=t.replace(/\[[^\]]*\]$/g,"");let n=t.lastIndexOf("/");return n>=0&&(t=t.slice(n+1)),t=t.replace(/-\d{8}$/,""),t}var G="2026-05-09",je="0.8.9-rc.13",X=10,Y=parseInt(je.split("rc.")[1]),Ke=new Set(["workflow","mcp"]),jt=600*1e3,ft=class extends nt{dbPath;pidNullObservedSince=new Map;constructor(t={}){super(),t.dbPath?this.dbPath=t.dbPath:t.dbRoot&&(this.dbPath=join(t.dbRoot,".crewx","crewx.db"));}resolveDbPath(){return this.dbPath?this.dbPath:super.resolveDbPath()}openHandle(t){let n=this.resolveDbPath();if(t){let r=dirname(n);existsSync(r)||mkdirSync(r,{recursive:true});}else if(!existsSync(n))throw new _("NOT_FOUND","Database not found");let s=b(n);if(t)try{ct(s.db,n);}catch(r){throw s.close(),r}return s}startTask(t){let n=this.openHandle(true);try{n.db.insert(e).values({id:t.id,agent_id:t.agentId,prompt:t.prompt,mode:t.mode,status:t.status,started_at:t.startedAt,pid:t.pid??null,parent_task_id:t.parentTaskId??null,caller_agent_id:t.callerAgentId??null,trace_id:t.traceId??null,command:t.command??null,metadata:t.metadata??null,workspace_id:t.workspaceId??null,platform:t.platform??"cli",crewx_version:t.crewxVersion??null,thread_id:t.threadId??null,model:t.model??null,rendered_prompt:t.renderedPrompt??null,coding_agent_command:t.codingAgentCommand??null}).onConflictDoUpdate({target:e.id,set:{pid:sql`COALESCE(excluded.pid, ${e.pid})`},setWhere:eq(e.status,"running")}).run();}catch(s){throw s instanceof _?s:new _("DB_ERROR","Failed to start task",s)}finally{n.close();}}finishTask(t){let n=this.openHandle(true);try{let s=t.runEpoch??null;n.runRaw(`UPDATE tasks SET status=?, result=?, error=?, completed_at=?, duration_ms=?,
|
|
14
14
|
exit_code=?, input_tokens=?, output_tokens=?, cached_input_tokens=?, cost_usd=?,
|
|
15
15
|
model=COALESCE(?, model)
|
|
16
|
-
WHERE id=? AND status='running' AND COALESCE(run_epoch, 0) = COALESCE(?, 0)`,[t.status,t.result??null,t.error??null,t.completedAt,t.durationMs??null,t.exitCode??null,t.inputTokens??0,t.outputTokens??0,t.cachedInputTokens??0,t.costUsd??0,t.model??null,t.id,s]);}catch(s){throw s instanceof
|
|
16
|
+
WHERE id=? AND status='running' AND COALESCE(run_epoch, 0) = COALESCE(?, 0)`,[t.status,t.result??null,t.error??null,t.completedAt,t.durationMs??null,t.exitCode??null,t.inputTokens??0,t.outputTokens??0,t.cachedInputTokens??0,t.costUsd??0,t.model??null,t.id,s]);}catch(s){throw s instanceof _?s:new _("DB_ERROR","Failed to finish task",s)}finally{n.close();}}appendLog(t,n){let s=this.openHandle(true);try{s.db.transaction(r=>{let o=r.select({logs:e.logs}).from(e).where(eq(e.id,t)).limit(1).get(),i=o?.logs?JSON.parse(o.logs):[];i.push(n),r.update(e).set({logs:JSON.stringify(i)}).where(eq(e.id,t)).run();},{behavior:"immediate"});}catch(r){throw r instanceof _?r:new _("DB_ERROR","Failed to append log",r)}finally{s.close();}}getRunningTasks(){if(!this.dbExists())return [];let t=this.openHandle(false);try{return t.db.select().from(e).where(eq(e.status,"running")).orderBy(desc(e.started_at)).all()}catch(n){throw new _("DB_ERROR","Failed to get running tasks",n)}finally{t.close();}}getAllTasks(){if(!this.dbExists())return [];let t=this.openHandle(false);try{return t.db.select().from(e).orderBy(desc(e.started_at)).limit(100).all()}catch(n){throw new _("DB_ERROR","Failed to get all tasks",n)}finally{t.close();}}getTask(t){if(!this.dbExists())return;let n=this.openHandle(false);try{return n.db.select().from(e).where(eq(e.id,t)).limit(1).get()??void 0}catch(s){throw new _("DB_ERROR","Failed to get task",s)}finally{n.close();}}killTask(t){if(!this.dbExists())return {killed:false};let n=this.openHandle(true);try{let s=n.db.select({id:e.id,status:e.status,pid:e.pid}).from(e).where(eq(e.id,t)).limit(1).get();if(!s||s.status!=="running")return {killed:!1};if(s.pid)try{process.kill(s.pid,"SIGTERM");}catch{}return n.db.update(e).set({status:"failed",error:"Killed by user",completed_at:new Date().toISOString()}).where(and(eq(e.id,t),eq(e.status,"running"))).run(),{killed:!0,pid:s.pid??void 0}}catch(s){throw s instanceof _?s:new _("DB_ERROR","Failed to kill task",s)}finally{n.close();}}reapOrphanedTasks(){if(!this.dbExists())return 0;let t=this.openHandle(true);try{let n=t.db.select({id:e.id,pid:e.pid,platform:e.platform,run_epoch:e.run_epoch}).from(e).where(eq(e.status,"running")).all(),s=Date.now(),r=new Set,o=0;for(let i of n){if(i.pid){let l=!1;try{process.kill(i.pid,0),l=!0;}catch{}l||(t.db.update(e).set({status:"failed",error:"Reaped: process not found (orphaned task)",completed_at:new Date().toISOString()}).where(and(eq(e.id,i.id),eq(e.status,"running"))).run(),o++);continue}if(Ke.has(i.platform??"cli"))continue;let a=`${i.id}:${i.run_epoch??0}`;r.add(a);let c=this.pidNullObservedSince.get(a);if(c===void 0){this.pidNullObservedSince.set(a,s);continue}s-c>=jt&&(t.db.update(e).set({status:"failed",error:"Reaped: pid never recorded after resume (stale running_instruction)",completed_at:new Date().toISOString()}).where(and(eq(e.id,i.id),eq(e.status,"running"))).run(),o++,this.pidNullObservedSince.delete(a));}for(let i of Array.from(this.pidNullObservedSince.keys()))r.has(i)||this.pidNullObservedSince.delete(i);return o}finally{t.close();}}reapRunningWorkflowTasks(t=jt){if(!this.dbExists())return 0;let n=this.openHandle(true);try{let s=new Date(Date.now()-t).toISOString();return n.db.update(e).set({status:"failed",error:"Reaped: stale workflow run (finally not executed)",completed_at:new Date().toISOString()}).where(and(eq(e.status,"running"),eq(e.platform,"workflow"),isNull(e.pid),lt(e.started_at,s),or(isNull(e.metadata),notLike(e.metadata,'%"kind":"workflow_card"%')))).run().changes??0}finally{n.close();}}findTaskStatus(t,n){let s=this.resolveDbPaths();for(let r of s){if(!existsSync(r))continue;let o=b(r);try{let i=n?eq(e.workspace_id,n):void 0,a=i?and(eq(e.id,t),i):eq(e.id,t),c=o.db.select().from(e).where(a).limit(1).get()??void 0;if(!c){let l=or(eq(e.thread_id,t),and(isNull(e.thread_id),like(e.command,`%--thread=${t}%`))),u=i?and(l,i):l;c=o.db.select().from(e).where(u).orderBy(desc(e.started_at)).limit(1).get()??void 0;}if(c)return c}catch(i){throw new _("DB_ERROR","Failed to find task status",i)}finally{o.close();}}}findChildTasks(t,n){let s=this.resolveDbPaths(),r=new Set,o=[];for(let i of s){if(!existsSync(i))continue;let a=b(i);try{let c=n?and(eq(e.parent_task_id,t),eq(e.workspace_id,n)):eq(e.parent_task_id,t),l=a.db.select().from(e).where(c).orderBy(asc(e.started_at)).all();for(let u of l)r.has(u.id)||(r.add(u.id),o.push(u));}catch(c){throw new _("DB_ERROR","Failed to find child tasks",c)}finally{a.close();}}return o}getWorkspaceUsageSummary(t){if(!this.dbExists())return [];let n=this.openHandle(false);try{return n.db.all(t?sql`
|
|
17
17
|
SELECT
|
|
18
18
|
COALESCE(workspace_id, 'unknown') AS workspace_id,
|
|
19
19
|
COALESCE(SUM(input_tokens), 0) AS input_tokens,
|
|
@@ -34,7 +34,7 @@ ${s.join(`
|
|
|
34
34
|
FROM tasks
|
|
35
35
|
GROUP BY workspace_id
|
|
36
36
|
ORDER BY (COALESCE(SUM(input_tokens), 0) + COALESCE(SUM(output_tokens), 0)) DESC
|
|
37
|
-
`)}catch(s){throw new
|
|
37
|
+
`)}catch(s){throw new _("DB_ERROR","Failed to get workspace usage summary",s)}finally{n.close();}}getThreadTokenUsage(t,n){let s=this.resolveDbPaths(),r=new Set,o=0,i=0,a=0;for(let c of s){if(!existsSync(c))continue;let l=b(c);try{let u=or(eq(e.thread_id,t),and(isNull(e.thread_id),like(e.command,`%--thread=${t}%`))),h=n?and(u,eq(e.workspace_id,n)):u,g=l.db.select({id:e.id,input_tokens:e.input_tokens,output_tokens:e.output_tokens,cost_usd:e.cost_usd}).from(e).where(h).all();for(let y of g)r.has(y.id)||(r.add(y.id),o+=y.input_tokens??0,i+=y.output_tokens??0,a+=y.cost_usd??0);}catch(u){throw new _("DB_ERROR","Failed to get thread token usage",u)}finally{l.close();}}return {inputTokens:o,outputTokens:i,costUsd:a}}findTasksByThread(t,n){let s=this.resolveDbPaths(),r=new Set,o=[];for(let i of s){if(!existsSync(i))continue;let a=b(i);try{let c=or(eq(e.thread_id,t),and(isNull(e.thread_id),like(e.command,`%--thread=${t}%`))),l=n?and(c,eq(e.workspace_id,n)):c,u=a.db.select().from(e).where(l).orderBy(asc(e.started_at)).all();for(let h of u)r.has(h.id)||(r.add(h.id),o.push(h));}catch(c){throw new _("DB_ERROR","Failed to find tasks by thread",c)}finally{a.close();}}return o}parseWorkflowCardMetadata(t){if(!t)return {};try{let n=JSON.parse(t);return {kind:typeof n.kind=="string"?n.kind:void 0,workflowRunId:typeof n.workflowRunId=="string"?n.workflowRunId:void 0}}catch{return {}}}extractThreadIdFromCommand(t){return t?/--thread=(\S+)/.exec(t)?.[1]??null:null}findRunningWorkflowParentTasks(){if(!this.dbExists())return [];let t=[];for(let n of this.resolveDbPaths()){if(!existsSync(n))continue;let s=b(n);try{t.push(...s.db.select({id:e.id,agent_id:e.agent_id,thread_id:e.thread_id,workspace_id:e.workspace_id,platform:e.platform,status:e.status,error:e.error,completed_at:e.completed_at,duration_ms:e.duration_ms,started_at:e.started_at,metadata:e.metadata}).from(e).where(and(eq(e.platform,"workflow"),like(e.metadata,'%"kind":"workflow_card"%'))).orderBy(desc(e.started_at)).all());}catch(r){throw new _("DB_ERROR","Failed to find workflow parent tasks",r)}finally{s.close();}}return t}batchFetchWorkflowCards(t,n){let s=new Map;if(t.length===0)return s;let r=new Set(t),o=new Map,i=n?eq(e.workspace_id,n):void 0,a=(c,l)=>{if(!c)return;let u=o.get(c);if(u&&l.started_at<=u)return;let h=this.parseWorkflowCardMetadata(l.metadata);h.kind==="workflow_card"&&(o.set(c,l.started_at),s.set(c,{taskId:l.id,workflowRunId:h.workflowRunId,raw:l.result??void 0}));};for(let c of this.resolveDbPaths()){if(!existsSync(c))continue;let l=b(c);try{let u=and(inArray(e.thread_id,t),like(e.metadata,'%"kind":"workflow_card"%')),h=l.db.select({id:e.id,thread_id:e.thread_id,metadata:e.metadata,result:e.result,started_at:e.started_at}).from(e).where(i?and(u,i):u).all();for(let C of h)a(C.thread_id,C);let g=and(isNull(e.thread_id),like(e.metadata,'%"kind":"workflow_card"%')),y=l.db.select({id:e.id,command:e.command,metadata:e.metadata,result:e.result,started_at:e.started_at}).from(e).where(i?and(g,i):g).all();for(let C of y){let N=this.extractThreadIdFromCommand(C.command);!N||!r.has(N)||a(N,C);}}catch(u){throw new _("DB_ERROR","Failed to batch fetch workflow cards",u)}finally{l.close();}}return s}findAllTasks(t){if(!this.dbExists())return {rows:[],total:0};let n=this.openHandle(false);try{let s=[];t.workspaceId&&s.push(eq(e.workspace_id,t.workspaceId));let r=t.agents&&t.agents.length>0?t.agents:t.agentId?[t.agentId]:null;r&&s.push(inArray(e.agent_id,r));let o=t.statuses&&t.statuses.length>0?t.statuses:t.status?[t.status]:null;o&&s.push(inArray(e.status,o));let i=t.q??t.search;i&&s.push(like(e.prompt,`%${i}%`)),t.from&&s.push(gte(e.started_at,t.from)),t.to&&s.push(lt(e.started_at,t.to));let a=s.length>0?and(...s):void 0,c=n.db.select({count:sql`count(*)`}).from(e).where(a).get(),l=(t.sortDir??"DESC")==="ASC"?asc(e.started_at):desc(e.started_at);return {rows:n.db.select().from(e).where(a).orderBy(l).limit(t.limit).offset(t.offset).all(),total:c?.count??0}}catch(s){throw new _("DB_ERROR","Failed to find all tasks",s)}finally{n.close();}}getAgentUsage(t,n,s){if(!this.dbExists())return [];let r=this.openHandle(false);try{return r.db.all(s?sql`
|
|
38
38
|
SELECT
|
|
39
39
|
t.agent_id,
|
|
40
40
|
t.workspace_id,
|
|
@@ -119,7 +119,7 @@ ${s.join(`
|
|
|
119
119
|
), 0)
|
|
120
120
|
+ COALESCE(SUM(t.output_tokens), 0)
|
|
121
121
|
) DESC
|
|
122
|
-
`).map(
|
|
122
|
+
`).map(i=>({agentId:i.agent_id,workspaceId:i.workspace_id??null,totalTasks:i.total_tasks,inputTokens:i.input_tokens,outputTokens:i.output_tokens,cachedInputTokens:i.cached_input_tokens,costUsd:i.cost_usd,totalTokens:i.input_tokens+i.output_tokens}))}catch(o){throw new _("DB_ERROR","Failed to get agent usage",o)}finally{r.close();}}getAgentUsageTrendRaw(t,n,s){if(!this.dbExists())return [];let r=this.openHandle(false);try{return r.db.all(s?sql`
|
|
123
123
|
SELECT
|
|
124
124
|
date(t.started_at) AS date,
|
|
125
125
|
t.agent_id,
|
|
@@ -172,7 +172,7 @@ ${s.join(`
|
|
|
172
172
|
AND t.started_at < ${n}
|
|
173
173
|
GROUP BY date(t.started_at), t.agent_id
|
|
174
174
|
ORDER BY date(t.started_at) ASC
|
|
175
|
-
`).map(
|
|
175
|
+
`).map(i=>({date:i.date,agentId:i.agent_id,inputTokens:i.input_tokens,outputTokens:i.output_tokens,cachedInputTokens:i.cached_input_tokens,costUsd:i.cost_usd,totalTokens:i.input_tokens+i.output_tokens}))}catch(o){throw new _("DB_ERROR","Failed to get agent usage trend",o)}finally{r.close();}}findTaskForStop(t,n){if(!this.dbExists())return;let s=this.openHandle(false);try{return s.db.select().from(e).where(and(eq(e.id,t),eq(e.workspace_id,n))).limit(1).get()??void 0}catch(r){throw new _("DB_ERROR","Failed to find task for stop",r)}finally{s.close();}}findLatestTaskByMetadata(t){if(!this.dbExists())return null;let n=this.openHandle(false);try{return n.db.select({id:e.id,thread_id:e.thread_id,status:e.status,result:e.result,error:e.error,started_at:e.started_at,completed_at:e.completed_at}).from(e).where(and(eq(e.agent_id,t.agentId),eq(e.workspace_id,t.workspaceId),sql`${e.metadata} IS NOT NULL AND json_valid(${e.metadata}) AND json_extract(${e.metadata}, '$.' || ${t.metaKey}) = ${t.metaValue}`)).orderBy(desc(e.started_at)).limit(1).get()??null}catch(s){throw new _("DB_ERROR","Failed to find latest task by metadata",s)}finally{n.close();}}markTaskFailed(t,n,s){if(!this.dbExists())return;let r=this.openHandle(true);try{let o=new Date().toISOString(),i=s?and(eq(e.id,t),eq(e.status,"running"),eq(e.workspace_id,s)):and(eq(e.id,t),eq(e.status,"running"));r.db.update(e).set({status:"failed",error:n,completed_at:o}).where(i).run();}catch(o){throw o instanceof _?o:new _("DB_ERROR","Failed to mark task failed",o)}finally{r.close();}}findTasksByPromptHint(t,n){let s=this.resolveDbPaths(),r=new Set,o=[];for(let i of s){if(!existsSync(i))continue;let a=b(i);try{let c=n?and(like(e.prompt,`%${t}%`),eq(e.workspace_id,n)):like(e.prompt,`%${t}%`),l=a.db.select().from(e).where(c).orderBy(asc(e.started_at)).all();for(let u of l)r.has(u.id)||(r.add(u.id),o.push(u));}catch(c){throw new _("DB_ERROR","Failed to find tasks by prompt hint",c)}finally{a.close();}}return o}getProviderUsage(t,n,s){if(!this.dbExists())return [];let r=this.openHandle(false);try{let o=sql`
|
|
176
176
|
CASE
|
|
177
177
|
WHEN ${e.model} LIKE 'claude-%' OR ${e.model} IN ('opus', 'sonnet', 'haiku', 'opus[1m]', 'sonnet[1m]') THEN 'claude'
|
|
178
178
|
WHEN ${e.model} LIKE 'gpt-%' OR ${e.model} LIKE 'codex-%' THEN 'codex'
|
|
@@ -182,7 +182,7 @@ ${s.join(`
|
|
|
182
182
|
WHEN ${e.model} LIKE 'qwen%' THEN 'qwen'
|
|
183
183
|
ELSE 'unknown'
|
|
184
184
|
END
|
|
185
|
-
`,
|
|
185
|
+
`,i=sql`
|
|
186
186
|
COALESCE(${e.input_tokens}, 0)
|
|
187
187
|
+ CASE
|
|
188
188
|
WHEN ${e.started_at} >= ${G}
|
|
@@ -194,21 +194,21 @@ ${s.join(`
|
|
|
194
194
|
THEN COALESCE(${e.cached_input_tokens}, 0)
|
|
195
195
|
ELSE 0
|
|
196
196
|
END
|
|
197
|
-
`,
|
|
197
|
+
`,a=s?sql`WHERE ${e.status} IN ('completed', 'success') AND ${e.started_at} >= ${t} AND ${e.started_at} < ${n} AND ${e.workspace_id} = ${s}`:sql`WHERE ${e.status} IN ('completed', 'success') AND ${e.started_at} >= ${t} AND ${e.started_at} < ${n}`;return r.db.all(sql`
|
|
198
198
|
SELECT
|
|
199
199
|
${o} AS provider,
|
|
200
200
|
COUNT(*) AS total_tasks,
|
|
201
|
-
COALESCE(SUM(${
|
|
201
|
+
COALESCE(SUM(${i}), 0) AS input_tokens,
|
|
202
202
|
COALESCE(SUM(${e.output_tokens}), 0) AS output_tokens,
|
|
203
203
|
COALESCE(SUM(${e.cached_input_tokens}), 0) AS cached_input_tokens,
|
|
204
204
|
COALESCE(SUM(${e.cost_usd}), 0) AS cost_usd,
|
|
205
205
|
COALESCE(SUM(${e.duration_ms}), 0) AS active_duration_ms,
|
|
206
206
|
MAX(${e.completed_at}) AS last_active_at
|
|
207
207
|
FROM ${e}
|
|
208
|
-
${
|
|
208
|
+
${a}
|
|
209
209
|
GROUP BY provider
|
|
210
|
-
ORDER BY (COALESCE(SUM(${
|
|
211
|
-
`).map(l=>({provider:l.provider,totalTasks:l.total_tasks,inputTokens:l.input_tokens,outputTokens:l.output_tokens,cachedInputTokens:l.cached_input_tokens,costUsd:l.cost_usd,totalTokens:l.input_tokens+l.output_tokens,activeDurationMs:l.active_duration_ms??0,lastActiveAt:l.last_active_at??null}))}catch(o){throw new
|
|
210
|
+
ORDER BY (COALESCE(SUM(${i}), 0) + COALESCE(SUM(${e.output_tokens}), 0)) DESC
|
|
211
|
+
`).map(l=>({provider:l.provider,totalTasks:l.total_tasks,inputTokens:l.input_tokens,outputTokens:l.output_tokens,cachedInputTokens:l.cached_input_tokens,costUsd:l.cost_usd,totalTokens:l.input_tokens+l.output_tokens,activeDurationMs:l.active_duration_ms??0,lastActiveAt:l.last_active_at??null}))}catch(o){throw new _("DB_ERROR","Failed to get provider usage",o)}finally{r.close();}}getModelUsage(t,n,s){if(!this.dbExists())return [];let r=this.openHandle(false);try{let o=sql`
|
|
212
212
|
CASE
|
|
213
213
|
WHEN ${e.model} LIKE 'claude-%' OR ${e.model} IN ('opus', 'sonnet', 'haiku', 'opus[1m]', 'sonnet[1m]') THEN 'claude'
|
|
214
214
|
WHEN ${e.model} LIKE 'gpt-%' OR ${e.model} LIKE 'codex-%' THEN 'codex'
|
|
@@ -218,7 +218,7 @@ ${s.join(`
|
|
|
218
218
|
WHEN ${e.model} LIKE 'qwen%' THEN 'qwen'
|
|
219
219
|
ELSE 'unknown'
|
|
220
220
|
END
|
|
221
|
-
`,
|
|
221
|
+
`,i=sql`
|
|
222
222
|
COALESCE(${e.input_tokens}, 0)
|
|
223
223
|
+ CASE
|
|
224
224
|
WHEN ${e.started_at} >= ${G}
|
|
@@ -230,21 +230,21 @@ ${s.join(`
|
|
|
230
230
|
THEN COALESCE(${e.cached_input_tokens}, 0)
|
|
231
231
|
ELSE 0
|
|
232
232
|
END
|
|
233
|
-
`,
|
|
233
|
+
`,a=s?sql`WHERE ${e.status} IN ('completed', 'success') AND ${e.started_at} >= ${t} AND ${e.started_at} < ${n} AND ${e.workspace_id} = ${s}`:sql`WHERE ${e.status} IN ('completed', 'success') AND ${e.started_at} >= ${t} AND ${e.started_at} < ${n}`,c=r.db.all(sql`
|
|
234
234
|
SELECT
|
|
235
235
|
${e.model} AS model,
|
|
236
236
|
${o} AS provider,
|
|
237
237
|
COUNT(*) AS total_tasks,
|
|
238
|
-
COALESCE(SUM(${
|
|
238
|
+
COALESCE(SUM(${i}), 0) AS input_tokens,
|
|
239
239
|
COALESCE(SUM(${e.output_tokens}), 0) AS output_tokens,
|
|
240
240
|
COALESCE(SUM(${e.cached_input_tokens}), 0) AS cached_input_tokens,
|
|
241
241
|
COALESCE(SUM(${e.cost_usd}), 0) AS cost_usd,
|
|
242
242
|
COALESCE(SUM(${e.duration_ms}), 0) AS active_duration_ms,
|
|
243
243
|
MAX(${e.completed_at}) AS last_active_at
|
|
244
244
|
FROM ${e}
|
|
245
|
-
${
|
|
245
|
+
${a}
|
|
246
246
|
GROUP BY ${e.model}
|
|
247
|
-
`),l=new Map;for(let u of c){let h=
|
|
247
|
+
`),l=new Map;for(let u of c){let h=Wt(u.model??""),g=l.get(h);g?(g.totalTasks+=u.total_tasks,g.inputTokens+=u.input_tokens,g.outputTokens+=u.output_tokens,g.cachedInputTokens+=u.cached_input_tokens,g.costUsd+=u.cost_usd,g.totalTokens+=u.input_tokens+u.output_tokens,g.activeDurationMs+=u.active_duration_ms??0,u.last_active_at&&(!g.lastActiveAt||u.last_active_at>g.lastActiveAt)&&(g.lastActiveAt=u.last_active_at)):l.set(h,{model:h,provider:u.provider,totalTasks:u.total_tasks,inputTokens:u.input_tokens,outputTokens:u.output_tokens,cachedInputTokens:u.cached_input_tokens,costUsd:u.cost_usd,totalTokens:u.input_tokens+u.output_tokens,activeDurationMs:u.active_duration_ms??0,lastActiveAt:u.last_active_at??null});}return Array.from(l.values()).sort((u,h)=>h.costUsd-u.costUsd)}catch(o){throw new _("DB_ERROR","Failed to get model usage",o)}finally{r.close();}}getTasksForReport(t,n,s){if(!this.dbExists())return [];let r=this.openHandle(false);try{let o=s?sql`WHERE ${e.started_at} >= ${t} AND ${e.started_at} < ${n} AND ${e.workspace_id} = ${s}`:sql`WHERE ${e.started_at} >= ${t} AND ${e.started_at} < ${n}`;return r.db.all(sql`
|
|
248
248
|
SELECT
|
|
249
249
|
${e.thread_id} AS thread_id,
|
|
250
250
|
${e.agent_id} AS agent_id,
|
|
@@ -255,11 +255,11 @@ ${s.join(`
|
|
|
255
255
|
FROM ${e}
|
|
256
256
|
${o}
|
|
257
257
|
ORDER BY ${e.started_at} ASC
|
|
258
|
-
`).map(
|
|
258
|
+
`).map(a=>({threadId:a.thread_id,agentId:a.agent_id,startedAt:a.started_at,status:a.status,error:a.error,exitCode:a.exit_code}))}catch(o){throw new _("DB_ERROR","Failed to get tasks for report",o)}finally{r.close();}}findTaskEvidence(t){if(!this.dbExists())return [];let n=this.openHandle(false);try{let s=[];t.workspaceId&&s.push(eq(e.workspace_id,t.workspaceId)),t.agents&&t.agents.length>0&&s.push(inArray(e.agent_id,t.agents)),t.statuses&&t.statuses.length>0&&s.push(inArray(e.status,t.statuses)),t.from&&s.push(gte(e.started_at,t.from)),t.to&&s.push(lt(e.started_at,t.to));let r=s.length>0?and(...s):void 0,o=(t.order??"DESC")==="ASC"?asc(e.started_at):desc(e.started_at),i={id:e.id,agent_id:e.agent_id,status:e.status,prompt:e.prompt,started_at:e.started_at,completed_at:e.completed_at,thread_id:e.thread_id};return t.limit?n.db.select(i).from(e).where(r).orderBy(o).limit(t.limit).all():n.db.select(i).from(e).where(r).orderBy(o).all()}catch(s){throw new _("DB_ERROR","Failed to find task evidence",s)}finally{n.close();}}findThreadChains(t){if(!this.dbExists())return [];let n=this.openHandle(false);try{let s=t.maxThreads??8,r=t.maxTurnsPerThread??4,o=[isNotNull(e.thread_id),isNull(e.parent_task_id),isNull(e.caller_agent_id),or(isNull(e.platform),ne(e.platform,"workflow")),or(isNull(e.metadata),notLike(e.metadata,'%"kind":"workflow_card"%')),or(isNull(e.metadata),notLike(e.metadata,'%"retriedFromTaskId"%'))];t.workspaceId&&o.push(eq(e.workspace_id,t.workspaceId)),t.from&&o.push(gte(e.started_at,t.from)),t.to&&o.push(lt(e.started_at,t.to));let i=n.db.select({id:e.id,agent_id:e.agent_id,status:e.status,prompt:e.prompt,started_at:e.started_at,completed_at:e.completed_at,thread_id:e.thread_id}).from(e).where(and(...o)).orderBy(asc(e.started_at),asc(e.id)).all(),a=new Map;for(let l of i){if(!l.thread_id)continue;let u={id:l.id,agentId:l.agent_id,status:l.status,prompt:l.prompt,startedAt:l.started_at,completedAt:l.completed_at},h=a.get(l.thread_id);h?h.push(u):a.set(l.thread_id,[u]);}let c=[];for(let[l,u]of a){let h=u.filter(g=>g.agentId===t.targetAgentId).length;h<2||c.push({threadId:l,targetAgentTurnCount:h,turns:u});}return c.sort((l,u)=>{let h=l.turns[l.turns.length-1].startedAt,g=u.turns[u.turns.length-1].startedAt;return h<g?1:h>g?-1:0}),c.slice(0,s).map(l=>({threadId:l.threadId,targetAgentTurnCount:l.targetAgentTurnCount,turns:l.turns.slice(-r)}))}catch(s){throw new _("DB_ERROR","Failed to find thread chains",s)}finally{n.close();}}};var At=class extends j{name="sqlite-tracing";unsubs=[];dbPath;version;constructor(t){super(),this.dbPath=join(t?.dbRoot??homedir(),".crewx","crewx.db"),this.version=t?.version??"unknown";}attach(t){let n=new ft({dbPath:this.dbPath}),s=process.cwd(),o=existsSync(join(s,"crewx.yaml"))||existsSync(join(s,"crewx.yml"))?$t(s):null,i=process.argv.join(" ");this.unsubs.push(t.on("task:start",a=>{try{let c=a.callerAgentId??null,l=a.parentTaskId??null,u=a.rootTraceId??a.traceId,h=a.metadata?JSON.stringify(a.metadata):JSON.stringify({provider:a.provider??"cli/claude"});n.startTask({id:a.traceId,agentId:a.agentRef.replace(/^@/,""),prompt:a.message,mode:a.mode,status:"running",pid:a.pid??null,startedAt:a.timestamp.toISOString(),crewxVersion:this.version,platform:a.platform??"cli",model:a.model??null,renderedPrompt:a.renderedPrompt??null,command:i,codingAgentCommand:a.codingAgentCommand??null,workspaceId:a.workspaceId??o,callerAgentId:c,parentTaskId:l,traceId:u,metadata:h,threadId:a.threadId??null});}catch{}}),t.on("task:output",a=>{try{n.appendLog(a.traceId,{timestamp:a.timestamp.toISOString(),level:a.level??"stdout",message:a.output});}catch{}}),t.on("task:end",a=>{try{let c=typeof a.metadata?.runEpoch=="number"?a.metadata.runEpoch:null,l=a.error?JSON.stringify({code:a.error.code,message:a.error.message,...a.error.providerCode?{providerCode:a.error.providerCode}:{}}):null;n.finishTask({id:a.traceId,status:a.error?"failed":"success",result:a.result??null,error:l,completedAt:a.timestamp.toISOString(),durationMs:a.durationMs,exitCode:a.exitCode??null,inputTokens:a.inputTokens??0,outputTokens:a.outputTokens??0,cachedInputTokens:a.cachedInputTokens??0,costUsd:a.costUsd??0,model:a.model??null,runEpoch:c});}catch{}}));}detach(t){this.unsubs.forEach(n=>n()),this.unsubs=[];}};var mt=class extends nt{dbPath;constructor(t={}){super(),t.dbPath?this.dbPath=t.dbPath:t.dbRoot&&(this.dbPath=join(t.dbRoot,".crewx","crewx.db"));}resolveDbPath(){return this.dbPath?this.dbPath:super.resolveDbPath()}openHandle(t){let n=this.resolveDbPath();if(t){let r=dirname(n);existsSync(r)||mkdirSync(r,{recursive:true});}else if(!existsSync(n))throw new _("NOT_FOUND","Database not found");let s=b(n);if(t)try{ct(s.db,n);}catch(r){throw s.close(),r}return s}validateWorkspaceId(t,n){return t.db.select({id:st.id}).from(st).where(eq(st.id,n)).limit(1).get()?n:null}topLevelTaskPredicateSql(t="child"){return sql.raw(`NOT EXISTS (
|
|
259
259
|
SELECT 1 FROM tasks parent
|
|
260
260
|
WHERE parent.id = ${t}.parent_task_id
|
|
261
261
|
AND parent.thread_id = ${t}.thread_id
|
|
262
|
-
)`)}findAllThreads(t){let n=this.resolveDbPaths(),s=new Set,r=[];for(let o of n){if(!existsSync(o))continue;let
|
|
262
|
+
)`)}findAllThreads(t){let n=this.resolveDbPaths(),s=new Set,r=[];for(let o of n){if(!existsSync(o))continue;let i=b(o);try{let a=t?eq(p.workspace_id,t):void 0,c=i.db.select().from(p).where(a).orderBy(desc(p.updated_at)).all();for(let l of c)s.has(l.id)||(s.add(l.id),r.push(l));}catch(a){throw new _("DB_ERROR","Failed to find all threads",a)}finally{i.close();}}return r}findThreadsByIdsOrTitles(t,n){if(t.length===0)return [];let s=this.resolveDbPaths(),r=new Set,o=[];for(let i of s){if(!existsSync(i))continue;let a=b(i);try{let c=or(inArray(p.id,t),inArray(p.title,t)),l=n?and(c,eq(p.workspace_id,n)):c,u=a.db.select().from(p).where(l).orderBy(desc(p.updated_at)).all();for(let h of u)r.has(h.id)||(r.add(h.id),o.push(h));}catch(c){throw new _("DB_ERROR","Failed to find threads by ids or titles",c)}finally{a.close();}}return o}findThreadById(t,n){let s=this.resolveDbPaths();for(let r of s){if(!existsSync(r))continue;let o=b(r);try{let i=eq(p.id,t),a=n?and(i,eq(p.workspace_id,n)):i,c=o.db.select().from(p).where(a).limit(1).get()??void 0;if(c)return c}catch(i){throw new _("DB_ERROR","Failed to find thread by id",i)}finally{o.close();}}}threadExists(t,n){let s=this.resolveDbPaths();for(let r of s){if(!existsSync(r))continue;let o=b(r);try{let i=eq(p.id,t),a=n?and(i,eq(p.workspace_id,n)):i;if(o.db.select({id:p.id}).from(p).where(a).limit(1).get())return !0}catch(i){throw new _("DB_ERROR","Failed to check thread existence",i)}finally{o.close();}}return false}aggregateTaskStats(t,n){let s=this.resolveDbPaths(),r=0,o=0,i=0,a=0,c=0,l=new Set;for(let u of s){if(!existsSync(u))continue;let h=b(u);try{let g=h.db.get(sql`
|
|
263
263
|
SELECT
|
|
264
264
|
count(*) AS cnt,
|
|
265
265
|
COALESCE(SUM(child.input_tokens), 0) AS total_input,
|
|
@@ -270,13 +270,13 @@ ${s.join(`
|
|
|
270
270
|
WHERE child.thread_id = ${t}
|
|
271
271
|
AND ${this.topLevelTaskPredicateSql()}
|
|
272
272
|
${n?sql`AND child.workspace_id = ${n}`:sql``}
|
|
273
|
-
`);
|
|
273
|
+
`);g&&(r+=g.cnt,o+=g.total_input,i+=g.total_output,a+=g.total_cached,c+=g.total_cost);let y=h.db.all(sql`
|
|
274
274
|
SELECT DISTINCT child.agent_id FROM tasks child
|
|
275
275
|
WHERE child.thread_id = ${t}
|
|
276
276
|
AND child.agent_id IS NOT NULL AND child.agent_id != ''
|
|
277
277
|
AND ${this.topLevelTaskPredicateSql()}
|
|
278
278
|
${n?sql`AND child.workspace_id = ${n}`:sql``}
|
|
279
|
-
`);for(let C of y)l.add(C.agent_id);}catch(
|
|
279
|
+
`);for(let C of y)l.add(C.agent_id);}catch(g){throw new _("DB_ERROR","Failed to aggregate task stats",g)}finally{h.close();}}return {taskCount:r,inputTokens:o,outputTokens:i,cachedInputTokens:a,costUsd:c,agentIds:Array.from(l)}}findTopLevelTasks(t,n,s){let r=this.resolveDbPaths(),o=new Set,i=[];for(let a of r){if(!existsSync(a))continue;let c=b(a);try{let l;s!==void 0?l=c.db.all(sql`
|
|
280
280
|
SELECT * FROM (
|
|
281
281
|
SELECT child.*,
|
|
282
282
|
ROW_NUMBER() OVER (PARTITION BY child.agent_id ORDER BY child.started_at DESC) AS rn
|
|
@@ -293,7 +293,7 @@ ${s.join(`
|
|
|
293
293
|
AND ${this.topLevelTaskPredicateSql()}
|
|
294
294
|
${n?sql`AND child.workspace_id = ${n}`:sql``}
|
|
295
295
|
ORDER BY child.started_at ASC
|
|
296
|
-
`);for(let u of l)o.has(u.id)||(o.add(u.id),
|
|
296
|
+
`);for(let u of l)o.has(u.id)||(o.add(u.id),i.push(u));}catch(l){throw new _("DB_ERROR","Failed to find top-level tasks",l)}finally{c.close();}}if(s!==void 0&&r.length>1){let a=new Map;for(let c of i){let l=c.agent_id??"";a.has(l)||a.set(l,[]),a.get(l).push(c);}i=[];for(let c of a.values())c.sort((l,u)=>(u.started_at??"").localeCompare(l.started_at??"")),i.push(...c.slice(0,s));i.sort((c,l)=>(c.started_at??"").localeCompare(l.started_at??""));}return i}findAllTasks(t,n){let s=this.resolveDbPaths(),r=new Set,o=[];for(let i of s){if(!existsSync(i))continue;let a=b(i);try{let c=eq(e.thread_id,t),l=n?and(c,eq(e.workspace_id,n)):c,u=a.db.select().from(e).where(l).orderBy(asc(e.started_at)).all();for(let h of u)r.has(h.id)||(r.add(h.id),o.push(h));}catch(c){throw new _("DB_ERROR","Failed to find all tasks for thread",c)}finally{a.close();}}return o}findTaskById(t,n,s){let r=this.resolveDbPaths();for(let o of r){if(!existsSync(o))continue;let i=b(o);try{let a=and(eq(e.id,n),eq(e.thread_id,t)),c=s?and(a,eq(e.workspace_id,s)):a,l=i.db.select().from(e).where(c).limit(1).get();if(!l)continue;let u=i.db.select().from(e).where(eq(e.parent_task_id,l.id)).orderBy(asc(e.started_at)).all();return {task:l,children:u}}catch(a){throw new _("DB_ERROR","Failed to find task by id",a)}finally{i.close();}}}batchFetchTasksQuery(t,n){return sql`
|
|
297
297
|
SELECT child.id, child.thread_id, child.agent_id, child.status,
|
|
298
298
|
child.parent_task_id, child.started_at, child.completed_at,
|
|
299
299
|
child.duration_ms, child.input_tokens, child.output_tokens,
|
|
@@ -303,7 +303,7 @@ ${s.join(`
|
|
|
303
303
|
AND ${this.topLevelTaskPredicateSql()}
|
|
304
304
|
${n?sql`AND child.workspace_id = ${n}`:sql``}
|
|
305
305
|
ORDER BY child.started_at ASC
|
|
306
|
-
`}batchFetchTasks(t,n){let s=new Map;if(t.length===0)return s;let r=this.resolveDbPaths();for(let o of r){if(!existsSync(o))continue;let
|
|
306
|
+
`}batchFetchTasks(t,n){let s=new Map;if(t.length===0)return s;let r=this.resolveDbPaths();for(let o of r){if(!existsSync(o))continue;let i=b(o);try{let a=i.db.all(this.batchFetchTasksQuery(t,n));for(let c of a){let l=c.thread_id;s.has(l)||s.set(l,[]),s.get(l).push(c);}}catch(a){throw new _("DB_ERROR","Failed to batch fetch tasks",a)}finally{i.close();}}return s}explainBatchFetchTasksPlan(t,n){let s=this.resolveDbPaths();for(let r of s){if(!existsSync(r))continue;let o=b(r);try{return o.db.all(sql`EXPLAIN QUERY PLAN ${this.batchFetchTasksQuery(t,n)}`).map(a=>a.detail)}finally{o.close();}}return []}updateThreadTitle(t,n,s){if(!this.dbExists())return;let r=this.openHandle(true);try{let o=eq(p.id,t),i=s?and(o,eq(p.workspace_id,s)):o;if(!r.db.select({id:p.id}).from(p).where(i).limit(1).get())return;r.db.update(p).set({title:n,title_locked:1,updated_at:new Date().toISOString()}).where(eq(p.id,t)).run();}catch(o){throw o instanceof _?o:new _("DB_ERROR","Failed to update thread title",o)}finally{r.close();}}upsertThread(t,n){let s=this.openHandle(true);try{let r=n.workspaceId?this.validateWorkspaceId(s,n.workspaceId):null,o=new Date().toISOString();if(s.db.select({id:p.id,message_count:p.message_count}).from(p).where(eq(p.id,t)).limit(1).get()){let a={updated_at:o};n.title!==void 0&&(a.title=n.title),n.titleLocked!==void 0&&(a.title_locked=n.titleLocked?1:0),s.db.update(p).set(a).where(eq(p.id,t)).run();}else s.db.insert(p).values({id:t,platform:n.platform,workspace_id:r,title:n.title??null,title_locked:n.titleLocked?1:0,message_count:0,created_at:o,updated_at:o}).run();}catch(r){throw r instanceof _?r:new _("DB_ERROR","Failed to upsert thread",r)}finally{s.close();}}ensureThread(t,n,s){let r=this.openHandle(true);try{let o=s?this.validateWorkspaceId(r,s):null,i=r.db.select({id:p.id,platform:p.platform,workspace_id:p.workspace_id}).from(p).where(eq(p.id,t)).limit(1).get();if(i){o&&!i.workspace_id&&r.db.update(p).set({workspace_id:o}).where(eq(p.id,t)).run();return}let a=new Date().toISOString();r.db.insert(p).values({id:t,platform:n,workspace_id:o,message_count:0,created_at:a,updated_at:a}).run();}catch(o){throw o instanceof _?o:new _("DB_ERROR","Failed to ensure thread",o)}finally{r.close();}}saveUserMessage(t,n,s){if(!this.dbExists())return {firstMessage:false};let r=this.openHandle(true);try{let o=new Date().toISOString();return {firstMessage:r.db.transaction(a=>{let l=a.select({message_count:p.message_count}).from(p).where(eq(p.id,t)).limit(1).get()?.message_count===0;return a.run(sql`
|
|
307
307
|
UPDATE threads
|
|
308
308
|
SET first_message = COALESCE(first_message, ${n}),
|
|
309
309
|
title = CASE WHEN title_locked = 0 AND title IS NULL THEN substr(${n}, 1, 60) ELSE title END,
|
|
@@ -311,8 +311,8 @@ ${s.join(`
|
|
|
311
311
|
message_count = message_count + 1,
|
|
312
312
|
updated_at = ${o}
|
|
313
313
|
WHERE id = ${t}
|
|
314
|
-
`),l},{behavior:"immediate"})}}catch(o){throw o instanceof
|
|
314
|
+
`),l},{behavior:"immediate"})}}catch(o){throw o instanceof _?o:new _("DB_ERROR","Failed to save user message",o)}finally{r.close();}}saveAssistantMessage(t,n,s){if(!this.dbExists())return;let r=this.openHandle(true);try{let o=new Date().toISOString();r.db.update(p).set({last_message:n,updated_at:o}).where(eq(p.id,t)).run();}catch(o){throw o instanceof _?o:new _("DB_ERROR","Failed to save assistant message",o)}finally{r.close();}}updateThread(t,n){if(!this.dbExists())return;let s=this.openHandle(true);try{let r={updated_at:new Date().toISOString()};n.title!==void 0&&(r.title=n.title,r.title_locked=1),n.titleLocked!==void 0&&(r.title_locked=n.titleLocked?1:0),s.db.update(p).set(r).where(eq(p.id,t)).run();}catch(r){throw r instanceof _?r:new _("DB_ERROR","Failed to update thread",r)}finally{s.close();}}togglePin(t,n){let s=this.openHandle(true);try{let r=n?and(eq(p.id,t),eq(p.workspace_id,n)):eq(p.id,t),o=s.db.select({pinned:p.pinned,metadata:p.metadata}).from(p).where(r).get();if(!o)return null;let i=o.pinned?0:1,a=o.metadata?JSON.parse(o.metadata):{};if(i){let c=n?and(eq(p.pinned,1),eq(p.workspace_id,n)):eq(p.pinned,1),l=s.db.select({metadata:p.metadata}).from(p).where(c).all(),u=null;for(let h of l){let g=h.metadata?JSON.parse(h.metadata):{};typeof g.pinOrder=="number"&&(u===null||g.pinOrder<u)&&(u=g.pinOrder);}a.pinOrder=u===null?0:u-1;}else delete a.pinOrder;return s.db.update(p).set({pinned:i,metadata:Object.keys(a).length>0?JSON.stringify(a):null}).where(r).run(),{pinned:!!i}}catch(r){throw r instanceof _?r:new _("DB_ERROR","Failed to toggle pin",r)}finally{s.close();}}reorderPins(t,n){let s=this.openHandle(true);try{for(let r=0;r<t.length;r++){let o=n?and(eq(p.id,t[r]),eq(p.workspace_id,n)):eq(p.id,t[r]),i=s.db.select({metadata:p.metadata}).from(p).where(o).get();if(!i)continue;let a=i.metadata?JSON.parse(i.metadata):{};a.pinOrder=r+1,s.db.update(p).set({metadata:JSON.stringify(a)}).where(o).run();}}catch(r){throw r instanceof _?r:new _("DB_ERROR","Failed to reorder pins",r)}finally{s.close();}}toggleStar(t,n){let s=this.openHandle(true);try{let r=n?and(eq(p.id,t),eq(p.workspace_id,n)):eq(p.id,t),o=s.db.select({starred:p.starred}).from(p).where(r).get();if(!o)return null;let i=o.starred?0:1;return s.db.update(p).set({starred:i}).where(r).run(),{starred:!!i}}catch(r){throw r instanceof _?r:new _("DB_ERROR","Failed to toggle star",r)}finally{s.close();}}resolveOverdriveForRequest(t,n,s,r){let i=this.openHandle(true);try{let a=n?and(eq(p.id,t),eq(p.workspace_id,n)):eq(p.id,t);return i.db.transaction(l=>{let u=l.select({metadata:p.metadata}).from(p).where(a).get();if(!u)return null;let h=u.metadata?JSON.parse(u.metadata):{},g=h.overdrive??{},y=r?.defaultTurns??g.defaultTurns??3,C=r?.updatedBy??"ui",N=new Date().toISOString(),$,M,B,rt;switch(s){case "enable-count":{let ot=r?.turns??y,it=r?.consumeCurrent?Math.max(ot-1,0):ot;$=it>0?"count":"off",M=it,B=!0,rt="count";break}case "enable-latch":{$="latch",M=0,B=!0,rt="latch";break}case "disable":{$="off",M=0,B=!1;break}default:{let ot=g.state??"off",it=typeof g.remaining=="number"?g.remaining:0;if(ot==="count"&&it>0){let Nt=it-1;Nt<=0?($="off",M=0):($="count",M=Nt),B=!0,rt="count";}else ot==="latch"?($="latch",M=0,B=!0,rt="latch"):($="off",M=0,B=!1);break}}return h.overdrive={state:$,remaining:M,defaultTurns:y,updatedAt:N,updatedBy:C},l.update(p).set({metadata:JSON.stringify(h),updated_at:N}).where(a).run(),{applied:B,appliedMode:rt,state:$,remaining:M}},{behavior:"immediate"})}catch(a){throw a instanceof _?a:new _("DB_ERROR","Failed to resolve overdrive",a)}finally{i.close();}}};function tn(d){return d.replace(/<conversation_history[^>]*>[\s\S]*?<\/conversation_history>/g,"").split(`
|
|
315
315
|
`).filter(r=>!(r.startsWith("Loaded ")&&r.includes("layouts from")||r.includes("[dotenv@")||r.includes("[Nest]")&&r.includes("DEBUG")||r.startsWith("Registered custom layout:")||r.startsWith("Updated custom layout:"))).join(`
|
|
316
|
-
`).trim()}function
|
|
317
|
-
`):n&&typeof n=="object"&&n.result!==void 0&&(t=n.result||"");}catch{t=
|
|
318
|
-
`)[0].slice(0,200)),n.push({id:`${s.id}-assistant`,text:r,isAssistant:true,timestamp:new Date(s.started_at).getTime(),metadata:
|
|
316
|
+
`).trim()}function en(d){if(!d)return "";let t=d;try{let n=JSON.parse(t);Array.isArray(n)?t=n.filter(s=>s?.type==="text"&&s?.text).map(s=>s.text).join(`
|
|
317
|
+
`):n&&typeof n=="object"&&n.result!==void 0&&(t=n.result||"");}catch{t=tn(t);}return t}var kt=class{dbPath;constructor(t){this.dbPath=t??join(homedir(),".crewx","crewx.db");}getThreadRepo(){return new mt({dbPath:this.dbPath})}updateThread(t,n){this.getThreadRepo().updateThread(t,{title:n.title});}async ensureThread(t,n,s){let r=this.getThreadRepo(),o=r.findThreadById(t);if(o){if(o.platform!==n)throw new Error(`Thread '${t}' already exists with platform '${o.platform}' \u2014 cannot change to '${n}' (platform is immutable)`);return {created:false}}return r.ensureThread(t,n,s),{created:true}}async fetchHistory(t,n){let s=n?.limit??100,r=this.getThreadRepo(),o=r.findThreadById(t),i=r.findTopLevelTasks(t,void 0,s),a=new Set(["queued","cancelled"]);i=i.filter(u=>(!u.status||!a.has(u.status))&&(!n?.currentTraceId||u.trace_id!==n.currentTraceId));let c=o?.platform??"cli",l=this.rowsToMessages(i);return {threadId:t,platform:c,messages:l,metadata:{title:o?.title??void 0,firstMessage:o?.first_message??void 0,lastMessage:o?.last_message??void 0,messageCount:o?.message_count??0,updatedAt:o?.updated_at?new Date(o.updated_at).getTime():void 0}}}async saveUserMessage(t,n,s,r){let{firstMessage:o}=this.getThreadRepo().saveUserMessage(t,n);return {id:t,firstMessage:o}}async saveAssistantMessage(t,n,s,r){return this.getThreadRepo().saveAssistantMessage(t,n),{id:t}}close(){}normalizeStatus(t){if(t&&!["success","completed","done"].includes(t)){if(["failed","error"].includes(t))return "failed";if(t==="running")return "running"}}rowsToMessages(t){let n=[];for(let s of t){s.prompt&&n.push({id:`${s.id}-user`,text:s.prompt,isAssistant:false,timestamp:new Date(s.started_at).getTime(),metadata:{caller_agent_id:s.caller_agent_id}});let r=en(s.result),o=this.normalizeStatus(s.status);if(r||o==="running"||o==="failed"){let i={agent_id:s.agent_id,task_id:s.id};o&&(i.status=o),o==="failed"&&s.error&&(i.reason=s.error.split(`
|
|
318
|
+
`)[0].slice(0,200)),n.push({id:`${s.id}-assistant`,text:r,isAssistant:true,timestamp:new Date(s.started_at).getTime(),metadata:i});}}return n}};var Ct=class extends j{name="conversation";_provider;unsubStart=null;unsubEnd=null;constructor(t){super(),this._provider=new kt(t?.dbPath);}get conversationProvider(){return this._provider}async afterUserMessage(t,n,s,r){}async afterAssistantMessage(t,n,s){}attach(t){this.unsubStart=t.on("task:start",async n=>{if(!n.threadId)return;let s=n.platform??"cli";try{let r=await this._provider.ensureThread(n.threadId,s,n.workspaceId),o=await this._provider.saveUserMessage(n.threadId,n.message??"");await this.afterUserMessage(n.threadId,o.id,r.created||o.firstMessage,n);}catch{}}),this.unsubEnd=t.on("task:end",async n=>{if(!n.result)return;let s=n.metadata?.threadId;if(!s)return;let r=n.agentRef?.replace(/^@/,"")??"";try{let{id:o}=await this._provider.saveAssistantMessage(s,n.result,r);await this.afterAssistantMessage(s,o,n);}catch{}});}detach(t){this.unsubStart?.(),this.unsubStart=null,this.unsubEnd?.(),this.unsubEnd=null,this._provider.close?.();}};export{Ct as ConversationPlugin,Et as FileLoggerPlugin,At as SqliteTracingPlugin};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import*as b from'path';import {join}from'path';import*as g from'fs';import {existsSync,readFileSync}from'fs';import*as q from'crypto';import*as W from'js-yaml';import*as N from'os';import*as Q from'tar';import {gunzipSync,gzipSync}from'zlib';function ce(e){let t=n=>n.replace(/[.+^${}()|[\]\\]/g,"\\$&"),s=e.split("/").map(n=>n==="**"?".*":n.split("*").map(t).join("[^/]*"));return new RegExp(`^${s.join("\\/")}$`)}function A(e,t){try{return ce(t).test(e)}catch{return false}}function U(e,...t){let r=e.split("/");if(r.length<t.length)return false;let s=r.length-t.length;return t.every((n,i)=>A(r[s+i],n))}function ue(e,t){return e.split("/").some(r=>A(r,t))}var D=[{label:".env*",test:e=>A(e,".env*")},{label:".git/",test:(e,t,r)=>r&&e===".git"},{label:"memory/",test:(e,t,r)=>r&&e==="memory"},{label:"*.key",test:e=>A(e,"*.key")},{label:"*.pem",test:e=>A(e,"*.pem")},{label:"auth.json",test:e=>e==="auth.json"},{label:"node_modules/",test:(e,t,r)=>r&&e==="node_modules"},{label:"conversations/",test:(e,t,r)=>r&&e==="conversations"},{label:".crewx/threads/",test:(e,t,r)=>r&&U(t,".crewx","threads")},{label:".crewx/crewx.db",test:(e,t,r)=>!r&&U(t,".crewx","crewx.db")},{label:".crewx/*.log",test:(e,t,r)=>!r&&U(t,".crewx","*.log")},{label:".crewx/publish/",test:(e,t,r)=>r&&U(t,".crewx","publish")},{label:".crewx/",test:(e,t)=>ue(t,".crewx")}];function k(e,t,r){for(let s of D)if(s.test(e,t,r))return s.label;return null}function K(e){let t=[],r=[];function s(n,i,a){let m;try{m=g.readdirSync(n,{withFileTypes:!0});}catch{return}m.sort((c,u)=>c.name.localeCompare(u.name));for(let c of m){let u=i?`${i}/${c.name}`:c.name,l=b.join(n,c.name);if(c.isSymbolicLink()){let p;try{p=g.statSync(l);}catch{continue}if(p.isDirectory()){r.push({path:u,rule:a??"symlink-dir"});continue}let P=a??k(c.name,u,false);P?r.push({path:u,rule:P}):t.push(u);continue}if(c.isDirectory()){let p=a??k(c.name,u,true);s(l,u,p);continue}if(c.isFile()){let p=a??k(c.name,u,false);p?r.push({path:u,rule:p}):t.push(u);}}}return s(e,"",null),t.sort(),r.sort((n,i)=>n.path<i.path?-1:n.path>i.path?1:0),{included:t,excluded:r}}var le=[{rule:"token-prefix",regex:/\b(?:sk-|ghp_|xoxb-)[A-Za-z0-9_-]{10,}/},{rule:"private-key",regex:/-----BEGIN [A-Z ]*PRIVATE KEY-----/},{rule:"aws-access-key",regex:/\bAKIA[0-9A-Z]{16}\b/}];function pe(e){return e.includes(0)}function X(e,t){let r=[];for(let s of t){let n=b.join(e,s),i;try{i=g.readFileSync(n);}catch{continue}if(pe(i))continue;i.toString("utf8").split(/\r\n|\r|\n/).forEach((m,c)=>{for(let{rule:u,regex:l}of le)l.test(m)&&r.push({path:s,line:c+1,rule:u});});}return r}var G=/^[a-z0-9-]+$/,fe=/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/,me=/^[A-Za-z_][A-Za-z0-9_]*$/;function he(e){let t=b.join(e,"crewx.yaml");if(!g.existsSync(t))return {};let r;try{r=W.load(g.readFileSync(t,"utf8"));}catch{return {}}if(!r||typeof r!="object")return {};let s=r.metadata;if(!s||typeof s!="object")return {};let n=s;return {name:typeof n.name=="string"?n.name:void 0,version:typeof n.version=="string"?n.version:void 0,description:typeof n.description=="string"?n.description:void 0,requiredEnv:n.requiredEnv,crewxMinVersion:typeof n.crewxMinVersion=="string"?n.crewxMinVersion:void 0}}function de(e){return q.createHash("sha256").update(new Uint8Array(g.readFileSync(e))).digest("hex")}function Z(e,t,r={}){let s=he(e),n=s.name??b.basename(e);if(!G.test(n))throw new Error(`publish: invalid name "${n}" \u2014 must match ${G} (lowercase letters, numbers, hyphen only)`);let i=r.version??s.version;if(!i)throw new Error("publish: version is required \u2014 set crewx.yaml metadata.version or pass opts.version");if(!fe.test(i))throw new Error(`publish: invalid version "${i}" \u2014 must be semver (e.g. 1.0.0)`);let a=Array.isArray(s.requiredEnv)?s.requiredEnv:[],m=[];for(let l of a){if(typeof l!="string"||!me.test(l))throw new Error(`publish: requiredEnv must contain names only (no values), got "${String(l)}"`);m.push(l);}let c=t.map(l=>({path:l,sha256:de(b.join(e,l))})).sort((l,p)=>l.path<p.path?-1:l.path>p.path?1:0),u={name:n,version:i,type:"template",description:s.description??"",files:c,requiredEnv:m};return s.crewxMinVersion&&(u.crewxMinVersion=s.crewxMinVersion),u}async function ee(e,t){let r=b.join(e,".crewx","publish");g.mkdirSync(r,{recursive:true});let s=b.join(r,`${t.name}-${t.version}.tgz`),n=g.mkdtempSync(b.join(N.tmpdir(),"crewx-publish-"));try{g.writeFileSync(b.join(n,"manifest.json"),JSON.stringify(t,null,2));for(let i of t.files){let a=b.join(n,i.path);g.mkdirSync(b.dirname(a),{recursive:!0}),g.copyFileSync(b.join(e,i.path),a);}await Q.create({gzip:!0,file:s,cwd:n,portable:!0,noMtime:!0},["manifest.json",...t.files.map(i=>i.path)]);}finally{g.rmSync(n,{recursive:true,force:true});}return s}var S="/api/v1";var be=201,we=409,O=401;function Ee(){return process.env.WI013_FAKE_UPLOAD==="1"}function Ae(e){let t=gunzipSync(new Uint8Array(e)),r=gzipSync(new Uint8Array(t),{level:1});if(Buffer.compare(new Uint8Array(r),new Uint8Array(e))===0)throw new Error("WI013_FAKE_UPLOAD: re-gzipped bytes are identical to the original \u2014 tamper is a no-op");return r}function Se(e){return e.replace(/\/+$/,"")}async function C(e){try{return await e.json()}catch{return null}}function w(e){let t=e?.message;return typeof t=="string"?t:void 0}function te(e,t,r){let s=e;if(!s||s.success!==true||s.data===void 0)throw new Error(`publish: ${t} response envelope malformed (expected { success: true, data }) \u2014 HTTP ${r}`);return s.data}async function xe(e){let t=Se(e.baseUrl),r=e.accessPolicy??"private",s=e.manifest.name,n;try{n=await fetch(`${t}${S}/publisher/items`,{method:"POST",headers:{Authorization:`Bearer ${e.accessToken}`,"Content-Type":"application/json"},body:JSON.stringify({slug:s,displayName:s,description:e.manifest.description,type:"template",version:e.manifest.version,accessPolicy:r})});}catch(o){throw new Error(`publish: submit \uC694\uCCAD\uC774 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4 (\uB124\uD2B8\uC6CC\uD06C) \u2014 ${o instanceof Error?o.message:String(o)}`)}let i;if(n.status===be)i="created";else if(n.status===we)i="existing";else {if(n.status===O)throw new Error("publish: \uC778\uC99D\uC774 \uB9CC\uB8CC\uB418\uC5C8\uAC70\uB098 \uC5C6\uC2B5\uB2C8\uB2E4 \u2014 \uB2E4\uC2DC \uB85C\uADF8\uC778\uD558\uC138\uC694");{let o=await C(n);throw new Error(`publish: submit \uC2E4\uD328 \u2014 HTTP ${n.status}${w(o)?` ${w(o)}`:""}`)}}let a="not-needed",m=null;if(i==="existing"){let o;try{o=await fetch(`${t}${S}/publisher/items`,{method:"GET",headers:{Authorization:`Bearer ${e.accessToken}`}});}catch(f){throw new Error(`publish: version \uC870\uD68C \uC694\uCCAD\uC774 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4 (\uB124\uD2B8\uC6CC\uD06C) \u2014 ${f instanceof Error?f.message:String(f)}`)}let $=await C(o);if(o.status!==200)throw new Error(`publish: publisher items \uC870\uD68C \uC2E4\uD328 \u2014 HTTP ${o.status}${w($)?` ${w($)}`:""}`);let z=te($,"publisher items",o.status)?.items;if(!Array.isArray(z))throw new Error(`publish: publisher items response malformed (expected data.items[]) \u2014 HTTP ${o.status}`);let I=z.find(f=>!f||typeof f!="object"?false:f.slug===s);if(!I||typeof I.version!="string")throw new Error(`publish: publisher items response does not contain slug "${s}" \u2014 HTTP ${o.status}`);if(m=I.version,m!==e.manifest.version){let f;try{f=await fetch(`${t}${S}/publisher/items/${encodeURIComponent(s)}`,{method:"PUT",headers:{Authorization:`Bearer ${e.accessToken}`,"Content-Type":"application/json"},body:JSON.stringify({version:e.manifest.version})});}catch(_){throw new Error(`publish: version update \uC694\uCCAD\uC774 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4 (\uB124\uD2B8\uC6CC\uD06C) \u2014 ${_ instanceof Error?_.message:String(_)}`)}if(!f.ok){let _=await C(f),E=w(_);throw f.status===O?new Error(`publish: version update \uC778\uC99D\uC774 \uB9CC\uB8CC\uB418\uC5C8\uAC70\uB098 \uC5C6\uC2B5\uB2C8\uB2E4 \u2014 \uB2E4\uC2DC \uB85C\uADF8\uC778\uD558\uC138\uC694 (HTTP ${f.status})${E?` ${E}`:""}`):f.status===403?new Error(`publish: version update \uAD8C\uD55C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4 \u2014 \uAE30\uC874 \uD56D\uBAA9\uC758 \uC18C\uC720\uC790\uB9CC \uBC84\uC804\uC744 \uAC31\uC2E0\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4 (HTTP ${f.status})${E?` ${E}`:""}`):new Error(`publish: version update \uC2E4\uD328 \u2014 HTTP ${f.status}${E?` ${E}`:""}`)}a="applied";}}let c=g.readFileSync(e.tgzPath),u=Ee()?Ae(c):c,l=new FormData;l.set("archive",new Blob([new Uint8Array(u)],{type:"application/gzip"}),`${s}-${e.manifest.version}.tgz`);let p;try{p=await fetch(`${t}${S}/publisher/items/${encodeURIComponent(s)}/upload`,{method:"POST",headers:{Authorization:`Bearer ${e.accessToken}`},body:l});}catch(o){throw new Error(`publish: upload \uC694\uCCAD\uC774 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4 (\uB124\uD2B8\uC6CC\uD06C) \u2014 ${o instanceof Error?o.message:String(o)}`)}if(p.status===O)throw new Error("publish: \uC778\uC99D\uC774 \uB9CC\uB8CC\uB418\uC5C8\uAC70\uB098 \uC5C6\uC2B5\uB2C8\uB2E4 \u2014 \uB2E4\uC2DC \uB85C\uADF8\uC778\uD558\uC138\uC694");if(!p.ok){let o=await C(p);throw new Error(`publish: upload \uC2E4\uD328 \u2014 HTTP ${p.status}${w(o)?` ${w(o)}`:""}`)}let P=await C(p),H=te(P,"upload",p.status);return {slug:s,version:e.manifest.version,artifactChecksum:H.artifactChecksum,artifactSizeBytes:H.artifactSizeBytes,submitOutcome:i,versionUpdate:a,serverVersionBefore:m}}function se(){if(process.env.CREWX_HOME)try{return g.realpathSync(process.env.CREWX_HOME)}catch{return b.join(N.homedir(),".crewx")}return process.platform!=="win32"&&process.env.XDG_CONFIG_HOME?b.join(process.env.XDG_CONFIG_HOME,"crewx"):b.join(N.homedir(),".crewx")}var y=class extends Error{code;constructor(t,r){super(r),this.name="AccountAuthBoundaryError",this.code=t;}};function j(e=process.env){let t=e.CREWX_ACCOUNT_ISSUER?.trim(),r=e.CREWX_ACCOUNT_ANON_KEY?.trim();if(!t&&!r)throw new y("ACCOUNT_USER_PAIR_MISSING","CrewX user-realm issuer and anon/publishable key pair are not configured");if(!t)throw new y("ACCOUNT_USER_ISSUER_MISSING","CrewX user-realm issuer is not configured");if(!r)throw new y("ACCOUNT_USER_ANON_KEY_MISSING","CrewX user-realm anon/publishable key is not configured");return {issuer:t,anonKey:r}}function x(){throw new y("ACCOUNT_ACCESS_TOKEN_INVALID","Account access token could not be verified")}function ie(e){try{return JSON.parse(Buffer.from(e,"base64url").toString("utf8"))}catch{return x()}}function oe(e){if(typeof e!="string")return x();let t=e.split(".");if(t.length!==3||t.some(i=>i.length===0))return x();let r=ie(t[0]),s=ie(t[1]);if(!r||typeof r!="object"||!s||typeof s!="object")return x();let n=s;return typeof n.iss!="string"||n.iss.length===0||typeof n.sub!="string"||n.sub.length===0?x():{issuer:n.iss,sub:n.sub}}function ae(e,t,r){let s=oe(e);if(s.issuer!==t.issuer)throw new y("ACCOUNT_TOKEN_ISSUER_MISMATCH","Account access token does not match the configured user realm");if(r!==void 0&&s.sub!==r)throw new y("ACCOUNT_TOKEN_SUB_MISMATCH","Account access token subject does not match the expected identity");return s}function B(e,t){if(e.issuer!==t.issuer)throw new y("ACCOUNT_AUTH_JSON_ISSUER_MISMATCH","auth.json does not match the configured user realm");let r=ae(e.access_token,t);if(r.sub!==e.sub)throw new y("ACCOUNT_AUTH_JSON_SUB_MISMATCH","auth.json subject does not match the access token identity");return r}function Ce(e){if(!e||typeof e!="object")return false;let t=e;return t.version===1&&typeof t.sub=="string"&&typeof t.email=="string"&&typeof t.access_token=="string"&&typeof t.refresh_token=="string"&&typeof t.expires_at=="number"&&typeof t.issuer=="string"&&typeof t.updated_at=="string"}function Pe(){let e=join(se(),"auth.json");if(!existsSync(e))throw new Error(`Login required \u2014 ${e} was not found (please log in first)`);let t;try{t=readFileSync(e,"utf8");}catch(n){throw new Error(`Could not read auth.json (${e}): ${n instanceof Error?n.message:String(n)}`)}let r;try{r=JSON.parse(t);}catch(n){throw new Error(`Failed to parse auth.json (${e}): ${n instanceof Error?n.message:String(n)}`)}if(!Ce(r))throw new Error(`auth.json is malformed (${e}) \u2014 please log in again`);let s=j();return B(r,s),r}async function Ue(e,t={}){let r=b.resolve(e),{included:s,excluded:n}=K(r),i=Z(r,s,{version:t.version}),a=X(r,s);return {manifest:i,included:s,excluded:n,secretFindings:a}}async function ft(e,t={}){let r=await Ue(e,t);if(r.secretFindings.length>0){let i=r.secretFindings.map(a=>`${a.path}:${a.line} (${a.rule})`).join(", ");throw new Error(`publish: aborted \u2014 secret findings must be resolved before packing: ${i}`)}let s=b.resolve(e),n=await ee(s,r.manifest);return {manifest:r.manifest,tgzPath:n}}export{y as AccountAuthBoundaryError,D as EXCLUDE_RULES,S as MARKETPLACE_API_PREFIX,B as assertAuthJsonUserRealm,ae as assertUserRealmAccessToken,oe as decodeAccessTokenIdentity,ft as packTemplate,Ue as planPublish,Pe as readAuthJson,j as resolveUserAccountConfig,xe as uploadToMarketplace};
|
|
1
|
+
import*as E from'path';import {join}from'path';import*as g from'fs';import {existsSync,readFileSync}from'fs';import*as W from'crypto';import*as G from'js-yaml';import*as N from'os';import*as Q from'tar';import {gunzipSync,gzipSync}from'zlib';function ce(e){let t=n=>n.replace(/[.+^${}()|[\]\\]/g,"\\$&"),s=e.split("/").map(n=>n==="**"?".*":n.split("*").map(t).join("[^/]*"));return new RegExp(`^${s.join("\\/")}$`)}function A(e,t){try{return ce(t).test(e)}catch{return false}}function v(e,...t){let r=e.split("/");if(r.length<t.length)return false;let s=r.length-t.length;return t.every((n,i)=>A(r[s+i],n))}function ue(e,t){return e.split("/").some(r=>A(r,t))}var z=[{label:".env*",test:e=>A(e,".env*")},{label:".git/",test:(e,t,r)=>r&&e===".git"},{label:"memory/",test:(e,t,r)=>r&&e==="memory"},{label:"*.key",test:e=>A(e,"*.key")},{label:"*.pem",test:e=>A(e,"*.pem")},{label:"auth.json",test:e=>e==="auth.json"},{label:"node_modules/",test:(e,t,r)=>r&&e==="node_modules"},{label:"conversations/",test:(e,t,r)=>r&&e==="conversations"},{label:".crewx/threads/",test:(e,t,r)=>r&&v(t,".crewx","threads")},{label:".crewx/crewx.db",test:(e,t,r)=>!r&&v(t,".crewx","crewx.db")},{label:".crewx/*.log",test:(e,t,r)=>!r&&v(t,".crewx","*.log")},{label:".crewx/publish/",test:(e,t,r)=>r&&v(t,".crewx","publish")},{label:".crewx/",test:(e,t)=>ue(t,".crewx")}];function R(e,t,r){for(let s of z)if(s.test(e,t,r))return s.label;return null}function K(e){let t=[],r=[];function s(n,i,a){let d;try{d=g.readdirSync(n,{withFileTypes:!0});}catch{return}d.sort((c,u)=>c.name.localeCompare(u.name));for(let c of d){let u=i?`${i}/${c.name}`:c.name,l=E.join(n,c.name);if(c.isSymbolicLink()){let p;try{p=g.statSync(l);}catch{continue}if(p.isDirectory()){r.push({path:u,rule:a??"symlink-dir"});continue}let C=a??R(c.name,u,false);C?r.push({path:u,rule:C}):t.push(u);continue}if(c.isDirectory()){let p=a??R(c.name,u,true);s(l,u,p);continue}if(c.isFile()){let p=a??R(c.name,u,false);p?r.push({path:u,rule:p}):t.push(u);}}}return s(e,"",null),t.sort(),r.sort((n,i)=>n.path<i.path?-1:n.path>i.path?1:0),{included:t,excluded:r}}var le=[{rule:"token-prefix",regex:/\b(?:sk-|ghp_|xoxb-)[A-Za-z0-9_-]{10,}/},{rule:"private-key",regex:/-----BEGIN [A-Z ]*PRIVATE KEY-----/},{rule:"aws-access-key",regex:/\bAKIA[0-9A-Z]{16}\b/}];function pe(e){return e.includes(0)}function V(e,t){let r=[];for(let s of t){let n=E.join(e,s),i;try{i=g.readFileSync(n);}catch{continue}if(pe(i))continue;i.toString("utf8").split(/\r\n|\r|\n/).forEach((d,c)=>{for(let{rule:u,regex:l}of le)l.test(d)&&r.push({path:s,line:c+1,rule:u});});}return r}var X=/^[a-z0-9-]+$/,fe=/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/,de=/^[A-Za-z_][A-Za-z0-9_]*$/;function me(e){let t=E.join(e,"crewx.yaml");if(!g.existsSync(t))return {};let r;try{r=G.load(g.readFileSync(t,"utf8"));}catch{return {}}if(!r||typeof r!="object")return {};let s=r.metadata;if(!s||typeof s!="object")return {};let n=s;return {name:typeof n.name=="string"?n.name:void 0,version:typeof n.version=="string"?n.version:void 0,description:typeof n.description=="string"?n.description:void 0,requiredEnv:n.requiredEnv,crewxMinVersion:typeof n.crewxMinVersion=="string"?n.crewxMinVersion:void 0}}function he(e){return W.createHash("sha256").update(new Uint8Array(g.readFileSync(e))).digest("hex")}function Z(e,t,r={}){let s=me(e),n=s.name??E.basename(e);if(!X.test(n))throw new Error(`publish: invalid name "${n}" \u2014 must match ${X} (lowercase letters, numbers, hyphen only)`);let i=r.version??s.version;if(!i)throw new Error("publish: version is required \u2014 set crewx.yaml metadata.version or pass opts.version");if(!fe.test(i))throw new Error(`publish: invalid version "${i}" \u2014 must be semver (e.g. 1.0.0)`);let a=Array.isArray(s.requiredEnv)?s.requiredEnv:[],d=[];for(let l of a){if(typeof l!="string"||!de.test(l))throw new Error(`publish: requiredEnv must contain names only (no values), got "${String(l)}"`);d.push(l);}let c=t.map(l=>({path:l,sha256:he(E.join(e,l))})).sort((l,p)=>l.path<p.path?-1:l.path>p.path?1:0),u={name:n,version:i,type:"template",description:s.description??"",files:c,requiredEnv:d};return s.crewxMinVersion&&(u.crewxMinVersion=s.crewxMinVersion),u}async function ee(e,t){let r=E.join(e,".crewx","publish");g.mkdirSync(r,{recursive:true});let s=E.join(r,`${t.name}-${t.version}.tgz`),n=g.mkdtempSync(E.join(N.tmpdir(),"crewx-publish-"));try{g.writeFileSync(E.join(n,"manifest.json"),JSON.stringify(t,null,2));for(let i of t.files){let a=E.join(n,i.path);g.mkdirSync(E.dirname(a),{recursive:!0}),g.copyFileSync(E.join(e,i.path),a);}await Q.create({gzip:!0,file:s,cwd:n,portable:!0,noMtime:!0},["manifest.json",...t.files.map(i=>i.path)]);}finally{g.rmSync(n,{recursive:true,force:true});}return s}var _="/api/v1";var Ee=201,be=409,I=401;function we(){return process.env.WI013_FAKE_UPLOAD==="1"}function Ae(e){let t=gunzipSync(new Uint8Array(e)),r=gzipSync(new Uint8Array(t),{level:1});if(Buffer.compare(new Uint8Array(r),new Uint8Array(e))===0)throw new Error("publish: [E_MALFORMED] Re-gzipped upload bytes are identical to the original \u2014 tamper is a no-op");return r}function _e(e){return e.replace(/\/+$/,"")}async function U(e){try{return await e.json()}catch{return null}}function b(e){let t=e?.message;return typeof t=="string"?t:void 0}function te(e,t,r){let s=e;if(!s||s.success!==true||s.data===void 0)throw new Error(`publish: [E_MALFORMED] ${t} response envelope is malformed (expected { success: true, data }) \u2014 HTTP ${r}`);return s.data}async function Te(e){let t=_e(e.baseUrl),r=e.accessPolicy??"private",s=e.manifest.name,n;try{n=await fetch(`${t}${_}/publisher/items`,{method:"POST",headers:{Authorization:`Bearer ${e.accessToken}`,"Content-Type":"application/json"},body:JSON.stringify({slug:s,displayName:s,description:e.manifest.description,type:"template",version:e.manifest.version,accessPolicy:r})});}catch(o){throw new Error(`publish: [E_NETWORK] Submit request failed (network) \u2014 ${o instanceof Error?o.message:String(o)}`)}let i;if(n.status===Ee)i="created";else if(n.status===be)i="existing";else {if(n.status===I)throw new Error("publish: [E_AUTH_EXPIRED] Authentication is expired or missing \u2014 please log in again (HTTP 401)");{let o=await U(n);throw new Error(`publish: [E_HTTP] Submit request failed \u2014 HTTP ${n.status}${b(o)?` ${b(o)}`:""}`)}}let a="not-needed",d=null;if(i==="existing"){let o;try{o=await fetch(`${t}${_}/publisher/items`,{method:"GET",headers:{Authorization:`Bearer ${e.accessToken}`}});}catch(f){throw new Error(`publish: [E_NETWORK] Publisher items request failed (network) \u2014 ${f instanceof Error?f.message:String(f)}`)}let O=await U(o);if(o.status!==200)throw new Error(`publish: [E_HTTP] Publisher items request failed \u2014 HTTP ${o.status}${b(O)?` ${b(O)}`:""}`);let D=te(O,"publisher items",o.status)?.items;if(!Array.isArray(D))throw new Error(`publish: [E_MALFORMED] Publisher items response is malformed (expected data.items[]) \u2014 HTTP ${o.status}`);let $=D.find(f=>!f||typeof f!="object"?false:f.slug===s);if(!$||typeof $.version!="string")throw new Error(`publish: [E_MALFORMED] Publisher items response does not contain slug "${s}" \u2014 HTTP ${o.status}`);if(d=$.version,d!==e.manifest.version){let f;try{f=await fetch(`${t}${_}/publisher/items/${encodeURIComponent(s)}`,{method:"PUT",headers:{Authorization:`Bearer ${e.accessToken}`,"Content-Type":"application/json"},body:JSON.stringify({version:e.manifest.version})});}catch(x){throw new Error(`publish: [E_NETWORK] Version update request failed (network) \u2014 ${x instanceof Error?x.message:String(x)}`)}if(!f.ok){let x=await U(f),w=b(x);throw f.status===I?new Error(`publish: [E_AUTH_EXPIRED] Authentication is expired or missing \u2014 please log in again (HTTP ${f.status})${w?` ${w}`:""}`):f.status===403?new Error(`publish: [E_FORBIDDEN] Version update is forbidden; only the item owner can update an existing item (HTTP ${f.status})${w?` ${w}`:""}`):new Error(`publish: [E_HTTP] Version update failed \u2014 HTTP ${f.status}${w?` ${w}`:""}`)}a="applied";}}let c=g.readFileSync(e.tgzPath),u=we()?Ae(c):c,l=new FormData;l.set("archive",new Blob([new Uint8Array(u)],{type:"application/gzip"}),`${s}-${e.manifest.version}.tgz`);let p;try{p=await fetch(`${t}${_}/publisher/items/${encodeURIComponent(s)}/upload`,{method:"POST",headers:{Authorization:`Bearer ${e.accessToken}`},body:l});}catch(o){throw new Error(`publish: [E_NETWORK] Upload request failed (network) \u2014 ${o instanceof Error?o.message:String(o)}`)}if(p.status===I)throw new Error("publish: [E_AUTH_EXPIRED] Authentication is expired or missing \u2014 please log in again (HTTP 401)");if(!p.ok){let o=await U(p);throw new Error(`publish: [E_HTTP] Upload request failed \u2014 HTTP ${p.status}${b(o)?` ${b(o)}`:""}`)}let C=await U(p),B=te(C,"upload",p.status);return {slug:s,version:e.manifest.version,artifactChecksum:B.artifactChecksum,artifactSizeBytes:B.artifactSizeBytes,submitOutcome:i,versionUpdate:a,serverVersionBefore:d}}function se(){if(process.env.CREWX_HOME)try{return g.realpathSync(process.env.CREWX_HOME)}catch{return E.join(N.homedir(),".crewx")}return process.platform!=="win32"&&process.env.XDG_CONFIG_HOME?E.join(process.env.XDG_CONFIG_HOME,"crewx"):E.join(N.homedir(),".crewx")}var y=class extends Error{code;constructor(t,r){super(r),this.name="AccountAuthBoundaryError",this.code=t;}};function H(e=process.env){let t=e.CREWX_ACCOUNT_ISSUER?.trim(),r=e.CREWX_ACCOUNT_ANON_KEY?.trim();if(!t&&!r)throw new y("ACCOUNT_USER_PAIR_MISSING","CrewX user-realm issuer and anon/publishable key pair are not configured");if(!t)throw new y("ACCOUNT_USER_ISSUER_MISSING","CrewX user-realm issuer is not configured");if(!r)throw new y("ACCOUNT_USER_ANON_KEY_MISSING","CrewX user-realm anon/publishable key is not configured");return {issuer:t,anonKey:r}}function T(){throw new y("ACCOUNT_ACCESS_TOKEN_INVALID","Account access token could not be verified")}function ie(e){try{return JSON.parse(Buffer.from(e,"base64url").toString("utf8"))}catch{return T()}}function oe(e){if(typeof e!="string")return T();let t=e.split(".");if(t.length!==3||t.some(i=>i.length===0))return T();let r=ie(t[0]),s=ie(t[1]);if(!r||typeof r!="object"||!s||typeof s!="object")return T();let n=s;return typeof n.iss!="string"||n.iss.length===0||typeof n.sub!="string"||n.sub.length===0?T():{issuer:n.iss,sub:n.sub}}function ae(e,t,r){let s=oe(e);if(s.issuer!==t.issuer)throw new y("ACCOUNT_TOKEN_ISSUER_MISMATCH","Account access token does not match the configured user realm");if(r!==void 0&&s.sub!==r)throw new y("ACCOUNT_TOKEN_SUB_MISMATCH","Account access token subject does not match the expected identity");return s}function F(e,t){if(e.issuer!==t.issuer)throw new y("ACCOUNT_AUTH_JSON_ISSUER_MISMATCH","auth.json does not match the configured user realm");let r=ae(e.access_token,t);if(r.sub!==e.sub)throw new y("ACCOUNT_AUTH_JSON_SUB_MISMATCH","auth.json subject does not match the access token identity");return r}function Ue(e){if(!e||typeof e!="object")return false;let t=e;return t.version===1&&typeof t.sub=="string"&&typeof t.email=="string"&&typeof t.access_token=="string"&&typeof t.refresh_token=="string"&&typeof t.expires_at=="number"&&typeof t.issuer=="string"&&typeof t.updated_at=="string"}function Ce(){let e=join(se(),"auth.json");if(!existsSync(e))throw new Error(`Login required \u2014 ${e} was not found (please log in first)`);let t;try{t=readFileSync(e,"utf8");}catch(n){throw new Error(`Could not read auth.json (${e}): ${n instanceof Error?n.message:String(n)}`)}let r;try{r=JSON.parse(t);}catch(n){throw new Error(`Failed to parse auth.json (${e}): ${n instanceof Error?n.message:String(n)}`)}if(!Ue(r))throw new Error(`auth.json is malformed (${e}) \u2014 please log in again`);let s=H();return F(r,s),r}async function ve(e,t={}){let r=E.resolve(e),{included:s,excluded:n}=K(r),i=Z(r,s,{version:t.version}),a=V(r,s);return {manifest:i,included:s,excluded:n,secretFindings:a}}async function ft(e,t={}){let r=await ve(e,t);if(r.secretFindings.length>0){let i=r.secretFindings.map(a=>`${a.path}:${a.line} (${a.rule})`).join(", ");throw new Error(`publish: aborted \u2014 secret findings must be resolved before packing: ${i}`)}let s=E.resolve(e),n=await ee(s,r.manifest);return {manifest:r.manifest,tgzPath:n}}export{y as AccountAuthBoundaryError,z as EXCLUDE_RULES,_ as MARKETPLACE_API_PREFIX,F as assertAuthJsonUserRealm,ae as assertUserRealmAccessToken,oe as decodeAccessTokenIdentity,ft as packTemplate,ve as planPublish,Ce as readAuthJson,H as resolveUserAccountConfig,Te as uploadToMarketplace};
|