@crewx/sdk 0.8.4-rc.0 → 0.8.4-rc.1
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/conversation/types.d.ts +1 -1
- package/dist/esm/index.js +34 -34
- package/dist/esm/plugins/index.js +3 -3
- package/dist/esm/repository/index.js +8 -8
- package/dist/index.js +33 -33
- package/dist/plugins/index.js +3 -3
- package/dist/provider/acp/connection.d.ts +1 -0
- package/dist/provider/bridge.d.ts +1 -0
- package/dist/provider/cli/adapters/tool-input.util.d.ts +1 -0
- package/dist/repository/index.js +8 -8
- package/dist/repository/workspace.repository.d.ts +4 -0
- package/dist/types/task-log.types.d.ts +1 -1
- package/dist/utils/workspace.d.ts +2 -0
- package/package.json +1 -1
|
@@ -8,9 +8,9 @@ Message: ${e.message}
|
|
|
8
8
|
`;writeFileSync(n,r,{encoding:"utf8",mode:384});}catch{}}),t.on("task:output",e=>{try{let s=this.logFiles.get(e.traceId);if(!s)return;let n=new Date().toISOString();appendFileSync(s,`[${n}] STDOUT: ${e.output}
|
|
9
9
|
`,"utf8");}catch{}}),t.on("task:end",e=>{try{let s=this.logFiles.get(e.traceId);if(!s)return;let n=new Date().toLocaleString(),r=e.error?`failed: ${e.error.message}`:"completed successfully",i=`[${n}] INFO: Task ${r} in ${e.durationMs}ms
|
|
10
10
|
[${n}] INFO: Process closed with exit code: ${e.error?1:0}
|
|
11
|
-
`;appendFileSync(s,i,"utf8"),this.logFiles.delete(e.traceId);}catch{}}));}detach(t){this.unsubs.forEach(e=>e()),this.unsubs=[],this.logFiles.clear();}};function vt(d){let t=et.resolve(d);return process.platform==="win32"&&(t=t.replace(/\\/g,"/"),t=t.replace(/^([A-Z]):/,(e,s)=>`${s.toLowerCase()}:`)),t.length>1&&!/^[a-zA-Z]:\/$/.test(t)&&(t=t.replace(/\/+$/,"")),t}function pt(d){let t=vt(d);return createHash("sha256").update(t).digest("hex")}var
|
|
11
|
+
`;appendFileSync(s,i,"utf8"),this.logFiles.delete(e.traceId);}catch{}}));}detach(t){this.unsubs.forEach(e=>e()),this.unsubs=[],this.logFiles.clear();}};function vt(d){let t=et.resolve(d);return process.platform==="win32"&&(t=t.replace(/\\/g,"/"),t=t.replace(/^([A-Z]):/,(e,s)=>`${s.toLowerCase()}:`)),t.length>1&&!/^[a-zA-Z]:\/$/.test(t)&&(t=t.replace(/\/+$/,"")),t}function pt(d){let t=vt(d);return createHash("sha256").update(t).digest("hex")}var F=class{resolveDbPath(){return process.env.CREWX_DB?process.env.CREWX_DB:process.env.CREWX_TRACES_DB?process.env.CREWX_TRACES_DB:join(It.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=Z("better-sqlite3"),{drizzle:e}=Z("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"),{db:e(s),runRaw:(n,r=[])=>s.prepare(n).run(...r),close:()=>s.close()}}var _t=new Set;function Ut(d){let{migrate:t}=Z("drizzle-orm/better-sqlite3/migrator"),e=[et__default.join(g,"../migrations"),et__default.join(g,"migrations")],s=e.find(n=>existsSync(et__default.join(n,"meta/_journal.json")));if(!s)throw new Error(`migrations folder not found. Searched:
|
|
12
12
|
${e.join(`
|
|
13
|
-
`)}`);t(d,{migrationsFolder:s});}function W(d,t){_t.has(t)||(Ut(d),_t.add(t));}var c=class extends Error{code;cause;constructor(t,e,s){super(e),this.name="RepositoryError",this.code=t,this.cause=s,Object.setPrototypeOf(this,new.target.prototype);}};var q=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 o=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"),workspace_name:text("workspace_name"),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_name:text("project_name"),project_ref:text("project_ref"),cached_input_tokens:integer("cached_input_tokens").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 u=sqliteTable("threads",{id:text("id").primaryKey(),workspace_id:text("workspace_id").references(()=>q.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)},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)}));var Wt=sqliteTable("spans",{id:text("id").primaryKey(),task_id:text("task_id").references(()=>o.id,{onDelete:"set null"}),parent_span_id:text("parent_span_id").references(()=>Wt.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").notNull().references(()=>o.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(()=>u.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)}));var X=class extends
|
|
13
|
+
`)}`);t(d,{migrationsFolder:s});}function W(d,t){_t.has(t)||(Ut(d),_t.add(t));}var c=class extends Error{code;cause;constructor(t,e,s){super(e),this.name="RepositoryError",this.code=t,this.cause=s,Object.setPrototypeOf(this,new.target.prototype);}};var q=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 o=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"),workspace_name:text("workspace_name"),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_name:text("project_name"),project_ref:text("project_ref"),cached_input_tokens:integer("cached_input_tokens").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 u=sqliteTable("threads",{id:text("id").primaryKey(),workspace_id:text("workspace_id").references(()=>q.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)},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)}));var Wt=sqliteTable("spans",{id:text("id").primaryKey(),task_id:text("task_id").references(()=>o.id,{onDelete:"set null"}),parent_span_id:text("parent_span_id").references(()=>Wt.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").notNull().references(()=>o.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(()=>u.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)}));var X=class extends F{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 e=this.resolveDbPath();if(t){let n=dirname(e);existsSync(n)||mkdirSync(n,{recursive:true});}else if(!existsSync(e))throw new c("NOT_FOUND","Database not found");let s=b(e);if(t)try{W(s.db,e);}catch(n){throw s.close(),n}return s}startTask(t){let e=this.openHandle(true);try{e.db.insert(o).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,workspace_name:t.workspaceName??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}).onConflictDoNothing().run();}catch(s){throw s instanceof c?s:new c("DB_ERROR","Failed to start task",s)}finally{e.close();}}finishTask(t){let e=this.openHandle(true);try{e.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) WHERE id=?`,[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]);}catch(s){throw s instanceof c?s:new c("DB_ERROR","Failed to finish task",s)}finally{e.close();}}appendLog(t,e){let s=this.openHandle(true);try{s.db.transaction(n=>{let r=n.select({logs:o.logs}).from(o).where(eq(o.id,t)).limit(1).get(),i=r?.logs?JSON.parse(r.logs):[];i.push(e),n.update(o).set({logs:JSON.stringify(i)}).where(eq(o.id,t)).run();},{behavior:"immediate"});}catch(n){throw n instanceof c?n:new c("DB_ERROR","Failed to append log",n)}finally{s.close();}}getRunningTasks(){if(!this.dbExists())return [];let t=this.openHandle(false);try{return t.db.select().from(o).where(eq(o.status,"running")).orderBy(desc(o.started_at)).all()}catch(e){throw new c("DB_ERROR","Failed to get running tasks",e)}finally{t.close();}}getAllTasks(){if(!this.dbExists())return [];let t=this.openHandle(false);try{return t.db.select().from(o).orderBy(desc(o.started_at)).limit(100).all()}catch(e){throw new c("DB_ERROR","Failed to get all tasks",e)}finally{t.close();}}getTask(t){if(!this.dbExists())return;let e=this.openHandle(false);try{return e.db.select().from(o).where(eq(o.id,t)).limit(1).get()??void 0}catch(s){throw new c("DB_ERROR","Failed to get task",s)}finally{e.close();}}killTask(t){if(!this.dbExists())return {killed:false};let e=this.openHandle(true);try{let s=e.db.select({id:o.id,status:o.status,pid:o.pid}).from(o).where(eq(o.id,t)).limit(1).get();if(!s||s.status!=="running")return {killed:!1};if(s.pid)try{process.kill(s.pid,"SIGTERM");}catch{}return e.db.update(o).set({status:"failed",error:"Killed by user",completed_at:new Date().toISOString()}).where(and(eq(o.id,t),eq(o.status,"running"))).run(),{killed:!0,pid:s.pid??void 0}}catch(s){throw s instanceof c?s:new c("DB_ERROR","Failed to kill task",s)}finally{e.close();}}findTaskStatus(t,e){let s=this.resolveDbPaths();for(let n of s){if(!existsSync(n))continue;let r=b(n);try{let i=e?eq(o.workspace_id,e):void 0,l=i?and(eq(o.id,t),i):eq(o.id,t),a=r.db.select().from(o).where(l).limit(1).get()??void 0;if(!a){let _=or(eq(o.thread_id,t),and(isNull(o.thread_id),like(o.command,`%--thread=${t}%`))),p=i?and(_,i):_;a=r.db.select().from(o).where(p).orderBy(desc(o.started_at)).limit(1).get()??void 0;}if(a)return a}catch(i){throw new c("DB_ERROR","Failed to find task status",i)}finally{r.close();}}}findChildTasks(t,e){let s=this.resolveDbPaths(),n=new Set,r=[];for(let i of s){if(!existsSync(i))continue;let l=b(i);try{let a=e?and(eq(o.parent_task_id,t),eq(o.workspace_id,e)):eq(o.parent_task_id,t),_=l.db.select().from(o).where(a).orderBy(asc(o.started_at)).all();for(let p of _)n.has(p.id)||(n.add(p.id),r.push(p));}catch(a){throw new c("DB_ERROR","Failed to find child tasks",a)}finally{l.close();}}return r}getWorkspaceUsageSummary(t){if(!this.dbExists())return [];let e=this.openHandle(false);try{return e.db.all(t?sql`
|
|
16
16
|
SELECT
|
|
@@ -97,7 +97,7 @@ ${e.join(`
|
|
|
97
97
|
AND t.started_at < ${e}
|
|
98
98
|
GROUP BY date(t.started_at), t.agent_id
|
|
99
99
|
ORDER BY date(t.started_at) ASC
|
|
100
|
-
`).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}))}catch(r){throw new c("DB_ERROR","Failed to get agent usage trend",r)}finally{n.close();}}findTaskForStop(t,e){if(!this.dbExists())return;let s=this.openHandle(false);try{return s.db.select().from(o).where(and(eq(o.id,t),eq(o.workspace_id,e))).limit(1).get()??void 0}catch(n){throw new c("DB_ERROR","Failed to find task for stop",n)}finally{s.close();}}markTaskFailed(t,e,s){if(!this.dbExists())return;let n=this.openHandle(true);try{let r=new Date().toISOString(),i=s?and(eq(o.id,t),eq(o.status,"running"),eq(o.workspace_id,s)):and(eq(o.id,t),eq(o.status,"running"));n.db.update(o).set({status:"failed",error:e,completed_at:r}).where(i).run();}catch(r){throw r instanceof c?r:new c("DB_ERROR","Failed to mark task failed",r)}finally{n.close();}}findTasksByPromptHint(t,e){let s=this.resolveDbPaths(),n=new Set,r=[];for(let i of s){if(!existsSync(i))continue;let l=b(i);try{let a=e?and(like(o.prompt,`%${t}%`),eq(o.workspace_id,e)):like(o.prompt,`%${t}%`),_=l.db.select().from(o).where(a).orderBy(asc(o.started_at)).all();for(let p of _)n.has(p.id)||(n.add(p.id),r.push(p));}catch(a){throw new c("DB_ERROR","Failed to find tasks by prompt hint",a)}finally{l.close();}}return r}};var it=class extends O{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 e=new X({dbPath:this.dbPath}),s=process.cwd(),n=existsSync(join(s,"crewx.yaml"))||existsSync(join(s,"crewx.yml")),r=n?pt(s):null,i=n?basename(s):null,l=process.argv.join(" ");this.unsubs.push(t.on("task:start",a=>{try{let _=process.env.CREWX_CALLER_AGENT_ID||null,p=process.env.CREWX_PARENT_TASK_ID||null,k=process.env.CREWX_TRACE_ID||a.traceId,A=a.metadata?JSON.stringify(a.metadata):JSON.stringify({provider:a.provider??"cli/claude"});e.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:l,codingAgentCommand:a.codingAgentCommand??null,workspaceId:a.workspaceId??r,workspaceName:a.workspaceName??i,callerAgentId:_,parentTaskId:p,traceId:k,metadata:A,threadId:a.threadId??null});}catch{}}),t.on("task:output",a=>{try{e.appendLog(a.traceId,{timestamp:a.timestamp.toISOString(),level:a.level??"stdout",message:a.output});}catch{}}),t.on("task:end",a=>{try{e.finishTask({id:a.traceId,status:a.error?"failed":"success",result:a.result??null,error:a.error?JSON.stringify(a.error):null,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});}catch{}}));}detach(t){this.unsubs.forEach(e=>e()),this.unsubs=[];}};var V=class extends
|
|
100
|
+
`).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}))}catch(r){throw new c("DB_ERROR","Failed to get agent usage trend",r)}finally{n.close();}}findTaskForStop(t,e){if(!this.dbExists())return;let s=this.openHandle(false);try{return s.db.select().from(o).where(and(eq(o.id,t),eq(o.workspace_id,e))).limit(1).get()??void 0}catch(n){throw new c("DB_ERROR","Failed to find task for stop",n)}finally{s.close();}}markTaskFailed(t,e,s){if(!this.dbExists())return;let n=this.openHandle(true);try{let r=new Date().toISOString(),i=s?and(eq(o.id,t),eq(o.status,"running"),eq(o.workspace_id,s)):and(eq(o.id,t),eq(o.status,"running"));n.db.update(o).set({status:"failed",error:e,completed_at:r}).where(i).run();}catch(r){throw r instanceof c?r:new c("DB_ERROR","Failed to mark task failed",r)}finally{n.close();}}findTasksByPromptHint(t,e){let s=this.resolveDbPaths(),n=new Set,r=[];for(let i of s){if(!existsSync(i))continue;let l=b(i);try{let a=e?and(like(o.prompt,`%${t}%`),eq(o.workspace_id,e)):like(o.prompt,`%${t}%`),_=l.db.select().from(o).where(a).orderBy(asc(o.started_at)).all();for(let p of _)n.has(p.id)||(n.add(p.id),r.push(p));}catch(a){throw new c("DB_ERROR","Failed to find tasks by prompt hint",a)}finally{l.close();}}return r}};var it=class extends O{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 e=new X({dbPath:this.dbPath}),s=process.cwd(),n=existsSync(join(s,"crewx.yaml"))||existsSync(join(s,"crewx.yml")),r=n?pt(s):null,i=n?basename(s):null,l=process.argv.join(" ");this.unsubs.push(t.on("task:start",a=>{try{let _=process.env.CREWX_CALLER_AGENT_ID||null,p=process.env.CREWX_PARENT_TASK_ID||null,k=process.env.CREWX_TRACE_ID||a.traceId,A=a.metadata?JSON.stringify(a.metadata):JSON.stringify({provider:a.provider??"cli/claude"});e.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:l,codingAgentCommand:a.codingAgentCommand??null,workspaceId:a.workspaceId??r,workspaceName:a.workspaceName??i,callerAgentId:_,parentTaskId:p,traceId:k,metadata:A,threadId:a.threadId??null});}catch{}}),t.on("task:output",a=>{try{e.appendLog(a.traceId,{timestamp:a.timestamp.toISOString(),level:a.level??"stdout",message:a.output});}catch{}}),t.on("task:end",a=>{try{e.finishTask({id:a.traceId,status:a.error?"failed":"success",result:a.result??null,error:a.error?JSON.stringify(a.error):null,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});}catch{}}));}detach(t){this.unsubs.forEach(e=>e()),this.unsubs=[];}};var V=class extends F{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 e=this.resolveDbPath();if(t){let n=dirname(e);existsSync(n)||mkdirSync(n,{recursive:true});}else if(!existsSync(e))throw new c("NOT_FOUND","Database not found");let s=b(e);if(t)try{W(s.db,e);}catch(n){throw s.close(),n}return s}validateWorkspaceId(t,e){return t.db.select({id:q.id}).from(q).where(eq(q.id,e)).limit(1).get()?e:null}findAllThreads(t){let e=this.resolveDbPaths(),s=new Set,n=[];for(let r of e){if(!existsSync(r))continue;let i=b(r);try{let l=t?or(eq(u.workspace_id,t),isNull(u.workspace_id)):void 0,a=i.db.select().from(u).where(l).orderBy(desc(u.updated_at)).all();for(let _ of a)s.has(_.id)||(s.add(_.id),n.push(_));}catch(l){throw new c("DB_ERROR","Failed to find all threads",l)}finally{i.close();}}return n}findThreadById(t,e){let s=this.resolveDbPaths();for(let n of s){if(!existsSync(n))continue;let r=b(n);try{let i=eq(u.id,t),l=e?and(i,or(eq(u.workspace_id,e),isNull(u.workspace_id))):i,a=r.db.select().from(u).where(l).limit(1).get()??void 0;if(a)return a}catch(i){throw new c("DB_ERROR","Failed to find thread by id",i)}finally{r.close();}}}threadExists(t,e){let s=this.resolveDbPaths();for(let n of s){if(!existsSync(n))continue;let r=b(n);try{let i=eq(u.id,t),l=e?and(i,or(eq(u.workspace_id,e),isNull(u.workspace_id))):i;if(r.db.select({id:u.id}).from(u).where(l).limit(1).get())return !0}catch(i){throw new c("DB_ERROR","Failed to check thread existence",i)}finally{r.close();}}return false}aggregateTaskStats(t,e){let s=this.resolveDbPaths(),n=0,r=0,i=0,l=0,a=0,_=new Set;for(let p of s){if(!existsSync(p))continue;let k=b(p);try{let A=and(eq(o.thread_id,t),or(isNull(o.parent_task_id),eq(o.parent_task_id,""))),P=e?and(A,eq(o.workspace_id,e)):A,B=k.db.select({cnt:sql`count(*)`,total_input:sql`COALESCE(SUM(input_tokens), 0)`,total_output:sql`COALESCE(SUM(output_tokens), 0)`,total_cached:sql`COALESCE(SUM(cached_input_tokens), 0)`,total_cost:sql`COALESCE(SUM(cost_usd), 0)`}).from(o).where(P).get();B&&(n+=B.cnt,r+=B.total_input,i+=B.total_output,l+=B.total_cached,a+=B.total_cost);let yt=k.db.all(sql`
|
|
101
101
|
SELECT DISTINCT agent_id FROM tasks
|
|
102
102
|
WHERE thread_id = ${t}
|
|
103
103
|
AND agent_id IS NOT NULL AND agent_id != ''
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import*as
|
|
1
|
+
import*as at from'path';import at__default,{join,dirname,basename}from'path';import {fileURLToPath}from'url';import {existsSync,mkdirSync}from'fs';import Yt from'os';import {sql,and,eq,ne,isNull,desc,isNotNull,or,like,asc,inArray,gte,lt as lt$1}from'drizzle-orm';import {sqliteTable,text,integer,real,index,unique}from'drizzle-orm/sqlite-core';import {randomUUID,createHash}from'crypto';var it=(d=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(d,{get:(t,e)=>(typeof require<"u"?require:t)[e]}):d)(function(d){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+d+'" is not supported')});var Mt=()=>fileURLToPath(import.meta.url),$t=()=>at__default.dirname(Mt()),k=$t();var R=class{resolveDbPath(){return process.env.CREWX_DB?process.env.CREWX_DB:process.env.CREWX_TRACES_DB?process.env.CREWX_TRACES_DB:join(Yt.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())}};var i=class extends Error{code;cause;constructor(t,e,n){super(e),this.name="RepositoryError",this.code=t,this.cause=n,Object.setPrototypeOf(this,new.target.prototype);}};function m(d){let t=it("better-sqlite3"),{drizzle:e}=it("drizzle-orm/better-sqlite3"),n=new t(d);return n.exec("PRAGMA journal_mode = WAL"),n.exec("PRAGMA busy_timeout = 5000"),n.exec("PRAGMA foreign_keys = ON"),{db:e(n),runRaw:(o,s=[])=>n.prepare(o).run(...s),close:()=>n.close()}}var yt=new Set;function V(d){let{migrate:t}=it("drizzle-orm/better-sqlite3/migrator"),e=[at__default.join(k,"../migrations"),at__default.join(k,"migrations")],n=e.find(o=>existsSync(at__default.join(o,"meta/_journal.json")));if(!n)throw new Error(`migrations folder not found. Searched:
|
|
2
2
|
${e.join(`
|
|
3
|
-
`)}`);t(
|
|
3
|
+
`)}`);t(d,{migrationsFolder:n});}function S(d,t){yt.has(t)||(V(d),yt.add(t));}var u=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 r=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"),workspace_name:text("workspace_name"),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_name:text("project_name"),project_ref:text("project_ref"),cached_input_tokens:integer("cached_input_tokens").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(()=>u.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)},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)}));var H=sqliteTable("spans",{id:text("id").primaryKey(),task_id:text("task_id").references(()=>r.id,{onDelete:"set null"}),parent_span_id:text("parent_span_id").references(()=>H.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)}));var L=sqliteTable("tool_calls",{id:text("id").primaryKey(),task_id:text("task_id").notNull().references(()=>r.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)}));var P=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)}));var Z=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)}));function lt(d){let t=at.resolve(d);return process.platform==="win32"&&(t=t.replace(/\\/g,"/"),t=t.replace(/^([A-Z]):/,(e,n)=>`${n.toLowerCase()}:`)),t.length>1&&!/^[a-zA-Z]:\/$/.test(t)&&(t=t.replace(/\/+$/,"")),t}function Ot(d){let t=lt(d);return createHash("sha256").update(t).digest("hex")}function tt(d){return d.toLowerCase().replace(/[^a-z0-9-]/g,"-").replace(/-{2,}/g,"-").replace(/^-+|-+$/g,"")}var pt=class extends R{dbRoot;constructor(t={}){super(),this.dbRoot=t.dbRoot;}resolveDbPath(){return this.dbRoot?join(this.dbRoot,".crewx","crewx.db"):super.resolveDbPath()}openHandle(t){let e=this.resolveDbPath();if(t){let o=dirname(e);existsSync(o)||mkdirSync(o,{recursive:true});}else if(!existsSync(e))throw new i("NOT_FOUND","Database not found");let n=m(e);if(t)try{V(n.db);}catch(o){throw n.close(),o}return n}resolveSlug(t,e,n){let o=tt(basename(n)),a=`${tt(basename(dirname(n)))}-${o}`,l=[o,a];try{let c=_=>t.select({id:u.id}).from(u).where(and(eq(u.slug,_),ne(u.id,e))).limit(1).all().length>0;for(let _ of l)if(!c(_))return _;for(let _=2;_<1e3;_+=1){let h=`${a}-${_}`;if(!c(h))return h}}catch{}return o}normalizeLegacySlugs(){if(!this.dbExists())return {updated:0,checked:0};let t=this.openHandle(true);try{let e=t.db.select({id:u.id,slug:u.slug}).from(u).all(),n=0;for(let o of e)if(o.slug.includes("/")){let s=tt(o.slug.replace(/\//g,"-"));t.db.update(u).set({slug:s,updated_at:new Date().toISOString()}).where(eq(u.id,o.id)).run(),n+=1;}return {updated:n,checked:e.length}}catch(e){throw new i("DB_ERROR","Failed to normalize legacy slugs",e)}finally{t.close();}}ensureRow(t,e){let{id:n,slug:o,name:s,workspacePath:a}=e,l=new Date().toISOString();t.insert(u).values({id:n,slug:o,name:s,workspace_path:a,is_active:1,created_at:l,updated_at:l}).onConflictDoNothing().run(),t.update(u).set({workspace_path:a,updated_at:l}).where(and(eq(u.id,n),isNull(u.workspace_path))).run();}registerWorkspace(t){let e=lt(t),n=this.openHandle(true);try{let o=Ot(e),s=basename(e),a=this.resolveSlug(n.db,o,e);return this.ensureRow(n.db,{id:o,slug:a,name:s,workspacePath:e}),{id:o,slug:a}}catch(o){throw o instanceof i?o:new i("DB_ERROR","Failed to register workspace",o)}finally{n.close();}}listProjects(t){if(!this.dbExists())return {rows:[],total:0};let e=this.openHandle(false);try{let n=t.isActive!==void 0?eq(u.is_active,t.isActive?1:0):void 0,o=e.db.select({count:sql`count(*)`}).from(u).where(n).get();return {rows:e.db.select().from(u).where(n).orderBy(desc(u.updated_at)).limit(t.limit).offset(t.offset).all(),total:o?.count??0}}catch(n){throw new i("DB_ERROR","Failed to list projects",n)}finally{e.close();}}findById(t){if(!this.dbExists())return;let e=this.openHandle(false);try{return e.db.select().from(u).where(eq(u.id,t)).limit(1).get()??void 0}catch(n){throw new i("DB_ERROR","Failed to find workspace",n)}finally{e.close();}}findAgentsByProject(t){if(!this.dbExists())return [];let e=this.openHandle(false);try{return e.db.all(sql`SELECT DISTINCT agent_id FROM tasks WHERE workspace_id = ${t} AND agent_id IS NOT NULL ORDER BY agent_id`).map(o=>o.agent_id)}catch(n){throw new i("DB_ERROR","Failed to find agents by project",n)}finally{e.close();}}findThreadsByProject(t,e){if(!this.dbExists())return {rows:[],total:0};let n=this.openHandle(false);try{let o=n.db.get(sql`SELECT COUNT(*) as count FROM threads WHERE workspace_id = ${t}`);return {rows:n.db.all(sql`SELECT t.*,
|
|
4
4
|
(SELECT agent_id FROM tasks tk WHERE tk.thread_id = t.id AND tk.agent_id IS NOT NULL ORDER BY tk.started_at ASC LIMIT 1) AS agent_id
|
|
5
5
|
FROM threads t
|
|
6
6
|
WHERE t.workspace_id = ${t}
|
|
7
7
|
ORDER BY t.updated_at DESC
|
|
8
|
-
LIMIT ${e.limit} OFFSET ${e.offset}`),total:o?.count??0}}catch(o){throw new i("DB_ERROR","Failed to find threads by project",o)}finally{n.close();}}findBySlug(t){if(!this.dbExists())return;let e=this.openHandle(false);try{return e.db.select().from(
|
|
8
|
+
LIMIT ${e.limit} OFFSET ${e.offset}`),total:o?.count??0}}catch(o){throw new i("DB_ERROR","Failed to find threads by project",o)}finally{n.close();}}findBySlug(t){if(!this.dbExists())return;let e=this.openHandle(false);try{return e.db.select().from(u).where(eq(u.slug,t)).limit(1).get()??void 0}catch(n){throw new i("DB_ERROR","Failed to find workspace by slug",n)}finally{e.close();}}slugExists(t,e){if(!this.dbExists())return false;let n=this.openHandle(false);try{let o=e?and(eq(u.slug,t),ne(u.id,e)):eq(u.slug,t);return !!n.db.select({id:u.id}).from(u).where(o).limit(1).get()}catch(o){throw new i("DB_ERROR","Failed to check slug",o)}finally{n.close();}}insert(t,e,n,o){let s=this.openHandle(true);try{let a=new Date().toISOString();s.db.insert(u).values({id:t,slug:e,name:n,workspace_path:o,is_active:1,created_at:a,updated_at:a}).run();let l=s.db.select().from(u).where(eq(u.id,t)).limit(1).get();if(!l)throw new i("DB_ERROR","Insert did not return a row");return l}catch(a){throw a instanceof i?a:new i("DB_ERROR","Failed to insert workspace",a)}finally{s.close();}}update(t,e,n){let o=this.openHandle(true);try{o.runRaw(`UPDATE workspaces SET ${e.join(", ")} WHERE id = ?`,n);let s=o.db.select().from(u).where(eq(u.id,t)).limit(1).get();if(!s)throw new i("NOT_FOUND",`Workspace ${t} not found`);return s}catch(s){throw s instanceof i?s:new i("DB_ERROR","Failed to update workspace",s)}finally{o.close();}}cleanupOrphanWorkspaces(){if(!this.dbExists())return {softDeleted:0,checked:0};let t=this.openHandle(true);try{let e=t.db.select({id:u.id,workspace_path:u.workspace_path}).from(u).where(and(eq(u.is_active,1),isNotNull(u.workspace_path))).all(),n=0;for(let o of e){let s=o.workspace_path;existsSync(join(s,"crewx.yaml"))||existsSync(join(s,"crewx.yml"))||(t.db.update(u).set({is_active:0,updated_at:new Date().toISOString()}).where(eq(u.id,o.id)).run(),n+=1);}return {softDeleted:n,checked:e.length}}catch(e){throw new i("DB_ERROR","Failed to cleanup orphan workspaces",e)}finally{t.close();}}delete(t){let e=this.openHandle(true);try{e.db.run(sql`UPDATE threads SET workspace_id = NULL WHERE workspace_id = ${t}`),e.db.delete(u).where(eq(u.id,t)).run();}catch(n){throw n instanceof i?n:new i("DB_ERROR","Failed to delete workspace",n)}finally{e.close();}}};var ft=class extends R{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 e=this.resolveDbPath();if(t){let o=dirname(e);existsSync(o)||mkdirSync(o,{recursive:true});}else if(!existsSync(e))throw new i("NOT_FOUND","Database not found");let n=m(e);if(t)try{S(n.db,e);}catch(o){throw n.close(),o}return n}startTask(t){let e=this.openHandle(true);try{e.db.insert(r).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,workspace_name:t.workspaceName??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}).onConflictDoNothing().run();}catch(n){throw n instanceof i?n:new i("DB_ERROR","Failed to start task",n)}finally{e.close();}}finishTask(t){let e=this.openHandle(true);try{e.runRaw(`UPDATE tasks SET status=?, result=?, error=?, completed_at=?, duration_ms=?,
|
|
9
9
|
exit_code=?, input_tokens=?, output_tokens=?, cached_input_tokens=?, cost_usd=?,
|
|
10
|
-
model=COALESCE(?, model) WHERE id=?`,[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]);}catch(n){throw n instanceof i?n:new i("DB_ERROR","Failed to finish task",n)}finally{e.close();}}appendLog(t,e){let n=this.openHandle(true);try{n.db.transaction(o=>{let s=o.select({logs:r.logs}).from(r).where(eq(r.id,t)).limit(1).get(),a=s?.logs?JSON.parse(s.logs):[];a.push(e),o.update(r).set({logs:JSON.stringify(a)}).where(eq(r.id,t)).run();},{behavior:"immediate"});}catch(o){throw o instanceof i?o:new i("DB_ERROR","Failed to append log",o)}finally{n.close();}}getRunningTasks(){if(!this.dbExists())return [];let t=this.openHandle(false);try{return t.db.select().from(r).where(eq(r.status,"running")).orderBy(desc(r.started_at)).all()}catch(e){throw new i("DB_ERROR","Failed to get running tasks",e)}finally{t.close();}}getAllTasks(){if(!this.dbExists())return [];let t=this.openHandle(false);try{return t.db.select().from(r).orderBy(desc(r.started_at)).limit(100).all()}catch(e){throw new i("DB_ERROR","Failed to get all tasks",e)}finally{t.close();}}getTask(t){if(!this.dbExists())return;let e=this.openHandle(false);try{return e.db.select().from(r).where(eq(r.id,t)).limit(1).get()??void 0}catch(n){throw new i("DB_ERROR","Failed to get task",n)}finally{e.close();}}killTask(t){if(!this.dbExists())return {killed:false};let e=this.openHandle(true);try{let n=e.db.select({id:r.id,status:r.status,pid:r.pid}).from(r).where(eq(r.id,t)).limit(1).get();if(!n||n.status!=="running")return {killed:!1};if(n.pid)try{process.kill(n.pid,"SIGTERM");}catch{}return e.db.update(r).set({status:"failed",error:"Killed by user",completed_at:new Date().toISOString()}).where(and(eq(r.id,t),eq(r.status,"running"))).run(),{killed:!0,pid:n.pid??void 0}}catch(n){throw n instanceof i?n:new i("DB_ERROR","Failed to kill task",n)}finally{e.close();}}findTaskStatus(t,e){let n=this.resolveDbPaths();for(let o of n){if(!existsSync(o))continue;let s=m(o);try{let a=e?eq(r.workspace_id,e):void 0,
|
|
10
|
+
model=COALESCE(?, model) WHERE id=?`,[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]);}catch(n){throw n instanceof i?n:new i("DB_ERROR","Failed to finish task",n)}finally{e.close();}}appendLog(t,e){let n=this.openHandle(true);try{n.db.transaction(o=>{let s=o.select({logs:r.logs}).from(r).where(eq(r.id,t)).limit(1).get(),a=s?.logs?JSON.parse(s.logs):[];a.push(e),o.update(r).set({logs:JSON.stringify(a)}).where(eq(r.id,t)).run();},{behavior:"immediate"});}catch(o){throw o instanceof i?o:new i("DB_ERROR","Failed to append log",o)}finally{n.close();}}getRunningTasks(){if(!this.dbExists())return [];let t=this.openHandle(false);try{return t.db.select().from(r).where(eq(r.status,"running")).orderBy(desc(r.started_at)).all()}catch(e){throw new i("DB_ERROR","Failed to get running tasks",e)}finally{t.close();}}getAllTasks(){if(!this.dbExists())return [];let t=this.openHandle(false);try{return t.db.select().from(r).orderBy(desc(r.started_at)).limit(100).all()}catch(e){throw new i("DB_ERROR","Failed to get all tasks",e)}finally{t.close();}}getTask(t){if(!this.dbExists())return;let e=this.openHandle(false);try{return e.db.select().from(r).where(eq(r.id,t)).limit(1).get()??void 0}catch(n){throw new i("DB_ERROR","Failed to get task",n)}finally{e.close();}}killTask(t){if(!this.dbExists())return {killed:false};let e=this.openHandle(true);try{let n=e.db.select({id:r.id,status:r.status,pid:r.pid}).from(r).where(eq(r.id,t)).limit(1).get();if(!n||n.status!=="running")return {killed:!1};if(n.pid)try{process.kill(n.pid,"SIGTERM");}catch{}return e.db.update(r).set({status:"failed",error:"Killed by user",completed_at:new Date().toISOString()}).where(and(eq(r.id,t),eq(r.status,"running"))).run(),{killed:!0,pid:n.pid??void 0}}catch(n){throw n instanceof i?n:new i("DB_ERROR","Failed to kill task",n)}finally{e.close();}}findTaskStatus(t,e){let n=this.resolveDbPaths();for(let o of n){if(!existsSync(o))continue;let s=m(o);try{let a=e?eq(r.workspace_id,e):void 0,l=a?and(eq(r.id,t),a):eq(r.id,t),c=s.db.select().from(r).where(l).limit(1).get()??void 0;if(!c){let _=or(eq(r.thread_id,t),and(isNull(r.thread_id),like(r.command,`%--thread=${t}%`))),h=a?and(_,a):_;c=s.db.select().from(r).where(h).orderBy(desc(r.started_at)).limit(1).get()??void 0;}if(c)return c}catch(a){throw new i("DB_ERROR","Failed to find task status",a)}finally{s.close();}}}findChildTasks(t,e){let n=this.resolveDbPaths(),o=new Set,s=[];for(let a of n){if(!existsSync(a))continue;let l=m(a);try{let c=e?and(eq(r.parent_task_id,t),eq(r.workspace_id,e)):eq(r.parent_task_id,t),_=l.db.select().from(r).where(c).orderBy(asc(r.started_at)).all();for(let h of _)o.has(h.id)||(o.add(h.id),s.push(h));}catch(c){throw new i("DB_ERROR","Failed to find child tasks",c)}finally{l.close();}}return s}getWorkspaceUsageSummary(t){if(!this.dbExists())return [];let e=this.openHandle(false);try{return e.db.all(t?sql`
|
|
11
11
|
SELECT
|
|
12
12
|
COALESCE(workspace_id, 'unknown') AS workspace_id,
|
|
13
13
|
COALESCE(workspace_name, 'Unknown Workspace') AS workspace_name,
|
|
@@ -30,7 +30,7 @@ ${e.join(`
|
|
|
30
30
|
FROM tasks
|
|
31
31
|
GROUP BY workspace_id, workspace_name
|
|
32
32
|
ORDER BY (COALESCE(SUM(input_tokens), 0) + COALESCE(SUM(output_tokens), 0)) DESC
|
|
33
|
-
`)}catch(n){throw new i("DB_ERROR","Failed to get workspace usage summary",n)}finally{e.close();}}getThreadTokenUsage(t,e){let n=this.resolveDbPaths(),o=new Set,s=0,a=0,
|
|
33
|
+
`)}catch(n){throw new i("DB_ERROR","Failed to get workspace usage summary",n)}finally{e.close();}}getThreadTokenUsage(t,e){let n=this.resolveDbPaths(),o=new Set,s=0,a=0,l=0;for(let c of n){if(!existsSync(c))continue;let _=m(c);try{let h=or(eq(r.thread_id,t),and(isNull(r.thread_id),like(r.command,`%--thread=${t}%`))),b=e?and(h,eq(r.workspace_id,e)):h,j=_.db.select({id:r.id,input_tokens:r.input_tokens,output_tokens:r.output_tokens,cost_usd:r.cost_usd}).from(r).where(b).all();for(let q of j)o.has(q.id)||(o.add(q.id),s+=q.input_tokens??0,a+=q.output_tokens??0,l+=q.cost_usd??0);}catch(h){throw new i("DB_ERROR","Failed to get thread token usage",h)}finally{_.close();}}return {inputTokens:s,outputTokens:a,costUsd:l}}findTasksByThread(t,e){let n=this.resolveDbPaths(),o=new Set,s=[];for(let a of n){if(!existsSync(a))continue;let l=m(a);try{let c=or(eq(r.thread_id,t),and(isNull(r.thread_id),like(r.command,`%--thread=${t}%`))),_=e?and(c,eq(r.workspace_id,e)):c,h=l.db.select().from(r).where(_).orderBy(asc(r.started_at)).all();for(let b of h)o.has(b.id)||(o.add(b.id),s.push(b));}catch(c){throw new i("DB_ERROR","Failed to find tasks by thread",c)}finally{l.close();}}return s}findAllTasks(t){if(!this.dbExists())return {rows:[],total:0};let e=this.openHandle(false);try{let n=[];t.workspaceId&&n.push(eq(r.workspace_id,t.workspaceId));let o=t.agents&&t.agents.length>0?t.agents:t.agentId?[t.agentId]:null;o&&n.push(inArray(r.agent_id,o));let s=t.statuses&&t.statuses.length>0?t.statuses:t.status?[t.status]:null;s&&n.push(inArray(r.status,s));let a=t.q??t.search;a&&n.push(like(r.prompt,`%${a}%`)),t.from&&n.push(gte(r.started_at,t.from)),t.to&&n.push(lt$1(r.started_at,t.to));let l=n.length>0?and(...n):void 0,c=e.db.select({count:sql`count(*)`}).from(r).where(l).get(),_=(t.sortDir??"DESC")==="ASC"?asc(r.started_at):desc(r.started_at);return {rows:e.db.select().from(r).where(l).orderBy(_).limit(t.limit).offset(t.offset).all(),total:c?.count??0}}catch(n){throw new i("DB_ERROR","Failed to find all tasks",n)}finally{e.close();}}getAgentUsage(t,e,n){if(!this.dbExists())return [];let o=this.openHandle(false);try{return o.db.all(n?sql`
|
|
34
34
|
SELECT
|
|
35
35
|
t.agent_id,
|
|
36
36
|
t.workspace_id,
|
|
@@ -92,13 +92,13 @@ ${e.join(`
|
|
|
92
92
|
AND t.started_at < ${e}
|
|
93
93
|
GROUP BY date(t.started_at), t.agent_id
|
|
94
94
|
ORDER BY date(t.started_at) ASC
|
|
95
|
-
`).map(a=>({date:a.date,agentId:a.agent_id,inputTokens:a.input_tokens,outputTokens:a.output_tokens,cachedInputTokens:a.cached_input_tokens,costUsd:a.cost_usd}))}catch(s){throw new i("DB_ERROR","Failed to get agent usage trend",s)}finally{o.close();}}findTaskForStop(t,e){if(!this.dbExists())return;let n=this.openHandle(false);try{return n.db.select().from(r).where(and(eq(r.id,t),eq(r.workspace_id,e))).limit(1).get()??void 0}catch(o){throw new i("DB_ERROR","Failed to find task for stop",o)}finally{n.close();}}markTaskFailed(t,e,n){if(!this.dbExists())return;let o=this.openHandle(true);try{let s=new Date().toISOString(),a=n?and(eq(r.id,t),eq(r.status,"running"),eq(r.workspace_id,n)):and(eq(r.id,t),eq(r.status,"running"));o.db.update(r).set({status:"failed",error:e,completed_at:s}).where(a).run();}catch(s){throw s instanceof i?s:new i("DB_ERROR","Failed to mark task failed",s)}finally{o.close();}}findTasksByPromptHint(t,e){let n=this.resolveDbPaths(),o=new Set,s=[];for(let a of n){if(!existsSync(a))continue;let
|
|
95
|
+
`).map(a=>({date:a.date,agentId:a.agent_id,inputTokens:a.input_tokens,outputTokens:a.output_tokens,cachedInputTokens:a.cached_input_tokens,costUsd:a.cost_usd}))}catch(s){throw new i("DB_ERROR","Failed to get agent usage trend",s)}finally{o.close();}}findTaskForStop(t,e){if(!this.dbExists())return;let n=this.openHandle(false);try{return n.db.select().from(r).where(and(eq(r.id,t),eq(r.workspace_id,e))).limit(1).get()??void 0}catch(o){throw new i("DB_ERROR","Failed to find task for stop",o)}finally{n.close();}}markTaskFailed(t,e,n){if(!this.dbExists())return;let o=this.openHandle(true);try{let s=new Date().toISOString(),a=n?and(eq(r.id,t),eq(r.status,"running"),eq(r.workspace_id,n)):and(eq(r.id,t),eq(r.status,"running"));o.db.update(r).set({status:"failed",error:e,completed_at:s}).where(a).run();}catch(s){throw s instanceof i?s:new i("DB_ERROR","Failed to mark task failed",s)}finally{o.close();}}findTasksByPromptHint(t,e){let n=this.resolveDbPaths(),o=new Set,s=[];for(let a of n){if(!existsSync(a))continue;let l=m(a);try{let c=e?and(like(r.prompt,`%${t}%`),eq(r.workspace_id,e)):like(r.prompt,`%${t}%`),_=l.db.select().from(r).where(c).orderBy(asc(r.started_at)).all();for(let h of _)o.has(h.id)||(o.add(h.id),s.push(h));}catch(c){throw new i("DB_ERROR","Failed to find tasks by prompt hint",c)}finally{l.close();}}return s}};var mt=class extends R{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 e=this.resolveDbPath();if(t){let o=dirname(e);existsSync(o)||mkdirSync(o,{recursive:true});}else if(!existsSync(e))throw new i("NOT_FOUND","Database not found");let n=m(e);if(t)try{S(n.db,e);}catch(o){throw n.close(),o}return n}validateWorkspaceId(t,e){return t.db.select({id:u.id}).from(u).where(eq(u.id,e)).limit(1).get()?e:null}findAllThreads(t){let e=this.resolveDbPaths(),n=new Set,o=[];for(let s of e){if(!existsSync(s))continue;let a=m(s);try{let l=t?or(eq(p.workspace_id,t),isNull(p.workspace_id)):void 0,c=a.db.select().from(p).where(l).orderBy(desc(p.updated_at)).all();for(let _ of c)n.has(_.id)||(n.add(_.id),o.push(_));}catch(l){throw new i("DB_ERROR","Failed to find all threads",l)}finally{a.close();}}return o}findThreadById(t,e){let n=this.resolveDbPaths();for(let o of n){if(!existsSync(o))continue;let s=m(o);try{let a=eq(p.id,t),l=e?and(a,or(eq(p.workspace_id,e),isNull(p.workspace_id))):a,c=s.db.select().from(p).where(l).limit(1).get()??void 0;if(c)return c}catch(a){throw new i("DB_ERROR","Failed to find thread by id",a)}finally{s.close();}}}threadExists(t,e){let n=this.resolveDbPaths();for(let o of n){if(!existsSync(o))continue;let s=m(o);try{let a=eq(p.id,t),l=e?and(a,or(eq(p.workspace_id,e),isNull(p.workspace_id))):a;if(s.db.select({id:p.id}).from(p).where(l).limit(1).get())return !0}catch(a){throw new i("DB_ERROR","Failed to check thread existence",a)}finally{s.close();}}return false}aggregateTaskStats(t,e){let n=this.resolveDbPaths(),o=0,s=0,a=0,l=0,c=0,_=new Set;for(let h of n){if(!existsSync(h))continue;let b=m(h);try{let j=and(eq(r.thread_id,t),or(isNull(r.parent_task_id),eq(r.parent_task_id,""))),q=e?and(j,eq(r.workspace_id,e)):j,W=b.db.select({cnt:sql`count(*)`,total_input:sql`COALESCE(SUM(input_tokens), 0)`,total_output:sql`COALESCE(SUM(output_tokens), 0)`,total_cached:sql`COALESCE(SUM(cached_input_tokens), 0)`,total_cost:sql`COALESCE(SUM(cost_usd), 0)`}).from(r).where(q).get();W&&(o+=W.cnt,s+=W.total_input,a+=W.total_output,l+=W.total_cached,c+=W.total_cost);let Ht=b.db.all(sql`
|
|
96
96
|
SELECT DISTINCT agent_id FROM tasks
|
|
97
97
|
WHERE thread_id = ${t}
|
|
98
98
|
AND agent_id IS NOT NULL AND agent_id != ''
|
|
99
99
|
AND (parent_task_id IS NULL OR parent_task_id = '')
|
|
100
100
|
${e?sql`AND workspace_id = ${e}`:sql``}
|
|
101
|
-
`);for(let
|
|
101
|
+
`);for(let Ut of Ht)_.add(Ut.agent_id);}catch(j){throw new i("DB_ERROR","Failed to aggregate task stats",j)}finally{b.close();}}return {taskCount:o,inputTokens:s,outputTokens:a,cachedInputTokens:l,costUsd:c,agentIds:Array.from(_)}}findTopLevelTasks(t,e){let n=this.resolveDbPaths(),o=new Set,s=[];for(let a of n){if(!existsSync(a))continue;let l=m(a);try{let c=and(eq(r.thread_id,t),or(isNull(r.parent_task_id),eq(r.parent_task_id,""))),_=e?and(c,eq(r.workspace_id,e)):c,h=l.db.select().from(r).where(_).orderBy(asc(r.started_at)).all();for(let b of h)o.has(b.id)||(o.add(b.id),s.push(b));}catch(c){throw new i("DB_ERROR","Failed to find top-level tasks",c)}finally{l.close();}}return s}findAllTasks(t,e){let n=this.resolveDbPaths(),o=new Set,s=[];for(let a of n){if(!existsSync(a))continue;let l=m(a);try{let c=eq(r.thread_id,t),_=e?and(c,eq(r.workspace_id,e)):c,h=l.db.select().from(r).where(_).orderBy(asc(r.started_at)).all();for(let b of h)o.has(b.id)||(o.add(b.id),s.push(b));}catch(c){throw new i("DB_ERROR","Failed to find all tasks for thread",c)}finally{l.close();}}return s}findTaskById(t,e,n){let o=this.resolveDbPaths();for(let s of o){if(!existsSync(s))continue;let a=m(s);try{let l=and(eq(r.id,e),eq(r.thread_id,t)),c=n?and(l,eq(r.workspace_id,n)):l,_=a.db.select().from(r).where(c).limit(1).get();if(!_)continue;let h=a.db.select().from(r).where(eq(r.parent_task_id,_.id)).orderBy(asc(r.started_at)).all();return {task:_,children:h}}catch(l){throw new i("DB_ERROR","Failed to find task by id",l)}finally{a.close();}}}batchFetchTasks(t,e){let n=new Map;if(t.length===0)return n;let o=this.resolveDbPaths();for(let s of o){if(!existsSync(s))continue;let a=m(s);try{let l=and(inArray(r.thread_id,t),or(isNull(r.parent_task_id),eq(r.parent_task_id,""))),c=e?and(l,eq(r.workspace_id,e)):l,_=a.db.select().from(r).where(c).orderBy(asc(r.started_at)).all();for(let h of _){let b=h.thread_id;n.has(b)||n.set(b,[]),n.get(b).push(h);}}catch(l){throw new i("DB_ERROR","Failed to batch fetch tasks",l)}finally{a.close();}}return n}updateThreadTitle(t,e,n){if(!this.dbExists())return;let o=this.openHandle(true);try{let s=eq(p.id,t),a=n?and(s,or(eq(p.workspace_id,n),isNull(p.workspace_id))):s;if(!o.db.select({id:p.id}).from(p).where(a).limit(1).get())return;o.db.update(p).set({title:e,title_locked:1,updated_at:new Date().toISOString()}).where(eq(p.id,t)).run();}catch(s){throw s instanceof i?s:new i("DB_ERROR","Failed to update thread title",s)}finally{o.close();}}upsertThread(t,e){let n=this.openHandle(true);try{let o=e.workspaceId?this.validateWorkspaceId(n,e.workspaceId):null,s=new Date().toISOString();if(n.db.select({id:p.id,message_count:p.message_count}).from(p).where(eq(p.id,t)).limit(1).get()){let l={updated_at:s};e.title!==void 0&&(l.title=e.title),e.titleLocked!==void 0&&(l.title_locked=e.titleLocked?1:0),n.db.update(p).set(l).where(eq(p.id,t)).run();}else n.db.insert(p).values({id:t,platform:e.platform,workspace_id:o,title:e.title??null,title_locked:e.titleLocked?1:0,message_count:0,created_at:s,updated_at:s}).run();}catch(o){throw o instanceof i?o:new i("DB_ERROR","Failed to upsert thread",o)}finally{n.close();}}ensureThread(t,e,n){let o=this.openHandle(true);try{let s=n?this.validateWorkspaceId(o,n):null,a=o.db.select({id:p.id,platform:p.platform,workspace_id:p.workspace_id}).from(p).where(eq(p.id,t)).limit(1).get();if(a){s&&!a.workspace_id&&o.db.update(p).set({workspace_id:s}).where(eq(p.id,t)).run();return}let l=new Date().toISOString();o.db.insert(p).values({id:t,platform:e,workspace_id:s,message_count:0,created_at:l,updated_at:l}).run();}catch(s){throw s instanceof i?s:new i("DB_ERROR","Failed to ensure thread",s)}finally{o.close();}}saveUserMessage(t,e,n){if(!this.dbExists())return;let o=this.openHandle(true);try{let s=new Date().toISOString();o.db.run(sql`
|
|
102
102
|
UPDATE threads
|
|
103
103
|
SET first_message = COALESCE(first_message, ${e}),
|
|
104
104
|
title = CASE WHEN title_locked = 0 AND title IS NULL THEN substr(${e}, 1, 60) ELSE title END,
|
|
@@ -106,4 +106,4 @@ ${e.join(`
|
|
|
106
106
|
message_count = message_count + 1,
|
|
107
107
|
updated_at = ${s}
|
|
108
108
|
WHERE id = ${t}
|
|
109
|
-
`);}catch(s){throw s instanceof i?s:new i("DB_ERROR","Failed to save user message",s)}finally{o.close();}}saveAssistantMessage(t,e,n){if(!this.dbExists())return;let o=this.openHandle(true);try{let s=new Date().toISOString();o.db.update(
|
|
109
|
+
`);}catch(s){throw s instanceof i?s:new i("DB_ERROR","Failed to save user message",s)}finally{o.close();}}saveAssistantMessage(t,e,n){if(!this.dbExists())return;let o=this.openHandle(true);try{let s=new Date().toISOString();o.db.update(p).set({last_message:e,updated_at:s}).where(eq(p.id,t)).run();}catch(s){throw s instanceof i?s:new i("DB_ERROR","Failed to save assistant message",s)}finally{o.close();}}updateThread(t,e){if(!this.dbExists())return;let n=this.openHandle(true);try{let o={updated_at:new Date().toISOString()};e.title!==void 0&&(o.title=e.title,o.title_locked=1),e.titleLocked!==void 0&&(o.title_locked=e.titleLocked?1:0),n.db.update(p).set(o).where(eq(p.id,t)).run();}catch(o){throw o instanceof i?o:new i("DB_ERROR","Failed to update thread",o)}finally{n.close();}}};var wt=class extends R{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 e=this.resolveDbPath();if(t){let o=dirname(e);existsSync(o)||mkdirSync(o,{recursive:true});}else if(!existsSync(e))throw new i("NOT_FOUND","Database not found");let n=m(e);if(t)try{S(n.db,e);}catch(o){throw n.close(),o}return n}insertSpan(t){let e=this.openHandle(true);try{e.db.insert(H).values(t).run();}catch(n){throw n instanceof i?n:new i("DB_ERROR","Failed to insert span",n)}finally{e.close();}}findByTaskId(t){if(!this.dbExists())return [];let e=this.openHandle(false);try{return e.db.select().from(H).where(eq(H.task_id,t)).all()}catch(n){throw new i("DB_ERROR","Failed to find spans by task id",n)}finally{e.close();}}findById(t){if(!this.dbExists())return;let e=this.openHandle(false);try{return e.db.select().from(H).where(eq(H.id,t)).limit(1).get()??void 0}catch(n){throw new i("DB_ERROR","Failed to find span by id",n)}finally{e.close();}}};var gt=class extends R{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 e=this.resolveDbPath();if(t){let o=dirname(e);existsSync(o)||mkdirSync(o,{recursive:true});}else if(!existsSync(e))throw new i("NOT_FOUND","Database not found");let n=m(e);if(t)try{S(n.db,e);}catch(o){throw n.close(),o}return n}insertToolCall(t){let e=this.openHandle(true);try{e.db.insert(L).values(t).run();}catch(n){throw n instanceof i?n:new i("DB_ERROR","Failed to insert tool call",n)}finally{e.close();}}findByTaskId(t){if(!this.dbExists())return [];let e=this.openHandle(false);try{return e.db.select().from(L).where(eq(L.task_id,t)).all()}catch(n){throw new i("DB_ERROR","Failed to find tool calls by task id",n)}finally{e.close();}}aggregateByName(t){if(!this.dbExists())return [];let e=this.openHandle(false);try{return e.db.select({toolName:L.tool_name,count:sql`count(*)`}).from(L).where(eq(L.task_id,t)).groupBy(L.tool_name).all().map(n=>({toolName:n.toolName,count:n.count}))}catch(n){throw new i("DB_ERROR","Failed to aggregate tool calls by name",n)}finally{e.close();}}};var kt=class extends R{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 e=this.resolveDbPath();if(t){let o=dirname(e);existsSync(o)||mkdirSync(o,{recursive:true});}else if(!existsSync(e))throw new i("NOT_FOUND","Database not found");let n=m(e);if(t)try{S(n.db,e);}catch(o){throw n.close(),o}return n}ensureThreadExists(t,e){if(!t.db.select({id:p.id}).from(p).where(eq(p.id,e)).limit(1).get())throw new i("NOT_FOUND",`Thread not found: ${e}`)}findByThreadId(t){if(!this.dbExists())return [];let e=this.openHandle(false);try{return this.ensureThreadExists(e,t),e.db.select().from(P).where(eq(P.thread_id,t)).orderBy(asc(P.seq)).all()}catch(n){throw n instanceof i?n:new i("DB_ERROR","Failed to find boxes by thread id",n)}finally{e.close();}}findById(t,e){if(!this.dbExists())return;let n=this.openHandle(false);try{return n.db.select().from(P).where(and(eq(P.id,e),eq(P.thread_id,t))).limit(1).get()??void 0}catch(o){throw o instanceof i?o:new i("DB_ERROR","Failed to find box by id",o)}finally{n.close();}}insert(t){let e=this.openHandle(true);try{this.ensureThreadExists(e,t.threadId);try{e.db.insert(P).values({id:t.id,thread_id:t.threadId,seq:t.seq,first_task_id:t.first_task_id,mid_task_id:t.mid_task_id,last_task_id:t.last_task_id,task_count:t.task_count,summary:t.summary??null,source_tokens:t.source_tokens,summary_tokens:t.summary_tokens??null,created_at:t.created_at}).run();}catch(o){throw o instanceof Error&&/UNIQUE constraint failed/i.test(o.message)?new i("CONFLICT",`Duplicate seq ${String(t.seq)} for thread ${t.threadId}`,o):o}let n=e.db.select().from(P).where(eq(P.id,t.id)).limit(1).get();if(!n)throw new i("DB_ERROR","Insert did not return a row");return n}catch(n){throw n instanceof i?n:new i("DB_ERROR","Failed to insert thread box",n)}finally{e.close();}}};var bt=class extends R{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 e=this.resolveDbPath();if(t){let o=dirname(e);existsSync(o)||mkdirSync(o,{recursive:true});}else if(!existsSync(e))throw new i("NOT_FOUND","Database not found");let n=m(e);if(t)try{S(n.db,e);}catch(o){throw n.close(),o}return n}bulkInsert(t){if(t.length===0)return;let e=this.openHandle(true);try{let n=new Date().toISOString();e.db.transaction(o=>{for(let s of t)o.insert(Z).values({id:randomUUID(),path:s.path,method:s.method,status_code:s.statusCode,duration_ms:s.durationMs,ip:s.ip??null,request_headers:s.requestHeaders??null,response_headers:s.responseHeaders??null,request_body:s.requestBody??null,response_body:s.responseBody??null,query:s.query??null,user_id:s.userId??null,project_id:s.projectId??null,partition_key:s.partitionKey??"default",timestamp:n,metadata:s.metadata??null}).run();});}catch(n){throw n instanceof i?n:new i("DB_ERROR","Failed to bulk insert request logs",n)}finally{e.close();}}findRecent(t=100){if(!this.dbExists())return [];let e=this.openHandle(false);try{return e.db.select().from(Z).orderBy(desc(Z.timestamp)).limit(t).all()}catch(n){throw new i("DB_ERROR","Failed to find recent request logs",n)}finally{e.close();}}};export{R as BaseSqliteRepository,i as RepositoryError,bt as RequestLogRepository,wt as SpanRepository,ft as TaskRepository,kt as ThreadBoxRepository,mt as ThreadRepository,gt as ToolCallRepository,pt as WorkspaceRepository,m as openDrizzleDb,V as runMigrations,S as runMigrationsOnce};
|