@crewx/sdk 0.9.0-rc.7 → 0.9.0-rc.71
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/README.md +1 -1
- package/dist/activity-log/builder.d.ts +55 -6
- package/dist/config/canonicalize-agent-options.d.ts +17 -0
- package/dist/config/global-settings.d.ts +33 -0
- package/dist/config/migrate-grok-mode.d.ts +6 -0
- package/dist/config/model-compat.d.ts +31 -0
- package/dist/config/models.generated.d.ts +33 -0
- package/dist/config/models.remote.d.ts +1 -0
- package/dist/config/overdrive.d.ts +7 -0
- package/dist/config/pricing.d.ts +8 -5
- package/dist/config/pricing.generated.d.ts +4 -0
- package/dist/config/pricing.types.d.ts +4 -10
- package/dist/config/timeout.config.d.ts +3 -0
- package/dist/config/wi-boards.d.ts +19 -0
- package/dist/context-budget/index.d.ts +105 -0
- package/dist/conversation/index.d.ts +1 -1
- package/dist/conversation/to-template-messages.d.ts +7 -0
- package/dist/conversation/types.d.ts +1 -0
- package/dist/desktop/command-runner.d.ts +4 -0
- package/dist/desktop/default-adapters.d.ts +4 -0
- package/dist/desktop/global-install.d.ts +19 -0
- package/dist/desktop/index.d.ts +2 -0
- package/dist/desktop/index.js +3 -0
- package/dist/desktop/install.d.ts +5 -0
- package/dist/desktop/lnk.d.ts +22 -0
- package/dist/desktop/manifest.d.ts +21 -0
- package/dist/desktop/types.d.ts +67 -0
- package/dist/desktop/version.d.ts +1 -0
- package/dist/desktop/windows-paths.d.ts +21 -0
- package/dist/desktop/wrapper.d.ts +18 -0
- package/dist/esm/desktop/index.js +3 -0
- package/dist/esm/index.js +271 -102
- package/dist/esm/plugins/index.js +166 -75
- package/dist/esm/publish/index.js +1 -0
- package/dist/esm/repository/index.js +184 -78
- package/dist/esm/testing/index.js +1 -1
- package/dist/events/types.d.ts +4 -0
- package/dist/facade/Crewx.d.ts +30 -0
- package/dist/index.browser.d.ts +7 -1
- package/dist/index.browser.js +6 -2
- package/dist/index.d.ts +36 -8
- package/dist/index.js +271 -102
- package/dist/internal/windows-spawn.d.ts +10 -0
- package/dist/local-server/base-url.d.ts +18 -0
- package/dist/local-server/index.d.ts +8 -0
- package/dist/local-server/opencode.d.ts +8 -0
- package/dist/local-server/probe.d.ts +3 -0
- package/dist/local-server/runtime.d.ts +26 -0
- package/dist/local-server/types.d.ts +43 -0
- package/dist/migrations/0008_careful_black_bird.sql +17 -0
- package/dist/migrations/0009_hot_dark_phoenix.sql +1 -0
- package/dist/migrations/0010_analyze_stats.sql +6 -0
- package/dist/migrations/0011_far_black_tarantula.sql +1 -0
- package/dist/migrations/0012_blue_turbo.sql +23 -0
- package/dist/migrations/0013_hesitant_adam_destine.sql +15 -0
- package/dist/migrations/0014_organic_mongu.sql +73 -0
- package/dist/migrations/0015_panoramic_gorilla_man.sql +71 -0
- package/dist/migrations/0016_fuzzy_hemingway.sql +14 -0
- package/dist/migrations/0017_project_stage_sdk_migration.sql +29 -0
- package/dist/migrations/meta/0008_snapshot.json +1327 -0
- package/dist/migrations/meta/0009_snapshot.json +1335 -0
- package/dist/migrations/meta/0010_snapshot.json +1335 -0
- package/dist/migrations/meta/0011_snapshot.json +1342 -0
- package/dist/migrations/meta/0012_snapshot.json +1494 -0
- package/dist/migrations/meta/0013_snapshot.json +1592 -0
- package/dist/migrations/meta/0014_snapshot.json +1975 -0
- package/dist/migrations/meta/0015_snapshot.json +2315 -0
- package/dist/migrations/meta/0016_snapshot.json +2419 -0
- package/dist/migrations/meta/0017_snapshot.json +2419 -0
- package/dist/migrations/meta/_journal.json +71 -1
- package/dist/paths.d.ts +1 -0
- package/dist/plugin/types.d.ts +1 -0
- package/dist/plugins/index.js +166 -75
- package/dist/provider/acp/connection.d.ts +4 -0
- package/dist/provider/acp/meta.d.ts +11 -0
- package/dist/provider/bridge.d.ts +16 -1
- package/dist/provider/classify-task-error.d.ts +2 -0
- package/dist/provider/cli/adapter.types.d.ts +6 -0
- package/dist/provider/cli/adapters/cli-knob.util.d.ts +8 -0
- package/dist/provider/cli/adapters/grok.d.ts +2 -0
- package/dist/provider/cli/adapters/index.d.ts +1 -0
- package/dist/provider/cli/index.d.ts +1 -1
- package/dist/provider/cli/meta.d.ts +5 -0
- package/dist/provider/errors.d.ts +1 -0
- package/dist/provider/idle-watchdog.d.ts +19 -0
- package/dist/provider/models.d.ts +17 -12
- package/dist/provider/order.d.ts +1 -1
- package/dist/provider/parse-usage.d.ts +6 -0
- package/dist/provider/provider-selection.d.ts +8 -0
- package/dist/provider/redact-technical-message.d.ts +1 -0
- package/dist/provider/task-error.types.d.ts +16 -0
- package/dist/publish/auth-boundary.d.ts +22 -0
- package/dist/publish/auth-json.d.ts +11 -0
- package/dist/publish/constants.d.ts +6 -0
- package/dist/publish/index.d.ts +30 -0
- package/dist/publish/index.js +1 -0
- package/dist/publish/manifest.d.ts +17 -0
- package/dist/publish/marketplace-api.constants.d.ts +1 -0
- package/dist/publish/pack.d.ts +2 -0
- package/dist/publish/scan.d.ts +9 -0
- package/dist/publish/secrets.d.ts +6 -0
- package/dist/publish/upload.d.ts +18 -0
- package/dist/repository/agent-suggestion.repository.d.ts +34 -0
- package/dist/repository/db.d.ts +8 -0
- package/dist/repository/index.d.ts +16 -3
- package/dist/repository/index.js +184 -78
- package/dist/repository/notification.repository.d.ts +58 -0
- package/dist/repository/project.repository.d.ts +90 -0
- package/dist/repository/task-log-migration.d.ts +74 -0
- package/dist/repository/task-log.repository.d.ts +44 -0
- package/dist/repository/task.repository.d.ts +114 -0
- package/dist/repository/thread.repository.d.ts +5 -2
- package/dist/repository/usage-report.repository.d.ts +27 -0
- package/dist/schema/agent-suggestions.d.ts +199 -0
- package/dist/schema/index.d.ts +7 -0
- package/dist/schema/notifications.d.ts +303 -0
- package/dist/schema/projects.d.ts +610 -0
- package/dist/schema/task-log-events.d.ts +119 -0
- package/dist/schema/tasks.d.ts +53 -0
- package/dist/schema/ui-action-receipts.d.ts +303 -0
- package/dist/schema/ui-instances.d.ts +267 -0
- package/dist/schema/usage-reports.d.ts +252 -0
- package/dist/testing/index.js +1 -1
- package/dist/types/index.d.ts +445 -3
- package/dist/ui-card/index.d.ts +2 -0
- package/dist/ui-card/legacy-card-parser.d.ts +11 -0
- package/dist/ui-instance/definition.d.ts +6 -0
- package/dist/ui-instance/errors.d.ts +17 -0
- package/dist/ui-instance/index.d.ts +6 -0
- package/dist/ui-instance/json.d.ts +5 -0
- package/dist/ui-instance/runtime.d.ts +13 -0
- package/dist/ui-instance/store.d.ts +65 -0
- package/dist/ui-instance/types.d.ts +200 -0
- package/dist/utils/crewx-home.d.ts +1 -0
- package/dist/utils/id.d.ts +1 -1
- package/dist/utils/timestamp.d.ts +1 -0
- package/dist/wi/create.d.ts +48 -0
- package/dist/wi/select.d.ts +20 -0
- package/package.json +18 -2
- package/templates/agents/default.yaml +175 -117
- package/templates/documents/crewx-manual.md +138 -138
- package/templates/workflows/wi-default-flow.yaml +65 -0
- package/templates/workflows/wi-plan-flow.yaml +140 -0
|
@@ -1,19 +1,59 @@
|
|
|
1
|
-
import*as
|
|
1
|
+
import*as Q from'path';import Q__default,{join,dirname}from'path';import {fileURLToPath}from'url';import {existsSync,mkdirSync,writeFileSync,appendFileSync,readFileSync}from'fs';import Pe,{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,check,uniqueIndex,unique,primaryKey}from'drizzle-orm/sqlite-core';var yt=(r=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(r,{get:(t,e)=>(typeof require<"u"?require:t)[e]}):r)(function(r){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+r+'" is not supported')});var xe=()=>fileURLToPath(import.meta.url),Ae=()=>Q__default.dirname(xe()),k=Ae();var it=class{detach(t){}};function Jt(r){let t=e=>String(e).padStart(2,"0");return `${r.getFullYear()}${t(r.getMonth()+1)}${t(r.getDate())}T${t(r.getHours())}${t(r.getMinutes())}${t(r.getSeconds())}`}function It(r){let t=r.toISOString();return `${t.slice(0,10)} ${t.slice(11,19)} UTC`}var Pt=class extends it{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",e=>{try{existsSync(this.logsDir)||mkdirSync(this.logsDir,{recursive:!0});let s=Jt(e.timestamp),o=join(this.logsDir,`${s}_${e.traceId}.log`);this.logFiles.set(e.traceId,o);let i=`=== TASK LOG: ${e.traceId} ===
|
|
2
2
|
CrewX Version: ${this.version}
|
|
3
3
|
Mode: ${e.mode}
|
|
4
4
|
Agent: ${e.agentRef}
|
|
5
|
-
Started: ${e.timestamp
|
|
5
|
+
Started: ${It(e.timestamp)}
|
|
6
6
|
Message: ${e.message}
|
|
7
7
|
|
|
8
|
-
`;writeFileSync(
|
|
9
|
-
`,"utf8");}catch{}}),t.on("task:end",e=>{try{let s=this.logFiles.get(e.traceId);if(!s)return;let
|
|
10
|
-
[${
|
|
11
|
-
`;appendFileSync(s,
|
|
8
|
+
`;writeFileSync(o,i,{encoding:"utf8",mode:384});}catch{}}),t.on("task:output",e=>{try{let s=this.logFiles.get(e.traceId);if(!s)return;let o=new Date().toISOString();appendFileSync(s,`[${o}] STDOUT: ${e.output}
|
|
9
|
+
`,"utf8");}catch{}}),t.on("task:end",e=>{try{let s=this.logFiles.get(e.traceId);if(!s)return;let o=It(new Date),i=e.error?`failed: ${e.error.message}`:"completed successfully",d=`[${o}] INFO: Task ${i} in ${e.durationMs}ms
|
|
10
|
+
[${o}] INFO: Process closed with exit code: ${e.error?1:0}
|
|
11
|
+
`;appendFileSync(s,d,"utf8"),this.logFiles.delete(e.traceId);}catch{}}));}detach(t){this.unsubs.forEach(e=>e()),this.unsubs=[],this.logFiles.clear();}};function Le(r){let t=Q.resolve(r);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 Qt(r){let t=Le(r);return createHash("sha256").update(t).digest("hex")}var at=class{resolveDbPath(){return process.env.CREWX_DB?process.env.CREWX_DB:process.env.CREWX_TRACES_DB?process.env.CREWX_TRACES_DB:join(Pe.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 Ue=32*1024*1024;function N(r){let t=yt("better-sqlite3"),{drizzle:e}=yt("drizzle-orm/better-sqlite3"),s=new t(r);return s.exec("PRAGMA journal_mode = WAL"),s.exec(`PRAGMA journal_size_limit = ${Ue}`),s.exec("PRAGMA busy_timeout = 5000"),s.exec("PRAGMA foreign_keys = ON"),s.exec("PRAGMA analysis_limit = 400"),s.exec("PRAGMA optimize"),{db:e(s),runRaw:(o,i=[])=>s.prepare(o).run(...i),close:()=>s.close()}}var Zt=new Set,je={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 Mt(r,t){return (r.get(`SELECT count(*) as cnt FROM sqlite_master WHERE type='table' AND name='${t}'`)?.cnt??0)>0}function qe(r,t){if(t>0||!Mt(r,"tasks"))return;let e=r.all("PRAGMA table_info(tasks)"),s=new Set(e.map(o=>o.name));for(let[o,i]of Object.entries(je))s.has(o)||r.run(`ALTER TABLE tasks ADD COLUMN ${o} ${i}`);}var Be={"0002_normalize_task_names":{workspace_name:"TEXT",project_name:"TEXT"},"0015_panoramic_gorilla_man":{project_id:"TEXT",workspace_id:"TEXT"}};function He(r,t,e){if(!Mt(r,"__drizzle_migrations")||!Mt(r,"tasks"))return;let s=r.all(e`SELECT hash FROM __drizzle_migrations`),o=new Set(s.map(d=>d.hash)),i=JSON.parse(readFileSync(Q__default.join(t,"meta/_journal.json"),"utf-8"));for(let d of i.entries){let a=Be[d.tag];if(!a)continue;let u=Q__default.join(t,`${d.tag}.sql`);if(!existsSync(u))continue;let c=readFileSync(u,"utf-8"),l=createHash("sha256").update(c).digest("hex");if(o.has(l))continue;let g=r.all("PRAGMA table_info(tasks)"),f=new Set(g.map(w=>w.name));for(let[w,L]of Object.entries(a))f.has(w)||(r.run(`ALTER TABLE tasks ADD COLUMN ${w} ${L}`),f.add(w));}}function Fe(r,t,e){let s=r.all(e`SELECT hash FROM __drizzle_migrations`),o=new Set(s.map(d=>d.hash)),i=JSON.parse(readFileSync(Q__default.join(t,"meta/_journal.json"),"utf-8"));for(let d of i.entries){let a=Q__default.join(t,`${d.tag}.sql`);if(!existsSync(a))continue;let u=readFileSync(a,"utf-8"),c=createHash("sha256").update(u).digest("hex");if(o.has(c))continue;let l=/ALTER\s+TABLE\s+[`"]?(\w+)[`"]?\s+ADD\s+[`"]?(\w+)[`"]?/gi,g=[],f;for(;(f=l.exec(u))!==null;)g.push({table:f[1],column:f[2]});if(g.length===0||!u.split(/-->\s*statement-breakpoint/).map(O=>O.trim()).filter(Boolean).every(O=>/^ALTER\s+TABLE\s+.+\s+ADD\s+/i.test(O)))continue;g.every(({table:O,column:q})=>r.all(`PRAGMA table_info("${O}")`).some(V=>V.name===q))&&r.run(e`INSERT INTO __drizzle_migrations (hash, created_at) VALUES (${c}, ${d.when})`);}}function ze(r){let{migrate:t}=yt("drizzle-orm/better-sqlite3/migrator"),{sql:e}=yt("drizzle-orm"),s=[Q__default.join(k,"../migrations"),Q__default.join(k,"migrations"),Q__default.join(k,"../../../../drizzle/migrations"),Q__default.join(process.cwd(),"drizzle/migrations")],o=s.find(c=>existsSync(Q__default.join(c,"meta/_journal.json")));if(!o)throw new Error(`migrations folder not found. Searched:
|
|
12
12
|
${s.join(`
|
|
13
|
-
`)}`);let r=d.get(e`SELECT count(*) as cnt FROM sqlite_master WHERE type='table' AND name='__drizzle_migrations'`),i=0;r?.cnt&&(i=d.get(e`SELECT count(*) as cnt FROM __drizzle_migrations`)?.cnt??0),Jt(d,i),r?.cnt&&(Zt(d,n,e),Qt(d,n,e)),t(d,{migrationsFolder:n});let l=(d.get(e`SELECT count(*) as cnt FROM __drizzle_migrations`)?.cnt??0)-i;if(l>0){let c=r?.cnt?"Database migrated":"Database initialized";console.error(`[crewx] ${c} (${l} migration${l>1?"s":""} applied).`);}}function st(d,t){xt.has(t)||(te(d),xt.add(t));}var _=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 Y=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"),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 u=sqliteTable("threads",{id:text("id").primaryKey(),workspace_id:text("workspace_id").references(()=>Y.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)}));var de=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(()=>de.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(()=>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)}));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)}));var W="2026-05-09",be="0.8.9-rc.13",j=10,K=parseInt(be.split("rc.")[1]),dt=class extends X{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 _("NOT_FOUND","Database not found");let s=T(e);if(t)try{st(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,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:o.id,set:{pid:sql`COALESCE(excluded.pid, ${o.pid})`},setWhere:eq(o.status,"running")}).run();}catch(s){throw s instanceof _?s:new _("DB_ERROR","Failed to start task",s)}finally{e.close();}}finishTask(t){let e=this.openHandle(true);try{let s=t.runEpoch??null;e.runRaw(`UPDATE tasks SET status=?, result=?, error=?, completed_at=?, duration_ms=?,
|
|
13
|
+
`)}`);let i=r.get(e`SELECT count(*) as cnt FROM sqlite_master WHERE type='table' AND name='__drizzle_migrations'`),d=0;i?.cnt&&(d=r.get(e`SELECT count(*) as cnt FROM __drizzle_migrations`)?.cnt??0),qe(r,d),i?.cnt&&(Fe(r,o,e),He(r,o,e)),t(r,{migrationsFolder:o});let u=(r.get(e`SELECT count(*) as cnt FROM __drizzle_migrations`)?.cnt??0)-d;if(u>0){let c=i?.cnt?"Database migrated":"Database initialized";console.error(`[crewx] ${c} (${u} migration${u>1?"s":""} applied).`);}}function pt(r,t){Zt.has(t)||(ze(r),Zt.add(t));}var _=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 gt=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 n=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"),log_storage:text("log_storage",{enum:["blob","events"]}).notNull().default("blob"),last_log_seq:integer("last_log_seq").notNull().default(0),log_revision:integer("log_revision").notNull().default(0),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)},r=>({log_storage_check:check("tasks_log_storage_ck",sql`${r.log_storage} IN ('blob', 'events')`),idx_tasks_agent_id:index("idx_tasks_agent_id").on(r.agent_id),idx_tasks_status:index("idx_tasks_status").on(r.status),idx_tasks_started_at:index("idx_tasks_started_at").on(r.started_at),idx_tasks_trace_id:index("idx_tasks_trace_id").on(r.trace_id),idx_tasks_parent_task_id:index("idx_tasks_parent_task_id").on(r.parent_task_id),idx_tasks_crewx_version:index("idx_tasks_crewx_version").on(r.crewx_version),idx_tasks_pid:index("idx_tasks_pid").on(r.pid),idx_tasks_thread_id:index("idx_tasks_thread_id").on(r.thread_id),idx_tasks_workspace_id:index("idx_tasks_workspace_id").on(r.workspace_id),idx_tasks_workspace_ref:index("idx_tasks_workspace_ref").on(r.workspace_ref),idx_tasks_project_id:index("idx_tasks_project_id").on(r.project_id),idx_tasks_ws_started:index("idx_tasks_ws_started").on(r.workspace_id,r.started_at)}));var W=sqliteTable("task_log_events",{id:integer("id").primaryKey(),task_id:text("task_id").notNull().references(()=>n.id,{onDelete:"cascade"}),seq:integer("seq").notNull(),timestamp:text("timestamp").notNull(),level:text("level").notNull(),message:text("message").notNull()},r=>({taskSeqUnique:uniqueIndex("task_log_events_task_seq_uq").on(r.task_id,r.seq)}));var p=sqliteTable("threads",{id:text("id").primaryKey(),workspace_id:text("workspace_id").references(()=>gt.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)},r=>({idx_threads_updated_at:index("idx_threads_updated_at").on(r.updated_at),idx_threads_workspace_id:index("idx_threads_workspace_id").on(r.workspace_id),idx_threads_ws_updated:index("idx_threads_ws_updated").on(r.workspace_id,r.updated_at),idx_threads_title:index("idx_threads_title").on(r.title)}));var nn=sqliteTable("spans",{id:text("id").primaryKey(),task_id:text("task_id").references(()=>n.id,{onDelete:"set null"}),parent_span_id:text("parent_span_id").references(()=>nn.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")},r=>({idx_spans_task_id:index("idx_spans_task_id").on(r.task_id),idx_spans_parent_span_id:index("idx_spans_parent_span_id").on(r.parent_span_id)}));sqliteTable("tool_calls",{id:text("id").primaryKey(),task_id:text("task_id").references(()=>n.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()},r=>({idx_tool_calls_task_id:index("idx_tool_calls_task_id").on(r.task_id),idx_tool_calls_tool_name:index("idx_tool_calls_tool_name").on(r.tool_name),idx_tool_calls_timestamp:index("idx_tool_calls_timestamp").on(r.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()},r=>({idx_thread_boxes_thread_id:index("idx_thread_boxes_thread_id").on(r.thread_id),idx_thread_boxes_seq:index("idx_thread_boxes_seq").on(r.thread_id,r.seq),uniq_thread_boxes_thread_seq:unique().on(r.thread_id,r.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")},r=>({idx_request_logs_timestamp:index("idx_request_logs_timestamp").on(r.timestamp),idx_request_logs_path:index("idx_request_logs_path").on(r.path),idx_request_logs_status_code:index("idx_request_logs_status_code").on(r.status_code),idx_request_logs_partition_key:index("idx_request_logs_partition_key").on(r.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")},r=>({uniq_usage_limit_snapshots_bucket:uniqueIndex("uniq_usage_limit_snapshots_bucket").on(r.provider,r.account_ref,r.limit_window,r.bucket_start),idx_usage_limit_snapshots_window_bucket:index("idx_usage_limit_snapshots_window_bucket").on(r.limit_window,r.bucket_start),idx_usage_limit_snapshots_provider_window_bucket:index("idx_usage_limit_snapshots_provider_window_bucket").on(r.provider,r.limit_window,r.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")},r=>({uniq_usage_reports_ws_month:uniqueIndex("uniq_usage_reports_ws_month").on(r.workspace_id,r.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")},r=>({idx_notifications_ws_created:index("idx_notifications_ws_created").on(r.workspace_id,sql`${r.created_at} DESC`)}));sqliteTable("notification_reads",{notification_id:text("notification_id").notNull(),user_id:text("user_id").notNull(),read_at:text("read_at").notNull()},r=>({pk:primaryKey({columns:[r.notification_id,r.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()},r=>({idx_agent_suggestions_ws_agent:index("idx_agent_suggestions_ws_agent").on(r.workspace_id,r.agent_id),idx_agent_suggestions_ws_created:index("idx_agent_suggestions_ws_created").on(r.workspace_id,r.created_at)}));sqliteTable("ui_instances",{id:text("id").primaryKey().notNull(),definition_id:text("definition_id").notNull(),definition_version:integer("definition_version").notNull(),definition_hash:text("definition_hash").notNull(),workspace_id:text("workspace_id").notNull(),thread_id:text("thread_id").notNull(),anchor_task_id:text("anchor_task_id"),domain_ref_json:text("domain_ref_json").notNull(),state_json:text("state_json").notNull(),revision:integer("revision").notNull().default(0),status:text("status").notNull().default("active"),granted_capabilities_json:text("granted_capabilities_json").notNull().default("[]"),created_at:integer("created_at").notNull(),updated_at:integer("updated_at").notNull()},r=>({idCheck:check("ui_instances_id_ck",sql`length(${r.id}) BETWEEN 5 AND 128 AND ${r.id} GLOB 'uic_*'`),definitionIdCheck:check("ui_instances_definition_id_ck",sql`length(${r.definition_id}) BETWEEN 1 AND 128`),definitionVersionCheck:check("ui_instances_definition_version_ck",sql`${r.definition_version} >= 1`),definitionHashCheck:check("ui_instances_definition_hash_ck",sql`length(${r.definition_hash}) = 64 AND ${r.definition_hash} NOT GLOB '*[^0-9a-f]*'`),workspaceIdCheck:check("ui_instances_workspace_id_ck",sql`length(${r.workspace_id}) BETWEEN 1 AND 256`),threadIdCheck:check("ui_instances_thread_id_ck",sql`length(${r.thread_id}) BETWEEN 1 AND 256`),domainRefJsonCheck:check("ui_instances_domain_ref_json_ck",sql`json_valid(${r.domain_ref_json}) AND json_type(${r.domain_ref_json}) = 'object'`),stateJsonCheck:check("ui_instances_state_json_ck",sql`json_valid(${r.state_json}) AND json_type(${r.state_json}) = 'object'`),revisionCheck:check("ui_instances_revision_ck",sql`${r.revision} >= 0`),statusCheck:check("ui_instances_status_ck",sql`${r.status} IN ('active', 'completed', 'expired', 'revoked', 'unsupported')`),grantedCapabilitiesJsonCheck:check("ui_instances_granted_capabilities_json_ck",sql`json_valid(${r.granted_capabilities_json}) AND json_type(${r.granted_capabilities_json}) = 'array'`),createdAtCheck:check("ui_instances_created_at_ck",sql`${r.created_at} >= 0`),updatedAtCheck:check("ui_instances_updated_at_ck",sql`${r.updated_at} >= ${r.created_at}`),workspaceThreadIdx:index("ui_instances_workspace_thread_idx").on(r.workspace_id,r.thread_id)}));sqliteTable("ui_action_receipts",{id:text("id").primaryKey().notNull(),instance_id:text("instance_id").notNull(),request_id:text("request_id").notNull(),action_id:text("action_id").notNull(),actor_json:text("actor_json").notNull(),source:text("source").notNull(),expected_revision:integer("expected_revision").notNull(),before_revision:integer("before_revision").notNull(),after_revision:integer("after_revision"),status:text("status").notNull(),outcome:text("outcome"),input_json:text("input_json").notNull(),result_json:text("result_json"),error_code:text("error_code"),requested_at:integer("requested_at").notNull(),settled_at:integer("settled_at")},r=>({idCheck:check("ui_action_receipts_id_ck",sql`length(${r.id}) BETWEEN 5 AND 128`),instanceIdCheck:check("ui_action_receipts_instance_id_ck",sql`length(${r.instance_id}) BETWEEN 1 AND 128`),requestIdCheck:check("ui_action_receipts_request_id_ck",sql`length(${r.request_id}) BETWEEN 1 AND 128`),actionIdCheck:check("ui_action_receipts_action_id_ck",sql`length(${r.action_id}) BETWEEN 1 AND 128`),actorJsonCheck:check("ui_action_receipts_actor_json_ck",sql`json_valid(${r.actor_json}) AND json_type(${r.actor_json}) = 'object'`),sourceCheck:check("ui_action_receipts_source_ck",sql`${r.source} IN ('ui_host', 'cli', 'system')`),expectedRevisionCheck:check("ui_action_receipts_expected_revision_ck",sql`${r.expected_revision} >= 0`),beforeRevisionCheck:check("ui_action_receipts_before_revision_ck",sql`${r.before_revision} >= 0`),afterRevisionCheck:check("ui_action_receipts_after_revision_ck",sql`${r.after_revision} IS NULL OR ${r.after_revision} >= 0`),statusCheck:check("ui_action_receipts_status_ck",sql`${r.status} IN ('requested', 'settled')`),outcomeCheck:check("ui_action_receipts_outcome_ck",sql`${r.outcome} IS NULL OR ${r.outcome} IN ('succeeded', 'rejected', 'failed', 'conflicted', 'expired')`),inputJsonCheck:check("ui_action_receipts_input_json_ck",sql`json_valid(${r.input_json}) AND json_type(${r.input_json}) = 'object'`),resultJsonCheck:check("ui_action_receipts_result_json_ck",sql`${r.result_json} IS NULL OR (json_valid(${r.result_json}) AND json_type(${r.result_json}) = 'object')`),requestedAtCheck:check("ui_action_receipts_requested_at_ck",sql`${r.requested_at} >= 0`),settledAtCheck:check("ui_action_receipts_settled_at_ck",sql`${r.settled_at} IS NULL OR ${r.settled_at} >= ${r.requested_at}`),statusTransitionCheck:check("ui_action_receipts_status_transition_ck",sql`(
|
|
14
|
+
(${r.status} = 'requested' AND ${r.after_revision} IS NULL AND ${r.outcome} IS NULL AND ${r.settled_at} IS NULL)
|
|
15
|
+
OR
|
|
16
|
+
(${r.status} = 'settled' AND ${r.after_revision} IS NOT NULL AND ${r.outcome} IS NOT NULL AND ${r.settled_at} IS NOT NULL)
|
|
17
|
+
)`),instanceRequestUnique:uniqueIndex("ui_action_receipts_instance_request_uq").on(r.instance_id,r.request_id),instanceIdIdx:index("ui_action_receipts_instance_id_idx").on(r.instance_id),requestedAtIdx:index("ui_action_receipts_requested_at_idx").on(r.requested_at)}));var ue=sqliteTable("projects",{id:text("id").primaryKey().notNull(),workspace_id:text("workspace_id").notNull(),name:text("name").notNull(),outcome:text("outcome").notNull(),due_date:text("due_date"),scene:text("scene").notNull().default("planning"),stages_json:text("stages_json").notNull(),stage_index:integer("stage_index").notNull(),created_at:text("created_at").notNull(),updated_at:text("updated_at").notNull(),accepted_at:text("accepted_at"),archived_at:text("archived_at")},r=>({idCheck:check("projects_id_ck",sql`${r.id} GLOB 'prj_*'`),sceneCheck:check("projects_scene_ck",sql`${r.scene} IN ('planning', 'plan_review', 'running', 'human_wait', 'limit_wait', 'failed_stop', 'analyzing_feedback', 'replanned', 'awaiting_review', 'accepted')`),stagesJsonCheck:check("projects_stages_json_ck",sql`json_valid(${r.stages_json}) AND json_type(${r.stages_json}) = 'array'`),stageIndexCheck:check("projects_stage_index_ck",sql`${r.stage_index} >= 1`)}));sqliteTable("project_criteria",{id:text("id").primaryKey().notNull(),project_id:text("project_id").notNull().references(()=>ue.id,{onDelete:"cascade"}),position:integer("position").notNull(),statement:text("statement").notNull(),verify_status:text("verify_status").notNull().default("pending"),verified_at:text("verified_at"),evidence_json:text("evidence_json").notNull().default("[]"),created_at:text("created_at").notNull(),updated_at:text("updated_at").notNull()},r=>({idCheck:check("project_criteria_id_ck",sql`${r.id} GLOB 'pjc_*'`),verifyStatusCheck:check("project_criteria_verify_status_ck",sql`${r.verify_status} IN ('pending', 'verifying', 'passed', 'failed')`),evidenceJsonCheck:check("project_criteria_evidence_json_ck",sql`json_valid(${r.evidence_json}) AND json_type(${r.evidence_json}) = 'array'`),projectPositionUnique:uniqueIndex("project_criteria_project_position_uq").on(r.project_id,r.position)}));sqliteTable("project_events",{id:text("id").primaryKey().notNull(),project_id:text("project_id").notNull().references(()=>ue.id,{onDelete:"restrict"}),seq:integer("seq").notNull(),actor_type:text("actor_type").notNull(),actor_id:text("actor_id"),type:text("type").notNull(),title:text("title").notNull(),summary:text("summary"),payload_json:text("payload_json").notNull().default("{}"),created_at:text("created_at").notNull()},r=>({idCheck:check("project_events_id_ck",sql`${r.id} GLOB 'pje_*'`),actorTypeCheck:check("project_events_actor_type_ck",sql`${r.actor_type} IN ('user', 'project_manager', 'system')`),payloadJsonCheck:check("project_events_payload_json_ck",sql`json_valid(${r.payload_json}) AND json_type(${r.payload_json}) = 'object'`),projectSeqUnique:uniqueIndex("project_events_project_seq_uq").on(r.project_id,r.seq)}));function _e(r){let t=r.toLowerCase().trim();t=t.replace(/\[[^\]]*\]$/g,"");let e=t.lastIndexOf("/");return e>=0&&(t=t.slice(e+1)),t=t.replace(/-\d{8}$/,""),t}function he(r,t){let e=t===void 0?"":` at index ${t}`;if(!r||typeof r!="object")throw new _("VALIDATION",`Task log entry${e} must be an object`);if(typeof r.timestamp!="string"||typeof r.level!="string"||typeof r.message!="string")throw new _("VALIDATION",`Task log entry${e} must contain string timestamp, level, and message fields`);return {timestamp:r.timestamp,level:r.level,message:r.message}}function fe(r,t){if(t===null||t.trim()==="")return [];let e;try{e=JSON.parse(t);}catch(s){throw new _("DB_ERROR",`Malformed legacy task logs: ${r}`,s)}if(!Array.isArray(e))throw new _("DB_ERROR",`Malformed legacy task logs: ${r} (expected an array)`);try{return e.map((s,o)=>he(s,o))}catch(s){throw s instanceof _?new _("DB_ERROR",`Malformed legacy task logs: ${r}`,s):s}}function ke(r){if(r.log_storage!=="blob"&&r.log_storage!=="events")throw new _("DB_ERROR",`Invalid task log storage for task: ${r.id}`);if(!Number.isInteger(r.last_log_seq)||r.last_log_seq<0)throw new _("DB_ERROR",`Invalid task log sequence for task: ${r.id}`);if(!Number.isInteger(r.log_revision)||r.log_revision<0)throw new _("DB_ERROR",`Invalid task log revision for task: ${r.id}`);return r.log_storage}function me(r){return {taskId:r.id,source:ke(r),revision:r.log_revision,lastSeq:r.last_log_seq}}function $n(r){if(!Number.isInteger(r)||r<0)throw new _("VALIDATION","Task log tail limit must be a non-negative integer")}var Ct=class extends at{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 _("NOT_FOUND","Database not found");let s=N(e);if(t)try{pt(s.db,e);}catch(o){throw s.close(),o}return s}findStateRow(t,e){return t.db.select({id:n.id,log_storage:n.log_storage,last_log_seq:n.last_log_seq,log_revision:n.log_revision,logs:n.logs}).from(n).where(eq(n.id,e)).limit(1).get()}findStateRowInTransaction(t,e){return t.select({id:n.id,log_storage:n.log_storage,last_log_seq:n.last_log_seq,log_revision:n.log_revision,logs:n.logs}).from(n).where(eq(n.id,e)).limit(1).get()}requireStateRowInTransaction(t,e){let s=this.findStateRowInTransaction(t,e);if(!s)throw new _("NOT_FOUND",`Task not found: ${e}`);return s}appendLog(t,e){return this.appendLogs(t,[e])}appendLogs(t,e){let s=e.map((i,d)=>he(i,d));if(s.length===0){let i=this.getLogState(t);if(!i)throw new _("NOT_FOUND",`Task not found: ${t}`);return i}let o=this.openHandle(true);try{return o.db.transaction(d=>{let a=this.requireStateRowInTransaction(d,t),u=ke(a);if(u==="blob"){let f=fe(t,a.logs);if(d.update(n).set({logs:JSON.stringify([...f,...s]),log_revision:sql`${n.log_revision} + 1`}).where(eq(n.id,t)).run().changes!==1)throw new _("NOT_FOUND",`Task not found: ${t}`);return {taskId:t,source:u,revision:a.log_revision+1,lastSeq:a.last_log_seq}}let c=a.last_log_seq+1,l=a.last_log_seq+s.length;if(d.insert(W).values(s.map((f,w)=>({task_id:t,seq:c+w,timestamp:f.timestamp,level:f.level,message:f.message}))).run(),d.update(n).set({last_log_seq:l,log_revision:sql`${n.log_revision} + 1`}).where(eq(n.id,t)).run().changes!==1)throw new _("NOT_FOUND",`Task not found: ${t}`);return {taskId:t,source:u,revision:a.log_revision+1,lastSeq:l}},{behavior:"immediate"})}catch(i){throw i instanceof _?i:new _("DB_ERROR","Failed to append task log",i)}finally{o.close();}}getLogState(t){if(!this.dbExists())return;let e=this.openHandle(false);try{let s=this.findStateRow(e,t);return s?me(s):void 0}catch(s){throw s instanceof _?s:new _("DB_ERROR","Failed to read task log state",s)}finally{e.close();}}readLogs(t){return this.readLogsInternal(t)}readLogsTail(t,e){return $n(e),this.readLogsInternal(t,e)}readTail(t,e){return this.readLogsTail(t,e)}readLogsInternal(t,e){if(!this.dbExists())return;let s=this.openHandle(false);try{return s.db.transaction(o=>{let i=this.findStateRowInTransaction(o,t);if(!i)return;let d=me(i);if(d.source==="blob"){let l=fe(t,i.logs);return {...d,entries:e===void 0?l:l.slice(Math.max(0,l.length-e))}}let a=o.select({seq:W.seq,timestamp:W.timestamp,level:W.level,message:W.message}).from(W).where(eq(W.task_id,t)).orderBy(e===void 0?asc(W.seq):desc(W.seq)),c=(e===void 0?a.all():a.limit(e).all()).map(({timestamp:l,level:g,message:f})=>({timestamp:l,level:g,message:f}));return e!==void 0&&c.reverse(),{...d,entries:c}},{behavior:"deferred"})}catch(o){throw o instanceof _?o:new _("DB_ERROR","Failed to read task logs",o)}finally{s.close();}}};var Ft=40,st="2026-05-09",Mn="0.8.9-rc.13",rt=10,ot=parseInt(Mn.split("rc.")[1]);function we(){let r=sql`
|
|
18
|
+
CASE
|
|
19
|
+
WHEN ${n.model} LIKE 'claude-%' OR ${n.model} IN ('opus', 'sonnet', 'haiku', 'opus[1m]', 'sonnet[1m]') THEN 'claude'
|
|
20
|
+
WHEN ${n.model} LIKE 'gpt-%' OR ${n.model} LIKE 'codex-%' THEN 'codex'
|
|
21
|
+
WHEN ${n.model} LIKE 'gemini-%' THEN 'gemini'
|
|
22
|
+
WHEN ${n.model} LIKE 'grok-%' THEN 'grok'
|
|
23
|
+
WHEN ${n.model} LIKE 'zai-%' OR ${n.model} LIKE 'openrouter/z-ai/%' THEN 'opencode'
|
|
24
|
+
WHEN ${n.model} LIKE 'minimax/%' THEN 'minimax'
|
|
25
|
+
WHEN ${n.model} LIKE 'qwen%' THEN 'qwen'
|
|
26
|
+
ELSE 'unknown'
|
|
27
|
+
END
|
|
28
|
+
`,t=sql`json_extract(${n.metadata}, '$.provider')`,e=sql`trim(${t})`,s=sql`substr(${e}, 1, instr(${e}, '/') - 1)`,o=sql`
|
|
29
|
+
CASE
|
|
30
|
+
WHEN instr(${e}, '/') > 0
|
|
31
|
+
AND ${s} IN ('cli', 'acp', 'api', 'plugin', 'remote')
|
|
32
|
+
THEN substr(${e}, instr(${e}, '/') + 1)
|
|
33
|
+
ELSE ${e}
|
|
34
|
+
END
|
|
35
|
+
`;return sql`
|
|
36
|
+
CASE
|
|
37
|
+
WHEN ${n.metadata} IS NULL THEN ${r}
|
|
38
|
+
WHEN json_valid(${n.metadata}) = 0 THEN 'unknown'
|
|
39
|
+
WHEN json_type(${n.metadata}, '$') IS NOT 'object' THEN 'unknown'
|
|
40
|
+
WHEN json_type(${n.metadata}, '$.provider') IS NULL THEN ${r}
|
|
41
|
+
WHEN json_type(${n.metadata}, '$.provider') IS NOT 'text' THEN 'unknown'
|
|
42
|
+
WHEN ${e} = '' THEN 'unknown'
|
|
43
|
+
WHEN trim(${o}) = '' THEN 'unknown'
|
|
44
|
+
ELSE ${o}
|
|
45
|
+
END
|
|
46
|
+
`}var Un=new Set(["workflow","mcp"]),Ee=600*1e3,Dt=class extends at{dbPath;taskLogRepository;pidNullObservedSince=new Map;constructor(t={}){super(),t.dbPath?this.dbPath=t.dbPath:t.dbRoot&&(this.dbPath=join(t.dbRoot,".crewx","crewx.db")),this.taskLogRepository=new Ct({dbPath:this.dbPath});}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 _("NOT_FOUND","Database not found");let s=N(e);if(t)try{pt(s.db,e);}catch(o){throw s.close(),o}return s}startTask(t){let e=this.openHandle(true);try{let s={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,project_id:t.projectId??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,log_storage:"events"},o=i=>{e.db.insert(n).values(i).onConflictDoUpdate({target:n.id,set:{pid:sql`COALESCE(excluded.pid, ${n.pid})`},setWhere:eq(n.status,"running")}).run();};try{o(s);}catch(i){let d=i instanceof Error?i.message:typeof i=="object"&&i!==null&&"message"in i?String(i.message):String(i);if(!/log_storage/i.test(d)||!/no such column|no column named/i.test(d))throw i;e.runRaw(`INSERT INTO tasks (
|
|
47
|
+
id, agent_id, prompt, mode, status, started_at, pid,
|
|
48
|
+
parent_task_id, caller_agent_id, trace_id, command, metadata,
|
|
49
|
+
workspace_id, project_id, platform, crewx_version, thread_id,
|
|
50
|
+
model, rendered_prompt, coding_agent_command
|
|
51
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
52
|
+
ON CONFLICT(id) DO UPDATE SET pid = COALESCE(excluded.pid, tasks.pid)
|
|
53
|
+
WHERE tasks.status = 'running'`,[s.id,s.agent_id,s.prompt,s.mode,s.status,s.started_at,s.pid,s.parent_task_id,s.caller_agent_id,s.trace_id,s.command,s.metadata,s.workspace_id,s.project_id,s.platform,s.crewx_version,s.thread_id,s.model,s.rendered_prompt,s.coding_agent_command]);}}catch(s){throw s instanceof _?s:new _("DB_ERROR","Failed to start task",s)}finally{e.close();}}listTasksByProjectId(t){if(!this.dbExists())return [];let e=this.openHandle(false);try{return e.db.select().from(n).where(eq(n.project_id,t)).orderBy(desc(n.started_at)).all()}catch(s){throw s instanceof _?s:new _("DB_ERROR","Failed to list tasks by project",s)}finally{e.close();}}finishTask(t){let e=this.openHandle(true);try{let s=t.runEpoch??null;e.runRaw(`UPDATE tasks SET status=?, result=?, error=?, completed_at=?, duration_ms=?,
|
|
14
54
|
exit_code=?, input_tokens=?, output_tokens=?, cached_input_tokens=?, cost_usd=?,
|
|
15
55
|
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 _?s:new _("DB_ERROR","Failed to finish task",s)}finally{e.close();}}appendLog(t,e){
|
|
56
|
+
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{e.close();}}appendLog(t,e){this.taskLogRepository.appendLog(t,e);}appendLogs(t,e){this.taskLogRepository.appendLogs(t,e);}readLogs(t){return this.taskLogRepository.readLogs(t)}readLogsTail(t,e){return this.taskLogRepository.readLogsTail(t,e)}getLogState(t){return this.taskLogRepository.getLogState(t)}getRunningTasks(){if(!this.dbExists())return [];let t=this.openHandle(false);try{return t.db.select().from(n).where(eq(n.status,"running")).orderBy(desc(n.started_at)).all()}catch(e){throw new _("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(n).orderBy(desc(n.started_at)).limit(100).all()}catch(e){throw new _("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(n).where(eq(n.id,t)).limit(1).get()??void 0}catch(s){throw new _("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:n.id,status:n.status,pid:n.pid}).from(n).where(eq(n.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(n).set({status:"failed",error:"Killed by user",completed_at:new Date().toISOString()}).where(and(eq(n.id,t),eq(n.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{e.close();}}reapOrphanedTasks(){if(!this.dbExists())return 0;let t=this.openHandle(true);try{let e=t.db.select({id:n.id,pid:n.pid,platform:n.platform,run_epoch:n.run_epoch}).from(n).where(eq(n.status,"running")).all(),s=Date.now(),o=new Set,i=0;for(let d of e){if(d.pid){let c=!1;try{process.kill(d.pid,0),c=!0;}catch{}c||(t.db.update(n).set({status:"failed",error:"Reaped: process not found (orphaned task)",completed_at:new Date().toISOString()}).where(and(eq(n.id,d.id),eq(n.status,"running"))).run(),i++);continue}if(Un.has(d.platform??"cli"))continue;let a=`${d.id}:${d.run_epoch??0}`;o.add(a);let u=this.pidNullObservedSince.get(a);if(u===void 0){this.pidNullObservedSince.set(a,s);continue}s-u>=Ee&&(t.db.update(n).set({status:"failed",error:"Reaped: pid never recorded after resume (stale running_instruction)",completed_at:new Date().toISOString()}).where(and(eq(n.id,d.id),eq(n.status,"running"))).run(),i++,this.pidNullObservedSince.delete(a));}for(let d of Array.from(this.pidNullObservedSince.keys()))o.has(d)||this.pidNullObservedSince.delete(d);return i}finally{t.close();}}reapRunningWorkflowTasks(t=Ee){if(!this.dbExists())return 0;let e=this.openHandle(true);try{let s=new Date(Date.now()-t).toISOString();return e.db.update(n).set({status:"failed",error:"Reaped: stale workflow run (finally not executed)",completed_at:new Date().toISOString()}).where(and(eq(n.status,"running"),eq(n.platform,"workflow"),isNull(n.pid),lt(n.started_at,s),or(isNull(n.metadata),and(notLike(n.metadata,'%"kind":"workflow_card"%'),notLike(n.metadata,'%"kind":"workflow_ui_instance"%'))))).run().changes??0}finally{e.close();}}findTaskStatus(t,e){let s=this.resolveDbPaths();for(let o of s){if(!existsSync(o))continue;let i=N(o);try{let d=e?eq(n.workspace_id,e):void 0,a=d?and(eq(n.id,t),d):eq(n.id,t),u=i.db.select().from(n).where(a).limit(1).get()??void 0;if(!u){let c=or(eq(n.thread_id,t),and(isNull(n.thread_id),like(n.command,`%--thread=${t}%`))),l=d?and(c,d):c;u=i.db.select().from(n).where(l).orderBy(desc(n.started_at)).limit(1).get()??void 0;}if(u)return u}catch(d){throw new _("DB_ERROR","Failed to find task status",d)}finally{i.close();}}}findChildTasks(t,e){let s=this.resolveDbPaths(),o=new Set,i=[];for(let d of s){if(!existsSync(d))continue;let a=N(d);try{let u=e?and(eq(n.parent_task_id,t),eq(n.workspace_id,e)):eq(n.parent_task_id,t),c=a.db.select().from(n).where(u).orderBy(asc(n.started_at)).all();for(let l of c)o.has(l.id)||(o.add(l.id),i.push(l));}catch(u){throw new _("DB_ERROR","Failed to find child tasks",u)}finally{a.close();}}return i}getWorkspaceUsageSummary(t){if(!this.dbExists())return [];let e=this.openHandle(false);try{return e.db.all(t?sql`
|
|
17
57
|
SELECT
|
|
18
58
|
COALESCE(workspace_id, 'unknown') AS workspace_id,
|
|
19
59
|
COALESCE(SUM(input_tokens), 0) AS input_tokens,
|
|
@@ -34,7 +74,7 @@ ${s.join(`
|
|
|
34
74
|
FROM tasks
|
|
35
75
|
GROUP BY workspace_id
|
|
36
76
|
ORDER BY (COALESCE(SUM(input_tokens), 0) + COALESCE(SUM(output_tokens), 0)) DESC
|
|
37
|
-
`)}catch(s){throw new _("DB_ERROR","Failed to get workspace usage summary",s)}finally{e.close();}}getThreadTokenUsage(t,e){let s=this.resolveDbPaths(),
|
|
77
|
+
`)}catch(s){throw new _("DB_ERROR","Failed to get workspace usage summary",s)}finally{e.close();}}getThreadTokenUsage(t,e){let s=this.resolveDbPaths(),o=new Set,i=0,d=0,a=0;for(let u of s){if(!existsSync(u))continue;let c=N(u);try{let l=or(eq(n.thread_id,t),and(isNull(n.thread_id),like(n.command,`%--thread=${t}%`))),g=e?and(l,eq(n.workspace_id,e)):l,f=c.db.select({id:n.id,input_tokens:n.input_tokens,output_tokens:n.output_tokens,cost_usd:n.cost_usd}).from(n).where(g).all();for(let w of f)o.has(w.id)||(o.add(w.id),i+=w.input_tokens??0,d+=w.output_tokens??0,a+=w.cost_usd??0);}catch(l){throw new _("DB_ERROR","Failed to get thread token usage",l)}finally{c.close();}}return {inputTokens:i,outputTokens:d,costUsd:a}}findTasksByThread(t,e){let s=this.resolveDbPaths(),o=new Set,i=[];for(let d of s){if(!existsSync(d))continue;let a=N(d);try{let u=or(eq(n.thread_id,t),and(isNull(n.thread_id),like(n.command,`%--thread=${t}%`))),c=e?and(u,eq(n.workspace_id,e)):u,l=a.db.select().from(n).where(c).orderBy(asc(n.started_at)).all();for(let g of l)o.has(g.id)||(o.add(g.id),i.push(g));}catch(u){throw new _("DB_ERROR","Failed to find tasks by thread",u)}finally{a.close();}}return i}parseWorkflowCardMetadata(t){if(!t)return {};try{let e=JSON.parse(t);return {kind:typeof e.kind=="string"?e.kind:void 0,workflowRunId:typeof e.workflowRunId=="string"?e.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 e of this.resolveDbPaths()){if(!existsSync(e))continue;let s=N(e);try{t.push(...s.db.select({id:n.id,agent_id:n.agent_id,thread_id:n.thread_id,workspace_id:n.workspace_id,platform:n.platform,status:n.status,error:n.error,completed_at:n.completed_at,duration_ms:n.duration_ms,started_at:n.started_at,metadata:n.metadata}).from(n).where(and(eq(n.platform,"workflow"),or(like(n.metadata,'%"kind":"workflow_card"%'),like(n.metadata,'%"kind":"workflow_ui_instance"%')))).orderBy(desc(n.started_at)).all());}catch(o){throw new _("DB_ERROR","Failed to find workflow parent tasks",o)}finally{s.close();}}return t}batchFetchWorkflowCards(t,e){let s=new Map;if(t.length===0)return s;let o=new Set(t),i=new Map,d=e?eq(n.workspace_id,e):void 0,a=(u,c)=>{if(!u)return;let l=i.get(u);if(l&&c.started_at<=l)return;let g=this.parseWorkflowCardMetadata(c.metadata);g.kind!=="workflow_card"&&g.kind!=="workflow_ui_instance"||(i.set(u,c.started_at),s.set(u,{taskId:c.id,workflowRunId:g.workflowRunId,raw:c.result??void 0}));};for(let u of this.resolveDbPaths()){if(!existsSync(u))continue;let c=N(u);try{let l=and(inArray(n.thread_id,t),or(like(n.metadata,'%"kind":"workflow_card"%'),like(n.metadata,'%"kind":"workflow_ui_instance"%'))),g=c.db.select({id:n.id,thread_id:n.thread_id,metadata:n.metadata,result:n.result,started_at:n.started_at}).from(n).where(d?and(l,d):l).all();for(let L of g)a(L.thread_id,L);let f=and(isNull(n.thread_id),or(like(n.metadata,'%"kind":"workflow_card"%'),like(n.metadata,'%"kind":"workflow_ui_instance"%'))),w=c.db.select({id:n.id,command:n.command,metadata:n.metadata,result:n.result,started_at:n.started_at}).from(n).where(d?and(f,d):f).all();for(let L of w){let O=this.extractThreadIdFromCommand(L.command);!O||!o.has(O)||a(O,L);}}catch(l){throw new _("DB_ERROR","Failed to batch fetch workflow cards",l)}finally{c.close();}}return s}findAllTasks(t){if(!this.dbExists())return {rows:[],total:0};let e=this.openHandle(false);try{let s=[];t.workspaceId&&s.push(eq(n.workspace_id,t.workspaceId));let o=t.agents&&t.agents.length>0?t.agents:t.agentId?[t.agentId]:null;o&&s.push(inArray(n.agent_id,o));let i=t.statuses&&t.statuses.length>0?t.statuses:t.status?[t.status]:null;i&&s.push(inArray(n.status,i));let d=t.q??t.search;d&&s.push(like(n.prompt,`%${d}%`)),t.from&&s.push(gte(n.started_at,t.from)),t.to&&s.push(lt(n.started_at,t.to));let a=s.length>0?and(...s):void 0,u=e.db.select({count:sql`count(*)`}).from(n).where(a).get(),c=(t.sortDir??"DESC")==="ASC"?asc(n.started_at):desc(n.started_at);return {rows:e.db.select().from(n).where(a).orderBy(c).limit(t.limit).offset(t.offset).all(),total:u?.count??0}}catch(s){throw new _("DB_ERROR","Failed to find all tasks",s)}finally{e.close();}}getAgentUsage(t,e,s){if(!this.dbExists())return [];let o=this.openHandle(false);try{return o.db.all(s?sql`
|
|
38
78
|
SELECT
|
|
39
79
|
t.agent_id,
|
|
40
80
|
t.workspace_id,
|
|
@@ -42,11 +82,11 @@ ${s.join(`
|
|
|
42
82
|
COALESCE(SUM(
|
|
43
83
|
COALESCE(t.input_tokens, 0)
|
|
44
84
|
+ CASE
|
|
45
|
-
WHEN t.started_at >= ${
|
|
85
|
+
WHEN t.started_at >= ${st}
|
|
46
86
|
AND (
|
|
47
87
|
t.crewx_version IS NULL
|
|
48
88
|
OR (t.crewx_version LIKE '0.8.%' AND t.crewx_version NOT LIKE '0.8.9%')
|
|
49
|
-
OR (t.crewx_version LIKE '0.8.9-rc.%' AND CAST(SUBSTR(t.crewx_version, ${
|
|
89
|
+
OR (t.crewx_version LIKE '0.8.9-rc.%' AND CAST(SUBSTR(t.crewx_version, ${rt}) AS INTEGER) < ${ot})
|
|
50
90
|
)
|
|
51
91
|
THEN COALESCE(t.cached_input_tokens, 0)
|
|
52
92
|
ELSE 0
|
|
@@ -65,11 +105,11 @@ ${s.join(`
|
|
|
65
105
|
COALESCE(SUM(
|
|
66
106
|
COALESCE(t.input_tokens, 0)
|
|
67
107
|
+ CASE
|
|
68
|
-
WHEN t.started_at >= ${
|
|
108
|
+
WHEN t.started_at >= ${st}
|
|
69
109
|
AND (
|
|
70
110
|
t.crewx_version IS NULL
|
|
71
111
|
OR (t.crewx_version LIKE '0.8.%' AND t.crewx_version NOT LIKE '0.8.9%')
|
|
72
|
-
OR (t.crewx_version LIKE '0.8.9-rc.%' AND CAST(SUBSTR(t.crewx_version, ${
|
|
112
|
+
OR (t.crewx_version LIKE '0.8.9-rc.%' AND CAST(SUBSTR(t.crewx_version, ${rt}) AS INTEGER) < ${ot})
|
|
73
113
|
)
|
|
74
114
|
THEN COALESCE(t.cached_input_tokens, 0)
|
|
75
115
|
ELSE 0
|
|
@@ -85,11 +125,11 @@ ${s.join(`
|
|
|
85
125
|
COALESCE(SUM(
|
|
86
126
|
COALESCE(t.input_tokens, 0)
|
|
87
127
|
+ CASE
|
|
88
|
-
WHEN t.started_at >= ${
|
|
128
|
+
WHEN t.started_at >= ${st}
|
|
89
129
|
AND (
|
|
90
130
|
t.crewx_version IS NULL
|
|
91
131
|
OR (t.crewx_version LIKE '0.8.%' AND t.crewx_version NOT LIKE '0.8.9%')
|
|
92
|
-
OR (t.crewx_version LIKE '0.8.9-rc.%' AND CAST(SUBSTR(t.crewx_version, ${
|
|
132
|
+
OR (t.crewx_version LIKE '0.8.9-rc.%' AND CAST(SUBSTR(t.crewx_version, ${rt}) AS INTEGER) < ${ot})
|
|
93
133
|
)
|
|
94
134
|
THEN COALESCE(t.cached_input_tokens, 0)
|
|
95
135
|
ELSE 0
|
|
@@ -107,11 +147,11 @@ ${s.join(`
|
|
|
107
147
|
COALESCE(SUM(
|
|
108
148
|
COALESCE(t.input_tokens, 0)
|
|
109
149
|
+ CASE
|
|
110
|
-
WHEN t.started_at >= ${
|
|
150
|
+
WHEN t.started_at >= ${st}
|
|
111
151
|
AND (
|
|
112
152
|
t.crewx_version IS NULL
|
|
113
153
|
OR (t.crewx_version LIKE '0.8.%' AND t.crewx_version NOT LIKE '0.8.9%')
|
|
114
|
-
OR (t.crewx_version LIKE '0.8.9-rc.%' AND CAST(SUBSTR(t.crewx_version, ${
|
|
154
|
+
OR (t.crewx_version LIKE '0.8.9-rc.%' AND CAST(SUBSTR(t.crewx_version, ${rt}) AS INTEGER) < ${ot})
|
|
115
155
|
)
|
|
116
156
|
THEN COALESCE(t.cached_input_tokens, 0)
|
|
117
157
|
ELSE 0
|
|
@@ -119,18 +159,18 @@ ${s.join(`
|
|
|
119
159
|
), 0)
|
|
120
160
|
+ COALESCE(SUM(t.output_tokens), 0)
|
|
121
161
|
) DESC
|
|
122
|
-
`).map(
|
|
162
|
+
`).map(d=>({agentId:d.agent_id,workspaceId:d.workspace_id??null,totalTasks:d.total_tasks,inputTokens:d.input_tokens,outputTokens:d.output_tokens,cachedInputTokens:d.cached_input_tokens,costUsd:d.cost_usd,totalTokens:d.input_tokens+d.output_tokens}))}catch(i){throw new _("DB_ERROR","Failed to get agent usage",i)}finally{o.close();}}getAgentUsageTrendRaw(t,e,s){if(!this.dbExists())return [];let o=this.openHandle(false);try{return o.db.all(s?sql`
|
|
123
163
|
SELECT
|
|
124
164
|
date(t.started_at) AS date,
|
|
125
165
|
t.agent_id,
|
|
126
166
|
COALESCE(SUM(
|
|
127
167
|
COALESCE(t.input_tokens, 0)
|
|
128
168
|
+ CASE
|
|
129
|
-
WHEN t.started_at >= ${
|
|
169
|
+
WHEN t.started_at >= ${st}
|
|
130
170
|
AND (
|
|
131
171
|
t.crewx_version IS NULL
|
|
132
172
|
OR (t.crewx_version LIKE '0.8.%' AND t.crewx_version NOT LIKE '0.8.9%')
|
|
133
|
-
OR (t.crewx_version LIKE '0.8.9-rc.%' AND CAST(SUBSTR(t.crewx_version, ${
|
|
173
|
+
OR (t.crewx_version LIKE '0.8.9-rc.%' AND CAST(SUBSTR(t.crewx_version, ${rt}) AS INTEGER) < ${ot})
|
|
134
174
|
)
|
|
135
175
|
THEN COALESCE(t.cached_input_tokens, 0)
|
|
136
176
|
ELSE 0
|
|
@@ -153,11 +193,11 @@ ${s.join(`
|
|
|
153
193
|
COALESCE(SUM(
|
|
154
194
|
COALESCE(t.input_tokens, 0)
|
|
155
195
|
+ CASE
|
|
156
|
-
WHEN t.started_at >= ${
|
|
196
|
+
WHEN t.started_at >= ${st}
|
|
157
197
|
AND (
|
|
158
198
|
t.crewx_version IS NULL
|
|
159
199
|
OR (t.crewx_version LIKE '0.8.%' AND t.crewx_version NOT LIKE '0.8.9%')
|
|
160
|
-
OR (t.crewx_version LIKE '0.8.9-rc.%' AND CAST(SUBSTR(t.crewx_version, ${
|
|
200
|
+
OR (t.crewx_version LIKE '0.8.9-rc.%' AND CAST(SUBSTR(t.crewx_version, ${rt}) AS INTEGER) < ${ot})
|
|
161
201
|
)
|
|
162
202
|
THEN COALESCE(t.cached_input_tokens, 0)
|
|
163
203
|
ELSE 0
|
|
@@ -172,51 +212,98 @@ ${s.join(`
|
|
|
172
212
|
AND t.started_at < ${e}
|
|
173
213
|
GROUP BY date(t.started_at), t.agent_id
|
|
174
214
|
ORDER BY date(t.started_at) ASC
|
|
175
|
-
`).map(
|
|
176
|
-
|
|
177
|
-
WHEN ${o.model} LIKE 'claude-%' OR ${o.model} IN ('opus', 'sonnet', 'haiku', 'opus[1m]', 'sonnet[1m]') THEN 'claude'
|
|
178
|
-
WHEN ${o.model} LIKE 'gpt-%' OR ${o.model} LIKE 'codex-%' THEN 'codex'
|
|
179
|
-
WHEN ${o.model} LIKE 'gemini-%' THEN 'gemini'
|
|
180
|
-
WHEN ${o.model} LIKE 'zai-%' OR ${o.model} LIKE 'openrouter/z-ai/%' THEN 'opencode'
|
|
181
|
-
WHEN ${o.model} LIKE 'minimax/%' THEN 'minimax'
|
|
182
|
-
WHEN ${o.model} LIKE 'qwen%' THEN 'qwen'
|
|
183
|
-
ELSE 'unknown'
|
|
184
|
-
END
|
|
185
|
-
`,i=sql`
|
|
186
|
-
COALESCE(${o.input_tokens}, 0)
|
|
215
|
+
`).map(d=>({date:d.date,agentId:d.agent_id,inputTokens:d.input_tokens,outputTokens:d.output_tokens,cachedInputTokens:d.cached_input_tokens,costUsd:d.cost_usd,totalTokens:d.input_tokens+d.output_tokens}))}catch(i){throw new _("DB_ERROR","Failed to get agent usage trend",i)}finally{o.close();}}findTaskForStop(t,e){if(!this.dbExists())return;let s=this.openHandle(false);try{return s.db.select().from(n).where(and(eq(n.id,t),eq(n.workspace_id,e))).limit(1).get()??void 0}catch(o){throw new _("DB_ERROR","Failed to find task for stop",o)}finally{s.close();}}findLatestTaskByMetadata(t){if(!this.dbExists())return null;let e=this.openHandle(false);try{return e.db.select({id:n.id,thread_id:n.thread_id,status:n.status,result:n.result,error:n.error,started_at:n.started_at,completed_at:n.completed_at,metadata:n.metadata}).from(n).where(and(eq(n.agent_id,t.agentId),eq(n.workspace_id,t.workspaceId),sql`${n.metadata} IS NOT NULL AND json_valid(${n.metadata}) AND json_extract(${n.metadata}, '$.' || ${t.metaKey}) = ${t.metaValue}`)).orderBy(desc(n.started_at)).limit(1).get()??null}catch(s){throw new _("DB_ERROR","Failed to find latest task by metadata",s)}finally{e.close();}}markTaskFailed(t,e,s){if(!this.dbExists())return;let o=this.openHandle(true);try{let i=new Date().toISOString(),d=s?and(eq(n.id,t),eq(n.status,"running"),eq(n.workspace_id,s)):and(eq(n.id,t),eq(n.status,"running"));o.db.update(n).set({status:"failed",error:e,completed_at:i}).where(d).run();}catch(i){throw i instanceof _?i:new _("DB_ERROR","Failed to mark task failed",i)}finally{o.close();}}findTasksByPromptHint(t,e){let s=this.resolveDbPaths(),o=new Set,i=[];for(let d of s){if(!existsSync(d))continue;let a=N(d);try{let u=e?and(like(n.prompt,`%${t}%`),eq(n.workspace_id,e)):like(n.prompt,`%${t}%`),c=a.db.select().from(n).where(u).orderBy(asc(n.started_at)).all();for(let l of c)o.has(l.id)||(o.add(l.id),i.push(l));}catch(u){throw new _("DB_ERROR","Failed to find tasks by prompt hint",u)}finally{a.close();}}return i}getProviderUsage(t,e,s){if(!this.dbExists())return [];let o=this.openHandle(false);try{let i=we(),d=sql`
|
|
216
|
+
COALESCE(${n.input_tokens}, 0)
|
|
187
217
|
+ CASE
|
|
188
|
-
WHEN ${
|
|
218
|
+
WHEN ${n.started_at} >= ${st}
|
|
189
219
|
AND (
|
|
190
|
-
${
|
|
191
|
-
OR (${
|
|
192
|
-
OR (${
|
|
220
|
+
${n.crewx_version} IS NULL
|
|
221
|
+
OR (${n.crewx_version} LIKE '0.8.%' AND ${n.crewx_version} NOT LIKE '0.8.9%')
|
|
222
|
+
OR (${n.crewx_version} LIKE '0.8.9-rc.%' AND CAST(SUBSTR(${n.crewx_version}, ${rt}) AS INTEGER) < ${ot})
|
|
193
223
|
)
|
|
194
|
-
THEN COALESCE(${
|
|
224
|
+
THEN COALESCE(${n.cached_input_tokens}, 0)
|
|
195
225
|
ELSE 0
|
|
196
226
|
END
|
|
197
|
-
`,a=s?sql`WHERE ${
|
|
227
|
+
`,a=s?sql`WHERE ${n.status} IN ('completed', 'success') AND ${n.started_at} >= ${t} AND ${n.started_at} < ${e} AND ${n.workspace_id} = ${s}`:sql`WHERE ${n.status} IN ('completed', 'success') AND ${n.started_at} >= ${t} AND ${n.started_at} < ${e}`;return o.db.all(sql`
|
|
198
228
|
SELECT
|
|
199
|
-
${
|
|
229
|
+
${i} AS provider,
|
|
200
230
|
COUNT(*) AS total_tasks,
|
|
201
|
-
COALESCE(SUM(${
|
|
202
|
-
COALESCE(SUM(${
|
|
203
|
-
COALESCE(SUM(${
|
|
204
|
-
COALESCE(SUM(${
|
|
205
|
-
COALESCE(SUM(${
|
|
206
|
-
MAX(${
|
|
207
|
-
FROM ${
|
|
231
|
+
COALESCE(SUM(${d}), 0) AS input_tokens,
|
|
232
|
+
COALESCE(SUM(${n.output_tokens}), 0) AS output_tokens,
|
|
233
|
+
COALESCE(SUM(${n.cached_input_tokens}), 0) AS cached_input_tokens,
|
|
234
|
+
COALESCE(SUM(${n.cost_usd}), 0) AS cost_usd,
|
|
235
|
+
COALESCE(SUM(${n.duration_ms}), 0) AS active_duration_ms,
|
|
236
|
+
MAX(${n.completed_at}) AS last_active_at
|
|
237
|
+
FROM ${n}
|
|
238
|
+
${a}
|
|
239
|
+
GROUP BY ${i}
|
|
240
|
+
ORDER BY (COALESCE(SUM(${d}), 0) + COALESCE(SUM(${n.output_tokens}), 0)) DESC
|
|
241
|
+
`).map(c=>({provider:c.provider,totalTasks:c.total_tasks,inputTokens:c.input_tokens,outputTokens:c.output_tokens,cachedInputTokens:c.cached_input_tokens,costUsd:c.cost_usd,totalTokens:c.input_tokens+c.output_tokens,activeDurationMs:c.active_duration_ms??0,lastActiveAt:c.last_active_at??null}))}catch(i){throw new _("DB_ERROR","Failed to get provider usage",i)}finally{o.close();}}getModelUsage(t,e,s){if(!this.dbExists())return [];let o=this.openHandle(false);try{let i=we(),d=sql`
|
|
242
|
+
COALESCE(${n.input_tokens}, 0)
|
|
243
|
+
+ CASE
|
|
244
|
+
WHEN ${n.started_at} >= ${st}
|
|
245
|
+
AND (
|
|
246
|
+
${n.crewx_version} IS NULL
|
|
247
|
+
OR (${n.crewx_version} LIKE '0.8.%' AND ${n.crewx_version} NOT LIKE '0.8.9%')
|
|
248
|
+
OR (${n.crewx_version} LIKE '0.8.9-rc.%' AND CAST(SUBSTR(${n.crewx_version}, ${rt}) AS INTEGER) < ${ot})
|
|
249
|
+
)
|
|
250
|
+
THEN COALESCE(${n.cached_input_tokens}, 0)
|
|
251
|
+
ELSE 0
|
|
252
|
+
END
|
|
253
|
+
`,a=s?sql`WHERE ${n.status} IN ('completed', 'success') AND ${n.started_at} >= ${t} AND ${n.started_at} < ${e} AND ${n.workspace_id} = ${s}`:sql`WHERE ${n.status} IN ('completed', 'success') AND ${n.started_at} >= ${t} AND ${n.started_at} < ${e}`,u=o.db.all(sql`
|
|
254
|
+
SELECT
|
|
255
|
+
${n.model} AS model,
|
|
256
|
+
${i} AS provider,
|
|
257
|
+
COUNT(*) AS total_tasks,
|
|
258
|
+
COALESCE(SUM(${d}), 0) AS input_tokens,
|
|
259
|
+
COALESCE(SUM(${n.output_tokens}), 0) AS output_tokens,
|
|
260
|
+
COALESCE(SUM(${n.cached_input_tokens}), 0) AS cached_input_tokens,
|
|
261
|
+
COALESCE(SUM(${n.cost_usd}), 0) AS cost_usd,
|
|
262
|
+
COALESCE(SUM(${n.duration_ms}), 0) AS active_duration_ms,
|
|
263
|
+
MAX(${n.completed_at}) AS last_active_at
|
|
264
|
+
FROM ${n}
|
|
208
265
|
${a}
|
|
209
|
-
GROUP BY
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
266
|
+
GROUP BY ${n.model}, ${i}
|
|
267
|
+
`),c=new Map;for(let l of u){let g=_e(l.model??""),f=JSON.stringify([l.provider,g]),w=c.get(f);w?(w.totalTasks+=l.total_tasks,w.inputTokens+=l.input_tokens,w.outputTokens+=l.output_tokens,w.cachedInputTokens+=l.cached_input_tokens,w.costUsd+=l.cost_usd,w.totalTokens+=l.input_tokens+l.output_tokens,w.activeDurationMs+=l.active_duration_ms??0,l.last_active_at&&(!w.lastActiveAt||l.last_active_at>w.lastActiveAt)&&(w.lastActiveAt=l.last_active_at)):c.set(f,{model:g,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});}return Array.from(c.values()).sort((l,g)=>g.costUsd-l.costUsd)}catch(i){throw new _("DB_ERROR","Failed to get model usage",i)}finally{o.close();}}getTasksForReport(t,e,s){if(!this.dbExists())return [];let o=this.openHandle(false);try{let i=s?sql`WHERE ${n.started_at} >= ${t} AND ${n.started_at} < ${e} AND ${n.workspace_id} = ${s}`:sql`WHERE ${n.started_at} >= ${t} AND ${n.started_at} < ${e}`;return o.db.all(sql`
|
|
268
|
+
SELECT
|
|
269
|
+
${n.thread_id} AS thread_id,
|
|
270
|
+
${n.agent_id} AS agent_id,
|
|
271
|
+
${n.started_at} AS started_at,
|
|
272
|
+
${n.status} AS status,
|
|
273
|
+
${n.error} AS error,
|
|
274
|
+
${n.exit_code} AS exit_code
|
|
275
|
+
FROM ${n}
|
|
276
|
+
${i}
|
|
277
|
+
ORDER BY ${n.started_at} ASC
|
|
278
|
+
`).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(i){throw new _("DB_ERROR","Failed to get tasks for report",i)}finally{o.close();}}getDelegationMatrix(t,e,s){if(!this.dbExists())return {edges:[],truncated:false};let o=this.openHandle(false);try{let i=sql`
|
|
279
|
+
COALESCE(${n.input_tokens}, 0)
|
|
280
|
+
+ CASE
|
|
281
|
+
WHEN ${n.started_at} >= ${st}
|
|
282
|
+
AND (
|
|
283
|
+
${n.crewx_version} IS NULL
|
|
284
|
+
OR (${n.crewx_version} LIKE '0.8.%' AND ${n.crewx_version} NOT LIKE '0.8.9%')
|
|
285
|
+
OR (${n.crewx_version} LIKE '0.8.9-rc.%' AND CAST(SUBSTR(${n.crewx_version}, ${rt}) AS INTEGER) < ${ot})
|
|
286
|
+
)
|
|
287
|
+
THEN COALESCE(${n.cached_input_tokens}, 0)
|
|
288
|
+
ELSE 0
|
|
289
|
+
END
|
|
290
|
+
`,d=s?sql`WHERE ${n.status} IN ('completed', 'success') AND ${n.started_at} >= ${t} AND ${n.started_at} < ${e} AND ${n.workspace_id} = ${s}`:sql`WHERE ${n.status} IN ('completed', 'success') AND ${n.started_at} >= ${t} AND ${n.started_at} < ${e}`,a=o.db.all(sql`
|
|
291
|
+
SELECT
|
|
292
|
+
${n.caller_agent_id} AS caller_agent_id,
|
|
293
|
+
${n.agent_id} AS agent_id,
|
|
294
|
+
COUNT(*) AS task_count,
|
|
295
|
+
COALESCE(SUM(${i}), 0) AS input_tokens,
|
|
296
|
+
COALESCE(SUM(${n.output_tokens}), 0) AS output_tokens
|
|
297
|
+
FROM ${n}
|
|
298
|
+
${d}
|
|
299
|
+
GROUP BY ${n.caller_agent_id}, ${n.agent_id}
|
|
300
|
+
ORDER BY task_count DESC, ${n.caller_agent_id} ASC, ${n.agent_id} ASC
|
|
301
|
+
LIMIT ${Ft+1}
|
|
302
|
+
`),u=a.length>Ft;return {edges:a.slice(0,Ft).map(l=>({callerAgentId:l.caller_agent_id??null,agentId:l.agent_id,taskCount:l.task_count,totalTokens:l.input_tokens+l.output_tokens,outputTokens:l.output_tokens})),truncated:u}}catch(i){throw new _("DB_ERROR","Failed to get delegation matrix",i)}finally{o.close();}}findTaskEvidence(t){if(!this.dbExists())return [];let e=this.openHandle(false);try{let s=[];t.workspaceId&&s.push(eq(n.workspace_id,t.workspaceId)),t.agents&&t.agents.length>0&&s.push(inArray(n.agent_id,t.agents)),t.statuses&&t.statuses.length>0&&s.push(inArray(n.status,t.statuses)),t.from&&s.push(gte(n.started_at,t.from)),t.to&&s.push(lt(n.started_at,t.to));let o=s.length>0?and(...s):void 0,i=(t.order??"DESC")==="ASC"?asc(n.started_at):desc(n.started_at),d={id:n.id,agent_id:n.agent_id,status:n.status,prompt:n.prompt,started_at:n.started_at,completed_at:n.completed_at,thread_id:n.thread_id};return t.limit?e.db.select(d).from(n).where(o).orderBy(i).limit(t.limit).all():e.db.select(d).from(n).where(o).orderBy(i).all()}catch(s){throw new _("DB_ERROR","Failed to find task evidence",s)}finally{e.close();}}findThreadChains(t){if(!this.dbExists())return [];let e=this.openHandle(false);try{let s=t.maxThreads??8,o=t.maxTurnsPerThread??4,i=[isNotNull(n.thread_id),isNull(n.parent_task_id),isNull(n.caller_agent_id),or(isNull(n.platform),ne(n.platform,"workflow")),or(isNull(n.metadata),and(notLike(n.metadata,'%"kind":"workflow_card"%'),notLike(n.metadata,'%"kind":"workflow_ui_instance"%'))),or(isNull(n.metadata),notLike(n.metadata,'%"retriedFromTaskId"%'))];t.workspaceId&&i.push(eq(n.workspace_id,t.workspaceId)),t.from&&i.push(gte(n.started_at,t.from)),t.to&&i.push(lt(n.started_at,t.to));let d=e.db.select({id:n.id,agent_id:n.agent_id,status:n.status,prompt:n.prompt,started_at:n.started_at,completed_at:n.completed_at,thread_id:n.thread_id}).from(n).where(and(...i)).orderBy(asc(n.started_at),asc(n.id)).all(),a=new Map;for(let c of d){if(!c.thread_id)continue;let l={id:c.id,agentId:c.agent_id,status:c.status,prompt:c.prompt,startedAt:c.started_at,completedAt:c.completed_at},g=a.get(c.thread_id);g?g.push(l):a.set(c.thread_id,[l]);}let u=[];for(let[c,l]of a){let g=l.filter(f=>f.agentId===t.targetAgentId).length;g<2||u.push({threadId:c,targetAgentTurnCount:g,turns:l});}return u.sort((c,l)=>{let g=c.turns[c.turns.length-1].startedAt,f=l.turns[l.turns.length-1].startedAt;return g<f?1:g>f?-1:0}),u.slice(0,s).map(c=>({threadId:c.threadId,targetAgentTurnCount:c.targetAgentTurnCount,turns:c.turns.slice(-o)}))}catch(s){throw new _("DB_ERROR","Failed to find thread chains",s)}finally{e.close();}}};var Wt=class extends it{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 Dt({dbPath:this.dbPath}),s=process.cwd(),i=existsSync(join(s,"crewx.yaml"))||existsSync(join(s,"crewx.yml"))?Qt(s):null,d=process.argv.join(" ");this.unsubs.push(t.on("task:start",a=>{try{let u=a.callerAgentId??null,c=a.parentTaskId??null,l=a.rootTraceId??a.traceId,g=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:d,codingAgentCommand:a.codingAgentCommand??null,workspaceId:a.workspaceId??i,projectId:a.projectId??null,callerAgentId:u,parentTaskId:c,traceId:l,metadata:g,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{let u=typeof a.metadata?.runEpoch=="number"?a.metadata.runEpoch:null,c=a.error?JSON.stringify({code:a.error.code,message:a.error.message,...a.error.providerCode?{providerCode:a.error.providerCode}:{}}):null;e.finishTask({id:a.traceId,status:a.error?"failed":"success",result:a.result??null,error:c,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:u});}catch{}}));}detach(t){this.unsubs.forEach(e=>e()),this.unsubs=[];}};var Lt=class extends at{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 _("NOT_FOUND","Database not found");let s=N(e);if(t)try{pt(s.db,e);}catch(o){throw s.close(),o}return s}validateWorkspaceId(t,e){return t.db.select({id:gt.id}).from(gt).where(eq(gt.id,e)).limit(1).get()?e:null}topLevelTaskPredicateSql(t="child"){return sql.raw(`NOT EXISTS (
|
|
303
|
+
SELECT 1 FROM tasks parent
|
|
304
|
+
WHERE parent.id = ${t}.parent_task_id
|
|
305
|
+
AND parent.thread_id = ${t}.thread_id
|
|
306
|
+
)`)}findAllThreads(t){let e=this.resolveDbPaths(),s=new Set,o=[];for(let i of e){if(!existsSync(i))continue;let d=N(i);try{let a=t?eq(p.workspace_id,t):void 0,u=d.db.select().from(p).where(a).orderBy(desc(p.updated_at)).all();for(let c of u)s.has(c.id)||(s.add(c.id),o.push(c));}catch(a){throw new _("DB_ERROR","Failed to find all threads",a)}finally{d.close();}}return o}findThreadsByIdsOrTitles(t,e){if(t.length===0)return [];let s=this.resolveDbPaths(),o=new Set,i=[];for(let d of s){if(!existsSync(d))continue;let a=N(d);try{let u=or(inArray(p.id,t),inArray(p.title,t)),c=e?and(u,eq(p.workspace_id,e)):u,l=a.db.select().from(p).where(c).orderBy(desc(p.updated_at)).all();for(let g of l)o.has(g.id)||(o.add(g.id),i.push(g));}catch(u){throw new _("DB_ERROR","Failed to find threads by ids or titles",u)}finally{a.close();}}return i}findThreadById(t,e){let s=this.resolveDbPaths();for(let o of s){if(!existsSync(o))continue;let i=N(o);try{let d=eq(p.id,t),a=e?and(d,eq(p.workspace_id,e)):d,u=i.db.select().from(p).where(a).limit(1).get()??void 0;if(u)return u}catch(d){throw new _("DB_ERROR","Failed to find thread by id",d)}finally{i.close();}}}threadExists(t,e){let s=this.resolveDbPaths();for(let o of s){if(!existsSync(o))continue;let i=N(o);try{let d=eq(p.id,t),a=e?and(d,eq(p.workspace_id,e)):d;if(i.db.select({id:p.id}).from(p).where(a).limit(1).get())return !0}catch(d){throw new _("DB_ERROR","Failed to check thread existence",d)}finally{i.close();}}return false}aggregateTaskStats(t,e){let s=this.resolveDbPaths(),o=0,i=0,d=0,a=0,u=0,c=new Set;for(let l of s){if(!existsSync(l))continue;let g=N(l);try{let f=g.db.get(sql`
|
|
220
307
|
SELECT
|
|
221
308
|
count(*) AS cnt,
|
|
222
309
|
COALESCE(SUM(child.input_tokens), 0) AS total_input,
|
|
@@ -227,13 +314,13 @@ ${s.join(`
|
|
|
227
314
|
WHERE child.thread_id = ${t}
|
|
228
315
|
AND ${this.topLevelTaskPredicateSql()}
|
|
229
316
|
${e?sql`AND child.workspace_id = ${e}`:sql``}
|
|
230
|
-
`);
|
|
317
|
+
`);f&&(o+=f.cnt,i+=f.total_input,d+=f.total_output,a+=f.total_cached,u+=f.total_cost);let w=g.db.all(sql`
|
|
231
318
|
SELECT DISTINCT child.agent_id FROM tasks child
|
|
232
319
|
WHERE child.thread_id = ${t}
|
|
233
320
|
AND child.agent_id IS NOT NULL AND child.agent_id != ''
|
|
234
321
|
AND ${this.topLevelTaskPredicateSql()}
|
|
235
322
|
${e?sql`AND child.workspace_id = ${e}`:sql``}
|
|
236
|
-
`);for(let
|
|
323
|
+
`);for(let L of w)c.add(L.agent_id);}catch(f){throw new _("DB_ERROR","Failed to aggregate task stats",f)}finally{g.close();}}return {taskCount:o,inputTokens:i,outputTokens:d,cachedInputTokens:a,costUsd:u,agentIds:Array.from(c)}}findTopLevelTasks(t,e,s){let o=this.resolveDbPaths(),i=new Set,d=[];for(let a of o){if(!existsSync(a))continue;let u=N(a);try{let c;s!==void 0?c=u.db.all(sql`
|
|
237
324
|
SELECT * FROM (
|
|
238
325
|
SELECT child.*,
|
|
239
326
|
ROW_NUMBER() OVER (PARTITION BY child.agent_id ORDER BY child.started_at DESC) AS rn
|
|
@@ -244,28 +331,32 @@ ${s.join(`
|
|
|
244
331
|
) ranked
|
|
245
332
|
WHERE rn <= ${s}
|
|
246
333
|
ORDER BY started_at ASC
|
|
247
|
-
`):c=
|
|
334
|
+
`):c=u.db.all(sql`
|
|
248
335
|
SELECT child.* FROM tasks child
|
|
249
336
|
WHERE child.thread_id = ${t}
|
|
250
337
|
AND ${this.topLevelTaskPredicateSql()}
|
|
251
338
|
${e?sql`AND child.workspace_id = ${e}`:sql``}
|
|
252
339
|
ORDER BY child.started_at ASC
|
|
253
|
-
`);for(let
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
340
|
+
`);for(let l of c)i.has(l.id)||(i.add(l.id),d.push(l));}catch(c){throw new _("DB_ERROR","Failed to find top-level tasks",c)}finally{u.close();}}if(s!==void 0&&o.length>1){let a=new Map;for(let u of d){let c=u.agent_id??"";a.has(c)||a.set(c,[]),a.get(c).push(u);}d=[];for(let u of a.values())u.sort((c,l)=>(l.started_at??"").localeCompare(c.started_at??"")),d.push(...u.slice(0,s));d.sort((u,c)=>(u.started_at??"").localeCompare(c.started_at??""));}return d}findAllTasks(t,e){let s=this.resolveDbPaths(),o=new Set,i=[];for(let d of s){if(!existsSync(d))continue;let a=N(d);try{let u=eq(n.thread_id,t),c=e?and(u,eq(n.workspace_id,e)):u,l=a.db.select().from(n).where(c).orderBy(asc(n.started_at)).all();for(let g of l)o.has(g.id)||(o.add(g.id),i.push(g));}catch(u){throw new _("DB_ERROR","Failed to find all tasks for thread",u)}finally{a.close();}}return i}findTaskById(t,e,s){let o=this.resolveDbPaths();for(let i of o){if(!existsSync(i))continue;let d=N(i);try{let a=and(eq(n.id,e),eq(n.thread_id,t)),u=s?and(a,eq(n.workspace_id,s)):a,c=d.db.select().from(n).where(u).limit(1).get();if(!c)continue;let l=d.db.select().from(n).where(eq(n.parent_task_id,c.id)).orderBy(asc(n.started_at)).all();return {task:c,children:l}}catch(a){throw new _("DB_ERROR","Failed to find task by id",a)}finally{d.close();}}}batchFetchTasksQuery(t,e){return sql`
|
|
341
|
+
SELECT child.id, child.thread_id, child.agent_id, child.status,
|
|
342
|
+
child.parent_task_id, child.started_at, child.completed_at,
|
|
343
|
+
child.duration_ms, child.input_tokens, child.output_tokens,
|
|
344
|
+
child.cost_usd, child.error
|
|
345
|
+
FROM tasks child INDEXED BY idx_tasks_thread_id
|
|
346
|
+
WHERE child.thread_id IN (${sql.join(t.map(s=>sql`${s}`),sql`, `)})
|
|
347
|
+
AND ${this.topLevelTaskPredicateSql()}
|
|
348
|
+
${e?sql`AND child.workspace_id = ${e}`:sql``}
|
|
349
|
+
ORDER BY child.started_at ASC
|
|
350
|
+
`}batchFetchTasks(t,e){let s=new Map;if(t.length===0)return s;let o=this.resolveDbPaths();for(let i of o){if(!existsSync(i))continue;let d=N(i);try{let a=d.db.all(this.batchFetchTasksQuery(t,e));for(let u of a){let c=u.thread_id;s.has(c)||s.set(c,[]),s.get(c).push(u);}}catch(a){throw new _("DB_ERROR","Failed to batch fetch tasks",a)}finally{d.close();}}return s}explainBatchFetchTasksPlan(t,e){let s=this.resolveDbPaths();for(let o of s){if(!existsSync(o))continue;let i=N(o);try{return i.db.all(sql`EXPLAIN QUERY PLAN ${this.batchFetchTasksQuery(t,e)}`).map(a=>a.detail)}finally{i.close();}}return []}updateThreadTitle(t,e,s){if(!this.dbExists())return;let o=this.openHandle(true);try{let i=eq(p.id,t),d=s?and(i,eq(p.workspace_id,s)):i;if(!o.db.select({id:p.id}).from(p).where(d).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(i){throw i instanceof _?i:new _("DB_ERROR","Failed to update thread title",i)}finally{o.close();}}upsertThread(t,e){let s=this.openHandle(true);try{let o=e.workspaceId?this.validateWorkspaceId(s,e.workspaceId):null,i=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:i};e.title!==void 0&&(a.title=e.title),e.titleLocked!==void 0&&(a.title_locked=e.titleLocked?1:0),s.db.update(p).set(a).where(eq(p.id,t)).run();}else s.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:i,updated_at:i}).run();}catch(o){throw o instanceof _?o:new _("DB_ERROR","Failed to upsert thread",o)}finally{s.close();}}ensureThread(t,e,s){let o=this.openHandle(true);try{let i=s?this.validateWorkspaceId(o,s):null,d=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(d){i&&!d.workspace_id&&o.db.update(p).set({workspace_id:i}).where(eq(p.id,t)).run();return}let a=new Date().toISOString();o.db.insert(p).values({id:t,platform:e,workspace_id:i,message_count:0,created_at:a,updated_at:a}).run();}catch(i){throw i instanceof _?i:new _("DB_ERROR","Failed to ensure thread",i)}finally{o.close();}}saveUserMessage(t,e,s){if(!this.dbExists())return {firstMessage:false};let o=this.openHandle(true);try{let i=new Date().toISOString();return {firstMessage:o.db.transaction(a=>{let c=a.select({message_count:p.message_count}).from(p).where(eq(p.id,t)).limit(1).get()?.message_count===0;return a.run(sql`
|
|
260
351
|
UPDATE threads
|
|
261
352
|
SET first_message = COALESCE(first_message, ${e}),
|
|
262
353
|
title = CASE WHEN title_locked = 0 AND title IS NULL THEN substr(${e}, 1, 60) ELSE title END,
|
|
263
354
|
last_message = ${e},
|
|
264
355
|
message_count = message_count + 1,
|
|
265
|
-
updated_at = ${
|
|
356
|
+
updated_at = ${i}
|
|
266
357
|
WHERE id = ${t}
|
|
267
|
-
`),c},{behavior:"immediate"})}}catch(
|
|
268
|
-
`).filter(
|
|
269
|
-
`).trim()}function
|
|
270
|
-
`):e&&typeof e=="object"&&e.result!==void 0&&(t=e.result||"");}catch{t=
|
|
271
|
-
`)[0].slice(0,200)),e.push({id:`${s.id}-assistant`,text:
|
|
358
|
+
`),c},{behavior:"immediate"})}}catch(i){throw i instanceof _?i:new _("DB_ERROR","Failed to save user message",i)}finally{o.close();}}saveAssistantMessage(t,e,s){if(!this.dbExists())return;let o=this.openHandle(true);try{let i=new Date().toISOString();o.db.update(p).set({last_message:e,updated_at:i}).where(eq(p.id,t)).run();}catch(i){throw i instanceof _?i:new _("DB_ERROR","Failed to save assistant message",i)}finally{o.close();}}updateThread(t,e){if(!this.dbExists())return;let s=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),s.db.update(p).set(o).where(eq(p.id,t)).run();}catch(o){throw o instanceof _?o:new _("DB_ERROR","Failed to update thread",o)}finally{s.close();}}togglePin(t,e){let s=this.openHandle(true);try{let o=e?and(eq(p.id,t),eq(p.workspace_id,e)):eq(p.id,t),i=s.db.select({pinned:p.pinned,metadata:p.metadata}).from(p).where(o).get();if(!i)return null;let d=i.pinned?0:1,a=i.metadata?JSON.parse(i.metadata):{};if(d){let u=e?and(eq(p.pinned,1),eq(p.workspace_id,e)):eq(p.pinned,1),c=s.db.select({metadata:p.metadata}).from(p).where(u).all(),l=null;for(let g of c){let f=g.metadata?JSON.parse(g.metadata):{};typeof f.pinOrder=="number"&&(l===null||f.pinOrder<l)&&(l=f.pinOrder);}a.pinOrder=l===null?0:l-1;}else delete a.pinOrder;return s.db.update(p).set({pinned:d,metadata:Object.keys(a).length>0?JSON.stringify(a):null}).where(o).run(),{pinned:!!d}}catch(o){throw o instanceof _?o:new _("DB_ERROR","Failed to toggle pin",o)}finally{s.close();}}reorderPins(t,e){let s=this.openHandle(true);try{for(let o=0;o<t.length;o++){let i=e?and(eq(p.id,t[o]),eq(p.workspace_id,e)):eq(p.id,t[o]),d=s.db.select({metadata:p.metadata}).from(p).where(i).get();if(!d)continue;let a=d.metadata?JSON.parse(d.metadata):{};a.pinOrder=o+1,s.db.update(p).set({metadata:JSON.stringify(a)}).where(i).run();}}catch(o){throw o instanceof _?o:new _("DB_ERROR","Failed to reorder pins",o)}finally{s.close();}}toggleStar(t,e){let s=this.openHandle(true);try{let o=e?and(eq(p.id,t),eq(p.workspace_id,e)):eq(p.id,t),i=s.db.select({starred:p.starred}).from(p).where(o).get();if(!i)return null;let d=i.starred?0:1;return s.db.update(p).set({starred:d}).where(o).run(),{starred:!!d}}catch(o){throw o instanceof _?o:new _("DB_ERROR","Failed to toggle star",o)}finally{s.close();}}resolveOverdriveForRequest(t,e,s,o){let d=this.openHandle(true);try{let a=e?and(eq(p.id,t),eq(p.workspace_id,e)):eq(p.id,t);return d.db.transaction(c=>{let l=c.select({metadata:p.metadata}).from(p).where(a).get();if(!l)return null;let g=l.metadata?JSON.parse(l.metadata):{},f=g.overdrive??{},w=o?.defaultTurns??f.defaultTurns??3,L=o?.updatedBy??"ui",O=new Date().toISOString(),q,z,V,ft;switch(s){case "enable-count":{let mt=o?.turns??w,ht=o?.consumeCurrent?Math.max(mt-1,0):mt;q=ht>0?"count":"off",z=ht,V=!0,ft="count";break}case "enable-latch":{q="latch",z=0,V=!0,ft="latch";break}case "disable":{q="off",z=0,V=!1;break}default:{let mt=f.state??"off",ht=typeof f.remaining=="number"?f.remaining:0;if(mt==="count"&&ht>0){let Gt=ht-1;Gt<=0?(q="off",z=0):(q="count",z=Gt),V=!0,ft="count";}else mt==="latch"?(q="latch",z=0,V=!0,ft="latch"):(q="off",z=0,V=!1);break}}return g.overdrive={state:q,remaining:z,defaultTurns:w,updatedAt:O,updatedBy:L},c.update(p).set({metadata:JSON.stringify(g),updated_at:O}).where(a).run(),{applied:V,appliedMode:ft,state:q,remaining:z}},{behavior:"immediate"})}catch(a){throw a instanceof _?a:new _("DB_ERROR","Failed to resolve overdrive",a)}finally{d.close();}}};function Kn(r){return r.replace(/<conversation_history[^>]*>[\s\S]*?<\/conversation_history>/g,"").split(`
|
|
359
|
+
`).filter(o=>!(o.startsWith("Loaded ")&&o.includes("layouts from")||o.includes("[dotenv@")||o.includes("[Nest]")&&o.includes("DEBUG")||o.startsWith("Registered custom layout:")||o.startsWith("Updated custom layout:"))).join(`
|
|
360
|
+
`).trim()}function Gn(r){if(!r)return "";let t=r;try{let e=JSON.parse(t);Array.isArray(e)?t=e.filter(s=>s?.type==="text"&&s?.text).map(s=>s.text).join(`
|
|
361
|
+
`):e&&typeof e=="object"&&e.result!==void 0&&(t=e.result||"");}catch{t=Kn(t);}return t}var Ot=class{dbPath;constructor(t){this.dbPath=t??join(homedir(),".crewx","crewx.db");}getThreadRepo(){return new Lt({dbPath:this.dbPath})}updateThread(t,e){this.getThreadRepo().updateThread(t,{title:e.title});}async ensureThread(t,e,s){let o=this.getThreadRepo(),i=o.findThreadById(t);if(i){if(i.platform!==e)throw new Error(`Thread '${t}' already exists with platform '${i.platform}' \u2014 cannot change to '${e}' (platform is immutable)`);return {created:false}}return o.ensureThread(t,e,s),{created:true}}async fetchHistory(t,e){let s=e?.limit??100,o=this.getThreadRepo(),i=o.findThreadById(t),d=o.findTopLevelTasks(t,void 0,s),a=new Set(["queued","cancelled"]);d=d.filter(l=>(!l.status||!a.has(l.status))&&(!e?.currentTraceId||l.trace_id!==e.currentTraceId));let u=i?.platform??"cli",c=this.rowsToMessages(d);return {threadId:t,platform:u,messages:c,metadata:{title:i?.title??void 0,firstMessage:i?.first_message??void 0,lastMessage:i?.last_message??void 0,messageCount:i?.message_count??0,updatedAt:i?.updated_at?new Date(i.updated_at).getTime():void 0}}}async saveUserMessage(t,e,s,o){let{firstMessage:i}=this.getThreadRepo().saveUserMessage(t,e);return {id:t,firstMessage:i}}async saveAssistantMessage(t,e,s,o){return this.getThreadRepo().saveAssistantMessage(t,e),{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 e=[];for(let s of t){s.prompt&&e.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 o=Gn(s.result),i=this.normalizeStatus(s.status);if(o||i==="running"||i==="failed"){let d={agent_id:s.agent_id,task_id:s.id};i&&(d.status=i),i==="failed"&&s.error&&(d.reason=s.error.split(`
|
|
362
|
+
`)[0].slice(0,200)),e.push({id:`${s.id}-assistant`,text:o,isAssistant:true,timestamp:new Date(s.started_at).getTime(),metadata:d});}}return e}};var Kt=class extends it{name="conversation";_provider;unsubStart=null;unsubEnd=null;constructor(t){super(),this._provider=new Ot(t?.dbPath);}get conversationProvider(){return this._provider}async afterUserMessage(t,e,s,o){}async afterAssistantMessage(t,e,s){}attach(t){this.unsubStart=t.on("task:start",async e=>{if(!e.threadId)return;let s=e.platform??"cli";try{let o=await this._provider.ensureThread(e.threadId,s,e.workspaceId),i=await this._provider.saveUserMessage(e.threadId,e.message??"");await this.afterUserMessage(e.threadId,i.id,o.created||i.firstMessage,e);}catch{}}),this.unsubEnd=t.on("task:end",async e=>{if(!e.result)return;let s=e.metadata?.threadId;if(!s)return;let o=e.agentRef?.replace(/^@/,"")??"";try{let{id:i}=await this._provider.saveAssistantMessage(s,e.result,o);await this.afterAssistantMessage(s,i,e);}catch{}});}detach(t){this.unsubStart?.(),this.unsubStart=null,this.unsubEnd?.(),this.unsubEnd=null,this._provider.close?.();}};export{Kt as ConversationPlugin,Pt as FileLoggerPlugin,Wt as SqliteTracingPlugin};
|