@crewx/sdk 0.9.0-rc.8 → 0.9.0-rc.80

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.
Files changed (168) hide show
  1. package/README.md +1 -1
  2. package/dist/activity-log/builder.d.ts +55 -6
  3. package/dist/config/canonicalize-agent-options.d.ts +17 -0
  4. package/dist/config/global-settings.d.ts +33 -0
  5. package/dist/config/migrate-grok-mode.d.ts +6 -0
  6. package/dist/config/model-compat.d.ts +31 -0
  7. package/dist/config/models.generated.d.ts +33 -0
  8. package/dist/config/models.remote.d.ts +1 -0
  9. package/dist/config/overdrive.d.ts +7 -0
  10. package/dist/config/pricing.d.ts +8 -5
  11. package/dist/config/pricing.generated.d.ts +4 -0
  12. package/dist/config/pricing.types.d.ts +4 -10
  13. package/dist/config/timeout.config.d.ts +3 -0
  14. package/dist/config/wi-boards.d.ts +19 -0
  15. package/dist/context-budget/continuity.d.ts +61 -0
  16. package/dist/context-budget/index.d.ts +140 -0
  17. package/dist/conversation/index.d.ts +1 -1
  18. package/dist/conversation/sqlite-provider.d.ts +5 -1
  19. package/dist/conversation/to-template-messages.d.ts +7 -0
  20. package/dist/conversation/types.d.ts +43 -0
  21. package/dist/desktop/command-runner.d.ts +4 -0
  22. package/dist/desktop/default-adapters.d.ts +4 -0
  23. package/dist/desktop/global-install.d.ts +19 -0
  24. package/dist/desktop/index.d.ts +2 -0
  25. package/dist/desktop/index.js +3 -0
  26. package/dist/desktop/install.d.ts +5 -0
  27. package/dist/desktop/lnk.d.ts +22 -0
  28. package/dist/desktop/manifest.d.ts +21 -0
  29. package/dist/desktop/types.d.ts +67 -0
  30. package/dist/desktop/version.d.ts +1 -0
  31. package/dist/desktop/windows-paths.d.ts +21 -0
  32. package/dist/desktop/wrapper.d.ts +18 -0
  33. package/dist/esm/desktop/index.js +3 -0
  34. package/dist/esm/index.js +345 -96
  35. package/dist/esm/plugins/index.js +187 -93
  36. package/dist/esm/publish/index.js +1 -0
  37. package/dist/esm/repository/index.js +203 -94
  38. package/dist/esm/testing/index.js +1 -1
  39. package/dist/events/types.d.ts +4 -0
  40. package/dist/facade/Crewx.d.ts +38 -2
  41. package/dist/highlight/thread-highlight-prompt.d.ts +2 -0
  42. package/dist/highlight/thread-highlighter.d.ts +326 -0
  43. package/dist/index.browser.d.ts +9 -1
  44. package/dist/index.browser.js +6 -2
  45. package/dist/index.d.ts +57 -8
  46. package/dist/index.js +345 -96
  47. package/dist/internal/windows-spawn.d.ts +10 -0
  48. package/dist/layout/types.d.ts +17 -1
  49. package/dist/local-server/base-url.d.ts +18 -0
  50. package/dist/local-server/index.d.ts +8 -0
  51. package/dist/local-server/opencode.d.ts +8 -0
  52. package/dist/local-server/probe.d.ts +3 -0
  53. package/dist/local-server/runtime.d.ts +26 -0
  54. package/dist/local-server/types.d.ts +43 -0
  55. package/dist/migrations/0008_careful_black_bird.sql +17 -0
  56. package/dist/migrations/0009_hot_dark_phoenix.sql +1 -0
  57. package/dist/migrations/0010_analyze_stats.sql +6 -0
  58. package/dist/migrations/0011_far_black_tarantula.sql +1 -0
  59. package/dist/migrations/0012_blue_turbo.sql +23 -0
  60. package/dist/migrations/0013_hesitant_adam_destine.sql +15 -0
  61. package/dist/migrations/0014_organic_mongu.sql +73 -0
  62. package/dist/migrations/0015_panoramic_gorilla_man.sql +71 -0
  63. package/dist/migrations/0016_fuzzy_hemingway.sql +14 -0
  64. package/dist/migrations/0017_project_stage_sdk_migration.sql +29 -0
  65. package/dist/migrations/0018_bored_jackal.sql +33 -0
  66. package/dist/migrations/0019_backfill_task_thread_ids.sql +74 -0
  67. package/dist/migrations/0020_useful_iron_lad.sql +55 -0
  68. package/dist/migrations/0021_dashing_peter_quill.sql +51 -0
  69. package/dist/migrations/meta/0008_snapshot.json +1327 -0
  70. package/dist/migrations/meta/0009_snapshot.json +1335 -0
  71. package/dist/migrations/meta/0010_snapshot.json +1335 -0
  72. package/dist/migrations/meta/0011_snapshot.json +1342 -0
  73. package/dist/migrations/meta/0012_snapshot.json +1494 -0
  74. package/dist/migrations/meta/0013_snapshot.json +1592 -0
  75. package/dist/migrations/meta/0014_snapshot.json +1975 -0
  76. package/dist/migrations/meta/0015_snapshot.json +2315 -0
  77. package/dist/migrations/meta/0016_snapshot.json +2419 -0
  78. package/dist/migrations/meta/0017_snapshot.json +2419 -0
  79. package/dist/migrations/meta/0018_snapshot.json +2570 -0
  80. package/dist/migrations/meta/0020_snapshot.json +2895 -0
  81. package/dist/migrations/meta/0021_snapshot.json +3031 -0
  82. package/dist/migrations/meta/_journal.json +98 -0
  83. package/dist/paths.d.ts +1 -0
  84. package/dist/plugin/types.d.ts +1 -0
  85. package/dist/plugins/index.js +187 -93
  86. package/dist/plugins/sqlite-tracing.d.ts +22 -0
  87. package/dist/provider/acp/connection.d.ts +4 -0
  88. package/dist/provider/acp/meta.d.ts +11 -0
  89. package/dist/provider/bridge.d.ts +6 -0
  90. package/dist/provider/classify-task-error.d.ts +2 -0
  91. package/dist/provider/cli/adapter.types.d.ts +6 -0
  92. package/dist/provider/cli/adapters/cli-knob.util.d.ts +7 -0
  93. package/dist/provider/cli/adapters/grok.d.ts +2 -0
  94. package/dist/provider/cli/adapters/index.d.ts +1 -0
  95. package/dist/provider/cli/index.d.ts +1 -1
  96. package/dist/provider/cli/meta.d.ts +5 -0
  97. package/dist/provider/errors.d.ts +1 -0
  98. package/dist/provider/idle-watchdog.d.ts +19 -0
  99. package/dist/provider/models.d.ts +17 -12
  100. package/dist/provider/order.d.ts +1 -1
  101. package/dist/provider/parse-usage.d.ts +6 -0
  102. package/dist/provider/provider-selection.d.ts +8 -0
  103. package/dist/provider/redact-technical-message.d.ts +1 -0
  104. package/dist/provider/task-error.types.d.ts +16 -0
  105. package/dist/publish/auth-boundary.d.ts +22 -0
  106. package/dist/publish/auth-json.d.ts +11 -0
  107. package/dist/publish/constants.d.ts +6 -0
  108. package/dist/publish/index.d.ts +30 -0
  109. package/dist/publish/index.js +1 -0
  110. package/dist/publish/manifest.d.ts +17 -0
  111. package/dist/publish/marketplace-api.constants.d.ts +1 -0
  112. package/dist/publish/pack.d.ts +2 -0
  113. package/dist/publish/scan.d.ts +9 -0
  114. package/dist/publish/secrets.d.ts +6 -0
  115. package/dist/publish/upload.d.ts +18 -0
  116. package/dist/repository/agent-suggestion.repository.d.ts +34 -0
  117. package/dist/repository/common-code.repository.d.ts +39 -0
  118. package/dist/repository/db.d.ts +8 -0
  119. package/dist/repository/index.d.ts +28 -4
  120. package/dist/repository/index.js +203 -94
  121. package/dist/repository/notification.repository.d.ts +58 -0
  122. package/dist/repository/project.repository.d.ts +90 -0
  123. package/dist/repository/request-log.repository.d.ts +1 -0
  124. package/dist/repository/task-log-migration.d.ts +74 -0
  125. package/dist/repository/task-log.repository.d.ts +44 -0
  126. package/dist/repository/task.repository.d.ts +119 -0
  127. package/dist/repository/thread-history.repository.d.ts +193 -0
  128. package/dist/repository/thread-title-common-code-migration.d.ts +13 -0
  129. package/dist/repository/thread-title.types.d.ts +29 -0
  130. package/dist/repository/thread.repository.d.ts +21 -2
  131. package/dist/repository/usage-report.repository.d.ts +27 -0
  132. package/dist/schema/agent-suggestions.d.ts +199 -0
  133. package/dist/schema/common-codes.d.ts +216 -0
  134. package/dist/schema/index.d.ts +9 -0
  135. package/dist/schema/notifications.d.ts +303 -0
  136. package/dist/schema/projects.d.ts +610 -0
  137. package/dist/schema/task-log-events.d.ts +119 -0
  138. package/dist/schema/tasks.d.ts +53 -0
  139. package/dist/schema/thread-history.d.ts +734 -0
  140. package/dist/schema/threads.d.ts +2 -0
  141. package/dist/schema/ui-action-receipts.d.ts +303 -0
  142. package/dist/schema/ui-instances.d.ts +267 -0
  143. package/dist/schema/usage-reports.d.ts +252 -0
  144. package/dist/testing/index.js +1 -1
  145. package/dist/types/index.d.ts +1536 -3
  146. package/dist/ui-card/index.d.ts +2 -0
  147. package/dist/ui-card/legacy-card-parser.d.ts +11 -0
  148. package/dist/ui-instance/definition.d.ts +6 -0
  149. package/dist/ui-instance/errors.d.ts +17 -0
  150. package/dist/ui-instance/index.d.ts +6 -0
  151. package/dist/ui-instance/json.d.ts +5 -0
  152. package/dist/ui-instance/runtime.d.ts +13 -0
  153. package/dist/ui-instance/store.d.ts +65 -0
  154. package/dist/ui-instance/types.d.ts +200 -0
  155. package/dist/ui-plugin/index.d.ts +3 -0
  156. package/dist/ui-plugin/manifest.d.ts +3 -0
  157. package/dist/ui-plugin/types.d.ts +76 -0
  158. package/dist/ui-plugin/validator.d.ts +9 -0
  159. package/dist/utils/crewx-home.d.ts +1 -0
  160. package/dist/utils/id.d.ts +1 -1
  161. package/dist/utils/timestamp.d.ts +1 -0
  162. package/dist/wi/create.d.ts +48 -0
  163. package/dist/wi/select.d.ts +20 -0
  164. package/package.json +18 -2
  165. package/templates/agents/default.yaml +240 -116
  166. package/templates/documents/crewx-manual.md +138 -138
  167. package/templates/workflows/wi-default-flow.yaml +65 -0
  168. package/templates/workflows/wi-plan-flow.yaml +140 -0
