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