@@ -1,14 +1,54 @@
1
- import*as F from'path';import F__default,{join,dirname,basename}from'path';import {fileURLToPath}from'url';import Yt,{existsSync,mkdirSync,readFileSync}from'fs';import he from'os';import {sql,and,eq,ne,isNull,desc,isNotNull,or,like,asc,inArray,gte,lt as lt$1,lte}from'drizzle-orm';import {randomUUID,createHash}from'crypto';import {sqliteTable,text,integer,real,index,unique,uniqueIndex,getTableConfig}from'drizzle-orm/sqlite-core';var lt=(a=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(a,{get:(t,e)=>(typeof require<"u"?require:t)[e]}):a)(function(a){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+a+'" is not supported')});var ce=()=>fileURLToPath(import.meta.url),ue=()=>F__default.dirname(ce()),b=ue();var x=class{resolveDbPath(){return process.env.CREWX_DB?process.env.CREWX_DB:process.env.CREWX_TRACES_DB?process.env.CREWX_TRACES_DB:join(he.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 d=class extends Error{code;cause;constructor(t,e,n){super(e),this.name="RepositoryError",this.code=t,this.cause=n,Object.setPrototypeOf(this,new.target.prototype);}};function k(a){let t=lt("better-sqlite3"),{drizzle:e}=lt("drizzle-orm/better-sqlite3"),n=new t(a);return n.exec("PRAGMA journal_mode = WAL"),n.exec("PRAGMA busy_timeout = 5000"),n.exec("PRAGMA foreign_keys = ON"),{db:e(n),runRaw:(r,s=[])=>n.prepare(r).run(...s),close:()=>n.close()}}var Bt=new Set,fe={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 kt(a,t){return (a.get(`SELECT count(*) as cnt FROM sqlite_master WHERE type='table' AND name='${t}'`)?.cnt??0)>0}function me(a,t){if(t>0||!kt(a,"tasks"))return;let e=a.all("PRAGMA table_info(tasks)"),n=new Set(e.map(r=>r.name));for(let[r,s]of Object.entries(fe))n.has(r)||a.run(`ALTER TABLE tasks ADD COLUMN ${r} ${s}`);}var ge={"0002_normalize_task_names":{workspace_name:"TEXT",project_name:"TEXT"}};function we(a,t,e){if(!kt(a,"__drizzle_migrations")||!kt(a,"tasks"))return;let n=a.all(e`SELECT hash FROM __drizzle_migrations`),r=new Set(n.map(o=>o.hash)),s=JSON.parse(readFileSync(F__default.join(t,"meta/_journal.json"),"utf-8"));for(let o of s.entries){let l=ge[o.tag];if(!l)continue;let u=F__default.join(t,`${o.tag}.sql`);if(!existsSync(u))continue;let c=readFileSync(u,"utf-8"),_=createHash("sha256").update(c).digest("hex");if(r.has(_))continue;let m=a.all("PRAGMA table_info(tasks)"),g=new Set(m.map(R=>R.name));for(let[R,q]of Object.entries(l))g.has(R)||(a.run(`ALTER TABLE tasks ADD COLUMN ${R} ${q}`),g.add(R));}}function ke(a,t,e){let n=a.all(e`SELECT hash FROM __drizzle_migrations`),r=new Set(n.map(o=>o.hash)),s=JSON.parse(readFileSync(F__default.join(t,"meta/_journal.json"),"utf-8"));for(let o of s.entries){let l=F__default.join(t,`${o.tag}.sql`);if(!existsSync(l))continue;let u=readFileSync(l,"utf-8"),c=createHash("sha256").update(u).digest("hex");if(r.has(c))continue;let _=/ALTER\s+TABLE\s+[`"]?(\w+)[`"]?\s+ADD\s+[`"]?(\w+)[`"]?/gi,m=[],g;for(;(g=_.exec(u))!==null;)m.push({table:g[1],column:g[2]});if(m.length===0||!u.split(/-->\s*statement-breakpoint/).map(H=>H.trim()).filter(Boolean).every(H=>/^ALTER\s+TABLE\s+.+\s+ADD\s+/i.test(H)))continue;m.every(({table:H,column:C})=>a.all(`PRAGMA table_info("${H}")`).some(I=>I.name===C))&&a.run(e`INSERT INTO __drizzle_migrations (hash, created_at) VALUES (${c}, ${o.when})`);}}function et(a){let{migrate:t}=lt("drizzle-orm/better-sqlite3/migrator"),{sql:e}=lt("drizzle-orm"),n=[F__default.join(b,"../migrations"),F__default.join(b,"migrations"),F__default.join(b,"../../../../drizzle/migrations"),F__default.join(process.cwd(),"drizzle/migrations")],r=n.find(c=>existsSync(F__default.join(c,"meta/_journal.json")));if(!r)throw new Error(`migrations folder not found. Searched:
2
- ${n.join(`
3
- `)}`);let s=a.get(e`SELECT count(*) as cnt FROM sqlite_master WHERE type='table' AND name='__drizzle_migrations'`),o=0;s?.cnt&&(o=a.get(e`SELECT count(*) as cnt FROM __drizzle_migrations`)?.cnt??0),me(a,o),s?.cnt&&(ke(a,r,e),we(a,r,e)),t(a,{migrationsFolder:r});let u=(a.get(e`SELECT count(*) as cnt FROM __drizzle_migrations`)?.cnt??0)-o;if(u>0){let c=s?.cnt?"Database migrated":"Database initialized";console.error(`[crewx] ${c} (${u} migration${u>1?"s":""} applied).`);}}function O(a,t){Bt.has(t)||(et(a),Bt.add(t));}var h=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 i=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)},a=>({idx_tasks_agent_id:index("idx_tasks_agent_id").on(a.agent_id),idx_tasks_status:index("idx_tasks_status").on(a.status),idx_tasks_started_at:index("idx_tasks_started_at").on(a.started_at),idx_tasks_trace_id:index("idx_tasks_trace_id").on(a.trace_id),idx_tasks_parent_task_id:index("idx_tasks_parent_task_id").on(a.parent_task_id),idx_tasks_crewx_version:index("idx_tasks_crewx_version").on(a.crewx_version),idx_tasks_pid:index("idx_tasks_pid").on(a.pid),idx_tasks_thread_id:index("idx_tasks_thread_id").on(a.thread_id),idx_tasks_workspace_id:index("idx_tasks_workspace_id").on(a.workspace_id),idx_tasks_workspace_ref:index("idx_tasks_workspace_ref").on(a.workspace_ref),idx_tasks_project_id:index("idx_tasks_project_id").on(a.project_id),idx_tasks_ws_started:index("idx_tasks_ws_started").on(a.workspace_id,a.started_at)}));var p=sqliteTable("threads",{id:text("id").primaryKey(),workspace_id:text("workspace_id").references(()=>h.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)},a=>({idx_threads_updated_at:index("idx_threads_updated_at").on(a.updated_at),idx_threads_workspace_id:index("idx_threads_workspace_id").on(a.workspace_id)}));var W=sqliteTable("spans",{id:text("id").primaryKey(),task_id:text("task_id").references(()=>i.id,{onDelete:"set null"}),parent_span_id:text("parent_span_id").references(()=>W.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")},a=>({idx_spans_task_id:index("idx_spans_task_id").on(a.task_id),idx_spans_parent_span_id:index("idx_spans_parent_span_id").on(a.parent_span_id)}));var z=sqliteTable("tool_calls",{id:text("id").primaryKey(),task_id:text("task_id").references(()=>i.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()},a=>({idx_tool_calls_task_id:index("idx_tool_calls_task_id").on(a.task_id),idx_tool_calls_tool_name:index("idx_tool_calls_tool_name").on(a.tool_name),idx_tool_calls_timestamp:index("idx_tool_calls_timestamp").on(a.timestamp)}));var B=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()},a=>({idx_thread_boxes_thread_id:index("idx_thread_boxes_thread_id").on(a.thread_id),idx_thread_boxes_seq:index("idx_thread_boxes_seq").on(a.thread_id,a.seq),uniq_thread_boxes_thread_seq:unique().on(a.thread_id,a.seq)}));var nt=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")},a=>({idx_request_logs_timestamp:index("idx_request_logs_timestamp").on(a.timestamp),idx_request_logs_path:index("idx_request_logs_path").on(a.path),idx_request_logs_status_code:index("idx_request_logs_status_code").on(a.status_code),idx_request_logs_partition_key:index("idx_request_logs_partition_key").on(a.partition_key)}));var D=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")},a=>({uniq_usage_limit_snapshots_bucket:uniqueIndex("uniq_usage_limit_snapshots_bucket").on(a.provider,a.account_ref,a.limit_window,a.bucket_start),idx_usage_limit_snapshots_window_bucket:index("idx_usage_limit_snapshots_window_bucket").on(a.limit_window,a.bucket_start),idx_usage_limit_snapshots_provider_window_bucket:index("idx_usage_limit_snapshots_provider_window_bucket").on(a.provider,a.limit_window,a.bucket_start)}));function Rt(a){let t=F.resolve(a);return process.platform==="win32"&&(t=t.replace(/\\/g,"/"),t=t.replace(/^([A-Z]):/,(e,n)=>`${n.toLowerCase()}:`)),t.length>1&&!/^[a-zA-Z]:\/$/.test(t)&&(t=t.replace(/\/+$/,"")),t}function Wt(a){let t=Rt(a);return createHash("sha256").update(t).digest("hex")}function ht(a){return a.toLowerCase().replace(/[^a-z0-9-]/g,"-").replace(/-{2,}/g,"-").replace(/^-+|-+$/g,"")}var Tt=class extends x{dbRoot;constructor(t={}){super(),this.dbRoot=t.dbRoot;}resolveDbPath(){return this.dbRoot?join(this.dbRoot,".crewx","crewx.db"):super.resolveDbPath()}openHandle(t){let e=this.resolveDbPath();if(t){let r=dirname(e);existsSync(r)||mkdirSync(r,{recursive:true});}else if(!existsSync(e))throw new d("NOT_FOUND","Database not found");let n=k(e);if(t)try{et(n.db);}catch(r){throw n.close(),r}return n}resolveSlug(t,e,n){let r=ht(basename(n)),o=`${ht(basename(dirname(n)))}-${r}`,l=[r,o];try{let u=c=>t.select({id:h.id}).from(h).where(and(eq(h.slug,c),ne(h.id,e))).limit(1).all().length>0;for(let c of l)if(!u(c))return c;for(let c=2;c<1e3;c+=1){let _=`${o}-${c}`;if(!u(_))return _}}catch{}return r}normalizeLegacySlugs(){if(!this.dbExists())return {updated:0,checked:0};let t=this.openHandle(true);try{let e=t.db.select({id:h.id,slug:h.slug}).from(h).all(),n=0;for(let r of e)if(r.slug.includes("/")){let s=ht(r.slug.replace(/\//g,"-"));t.db.update(h).set({slug:s,updated_at:new Date().toISOString()}).where(eq(h.id,r.id)).run(),n+=1;}return {updated:n,checked:e.length}}catch(e){throw new d("DB_ERROR","Failed to normalize legacy slugs",e)}finally{t.close();}}ensureRow(t,e){let{id:n,slug:r,name:s,workspacePath:o}=e,l=new Date().toISOString();t.insert(h).values({id:n,slug:r,name:s,workspace_path:o,is_active:1,created_at:l,updated_at:l}).onConflictDoNothing().run(),t.update(h).set({workspace_path:o,updated_at:l}).where(and(eq(h.id,n),isNull(h.workspace_path))).run();}registerWorkspace(t){let e=Rt(t),n=this.openHandle(true);try{let r=Wt(e),s=basename(e),o=this.resolveSlug(n.db,r,e);return this.ensureRow(n.db,{id:r,slug:o,name:s,workspacePath:e}),{id:r,slug:o}}catch(r){throw r instanceof d?r:new d("DB_ERROR","Failed to register workspace",r)}finally{n.close();}}listProjects(t){if(!this.dbExists())return {rows:[],total:0};let e=this.openHandle(false);try{let n=t.isActive!==void 0?eq(h.is_active,t.isActive?1:0):void 0,r=e.db.select({count:sql`count(*)`}).from(h).where(n).get();return {rows:e.db.select().from(h).where(n).orderBy(desc(h.updated_at)).limit(t.limit).offset(t.offset).all(),total:r?.count??0}}catch(n){throw new d("DB_ERROR","Failed to list projects",n)}finally{e.close();}}findById(t){if(!this.dbExists())return;let e=this.openHandle(false);try{return e.db.select().from(h).where(eq(h.id,t)).limit(1).get()??void 0}catch(n){throw new d("DB_ERROR","Failed to find workspace",n)}finally{e.close();}}findAgentsByProject(t){if(!this.dbExists())return [];let e=this.openHandle(false);try{return e.db.all(sql`SELECT DISTINCT agent_id FROM tasks WHERE workspace_id = ${t} AND agent_id IS NOT NULL ORDER BY agent_id`).map(r=>r.agent_id)}catch(n){throw new d("DB_ERROR","Failed to find agents by project",n)}finally{e.close();}}findThreadsByProject(t,e){if(!this.dbExists())return {rows:[],total:0};let n=this.openHandle(false);try{let r=n.db.get(sql`SELECT COUNT(*) as count FROM threads WHERE workspace_id = ${t}`);return {rows:n.db.all(sql`SELECT t.*,
1
+ import*as Me from'path';import Me__default,{join,dirname,basename,resolve}from'path';import {fileURLToPath}from'url';import*as Qn from'fs';import Qn__default,{existsSync,mkdirSync,readFileSync,statfsSync,statSync}from'fs';import _i,{homedir}from'os';import {randomUUID,createHash,randomBytes}from'crypto';import {sql,and,eq,asc,ne,isNull,desc,isNotNull,gt as gt$1,lt,or,notLike,like,inArray,gte,lte}from'drizzle-orm';import {sqliteTable,text,integer,real,index,check,uniqueIndex,unique,primaryKey,getTableConfig}from'drizzle-orm/sqlite-core';var rt=(n=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(n,{get:(e,t)=>(typeof require<"u"?require:e)[t]}):n)(function(n){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+n+'" is not supported')});var ui=()=>fileURLToPath(import.meta.url),hi=()=>Me__default.dirname(ui()),y=hi();var x=class{resolveDbPath(){return process.env.CREWX_DB?process.env.CREWX_DB:process.env.CREWX_TRACES_DB?process.env.CREWX_TRACES_DB:join(_i.homedir(),".crewx","crewx.db")}resolveDbPaths(){return [this.resolveDbPath()]}isMissingTableError(e){return e instanceof Error&&/no such table:/i.test(e.message)}dbExists(e){return existsSync(e??this.resolveDbPath())}};var c=class extends Error{code;cause;constructor(e,t,r){super(t),this.name="RepositoryError",this.code=e,this.cause=r,Object.setPrototypeOf(this,new.target.prototype);}};var hn=n=>{try{return Qn.statSync(`${n}-wal`).size}catch{return 0}},pn=32*1024*1024;function T(n){let e=rt("better-sqlite3"),{drizzle:t}=rt("drizzle-orm/better-sqlite3"),r=new e(n);return r.exec("PRAGMA journal_mode = WAL"),r.exec(`PRAGMA journal_size_limit = ${pn}`),r.exec("PRAGMA busy_timeout = 5000"),r.exec("PRAGMA foreign_keys = ON"),r.exec("PRAGMA analysis_limit = 400"),{db:t(r),runRaw:(o,i=[])=>r.prepare(o).run(...i),close:()=>r.close()}}function fi(n,e="TRUNCATE"){if(e!=="PASSIVE"&&e!=="TRUNCATE")throw new Error(`Unsupported journal reclaim mode: ${e}`);let t=rt("better-sqlite3"),r=hn(n),o;try{o=new t(n),o.pragma("busy_timeout = 1000");let i=o.pragma(`wal_checkpoint(${e})`),s=hn(n);return {busy:i[0]?.busy===1,walBytesBefore:r,walBytesAfter:s}}finally{o?.close();}}var _n=new Set,mi={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",command:"TEXT"};function mr(n,e){return (n.get(`SELECT count(*) as cnt FROM sqlite_master WHERE type='table' AND name='${e}'`)?.cnt??0)>0}function wi(n,e){if(e>0||!mr(n,"tasks"))return;let t=n.all("PRAGMA table_info(tasks)"),r=new Set(t.map(o=>o.name));for(let[o,i]of Object.entries(mi))r.has(o)||n.run(`ALTER TABLE tasks ADD COLUMN ${o} ${i}`);}var ki={"0002_normalize_task_names":{workspace_name:"TEXT",project_name:"TEXT"},"0015_panoramic_gorilla_man":{project_id:"TEXT",workspace_id:"TEXT"},"0019_backfill_task_thread_ids":{command:"TEXT",thread_id:"TEXT"}};function Ti(n,e,t){if(!mr(n,"__drizzle_migrations")||!mr(n,"tasks"))return;let r=n.all(t`SELECT hash FROM __drizzle_migrations`),o=new Set(r.map(s=>s.hash)),i=JSON.parse(readFileSync(Me__default.join(e,"meta/_journal.json"),"utf-8"));for(let s of i.entries){let d=ki[s.tag];if(!d)continue;let l=Me__default.join(e,`${s.tag}.sql`);if(!existsSync(l))continue;let u=readFileSync(l,"utf-8"),h=createHash("sha256").update(u).digest("hex");if(o.has(h))continue;let g=n.all("PRAGMA table_info(tasks)"),p=new Set(g.map(f=>f.name));for(let[f,O]of Object.entries(d))p.has(f)||(n.run(`ALTER TABLE tasks ADD COLUMN ${f} ${O}`),p.add(f));}}function yi(n,e,t){let r=n.all(t`SELECT hash FROM __drizzle_migrations`),o=new Set(r.map(s=>s.hash)),i=JSON.parse(readFileSync(Me__default.join(e,"meta/_journal.json"),"utf-8"));for(let s of i.entries){let d=Me__default.join(e,`${s.tag}.sql`);if(!existsSync(d))continue;let l=readFileSync(d,"utf-8"),u=createHash("sha256").update(l).digest("hex");if(o.has(u))continue;let h=/ALTER\s+TABLE\s+[`"]?(\w+)[`"]?\s+ADD\s+[`"]?(\w+)[`"]?/gi,g=[],p;for(;(p=h.exec(l))!==null;)g.push({table:p[1],column:p[2]});if(g.length===0||!l.split(/-->\s*statement-breakpoint/).map(w=>w.trim()).filter(Boolean).every(w=>/^ALTER\s+TABLE\s+.+\s+ADD\s+/i.test(w)))continue;g.every(({table:w,column:I})=>n.all(`PRAGMA table_info("${w}")`).some(V=>V.name===I))&&n.run(t`INSERT INTO __drizzle_migrations (hash, created_at) VALUES (${u}, ${s.when})`);}}function ct(n){let{migrate:e}=rt("drizzle-orm/better-sqlite3/migrator"),{sql:t}=rt("drizzle-orm"),r=[Me__default.join(y,"../migrations"),Me__default.join(y,"migrations"),Me__default.join(y,"../../../../drizzle/migrations"),Me__default.join(process.cwd(),"drizzle/migrations")],o=r.find(u=>existsSync(Me__default.join(u,"meta/_journal.json")));if(!o)throw new Error(`migrations folder not found. Searched:
2
+ ${r.join(`
3
+ `)}`);let i=n.get(t`SELECT count(*) as cnt FROM sqlite_master WHERE type='table' AND name='__drizzle_migrations'`),s=0;i?.cnt&&(s=n.get(t`SELECT count(*) as cnt FROM __drizzle_migrations`)?.cnt??0),wi(n,s),i?.cnt&&(yi(n,o,t),Ti(n,o,t)),e(n,{migrationsFolder:o});let l=(n.get(t`SELECT count(*) as cnt FROM __drizzle_migrations`)?.cnt??0)-s;if(l>0){let u=i?.cnt?"Database migrated":"Database initialized";console.error(`[crewx] ${u} (${l} migration${l>1?"s":""} applied).`);}}function $(n,e){_n.has(e)||(ct(n),_n.add(e));}var R=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 a=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)},n=>({log_storage_check:check("tasks_log_storage_ck",sql`${n.log_storage} IN ('blob', 'events')`),idx_tasks_agent_id:index("idx_tasks_agent_id").on(n.agent_id),idx_tasks_status:index("idx_tasks_status").on(n.status),idx_tasks_started_at:index("idx_tasks_started_at").on(n.started_at),idx_tasks_trace_id:index("idx_tasks_trace_id").on(n.trace_id),idx_tasks_parent_task_id:index("idx_tasks_parent_task_id").on(n.parent_task_id),idx_tasks_crewx_version:index("idx_tasks_crewx_version").on(n.crewx_version),idx_tasks_pid:index("idx_tasks_pid").on(n.pid),idx_tasks_thread_id:index("idx_tasks_thread_id").on(n.thread_id),idx_tasks_workspace_id:index("idx_tasks_workspace_id").on(n.workspace_id),idx_tasks_workspace_ref:index("idx_tasks_workspace_ref").on(n.workspace_ref),idx_tasks_project_id:index("idx_tasks_project_id").on(n.project_id),idx_tasks_ws_started:index("idx_tasks_ws_started").on(n.workspace_id,n.started_at)}));var Ae=sqliteTable("task_log_events",{id:integer("id").primaryKey(),task_id:text("task_id").notNull().references(()=>a.id,{onDelete:"cascade"}),seq:integer("seq").notNull(),timestamp:text("timestamp").notNull(),level:text("level").notNull(),message:text("message").notNull()},n=>({taskSeqUnique:uniqueIndex("task_log_events_task_seq_uq").on(n.task_id,n.seq)}));var Ai="json_extract(metadata, '$.threadTitle.state')",Oi="json_extract(metadata, '$.threadTitle.priority')",_=sqliteTable("threads",{id:text("id").primaryKey(),workspace_id:text("workspace_id").references(()=>R.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)},n=>({idx_threads_updated_at:index("idx_threads_updated_at").on(n.updated_at),idx_threads_workspace_id:index("idx_threads_workspace_id").on(n.workspace_id),idx_threads_ws_updated:index("idx_threads_ws_updated").on(n.workspace_id,n.updated_at),idx_threads_title:index("idx_threads_title").on(n.title),idx_threads_workspace_thread_state:index("idx_threads_workspace_thread_state").on(n.workspace_id,sql.raw(Ai)),idx_threads_workspace_thread_priority:index("idx_threads_workspace_thread_priority").on(n.workspace_id,sql.raw(Oi))}));var Fe=sqliteTable("spans",{id:text("id").primaryKey(),task_id:text("task_id").references(()=>a.id,{onDelete:"set null"}),parent_span_id:text("parent_span_id").references(()=>Fe.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")},n=>({idx_spans_task_id:index("idx_spans_task_id").on(n.task_id),idx_spans_parent_span_id:index("idx_spans_parent_span_id").on(n.parent_span_id)}));var Oe=sqliteTable("tool_calls",{id:text("id").primaryKey(),task_id:text("task_id").references(()=>a.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()},n=>({idx_tool_calls_task_id:index("idx_tool_calls_task_id").on(n.task_id),idx_tool_calls_tool_name:index("idx_tool_calls_tool_name").on(n.tool_name),idx_tool_calls_timestamp:index("idx_tool_calls_timestamp").on(n.timestamp)}));var Re=sqliteTable("thread_boxes",{id:text("id").primaryKey(),thread_id:text("thread_id").notNull().references(()=>_.id,{onDelete:"cascade"}),seq:integer("seq").notNull(),first_task_id:text("first_task_id").notNull(),mid_task_id:text("mid_task_id").notNull(),last_task_id:text("last_task_id").notNull(),task_count:integer("task_count").notNull(),summary:text("summary"),source_tokens:integer("source_tokens").notNull(),summary_tokens:integer("summary_tokens"),created_at:text("created_at").notNull()},n=>({idx_thread_boxes_thread_id:index("idx_thread_boxes_thread_id").on(n.thread_id),idx_thread_boxes_seq:index("idx_thread_boxes_seq").on(n.thread_id,n.seq),uniq_thread_boxes_thread_seq:unique().on(n.thread_id,n.seq)}));var ut=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")},n=>({idx_request_logs_timestamp:index("idx_request_logs_timestamp").on(n.timestamp),idx_request_logs_path:index("idx_request_logs_path").on(n.path),idx_request_logs_status_code:index("idx_request_logs_status_code").on(n.status_code),idx_request_logs_partition_key:index("idx_request_logs_partition_key").on(n.partition_key)}));var te=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")},n=>({uniq_usage_limit_snapshots_bucket:uniqueIndex("uniq_usage_limit_snapshots_bucket").on(n.provider,n.account_ref,n.limit_window,n.bucket_start),idx_usage_limit_snapshots_window_bucket:index("idx_usage_limit_snapshots_window_bucket").on(n.limit_window,n.bucket_start),idx_usage_limit_snapshots_provider_window_bucket:index("idx_usage_limit_snapshots_provider_window_bucket").on(n.provider,n.limit_window,n.bucket_start)}));var le=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")},n=>({uniq_usage_reports_ws_month:uniqueIndex("uniq_usage_reports_ws_month").on(n.workspace_id,n.month)}));var N=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")},n=>({idx_notifications_ws_created:index("idx_notifications_ws_created").on(n.workspace_id,sql`${n.created_at} DESC`)})),Y=sqliteTable("notification_reads",{notification_id:text("notification_id").notNull(),user_id:text("user_id").notNull(),read_at:text("read_at").notNull()},n=>({pk:primaryKey({columns:[n.notification_id,n.user_id]})}));var L=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()},n=>({idx_agent_suggestions_ws_agent:index("idx_agent_suggestions_ws_agent").on(n.workspace_id,n.agent_id),idx_agent_suggestions_ws_created:index("idx_agent_suggestions_ws_created").on(n.workspace_id,n.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()},n=>({idCheck:check("ui_instances_id_ck",sql`length(${n.id}) BETWEEN 5 AND 128 AND ${n.id} GLOB 'uic_*'`),definitionIdCheck:check("ui_instances_definition_id_ck",sql`length(${n.definition_id}) BETWEEN 1 AND 128`),definitionVersionCheck:check("ui_instances_definition_version_ck",sql`${n.definition_version} >= 1`),definitionHashCheck:check("ui_instances_definition_hash_ck",sql`length(${n.definition_hash}) = 64 AND ${n.definition_hash} NOT GLOB '*[^0-9a-f]*'`),workspaceIdCheck:check("ui_instances_workspace_id_ck",sql`length(${n.workspace_id}) BETWEEN 1 AND 256`),threadIdCheck:check("ui_instances_thread_id_ck",sql`length(${n.thread_id}) BETWEEN 1 AND 256`),domainRefJsonCheck:check("ui_instances_domain_ref_json_ck",sql`json_valid(${n.domain_ref_json}) AND json_type(${n.domain_ref_json}) = 'object'`),stateJsonCheck:check("ui_instances_state_json_ck",sql`json_valid(${n.state_json}) AND json_type(${n.state_json}) = 'object'`),revisionCheck:check("ui_instances_revision_ck",sql`${n.revision} >= 0`),statusCheck:check("ui_instances_status_ck",sql`${n.status} IN ('active', 'completed', 'expired', 'revoked', 'unsupported')`),grantedCapabilitiesJsonCheck:check("ui_instances_granted_capabilities_json_ck",sql`json_valid(${n.granted_capabilities_json}) AND json_type(${n.granted_capabilities_json}) = 'array'`),createdAtCheck:check("ui_instances_created_at_ck",sql`${n.created_at} >= 0`),updatedAtCheck:check("ui_instances_updated_at_ck",sql`${n.updated_at} >= ${n.created_at}`),workspaceThreadIdx:index("ui_instances_workspace_thread_idx").on(n.workspace_id,n.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")},n=>({idCheck:check("ui_action_receipts_id_ck",sql`length(${n.id}) BETWEEN 5 AND 128`),instanceIdCheck:check("ui_action_receipts_instance_id_ck",sql`length(${n.instance_id}) BETWEEN 1 AND 128`),requestIdCheck:check("ui_action_receipts_request_id_ck",sql`length(${n.request_id}) BETWEEN 1 AND 128`),actionIdCheck:check("ui_action_receipts_action_id_ck",sql`length(${n.action_id}) BETWEEN 1 AND 128`),actorJsonCheck:check("ui_action_receipts_actor_json_ck",sql`json_valid(${n.actor_json}) AND json_type(${n.actor_json}) = 'object'`),sourceCheck:check("ui_action_receipts_source_ck",sql`${n.source} IN ('ui_host', 'cli', 'system')`),expectedRevisionCheck:check("ui_action_receipts_expected_revision_ck",sql`${n.expected_revision} >= 0`),beforeRevisionCheck:check("ui_action_receipts_before_revision_ck",sql`${n.before_revision} >= 0`),afterRevisionCheck:check("ui_action_receipts_after_revision_ck",sql`${n.after_revision} IS NULL OR ${n.after_revision} >= 0`),statusCheck:check("ui_action_receipts_status_ck",sql`${n.status} IN ('requested', 'settled')`),outcomeCheck:check("ui_action_receipts_outcome_ck",sql`${n.outcome} IS NULL OR ${n.outcome} IN ('succeeded', 'rejected', 'failed', 'conflicted', 'expired')`),inputJsonCheck:check("ui_action_receipts_input_json_ck",sql`json_valid(${n.input_json}) AND json_type(${n.input_json}) = 'object'`),resultJsonCheck:check("ui_action_receipts_result_json_ck",sql`${n.result_json} IS NULL OR (json_valid(${n.result_json}) AND json_type(${n.result_json}) = 'object')`),requestedAtCheck:check("ui_action_receipts_requested_at_ck",sql`${n.requested_at} >= 0`),settledAtCheck:check("ui_action_receipts_settled_at_ck",sql`${n.settled_at} IS NULL OR ${n.settled_at} >= ${n.requested_at}`),statusTransitionCheck:check("ui_action_receipts_status_transition_ck",sql`(
4
+ (${n.status} = 'requested' AND ${n.after_revision} IS NULL AND ${n.outcome} IS NULL AND ${n.settled_at} IS NULL)
5
+ OR
6
+ (${n.status} = 'settled' AND ${n.after_revision} IS NOT NULL AND ${n.outcome} IS NOT NULL AND ${n.settled_at} IS NOT NULL)
7
+ )`),instanceRequestUnique:uniqueIndex("ui_action_receipts_instance_request_uq").on(n.instance_id,n.request_id),instanceIdIdx:index("ui_action_receipts_instance_id_idx").on(n.instance_id),requestedAtIdx:index("ui_action_receipts_requested_at_idx").on(n.requested_at)}));var j=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")},n=>({idCheck:check("projects_id_ck",sql`${n.id} GLOB 'prj_*'`),sceneCheck:check("projects_scene_ck",sql`${n.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(${n.stages_json}) AND json_type(${n.stages_json}) = 'array'`),stageIndexCheck:check("projects_stage_index_ck",sql`${n.stage_index} >= 1`)})),ge=sqliteTable("project_criteria",{id:text("id").primaryKey().notNull(),project_id:text("project_id").notNull().references(()=>j.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()},n=>({idCheck:check("project_criteria_id_ck",sql`${n.id} GLOB 'pjc_*'`),verifyStatusCheck:check("project_criteria_verify_status_ck",sql`${n.verify_status} IN ('pending', 'verifying', 'passed', 'failed')`),evidenceJsonCheck:check("project_criteria_evidence_json_ck",sql`json_valid(${n.evidence_json}) AND json_type(${n.evidence_json}) = 'array'`),projectPositionUnique:uniqueIndex("project_criteria_project_position_uq").on(n.project_id,n.position)})),ve=sqliteTable("project_events",{id:text("id").primaryKey().notNull(),project_id:text("project_id").notNull().references(()=>j.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()},n=>({idCheck:check("project_events_id_ck",sql`${n.id} GLOB 'pje_*'`),actorTypeCheck:check("project_events_actor_type_ck",sql`${n.actor_type} IN ('user', 'project_manager', 'system')`),payloadJsonCheck:check("project_events_payload_json_ck",sql`json_valid(${n.payload_json}) AND json_type(${n.payload_json}) = 'object'`),projectSeqUnique:uniqueIndex("project_events_project_seq_uq").on(n.project_id,n.seq)}));var Yt=["THREAD_STATE","THREAD_PRIORITY"],Xt=["gray","blue","violet","green","amber","orange","red","pink"],m=sqliteTable("common_codes",{code_group:text("code_group").notNull(),code:text("code").notNull(),code_name:text("code_name"),color:text("color").notNull().default("gray"),sort_order:integer("sort_order").notNull(),workspace_id:text("workspace_id"),is_builtin:integer("is_builtin").notNull().default(0),is_archived:integer("is_archived").notNull().default(0),metadata:text("metadata"),created_at:text("created_at").notNull(),updated_at:text("updated_at").notNull()},n=>({pk:primaryKey({columns:[n.code_group,n.code]}),metadataCheck:check("common_codes_metadata_ck",sql`${n.metadata} IS NULL OR (json_valid(${n.metadata}) AND json_type(${n.metadata}) = 'object')`),builtinCheck:check("common_codes_builtin_ck",sql`${n.is_builtin} IN (0, 1)`),archivedCheck:check("common_codes_archived_ck",sql`${n.is_archived} IN (0, 1)`),idxCommonCodesSelection:index("idx_common_codes_group_archived_order").on(n.code_group,n.is_archived,n.sort_order)}));var Cn=["thread.snapshot.imported","thread.title.changed","thread.priority.changed","thread.state.changed","thread.highlight.created","thread.highlight.updated","thread.highlight.deleted","thread.highlights.regenerated"],Dn=["user","agent","system"],Nn=["auto","manual"],An=["decision","judgment","issue","result","pivot"];var On=["queued","running","completed","failed"],M=sqliteTable("thread_events",{id:text("id").primaryKey().notNull(),thread_id:text("thread_id").notNull().references(()=>_.id,{onDelete:"cascade"}),seq:integer("seq").notNull(),type:text("type").notNull(),actor_type:text("actor_type").notNull(),payload_json:text("payload_json").notNull(),created_at:text("created_at").notNull(),actor_id:text("actor_id"),task_id:text("task_id"),highlight_id:text("highlight_id")},n=>({typeCheck:check("thread_events_type_ck",sql`${n.type} IN ('thread.snapshot.imported', 'thread.title.changed', 'thread.priority.changed', 'thread.state.changed', 'thread.highlight.created', 'thread.highlight.updated', 'thread.highlight.deleted', 'thread.highlights.regenerated')`),actorTypeCheck:check("thread_events_actor_type_ck",sql`${n.actor_type} IN ('user', 'agent', 'system')`),payloadJsonCheck:check("thread_events_payload_json_ck",sql`json_valid(${n.payload_json}) AND json_type(${n.payload_json}) = 'object'`),threadSeqIndex:index("idx_thread_events_thread_seq").on(n.thread_id,n.seq),threadCreatedIndex:index("idx_thread_events_thread_created").on(n.thread_id,n.created_at),threadSeqUnique:uniqueIndex("thread_events_thread_seq_uq").on(n.thread_id,n.seq)})),A=sqliteTable("thread_highlight_runs",{id:text("id").primaryKey().notNull(),thread_id:text("thread_id").notNull().references(()=>_.id,{onDelete:"cascade"}),request_id:text("request_id").notNull(),status:text("status").notNull(),detector_version:text("detector_version").notNull(),requested_at:text("requested_at").notNull(),started_at:text("started_at"),completed_at:text("completed_at"),error_code:text("error_code"),previous_auto_count:integer("previous_auto_count"),new_auto_count:integer("new_auto_count")},n=>({statusCheck:check("thread_highlight_runs_status_ck",sql`${n.status} IN ('queued', 'running', 'completed', 'failed')`),countCheck:check("thread_highlight_runs_counts_ck",sql`(${n.previous_auto_count} IS NULL OR ${n.previous_auto_count} >= 0) AND (${n.new_auto_count} IS NULL OR ${n.new_auto_count} >= 0)`),threadRequestUnique:uniqueIndex("thread_highlight_runs_thread_request_uq").on(n.thread_id,n.request_id),inProgressThreadUnique:uniqueIndex("thread_highlight_runs_in_progress_thread_uq").on(n.thread_id).where(sql`${n.status} IN ('queued', 'running')`),threadStatusRequestedIndex:index("idx_thread_highlight_runs_thread_status_requested").on(n.thread_id,n.status,n.requested_at)})),v=sqliteTable("thread_highlights",{id:text("id").primaryKey().notNull(),thread_id:text("thread_id").notNull().references(()=>_.id,{onDelete:"cascade"}),source:text("source").notNull(),kind:text("kind").notNull(),status:text("status").notNull().default("active"),text:text("text"),covers_from_task_id:text("covers_from_task_id").notNull(),covers_to_task_id:text("covers_to_task_id").notNull(),revision:integer("revision").notNull().default(0),created_at:text("created_at").notNull(),updated_at:text("updated_at").notNull(),agent_id:text("agent_id"),source_task_id:text("source_task_id"),detector_version:text("detector_version"),content_fingerprint:text("content_fingerprint"),dismissed_at:text("dismissed_at")},n=>({sourceCheck:check("thread_highlights_source_ck",sql`${n.source} IN ('auto', 'manual')`),kindCheck:check("thread_highlights_kind_ck",sql`${n.kind} IN ('decision', 'judgment', 'issue', 'result', 'pivot')`),statusCheck:check("thread_highlights_status_ck",sql`${n.status} IN ('active', 'dismissed')`),activeTextCheck:check("thread_highlights_active_text_ck",sql`${n.status} = 'dismissed' OR (${n.text} IS NOT NULL AND length(${n.text}) > 0)`),coversCheck:check("thread_highlights_covers_ck",sql`length(${n.covers_from_task_id}) > 0 AND length(${n.covers_to_task_id}) > 0`),autoKeyCheck:check("thread_highlights_auto_key_ck",sql`${n.source} = 'manual' OR (${n.source} = 'auto' AND ${n.source_task_id} IS NOT NULL AND ${n.detector_version} IS NOT NULL AND ${n.content_fingerprint} IS NOT NULL AND length(${n.source_task_id}) > 0 AND length(${n.detector_version}) > 0 AND length(${n.content_fingerprint}) > 0)`),threadStatusCreatedIndex:index("idx_thread_highlights_thread_status_created").on(n.thread_id,n.status,n.created_at),threadCoversIndex:index("idx_thread_highlights_thread_covers").on(n.thread_id,n.covers_from_task_id,n.covers_to_task_id),autoIdempotencyUnique:uniqueIndex("thread_highlights_auto_idempotency_uq").on(n.thread_id,n.source_task_id,n.detector_version,n.content_fingerprint).where(sql`${n.source} = 'auto'`)}));var Q=class extends c{reason;constructor(e,t="VALIDATION",r=e,o){super(t,r,o),this.name="CommonCodeRepositoryError",this.reason=e;}},Ln="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";function gs(){let n=randomBytes(16),e="";for(let t of n)e+=Ln[t%Ln.length];return e.slice(0,12)}function gt(){return `c_${gs()}`}function ps(n){return typeof n=="string"&&Yt.includes(n)}function _s(n){return typeof n=="string"&&Xt.includes(n)}function St(n){if(!ps(n))throw new Q("COMMON_CODE_GROUP_INVALID","VALIDATION",`Unsupported common-code group: ${n}`)}function Pn(n){if(!_s(n))throw new Q("COMMON_CODE_COLOR_INVALID","VALIDATION",`Unsupported common-code color: ${n}`)}function Hn(n){let e=typeof n=="string"?n.trim():"",t=[...e].length;if(t<1||t>20)throw new Q("COMMON_CODE_NAME_INVALID","VALIDATION","Common-code names must contain 1 to 20 Unicode characters");return e}function It(n){if(typeof n!="string"||n.trim().length===0)throw new Q("COMMON_CODE_WORKSPACE_INVALID","VALIDATION","Workspace id is required for a user common code")}function Ir(n){if(typeof n!="string"||n.trim().length===0)throw new Q("COMMON_CODE_CODE_INVALID","VALIDATION","Common-code code is required")}function ht(n,e){return and(eq(m.code_group,n),or(isNull(m.workspace_id),eq(m.workspace_id,e)))}var vr=class extends x{dbPath;constructor(e={}){super(),e.dbPath?this.dbPath=e.dbPath:e.dbRoot&&(this.dbPath=join(e.dbRoot,".crewx","crewx.db"));}resolveDbPath(){return this.dbPath??super.resolveDbPath()}openHandle(e){let t=this.resolveDbPath();if(!e&&!existsSync(t))throw new c("NOT_FOUND","Database not found");e&&mkdirSync(dirname(t),{recursive:true});let r=T(t);if(e)try{$(r.db,t);}catch(o){throw r.close(),o}return r}listSelectable(e,t){if(St(e),It(t),!this.dbExists())return [];let r=this.openHandle(false);try{return r.db.select().from(m).where(and(ht(e,t),eq(m.is_archived,0))).orderBy(asc(m.sort_order),asc(m.code)).all()}catch(o){throw new c("DB_ERROR","Failed to list selectable common codes",o)}finally{r.close();}}listForHistory(e,t){if(St(e),It(t),!this.dbExists())return [];let r=this.openHandle(false);try{return r.db.select().from(m).where(ht(e,t)).orderBy(asc(m.sort_order),asc(m.code)).all()}catch(o){throw new c("DB_ERROR","Failed to list common-code history",o)}finally{r.close();}}resolve(e,t){if(St(e),Ir(t),!this.dbExists())return null;let r=this.openHandle(false);try{return r.db.select().from(m).where(and(eq(m.code_group,e),eq(m.code,t))).limit(1).get()??null}catch(o){throw new c("DB_ERROR","Failed to resolve common code",o)}finally{r.close();}}createThreadState(e){It(e.workspaceId);let t=Hn(e.name);Pn(e.color);let r=this.openHandle(true);try{return r.db.transaction(o=>{if(o.select({code:m.code}).from(m).where(and(ht("THREAD_STATE",e.workspaceId),eq(m.is_archived,0),eq(m.code_name,t))).limit(1).get())throw new Q("COMMON_CODE_NAME_CONFLICT","CONFLICT",`Common-code name is already in use: ${t}`);let s=o.select({maxSortOrder:sql`max(${m.sort_order})`}).from(m).where(ht("THREAD_STATE",e.workspaceId)).get(),d=new Date().toISOString(),l=gt();for(;o.select({code:m.code}).from(m).where(and(eq(m.code_group,"THREAD_STATE"),eq(m.code,l))).limit(1).get();)l=gt();o.insert(m).values({code_group:"THREAD_STATE",code:l,code_name:t,color:e.color,sort_order:(s?.maxSortOrder??-1)+1,workspace_id:e.workspaceId,is_builtin:0,is_archived:0,metadata:null,created_at:d,updated_at:d}).run();let u=o.select().from(m).where(and(eq(m.code_group,"THREAD_STATE"),eq(m.code,l))).limit(1).get();if(!u)throw new c("DB_ERROR","Created common code could not be read back");return u},{behavior:"immediate"})}catch(o){throw o instanceof c?o:new c("DB_ERROR","Failed to create thread state common code",o)}finally{r.close();}}updateDisplay(e){if(St(e.group),Ir(e.code),It(e.workspaceId),e.name===void 0&&e.color===void 0)throw new Q("COMMON_CODE_UPDATE_EMPTY","VALIDATION","At least one display value is required");let t=e.name===void 0||e.name===null?e.name:Hn(e.name);e.color!==void 0&&Pn(e.color);let r=this.openHandle(true);try{return r.db.transaction(o=>{let i=o.select().from(m).where(and(eq(m.code_group,e.group),eq(m.code,e.code))).limit(1).get();if(!i)throw new Q("COMMON_CODE_NOT_FOUND","NOT_FOUND",`Common code not found: ${e.group}/${e.code}`);if(this.assertOwnership(i,e.workspaceId),t===null&&i.is_builtin!==1)throw new Q("COMMON_CODE_NAME_INVALID","VALIDATION","User common-code names cannot be cleared");if(typeof t=="string"&&i.is_archived===0){let l=and(ht(e.group,e.workspaceId),eq(m.is_archived,0));if(o.select({code:m.code}).from(m).where(and(l,eq(m.code_name,t),sql`${m.code} <> ${e.code}`)).limit(1).get())throw new Q("COMMON_CODE_NAME_CONFLICT","CONFLICT",`Common-code name is already in use: ${t}`)}let s={updated_at:new Date().toISOString()};e.name!==void 0&&(s.code_name=t??null),e.color!==void 0&&(s.color=e.color),o.update(m).set(s).where(and(eq(m.code_group,e.group),eq(m.code,e.code))).run();let d=o.select().from(m).where(and(eq(m.code_group,e.group),eq(m.code,e.code))).limit(1).get();if(!d)throw new c("DB_ERROR","Updated common code could not be read back");return d},{behavior:"immediate"})}catch(o){throw o instanceof c?o:new c("DB_ERROR","Failed to update common-code display values",o)}finally{r.close();}}archive(e,t,r,o=true){if(St(e),Ir(t),It(r),typeof o!="boolean")throw new Q("COMMON_CODE_ARCHIVE_INVALID","VALIDATION","Archive state must be boolean");let i=this.openHandle(true);try{return i.db.transaction(s=>{let d=s.select().from(m).where(and(eq(m.code_group,e),eq(m.code,t))).limit(1).get();if(!d)throw new Q("COMMON_CODE_NOT_FOUND","NOT_FOUND",`Common code not found: ${e}/${t}`);if(d.is_builtin===1)throw new Q("COMMON_CODE_BUILTIN_ARCHIVE_FORBIDDEN","VALIDATION","Builtin common codes cannot be archived");if(this.assertOwnership(d,r),!o&&d.code_name!==null&&s.select({code:m.code}).from(m).where(and(ht(e,r),eq(m.is_archived,0),eq(m.code_name,d.code_name),ne(m.code,t))).limit(1).get())throw new Q("COMMON_CODE_NAME_CONFLICT","CONFLICT",`Common-code name is already in use: ${d.code_name}`);s.update(m).set({is_archived:o?1:0,updated_at:new Date().toISOString()}).where(and(eq(m.code_group,e),eq(m.code,t))).run();let l=s.select().from(m).where(and(eq(m.code_group,e),eq(m.code,t))).limit(1).get();if(!l)throw new c("DB_ERROR","Archived common code could not be read back");return l},{behavior:"immediate"})}catch(s){throw s instanceof c?s:new c("DB_ERROR","Failed to archive common code",s)}finally{i.close();}}assertOwnership(e,t){if(e.workspace_id!==null&&e.workspace_id!==t)throw new Q("COMMON_CODE_SCOPE_FORBIDDEN","VALIDATION","Workspace does not own this common code")}};function Cr(n){let e=Me.resolve(n);return process.platform==="win32"&&(e=e.replace(/\\/g,"/"),e=e.replace(/^([A-Z]):/,(t,r)=>`${r.toLowerCase()}:`)),e.length>1&&!/^[a-zA-Z]:\/$/.test(e)&&(e=e.replace(/\/+$/,"")),e}function jn(n){let e=Cr(n);return createHash("sha256").update(e).digest("hex")}function tr(n){return n.toLowerCase().replace(/[^a-z0-9-]/g,"-").replace(/-{2,}/g,"-").replace(/^-+|-+$/g,"")}var Ar=class extends x{dbRoot;constructor(e={}){super(),this.dbRoot=e.dbRoot;}resolveDbPath(){return this.dbRoot?join(this.dbRoot,".crewx","crewx.db"):super.resolveDbPath()}openHandle(e){let t=this.resolveDbPath();if(e){let o=dirname(t);existsSync(o)||mkdirSync(o,{recursive:true});}else if(!existsSync(t))throw new c("NOT_FOUND","Database not found");let r=T(t);if(e)try{ct(r.db);}catch(o){throw r.close(),o}return r}resolveSlug(e,t,r){let o=tr(basename(r)),s=`${tr(basename(dirname(r)))}-${o}`,d=[o,s];try{let l=u=>e.select({id:R.id}).from(R).where(and(eq(R.slug,u),ne(R.id,t))).limit(1).all().length>0;for(let u of d)if(!l(u))return u;for(let u=2;u<1e3;u+=1){let h=`${s}-${u}`;if(!l(h))return h}}catch{}return o}normalizeLegacySlugs(){if(!this.dbExists())return {updated:0,checked:0};let e=this.openHandle(true);try{let t=e.db.select({id:R.id,slug:R.slug}).from(R).all(),r=0;for(let o of t)if(o.slug.includes("/")){let i=tr(o.slug.replace(/\//g,"-"));e.db.update(R).set({slug:i,updated_at:new Date().toISOString()}).where(eq(R.id,o.id)).run(),r+=1;}return {updated:r,checked:t.length}}catch(t){throw new c("DB_ERROR","Failed to normalize legacy slugs",t)}finally{e.close();}}ensureRow(e,t){let{id:r,slug:o,name:i,workspacePath:s}=t,d=new Date().toISOString();e.insert(R).values({id:r,slug:o,name:i,workspace_path:s,is_active:1,created_at:d,updated_at:d}).onConflictDoNothing().run(),e.update(R).set({workspace_path:s,updated_at:d}).where(and(eq(R.id,r),isNull(R.workspace_path))).run();}registerWorkspace(e){let t=Cr(e),r=this.openHandle(true);try{let o=jn(t),i=basename(t),s=this.resolveSlug(r.db,o,t);return this.ensureRow(r.db,{id:o,slug:s,name:i,workspacePath:t}),{id:o,slug:s}}catch(o){throw o instanceof c?o:new c("DB_ERROR","Failed to register workspace",o)}finally{r.close();}}listProjects(e){if(!this.dbExists())return {rows:[],total:0};let t=this.openHandle(false);try{let r=e.isActive!==void 0?eq(R.is_active,e.isActive?1:0):void 0,o=t.db.select({count:sql`count(*)`}).from(R).where(r).get();return {rows:t.db.select().from(R).where(r).orderBy(desc(R.updated_at)).limit(e.limit).offset(e.offset).all(),total:o?.count??0}}catch(r){throw new c("DB_ERROR","Failed to list projects",r)}finally{t.close();}}findById(e){if(!this.dbExists())return;let t=this.openHandle(false);try{return t.db.select().from(R).where(eq(R.id,e)).limit(1).get()??void 0}catch(r){throw new c("DB_ERROR","Failed to find workspace",r)}finally{t.close();}}findAgentsByProject(e){if(!this.dbExists())return [];let t=this.openHandle(false);try{return t.db.all(sql`SELECT DISTINCT agent_id FROM tasks WHERE workspace_id = ${e} AND agent_id IS NOT NULL ORDER BY agent_id`).map(o=>o.agent_id)}catch(r){throw new c("DB_ERROR","Failed to find agents by project",r)}finally{t.close();}}findThreadsByProject(e,t){if(!this.dbExists())return {rows:[],total:0};let r=this.openHandle(false);try{let o=r.db.get(sql`SELECT COUNT(*) as count FROM threads WHERE workspace_id = ${e}`);return {rows:r.db.all(sql`SELECT t.*,
4
8
  (SELECT agent_id FROM tasks tk WHERE tk.thread_id = t.id AND tk.agent_id IS NOT NULL ORDER BY tk.started_at ASC LIMIT 1) AS agent_id
5
9
  FROM threads t
6
- WHERE t.workspace_id = ${t}
10
+ WHERE t.workspace_id = ${e}
7
11
  ORDER BY t.updated_at DESC
8
- LIMIT ${e.limit} OFFSET ${e.offset}`),total:r?.count??0}}catch(r){throw new d("DB_ERROR","Failed to find threads by project",r)}finally{n.close();}}findBySlug(t){if(!this.dbExists())return;let e=this.openHandle(false);try{return e.db.select().from(h).where(eq(h.slug,t)).limit(1).get()??void 0}catch(n){throw new d("DB_ERROR","Failed to find workspace by slug",n)}finally{e.close();}}slugExists(t,e){if(!this.dbExists())return false;let n=this.openHandle(false);try{let r=e?and(eq(h.slug,t),ne(h.id,e)):eq(h.slug,t);return !!n.db.select({id:h.id}).from(h).where(r).limit(1).get()}catch(r){throw new d("DB_ERROR","Failed to check slug",r)}finally{n.close();}}insert(t,e,n,r){let s=this.openHandle(true);try{let o=new Date().toISOString();s.db.insert(h).values({id:t,slug:e,name:n,workspace_path:r,is_active:1,created_at:o,updated_at:o}).run();let l=s.db.select().from(h).where(eq(h.id,t)).limit(1).get();if(!l)throw new d("DB_ERROR","Insert did not return a row");return l}catch(o){throw o instanceof d?o:new d("DB_ERROR","Failed to insert workspace",o)}finally{s.close();}}update(t,e,n){let r=this.openHandle(true);try{r.runRaw(`UPDATE workspaces SET ${e.join(", ")} WHERE id = ?`,n);let s=r.db.select().from(h).where(eq(h.id,t)).limit(1).get();if(!s)throw new d("NOT_FOUND",`Workspace ${t} not found`);return s}catch(s){throw s instanceof d?s:new d("DB_ERROR","Failed to update workspace",s)}finally{r.close();}}cleanupOrphanWorkspaces(){if(!this.dbExists())return {softDeleted:0,checked:0};let t=this.openHandle(true);try{let e=t.db.select({id:h.id,workspace_path:h.workspace_path}).from(h).where(and(eq(h.is_active,1),isNotNull(h.workspace_path))).all(),n=0;for(let r of e){let s=r.workspace_path;existsSync(join(s,"crewx.yaml"))||existsSync(join(s,"crewx.yml"))||(t.db.update(h).set({is_active:0,updated_at:new Date().toISOString()}).where(eq(h.id,r.id)).run(),n+=1);}return {softDeleted:n,checked:e.length}}catch(e){throw new d("DB_ERROR","Failed to cleanup orphan workspaces",e)}finally{t.close();}}delete(t){let e=this.openHandle(true);try{e.db.run(sql`UPDATE threads SET workspace_id = NULL WHERE workspace_id = ${t}`),e.db.delete(h).where(eq(h.id,t)).run();}catch(n){throw n instanceof d?n:new d("DB_ERROR","Failed to delete workspace",n)}finally{e.close();}}};var Jt=[h,i,p,W,z,B,nt];function Fe(){return F__default.join(he.homedir(),".crewx","crewx.db")}function je(a){if(!Yt.existsSync(a))return null;let t=Math.floor(Date.now()/1e3),e=`${a}.bak-${t}`;return Yt.copyFileSync(a,e),e}function Vt(a){let t=a.all("SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'");return new Set(t.map(e=>e.name))}function We(a){return a==null||typeof a=="object"&&"queryChunks"in a?null:typeof a=="number"?String(a):typeof a=="boolean"?a?"1":"0":typeof a=="string"?`'${a.replace(/'/g,"''")}'`:String(a)}function Ke(a){let t=a.getSQLType(),e=`"${a.name}" ${t}`,n=We(a.default);return n!==null&&(e+=` DEFAULT ${n}`),a.notNull&&(e+=" NOT NULL"),e}function Ge(a,t){let e=t?.dbPath??Fe(),n=t?.force??false,r=t?.dryRun??false,s=r?null:je(e);if(n&&!r)try{a.run("DELETE FROM __drizzle_migrations");}catch{}let o=Vt(a);if(!r)try{et(a);}catch(m){let g=m instanceof Error?`${m.message} ${m.cause?.message??""}`:"";if(!n||!g.includes("duplicate column"))throw m}let l,u;r?(l=Jt.map(g=>getTableConfig(g).name).filter(g=>!o.has(g)),u=o):(u=Vt(a),l=[...u].filter(m=>!o.has(m)));let c=[],_=[];for(let m of Jt){let g=getTableConfig(m),R=g.name;if(!u.has(R))continue;let q=a.all(`PRAGMA table_info("${R}")`),H=new Set(q.map(S=>S.name)),C=new Set(g.columns.map(S=>S.name));for(let S of g.columns)if(!H.has(S.name)){if(!r){let I=Ke(S);a.run(`ALTER TABLE "${R}" ADD COLUMN ${I}`);}c.push({table:R,column:S.name});}for(let S of q)C.has(S.name)||_.push(`${R}.${S.name} exists in DB but not in schema (untouched)`);}return {created:l,altered:c,warnings:_,backupPath:s}}var Q="2026-05-09",Ze="0.8.9-rc.13",Z=10,tt=parseInt(Ze.split("rc.")[1]),Ot=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 r=dirname(e);existsSync(r)||mkdirSync(r,{recursive:true});}else if(!existsSync(e))throw new d("NOT_FOUND","Database not found");let n=k(e);if(t)try{O(n.db,e);}catch(r){throw n.close(),r}return n}startTask(t){let e=this.openHandle(true);try{e.db.insert(i).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:i.id,set:{pid:sql`COALESCE(excluded.pid, ${i.pid})`},setWhere:eq(i.status,"running")}).run();}catch(n){throw n instanceof d?n:new d("DB_ERROR","Failed to start task",n)}finally{e.close();}}finishTask(t){let e=this.openHandle(true);try{let n=t.runEpoch??null;e.runRaw(`UPDATE tasks SET status=?, result=?, error=?, completed_at=?, duration_ms=?,
12
+ LIMIT ${t.limit} OFFSET ${t.offset}`),total:o?.count??0}}catch(o){throw new c("DB_ERROR","Failed to find threads by project",o)}finally{r.close();}}findBySlug(e){if(!this.dbExists())return;let t=this.openHandle(false);try{return t.db.select().from(R).where(eq(R.slug,e)).limit(1).get()??void 0}catch(r){throw new c("DB_ERROR","Failed to find workspace by slug",r)}finally{t.close();}}slugExists(e,t){if(!this.dbExists())return false;let r=this.openHandle(false);try{let o=t?and(eq(R.slug,e),ne(R.id,t)):eq(R.slug,e);return !!r.db.select({id:R.id}).from(R).where(o).limit(1).get()}catch(o){throw new c("DB_ERROR","Failed to check slug",o)}finally{r.close();}}insert(e,t,r,o){let i=this.openHandle(true);try{let s=new Date().toISOString();i.db.insert(R).values({id:e,slug:t,name:r,workspace_path:o,is_active:1,created_at:s,updated_at:s}).run();let d=i.db.select().from(R).where(eq(R.id,e)).limit(1).get();if(!d)throw new c("DB_ERROR","Insert did not return a row");return d}catch(s){throw s instanceof c?s:new c("DB_ERROR","Failed to insert workspace",s)}finally{i.close();}}update(e,t,r){let o=this.openHandle(true);try{o.runRaw(`UPDATE workspaces SET ${t.join(", ")} WHERE id = ?`,r);let i=o.db.select().from(R).where(eq(R.id,e)).limit(1).get();if(!i)throw new c("NOT_FOUND",`Workspace ${e} not found`);return i}catch(i){throw i instanceof c?i:new c("DB_ERROR","Failed to update workspace",i)}finally{o.close();}}cleanupOrphanWorkspaces(){if(!this.dbExists())return {softDeleted:0,checked:0};let e=this.openHandle(true);try{let t=e.db.select({id:R.id,workspace_path:R.workspace_path}).from(R).where(and(eq(R.is_active,1),isNotNull(R.workspace_path))).all(),r=0;for(let o of t){let i=o.workspace_path;existsSync(join(i,"crewx.yaml"))||existsSync(join(i,"crewx.yml"))||(e.db.update(R).set({is_active:0,updated_at:new Date().toISOString()}).where(eq(R.id,o.id)).run(),r+=1);}return {softDeleted:r,checked:t.length}}catch(t){throw new c("DB_ERROR","Failed to cleanup orphan workspaces",t)}finally{e.close();}}delete(e){let t=this.openHandle(true);try{t.db.run(sql`UPDATE threads SET workspace_id = NULL WHERE workspace_id = ${e}`),t.db.delete(R).where(eq(R.id,e)).run();}catch(r){throw r instanceof c?r:new c("DB_ERROR","Failed to delete workspace",r)}finally{t.close();}}};var Or="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";function ys(n){let e=randomBytes(n*2),t="";for(let r=0;r<e.length&&t.length<n;r++){let o=e[r];o<248&&(t+=Or[o%62]);}for(;t.length<n;)t+=Or[randomBytes(1)[0]%62];return t}function fe(n){return `${n}_${ys(8)}`}function Fn(n,e){let{createHash:t}=rt("crypto"),r=t("sha256").update(e).digest(),o=Buffer.alloc(8);for(let s=0;s<32;s++)o[s%8]^=r[s];let i="";for(let s of o)i+=Or[s%62];return `${n}_${i}`}var Lr=["outcome_plan","contract_check","feature_link","use_verify","result_review"],Cs=new Set(Lr),Kn=Object.freeze(Lr.map(n=>({key:n,labelOverride:null}))),Ds=new Set(["created","plan_proposed","plan_approved","decision_requested","decision_answered","replanned","stage_advanced","criterion_verified","scene_changed","result_submitted","accepted"]),Ns=new Set(["planning","plan_review","running","human_wait","limit_wait","failed_stop","analyzing_feedback","replanned","awaiting_review","accepted"]),As=new Set(["pending","verifying","passed","failed"]),Os=new Set(["user","project_manager","system"]),xs=new Set(["task","wi","url"]),Ls=/^\d{4}-\d{2}-\d{2}$/;function G(n){throw new c("VALIDATION",n)}function Ee(n){throw new c("NOT_FOUND",n)}function Z(n,e){(typeof n!="string"||n.trim().length===0)&&G(`${e} is required`);}function Ps(n){if(n==null)return;Ls.test(n)||G("dueDate must use YYYY-MM-DD");let e=new Date(`${n}T00:00:00.000Z`);(Number.isNaN(e.getTime())||e.toISOString().slice(0,10)!==n)&&G("dueDate must be a valid calendar date");}function Jn(n){let e=n??Kn;(!Array.isArray(e)||e.length===0)&&G("stages must contain at least one stage");let t=new Set;return e.map(r=>{(!r||typeof r!="object"||Array.isArray(r))&&G("stage must be an object");let o=r;return Z(o.key,"stage.key"),o.labelOverride!==null&&typeof o.labelOverride!="string"&&G("stage.labelOverride must be a string or null"),o.labelOverride!==null&&Z(o.labelOverride,"stage.labelOverride"),typeof o.key!="string"&&G("stage.key is required"),!Cs.has(o.key)&&o.labelOverride===null&&G(`custom stage requires a labelOverride: ${o.key}`),t.has(o.key)&&G(`duplicate stage key: ${o.key}`),t.add(o.key),{key:o.key,labelOverride:o.labelOverride}})}function Hs(n){Array.isArray(n)||G("criteria must be an array");for(let e of n)Z(e,"criterion.statement");}function pt(n={}){let e=n.actorType??"system";Os.has(e)||G(`invalid actorType: ${String(e)}`);let t=n.actorId??null;return (e==="user"||e==="project_manager")&&(!t||t.trim().length===0)&&G(`actorId is required for ${e}`),{actorType:e,actorId:t}}function Yn(n,e){let t=n??{};if((t===null||typeof t!="object"||Array.isArray(t))&&G("event payload must be a JSON object"),e==="accepted")for(let r of ["remainingRisks","nextPlan","lessons","evidenceRefs"])(!Object.prototype.hasOwnProperty.call(t,r)||t[r]===void 0)&&G(`accepted payload requires ${r}`);try{return JSON.stringify(t)}catch(r){throw new c("VALIDATION","event payload must be JSON serializable",r)}}function $s(n){return Array.isArray(n)||G("evidence must be an array"),n.map(e=>((!e||typeof e!="object")&&G("evidence item must be an object"),xs.has(e.kind)||G(`invalid evidence kind: ${String(e.kind)}`),Z(e.ref,"evidence.ref"),e.label!==void 0&&typeof e.label!="string"&&G("evidence.label must be a string"),e.label===void 0?{kind:e.kind,ref:e.ref}:{kind:e.kind,ref:e.ref,label:e.label}))}function Vn(n){let e;try{e=JSON.parse(n);}catch(t){throw new c("DB_ERROR","Project stages JSON is invalid",t)}try{if(!Array.isArray(e))throw new c("DB_ERROR","Project stages JSON is invalid");return Jn(e)}catch(t){throw new c("DB_ERROR","Project stages JSON is invalid",t)}}function Xn(n){return Z(n.projectId,"projectId"),Z(n.title,"title"),Ds.has(n.type)||G(`invalid project event type: ${String(n.type)}`),{...pt(n),payloadJson:Yn(n.payload,n.type)}}function it(n,e,t){let r=Xn(e);n.select({id:j.id}).from(j).where(eq(j.id,e.projectId)).get()||Ee(`Project ${e.projectId} not found`);let i=n.select({maxSeq:sql`COALESCE(MAX(${ve.seq}), 0)`}).from(ve).where(eq(ve.project_id,e.projectId)).get()?.maxSeq??0,s=fe("pje");n.insert(ve).values({id:s,project_id:e.projectId,seq:i+1,actor_type:r.actorType,actor_id:r.actorId,type:e.type,title:e.title,summary:e.summary??null,payload_json:r.payloadJson,created_at:t}).run();let d=n.select().from(ve).where(eq(ve.id,s)).get();if(!d)throw new c("DB_ERROR","Event insert did not return a row");return d}var xr=class extends x{dbPath;constructor(e={}){super(),e.dbPath?this.dbPath=e.dbPath:e.dbRoot&&(this.dbPath=join(e.dbRoot,".crewx","crewx.db"));}resolveDbPath(){return this.dbPath??super.resolveDbPath()}openHandle(e){let t=this.resolveDbPath();if(!e&&!existsSync(t))throw new c("NOT_FOUND","Database not found");if(e){let o=dirname(t);existsSync(o)||mkdirSync(o,{recursive:true});}let r=T(t);if(e)try{$(r.db,t);}catch(o){throw r.close(),o}return r}getDetailFromHandle(e,t){let r=e.db.select().from(j).where(eq(j.id,t)).get();if(!r)return;let o=e.db.select().from(ge).where(eq(ge.project_id,t)).orderBy(asc(ge.position)).all();return {...r,stages:Vn(r.stages_json),criteria:o}}getDetailOrThrow(e){let t=this.getProject(e);return t||Ee(`Project ${e} not found`),t}createProject(e){Z(e.workspaceId,"workspaceId"),Z(e.name,"name"),Z(e.outcome,"outcome"),Ps(e.dueDate);let t=Jn(e.stages);Hs(e.criteria);let r=fe("prj"),o=new Date().toISOString(),i=this.openHandle(true);try{i.db.transaction(s=>{s.insert(j).values({id:r,workspace_id:e.workspaceId,name:e.name,outcome:e.outcome,due_date:e.dueDate??null,scene:"planning",stages_json:JSON.stringify(t),stage_index:1,created_at:o,updated_at:o,accepted_at:null,archived_at:null}).run(),e.criteria.forEach((d,l)=>{s.insert(ge).values({id:fe("pjc"),project_id:r,position:l+1,statement:d,verify_status:"pending",verified_at:null,evidence_json:"[]",created_at:o,updated_at:o}).run();}),it(s,{projectId:r,actorType:"system",type:"created",title:"Project created",payload:{}},o);});}catch(s){throw s instanceof c?s:new c("DB_ERROR","Failed to create project",s)}finally{i.close();}return this.getDetailOrThrow(r)}getProject(e){if(!this.dbExists())return;let t=this.openHandle(false);try{return this.getDetailFromHandle(t,e)}catch(r){throw r instanceof c?r:new c("DB_ERROR","Failed to get project",r)}finally{t.close();}}listProjectsByWorkspace(e,t={}){if(Z(e,"workspaceId"),!this.dbExists())return [];let r=this.openHandle(false);try{let o=t.includeArchived?eq(j.workspace_id,e):and(eq(j.workspace_id,e),isNull(j.archived_at));return r.db.select({id:j.id}).from(j).where(o).orderBy(desc(j.updated_at),desc(j.created_at)).all().map(s=>this.getDetailFromHandle(r,s.id)).filter(s=>s!==void 0)}catch(o){throw o instanceof c?o:new c("DB_ERROR","Failed to list projects",o)}finally{r.close();}}archiveProject(e){Z(e,"projectId");let t=this.openHandle(true);try{t.db.update(j).set({archived_at:new Date().toISOString()}).where(eq(j.id,e)).run().changes===0&&Ee(`Project ${e} not found`);}catch(r){throw r instanceof c?r:new c("DB_ERROR","Failed to archive project",r)}finally{t.close();}return this.getDetailOrThrow(e)}setScene(e,t,r={}){Z(e,"projectId"),Ns.has(t)||G(`invalid project scene: ${String(t)}`);let o=pt(r),i=new Date().toISOString(),s=this.openHandle(true);try{s.db.transaction(d=>{let l=d.select().from(j).where(eq(j.id,e)).get();l||Ee(`Project ${e} not found`),d.update(j).set({scene:t,updated_at:i}).where(eq(j.id,e)).run(),it(d,{projectId:e,...o,type:"scene_changed",title:"Project scene changed",payload:{before:l.scene,after:t}},i);});}catch(d){throw d instanceof c?d:new c("DB_ERROR","Failed to set project scene",d)}finally{s.close();}return this.getDetailOrThrow(e)}setStageIndex(e,t,r={}){Z(e,"projectId"),Number.isInteger(t)||G("stage index must be an integer");let o=pt(r),i=new Date().toISOString(),s=this.openHandle(true);try{s.db.transaction(d=>{let l=d.select().from(j).where(eq(j.id,e)).get();l||Ee(`Project ${e} not found`);let u=Vn(l.stages_json);(t<1||t>u.length)&&G("stage index is outside the project stages"),d.update(j).set({stage_index:t,updated_at:i}).where(eq(j.id,e)).run(),it(d,{projectId:e,...o,type:"stage_advanced",title:"Project stage advanced",payload:{before:l.stage_index,after:t}},i);});}catch(d){throw d instanceof c?d:new c("DB_ERROR","Failed to set project stage",d)}finally{s.close();}return this.getDetailOrThrow(e)}setCriterionVerify(e,t,r,o={}){let i=typeof e=="string"?{projectId:typeof r=="string"?e:void 0,criterionId:typeof r=="string"?t:e,verifyStatus:typeof r=="string"?r:t,...typeof r=="string"?o:r}:e,s=i.verifyStatus??i.status;(!s||!As.has(s))&&G(`invalid criterion status: ${String(s)}`),Z(i.criterionId,"criterionId");let d=pt(i),l=new Date().toISOString(),u=this.openHandle(true),h;try{u.db.transaction(p=>{let f=p.select().from(ge).where(eq(ge.id,i.criterionId)).get();f||Ee(`Criterion ${i.criterionId} not found`),h=f.project_id,i.projectId&&i.projectId!==f.project_id&&Ee(`Criterion ${i.criterionId} not found in project ${i.projectId}`),p.update(ge).set({verify_status:s,verified_at:s==="passed"?l:null,updated_at:l}).where(eq(ge.id,i.criterionId)).run(),it(p,{projectId:f.project_id,...d,type:"criterion_verified",title:"Criterion verification updated",payload:{criterionId:i.criterionId,status:s}},l);});}catch(p){throw p instanceof c?p:new c("DB_ERROR","Failed to set criterion verification",p)}finally{u.close();}let g=h?this.getProject(h)?.criteria.find(p=>p.id===i.criterionId):void 0;return g||Ee(`Criterion ${i.criterionId} not found`),g}setCriterionEvidence(e,t,r,o={}){let i=typeof e=="string"?{projectId:Array.isArray(r)?e:void 0,criterionId:Array.isArray(r)?t:e,evidence:Array.isArray(r)?r:t,...Array.isArray(r)?o:r}:e;Z(i.criterionId,"criterionId");let s=$s(i.evidence),d=pt(i),l=new Date().toISOString(),u=this.openHandle(true),h;try{u.db.transaction(p=>{let f=p.select().from(ge).where(eq(ge.id,i.criterionId)).get();f||Ee(`Criterion ${i.criterionId} not found`),h=f.project_id,i.projectId&&i.projectId!==f.project_id&&Ee(`Criterion ${i.criterionId} not found in project ${i.projectId}`),p.update(ge).set({evidence_json:JSON.stringify(s),updated_at:l}).where(eq(ge.id,i.criterionId)).run(),it(p,{projectId:f.project_id,...d,type:"criterion_verified",title:"Criterion evidence updated",payload:{criterionId:i.criterionId,evidence:s}},l);});}catch(p){throw p instanceof c?p:new c("DB_ERROR","Failed to set criterion evidence",p)}finally{u.close();}let g=h?this.getProject(h)?.criteria.find(p=>p.id===i.criterionId):void 0;return g||Ee(`Criterion ${i.criterionId} not found`),g}appendEvent(e,t){let r=typeof e=="string"?{...t,projectId:e}:e;Xn(r);let o=new Date().toISOString(),i=this.openHandle(true),s;try{i.db.transaction(d=>{s=it(d,r,o);});}catch(d){throw d instanceof c?d:new c("DB_ERROR","Failed to append project event",d)}finally{i.close();}if(!s)throw new c("DB_ERROR","Event append did not return a row");return s}listEvents(e,t={}){if(Z(e,"projectId"),t.afterSeq!==void 0&&(!Number.isInteger(t.afterSeq)||t.afterSeq<0)&&G("afterSeq must be a non-negative integer"),t.limit!==void 0&&(!Number.isInteger(t.limit)||t.limit<1)&&G("limit must be a positive integer"),!this.dbExists())return [];let r=this.openHandle(false);try{let o=[eq(ve.project_id,e)];t.afterSeq!==void 0&&o.push(gt$1(ve.seq,t.afterSeq));let i=r.db.select().from(ve).where(and(...o)).orderBy(asc(ve.seq));return t.limit!==void 0&&(i=i.limit(t.limit)),i.all()}catch(o){throw o instanceof c?o:new c("DB_ERROR","Failed to list project events",o)}finally{r.close();}}acceptProject(e,t){Z(e,"projectId");let r=pt(t),o={remainingRisks:t.remainingRisks,nextPlan:t.nextPlan,lessons:t.lessons,evidenceRefs:t.evidenceRefs};Yn(o,"accepted");let i=new Date().toISOString(),s=this.openHandle(true);try{s.db.transaction(d=>{d.select({id:j.id}).from(j).where(eq(j.id,e)).get()||Ee(`Project ${e} not found`),d.update(j).set({scene:"accepted",accepted_at:i,updated_at:i}).where(eq(j.id,e)).run(),it(d,{projectId:e,...r,type:"accepted",title:"Project accepted",payload:o},i);});}catch(d){throw d instanceof c?d:new c("DB_ERROR","Failed to accept project",d)}finally{s.close();}return this.getDetailOrThrow(e)}};var eo=[R,a,_,Fe,Oe,Re,ut];function qs(){return Me__default.join(_i.homedir(),".crewx","crewx.db")}function Bs(n){if(!Qn__default.existsSync(n))return null;let e=Math.floor(Date.now()/1e3),t=`${n}.bak-${e}`;return Qn__default.copyFileSync(n,t),t}function to(n){let e=n.all("SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'");return new Set(e.map(t=>t.name))}function Fs(n){return n==null||typeof n=="object"&&"queryChunks"in n?null:typeof n=="number"?String(n):typeof n=="boolean"?n?"1":"0":typeof n=="string"?`'${n.replace(/'/g,"''")}'`:String(n)}function Us(n){let e=n.getSQLType(),t=`"${n.name}" ${e}`,r=Fs(n.default);return r!==null&&(t+=` DEFAULT ${r}`),n.notNull&&(t+=" NOT NULL"),t}function zs(n,e){let t=e?.dbPath??qs(),r=e?.force??false,o=e?.dryRun??false,i=o?null:Bs(t);if(r&&!o)try{n.run("DELETE FROM __drizzle_migrations");}catch{}let s=to(n);if(!o)try{ct(n);}catch(g){let p=g instanceof Error?`${g.message} ${g.cause?.message??""}`:"";if(!r||!p.includes("duplicate column"))throw g}let d,l;o?(d=eo.map(p=>getTableConfig(p).name).filter(p=>!s.has(p)),l=s):(l=to(n),d=[...l].filter(g=>!s.has(g)));let u=[],h=[];for(let g of eo){let p=getTableConfig(g),f=p.name;if(!l.has(f))continue;let O=n.all(`PRAGMA table_info("${f}")`),w=new Set(O.map(E=>E.name)),I=new Set(p.columns.map(E=>E.name));for(let E of p.columns)if(!w.has(E.name)){if(!o){let V=Us(E);n.run(`ALTER TABLE "${f}" ADD COLUMN ${V}`);}u.push({table:f,column:E.name});}for(let E of O)I.has(E.name)||h.push(`${f}.${E.name} exists in DB but not in schema (untouched)`);}return {created:d,altered:u,warnings:h,backupPath:i}}function ro(n){let e=n.toLowerCase().trim();e=e.replace(/\[[^\]]*\]$/g,"");let t=e.lastIndexOf("/");return t>=0&&(e=e.slice(t+1)),e=e.replace(/-\d{8}$/,""),e}function ao(n,e){let t=e===void 0?"":` at index ${e}`;if(!n||typeof n!="object")throw new c("VALIDATION",`Task log entry${t} must be an object`);if(typeof n.timestamp!="string"||typeof n.level!="string"||typeof n.message!="string")throw new c("VALIDATION",`Task log entry${t} must contain string timestamp, level, and message fields`);return {timestamp:n.timestamp,level:n.level,message:n.message}}function io(n,e){if(e===null||e.trim()==="")return [];let t;try{t=JSON.parse(e);}catch(r){throw new c("DB_ERROR",`Malformed legacy task logs: ${n}`,r)}if(!Array.isArray(t))throw new c("DB_ERROR",`Malformed legacy task logs: ${n} (expected an array)`);try{return t.map((r,o)=>ao(r,o))}catch(r){throw r instanceof c?new c("DB_ERROR",`Malformed legacy task logs: ${n}`,r):r}}function co(n){if(n.log_storage!=="blob"&&n.log_storage!=="events")throw new c("DB_ERROR",`Invalid task log storage for task: ${n.id}`);if(!Number.isInteger(n.last_log_seq)||n.last_log_seq<0)throw new c("DB_ERROR",`Invalid task log sequence for task: ${n.id}`);if(!Number.isInteger(n.log_revision)||n.log_revision<0)throw new c("DB_ERROR",`Invalid task log revision for task: ${n.id}`);return n.log_storage}function so(n){return {taskId:n.id,source:co(n),revision:n.log_revision,lastSeq:n.last_log_seq}}function Qs(n){if(!Number.isInteger(n)||n<0)throw new c("VALIDATION","Task log tail limit must be a non-negative integer")}var Dt=class extends x{dbPath;constructor(e={}){super(),e.dbPath?this.dbPath=e.dbPath:e.dbRoot&&(this.dbPath=join(e.dbRoot,".crewx","crewx.db"));}resolveDbPath(){return this.dbPath?this.dbPath:super.resolveDbPath()}openHandle(e){let t=this.resolveDbPath();if(e){let o=dirname(t);existsSync(o)||mkdirSync(o,{recursive:true});}else if(!existsSync(t))throw new c("NOT_FOUND","Database not found");let r=T(t);if(e)try{$(r.db,t);}catch(o){throw r.close(),o}return r}findStateRow(e,t){return e.db.select({id:a.id,log_storage:a.log_storage,last_log_seq:a.last_log_seq,log_revision:a.log_revision,logs:a.logs}).from(a).where(eq(a.id,t)).limit(1).get()}findStateRowInTransaction(e,t){return e.select({id:a.id,log_storage:a.log_storage,last_log_seq:a.last_log_seq,log_revision:a.log_revision,logs:a.logs}).from(a).where(eq(a.id,t)).limit(1).get()}requireStateRowInTransaction(e,t){let r=this.findStateRowInTransaction(e,t);if(!r)throw new c("NOT_FOUND",`Task not found: ${t}`);return r}appendLog(e,t){return this.appendLogs(e,[t])}appendLogs(e,t){let r=t.map((i,s)=>ao(i,s));if(r.length===0){let i=this.getLogState(e);if(!i)throw new c("NOT_FOUND",`Task not found: ${e}`);return i}let o=this.openHandle(true);try{return o.db.transaction(s=>{let d=this.requireStateRowInTransaction(s,e),l=co(d);if(l==="blob"){let p=io(e,d.logs);if(s.update(a).set({logs:JSON.stringify([...p,...r]),log_revision:sql`${a.log_revision} + 1`}).where(eq(a.id,e)).run().changes!==1)throw new c("NOT_FOUND",`Task not found: ${e}`);return {taskId:e,source:l,revision:d.log_revision+1,lastSeq:d.last_log_seq}}let u=d.last_log_seq+1,h=d.last_log_seq+r.length;if(s.insert(Ae).values(r.map((p,f)=>({task_id:e,seq:u+f,timestamp:p.timestamp,level:p.level,message:p.message}))).run(),s.update(a).set({last_log_seq:h,log_revision:sql`${a.log_revision} + 1`}).where(eq(a.id,e)).run().changes!==1)throw new c("NOT_FOUND",`Task not found: ${e}`);return {taskId:e,source:l,revision:d.log_revision+1,lastSeq:h}},{behavior:"immediate"})}catch(i){throw i instanceof c?i:new c("DB_ERROR","Failed to append task log",i)}finally{o.close();}}getLogState(e){if(!this.dbExists())return;let t=this.openHandle(false);try{let r=this.findStateRow(t,e);return r?so(r):void 0}catch(r){throw r instanceof c?r:new c("DB_ERROR","Failed to read task log state",r)}finally{t.close();}}readLogs(e){return this.readLogsInternal(e)}readLogsTail(e,t){return Qs(t),this.readLogsInternal(e,t)}readTail(e,t){return this.readLogsTail(e,t)}readLogsInternal(e,t){if(!this.dbExists())return;let r=this.openHandle(false);try{return r.db.transaction(o=>{let i=this.findStateRowInTransaction(o,e);if(!i)return;let s=so(i);if(s.source==="blob"){let h=io(e,i.logs);return {...s,entries:t===void 0?h:h.slice(Math.max(0,h.length-t))}}let d=o.select({seq:Ae.seq,timestamp:Ae.timestamp,level:Ae.level,message:Ae.message}).from(Ae).where(eq(Ae.task_id,e)).orderBy(t===void 0?asc(Ae.seq):desc(Ae.seq)),u=(t===void 0?d.all():d.limit(t).all()).map(({timestamp:h,level:g,message:p})=>({timestamp:h,level:g,message:p}));return t!==void 0&&u.reverse(),{...s,entries:u}},{behavior:"deferred"})}catch(o){throw o instanceof c?o:new c("DB_ERROR","Failed to read task logs",o)}finally{r.close();}}};var Hr=40,We="2026-05-09",oa="0.8.9-rc.13",Ve=10,Ke=parseInt(oa.split("rc.")[1]);function lo(){let n=sql`
13
+ CASE
14
+ WHEN ${a.model} LIKE 'claude-%' OR ${a.model} IN ('opus', 'sonnet', 'haiku', 'opus[1m]', 'sonnet[1m]') THEN 'claude'
15
+ WHEN ${a.model} LIKE 'gpt-%' OR ${a.model} LIKE 'codex-%' THEN 'codex'
16
+ WHEN ${a.model} LIKE 'gemini-%' THEN 'gemini'
17
+ WHEN ${a.model} LIKE 'grok-%' THEN 'grok'
18
+ WHEN ${a.model} LIKE 'zai-%' OR ${a.model} LIKE 'openrouter/z-ai/%' THEN 'opencode'
19
+ WHEN ${a.model} LIKE 'minimax/%' THEN 'minimax'
20
+ WHEN ${a.model} LIKE 'qwen%' THEN 'qwen'
21
+ ELSE 'unknown'
22
+ END
23
+ `,e=sql`json_extract(${a.metadata}, '$.provider')`,t=sql`trim(${e})`,r=sql`substr(${t}, 1, instr(${t}, '/') - 1)`,o=sql`
24
+ CASE
25
+ WHEN instr(${t}, '/') > 0
26
+ AND ${r} IN ('cli', 'acp', 'api', 'plugin', 'remote')
27
+ THEN substr(${t}, instr(${t}, '/') + 1)
28
+ ELSE ${t}
29
+ END
30
+ `;return sql`
31
+ CASE
32
+ WHEN ${a.metadata} IS NULL THEN ${n}
33
+ WHEN json_valid(${a.metadata}) = 0 THEN 'unknown'
34
+ WHEN json_type(${a.metadata}, '$') IS NOT 'object' THEN 'unknown'
35
+ WHEN json_type(${a.metadata}, '$.provider') IS NULL THEN ${n}
36
+ WHEN json_type(${a.metadata}, '$.provider') IS NOT 'text' THEN 'unknown'
37
+ WHEN ${t} = '' THEN 'unknown'
38
+ WHEN trim(${o}) = '' THEN 'unknown'
39
+ ELSE ${o}
40
+ END
41
+ `}var ia=new Set(["workflow","mcp"]),uo=600*1e3,$r=class extends x{dbPath;taskLogRepository;pidNullObservedSince=new Map;constructor(e={}){super(),e.dbPath?this.dbPath=e.dbPath:e.dbRoot&&(this.dbPath=join(e.dbRoot,".crewx","crewx.db")),this.taskLogRepository=new Dt({dbPath:this.dbPath});}resolveDbPath(){return this.dbPath?this.dbPath:super.resolveDbPath()}openHandle(e){let t=this.resolveDbPath();if(e){let o=dirname(t);existsSync(o)||mkdirSync(o,{recursive:true});}else if(!existsSync(t))throw new c("NOT_FOUND","Database not found");let r=T(t);if(e)try{$(r.db,t);}catch(o){throw r.close(),o}return r}startTask(e){let t=this.openHandle(true);try{let r={id:e.id,agent_id:e.agentId,prompt:e.prompt,mode:e.mode,status:e.status,started_at:e.startedAt,pid:e.pid??null,parent_task_id:e.parentTaskId??null,caller_agent_id:e.callerAgentId??null,trace_id:e.traceId??null,command:e.command??null,metadata:e.metadata??null,workspace_id:e.workspaceId??null,project_id:e.projectId??null,platform:e.platform??"cli",crewx_version:e.crewxVersion??null,thread_id:e.threadId??null,model:e.model??null,rendered_prompt:e.renderedPrompt??null,coding_agent_command:e.codingAgentCommand??null,log_storage:"events"},o=i=>{t.db.insert(a).values(i).onConflictDoUpdate({target:a.id,set:{pid:sql`COALESCE(excluded.pid, ${a.pid})`},setWhere:eq(a.status,"running")}).run();};try{o(r);}catch(i){let s=i instanceof Error?i.message:typeof i=="object"&&i!==null&&"message"in i?String(i.message):String(i);if(!/log_storage/i.test(s)||!/no such column|no column named/i.test(s))throw i;t.runRaw(`INSERT INTO tasks (
42
+ id, agent_id, prompt, mode, status, started_at, pid,
43
+ parent_task_id, caller_agent_id, trace_id, command, metadata,
44
+ workspace_id, project_id, platform, crewx_version, thread_id,
45
+ model, rendered_prompt, coding_agent_command
46
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
47
+ ON CONFLICT(id) DO UPDATE SET pid = COALESCE(excluded.pid, tasks.pid)
48
+ WHERE tasks.status = 'running'`,[r.id,r.agent_id,r.prompt,r.mode,r.status,r.started_at,r.pid,r.parent_task_id,r.caller_agent_id,r.trace_id,r.command,r.metadata,r.workspace_id,r.project_id,r.platform,r.crewx_version,r.thread_id,r.model,r.rendered_prompt,r.coding_agent_command]);}}catch(r){throw r instanceof c?r:new c("DB_ERROR","Failed to start task",r)}finally{t.close();}}listTasksByProjectId(e){if(!this.dbExists())return [];let t=this.openHandle(false);try{return t.db.select().from(a).where(eq(a.project_id,e)).orderBy(desc(a.started_at)).all()}catch(r){throw r instanceof c?r:new c("DB_ERROR","Failed to list tasks by project",r)}finally{t.close();}}finishTask(e){let t=this.openHandle(true);try{let r=e.runEpoch??null;t.runRaw(`UPDATE tasks SET status=?, result=?, error=?, completed_at=?, duration_ms=?,
9
49
  exit_code=?, input_tokens=?, output_tokens=?, cached_input_tokens=?, cost_usd=?,
10
50
  model=COALESCE(?, model)
11
- 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,n]);}catch(n){throw n instanceof d?n:new d("DB_ERROR","Failed to finish task",n)}finally{e.close();}}appendLog(t,e){let n=this.openHandle(true);try{n.db.transaction(r=>{let s=r.select({logs:i.logs}).from(i).where(eq(i.id,t)).limit(1).get(),o=s?.logs?JSON.parse(s.logs):[];o.push(e),r.update(i).set({logs:JSON.stringify(o)}).where(eq(i.id,t)).run();},{behavior:"immediate"});}catch(r){throw r instanceof d?r:new d("DB_ERROR","Failed to append log",r)}finally{n.close();}}getRunningTasks(){if(!this.dbExists())return [];let t=this.openHandle(false);try{return t.db.select().from(i).where(eq(i.status,"running")).orderBy(desc(i.started_at)).all()}catch(e){throw new d("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(i).orderBy(desc(i.started_at)).limit(100).all()}catch(e){throw new d("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(i).where(eq(i.id,t)).limit(1).get()??void 0}catch(n){throw new d("DB_ERROR","Failed to get task",n)}finally{e.close();}}killTask(t){if(!this.dbExists())return {killed:false};let e=this.openHandle(true);try{let n=e.db.select({id:i.id,status:i.status,pid:i.pid}).from(i).where(eq(i.id,t)).limit(1).get();if(!n||n.status!=="running")return {killed:!1};if(n.pid)try{process.kill(n.pid,"SIGTERM");}catch{}return e.db.update(i).set({status:"failed",error:"Killed by user",completed_at:new Date().toISOString()}).where(and(eq(i.id,t),eq(i.status,"running"))).run(),{killed:!0,pid:n.pid??void 0}}catch(n){throw n instanceof d?n:new d("DB_ERROR","Failed to kill task",n)}finally{e.close();}}reapOrphanedTasks(){if(!this.dbExists())return 0;let t=this.openHandle(true);try{let e=t.db.select({id:i.id,pid:i.pid}).from(i).where(eq(i.status,"running")).all(),n=0;for(let r of e){if(!r.pid)continue;let s=!1;try{process.kill(r.pid,0),s=!0;}catch{}s||(t.db.update(i).set({status:"failed",error:"Reaped: process not found (orphaned task)",completed_at:new Date().toISOString()}).where(and(eq(i.id,r.id),eq(i.status,"running"))).run(),n++);}return n}finally{t.close();}}findTaskStatus(t,e){let n=this.resolveDbPaths();for(let r of n){if(!existsSync(r))continue;let s=k(r);try{let o=e?eq(i.workspace_id,e):void 0,l=o?and(eq(i.id,t),o):eq(i.id,t),u=s.db.select().from(i).where(l).limit(1).get()??void 0;if(!u){let c=or(eq(i.thread_id,t),and(isNull(i.thread_id),like(i.command,`%--thread=${t}%`))),_=o?and(c,o):c;u=s.db.select().from(i).where(_).orderBy(desc(i.started_at)).limit(1).get()??void 0;}if(u)return u}catch(o){throw new d("DB_ERROR","Failed to find task status",o)}finally{s.close();}}}findChildTasks(t,e){let n=this.resolveDbPaths(),r=new Set,s=[];for(let o of n){if(!existsSync(o))continue;let l=k(o);try{let u=e?and(eq(i.parent_task_id,t),eq(i.workspace_id,e)):eq(i.parent_task_id,t),c=l.db.select().from(i).where(u).orderBy(asc(i.started_at)).all();for(let _ of c)r.has(_.id)||(r.add(_.id),s.push(_));}catch(u){throw new d("DB_ERROR","Failed to find child tasks",u)}finally{l.close();}}return s}getWorkspaceUsageSummary(t){if(!this.dbExists())return [];let e=this.openHandle(false);try{return e.db.all(t?sql`
51
+ WHERE id=? AND status='running' AND COALESCE(run_epoch, 0) = COALESCE(?, 0)`,[e.status,e.result??null,e.error??null,e.completedAt,e.durationMs??null,e.exitCode??null,e.inputTokens??0,e.outputTokens??0,e.cachedInputTokens??0,e.costUsd??0,e.model??null,e.id,r]);}catch(r){throw r instanceof c?r:new c("DB_ERROR","Failed to finish task",r)}finally{t.close();}}appendLog(e,t){this.taskLogRepository.appendLog(e,t);}appendLogs(e,t){this.taskLogRepository.appendLogs(e,t);}readLogs(e){return this.taskLogRepository.readLogs(e)}readLogsTail(e,t){return this.taskLogRepository.readLogsTail(e,t)}getLogState(e){return this.taskLogRepository.getLogState(e)}getRunningTasks(){if(!this.dbExists())return [];let e=this.openHandle(false);try{return e.db.select().from(a).where(eq(a.status,"running")).orderBy(desc(a.started_at)).all()}catch(t){throw new c("DB_ERROR","Failed to get running tasks",t)}finally{e.close();}}getAllTasks(){if(!this.dbExists())return [];let e=this.openHandle(false);try{return e.db.select().from(a).orderBy(desc(a.started_at)).limit(100).all()}catch(t){throw new c("DB_ERROR","Failed to get all tasks",t)}finally{e.close();}}getTask(e){if(!this.dbExists())return;let t=this.openHandle(false);try{return t.db.select().from(a).where(eq(a.id,e)).limit(1).get()??void 0}catch(r){throw new c("DB_ERROR","Failed to get task",r)}finally{t.close();}}killTask(e){if(!this.dbExists())return {killed:false};let t=this.openHandle(true);try{let r=t.db.select({id:a.id,status:a.status,pid:a.pid}).from(a).where(eq(a.id,e)).limit(1).get();if(!r||r.status!=="running")return {killed:!1};if(r.pid)try{process.kill(r.pid,"SIGTERM");}catch{}return t.db.update(a).set({status:"failed",error:"Killed by user",completed_at:new Date().toISOString()}).where(and(eq(a.id,e),eq(a.status,"running"))).run(),{killed:!0,pid:r.pid??void 0}}catch(r){throw r instanceof c?r:new c("DB_ERROR","Failed to kill task",r)}finally{t.close();}}reapOrphanedTasks(){if(!this.dbExists())return 0;let e=this.openHandle(true);try{let t=e.db.select({id:a.id,pid:a.pid,platform:a.platform,run_epoch:a.run_epoch}).from(a).where(eq(a.status,"running")).all(),r=Date.now(),o=new Set,i=0;for(let s of t){if(s.pid){let u=!1;try{process.kill(s.pid,0),u=!0;}catch{}u||(e.db.update(a).set({status:"failed",error:"Reaped: process not found (orphaned task)",completed_at:new Date().toISOString()}).where(and(eq(a.id,s.id),eq(a.status,"running"))).run(),i++);continue}if(ia.has(s.platform??"cli"))continue;let d=`${s.id}:${s.run_epoch??0}`;o.add(d);let l=this.pidNullObservedSince.get(d);if(l===void 0){this.pidNullObservedSince.set(d,r);continue}r-l>=uo&&(e.db.update(a).set({status:"failed",error:"Reaped: pid never recorded after resume (stale running_instruction)",completed_at:new Date().toISOString()}).where(and(eq(a.id,s.id),eq(a.status,"running"))).run(),i++,this.pidNullObservedSince.delete(d));}for(let s of Array.from(this.pidNullObservedSince.keys()))o.has(s)||this.pidNullObservedSince.delete(s);return i}finally{e.close();}}reapRunningWorkflowTasks(e=uo){if(!this.dbExists())return 0;let t=this.openHandle(true);try{let r=new Date(Date.now()-e).toISOString();return t.db.update(a).set({status:"failed",error:"Reaped: stale workflow run (finally not executed)",completed_at:new Date().toISOString()}).where(and(eq(a.status,"running"),eq(a.platform,"workflow"),isNull(a.pid),lt(a.started_at,r),or(isNull(a.metadata),and(notLike(a.metadata,'%"kind":"workflow_card"%'),notLike(a.metadata,'%"kind":"workflow_ui_instance"%'))))).run().changes??0}finally{t.close();}}findTaskStatus(e,t){let r=this.resolveDbPaths();for(let o of r){if(!existsSync(o))continue;let i=T(o);try{let s=t?eq(a.workspace_id,t):void 0,d=s?and(eq(a.id,e),s):eq(a.id,e),l=i.db.select().from(a).where(d).limit(1).get()??void 0;if(!l){let u=s?and(eq(a.thread_id,e),s):eq(a.thread_id,e);l=i.db.select().from(a).where(u).orderBy(desc(a.started_at)).limit(1).get()??void 0;}if(l)return l}catch(s){throw new c("DB_ERROR","Failed to find task status",s)}finally{i.close();}}}findChildTasks(e,t){let r=this.resolveDbPaths(),o=new Set,i=[];for(let s of r){if(!existsSync(s))continue;let d=T(s);try{let l=t?and(eq(a.parent_task_id,e),eq(a.workspace_id,t)):eq(a.parent_task_id,e),u=d.db.select().from(a).where(l).orderBy(asc(a.started_at)).all();for(let h of u)o.has(h.id)||(o.add(h.id),i.push(h));}catch(l){throw new c("DB_ERROR","Failed to find child tasks",l)}finally{d.close();}}return i}getWorkspaceUsageSummary(e){if(!this.dbExists())return [];let t=this.openHandle(false);try{return t.db.all(e?sql`
12
52
  SELECT
13
53
  COALESCE(workspace_id, 'unknown') AS workspace_id,
14
54
  COALESCE(SUM(input_tokens), 0) AS input_tokens,
@@ -16,7 +56,7 @@ ${n.join(`
16
56
  COALESCE(SUM(cost_usd), 0) AS cost_usd,
17
57
  COUNT(*) AS task_count
18
58
  FROM tasks
19
- WHERE workspace_id = ${t}
59
+ WHERE workspace_id = ${e}
20
60
  GROUP BY workspace_id
21
61
  ORDER BY (COALESCE(SUM(input_tokens), 0) + COALESCE(SUM(output_tokens), 0)) DESC
22
62
  `:sql`
@@ -29,7 +69,7 @@ ${n.join(`
29
69
  FROM tasks
30
70
  GROUP BY workspace_id
31
71
  ORDER BY (COALESCE(SUM(input_tokens), 0) + COALESCE(SUM(output_tokens), 0)) DESC
32
- `)}catch(n){throw new d("DB_ERROR","Failed to get workspace usage summary",n)}finally{e.close();}}getThreadTokenUsage(t,e){let n=this.resolveDbPaths(),r=new Set,s=0,o=0,l=0;for(let u of n){if(!existsSync(u))continue;let c=k(u);try{let _=or(eq(i.thread_id,t),and(isNull(i.thread_id),like(i.command,`%--thread=${t}%`))),m=e?and(_,eq(i.workspace_id,e)):_,g=c.db.select({id:i.id,input_tokens:i.input_tokens,output_tokens:i.output_tokens,cost_usd:i.cost_usd}).from(i).where(m).all();for(let R of g)r.has(R.id)||(r.add(R.id),s+=R.input_tokens??0,o+=R.output_tokens??0,l+=R.cost_usd??0);}catch(_){throw new d("DB_ERROR","Failed to get thread token usage",_)}finally{c.close();}}return {inputTokens:s,outputTokens:o,costUsd:l}}findTasksByThread(t,e){let n=this.resolveDbPaths(),r=new Set,s=[];for(let o of n){if(!existsSync(o))continue;let l=k(o);try{let u=or(eq(i.thread_id,t),and(isNull(i.thread_id),like(i.command,`%--thread=${t}%`))),c=e?and(u,eq(i.workspace_id,e)):u,_=l.db.select().from(i).where(c).orderBy(asc(i.started_at)).all();for(let m of _)r.has(m.id)||(r.add(m.id),s.push(m));}catch(u){throw new d("DB_ERROR","Failed to find tasks by thread",u)}finally{l.close();}}return s}findAllTasks(t){if(!this.dbExists())return {rows:[],total:0};let e=this.openHandle(false);try{let n=[];t.workspaceId&&n.push(eq(i.workspace_id,t.workspaceId));let r=t.agents&&t.agents.length>0?t.agents:t.agentId?[t.agentId]:null;r&&n.push(inArray(i.agent_id,r));let s=t.statuses&&t.statuses.length>0?t.statuses:t.status?[t.status]:null;s&&n.push(inArray(i.status,s));let o=t.q??t.search;o&&n.push(like(i.prompt,`%${o}%`)),t.from&&n.push(gte(i.started_at,t.from)),t.to&&n.push(lt$1(i.started_at,t.to));let l=n.length>0?and(...n):void 0,u=e.db.select({count:sql`count(*)`}).from(i).where(l).get(),c=(t.sortDir??"DESC")==="ASC"?asc(i.started_at):desc(i.started_at);return {rows:e.db.select().from(i).where(l).orderBy(c).limit(t.limit).offset(t.offset).all(),total:u?.count??0}}catch(n){throw new d("DB_ERROR","Failed to find all tasks",n)}finally{e.close();}}getAgentUsage(t,e,n){if(!this.dbExists())return [];let r=this.openHandle(false);try{return r.db.all(n?sql`
72
+ `)}catch(r){throw new c("DB_ERROR","Failed to get workspace usage summary",r)}finally{t.close();}}getThreadTokenUsage(e,t){let r=this.resolveDbPaths(),o=new Set,i=0,s=0,d=0;for(let l of r){if(!existsSync(l))continue;let u=T(l);try{let h=eq(a.thread_id,e),g=t?and(h,eq(a.workspace_id,t)):h,p=u.db.select({id:a.id,input_tokens:a.input_tokens,output_tokens:a.output_tokens,cost_usd:a.cost_usd}).from(a).where(g).all();for(let f of p)o.has(f.id)||(o.add(f.id),i+=f.input_tokens??0,s+=f.output_tokens??0,d+=f.cost_usd??0);}catch(h){throw new c("DB_ERROR","Failed to get thread token usage",h)}finally{u.close();}}return {inputTokens:i,outputTokens:s,costUsd:d}}findTasksByThread(e,t,r){let o=this.resolveDbPaths(),i=new Set,s=[],d=r?.projection==="activity-log";for(let l of o){if(!existsSync(l))continue;let u=T(l);try{let h=eq(a.thread_id,e),g=t?and(h,eq(a.workspace_id,t)):h,p=d?u.db.select({id:a.id,thread_id:a.thread_id,agent_id:a.agent_id,parent_task_id:a.parent_task_id,started_at:a.started_at,completed_at:a.completed_at}).from(a).where(g).orderBy(asc(a.started_at)).all():u.db.select().from(a).where(g).orderBy(asc(a.started_at)).all();for(let f of p)i.has(f.id)||(i.add(f.id),s.push(f));}catch(h){throw new c("DB_ERROR","Failed to find tasks by thread",h)}finally{u.close();}}return s}parseWorkflowCardMetadata(e){if(!e)return {};try{let t=JSON.parse(e);return {kind:typeof t.kind=="string"?t.kind:void 0,workflowRunId:typeof t.workflowRunId=="string"?t.workflowRunId:void 0}}catch{return {}}}extractThreadIdFromCommand(e){return e?/--thread=(\S+)/.exec(e)?.[1]??null:null}findRunningWorkflowParentTasks(){if(!this.dbExists())return [];let e=[];for(let t of this.resolveDbPaths()){if(!existsSync(t))continue;let r=T(t);try{e.push(...r.db.select({id:a.id,agent_id:a.agent_id,thread_id:a.thread_id,workspace_id:a.workspace_id,platform:a.platform,status:a.status,error:a.error,completed_at:a.completed_at,duration_ms:a.duration_ms,started_at:a.started_at,metadata:a.metadata}).from(a).where(and(eq(a.platform,"workflow"),or(like(a.metadata,'%"kind":"workflow_card"%'),like(a.metadata,'%"kind":"workflow_ui_instance"%')))).orderBy(desc(a.started_at)).all());}catch(o){throw new c("DB_ERROR","Failed to find workflow parent tasks",o)}finally{r.close();}}return e}batchFetchWorkflowCards(e,t){let r=new Map;if(e.length===0)return r;let o=new Set(e),i=new Map,s=t?eq(a.workspace_id,t):void 0,d=(l,u)=>{if(!l)return;let h=i.get(l);if(h&&u.started_at<=h)return;let g=this.parseWorkflowCardMetadata(u.metadata);g.kind!=="workflow_card"&&g.kind!=="workflow_ui_instance"||(i.set(l,u.started_at),r.set(l,{taskId:u.id,workflowRunId:g.workflowRunId,raw:u.result??void 0}));};for(let l of this.resolveDbPaths()){if(!existsSync(l))continue;let u=T(l);try{let h=and(inArray(a.thread_id,e),or(like(a.metadata,'%"kind":"workflow_card"%'),like(a.metadata,'%"kind":"workflow_ui_instance"%'))),g=u.db.select({id:a.id,thread_id:a.thread_id,metadata:a.metadata,result:a.result,started_at:a.started_at}).from(a).where(s?and(h,s):h).all();for(let O of g)d(O.thread_id,O);let p=and(isNull(a.thread_id),or(like(a.metadata,'%"kind":"workflow_card"%'),like(a.metadata,'%"kind":"workflow_ui_instance"%'))),f=u.db.select({id:a.id,command:a.command,metadata:a.metadata,result:a.result,started_at:a.started_at}).from(a).where(s?and(p,s):p).all();for(let O of f){let w=this.extractThreadIdFromCommand(O.command);!w||!o.has(w)||d(w,O);}}catch(h){throw new c("DB_ERROR","Failed to batch fetch workflow cards",h)}finally{u.close();}}return r}findAllTasks(e){if(!this.dbExists())return {rows:[],total:0};let t=this.openHandle(false);try{let r=[];e.workspaceId&&r.push(eq(a.workspace_id,e.workspaceId));let o=e.agents&&e.agents.length>0?e.agents:e.agentId?[e.agentId]:null;o&&r.push(inArray(a.agent_id,o));let i=e.statuses&&e.statuses.length>0?e.statuses:e.status?[e.status]:null;i&&r.push(inArray(a.status,i));let s=e.q??e.search;s&&r.push(like(a.prompt,`%${s}%`)),e.from&&r.push(gte(a.started_at,e.from)),e.to&&r.push(lt(a.started_at,e.to));let d=r.length>0?and(...r):void 0,l=t.db.select({count:sql`count(*)`}).from(a).where(d).get(),u=(e.sortDir??"DESC")==="ASC"?asc(a.started_at):desc(a.started_at);return {rows:t.db.select().from(a).where(d).orderBy(u).limit(e.limit).offset(e.offset).all(),total:l?.count??0}}catch(r){throw new c("DB_ERROR","Failed to find all tasks",r)}finally{t.close();}}getAgentUsage(e,t,r){if(!this.dbExists())return [];let o=this.openHandle(false);try{return o.db.all(r?sql`
33
73
  SELECT
34
74
  t.agent_id,
35
75
  t.workspace_id,
@@ -37,11 +77,11 @@ ${n.join(`
37
77
  COALESCE(SUM(
38
78
  COALESCE(t.input_tokens, 0)
39
79
  + CASE
40
- WHEN t.started_at >= ${Q}
80
+ WHEN t.started_at >= ${We}
41
81
  AND (
42
82
  t.crewx_version IS NULL
43
83
  OR (t.crewx_version LIKE '0.8.%' AND t.crewx_version NOT LIKE '0.8.9%')
44
- OR (t.crewx_version LIKE '0.8.9-rc.%' AND CAST(SUBSTR(t.crewx_version, ${Z}) AS INTEGER) < ${tt})
84
+ OR (t.crewx_version LIKE '0.8.9-rc.%' AND CAST(SUBSTR(t.crewx_version, ${Ve}) AS INTEGER) < ${Ke})
45
85
  )
46
86
  THEN COALESCE(t.cached_input_tokens, 0)
47
87
  ELSE 0
@@ -52,19 +92,19 @@ ${n.join(`
52
92
  COALESCE(SUM(t.cost_usd), 0) AS cost_usd
53
93
  FROM tasks t
54
94
  WHERE t.status IN ('completed', 'success')
55
- AND t.started_at >= ${t}
56
- AND t.started_at < ${e}
57
- AND t.workspace_id = ${n}
95
+ AND t.started_at >= ${e}
96
+ AND t.started_at < ${t}
97
+ AND t.workspace_id = ${r}
58
98
  GROUP BY t.agent_id, t.workspace_id
59
99
  ORDER BY (
60
100
  COALESCE(SUM(
61
101
  COALESCE(t.input_tokens, 0)
62
102
  + CASE
63
- WHEN t.started_at >= ${Q}
103
+ WHEN t.started_at >= ${We}
64
104
  AND (
65
105
  t.crewx_version IS NULL
66
106
  OR (t.crewx_version LIKE '0.8.%' AND t.crewx_version NOT LIKE '0.8.9%')
67
- OR (t.crewx_version LIKE '0.8.9-rc.%' AND CAST(SUBSTR(t.crewx_version, ${Z}) AS INTEGER) < ${tt})
107
+ OR (t.crewx_version LIKE '0.8.9-rc.%' AND CAST(SUBSTR(t.crewx_version, ${Ve}) AS INTEGER) < ${Ke})
68
108
  )
69
109
  THEN COALESCE(t.cached_input_tokens, 0)
70
110
  ELSE 0
@@ -80,11 +120,11 @@ ${n.join(`
80
120
  COALESCE(SUM(
81
121
  COALESCE(t.input_tokens, 0)
82
122
  + CASE
83
- WHEN t.started_at >= ${Q}
123
+ WHEN t.started_at >= ${We}
84
124
  AND (
85
125
  t.crewx_version IS NULL
86
126
  OR (t.crewx_version LIKE '0.8.%' AND t.crewx_version NOT LIKE '0.8.9%')
87
- OR (t.crewx_version LIKE '0.8.9-rc.%' AND CAST(SUBSTR(t.crewx_version, ${Z}) AS INTEGER) < ${tt})
127
+ OR (t.crewx_version LIKE '0.8.9-rc.%' AND CAST(SUBSTR(t.crewx_version, ${Ve}) AS INTEGER) < ${Ke})
88
128
  )
89
129
  THEN COALESCE(t.cached_input_tokens, 0)
90
130
  ELSE 0
@@ -95,18 +135,18 @@ ${n.join(`
95
135
  COALESCE(SUM(t.cost_usd), 0) AS cost_usd
96
136
  FROM tasks t
97
137
  WHERE t.status IN ('completed', 'success')
98
- AND t.started_at >= ${t}
99
- AND t.started_at < ${e}
138
+ AND t.started_at >= ${e}
139
+ AND t.started_at < ${t}
100
140
  GROUP BY t.agent_id, t.workspace_id
101
141
  ORDER BY (
102
142
  COALESCE(SUM(
103
143
  COALESCE(t.input_tokens, 0)
104
144
  + CASE
105
- WHEN t.started_at >= ${Q}
145
+ WHEN t.started_at >= ${We}
106
146
  AND (
107
147
  t.crewx_version IS NULL
108
148
  OR (t.crewx_version LIKE '0.8.%' AND t.crewx_version NOT LIKE '0.8.9%')
109
- OR (t.crewx_version LIKE '0.8.9-rc.%' AND CAST(SUBSTR(t.crewx_version, ${Z}) AS INTEGER) < ${tt})
149
+ OR (t.crewx_version LIKE '0.8.9-rc.%' AND CAST(SUBSTR(t.crewx_version, ${Ve}) AS INTEGER) < ${Ke})
110
150
  )
111
151
  THEN COALESCE(t.cached_input_tokens, 0)
112
152
  ELSE 0
@@ -114,18 +154,18 @@ ${n.join(`
114
154
  ), 0)
115
155
  + COALESCE(SUM(t.output_tokens), 0)
116
156
  ) DESC
117
- `).map(o=>({agentId:o.agent_id,workspaceId:o.workspace_id??null,totalTasks:o.total_tasks,inputTokens:o.input_tokens,outputTokens:o.output_tokens,cachedInputTokens:o.cached_input_tokens,costUsd:o.cost_usd,totalTokens:o.input_tokens+o.output_tokens}))}catch(s){throw new d("DB_ERROR","Failed to get agent usage",s)}finally{r.close();}}getAgentUsageTrendRaw(t,e,n){if(!this.dbExists())return [];let r=this.openHandle(false);try{return r.db.all(n?sql`
157
+ `).map(s=>({agentId:s.agent_id,workspaceId:s.workspace_id??null,totalTasks:s.total_tasks,inputTokens:s.input_tokens,outputTokens:s.output_tokens,cachedInputTokens:s.cached_input_tokens,costUsd:s.cost_usd,totalTokens:s.input_tokens+s.output_tokens}))}catch(i){throw new c("DB_ERROR","Failed to get agent usage",i)}finally{o.close();}}getAgentUsageTrendRaw(e,t,r){if(!this.dbExists())return [];let o=this.openHandle(false);try{return o.db.all(r?sql`
118
158
  SELECT
119
159
  date(t.started_at) AS date,
120
160
  t.agent_id,
121
161
  COALESCE(SUM(
122
162
  COALESCE(t.input_tokens, 0)
123
163
  + CASE
124
- WHEN t.started_at >= ${Q}
164
+ WHEN t.started_at >= ${We}
125
165
  AND (
126
166
  t.crewx_version IS NULL
127
167
  OR (t.crewx_version LIKE '0.8.%' AND t.crewx_version NOT LIKE '0.8.9%')
128
- OR (t.crewx_version LIKE '0.8.9-rc.%' AND CAST(SUBSTR(t.crewx_version, ${Z}) AS INTEGER) < ${tt})
168
+ OR (t.crewx_version LIKE '0.8.9-rc.%' AND CAST(SUBSTR(t.crewx_version, ${Ve}) AS INTEGER) < ${Ke})
129
169
  )
130
170
  THEN COALESCE(t.cached_input_tokens, 0)
131
171
  ELSE 0
@@ -136,9 +176,9 @@ ${n.join(`
136
176
  COALESCE(SUM(t.cost_usd), 0) AS cost_usd
137
177
  FROM tasks t
138
178
  WHERE t.status IN ('completed', 'success')
139
- AND t.started_at >= ${t}
140
- AND t.started_at < ${e}
141
- AND t.workspace_id = ${n}
179
+ AND t.started_at >= ${e}
180
+ AND t.started_at < ${t}
181
+ AND t.workspace_id = ${r}
142
182
  GROUP BY date(t.started_at), t.agent_id
143
183
  ORDER BY date(t.started_at) ASC
144
184
  `:sql`
@@ -148,11 +188,11 @@ ${n.join(`
148
188
  COALESCE(SUM(
149
189
  COALESCE(t.input_tokens, 0)
150
190
  + CASE
151
- WHEN t.started_at >= ${Q}
191
+ WHEN t.started_at >= ${We}
152
192
  AND (
153
193
  t.crewx_version IS NULL
154
194
  OR (t.crewx_version LIKE '0.8.%' AND t.crewx_version NOT LIKE '0.8.9%')
155
- OR (t.crewx_version LIKE '0.8.9-rc.%' AND CAST(SUBSTR(t.crewx_version, ${Z}) AS INTEGER) < ${tt})
195
+ OR (t.crewx_version LIKE '0.8.9-rc.%' AND CAST(SUBSTR(t.crewx_version, ${Ve}) AS INTEGER) < ${Ke})
156
196
  )
157
197
  THEN COALESCE(t.cached_input_tokens, 0)
158
198
  ELSE 0
@@ -163,55 +203,117 @@ ${n.join(`
163
203
  COALESCE(SUM(t.cost_usd), 0) AS cost_usd
164
204
  FROM tasks t
165
205
  WHERE t.status IN ('completed', 'success')
166
- AND t.started_at >= ${t}
167
- AND t.started_at < ${e}
206
+ AND t.started_at >= ${e}
207
+ AND t.started_at < ${t}
168
208
  GROUP BY date(t.started_at), t.agent_id
169
209
  ORDER BY date(t.started_at) ASC
170
- `).map(o=>({date:o.date,agentId:o.agent_id,inputTokens:o.input_tokens,outputTokens:o.output_tokens,cachedInputTokens:o.cached_input_tokens,costUsd:o.cost_usd,totalTokens:o.input_tokens+o.output_tokens}))}catch(s){throw new d("DB_ERROR","Failed to get agent usage trend",s)}finally{r.close();}}findTaskForStop(t,e){if(!this.dbExists())return;let n=this.openHandle(false);try{return n.db.select().from(i).where(and(eq(i.id,t),eq(i.workspace_id,e))).limit(1).get()??void 0}catch(r){throw new d("DB_ERROR","Failed to find task for stop",r)}finally{n.close();}}markTaskFailed(t,e,n){if(!this.dbExists())return;let r=this.openHandle(true);try{let s=new Date().toISOString(),o=n?and(eq(i.id,t),eq(i.status,"running"),eq(i.workspace_id,n)):and(eq(i.id,t),eq(i.status,"running"));r.db.update(i).set({status:"failed",error:e,completed_at:s}).where(o).run();}catch(s){throw s instanceof d?s:new d("DB_ERROR","Failed to mark task failed",s)}finally{r.close();}}findTasksByPromptHint(t,e){let n=this.resolveDbPaths(),r=new Set,s=[];for(let o of n){if(!existsSync(o))continue;let l=k(o);try{let u=e?and(like(i.prompt,`%${t}%`),eq(i.workspace_id,e)):like(i.prompt,`%${t}%`),c=l.db.select().from(i).where(u).orderBy(asc(i.started_at)).all();for(let _ of c)r.has(_.id)||(r.add(_.id),s.push(_));}catch(u){throw new d("DB_ERROR","Failed to find tasks by prompt hint",u)}finally{l.close();}}return s}getProviderUsage(t,e,n){if(!this.dbExists())return [];let r=this.openHandle(false);try{let s=sql`
171
- CASE
172
- WHEN ${i.model} LIKE 'claude-%' OR ${i.model} IN ('opus', 'sonnet', 'haiku', 'opus[1m]', 'sonnet[1m]') THEN 'claude'
173
- WHEN ${i.model} LIKE 'gpt-%' OR ${i.model} LIKE 'codex-%' THEN 'codex'
174
- WHEN ${i.model} LIKE 'gemini-%' THEN 'gemini'
175
- WHEN ${i.model} LIKE 'zai-%' OR ${i.model} LIKE 'openrouter/z-ai/%' THEN 'opencode'
176
- WHEN ${i.model} LIKE 'minimax/%' THEN 'minimax'
177
- WHEN ${i.model} LIKE 'qwen%' THEN 'qwen'
178
- ELSE 'unknown'
179
- END
180
- `,o=sql`
181
- COALESCE(${i.input_tokens}, 0)
210
+ `).map(s=>({date:s.date,agentId:s.agent_id,inputTokens:s.input_tokens,outputTokens:s.output_tokens,cachedInputTokens:s.cached_input_tokens,costUsd:s.cost_usd,totalTokens:s.input_tokens+s.output_tokens}))}catch(i){throw new c("DB_ERROR","Failed to get agent usage trend",i)}finally{o.close();}}findTaskForStop(e,t){if(!this.dbExists())return;let r=this.openHandle(false);try{return r.db.select().from(a).where(and(eq(a.id,e),eq(a.workspace_id,t))).limit(1).get()??void 0}catch(o){throw new c("DB_ERROR","Failed to find task for stop",o)}finally{r.close();}}findLatestTaskByMetadata(e){if(!this.dbExists())return null;let t=this.openHandle(false);try{return t.db.select({id:a.id,thread_id:a.thread_id,status:a.status,result:a.result,error:a.error,started_at:a.started_at,completed_at:a.completed_at,metadata:a.metadata}).from(a).where(and(eq(a.agent_id,e.agentId),eq(a.workspace_id,e.workspaceId),sql`${a.metadata} IS NOT NULL AND json_valid(${a.metadata}) AND json_extract(${a.metadata}, '$.' || ${e.metaKey}) = ${e.metaValue}`)).orderBy(desc(a.started_at)).limit(1).get()??null}catch(r){throw new c("DB_ERROR","Failed to find latest task by metadata",r)}finally{t.close();}}markTaskFailed(e,t,r){if(!this.dbExists())return;let o=this.openHandle(true);try{let i=new Date().toISOString(),s=r?and(eq(a.id,e),eq(a.status,"running"),eq(a.workspace_id,r)):and(eq(a.id,e),eq(a.status,"running"));o.db.update(a).set({status:"failed",error:t,completed_at:i}).where(s).run();}catch(i){throw i instanceof c?i:new c("DB_ERROR","Failed to mark task failed",i)}finally{o.close();}}findTasksByPromptHint(e,t){let r=this.resolveDbPaths(),o=new Set,i=[];for(let s of r){if(!existsSync(s))continue;let d=T(s);try{let l=t?and(like(a.prompt,`%${e}%`),eq(a.workspace_id,t)):like(a.prompt,`%${e}%`),u=d.db.select().from(a).where(l).orderBy(asc(a.started_at)).all();for(let h of u)o.has(h.id)||(o.add(h.id),i.push(h));}catch(l){throw new c("DB_ERROR","Failed to find tasks by prompt hint",l)}finally{d.close();}}return i}getProviderUsage(e,t,r){if(!this.dbExists())return [];let o=this.openHandle(false);try{let i=lo(),s=sql`
211
+ COALESCE(${a.input_tokens}, 0)
182
212
  + CASE
183
- WHEN ${i.started_at} >= ${Q}
213
+ WHEN ${a.started_at} >= ${We}
184
214
  AND (
185
- ${i.crewx_version} IS NULL
186
- OR (${i.crewx_version} LIKE '0.8.%' AND ${i.crewx_version} NOT LIKE '0.8.9%')
187
- OR (${i.crewx_version} LIKE '0.8.9-rc.%' AND CAST(SUBSTR(${i.crewx_version}, ${Z}) AS INTEGER) < ${tt})
215
+ ${a.crewx_version} IS NULL
216
+ OR (${a.crewx_version} LIKE '0.8.%' AND ${a.crewx_version} NOT LIKE '0.8.9%')
217
+ OR (${a.crewx_version} LIKE '0.8.9-rc.%' AND CAST(SUBSTR(${a.crewx_version}, ${Ve}) AS INTEGER) < ${Ke})
188
218
  )
189
- THEN COALESCE(${i.cached_input_tokens}, 0)
219
+ THEN COALESCE(${a.cached_input_tokens}, 0)
190
220
  ELSE 0
191
221
  END
192
- `,l=n?sql`WHERE ${i.status} IN ('completed', 'success') AND ${i.started_at} >= ${t} AND ${i.started_at} < ${e} AND ${i.workspace_id} = ${n}`:sql`WHERE ${i.status} IN ('completed', 'success') AND ${i.started_at} >= ${t} AND ${i.started_at} < ${e}`;return r.db.all(sql`
222
+ `,d=r?sql`WHERE ${a.status} IN ('completed', 'success') AND ${a.started_at} >= ${e} AND ${a.started_at} < ${t} AND ${a.workspace_id} = ${r}`:sql`WHERE ${a.status} IN ('completed', 'success') AND ${a.started_at} >= ${e} AND ${a.started_at} < ${t}`;return o.db.all(sql`
193
223
  SELECT
194
- ${s} AS provider,
224
+ ${i} AS provider,
195
225
  COUNT(*) AS total_tasks,
196
- COALESCE(SUM(${o}), 0) AS input_tokens,
197
- COALESCE(SUM(${i.output_tokens}), 0) AS output_tokens,
198
- COALESCE(SUM(${i.cached_input_tokens}), 0) AS cached_input_tokens,
199
- COALESCE(SUM(${i.cost_usd}), 0) AS cost_usd,
200
- COALESCE(SUM(${i.duration_ms}), 0) AS active_duration_ms,
201
- MAX(${i.completed_at}) AS last_active_at
202
- FROM ${i}
203
- ${l}
204
- GROUP BY provider
205
- ORDER BY (COALESCE(SUM(${o}), 0) + COALESCE(SUM(${i.output_tokens}), 0)) DESC
206
- `).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(s){throw new d("DB_ERROR","Failed to get provider usage",s)}finally{r.close();}}};var At=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 r=dirname(e);existsSync(r)||mkdirSync(r,{recursive:true});}else if(!existsSync(e))throw new d("NOT_FOUND","Database not found");let n=k(e);if(t)try{O(n.db,e);}catch(r){throw n.close(),r}return n}validateWorkspaceId(t,e){return t.db.select({id:h.id}).from(h).where(eq(h.id,e)).limit(1).get()?e:null}topLevelTaskPredicateSql(t="child"){return sql.raw(`(
207
- ${t}.parent_task_id IS NULL
208
- OR ${t}.parent_task_id = ''
209
- OR NOT EXISTS (
210
- SELECT 1 FROM tasks parent
211
- WHERE parent.id = ${t}.parent_task_id
212
- AND parent.thread_id = ${t}.thread_id
213
- )
214
- )`)}findAllThreads(t){let e=this.resolveDbPaths(),n=new Set,r=[];for(let s of e){if(!existsSync(s))continue;let o=k(s);try{let l=t?eq(p.workspace_id,t):void 0,u=o.db.select().from(p).where(l).orderBy(desc(p.updated_at)).all();for(let c of u)n.has(c.id)||(n.add(c.id),r.push(c));}catch(l){throw new d("DB_ERROR","Failed to find all threads",l)}finally{o.close();}}return r}findThreadById(t,e){let n=this.resolveDbPaths();for(let r of n){if(!existsSync(r))continue;let s=k(r);try{let o=eq(p.id,t),l=e?and(o,eq(p.workspace_id,e)):o,u=s.db.select().from(p).where(l).limit(1).get()??void 0;if(u)return u}catch(o){throw new d("DB_ERROR","Failed to find thread by id",o)}finally{s.close();}}}threadExists(t,e){let n=this.resolveDbPaths();for(let r of n){if(!existsSync(r))continue;let s=k(r);try{let o=eq(p.id,t),l=e?and(o,eq(p.workspace_id,e)):o;if(s.db.select({id:p.id}).from(p).where(l).limit(1).get())return !0}catch(o){throw new d("DB_ERROR","Failed to check thread existence",o)}finally{s.close();}}return false}aggregateTaskStats(t,e){let n=this.resolveDbPaths(),r=0,s=0,o=0,l=0,u=0,c=new Set;for(let _ of n){if(!existsSync(_))continue;let m=k(_);try{let g=m.db.get(sql`
226
+ COALESCE(SUM(${s}), 0) AS input_tokens,
227
+ COALESCE(SUM(${a.output_tokens}), 0) AS output_tokens,
228
+ COALESCE(SUM(${a.cached_input_tokens}), 0) AS cached_input_tokens,
229
+ COALESCE(SUM(${a.cost_usd}), 0) AS cost_usd,
230
+ COALESCE(SUM(${a.duration_ms}), 0) AS active_duration_ms,
231
+ MAX(${a.completed_at}) AS last_active_at
232
+ FROM ${a}
233
+ ${d}
234
+ GROUP BY ${i}
235
+ ORDER BY (COALESCE(SUM(${s}), 0) + COALESCE(SUM(${a.output_tokens}), 0)) DESC
236
+ `).map(u=>({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}))}catch(i){throw new c("DB_ERROR","Failed to get provider usage",i)}finally{o.close();}}getModelUsage(e,t,r){if(!this.dbExists())return [];let o=this.openHandle(false);try{let i=lo(),s=sql`
237
+ COALESCE(${a.input_tokens}, 0)
238
+ + CASE
239
+ WHEN ${a.started_at} >= ${We}
240
+ AND (
241
+ ${a.crewx_version} IS NULL
242
+ OR (${a.crewx_version} LIKE '0.8.%' AND ${a.crewx_version} NOT LIKE '0.8.9%')
243
+ OR (${a.crewx_version} LIKE '0.8.9-rc.%' AND CAST(SUBSTR(${a.crewx_version}, ${Ve}) AS INTEGER) < ${Ke})
244
+ )
245
+ THEN COALESCE(${a.cached_input_tokens}, 0)
246
+ ELSE 0
247
+ END
248
+ `,d=r?sql`WHERE ${a.status} IN ('completed', 'success') AND ${a.started_at} >= ${e} AND ${a.started_at} < ${t} AND ${a.workspace_id} = ${r}`:sql`WHERE ${a.status} IN ('completed', 'success') AND ${a.started_at} >= ${e} AND ${a.started_at} < ${t}`,l=o.db.all(sql`
249
+ SELECT
250
+ ${a.model} AS model,
251
+ ${i} AS provider,
252
+ COUNT(*) AS total_tasks,
253
+ COALESCE(SUM(${s}), 0) AS input_tokens,
254
+ COALESCE(SUM(${a.output_tokens}), 0) AS output_tokens,
255
+ COALESCE(SUM(${a.cached_input_tokens}), 0) AS cached_input_tokens,
256
+ COALESCE(SUM(${a.cost_usd}), 0) AS cost_usd,
257
+ COALESCE(SUM(${a.duration_ms}), 0) AS active_duration_ms,
258
+ MAX(${a.completed_at}) AS last_active_at
259
+ FROM ${a}
260
+ ${d}
261
+ GROUP BY ${a.model}, ${i}
262
+ `),u=new Map;for(let h of l){let g=ro(h.model??""),p=JSON.stringify([h.provider,g]),f=u.get(p);f?(f.totalTasks+=h.total_tasks,f.inputTokens+=h.input_tokens,f.outputTokens+=h.output_tokens,f.cachedInputTokens+=h.cached_input_tokens,f.costUsd+=h.cost_usd,f.totalTokens+=h.input_tokens+h.output_tokens,f.activeDurationMs+=h.active_duration_ms??0,h.last_active_at&&(!f.lastActiveAt||h.last_active_at>f.lastActiveAt)&&(f.lastActiveAt=h.last_active_at)):u.set(p,{model:g,provider:h.provider,totalTasks:h.total_tasks,inputTokens:h.input_tokens,outputTokens:h.output_tokens,cachedInputTokens:h.cached_input_tokens,costUsd:h.cost_usd,totalTokens:h.input_tokens+h.output_tokens,activeDurationMs:h.active_duration_ms??0,lastActiveAt:h.last_active_at??null});}return Array.from(u.values()).sort((h,g)=>g.costUsd-h.costUsd)}catch(i){throw new c("DB_ERROR","Failed to get model usage",i)}finally{o.close();}}getTasksForReport(e,t,r){if(!this.dbExists())return [];let o=this.openHandle(false);try{let i=r?sql`WHERE ${a.started_at} >= ${e} AND ${a.started_at} < ${t} AND ${a.workspace_id} = ${r}`:sql`WHERE ${a.started_at} >= ${e} AND ${a.started_at} < ${t}`;return o.db.all(sql`
263
+ SELECT
264
+ ${a.thread_id} AS thread_id,
265
+ ${a.agent_id} AS agent_id,
266
+ ${a.started_at} AS started_at,
267
+ ${a.status} AS status,
268
+ ${a.error} AS error,
269
+ ${a.exit_code} AS exit_code
270
+ FROM ${a}
271
+ ${i}
272
+ ORDER BY ${a.started_at} ASC
273
+ `).map(d=>({threadId:d.thread_id,agentId:d.agent_id,startedAt:d.started_at,status:d.status,error:d.error,exitCode:d.exit_code}))}catch(i){throw new c("DB_ERROR","Failed to get tasks for report",i)}finally{o.close();}}getDelegationMatrix(e,t,r){if(!this.dbExists())return {edges:[],truncated:false};let o=this.openHandle(false);try{let i=sql`
274
+ COALESCE(${a.input_tokens}, 0)
275
+ + CASE
276
+ WHEN ${a.started_at} >= ${We}
277
+ AND (
278
+ ${a.crewx_version} IS NULL
279
+ OR (${a.crewx_version} LIKE '0.8.%' AND ${a.crewx_version} NOT LIKE '0.8.9%')
280
+ OR (${a.crewx_version} LIKE '0.8.9-rc.%' AND CAST(SUBSTR(${a.crewx_version}, ${Ve}) AS INTEGER) < ${Ke})
281
+ )
282
+ THEN COALESCE(${a.cached_input_tokens}, 0)
283
+ ELSE 0
284
+ END
285
+ `,s=r?sql`WHERE ${a.status} IN ('completed', 'success') AND ${a.started_at} >= ${e} AND ${a.started_at} < ${t} AND ${a.workspace_id} = ${r}`:sql`WHERE ${a.status} IN ('completed', 'success') AND ${a.started_at} >= ${e} AND ${a.started_at} < ${t}`,d=o.db.all(sql`
286
+ SELECT
287
+ ${a.caller_agent_id} AS caller_agent_id,
288
+ ${a.agent_id} AS agent_id,
289
+ COUNT(*) AS task_count,
290
+ COALESCE(SUM(${i}), 0) AS input_tokens,
291
+ COALESCE(SUM(${a.output_tokens}), 0) AS output_tokens
292
+ FROM ${a}
293
+ ${s}
294
+ GROUP BY ${a.caller_agent_id}, ${a.agent_id}
295
+ ORDER BY task_count DESC, ${a.caller_agent_id} ASC, ${a.agent_id} ASC
296
+ LIMIT ${Hr+1}
297
+ `),l=d.length>Hr;return {edges:d.slice(0,Hr).map(h=>({callerAgentId:h.caller_agent_id??null,agentId:h.agent_id,taskCount:h.task_count,totalTokens:h.input_tokens+h.output_tokens,outputTokens:h.output_tokens})),truncated:l}}catch(i){throw new c("DB_ERROR","Failed to get delegation matrix",i)}finally{o.close();}}findTaskEvidence(e){if(!this.dbExists())return [];let t=this.openHandle(false);try{let r=[];e.workspaceId&&r.push(eq(a.workspace_id,e.workspaceId)),e.agents&&e.agents.length>0&&r.push(inArray(a.agent_id,e.agents)),e.statuses&&e.statuses.length>0&&r.push(inArray(a.status,e.statuses)),e.from&&r.push(gte(a.started_at,e.from)),e.to&&r.push(lt(a.started_at,e.to));let o=r.length>0?and(...r):void 0,i=(e.order??"DESC")==="ASC"?asc(a.started_at):desc(a.started_at),s={id:a.id,agent_id:a.agent_id,status:a.status,prompt:a.prompt,started_at:a.started_at,completed_at:a.completed_at,thread_id:a.thread_id};return e.limit?t.db.select(s).from(a).where(o).orderBy(i).limit(e.limit).all():t.db.select(s).from(a).where(o).orderBy(i).all()}catch(r){throw new c("DB_ERROR","Failed to find task evidence",r)}finally{t.close();}}findThreadChains(e){if(!this.dbExists())return [];let t=this.openHandle(false);try{let r=e.maxThreads??8,o=e.maxTurnsPerThread??4,i=[isNotNull(a.thread_id),isNull(a.parent_task_id),isNull(a.caller_agent_id),or(isNull(a.platform),ne(a.platform,"workflow")),or(isNull(a.metadata),and(notLike(a.metadata,'%"kind":"workflow_card"%'),notLike(a.metadata,'%"kind":"workflow_ui_instance"%'))),or(isNull(a.metadata),notLike(a.metadata,'%"retriedFromTaskId"%'))];e.workspaceId&&i.push(eq(a.workspace_id,e.workspaceId)),e.from&&i.push(gte(a.started_at,e.from)),e.to&&i.push(lt(a.started_at,e.to));let s=t.db.select({id:a.id,agent_id:a.agent_id,status:a.status,prompt:a.prompt,started_at:a.started_at,completed_at:a.completed_at,thread_id:a.thread_id}).from(a).where(and(...i)).orderBy(asc(a.started_at),asc(a.id)).all(),d=new Map;for(let u of s){if(!u.thread_id)continue;let h={id:u.id,agentId:u.agent_id,status:u.status,prompt:u.prompt,startedAt:u.started_at,completedAt:u.completed_at},g=d.get(u.thread_id);g?g.push(h):d.set(u.thread_id,[h]);}let l=[];for(let[u,h]of d){let g=h.filter(p=>p.agentId===e.targetAgentId).length;g<2||l.push({threadId:u,targetAgentTurnCount:g,turns:h});}return l.sort((u,h)=>{let g=u.turns[u.turns.length-1].startedAt,p=h.turns[h.turns.length-1].startedAt;return g<p?1:g>p?-1:0}),l.slice(0,r).map(u=>({threadId:u.threadId,targetAgentTurnCount:u.targetAgentTurnCount,turns:u.turns.slice(-o)}))}catch(r){throw new c("DB_ERROR","Failed to find thread chains",r)}finally{t.close();}}};var _o=["success","failed","completed"],ar=10*1024*1024*1024,fo=256,ga=new Set(_o),oe=class extends Error{constructor(t,r,o="metadata"){super(r);this.taskId=t;this.kind=o;this.name="MigrationTaskError";}taskId;kind};function mo(n){return n||(process.env.CREWX_DB?process.env.CREWX_DB:process.env.CREWX_TRACES_DB?process.env.CREWX_TRACES_DB:join(homedir(),".crewx","crewx.db"))}function pa(){return rt("better-sqlite3")}function wo(n,e){let t=n===":memory:";if(!t&&!existsSync(n))throw new Error(`Database not found: ${n}`);let r=new(pa())(n,{readonly:e,fileMustExist:!t,timeout:5e3});return r.pragma("foreign_keys = ON"),r.pragma("busy_timeout = 5000"),r}function ft(n,e,t=[]){return n.prepare(e).all(...t)}function _t(n,e,t=[]){return n.prepare(e).get(...t)}function _a(n,e,t=[]){return n.prepare(e).run(...t)}function fa(n,e,t=[]){return n.prepare(e).iterate(...t)}function ma(n){return typeof n=="string"&&n.length>0?n:"<unknown>"}function ko(n){return typeof n=="string"&&ga.has(n)}function ho(n,e){n.set(e,(n.get(e)??0)+1);}function go(n){return Object.fromEntries([...n.entries()].sort(([e],[t])=>e.localeCompare(t)))}function wa(n){let e=new Set(ft(n,"SELECT name FROM sqlite_master WHERE type = 'table' AND name IN ('tasks', 'task_log_events')").map(s=>s.name)),t=["tasks","task_log_events"].filter(s=>!e.has(s));if(t.length>0)throw new Error(`Database schema is missing required table(s): ${t.join(", ")}`);let r=new Set(ft(n,"PRAGMA table_info('tasks')").map(s=>s.name)),i=["id","status","logs","log_storage","last_log_seq","log_revision"].filter(s=>!r.has(s));if(i.length>0)throw new Error(`Database schema is missing required tasks column(s): ${i.join(", ")}`)}function To(n,e){if(e==null)return {entries:[]};if(typeof e!="string")throw new oe(n,"Malformed task logs: tasks.logs must be JSON text or null","malformed");if(e.trim()==="")return {entries:[]};let t;try{t=JSON.parse(e);}catch(o){let i=o instanceof Error?o.message:String(o);throw new oe(n,`Malformed JSON in tasks.logs (${i})`,"malformed")}if(!Array.isArray(t))throw new oe(n,"Malformed task logs: expected a JSON array","malformed");let r=[];for(let[o,i]of t.entries()){if(i===null||typeof i!="object"||typeof i.timestamp!="string"||typeof i.level!="string"||typeof i.message!="string")throw new oe(n,`Malformed task logs: entry ${o} must contain string timestamp, level, and message fields`,"malformed");let s=i;r.push({timestamp:s.timestamp,level:s.level,message:s.message});}return {entries:r}}function qr(n,e){if(!Number.isInteger(n.last_log_seq)||n.last_log_seq<0)throw new oe(n.id,"Invalid last_log_seq metadata","metadata");if(!Number.isInteger(n.log_revision)||n.log_revision<0)throw new oe(n.id,"Invalid log_revision metadata","metadata");if(e==="blob"&&n.last_log_seq!==0)throw new oe(n.id,"Blob source must have last_log_seq=0","metadata")}function ka(n){let e=ft(n,`SELECT task_id, COUNT(*) AS event_count
298
+ FROM task_log_events GROUP BY task_id`);return new Map(e.map(t=>[t.task_id,t.event_count]))}function Ta(n){let e=ka(n),t=new Map,r=[],o=[],i=[],s=new Map,d=new Map,l=0,u=0,h=0,g=0,p=0,f=0;for(let O of fa(n,`SELECT id, status, logs, log_storage, last_log_seq, log_revision
299
+ FROM tasks ORDER BY id`)){let w=O,I=ma(w.status);if(ho(s,I),t.set(w.id,{id:w.id,status:w.status,log_storage:w.log_storage,last_log_seq:w.last_log_seq,log_revision:w.log_revision}),l+=1,w.log_storage==="events"){g+=1;try{qr(w,"events");}catch(ce){i.push(Br(ce,w.id));}w.logs!==null&&i.push({taskId:w.id,reason:"Event source still has a non-null tasks.logs blob",kind:"mixed-source"});continue}if(w.log_storage!=="blob"){i.push({taskId:w.id,reason:`Unknown log_storage value: ${w.log_storage}`,kind:"invalid-source"});continue}u+=1;let E=ko(w.status);E||(h+=1,ho(d,I)),typeof w.logs=="string"?f+=Buffer.byteLength(w.logs,"utf8"):Buffer.isBuffer(w.logs)&&(f+=w.logs.byteLength);let V=e.get(w.id)??0;V>0&&i.push({taskId:w.id,reason:`Blob source already has ${V} task_log_events row(s)`,kind:"mixed-source"});let je;try{je=To(w.id,w.logs),p+=je.entries.length,qr(w,"blob");}catch(ce){let ke=Br(ce,w.id);i.push(ke),ke.kind==="malformed"&&o.push(ke);continue}V>0||E&&r.push(w.id);}return {taskCount:l,candidateTaskCount:u,eligibleTaskCount:r.length,eventSourceTasks:g,statusCounts:go(s),deferredTaskCount:h,deferredStatusCounts:go(d),entryCount:p,sourceBytes:f,candidateIds:r,malformedRows:o,failures:i,tasks:t}}function Br(n,e){return n instanceof oe?{taskId:n.taskId,reason:n.message,kind:n.kind}:{taskId:e,reason:n instanceof Error?n.message:String(n),kind:"metadata"}}function ya(n){return _t(n,"SELECT COUNT(*) AS count FROM tasks WHERE status IN ('pending', 'running')")?.count??0}function Ra(n){return _t(n,"SELECT COUNT(*) AS count FROM tasks WHERE log_storage = 'blob'")?.count??0}function Ea(n){if(n===":memory:")return 0;let e=t=>{try{return statSync(t).size}catch{return 0}};return e(n)+e(`${n}-wal`)}function ba(n,e){return Ea(n)+e*fo}function yo(n,e){return Number.isFinite(n)&&Number.isFinite(e)&&n>=e+ar}function po(n){let e=dirname(resolve(n));for(;!existsSync(e);){let t=dirname(e);if(t===e)break;e=t;}return e}function Ro(n,e,t){let r=[...new Set([po(n),...t?[po(t)]:[]])],o=[],i=Number.POSITIVE_INFINITY;for(let l of r)try{let u=statfsSync(l);i=Math.min(i,u.bavail*u.bsize);}catch(u){i=0,o.push(`Unable to inspect free space for ${l}: ${u instanceof Error?u.message:String(u)}`);}let s=ba(n,e),d=s+ar;return {estimatedFreeSpaceBytes:s,requiredFreeSpaceBytes:d,availableFreeSpaceBytes:Number.isFinite(i)?Math.floor(i):0,minimumFreeSpaceReserveBytes:ar,freeSpaceGatePassed:yo(Number.isFinite(i)?Math.floor(i):0,s),warnings:o}}function Eo(n){return new Set(n.map(e=>e.taskId)).size}function bo(n){try{let e=n.pragma("wal_checkpoint(TRUNCATE)"),t=Array.isArray(e)?e[0]:e,r=t!==null&&typeof t=="object"&&"busy"in t?Number(t.busy):0;return r>0?`WAL checkpoint(TRUNCATE) busy (${r}); continuing without failing migration`:void 0}catch(e){return `WAL checkpoint(TRUNCATE) warning; continuing without failing migration: ${e instanceof Error?e.message:String(e)}`}}function ir(n,e,t,r,o=Ro(e,t.entryCount)){let i=r.failures??t.failures,s=r.malformedRows??t.malformedRows,{ok:d,...l}=r;return {mode:n,ok:d,dbPath:e,activeTaskCount:r.activeTaskCount??0,taskCount:t.taskCount,candidateTaskCount:t.candidateTaskCount,eligibleTaskCount:t.eligibleTaskCount,statusCounts:t.statusCounts,deferredTaskCount:t.deferredTaskCount,deferredStatusCounts:t.deferredStatusCounts,entryCount:t.entryCount,sourceBytes:t.sourceBytes,estimatedFreeSpaceBytes:o.estimatedFreeSpaceBytes,requiredFreeSpaceBytes:o.requiredFreeSpaceBytes,availableFreeSpaceBytes:o.availableFreeSpaceBytes,minimumFreeSpaceReserveBytes:o.minimumFreeSpaceReserveBytes,freeSpaceGatePassed:o.freeSpaceGatePassed,migratedTasks:r.migratedTasks??0,migratedEntries:r.migratedEntries??0,skippedTasks:r.skippedTasks??t.eventSourceTasks,failedTasks:r.failedTasks??Eo(i),malformedRows:s,failures:i,logicalSourceBytesRemoved:r.logicalSourceBytesRemoved??0,warnings:r.warnings??o.warnings,remainingTaskCount:r.remainingTaskCount??t.candidateTaskCount,...l}}function Sa(n,e){return n.length!==e.length?false:n.every((t,r)=>{let o=e[r];return t.seq===r+1&&t.timestamp===o.timestamp&&t.level===o.level&&t.message===o.message})}function Ia(n,e){return n.transaction(()=>{let r=_t(n,`SELECT id, status, logs, log_storage, last_log_seq, log_revision
300
+ FROM tasks WHERE id = ?`,[e]);if(!r)throw new oe(e,"Task disappeared before migration","metadata");if(r.log_storage==="events")return {status:"skipped",entryCount:0,sourceBytes:0};if(r.log_storage!=="blob")throw new oe(e,`Unknown log_storage value: ${r.log_storage}`,"invalid-source");if(!ko(r.status))return {status:"deferred",entryCount:0,sourceBytes:0};let o=r.logs,i=To(e,o);qr(r,"blob");let s=_t(n,"SELECT COUNT(*) AS count FROM task_log_events WHERE task_id = ?",[e])?.count??0;if(s!==0)throw new oe(e,`Blob source already has ${s} task_log_events row(s)`,"mixed-source");let d=n.prepare(`INSERT INTO task_log_events (task_id, seq, timestamp, level, message)
301
+ VALUES (?, ?, ?, ?, ?)`);for(let[g,p]of i.entries.entries())d.run(e,g+1,p.timestamp,p.level,p.message);let l=ft(n,`SELECT seq, timestamp, level, message
302
+ FROM task_log_events WHERE task_id = ? ORDER BY seq`,[e]);if(!Sa(l,i.entries))throw new oe(e,"Event parity check failed before source clear","metadata");if(_a(n,`UPDATE tasks
303
+ SET log_storage = 'events', last_log_seq = ?, log_revision = log_revision + 1, logs = NULL
304
+ WHERE id = ? AND log_storage = 'blob' AND logs IS ?`,[i.entries.length,e,o]).changes!==1)throw new oe(e,"Task changed while migration was in progress","metadata");let h=_t(n,`SELECT id, status, logs, log_storage, last_log_seq, log_revision
305
+ FROM tasks WHERE id = ?`,[e]);if(!h||h.log_storage!=="events"||h.logs!==null||h.last_log_seq!==i.entries.length||h.log_revision!==r.log_revision+1)throw new oe(e,"Final task metadata parity check failed","metadata");return {status:"migrated",entryCount:i.entries.length,sourceBytes:typeof o=="string"?Buffer.byteLength(o,"utf8"):Buffer.isBuffer(o)?o.byteLength:0}}).immediate()}function So(n){let e=new Date().toISOString().replace(/[-:.TZ]/g,"").slice(0,14),t=randomBytes(6).toString("hex");return `${n}.task-log-backup-${e}-${t}.sqlite`}async function va(n,e,t){let r=t??So(e);if(resolve(r)===resolve(e))throw new Error("Backup path must be different from the source database");if(existsSync(r))throw new Error(`Refusing to overwrite existing backup: ${r}`);if(mkdirSync(dirname(r),{recursive:true}),await n.backup(r),!existsSync(r))throw new Error(`SQLite backup was not created: ${r}`);let o=wo(r,true);try{let i=o.pragma("integrity_check",{simple:!0});if(i!=="ok")throw new Error(`Backup integrity check failed: ${i}`)}finally{o.close();}return r}function Ca(n){let e=ft(n,`SELECT task_id AS taskId,
306
+ COUNT(*) AS eventCount,
307
+ COUNT(DISTINCT seq) AS distinctSeqCount,
308
+ MIN(seq) AS minSeq,
309
+ MAX(seq) AS maxSeq
310
+ FROM task_log_events GROUP BY task_id`),t=e.reduce((r,o)=>r+o.eventCount,0);return {rows:e,eventCount:t}}function Je(n,e,t,r={}){return {taskId:n,kind:e,reason:t,...r}}function Da(n,e,t){let r=[];for(let g of t.failures)g.kind==="malformed"?r.push(Je(g.taskId,"malformed-blob",g.reason)):g.kind==="mixed-source"?r.push(Je(g.taskId,"mixed-source",g.reason)):r.push(Je(g.taskId,"source-invariant",g.reason));let o=Ca(n),i=new Map(o.rows.map(g=>[g.taskId,g]));for(let g of o.rows){let p=t.tasks.get(g.taskId);if(!p){r.push(Je(null,"orphan-event",`Event rows reference missing task ${g.taskId}`,{actual:g.eventCount}));continue}(g.minSeq===null||g.minSeq<1||g.distinctSeqCount!==g.maxSeq)&&r.push(Je(p.id,"seq-gap","Task event sequence has a gap or invalid starting sequence",{expected:g.maxSeq??0,actual:g.distinctSeqCount})),p.log_storage==="events"&&p.last_log_seq!==g.eventCount&&r.push(Je(p.id,"count-mismatch","last_log_seq does not match task_log_events row count",{expected:p.last_log_seq??0,actual:g.eventCount}));}for(let g of t.tasks.values())g.log_storage==="events"&&!i.has(g.id)&&g.last_log_seq!==0&&r.push(Je(g.id,"count-mismatch","Event-source task has no rows for its last_log_seq",{expected:g.last_log_seq??0,actual:0}));for(let g of ft(n,`SELECT task_id AS taskId, seq, COUNT(*) AS duplicateCount
311
+ FROM task_log_events GROUP BY task_id, seq HAVING COUNT(*) > 1`))r.push(Je(g.taskId,"duplicate-seq",`Duplicate task event sequence ${g.seq}`,{actual:g.duplicateCount,seq:g.seq}));let s=_t(n,`SELECT COUNT(*) AS count FROM task_log_events
312
+ WHERE seq IS NULL OR seq < 1 OR timestamp IS NULL OR level IS NULL OR message IS NULL`)?.count??0;s>0&&r.push(Je(null,"invalid-event","Event rows contain invalid sequence or null payload fields",{actual:s}));let d=new Set(r.flatMap(g=>g.taskId?[g.taskId]:[])),l=r.map(g=>({taskId:g.taskId??"(orphan)",reason:g.reason,kind:g.kind==="malformed-blob"?"malformed":g.kind==="mixed-source"?"mixed-source":"metadata"})),u=l.filter(g=>g.kind==="malformed"),h={checkedTasks:t.taskCount,eventSourceTasks:t.eventSourceTasks,blobSourceTasks:t.candidateTaskCount,eventCount:o.eventCount,orphanEventCount:r.filter(g=>g.kind==="orphan-event").length,failedTasks:d.size,issues:r};return ir("verify",e,t,{ok:r.length===0,migratedTasks:t.eventSourceTasks,migratedEntries:o.eventCount,skippedTasks:t.candidateTaskCount,failedTasks:d.size,malformedRows:u,failures:l,remainingTaskCount:t.candidateTaskCount,verification:h})}function Na(n){if(n.mode!=="apply"&&n.batchTasks!==void 0)throw new Error("--batch-tasks is only valid with --apply");if(n.batchTasks!==void 0&&(!Number.isInteger(n.batchTasks)||n.batchTasks<1))throw new Error("--batch-tasks must be a positive integer")}async function Aa(n){Na(n);let e=mo(n.dbPath),t=wo(e,n.mode!=="apply");try{wa(t);let r=Ta(t),o=ya(t);if(n.mode==="verify")return {...Da(t,e,r),activeTaskCount:o};if(n.mode==="dry-run")return ir("dry-run",e,r,{ok:r.failures.length===0,activeTaskCount:o,skippedTasks:r.eventSourceTasks,remainingTaskCount:r.candidateTaskCount});let i=n.backupPath??So(e),s=Ro(e,r.entryCount,i);if(!s.freeSpaceGatePassed)return ir("apply",e,r,{ok:!1,activeTaskCount:o,blockedReason:`Apply blocked: available free space (${s.availableFreeSpaceBytes} bytes) is below the required ${s.requiredFreeSpaceBytes} bytes (including a ${s.minimumFreeSpaceReserveBytes} byte reserve)`,skippedTasks:r.eventSourceTasks,remainingTaskCount:r.candidateTaskCount},s);let d=await va(t,e,i),l=[...r.failures],u=n.batchTasks===void 0?r.candidateIds:r.candidateIds.slice(0,n.batchTasks),h=n.batchTasks??Math.max(u.length,1),g=0,p=0,f=0,O=[...s.warnings];for(let[w,I]of u.entries()){try{let E=Ia(t,I);E.status==="migrated"&&(g+=1,p+=E.entryCount,f+=E.sourceBytes);}catch(E){l.push(Br(E,I));}if((w+1)%h===0||w===u.length-1){let E=bo(t);E&&O.push(E);}}return ir("apply",e,r,{ok:l.length===0,activeTaskCount:o,backupPath:d,backupMethod:"sqlite-online-backup",migratedTasks:g,migratedEntries:p,logicalSourceBytesRemoved:f,failedTasks:Eo(l),failures:l,malformedRows:r.malformedRows,remainingTaskCount:Ra(t),skippedTasks:r.eventSourceTasks,warnings:O},s)}finally{t.close();}}function Oa(n){return basename(n)}var at=class extends c{reason;constructor(e,t=e){super("VALIDATION",t),this.name="ThreadTitleMetadataPatchError",this.reason=e;}};function Ot(n){if(!n)return {};try{let e=JSON.parse(n);return !e||typeof e!="object"||Array.isArray(e)?{}:e}catch{return {}}}function $a(n){let t=Ot(n).threadTitle;if(!t||typeof t!="object"||Array.isArray(t))return {priority:null,state:null};let r=t;return {priority:typeof r.priority=="string"?r.priority:null,state:typeof r.state=="string"?r.state:null}}var Fr=class extends x{dbPath;constructor(e={}){super(),e.dbPath?this.dbPath=e.dbPath:e.dbRoot&&(this.dbPath=join(e.dbRoot,".crewx","crewx.db"));}resolveDbPath(){return this.dbPath?this.dbPath:super.resolveDbPath()}openHandle(e){let t=this.resolveDbPath();if(e){let o=dirname(t);existsSync(o)||mkdirSync(o,{recursive:true});}else if(!existsSync(t))throw new c("NOT_FOUND","Database not found");let r=T(t);if(e)try{$(r.db,t);}catch(o){throw r.close(),o}return r}validateWorkspaceId(e,t){return e.db.select({id:R.id}).from(R).where(eq(R.id,t)).limit(1).get()?t:null}topLevelTaskPredicateSql(e="child"){return sql.raw(`NOT EXISTS (
313
+ SELECT 1 FROM tasks parent
314
+ WHERE parent.id = ${e}.parent_task_id
315
+ AND parent.thread_id = ${e}.thread_id
316
+ )`)}findAllThreads(e){let t=this.resolveDbPaths(),r=new Set,o=[];for(let i of t){if(!existsSync(i))continue;let s=T(i);try{let d=e?eq(_.workspace_id,e):void 0,l=s.db.select().from(_).where(d).orderBy(desc(_.updated_at)).all();for(let u of l)r.has(u.id)||(r.add(u.id),o.push(u));}catch(d){throw new c("DB_ERROR","Failed to find all threads",d)}finally{s.close();}}return o}findThreadsByIdsOrTitles(e,t){if(e.length===0)return [];let r=this.resolveDbPaths(),o=new Set,i=[];for(let s of r){if(!existsSync(s))continue;let d=T(s);try{let l=or(inArray(_.id,e),inArray(_.title,e)),u=t?and(l,eq(_.workspace_id,t)):l,h=d.db.select().from(_).where(u).orderBy(desc(_.updated_at)).all();for(let g of h)o.has(g.id)||(o.add(g.id),i.push(g));}catch(l){throw new c("DB_ERROR","Failed to find threads by ids or titles",l)}finally{d.close();}}return i}findThreadById(e,t){let r=this.resolveDbPaths();for(let o of r){if(!existsSync(o))continue;let i=T(o);try{let s=eq(_.id,e),d=t?and(s,eq(_.workspace_id,t)):s,l=i.db.select().from(_).where(d).limit(1).get()??void 0;if(l)return l}catch(s){throw new c("DB_ERROR","Failed to find thread by id",s)}finally{i.close();}}}threadExists(e,t){let r=this.resolveDbPaths();for(let o of r){if(!existsSync(o))continue;let i=T(o);try{let s=eq(_.id,e),d=t?and(s,eq(_.workspace_id,t)):s;if(i.db.select({id:_.id}).from(_).where(d).limit(1).get())return !0}catch(s){throw new c("DB_ERROR","Failed to check thread existence",s)}finally{i.close();}}return false}aggregateTaskStats(e,t){let r=this.resolveDbPaths(),o=0,i=0,s=0,d=0,l=0,u=new Set;for(let h of r){if(!existsSync(h))continue;let g=T(h);try{let p=g.db.get(sql`
215
317
  SELECT
216
318
  count(*) AS cnt,
217
319
  COALESCE(SUM(child.input_tokens), 0) AS total_input,
@@ -219,44 +321,51 @@ ${n.join(`
219
321
  COALESCE(SUM(child.cached_input_tokens), 0) AS total_cached,
220
322
  COALESCE(SUM(child.cost_usd), 0) AS total_cost
221
323
  FROM tasks child
222
- WHERE child.thread_id = ${t}
324
+ WHERE child.thread_id = ${e}
223
325
  AND ${this.topLevelTaskPredicateSql()}
224
- ${e?sql`AND child.workspace_id = ${e}`:sql``}
225
- `);g&&(r+=g.cnt,s+=g.total_input,o+=g.total_output,l+=g.total_cached,u+=g.total_cost);let R=m.db.all(sql`
326
+ ${t?sql`AND child.workspace_id = ${t}`:sql``}
327
+ `);p&&(o+=p.cnt,i+=p.total_input,s+=p.total_output,d+=p.total_cached,l+=p.total_cost);let f=g.db.all(sql`
226
328
  SELECT DISTINCT child.agent_id FROM tasks child
227
- WHERE child.thread_id = ${t}
329
+ WHERE child.thread_id = ${e}
228
330
  AND child.agent_id IS NOT NULL AND child.agent_id != ''
229
331
  AND ${this.topLevelTaskPredicateSql()}
230
- ${e?sql`AND child.workspace_id = ${e}`:sql``}
231
- `);for(let q of R)c.add(q.agent_id);}catch(g){throw new d("DB_ERROR","Failed to aggregate task stats",g)}finally{m.close();}}return {taskCount:r,inputTokens:s,outputTokens:o,cachedInputTokens:l,costUsd:u,agentIds:Array.from(c)}}findTopLevelTasks(t,e,n){let r=this.resolveDbPaths(),s=new Set,o=[];for(let l of r){if(!existsSync(l))continue;let u=k(l);try{let c;n!==void 0?c=u.db.all(sql`
332
+ ${t?sql`AND child.workspace_id = ${t}`:sql``}
333
+ `);for(let O of f)u.add(O.agent_id);}catch(p){throw new c("DB_ERROR","Failed to aggregate task stats",p)}finally{g.close();}}return {taskCount:o,inputTokens:i,outputTokens:s,cachedInputTokens:d,costUsd:l,agentIds:Array.from(u)}}findTopLevelTasks(e,t,r){let o=this.resolveDbPaths(),i=new Set,s=[];for(let d of o){if(!existsSync(d))continue;let l=T(d);try{let u;r!==void 0?u=l.db.all(sql`
232
334
  SELECT * FROM (
233
335
  SELECT child.*,
234
336
  ROW_NUMBER() OVER (PARTITION BY child.agent_id ORDER BY child.started_at DESC) AS rn
235
337
  FROM tasks child
236
- WHERE child.thread_id = ${t}
338
+ WHERE child.thread_id = ${e}
237
339
  AND ${this.topLevelTaskPredicateSql()}
238
- ${e?sql`AND child.workspace_id = ${e}`:sql``}
340
+ ${t?sql`AND child.workspace_id = ${t}`:sql``}
239
341
  ) ranked
240
- WHERE rn <= ${n}
342
+ WHERE rn <= ${r}
241
343
  ORDER BY started_at ASC
242
- `):c=u.db.all(sql`
344
+ `):u=l.db.all(sql`
243
345
  SELECT child.* FROM tasks child
244
- WHERE child.thread_id = ${t}
346
+ WHERE child.thread_id = ${e}
245
347
  AND ${this.topLevelTaskPredicateSql()}
246
- ${e?sql`AND child.workspace_id = ${e}`:sql``}
348
+ ${t?sql`AND child.workspace_id = ${t}`:sql``}
247
349
  ORDER BY child.started_at ASC
248
- `);for(let _ of c)s.has(_.id)||(s.add(_.id),o.push(_));}catch(c){throw new d("DB_ERROR","Failed to find top-level tasks",c)}finally{u.close();}}if(n!==void 0&&r.length>1){let l=new Map;for(let u of o){let c=u.agent_id??"";l.has(c)||l.set(c,[]),l.get(c).push(u);}o=[];for(let u of l.values())u.sort((c,_)=>(_.started_at??"").localeCompare(c.started_at??"")),o.push(...u.slice(0,n));o.sort((u,c)=>(u.started_at??"").localeCompare(c.started_at??""));}return o}findAllTasks(t,e){let n=this.resolveDbPaths(),r=new Set,s=[];for(let o of n){if(!existsSync(o))continue;let l=k(o);try{let u=eq(i.thread_id,t),c=e?and(u,eq(i.workspace_id,e)):u,_=l.db.select().from(i).where(c).orderBy(asc(i.started_at)).all();for(let m of _)r.has(m.id)||(r.add(m.id),s.push(m));}catch(u){throw new d("DB_ERROR","Failed to find all tasks for thread",u)}finally{l.close();}}return s}findTaskById(t,e,n){let r=this.resolveDbPaths();for(let s of r){if(!existsSync(s))continue;let o=k(s);try{let l=and(eq(i.id,e),eq(i.thread_id,t)),u=n?and(l,eq(i.workspace_id,n)):l,c=o.db.select().from(i).where(u).limit(1).get();if(!c)continue;let _=o.db.select().from(i).where(eq(i.parent_task_id,c.id)).orderBy(asc(i.started_at)).all();return {task:c,children:_}}catch(l){throw new d("DB_ERROR","Failed to find task by id",l)}finally{o.close();}}}batchFetchTasks(t,e){let n=new Map;if(t.length===0)return n;let r=this.resolveDbPaths();for(let s of r){if(!existsSync(s))continue;let o=k(s);try{let l=o.db.all(sql`
249
- SELECT child.* FROM tasks child
250
- WHERE child.thread_id IN (${sql.join(t.map(u=>sql`${u}`),sql`, `)})
251
- AND ${this.topLevelTaskPredicateSql()}
252
- ${e?sql`AND child.workspace_id = ${e}`:sql``}
253
- ORDER BY child.started_at ASC
254
- `);for(let u of l){let c=u.thread_id;n.has(c)||n.set(c,[]),n.get(c).push(u);}}catch(l){throw new d("DB_ERROR","Failed to batch fetch tasks",l)}finally{o.close();}}return n}updateThreadTitle(t,e,n){if(!this.dbExists())return;let r=this.openHandle(true);try{let s=eq(p.id,t),o=n?and(s,eq(p.workspace_id,n)):s;if(!r.db.select({id:p.id}).from(p).where(o).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(s){throw s instanceof d?s:new d("DB_ERROR","Failed to update thread title",s)}finally{r.close();}}upsertThread(t,e){let n=this.openHandle(true);try{let r=e.workspaceId?this.validateWorkspaceId(n,e.workspaceId):null,s=new Date().toISOString();if(n.db.select({id:p.id,message_count:p.message_count}).from(p).where(eq(p.id,t)).limit(1).get()){let l={updated_at:s};e.title!==void 0&&(l.title=e.title),e.titleLocked!==void 0&&(l.title_locked=e.titleLocked?1:0),n.db.update(p).set(l).where(eq(p.id,t)).run();}else n.db.insert(p).values({id:t,platform:e.platform,workspace_id:r,title:e.title??null,title_locked:e.titleLocked?1:0,message_count:0,created_at:s,updated_at:s}).run();}catch(r){throw r instanceof d?r:new d("DB_ERROR","Failed to upsert thread",r)}finally{n.close();}}ensureThread(t,e,n){let r=this.openHandle(true);try{let s=n?this.validateWorkspaceId(r,n):null,o=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(o){s&&!o.workspace_id&&r.db.update(p).set({workspace_id:s}).where(eq(p.id,t)).run();return}let l=new Date().toISOString();r.db.insert(p).values({id:t,platform:e,workspace_id:s,message_count:0,created_at:l,updated_at:l}).run();}catch(s){throw s instanceof d?s:new d("DB_ERROR","Failed to ensure thread",s)}finally{r.close();}}saveUserMessage(t,e,n){if(!this.dbExists())return {firstMessage:false};let r=this.openHandle(true);try{let s=new Date().toISOString();return {firstMessage:r.db.transaction(l=>{let c=l.select({message_count:p.message_count}).from(p).where(eq(p.id,t)).limit(1).get()?.message_count===0;return l.run(sql`
350
+ `);for(let h of u)i.has(h.id)||(i.add(h.id),s.push(h));}catch(u){throw new c("DB_ERROR","Failed to find top-level tasks",u)}finally{l.close();}}if(r!==void 0&&o.length>1){let d=new Map;for(let l of s){let u=l.agent_id??"";d.has(u)||d.set(u,[]),d.get(u).push(l);}s=[];for(let l of d.values())l.sort((u,h)=>(h.started_at??"").localeCompare(u.started_at??"")),s.push(...l.slice(0,r));s.sort((l,u)=>(l.started_at??"").localeCompare(u.started_at??""));}return s}findAllTasks(e,t){let r=this.resolveDbPaths(),o=new Set,i=[];for(let s of r){if(!existsSync(s))continue;let d=T(s);try{let l=eq(a.thread_id,e),u=t?and(l,eq(a.workspace_id,t)):l,h=d.db.select().from(a).where(u).orderBy(asc(a.started_at)).all();for(let g of h)o.has(g.id)||(o.add(g.id),i.push(g));}catch(l){throw new c("DB_ERROR","Failed to find all tasks for thread",l)}finally{d.close();}}return i}findTaskById(e,t,r){let o=this.resolveDbPaths();for(let i of o){if(!existsSync(i))continue;let s=T(i);try{let d=and(eq(a.id,t),eq(a.thread_id,e)),l=r?and(d,eq(a.workspace_id,r)):d,u=s.db.select().from(a).where(l).limit(1).get();if(!u)continue;let h=s.db.select().from(a).where(eq(a.parent_task_id,u.id)).orderBy(asc(a.started_at)).all();return {task:u,children:h}}catch(d){throw new c("DB_ERROR","Failed to find task by id",d)}finally{s.close();}}}batchFetchTasksQuery(e,t){return sql`
351
+ SELECT child.id, child.thread_id, child.agent_id, child.status,
352
+ child.parent_task_id, child.started_at, child.completed_at,
353
+ child.duration_ms, child.input_tokens, child.output_tokens,
354
+ child.cost_usd, child.error
355
+ FROM tasks child INDEXED BY idx_tasks_thread_id
356
+ WHERE child.thread_id IN (${sql.join(e.map(r=>sql`${r}`),sql`, `)})
357
+ AND ${this.topLevelTaskPredicateSql()}
358
+ ${t?sql`AND child.workspace_id = ${t}`:sql``}
359
+ ORDER BY child.started_at ASC
360
+ `}batchFetchTasks(e,t){let r=new Map;if(e.length===0)return r;let o=this.resolveDbPaths();for(let i of o){if(!existsSync(i))continue;let s=T(i);try{let d=s.db.all(this.batchFetchTasksQuery(e,t));for(let l of d){let u=l.thread_id;r.has(u)||r.set(u,[]),r.get(u).push(l);}}catch(d){throw new c("DB_ERROR","Failed to batch fetch tasks",d)}finally{s.close();}}return r}explainBatchFetchTasksPlan(e,t){let r=this.resolveDbPaths();for(let o of r){if(!existsSync(o))continue;let i=T(o);try{return i.db.all(sql`EXPLAIN QUERY PLAN ${this.batchFetchTasksQuery(e,t)}`).map(d=>d.detail)}finally{i.close();}}return []}updateThreadTitle(e,t,r){if(!this.dbExists())return;let o=this.openHandle(true);try{let i=eq(_.id,e),s=r?and(i,eq(_.workspace_id,r)):i;if(!o.db.select({id:_.id}).from(_).where(s).limit(1).get())return;o.db.update(_).set({title:t,title_locked:1,updated_at:new Date().toISOString()}).where(eq(_.id,e)).run();}catch(i){throw i instanceof c?i:new c("DB_ERROR","Failed to update thread title",i)}finally{o.close();}}upsertThread(e,t){let r=this.openHandle(true);try{let o=t.workspaceId?this.validateWorkspaceId(r,t.workspaceId):null,i=new Date().toISOString();if(r.db.select({id:_.id,message_count:_.message_count}).from(_).where(eq(_.id,e)).limit(1).get()){let d={updated_at:i};t.title!==void 0&&(d.title=t.title),t.titleLocked!==void 0&&(d.title_locked=t.titleLocked?1:0),r.db.update(_).set(d).where(eq(_.id,e)).run();}else r.db.insert(_).values({id:e,platform:t.platform,workspace_id:o,title:t.title??null,title_locked:t.titleLocked?1:0,message_count:0,created_at:i,updated_at:i}).run();}catch(o){throw o instanceof c?o:new c("DB_ERROR","Failed to upsert thread",o)}finally{r.close();}}ensureThread(e,t,r){let o=this.openHandle(true);try{let i=r?this.validateWorkspaceId(o,r):null,s=o.db.select({id:_.id,platform:_.platform,workspace_id:_.workspace_id}).from(_).where(eq(_.id,e)).limit(1).get();if(s){i&&!s.workspace_id&&o.db.update(_).set({workspace_id:i}).where(eq(_.id,e)).run();return}let d=new Date().toISOString();o.db.insert(_).values({id:e,platform:t,workspace_id:i,message_count:0,created_at:d,updated_at:d}).run();}catch(i){throw i instanceof c?i:new c("DB_ERROR","Failed to ensure thread",i)}finally{o.close();}}saveUserMessage(e,t,r){if(!this.dbExists())return {firstMessage:false};let o=this.openHandle(true);try{let i=new Date().toISOString();return {firstMessage:o.db.transaction(d=>{let u=d.select({message_count:_.message_count}).from(_).where(eq(_.id,e)).limit(1).get()?.message_count===0;return d.run(sql`
255
361
  UPDATE threads
256
- SET first_message = COALESCE(first_message, ${e}),
257
- title = CASE WHEN title_locked = 0 AND title IS NULL THEN substr(${e}, 1, 60) ELSE title END,
258
- last_message = ${e},
362
+ SET first_message = COALESCE(first_message, ${t}),
363
+ title = CASE WHEN title_locked = 0 AND title IS NULL THEN substr(${t}, 1, 60) ELSE title END,
364
+ last_message = ${t},
259
365
  message_count = message_count + 1,
260
- updated_at = ${s}
261
- WHERE id = ${t}
262
- `),c},{behavior:"immediate"})}}catch(s){throw s instanceof d?s:new d("DB_ERROR","Failed to save user message",s)}finally{r.close();}}saveAssistantMessage(t,e,n){if(!this.dbExists())return;let r=this.openHandle(true);try{let s=new Date().toISOString();r.db.update(p).set({last_message:e,updated_at:s}).where(eq(p.id,t)).run();}catch(s){throw s instanceof d?s:new d("DB_ERROR","Failed to save assistant message",s)}finally{r.close();}}updateThread(t,e){if(!this.dbExists())return;let n=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),n.db.update(p).set(r).where(eq(p.id,t)).run();}catch(r){throw r instanceof d?r:new d("DB_ERROR","Failed to update thread",r)}finally{n.close();}}togglePin(t,e){let n=this.openHandle(true);try{let r=e?and(eq(p.id,t),eq(p.workspace_id,e)):eq(p.id,t),s=n.db.select({pinned:p.pinned,metadata:p.metadata}).from(p).where(r).get();if(!s)return null;let o=s.pinned?0:1,l=s.metadata?JSON.parse(s.metadata):{};if(o){let u=e?and(eq(p.pinned,1),eq(p.workspace_id,e)):eq(p.pinned,1),c=n.db.select({metadata:p.metadata}).from(p).where(u).all(),_=0;for(let m of c){let g=m.metadata?JSON.parse(m.metadata):{};typeof g.pinOrder=="number"&&g.pinOrder>_&&(_=g.pinOrder);}l.pinOrder=_+1;}else delete l.pinOrder;return n.db.update(p).set({pinned:o,metadata:Object.keys(l).length>0?JSON.stringify(l):null}).where(r).run(),{pinned:!!o}}catch(r){throw r instanceof d?r:new d("DB_ERROR","Failed to toggle pin",r)}finally{n.close();}}reorderPins(t,e){let n=this.openHandle(true);try{for(let r=0;r<t.length;r++){let s=e?and(eq(p.id,t[r]),eq(p.workspace_id,e)):eq(p.id,t[r]),o=n.db.select({metadata:p.metadata}).from(p).where(s).get();if(!o)continue;let l=o.metadata?JSON.parse(o.metadata):{};l.pinOrder=r+1,n.db.update(p).set({metadata:JSON.stringify(l)}).where(s).run();}}catch(r){throw r instanceof d?r:new d("DB_ERROR","Failed to reorder pins",r)}finally{n.close();}}toggleStar(t,e){let n=this.openHandle(true);try{let r=e?and(eq(p.id,t),eq(p.workspace_id,e)):eq(p.id,t),s=n.db.select({starred:p.starred}).from(p).where(r).get();if(!s)return null;let o=s.starred?0:1;return n.db.update(p).set({starred:o}).where(r).run(),{starred:!!o}}catch(r){throw r instanceof d?r:new d("DB_ERROR","Failed to toggle star",r)}finally{n.close();}}resolveOverdriveForRequest(t,e,n,r){let o=this.openHandle(true);try{let l=e?and(eq(p.id,t),eq(p.workspace_id,e)):eq(p.id,t);return o.db.transaction(c=>{let _=c.select({metadata:p.metadata}).from(p).where(l).get();if(!_)return null;let m=_.metadata?JSON.parse(_.metadata):{},g=m.overdrive??{},R=r?.defaultTurns??g.defaultTurns??3,q=r?.updatedBy??"ui",H=new Date().toISOString(),C,S,I,st;switch(n){case "enable-count":{let ot=r?.turns??R,it=r?.consumeCurrent?Math.max(ot-1,0):ot;C=it>0?"count":"off",S=it,I=!0,st="count";break}case "enable-latch":{C="latch",S=0,I=!0,st="latch";break}case "disable":{C="off",S=0,I=!1;break}default:{let ot=g.state??"off",it=typeof g.remaining=="number"?g.remaining:0;if(ot==="count"&&it>0){let $t=it-1;$t<=0?(C="off",S=0):(C="count",S=$t),I=!0,st="count";}else ot==="latch"?(C="latch",S=0,I=!0,st="latch"):(C="off",S=0,I=!1);break}}return m.overdrive={state:C,remaining:S,defaultTurns:R,updatedAt:H,updatedBy:q},c.update(p).set({metadata:JSON.stringify(m),updated_at:H}).where(l).run(),{applied:I,appliedMode:st,state:C,remaining:S}},{behavior:"immediate"})}catch(l){throw l instanceof d?l:new d("DB_ERROR","Failed to resolve overdrive",l)}finally{o.close();}}};var Nt=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 r=dirname(e);existsSync(r)||mkdirSync(r,{recursive:true});}else if(!existsSync(e))throw new d("NOT_FOUND","Database not found");let n=k(e);if(t)try{O(n.db,e);}catch(r){throw n.close(),r}return n}insertSpan(t){let e=this.openHandle(true);try{e.db.insert(W).values(t).run();}catch(n){throw n instanceof d?n:new d("DB_ERROR","Failed to insert span",n)}finally{e.close();}}findByTaskId(t){if(!this.dbExists())return [];let e=this.openHandle(false);try{return e.db.select().from(W).where(eq(W.task_id,t)).all()}catch(n){throw new d("DB_ERROR","Failed to find spans by task id",n)}finally{e.close();}}findById(t){if(!this.dbExists())return;let e=this.openHandle(false);try{return e.db.select().from(W).where(eq(W.id,t)).limit(1).get()??void 0}catch(n){throw new d("DB_ERROR","Failed to find span by id",n)}finally{e.close();}}};var Ct=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 r=dirname(e);existsSync(r)||mkdirSync(r,{recursive:true});}else if(!existsSync(e))throw new d("NOT_FOUND","Database not found");let n=k(e);if(t)try{O(n.db,e);}catch(r){throw n.close(),r}return n}insertToolCall(t){let e=this.openHandle(true);try{e.db.insert(z).values(t).run();}catch(n){throw n instanceof d?n:new d("DB_ERROR","Failed to insert tool call",n)}finally{e.close();}}findByTaskId(t){if(!this.dbExists())return [];let e=this.openHandle(false);try{return e.db.select().from(z).where(eq(z.task_id,t)).all()}catch(n){throw new d("DB_ERROR","Failed to find tool calls by task id",n)}finally{e.close();}}aggregateByName(t){if(!this.dbExists())return [];let e=this.openHandle(false);try{return e.db.select({toolName:z.tool_name,count:sql`count(*)`}).from(z).where(eq(z.task_id,t)).groupBy(z.tool_name).all().map(n=>({toolName:n.toolName,count:n.count}))}catch(n){throw new d("DB_ERROR","Failed to aggregate tool calls by name",n)}finally{e.close();}}};var vt=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 r=dirname(e);existsSync(r)||mkdirSync(r,{recursive:true});}else if(!existsSync(e))throw new d("NOT_FOUND","Database not found");let n=k(e);if(t)try{O(n.db,e);}catch(r){throw n.close(),r}return n}ensureThreadExists(t,e){if(!t.db.select({id:p.id}).from(p).where(eq(p.id,e)).limit(1).get())throw new d("NOT_FOUND",`Thread not found: ${e}`)}findByThreadId(t){if(!this.dbExists())return [];let e=this.openHandle(false);try{return this.ensureThreadExists(e,t),e.db.select().from(B).where(eq(B.thread_id,t)).orderBy(asc(B.seq)).all()}catch(n){throw n instanceof d?n:new d("DB_ERROR","Failed to find boxes by thread id",n)}finally{e.close();}}findById(t,e){if(!this.dbExists())return;let n=this.openHandle(false);try{return n.db.select().from(B).where(and(eq(B.id,e),eq(B.thread_id,t))).limit(1).get()??void 0}catch(r){throw r instanceof d?r:new d("DB_ERROR","Failed to find box by id",r)}finally{n.close();}}insert(t){let e=this.openHandle(true);try{this.ensureThreadExists(e,t.threadId);try{e.db.insert(B).values({id:t.id,thread_id:t.threadId,seq:t.seq,first_task_id:t.first_task_id,mid_task_id:t.mid_task_id,last_task_id:t.last_task_id,task_count:t.task_count,summary:t.summary??null,source_tokens:t.source_tokens,summary_tokens:t.summary_tokens??null,created_at:t.created_at}).run();}catch(r){throw r instanceof Error&&/UNIQUE constraint failed/i.test(r.message)?new d("CONFLICT",`Duplicate seq ${String(t.seq)} for thread ${t.threadId}`,r):r}let n=e.db.select().from(B).where(eq(B.id,t.id)).limit(1).get();if(!n)throw new d("DB_ERROR","Insert did not return a row");return n}catch(n){throw n instanceof d?n:new d("DB_ERROR","Failed to insert thread box",n)}finally{e.close();}}};var Lt=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 r=dirname(e);existsSync(r)||mkdirSync(r,{recursive:true});}else if(!existsSync(e))throw new d("NOT_FOUND","Database not found");let n=k(e);if(t)try{O(n.db,e);}catch(r){throw n.close(),r}return n}bulkInsert(t){if(t.length===0)return;let e=this.openHandle(true);try{let n=new Date().toISOString();e.db.transaction(r=>{for(let s of t)r.insert(nt).values({id:randomUUID(),path:s.path,method:s.method,status_code:s.statusCode,duration_ms:s.durationMs,ip:s.ip??null,request_headers:s.requestHeaders??null,response_headers:s.responseHeaders??null,request_body:s.requestBody??null,response_body:s.responseBody??null,query:s.query??null,user_id:s.userId??null,project_id:s.projectId??null,partition_key:s.partitionKey??"default",timestamp:n,metadata:s.metadata??null}).run();});}catch(n){throw n instanceof d?n:new d("DB_ERROR","Failed to bulk insert request logs",n)}finally{e.close();}}findRecent(t=100){if(!this.dbExists())return [];let e=this.openHandle(false);try{return e.db.select().from(nt).orderBy(desc(nt.timestamp)).limit(t).all()}catch(n){throw new d("DB_ERROR","Failed to find recent request logs",n)}finally{e.close();}}};function ae(a){return new Date(Math.floor(a/3e5)*3e5).toISOString()}var Pt=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 r=dirname(e);existsSync(r)||mkdirSync(r,{recursive:true});}else if(!existsSync(e))throw new d("NOT_FOUND","Database not found");let n=k(e);if(t)try{O(n.db,e);}catch(r){throw n.close(),r}return n}upsert(t){let e=this.openHandle(true);try{let n=ae(t.bucketStartMs),r=t.accountRef??"default";e.db.insert(D).values({id:t.id,provider:t.provider,account_ref:r,limit_window:t.limitWindow,bucket_start:n,captured_at:t.capturedAt,used_percent:t.usedPercent,remaining_percent:t.remainingPercent,resets_at:t.resetsAt??null,source:t.source,metadata:t.metadata??null}).onConflictDoUpdate({target:[D.provider,D.account_ref,D.limit_window,D.bucket_start],set:{captured_at:t.capturedAt,used_percent:t.usedPercent,remaining_percent:t.remainingPercent,resets_at:t.resetsAt??null,metadata:t.metadata??null}}).run();}catch(n){throw n instanceof d?n:new d("DB_ERROR","Failed to upsert usage limit snapshot",n)}finally{e.close();}}getTrends(t){if(!this.dbExists())return [];let e=this.openHandle(false);try{let n=e.db.select({provider:D.provider,bucket_start:D.bucket_start,used_percent:D.used_percent,remaining_percent:D.remaining_percent,resets_at:D.resets_at}).from(D).where(and(eq(D.limit_window,t.window),gte(D.bucket_start,t.fromIso),lte(D.bucket_start,t.toIso))).orderBy(asc(D.bucket_start)).all(),r=new Map;for(let s of n)r.has(s.provider)||r.set(s.provider,[]),r.get(s.provider).push({bucketStart:s.bucket_start,usedPercent:s.used_percent,remainingPercent:s.remaining_percent,resetsAt:s.resets_at??null});return Array.from(r.entries()).map(([s,o])=>({provider:s,points:o}))}catch(n){throw new d("DB_ERROR","Failed to get usage limit trends",n)}finally{e.close();}}};export{x as BaseSqliteRepository,d as RepositoryError,Lt as RequestLogRepository,Nt as SpanRepository,Ot as TaskRepository,vt as ThreadBoxRepository,At as ThreadRepository,Ct as ToolCallRepository,Pt as UsageLimitSnapshotRepository,Tt as WorkspaceRepository,ae as calcBucketStart,k as openDrizzleDb,Ge as pushSchema,et as runMigrations,O as runMigrationsOnce,i as tasks};
366
+ updated_at = ${i}
367
+ WHERE id = ${e}
368
+ `),u},{behavior:"immediate"})}}catch(i){throw i instanceof c?i:new c("DB_ERROR","Failed to save user message",i)}finally{o.close();}}saveAssistantMessage(e,t,r){if(!this.dbExists())return;let o=this.openHandle(true);try{let i=new Date().toISOString();o.db.update(_).set({last_message:t,updated_at:i}).where(eq(_.id,e)).run();}catch(i){throw i instanceof c?i:new c("DB_ERROR","Failed to save assistant message",i)}finally{o.close();}}updateThread(e,t){if(!this.dbExists())return;let r=this.openHandle(true);try{let o={updated_at:new Date().toISOString()};t.title!==void 0&&(o.title=t.title,o.title_locked=1),t.titleLocked!==void 0&&(o.title_locked=t.titleLocked?1:0),r.db.update(_).set(o).where(eq(_.id,e)).run();}catch(o){throw o instanceof c?o:new c("DB_ERROR","Failed to update thread",o)}finally{r.close();}}patchThreadTitleMetadata(e,t,r){let o=t;if(!o||typeof o!="object"||Array.isArray(o))return new at("THREAD_TITLE_PATCH_INVALID","Thread-title metadata patch must be an object");if(Object.keys(o).some(l=>l!=="priority"&&l!=="state"))return new at("THREAD_TITLE_PATCH_INVALID","Thread-title metadata patch only supports priority and state");let s=o;if(s.priority===void 0&&s.state===void 0)return new at("THREAD_TITLE_PATCH_EMPTY","Thread-title metadata patch must change priority or state");for(let l of [s.priority,s.state])if(l!=null&&(typeof l!="string"||l.length===0))return new at("THREAD_TITLE_PATCH_INVALID","Thread-title metadata values must be non-empty strings or null");let d=this.openHandle(true);try{let l=r?and(eq(_.id,e),eq(_.workspace_id,r)):eq(_.id,e);return d.db.transaction(u=>{let h=u.select({metadata:_.metadata}).from(_).where(l).get();if(!h)return null;let g=Ot(h.metadata),p=g.threadTitle,f=p&&typeof p=="object"&&!Array.isArray(p)?{...p}:{};s.priority===null?delete f.priority:s.priority!==void 0&&(f.priority=s.priority),s.state===null?delete f.state:s.state!==void 0&&(f.state=s.state),Object.keys(f).length>0?g.threadTitle=f:delete g.threadTitle;let O=Object.keys(g).length>0?JSON.stringify(g):null,w=new Date().toISOString();u.update(_).set({metadata:O,updated_at:w}).where(l).run();let I=u.select({metadata:_.metadata}).from(_).where(l).get();if(!I)throw new c("DB_ERROR","Thread-title metadata update could not be read back");let E=$a(I.metadata);return {threadId:e,priority:E.priority,state:E.state}},{behavior:"immediate"})}catch(l){throw l instanceof c?l:new c("DB_ERROR","Failed to patch thread-title metadata",l)}finally{d.close();}}togglePin(e,t){let r=this.openHandle(true);try{let o=t?and(eq(_.id,e),eq(_.workspace_id,t)):eq(_.id,e);return r.db.transaction(i=>{let s=i.select({pinned:_.pinned,metadata:_.metadata}).from(_).where(o).get();if(!s)return null;let d=s.pinned?0:1,l=Ot(s.metadata);if(d){let u=t?and(eq(_.pinned,1),eq(_.workspace_id,t)):eq(_.pinned,1),h=i.select({metadata:_.metadata}).from(_).where(u).all(),g=null;for(let p of h){let f=Ot(p.metadata);typeof f.pinOrder=="number"&&(g===null||f.pinOrder<g)&&(g=f.pinOrder);}l.pinOrder=g===null?0:g-1;}else delete l.pinOrder;return i.update(_).set({pinned:d,metadata:Object.keys(l).length>0?JSON.stringify(l):null}).where(o).run(),{pinned:!!d}},{behavior:"immediate"})}catch(o){throw o instanceof c?o:new c("DB_ERROR","Failed to toggle pin",o)}finally{r.close();}}reorderPins(e,t){let r=this.openHandle(true);try{r.db.transaction(o=>{for(let i=0;i<e.length;i++){let s=t?and(eq(_.id,e[i]),eq(_.workspace_id,t)):eq(_.id,e[i]),d=o.select({metadata:_.metadata}).from(_).where(s).get();if(!d)continue;let l=Ot(d.metadata);l.pinOrder=i+1,o.update(_).set({metadata:JSON.stringify(l)}).where(s).run();}},{behavior:"immediate"});}catch(o){throw o instanceof c?o:new c("DB_ERROR","Failed to reorder pins",o)}finally{r.close();}}toggleStar(e,t){let r=this.openHandle(true);try{let o=t?and(eq(_.id,e),eq(_.workspace_id,t)):eq(_.id,e),i=r.db.select({starred:_.starred}).from(_).where(o).get();if(!i)return null;let s=i.starred?0:1;return r.db.update(_).set({starred:s}).where(o).run(),{starred:!!s}}catch(o){throw o instanceof c?o:new c("DB_ERROR","Failed to toggle star",o)}finally{r.close();}}resolveOverdriveForRequest(e,t,r,o){let s=this.openHandle(true);try{let d=t?and(eq(_.id,e),eq(_.workspace_id,t)):eq(_.id,e);return s.db.transaction(u=>{let h=u.select({metadata:_.metadata}).from(_).where(d).get();if(!h)return null;let g=h.metadata?JSON.parse(h.metadata):{},p=g.overdrive??{},f=o?.defaultTurns??p.defaultTurns??3,O=o?.updatedBy??"ui",w=new Date().toISOString(),I,E,V,je;switch(r){case "enable-count":{let ce=o?.turns??f,ke=o?.consumeCurrent?Math.max(ce-1,0):ce;I=ke>0?"count":"off",E=ke,V=!0,je="count";break}case "enable-latch":{I="latch",E=0,V=!0,je="latch";break}case "disable":{I="off",E=0,V=!1;break}default:{let ce=p.state??"off",ke=typeof p.remaining=="number"?p.remaining:0;if(ce==="count"&&ke>0){let H=ke-1;H<=0?(I="off",E=0):(I="count",E=H),V=!0,je="count";}else ce==="latch"?(I="latch",E=0,V=!0,je="latch"):(I="off",E=0,V=!1);break}}return g.overdrive={state:I,remaining:E,defaultTurns:f,updatedAt:w,updatedBy:O},u.update(_).set({metadata:JSON.stringify(g),updated_at:w}).where(d).run(),{applied:V,appliedMode:je,state:I,remaining:E}},{behavior:"immediate"})}catch(d){throw d instanceof c?d:new c("DB_ERROR","Failed to resolve overdrive",d)}finally{s.close();}}};var mt="THREAD_STATE",lr="custom:";function Fa(n){return n.dbPath?n.dbPath:n.dbRoot?join(n.dbRoot,".crewx","crewx.db"):process.env.CREWX_DB?process.env.CREWX_DB:process.env.CREWX_TRACES_DB?process.env.CREWX_TRACES_DB:join(homedir(),".crewx","crewx.db")}function Gr(n){if(!n)return null;try{let e=JSON.parse(n);return !e||typeof e!="object"||Array.isArray(e)?null:e}catch{return null}}function No(n){let t=Gr(n)?.threadTitle;if(!t||typeof t!="object"||Array.isArray(t))return null;let r=t.state;return typeof r=="string"&&r.startsWith(lr)?r:null}function Ur(n){let e=[...n].length;return e>=1&&e<=20}function Ua(n){let e=n.select({id:_.id,workspace_id:_.workspace_id,metadata:_.metadata}).from(_).all(),t=[];for(let r of e){let o=No(r.metadata);o!==null&&t.push({id:r.id,workspace_id:r.workspace_id,metadata:r.metadata,label:o.slice(lr.length)});}return t}function za(n){return n===null?isNull(m.workspace_id):eq(m.workspace_id,n)}function Ga(n){return n===null?isNull(m.workspace_id):or(isNull(m.workspace_id),eq(m.workspace_id,n))}function Wa(n,e,t){let r=n.select().from(m).where(and(eq(m.code_group,mt),eq(m.code_name,e),za(t),eq(m.is_builtin,0))).limit(1).get();if(r)return {code:r.code,created:false};let o=n.select({maxSortOrder:sql`max(${m.sort_order})`}).from(m).where(and(eq(m.code_group,mt),Ga(t))).get(),i=gt();for(;n.select({code:m.code}).from(m).where(and(eq(m.code_group,mt),eq(m.code,i))).limit(1).get();)i=gt();let s=new Date().toISOString();return n.insert(m).values({code_group:mt,code:i,code_name:e,color:"gray",sort_order:(o?.maxSortOrder??-1)+1,workspace_id:t,is_builtin:0,is_archived:0,metadata:null,created_at:s,updated_at:s}).run(),{code:i,created:true}}function Va(n,e,t,r){let o=n.select({id:_.id,workspace_id:_.workspace_id,metadata:_.metadata}).from(_).all(),i=`${lr}${e}`,s=0,d=new Date().toISOString();for(let l of o){if(r!==null&&l.workspace_id!==r||No(l.metadata)!==i)continue;let u=Gr(l.metadata)??{},h=u.threadTitle,g=h&&typeof h=="object"&&!Array.isArray(h)?{...h}:{};g.state=t,u.threadTitle=g,n.update(_).set({metadata:JSON.stringify(u),updated_at:d}).where(eq(_.id,l.id)).run(),s+=1;}return s}function zr(n,e,t){return n.transaction(r=>{let o=Wa(r,e,t),i=Va(r,e,o.code,t);return {...o,migratedRows:i}},{behavior:"immediate"})}function Ka(n,e){return n.select({code:m.code}).from(m).where(and(eq(m.code_group,mt),eq(m.code_name,e),isNull(m.workspace_id),eq(m.is_builtin,0))).limit(1).get()?.code??null}function Ja(n){let e=new Set(n.select({code:m.code}).from(m).where(eq(m.code_group,mt)).all().map(i=>i.code)),t=n.select({metadata:_.metadata}).from(_).all(),r=0,o=0;for(let i of t){let d=Gr(i.metadata)?.threadTitle;if(!d||typeof d!="object"||Array.isArray(d))continue;let l=d.state;typeof l=="string"&&(l.startsWith(lr)&&(r+=1),e.has(l)||(o+=1));}return {remainingCustomReferences:r,orphanReferences:o}}function Ao(n={}){let e=Fa(n);if(!existsSync(e))return {migratedRows:0,createdCodes:0,remainingCustomReferences:0,orphanReferences:0};let t=T(e);try{$(t.db,e);let r=Ua(t.db),o=new Set;for(let h of n.configuredLabels??[])typeof h=="string"&&o.add(h);let i=new Set(o),s=new Map;for(let h of r)if(Ur(h.label))if(h.workspace_id===null)i.add(h.label);else {let g=s.get(h.workspace_id)??new Set;g.add(h.label),s.set(h.workspace_id,g);}let d=0,l=0,u=new Map;for(let h of [...i].sort()){if(!Ur(h))continue;let g=zr(t.db,h,null);u.set(h,g.code),d+=g.migratedRows,g.created&&(l+=1);}for(let h of [...s.keys()].sort())for(let g of [...s.get(h)].sort()){if(!Ur(g)||u.has(g))continue;if(Ka(t.db,g)){let f=zr(t.db,g,null);u.set(g,f.code),d+=f.migratedRows,f.created&&(l+=1);continue}let p=zr(t.db,g,h);d+=p.migratedRows,p.created&&(l+=1);}return {migratedRows:d,createdCodes:l,...Ja(t.db)}}catch(r){throw r instanceof c?r:new c("DB_ERROR","Failed to migrate legacy thread-title common codes",r)}finally{t.close();}}var Ya=Ao;var xo=["urgent","high","medium","low"],Lo=["investigating","in-progress","in-review","on-hold","done"],xt="custom:";var Xa=new Set(xo),Qa=new Set(Lo),Za={urgent:"U \uAE34\uAE09 Urgent",high:"P0 \uAE09\uD568 High",medium:"P1 \uC911\uC694 Medium",low:"P2 \uBCF4\uD1B5 Low"},Wr={investigating:"\uC870\uC0AC\uC911 Looking into","in-progress":"\uC9C4\uD589\uC911 In progress","in-review":"\uAC80\uD1A0\uC911 In review","on-hold":"\uBCF4\uB958 On hold",done:"\uC644\uB8CC Done"};function Oo(n,e){return !e||e.includes(n)?e??n:`${n} ${e}`}function Lt(n){return typeof n=="string"&&Xa.has(n)}function Pt(n){if(typeof n!="string")return false;if(Qa.has(n))return true;if(n.startsWith("c_"))return n.length>2;if(!n.startsWith(xt))return false;let e=n.slice(xt.length);return e.length>=1&&e.length<=20}function Po(n){if(n.startsWith(xt))return n.slice(xt.length)}function Vr(n){if(!n)return null;try{let e=JSON.parse(n);return !e||typeof e!="object"||Array.isArray(e)?null:e}catch{return null}}function ed(n){let e=Vr(n);return !!e&&Object.prototype.hasOwnProperty.call(e,"threadTitle")}function ur(n){let e=Vr(n);if(!e)return {};let t=e.threadTitle;if(!t||typeof t!="object"||Array.isArray(t))return {};let r=t,o={};return Lt(r.priority)&&(o.priority=r.priority),Pt(r.state)&&(o.state=r.state),o}function Kr(n,e){let t=Vr(n)??{},r={...ur(n)};return e.priority===null?delete r.priority:e.priority!==void 0&&(r.priority=e.priority),e.state===null?delete r.state:e.state!==void 0&&(r.state=e.state),r.priority===void 0&&r.state===void 0?delete t.threadTitle:t.threadTitle=r,Object.keys(t).length===0?null:JSON.stringify(t)}function td(n,e=new Map){let t=[];return n.priority&&t.push(Oo(Za[n.priority],e.get(n.priority))),n.state&&(n.state.startsWith(xt)?t.push(Po(n.state)??""):Wr[n.state]?t.push(Oo(Wr[n.state],e.get(n.state))):e.has(n.state)?t.push(n.state,e.get(n.state)??""):n.state.startsWith("c_")?t.push(n.state):t.push(Wr[n.state]??"")),t.filter(Boolean).join(" ")}function Ho(n,e){if(!n||n.trim().length===0)return;let t=new Set,r=false,o=false;for(let i of n.split(",")){let s=i.trim();if(s){if(s==="none"){r=true,o=true;continue}e(s)&&(t.add(s),o=true);}}if(o)return {values:t,includeNone:r}}function rd(n){return Ho(n,Lt)}function nd(n){return Ho(n,Pt)}function od(n,e){return e?n?e.values.has(n):e.includeNone:true}var Bo="regeneration_replaced",cd="THREAD_HIGHLIGHT_REGENERATION_NO_ELIGIBLE_TURNS",Fo="THREAD_HIGHLIGHT_REGENERATION_INTERRUPTED",ld="THREAD_HIGHLIGHT_REGENERATION_DETECTION_FAILED",Uo="THREAD_HIGHLIGHT_REGENERATION_COMMIT_FAILED",_r=class extends c{threadId;highlightId;expectedRevision;currentRevision;constructor(e,t,r,o){super("CONFLICT",`Highlight revision conflict: expected ${r}, current ${o}`),this.name="ThreadHistoryConflictError",this.threadId=e,this.highlightId=t,this.expectedRevision=r,this.currentRevision=o;}},Tt=class extends _r{},fr=class extends c{stableCode="THREAD_HIGHLIGHT_REGENERATION_IN_PROGRESS";run;constructor(e){super("CONFLICT","THREAD_HIGHLIGHT_REGENERATION_IN_PROGRESS"),this.name="ThreadHighlightRegenerationConflictError",this.run=e;}},ud=new Set(Dn),hd=new Set(Cn),gd=new Set(Nn),pd=new Set(An),_d=50,jo=100,Mo=280,qo=40,fd=new Set(On),hr=["queued","running"],md=["success","completed","done","failed","error"];function Yr(n){return fd.has(n)}function B(n){throw new c("VALIDATION",n)}function Ne(n){throw new c("NOT_FOUND",n)}function S(n,e){(typeof n!="string"||n.trim().length===0)&&B(`${e} is required`);}function $t(n={}){let e=n.actor??n,t=e.actorType??"system";return ud.has(t)||B(`invalid actorType: ${String(t)}`),e.actorId!==void 0&&e.actorId!==null&&typeof e.actorId!="string"&&B("actorId must be a string or null"),{actorType:t,actorId:e.actorId??null}}function wd(n){S(n.threadId,"threadId"),n.workspaceId!==void 0&&n.workspaceId!==null&&S(n.workspaceId,"workspaceId"),n.title!==void 0&&n.title!==null&&((typeof n.title!="string"||n.title.trim().length===0)&&B("title must not be empty"),n.title.length>120&&B("title must be at most 120 characters")),n.priority!==void 0&&n.priority!==null&&!Lt(n.priority)&&B(`invalid priority: ${String(n.priority)}`),n.state!==void 0&&n.state!==null&&!Pt(n.state)&&B(`invalid state: ${String(n.state)}`);}function kd(n){n.beforeSeq!==void 0&&n.afterSeq!==void 0&&B("beforeSeq and afterSeq cannot be used together");for(let[t,r]of [["beforeSeq",n.beforeSeq],["afterSeq",n.afterSeq]])r!==void 0&&(!Number.isInteger(r)||r<0)&&B(`${t} must be a non-negative integer`);let e=n.limit??_d;return (!Number.isInteger(e)||e<1||e>jo)&&B(`limit must be between 1 and ${jo}`),e}function Qr(n){typeof n!="string"&&B("text is required");let e=n.trim();return e.length===0&&B("text must not be empty"),e.length>Mo&&B(`text must be at most ${Mo} characters`),e}function Ye(n,e){return S(n??"",e),n}function Zr(n){pd.has(n)||B(`invalid highlight kind: ${String(n)}`);}function Td(n){gd.has(n)||B(`invalid highlight source: ${String(n)}`);}function yd(n){S(n.threadId,"threadId"),S(n.workspaceId,"workspaceId");let e=n.source??"manual";Td(e),Zr(n.kind);let t=Qr(n.text),r=n.coversFromTaskId??n.fromTaskId??n.taskId,o=n.coversToTaskId??n.toTaskId??n.taskId;if(e==="manual"){let h=n.taskId??(r&&o&&r===o?r:void 0),g=Ye(h,"taskId");return (r!==g||o!==g)&&B("manual highlights must cover exactly one task"),{source:e,kind:n.kind,text:t,coversFromTaskId:g,coversToTaskId:g,agentId:n.agentId??null,sourceTaskId:null,detectorVersion:null,contentFingerprint:null}}let i=Ye(r,"coversFromTaskId"),s=Ye(o,"coversToTaskId"),d=n.sourceTaskId??i,l=n.detectorVersion??(n.idempotencyKey!==void 0?"default":null),u=n.contentFingerprint??n.idempotencyKey??null;return Ye(d??void 0,"sourceTaskId"),Ye(l??void 0,"detectorVersion"),Ye(u??void 0,"contentFingerprint"),{source:e,kind:n.kind,text:t,coversFromTaskId:i,coversToTaskId:s,agentId:n.agentId??null,sourceTaskId:d,detectorVersion:l,contentFingerprint:u}}function Rd(n,e){(!n||typeof n!="object")&&B(`candidates[${e}] is required`),Zr(n.kind);let t=Qr(n.text),r=Ye(n.anchorTaskId,`candidates[${e}].anchorTaskId`),o=Ye(n.coversFromTaskId,`candidates[${e}].coversFromTaskId`),i=Ye(n.coversToTaskId,`candidates[${e}].coversToTaskId`),s=n.contentFingerprint?.trim()||Fn("thl",JSON.stringify({kind:n.kind,text:t,anchorTaskId:r,coversFromTaskId:o,coversToTaskId:i}));return S(s,`candidates[${e}].contentFingerprint`),{kind:n.kind,text:t,anchorTaskId:r,coversFromTaskId:o,coversToTaskId:i,contentFingerprint:s}}function Ed(n){Array.isArray(n)||B("candidates must be an array"),n.length>qo&&B(`candidates must contain at most ${qo} items`);let e=new Map;for(let[t,r]of n.entries()){let o=Rd(r,t);e.set(o.contentFingerprint,o);}return [...e.values()]}function Bt(n){let e=ur(n.metadata);return {threadId:n.id,workspaceId:n.workspace_id,title:n.title,priority:e.priority??null,state:e.state??null,metadata:n.metadata,titleLocked:n.title_locked===1,updatedAt:n.updated_at}}function bd(n){try{let e=JSON.stringify(n);return (!e||e==="null"||e.startsWith("["))&&B("event payload must be a JSON object"),e}catch(e){throw new c("VALIDATION","event payload must be JSON serializable",e)}}function jt(n,e){return n.select({maxSeq:sql`COALESCE(MAX(${M.seq}), 0)`}).from(M).where(eq(M.thread_id,e)).get()?.maxSeq??0}function Mt(n,e){return !!n.select({id:M.id}).from(M).where(eq(M.thread_id,e)).limit(1).get()}function dt(n,e){hd.has(e.type)||B(`invalid thread event type: ${String(e.type)}`);let t=fe("the");n.insert(M).values({id:t,thread_id:e.threadId,seq:e.seq,type:e.type,actor_type:e.actorType,actor_id:e.actorId,task_id:e.taskId??null,highlight_id:e.highlightId??null,payload_json:bd(e.payload),created_at:e.createdAt}).run();let r=n.select().from(M).where(eq(M.id,t)).get();if(!r)throw new c("DB_ERROR","Thread event insert did not return a row");return r}function qt(n,e,t,r,o){let i=Bt(e);dt(n,{threadId:e.id,seq:o,type:"thread.snapshot.imported",actorType:t.actorType,actorId:t.actorId,createdAt:r,payload:{title:i.title,priority:i.priority,state:i.state}});}function pr(n){return {highlightId:n.id,source:n.source,kind:n.kind,status:n.status,coversFromTaskId:n.covers_from_task_id,coversToTaskId:n.covers_to_task_id,revision:n.revision,...n.dismissed_at===null?{}:{dismissedAt:n.dismissed_at}}}function gr(n,e,t,r,o,i,s){let d=o==="thread.highlight.created"?pr(e):{before:s?pr({...e,...s,id:e.id}):void 0,after:pr(e)};return dt(n,{threadId:e.thread_id,seq:i,type:o,actorType:t.actorType,actorId:t.actorId,createdAt:r,taskId:e.source==="manual"?e.covers_from_task_id:e.source_task_id??e.covers_from_task_id,highlightId:e.id,payload:d})}function Sd(n,e,t,r,o,i){return dt(n,{threadId:e.thread_id,seq:o,type:"thread.highlight.deleted",actorType:t.actorType,actorId:t.actorId,createdAt:r,taskId:e.source_task_id??e.covers_from_task_id,highlightId:e.id,payload:{before:pr(e),...i??{}}})}var Xr=class extends x{dbPath;constructor(e={}){super(),e.dbPath?this.dbPath=e.dbPath:e.dbRoot&&(this.dbPath=join(e.dbRoot,".crewx","crewx.db"));}resolveDbPath(){return this.dbPath??super.resolveDbPath()}openHandle(e){let t=this.resolveDbPath();if(!e&&!existsSync(t))throw new c("NOT_FOUND","Database not found");if(e){let o=dirname(t);existsSync(o)||mkdirSync(o,{recursive:true});}let r=T(t);if(e)try{$(r.db,t);}catch(o){throw r.close(),o}return r}findThread(e,t,r){let o=eq(_.id,t),i=r===void 0?o:r===null?and(o,isNull(_.workspace_id)):and(o,eq(_.workspace_id,r));return e.select().from(_).where(i).limit(1).get()}findRegenerationRun(e,t,r){let o=e.select().from(A).where(eq(A.id,t)).limit(1).get();if(o&&!(r!==void 0&&!this.findThread(e,o.thread_id,r)))return o}resolveWorkspaceId(e){if(S(e,"threadId"),!existsSync(this.resolveDbPath()))return null;let t=this.openHandle(false);try{return t.db.select({workspaceId:_.workspace_id}).from(_).where(eq(_.id,e)).limit(1).get()?.workspaceId??null}catch(r){throw r instanceof c?r:new c("DB_ERROR","Failed to resolve thread workspace",r)}finally{t.close();}}getSnapshot(e,t){if(S(e,"threadId"),!existsSync(this.resolveDbPath()))return null;let r=this.openHandle(false);try{let o=this.findThread(r.db,e,t);return o?Bt(o):null}catch(o){throw o instanceof c?o:new c("DB_ERROR","Failed to read thread snapshot",o)}finally{r.close();}}updateSnapshot(e){wd(e);let t=$t(e),r=new Date().toISOString(),o=this.openHandle(true);try{return o.db.transaction(i=>{let s=this.findThread(i,e.threadId,e.workspaceId);s||Ne(`Thread ${e.threadId} not found`);let d=Bt(s),l=e.title!==void 0,u=l&&e.title!==d.title,h=l&&s.title_locked!==1,g=e.priority!==void 0&&e.priority!==d.priority,p=e.state!==void 0&&e.state!==d.state,f=u||g||p;if(!f&&!h)return d;let O=s.metadata;(g||p)&&(O=Kr(s.metadata,{priority:e.priority,state:e.state}));let w={};if(f&&(w.metadata=O,w.updated_at=r),u&&(w.title=e.title),l&&(w.title_locked=1),i.update(_).set(w).where(e.workspaceId===void 0?eq(_.id,e.threadId):e.workspaceId===null?and(eq(_.id,e.threadId),isNull(_.workspace_id)):and(eq(_.id,e.threadId),eq(_.workspace_id,e.workspaceId))).run(),!f){let V={...s,title_locked:1};return Bt(V)}let I=jt(i,s.id)+1;Mt(i,s.id)||(qt(i,s,t,r,I),I+=1),u&&(dt(i,{threadId:s.id,seq:I,type:"thread.title.changed",actorType:t.actorType,actorId:t.actorId,createdAt:r,taskId:e.taskId,payload:{before:d.title,after:e.title}}),I+=1),g&&(dt(i,{threadId:s.id,seq:I,type:"thread.priority.changed",actorType:t.actorType,actorId:t.actorId,createdAt:r,taskId:e.taskId,payload:{before:d.priority,after:e.priority}}),I+=1),p&&dt(i,{threadId:s.id,seq:I,type:"thread.state.changed",actorType:t.actorType,actorId:t.actorId,createdAt:r,taskId:e.taskId,payload:{before:d.state,after:e.state}});let E={...s,title:u?e.title:s.title,metadata:O,title_locked:l?1:s.title_locked,updated_at:r};return Bt(E)},{behavior:"immediate"})}catch(i){throw i instanceof c?i:new c("DB_ERROR","Failed to update thread snapshot",i)}finally{o.close();}}mutateSnapshot(e){return this.updateSnapshot(e)}updateThreadSnapshot(e){return this.updateSnapshot(e)}getLatestSeq(e,t){if(S(e,"threadId"),!existsSync(this.resolveDbPath()))return null;let r=this.openHandle(false);try{return this.findThread(r.db,e,t)?r.db.select({maxSeq:sql`COALESCE(MAX(${M.seq}), 0)`}).from(M).where(eq(M.thread_id,e)).get()?.maxSeq??0:null}catch(o){throw o instanceof c?o:new c("DB_ERROR","Failed to read latest thread event sequence",o)}finally{r.close();}}listCompletedThreadHighlightTurns(e,t){if(S(e,"threadId"),S(t,"workspaceId"),!existsSync(this.resolveDbPath()))return null;let r=this.openHandle(false);try{return this.findThread(r.db,e,t)?r.db.select({taskId:a.id,prompt:a.prompt,result:a.result,status:a.status,startedAt:a.started_at,completedAt:a.completed_at}).from(a).where(and(eq(a.thread_id,e),eq(a.workspace_id,t),inArray(a.status,md),or(isNull(a.parent_task_id),eq(a.parent_task_id,"")),sql`${a.result} IS NOT NULL AND length(trim(${a.result})) > 0`)).orderBy(asc(a.started_at),asc(a.id)).all().map(s=>({taskId:s.taskId,prompt:s.prompt,result:s.result,status:s.status,startedAt:s.startedAt,completedAt:s.completedAt})):null}catch(o){throw o instanceof c?o:new c("DB_ERROR","Failed to read completed thread highlight turns",o)}finally{r.close();}}createHighlightRegenerationRun(e){S(e.threadId,"threadId"),S(e.workspaceId,"workspaceId"),S(e.requestId,"requestId"),S(e.detectorVersion,"detectorVersion"),e.runId!==void 0&&S(e.runId,"runId");let t=new Date().toISOString(),r=this.openHandle(true);try{return r.db.transaction(o=>{let i=this.findThread(o,e.threadId,e.workspaceId);i||Ne(`Thread ${e.threadId} not found`);let s=o.select().from(A).where(and(eq(A.thread_id,i.id),eq(A.request_id,e.requestId))).orderBy(desc(A.requested_at),desc(A.id)).limit(1).get();if(s)return {run:s,created:!1};let d=o.select().from(A).where(and(eq(A.thread_id,i.id),inArray(A.status,hr))).orderBy(asc(A.requested_at),asc(A.id)).limit(1).get();if(d)throw new fr(d);let l=e.runId??fe("thr");o.insert(A).values({id:l,thread_id:i.id,request_id:e.requestId,status:"queued",detector_version:e.detectorVersion,requested_at:t,started_at:null,completed_at:null,error_code:null,previous_auto_count:null,new_auto_count:null}).run();let u=o.select().from(A).where(eq(A.id,l)).get();if(!u)throw new c("DB_ERROR","Highlight regeneration run insert did not return a row");return {run:u,created:!0}},{behavior:"immediate"})}catch(o){throw o instanceof c?o:new c("DB_ERROR","Failed to create highlight regeneration run",o)}finally{r.close();}}beginHighlightRegenerationRun(e){return this.createHighlightRegenerationRun(e)}queueHighlightRegenerationRun(e){return this.createHighlightRegenerationRun(e)}getHighlightRegenerationRun(e,t){if(S(e,"runId"),t!==void 0&&S(t,"workspaceId"),!existsSync(this.resolveDbPath()))return null;let r=this.openHandle(false);try{return this.findRegenerationRun(r.db,e,t)??null}catch(o){throw o instanceof c?o:new c("DB_ERROR","Failed to read highlight regeneration run",o)}finally{r.close();}}getHighlightRegenerationRunByRequest(e,t,r){if(S(e,"threadId"),S(t,"workspaceId"),S(r,"requestId"),!existsSync(this.resolveDbPath()))return null;let o=this.openHandle(false);try{return this.findThread(o.db,e,t)?o.db.select().from(A).where(and(eq(A.thread_id,e),eq(A.request_id,r))).orderBy(desc(A.requested_at),desc(A.id)).limit(1).get()??null:null}catch(i){throw i instanceof c?i:new c("DB_ERROR","Failed to read highlight regeneration request",i)}finally{o.close();}}findHighlightRegenerationRun(e,t,r){return this.getHighlightRegenerationRunByRequest(e,t,r)}startHighlightRegenerationRun(e,t){S(e,"runId"),t!==void 0&&S(t,"workspaceId");let r=new Date().toISOString(),o=this.openHandle(true);try{return o.db.transaction(i=>{let s=this.findRegenerationRun(i,e,t);if(s||Ne(`Highlight regeneration run ${e} not found`),Yr(s.status)||B(`invalid highlight regeneration status: ${s.status}`),s.status!=="queued")return s;i.update(A).set({status:"running",started_at:r}).where(and(eq(A.id,s.id),eq(A.status,"queued"))).run();let d=i.select().from(A).where(eq(A.id,s.id)).get();if(!d)throw new c("DB_ERROR","Highlight regeneration run start did not return a row");return d},{behavior:"immediate"})}catch(i){throw i instanceof c?i:new c("DB_ERROR","Failed to start highlight regeneration run",i)}finally{o.close();}}startHighlightRegeneration(e,t){return this.startHighlightRegenerationRun(e,t)}failHighlightRegenerationRun(e){S(e.runId,"runId"),S(e.errorCode,"errorCode"),e.workspaceId!==void 0&&S(e.workspaceId,"workspaceId");let t=new Date().toISOString(),r=this.openHandle(true);try{return r.db.transaction(o=>{let i=this.findRegenerationRun(o,e.runId,e.workspaceId);if(i||Ne(`Highlight regeneration run ${e.runId} not found`),Yr(i.status)||B(`invalid highlight regeneration status: ${i.status}`),i.status==="completed"||i.status==="failed")return i;o.update(A).set({status:"failed",completed_at:t,error_code:e.errorCode}).where(and(eq(A.id,i.id),inArray(A.status,hr))).run();let s=o.select().from(A).where(eq(A.id,i.id)).get();if(!s)throw new c("DB_ERROR","Highlight regeneration run failure did not return a row");return s},{behavior:"immediate"})}catch(o){throw o instanceof c?o:new c("DB_ERROR","Failed to fail highlight regeneration run",o)}finally{r.close();}}failHighlightRegeneration(e){return this.failHighlightRegenerationRun(e)}recoverInterruptedHighlightRegenerationRuns(e=Fo){S(e,"errorCode");let t=new Date().toISOString(),r=this.openHandle(true);try{return r.db.transaction(o=>o.update(A).set({status:"failed",completed_at:t,error_code:e}).where(inArray(A.status,hr)).run().changes,{behavior:"immediate"})}catch(o){throw o instanceof c?o:new c("DB_ERROR","Failed to recover interrupted highlight runs",o)}finally{r.close();}}completeHighlightRegenerationRun(e){S(e.runId,"runId"),S(e.threadId,"threadId"),S(e.workspaceId,"workspaceId"),S(e.detectorVersion,"detectorVersion");let t=Ed(e.candidates),r=$t(e),o=this.openHandle(true),i=false;try{return o.db.transaction(s=>{let d=this.findRegenerationRun(s,e.runId,e.workspaceId);if((!d||d.thread_id!==e.threadId)&&Ne(`Highlight regeneration run ${e.runId} not found`),Yr(d.status)||B(`invalid highlight regeneration status: ${d.status}`),d.status==="failed")throw new c("CONFLICT","Highlight regeneration run has already failed");if(d.status==="completed")return {run:d,deletedCount:0,createdCount:0,previousAutoCount:d.previous_auto_count??0,newAutoCount:d.new_auto_count??0};i=!0;let l=this.findThread(s,e.threadId,e.workspaceId);l||Ne(`Thread ${e.threadId} not found`),d.detector_version!==e.detectorVersion&&B("detectorVersion does not match the regeneration run");let u=s.select().from(v).where(eq(v.thread_id,l.id)).orderBy(asc(v.created_at),asc(v.id)).all(),h=new Set(t.map(H=>H.contentFingerprint)),g=u.filter(H=>H.source==="auto"&&H.status==="active"&&H.revision===0&&!h.has(H.content_fingerprint??"")),p=u.filter(H=>H.source==="auto"&&H.status==="active").length,f=new Set(u.filter(H=>!g.includes(H)&&H.content_fingerprint).map(H=>H.content_fingerprint)),O=t.filter(H=>!f.has(H.contentFingerprint)),w=new Date().toISOString(),I=jt(s,l.id)+1;Mt(s,l.id)||(qt(s,l,r,w,I),I+=1);for(let H of g)s.delete(v).where(eq(v.id,H.id)).run(),Sd(s,H,r,w,I,{runId:e.runId,reason:Bo}),I+=1;let E=0,V=e.agentId??(r.actorType==="agent"?r.actorId:null);for(let H of O){let ln=fe("thl");s.insert(v).values({id:ln,thread_id:l.id,source:"auto",kind:H.kind,status:"active",text:H.text,covers_from_task_id:H.coversFromTaskId,covers_to_task_id:H.coversToTaskId,revision:0,created_at:w,updated_at:w,agent_id:V,source_task_id:H.anchorTaskId,detector_version:e.detectorVersion,content_fingerprint:H.contentFingerprint,dismissed_at:null}).run();let un=s.select().from(v).where(eq(v.id,ln)).get();if(!un)throw new c("DB_ERROR","Regenerated highlight insert did not return a row");gr(s,un,r,w,"thread.highlight.created",I),I+=1,E+=1;}let ce=s.select().from(v).where(eq(v.thread_id,l.id)).all().filter(H=>H.source==="auto"&&H.status==="active").length;dt(s,{threadId:l.id,seq:I,type:"thread.highlights.regenerated",actorType:r.actorType,actorId:r.actorId,createdAt:w,payload:{runId:d.id,detectorVersion:e.detectorVersion,previousAutoCount:p,newAutoCount:ce,deletedCount:g.length,createdCount:E}}),s.update(A).set({status:"completed",started_at:d.started_at??w,completed_at:w,error_code:null,previous_auto_count:p,new_auto_count:ce}).where(and(eq(A.id,d.id),inArray(A.status,hr))).run();let ke=s.select().from(A).where(eq(A.id,d.id)).get();if(!ke)throw new c("DB_ERROR","Highlight regeneration completion did not return a row");return {run:ke,deletedCount:g.length,createdCount:E,previousAutoCount:p,newAutoCount:ce}},{behavior:"immediate"})}catch(s){if(i)try{this.failHighlightRegenerationRun({runId:e.runId,workspaceId:e.workspaceId,errorCode:Uo});}catch{}throw s instanceof c?s:new c("DB_ERROR","Failed to complete highlight regeneration",s)}finally{o.close();}}completeHighlightRegeneration(e){return this.completeHighlightRegenerationRun(e)}replaceAutoHighlightsAtomically(e){return this.completeHighlightRegenerationRun(e)}listTimeline(e,t,r={}){let o=typeof e=="string"?{...r,threadId:e,workspaceId:t}:e;S(o.threadId,"threadId"),S(o.workspaceId,"workspaceId");let i=kd(o);if(!existsSync(this.resolveDbPath()))return null;let s=this.openHandle(false);try{if(!this.findThread(s.db,o.threadId,o.workspaceId))return null;let d=s.db.select({maxSeq:sql`COALESCE(MAX(${M.seq}), 0)`}).from(M).where(eq(M.thread_id,o.threadId)).get()?.maxSeq??0,l;o.beforeSeq!==void 0?l=s.db.select().from(M).where(and(eq(M.thread_id,o.threadId),lt(M.seq,o.beforeSeq))).orderBy(desc(M.seq)).limit(i+1).all().reverse():o.afterSeq!==void 0?l=s.db.select().from(M).where(and(eq(M.thread_id,o.threadId),sql`${M.seq} > ${o.afterSeq}`)).orderBy(asc(M.seq)).limit(i+1).all():l=s.db.select().from(M).where(eq(M.thread_id,o.threadId)).orderBy(desc(M.seq)).limit(i+1).all().reverse();let u=l.length>i,h=o.afterSeq!==void 0?l.slice(0,i):u?l.slice(1):l,g=!1,p=h[0];return p&&(g=!!s.db.select({id:M.id}).from(M).where(and(eq(M.thread_id,o.threadId),lt(M.seq,p.seq))).limit(1).get()),{items:h,latestSeq:d,hasMoreOlder:g}}catch(d){throw d instanceof c?d:new c("DB_ERROR","Failed to list thread timeline",d)}finally{s.close();}}listEvents(e,t,r){return this.listTimeline(e,t,r)}getTimeline(e,t,r){return this.listTimeline(e,t,r)}createHighlight(e){let t=yd(e),r=$t(e),o=new Date().toISOString(),i=this.openHandle(true);try{return i.db.transaction(s=>{let d=this.findThread(s,e.threadId,e.workspaceId);if(d||Ne(`Thread ${e.threadId} not found`),t.source==="auto"){let p=s.select().from(v).where(and(eq(v.thread_id,e.threadId),eq(v.source_task_id,t.sourceTaskId),eq(v.detector_version,t.detectorVersion),eq(v.content_fingerprint,t.contentFingerprint))).orderBy(asc(v.created_at),asc(v.id)).limit(1).get();if(p)return p}let l=e.id??fe("thl"),u={id:l,thread_id:e.threadId,source:t.source,kind:t.kind,status:"active",text:t.text,covers_from_task_id:t.coversFromTaskId,covers_to_task_id:t.coversToTaskId,revision:0,created_at:o,updated_at:o,agent_id:t.agentId,source_task_id:t.sourceTaskId,detector_version:t.detectorVersion,content_fingerprint:t.contentFingerprint,dismissed_at:null};s.insert(v).values(u).run();let h=s.select().from(v).where(eq(v.id,l)).get();if(!h)throw new c("DB_ERROR","Highlight insert did not return a row");let g=jt(s,d.id)+1;return Mt(s,d.id)||(qt(s,d,r,o,g),g+=1),gr(s,h,r,o,"thread.highlight.created",g),h},{behavior:"immediate"})}catch(s){throw s instanceof c?s:new c("DB_ERROR","Failed to create thread highlight",s)}finally{i.close();}}updateHighlight(e){S(e.threadId,"threadId"),S(e.workspaceId,"workspaceId"),S(e.highlightId,"highlightId"),(!Number.isInteger(e.expectedRevision)||e.expectedRevision<0)&&B("expectedRevision must be a non-negative integer"),e.text===void 0&&e.kind===void 0&&e.coversFromTaskId===void 0&&e.coversToTaskId===void 0&&B("highlight update requires at least one field"),e.kind!==void 0&&Zr(e.kind);let t=e.text===void 0?void 0:Qr(e.text),r=$t(e),o=new Date().toISOString(),i=this.openHandle(true);try{return i.db.transaction(s=>{let d=this.findThread(s,e.threadId,e.workspaceId);d||Ne(`Thread ${e.threadId} not found`);let l=s.select().from(v).where(and(eq(v.id,e.highlightId),eq(v.thread_id,d.id))).limit(1).get();if(l||Ne(`Highlight ${e.highlightId} not found`),l.revision!==e.expectedRevision)throw new Tt(d.id,l.id,e.expectedRevision,l.revision);if(l.status!=="active")throw new Tt(d.id,l.id,e.expectedRevision,l.revision);let u=e.kind??l.kind,h=t??l.text,g=e.coversFromTaskId??l.covers_from_task_id,p=e.coversToTaskId??l.covers_to_task_id;(!h||g.length===0||p.length===0)&&B("highlight projection is incomplete");let f=u!==l.kind||h!==l.text||g!==l.covers_from_task_id||p!==l.covers_to_task_id,O=r.actorType==="user"&&l.source==="auto"&&f?"manual":l.source;if(!(f||O!==l.source))return l;let I=l.revision+1;s.update(v).set({source:O,kind:u,text:h,covers_from_task_id:g,covers_to_task_id:p,revision:I,updated_at:o}).where(and(eq(v.id,l.id),eq(v.revision,l.revision))).run();let E=s.select().from(v).where(eq(v.id,l.id)).get();if(!E)throw new c("DB_ERROR","Highlight update did not return a row");let V=jt(s,d.id)+1;return Mt(s,d.id)||(qt(s,d,r,o,V),V+=1),gr(s,E,r,o,"thread.highlight.updated",V,l),E},{behavior:"immediate"})}catch(s){throw s instanceof c?s:new c("DB_ERROR","Failed to update thread highlight",s)}finally{i.close();}}dismissHighlight(e){S(e.threadId,"threadId"),S(e.workspaceId,"workspaceId"),S(e.highlightId,"highlightId"),(!Number.isInteger(e.expectedRevision)||e.expectedRevision<0)&&B("expectedRevision must be a non-negative integer");let t=$t(e),r=new Date().toISOString(),o=this.openHandle(true);try{return o.db.transaction(i=>{let s=this.findThread(i,e.threadId,e.workspaceId);s||Ne(`Thread ${e.threadId} not found`);let d=i.select().from(v).where(and(eq(v.id,e.highlightId),eq(v.thread_id,s.id))).limit(1).get();if(d||Ne(`Highlight ${e.highlightId} not found`),d.revision!==e.expectedRevision)throw new Tt(s.id,d.id,e.expectedRevision,d.revision);if(d.status==="dismissed")return d;let l=d.revision+1;i.update(v).set({status:"dismissed",text:null,revision:l,updated_at:r,dismissed_at:r}).where(and(eq(v.id,d.id),eq(v.revision,d.revision))).run();let u=i.select().from(v).where(eq(v.id,d.id)).get();if(!u)throw new c("DB_ERROR","Highlight dismissal did not return a row");let h=jt(i,s.id)+1;return Mt(i,s.id)||(qt(i,s,t,r,h),h+=1),gr(i,u,t,r,"thread.highlight.deleted",h,d),u},{behavior:"immediate"})}catch(i){throw i instanceof c?i:new c("DB_ERROR","Failed to dismiss thread highlight",i)}finally{o.close();}}listActiveHighlights(e,t,r={}){if(S(e,"threadId"),S(t,"workspaceId"),r.taskId!==void 0&&S(r.taskId,"taskId"),r.coversFromTaskId!==void 0&&S(r.coversFromTaskId,"coversFromTaskId"),r.coversToTaskId!==void 0&&S(r.coversToTaskId,"coversToTaskId"),!existsSync(this.resolveDbPath()))return null;let o=this.openHandle(false);try{if(!this.findThread(o.db,e,t))return null;let s=o.db.select().from(v).where(and(eq(v.thread_id,e),eq(v.status,"active"))).orderBy(asc(v.created_at),asc(v.id)).all();if(r.taskId===void 0&&r.coversFromTaskId===void 0&&r.coversToTaskId===void 0)return s;let d=o.db.all(sql`
369
+ SELECT id, started_at FROM tasks WHERE thread_id = ${e}
370
+ ORDER BY started_at ASC, id ASC
371
+ `),l=new Map(d.map((p,f)=>[p.id,f])),u=r.taskId===void 0?void 0:l.get(r.taskId),h=r.coversFromTaskId===void 0?void 0:l.get(r.coversFromTaskId),g=r.coversToTaskId===void 0?void 0:l.get(r.coversToTaskId);return s.filter(p=>{let f=l.get(p.covers_from_task_id),O=l.get(p.covers_to_task_id);if(f===void 0||O===void 0)return !1;let w=Math.min(f,O),I=Math.max(f,O);return !(u!==void 0&&(u<w||u>I)||h!==void 0&&I<h||g!==void 0&&w>g)})}catch(i){throw i instanceof c?i:new c("DB_ERROR","Failed to list active thread highlights",i)}finally{o.close();}}listHighlights(e,t,r){return this.listActiveHighlights(e,t,r)}getActiveHighlights(e,t,r){return this.listActiveHighlights(e,t,r)}};var en=class extends x{dbPath;constructor(e={}){super(),e.dbPath?this.dbPath=e.dbPath:e.dbRoot&&(this.dbPath=join(e.dbRoot,".crewx","crewx.db"));}resolveDbPath(){return this.dbPath?this.dbPath:super.resolveDbPath()}openHandle(e){let t=this.resolveDbPath();if(e){let o=dirname(t);existsSync(o)||mkdirSync(o,{recursive:true});}else if(!existsSync(t))throw new c("NOT_FOUND","Database not found");let r=T(t);if(e)try{$(r.db,t);}catch(o){throw r.close(),o}return r}insertSpan(e){let t=this.openHandle(true);try{t.db.insert(Fe).values(e).run();}catch(r){throw r instanceof c?r:new c("DB_ERROR","Failed to insert span",r)}finally{t.close();}}findByTaskId(e){if(!this.dbExists())return [];let t=this.openHandle(false);try{return t.db.select().from(Fe).where(eq(Fe.task_id,e)).all()}catch(r){throw new c("DB_ERROR","Failed to find spans by task id",r)}finally{t.close();}}findById(e){if(!this.dbExists())return;let t=this.openHandle(false);try{return t.db.select().from(Fe).where(eq(Fe.id,e)).limit(1).get()??void 0}catch(r){throw new c("DB_ERROR","Failed to find span by id",r)}finally{t.close();}}};var tn=class extends x{dbPath;constructor(e={}){super(),e.dbPath?this.dbPath=e.dbPath:e.dbRoot&&(this.dbPath=join(e.dbRoot,".crewx","crewx.db"));}resolveDbPath(){return this.dbPath?this.dbPath:super.resolveDbPath()}openHandle(e){let t=this.resolveDbPath();if(e){let o=dirname(t);existsSync(o)||mkdirSync(o,{recursive:true});}else if(!existsSync(t))throw new c("NOT_FOUND","Database not found");let r=T(t);if(e)try{$(r.db,t);}catch(o){throw r.close(),o}return r}insertToolCall(e){let t=this.openHandle(true);try{t.db.insert(Oe).values(e).run();}catch(r){throw r instanceof c?r:new c("DB_ERROR","Failed to insert tool call",r)}finally{t.close();}}findByTaskId(e){if(!this.dbExists())return [];let t=this.openHandle(false);try{return t.db.select().from(Oe).where(eq(Oe.task_id,e)).all()}catch(r){throw new c("DB_ERROR","Failed to find tool calls by task id",r)}finally{t.close();}}aggregateByName(e){if(!this.dbExists())return [];let t=this.openHandle(false);try{return t.db.select({toolName:Oe.tool_name,count:sql`count(*)`}).from(Oe).where(eq(Oe.task_id,e)).groupBy(Oe.tool_name).all().map(r=>({toolName:r.toolName,count:r.count}))}catch(r){throw new c("DB_ERROR","Failed to aggregate tool calls by name",r)}finally{t.close();}}};var rn=class extends x{dbPath;constructor(e={}){super(),e.dbPath?this.dbPath=e.dbPath:e.dbRoot&&(this.dbPath=join(e.dbRoot,".crewx","crewx.db"));}resolveDbPath(){return this.dbPath?this.dbPath:super.resolveDbPath()}openHandle(e){let t=this.resolveDbPath();if(e){let o=dirname(t);existsSync(o)||mkdirSync(o,{recursive:true});}else if(!existsSync(t))throw new c("NOT_FOUND","Database not found");let r=T(t);if(e)try{$(r.db,t);}catch(o){throw r.close(),o}return r}ensureThreadExists(e,t){if(!e.db.select({id:_.id}).from(_).where(eq(_.id,t)).limit(1).get())throw new c("NOT_FOUND",`Thread not found: ${t}`)}findByThreadId(e){if(!this.dbExists())return [];let t=this.openHandle(false);try{return this.ensureThreadExists(t,e),t.db.select().from(Re).where(eq(Re.thread_id,e)).orderBy(asc(Re.seq)).all()}catch(r){throw r instanceof c?r:new c("DB_ERROR","Failed to find boxes by thread id",r)}finally{t.close();}}findById(e,t){if(!this.dbExists())return;let r=this.openHandle(false);try{return r.db.select().from(Re).where(and(eq(Re.id,t),eq(Re.thread_id,e))).limit(1).get()??void 0}catch(o){throw o instanceof c?o:new c("DB_ERROR","Failed to find box by id",o)}finally{r.close();}}insert(e){let t=this.openHandle(true);try{this.ensureThreadExists(t,e.threadId);try{t.db.insert(Re).values({id:e.id,thread_id:e.threadId,seq:e.seq,first_task_id:e.first_task_id,mid_task_id:e.mid_task_id,last_task_id:e.last_task_id,task_count:e.task_count,summary:e.summary??null,source_tokens:e.source_tokens,summary_tokens:e.summary_tokens??null,created_at:e.created_at}).run();}catch(o){throw o instanceof Error&&/UNIQUE constraint failed/i.test(o.message)?new c("CONFLICT",`Duplicate seq ${String(e.seq)} for thread ${e.threadId}`,o):o}let r=t.db.select().from(Re).where(eq(Re.id,e.id)).limit(1).get();if(!r)throw new c("DB_ERROR","Insert did not return a row");return r}catch(r){throw r instanceof c?r:new c("DB_ERROR","Failed to insert thread box",r)}finally{t.close();}}};var nn=class extends x{dbPath;constructor(e={}){super(),e.dbPath?this.dbPath=e.dbPath:e.dbRoot&&(this.dbPath=join(e.dbRoot,".crewx","crewx.db"));}resolveDbPath(){return this.dbPath?this.dbPath:super.resolveDbPath()}openHandle(e){let t=this.resolveDbPath();if(e){let o=dirname(t);existsSync(o)||mkdirSync(o,{recursive:true});}else if(!existsSync(t))throw new c("NOT_FOUND","Database not found");let r=T(t);if(e)try{$(r.db,t);}catch(o){throw r.close(),o}return r}bulkInsert(e){if(e.length===0)return;let t=this.openHandle(true);try{t.db.transaction(r=>{for(let o of e)r.insert(ut).values({id:randomUUID(),path:o.path,method:o.method,status_code:o.statusCode,duration_ms:o.durationMs,ip:o.ip??null,request_headers:o.requestHeaders??null,response_headers:o.responseHeaders??null,request_body:o.requestBody??null,response_body:o.responseBody??null,query:o.query??null,user_id:o.userId??null,project_id:o.projectId??null,partition_key:o.partitionKey??"default",timestamp:o.timestamp??new Date().toISOString(),metadata:o.metadata??null}).run();});}catch(r){throw r instanceof c?r:new c("DB_ERROR","Failed to bulk insert request logs",r)}finally{t.close();}}findRecent(e=100){if(!this.dbExists())return [];let t=this.openHandle(false);try{return t.db.select().from(ut).orderBy(desc(ut.timestamp)).limit(e).all()}catch(r){throw new c("DB_ERROR","Failed to find recent request logs",r)}finally{t.close();}}};function Xo(n){return new Date(Math.floor(n/3e5)*3e5).toISOString()}var on=class extends x{dbPath;constructor(e={}){super(),e.dbPath?this.dbPath=e.dbPath:e.dbRoot&&(this.dbPath=join(e.dbRoot,".crewx","crewx.db"));}resolveDbPath(){return this.dbPath?this.dbPath:super.resolveDbPath()}openHandle(e){let t=this.resolveDbPath();if(e){let o=dirname(t);existsSync(o)||mkdirSync(o,{recursive:true});}else if(!existsSync(t))throw new c("NOT_FOUND","Database not found");let r=T(t);if(e)try{$(r.db,t);}catch(o){throw r.close(),o}return r}upsert(e){let t=this.openHandle(true);try{let r=Xo(e.bucketStartMs),o=e.accountRef??"default";t.db.insert(te).values({id:e.id,provider:e.provider,account_ref:o,limit_window:e.limitWindow,bucket_start:r,captured_at:e.capturedAt,used_percent:e.usedPercent,remaining_percent:e.remainingPercent,resets_at:e.resetsAt??null,source:e.source,metadata:e.metadata??null}).onConflictDoUpdate({target:[te.provider,te.account_ref,te.limit_window,te.bucket_start],set:{captured_at:e.capturedAt,used_percent:e.usedPercent,remaining_percent:e.remainingPercent,resets_at:e.resetsAt??null,metadata:e.metadata??null}}).run();}catch(r){throw r instanceof c?r:new c("DB_ERROR","Failed to upsert usage limit snapshot",r)}finally{t.close();}}getTrends(e){if(!this.dbExists())return [];let t=this.openHandle(false);try{let r=t.db.select({provider:te.provider,bucket_start:te.bucket_start,used_percent:te.used_percent,remaining_percent:te.remaining_percent,resets_at:te.resets_at}).from(te).where(and(eq(te.limit_window,e.window),gte(te.bucket_start,e.fromIso),lte(te.bucket_start,e.toIso))).orderBy(asc(te.bucket_start)).all(),o=new Map;for(let i of r)o.has(i.provider)||o.set(i.provider,[]),o.get(i.provider).push({bucketStart:i.bucket_start,usedPercent:i.used_percent,remainingPercent:i.remaining_percent,resetsAt:i.resets_at??null});return Array.from(o.entries()).map(([i,s])=>({provider:i,points:s}))}catch(r){throw new c("DB_ERROR","Failed to get usage limit trends",r)}finally{t.close();}}};var sn=class extends x{dbPath;constructor(e={}){super(),e.dbPath?this.dbPath=e.dbPath:e.dbRoot&&(this.dbPath=join(e.dbRoot,".crewx","crewx.db"));}resolveDbPath(){return this.dbPath?this.dbPath:super.resolveDbPath()}openHandle(e){let t=this.resolveDbPath();if(e){let o=dirname(t);existsSync(o)||mkdirSync(o,{recursive:true});}else if(!existsSync(t))throw new c("NOT_FOUND","Database not found");let r=T(t);if(e)try{$(r.db,t);}catch(o){throw r.close(),o}return r}publish(e){let t=this.openHandle(true);try{t.db.insert(le).values({id:e.id,workspace_id:e.workspaceId,month:e.month,generated_at:e.generatedAt,source_range:e.sourceRange,tier:e.tier,total_tokens:e.totalTokens,total_cost_usd:e.totalCostUsd,payload:e.payload}).onConflictDoUpdate({target:[le.workspace_id,le.month],set:{generated_at:e.generatedAt,source_range:e.sourceRange,tier:e.tier,total_tokens:e.totalTokens,total_cost_usd:e.totalCostUsd,payload:e.payload}}).run();let r=t.db.select().from(le).where(and(eq(le.workspace_id,e.workspaceId),eq(le.month,e.month))).limit(1).get();if(!r)throw new c("DB_ERROR","Failed to read back published usage report");return r}catch(r){throw r instanceof c?r:new c("DB_ERROR","Failed to publish usage report",r)}finally{t.close();}}findByMonth(e,t){if(!this.dbExists())return;let r=this.openHandle(false);try{return r.db.select().from(le).where(and(eq(le.workspace_id,e),eq(le.month,t))).limit(1).get()??void 0}catch(o){throw new c("DB_ERROR","Failed to find usage report",o)}finally{r.close();}}listByWorkspace(e){if(!this.dbExists())return [];let t=this.openHandle(false);try{return t.db.select().from(le).where(eq(le.workspace_id,e)).orderBy(desc(le.month)).all()}catch(r){throw new c("DB_ERROR","Failed to list usage reports",r)}finally{t.close();}}};var oi=500,ii=50,an=class extends x{dbPath;cap;constructor(e={}){super(),e.dbPath?this.dbPath=e.dbPath:e.dbRoot&&(this.dbPath=join(e.dbRoot,".crewx","crewx.db")),this.cap=e.cap??oi;}resolveDbPath(){return this.dbPath?this.dbPath:super.resolveDbPath()}openHandle(e){let t=this.resolveDbPath();if(e){let o=dirname(t);existsSync(o)||mkdirSync(o,{recursive:true});}else if(!existsSync(t))throw new c("NOT_FOUND","Database not found");let r=T(t);if(e)try{$(r.db,t);}catch(o){throw r.close(),o}return r}create(e){let t=this.openHandle(true);try{let r=fe("ntf"),o=new Date().toISOString();return t.db.insert(N).values({id:r,workspace_id:e.workspaceId,agent_id:e.agentId??null,task_id:e.taskId??null,thread_id:e.threadId??null,source:e.source??"agent",level:e.level??"info",title:e.title,body:e.body??null,target_user_id:e.targetUserId??null,created_at:o,metadata:e.metadata??null}).run(),this.enforceCap(t,e.workspaceId),{id:r}}catch(r){throw r instanceof c?r:new c("DB_ERROR","Failed to create notification",r)}finally{t.close();}}enforceCap(e,t){let i=(e.db.select({count:sql`count(*)`}).from(N).where(eq(N.workspace_id,t)).get()?.count??0)-this.cap;if(i<=0)return;let d=e.db.select({id:N.id}).from(N).innerJoin(Y,eq(Y.notification_id,N.id)).where(eq(N.workspace_id,t)).groupBy(N.id).orderBy(asc(N.created_at)).limit(i).all().map(l=>l.id);d.length!==0&&(e.db.delete(Y).where(inArray(Y.notification_id,d)).run(),e.db.delete(N).where(inArray(N.id,d)).run());}list(e){if(!this.dbExists())return [];let t=e.limit??ii,r=this.openHandle(false);try{return r.db.select({id:N.id,workspace_id:N.workspace_id,agent_id:N.agent_id,task_id:N.task_id,thread_id:N.thread_id,source:N.source,level:N.level,title:N.title,body:N.body,target_user_id:N.target_user_id,created_at:N.created_at,metadata:N.metadata,read_at:Y.read_at}).from(N).leftJoin(Y,and(eq(Y.notification_id,N.id),eq(Y.user_id,e.userId))).where(eq(N.workspace_id,e.workspaceId)).orderBy(desc(N.created_at)).limit(t).all().map(i=>({...i,read_at:i.read_at??null,read:i.read_at!=null}))}catch(o){throw new c("DB_ERROR","Failed to list notifications",o)}finally{r.close();}}unreadCount(e){if(!this.dbExists())return 0;let t=this.openHandle(false);try{return t.db.select({count:sql`count(*)`}).from(N).leftJoin(Y,and(eq(Y.notification_id,N.id),eq(Y.user_id,e.userId))).where(and(eq(N.workspace_id,e.workspaceId),isNull(Y.notification_id))).get()?.count??0}catch(r){throw new c("DB_ERROR","Failed to count unread notifications",r)}finally{t.close();}}markRead(e){let t=this.openHandle(true);try{if(!t.db.select({id:N.id}).from(N).where(and(eq(N.id,e.notificationId),eq(N.workspace_id,e.workspaceId))).get())throw new c("NOT_FOUND","Notification not found in workspace");return t.db.insert(Y).values({notification_id:e.notificationId,user_id:e.userId,read_at:new Date().toISOString()}).onConflictDoNothing().run().changes>0}catch(r){throw r instanceof c?r:new c("DB_ERROR","Failed to mark notification read",r)}finally{t.close();}}markAllRead(e){let t=this.openHandle(true);try{let r=t.db.select({id:N.id}).from(N).leftJoin(Y,and(eq(Y.notification_id,N.id),eq(Y.user_id,e.userId))).where(and(eq(N.workspace_id,e.workspaceId),isNull(Y.notification_id))).all();if(r.length===0)return 0;let o=new Date().toISOString();return t.db.transaction(i=>{for(let s of r)i.insert(Y).values({notification_id:s.id,user_id:e.userId,read_at:o}).onConflictDoNothing().run();}),r.length}catch(r){throw r instanceof c?r:new c("DB_ERROR","Failed to mark all notifications read",r)}finally{t.close();}}};var di=50,cn=class extends x{dbPath;constructor(e={}){super(),e.dbPath?this.dbPath=e.dbPath:e.dbRoot&&(this.dbPath=join(e.dbRoot,".crewx","crewx.db"));}resolveDbPath(){return this.dbPath?this.dbPath:super.resolveDbPath()}openHandle(e){let t=this.resolveDbPath();if(e){let o=dirname(t);existsSync(o)||mkdirSync(o,{recursive:true});}else if(!existsSync(t))throw new c("NOT_FOUND","Database not found");let r=T(t);if(e)try{$(r.db,t);}catch(o){throw r.close(),o}return r}create(e){let t=this.openHandle(true);try{let r=new Date().toISOString(),o=[],i=e.map(s=>{let d=fe("sug");return o.push(d),{id:d,workspace_id:s.workspaceId,agent_id:s.agentId,task_id:s.taskId??null,type:s.type,status:s.status??"pending",payload:s.payload,applied_commit_sha:s.appliedCommitSha??null,created_at:r,updated_at:r}});return i.length>0&&t.db.insert(L).values(i).run(),{ids:o}}catch(r){throw r instanceof c?r:new c("DB_ERROR","Failed to create agent suggestions",r)}finally{t.close();}}findLatestSet(e,t){if(!this.dbExists())return [];let r=this.openHandle(false);try{let o=r.db.select({task_id:L.task_id}).from(L).where(and(eq(L.workspace_id,e),eq(L.agent_id,t))).orderBy(desc(L.created_at)).limit(1).get();if(!o)return [];let i=o.task_id===null?isNull(L.task_id):eq(L.task_id,o.task_id);return r.db.select().from(L).where(and(eq(L.workspace_id,e),eq(L.agent_id,t),i)).orderBy(asc(L.created_at)).all()}catch(o){throw new c("DB_ERROR","Failed to find latest agent suggestion set",o)}finally{r.close();}}findSetByTaskId(e,t,r){if(!this.dbExists())return [];let o=this.openHandle(false);try{return o.db.select().from(L).where(and(eq(L.workspace_id,e),eq(L.agent_id,t),eq(L.task_id,r))).orderBy(asc(L.created_at)).all()}catch(i){throw new c("DB_ERROR","Failed to find agent suggestion set by task id",i)}finally{o.close();}}findById(e,t,r){if(!this.dbExists())return null;let o=this.openHandle(false);try{return o.db.select().from(L).where(and(eq(L.workspace_id,e),eq(L.agent_id,t),eq(L.id,r))).get()??null}catch(i){throw new c("DB_ERROR","Failed to find agent suggestion by id",i)}finally{o.close();}}updateStatus(e,t,r){let o=this.openHandle(true);try{let i={status:t,updated_at:new Date().toISOString()};return r!==void 0&&(i.applied_commit_sha=r),o.db.update(L).set(i).where(eq(L.id,e)).run().changes>0}catch(i){throw i instanceof c?i:new c("DB_ERROR","Failed to update agent suggestion status",i)}finally{o.close();}}listByAgent(e,t,r=di){if(!this.dbExists())return [];let o=this.openHandle(false);try{return o.db.select().from(L).where(and(eq(L.workspace_id,e),eq(L.agent_id,t))).orderBy(desc(L.created_at)).limit(r).all()}catch(i){throw new c("DB_ERROR","Failed to list agent suggestions",i)}finally{o.close();}}findDismissed(e,t,r=20){if(!this.dbExists())return [];let o=this.openHandle(false);try{return o.db.select().from(L).where(and(eq(L.workspace_id,e),eq(L.agent_id,t),eq(L.status,"dismissed"))).orderBy(desc(L.updated_at)).limit(r).all()}catch(i){throw new c("DB_ERROR","Failed to find dismissed agent suggestions",i)}finally{o.close();}}};export{cn as AgentSuggestionRepository,Lo as BUILTIN_THREAD_STATES,x as BaseSqliteRepository,Xt as COMMON_CODE_COLORS,Yt as COMMON_CODE_GROUPS,pn as CREWX_JOURNAL_SIZE_LIMIT_BYTES,vr as CommonCodeRepository,Q as CommonCodeRepositoryError,di as DEFAULT_AGENT_SUGGESTION_LIST_LIMIT,oi as DEFAULT_NOTIFICATION_CAP,ii as DEFAULT_NOTIFICATION_LIST_LIMIT,Kn as DEFAULT_PROJECT_STAGES,Lr as DEFAULT_PROJECT_STAGE_KEYS,an as NotificationRepository,xr as ProjectRepository,c as RepositoryError,nn as RequestLogRepository,en as SpanRepository,fo as TASK_LOG_MIGRATION_EVENT_ROW_BYTES,ar as TASK_LOG_MIGRATION_MIN_FREE_SPACE_BYTES,_o as TASK_LOG_MIGRATION_TERMINAL_STATUSES,Bo as THREAD_HIGHLIGHT_DELETION_REASON_REGENERATION_REPLACED,Uo as THREAD_HIGHLIGHT_REGENERATION_COMMIT_FAILED,ld as THREAD_HIGHLIGHT_REGENERATION_DETECTION_FAILED,Fo as THREAD_HIGHLIGHT_REGENERATION_INTERRUPTED,cd as THREAD_HIGHLIGHT_REGENERATION_NO_ELIGIBLE_TURNS,xo as THREAD_PRIORITIES,Dt as TaskLogRepository,$r as TaskRepository,rn as ThreadBoxRepository,Tt as ThreadHighlightConflictError,fr as ThreadHighlightRegenerationConflictError,_r as ThreadHistoryConflictError,Xr as ThreadHistoryRepository,Fr as ThreadRepository,at as ThreadTitleMetadataPatchError,tn as ToolCallRepository,on as UsageLimitSnapshotRepository,sn as UsageReportRepository,Ar as WorkspaceRepository,Xo as calcBucketStart,Po as customStateLabel,gt as generateCommonCodeId,yo as hasSufficientTaskLogMigrationFreeSpace,ed as hasThreadTitleKey,Lt as isThreadPriority,Pt as isThreadState,od as matchesThreadTitleFilter,Kr as mergeThreadTitleMeta,Ao as migrateLegacyThreadTitleCommonCodes,Ya as migrateThreadTitleCommonCodes,T as openDrizzleDb,rd as parseThreadPriorityFilter,nd as parseThreadStateFilter,zs as pushSchema,ur as readThreadTitleMeta,fi as reclaimTemporaryJournal,mo as resolveTaskLogMigrationDbPath,ct as runMigrations,$ as runMigrationsOnce,Aa as runTaskLogMigration,Oa as taskLogBackupName,a as tasks,td as threadTitleSearchHaystack,bo as tryCheckpointTaskLogWal};