@crewx/cli 0.9.0-rc.19 → 0.9.0-rc.191

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 (82) hide show
  1. package/dist/bootstrap/codex-writable-roots.d.ts +20 -1
  2. package/dist/bootstrap/codex-writable-roots.js +1 -88
  3. package/dist/bootstrap/crewx-cli.js +1 -63
  4. package/dist/bootstrap/rate-limit-snapshot.d.ts +15 -0
  5. package/dist/bootstrap/rate-limit-snapshot.js +1 -0
  6. package/dist/builtin.d.ts +1 -1
  7. package/dist/builtin.js +5 -127
  8. package/dist/commands/agent.d.ts +1 -0
  9. package/dist/commands/agent.js +3 -246
  10. package/dist/commands/ai-account.d.ts +16 -0
  11. package/dist/commands/ai-account.js +38 -0
  12. package/dist/commands/cal.d.ts +15 -0
  13. package/dist/commands/cal.js +2 -0
  14. package/dist/commands/command-help.d.ts +28 -0
  15. package/dist/commands/command-help.js +87 -0
  16. package/dist/commands/db.d.ts +3 -0
  17. package/dist/commands/db.js +59 -125
  18. package/dist/commands/detached.d.ts +121 -0
  19. package/dist/commands/detached.js +15 -0
  20. package/dist/commands/doctor.d.ts +77 -0
  21. package/dist/commands/doctor.js +4 -196
  22. package/dist/commands/emit-trailer.d.ts +25 -0
  23. package/dist/commands/emit-trailer.js +2 -0
  24. package/dist/commands/execute.d.ts +8 -4
  25. package/dist/commands/execute.js +15 -146
  26. package/dist/commands/history.d.ts +18 -0
  27. package/dist/commands/history.js +2 -0
  28. package/dist/commands/hook/command-marker.d.ts +2 -0
  29. package/dist/commands/hook/command-marker.js +1 -0
  30. package/dist/commands/hook/install.d.ts +0 -1
  31. package/dist/commands/hook/install.js +8 -175
  32. package/dist/commands/hook/paths.js +1 -94
  33. package/dist/commands/hook/status.js +1 -86
  34. package/dist/commands/hook/uninstall.js +1 -71
  35. package/dist/commands/hook-dispatch.js +2 -180
  36. package/dist/commands/init.d.ts +34 -0
  37. package/dist/commands/init.js +38 -371
  38. package/dist/commands/kill.d.ts +2 -8
  39. package/dist/commands/kill.js +1 -52
  40. package/dist/commands/log.js +3 -95
  41. package/dist/commands/parse-agent-message.js +1 -52
  42. package/dist/commands/parse-common-flags.d.ts +5 -1
  43. package/dist/commands/parse-common-flags.js +3 -181
  44. package/dist/commands/ps.d.ts +2 -2
  45. package/dist/commands/ps.js +2 -107
  46. package/dist/commands/publish.d.ts +1 -0
  47. package/dist/commands/publish.js +27 -0
  48. package/dist/commands/query.d.ts +7 -2
  49. package/dist/commands/query.js +16 -146
  50. package/dist/commands/registry.js +1 -31
  51. package/dist/commands/resolve-prompt.js +3 -54
  52. package/dist/commands/resolve-recipient.d.ts +14 -0
  53. package/dist/commands/resolve-recipient.js +3 -0
  54. package/dist/commands/restart.d.ts +3 -1
  55. package/dist/commands/restart.js +18 -162
  56. package/dist/commands/result.d.ts +8 -3
  57. package/dist/commands/result.js +1 -70
  58. package/dist/commands/shortcut.d.ts +1 -0
  59. package/dist/commands/shortcut.js +18 -0
  60. package/dist/commands/slack.js +16 -559
  61. package/dist/commands/stop.d.ts +8 -0
  62. package/dist/commands/stop.js +8 -0
  63. package/dist/commands/write-output.js +1 -24
  64. package/dist/index.d.ts +1 -1
  65. package/dist/index.js +1 -5
  66. package/dist/logging.d.ts +1 -1
  67. package/dist/logging.js +10 -86
  68. package/dist/main.d.ts +3 -2
  69. package/dist/main.js +51 -253
  70. package/dist/register-builtin-tools.js +1 -9
  71. package/dist/slack/file-download.js +1 -134
  72. package/dist/slack/markdown.js +1 -33
  73. package/dist/utils/env-defaults.d.ts +2 -5
  74. package/dist/utils/env-defaults.js +1 -10
  75. package/dist/utils/inherited-trace.d.ts +24 -0
  76. package/dist/utils/inherited-trace.js +1 -25
  77. package/dist/utils/product-package-root.d.ts +6 -0
  78. package/dist/utils/product-package-root.js +1 -0
  79. package/dist/utils/sdk-compat.d.ts +24 -0
  80. package/dist/utils/sdk-compat.js +1 -0
  81. package/dist/utils/version.js +1 -28
  82. package/package.json +16 -12
@@ -0,0 +1,38 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.isAiAccountCapabilitiesRequest=un;exports.runAiAccountCommand=G;exports.handleAiAccount=an;const y=require("child_process");const N=require("./parse-common-flags");const U=require("./command-help");const a="cli/antigravity";const k={claude:"cli/claude","cli/claude":"cli/claude",codex:"cli/codex","cli/codex":"cli/codex",antigravity:a,"cli/antigravity":a};const M=new Set(["ACCOUNT_LABEL_INVALID","ACCOUNT_PROVIDER_INVALID","ACCOUNT_PROVIDER_UNSUPPORTED","ACCOUNT_NOT_FOUND","ACCOUNT_UNKNOWN","ACCOUNT_DEFAULT_PROTECTED","ACCOUNT_ACTIVE_PROTECTED","ACCOUNT_RESUME_REMOVED","ACCOUNT_RUNTIME_UNAVAILABLE","ACCOUNT_RUNTIME_CAPABILITY","ACCOUNT_RUNTIME_CAPABILITY_UNSUPPORTED","ACCOUNT_RUNTIME_MISMATCH","ACCOUNT_RUNTIME_CONTEXT_REQUIRED","ACCOUNT_INSTALL_FAILED","ACCOUNT_OPTION_UNSUPPORTED","ACCOUNT_NOT_SIGNED_IN","ACCOUNT_LOGIN_IN_PROGRESS","ACCOUNT_LOGIN_INCOMPLETE","ACCOUNT_LOGIN_UNSUPPORTED_HOST","ACCOUNT_LOGIN_UNSUPPORTED_POLICY","ACCOUNT_LOGIN_FAILED","ACCOUNT_LOGIN_CANCELLED","ACCOUNT_BUSY","ACCOUNT_RESUME_AUTH_CHANGED","ACCOUNT_RESUME_NOT_FOUND","ACCOUNT_LOGIN_FLOW_UNSUPPORTED","ACCOUNT_REGISTRY_INVALID","ACCOUNT_CAPABILITIES_UNSUPPORTED","ACCOUNT_LOGIN_REQUIRES_LOCAL_UI","ACCOUNT_COMMAND_FAILED","ACCOUNT_OPERATION_FAILED"]);class C extends Error{code;constructor(e){super(e);this.code=e;this.name="AiAccountCommandError"}}function I(n){return typeof n==="object"&&n!==null&&!Array.isArray(n)}function R(n,e){const i=n[e];return typeof i==="function"?i:void 0}function A(n,e,i="ACCOUNT_RUNTIME_CAPABILITY"){const t=R(n,e);if(!t)throw new C(i);return t}function b(){return require("@crewx/sdk")}function m(n,e){return typeof n==="string"&&M.has(n)?n:e}function w(n,e){if(n instanceof C)return n.code;if(I(n))return m(n.code,e);return e}function p(n,e){process.stderr.write(`Error [${m(n,"ACCOUNT_OPERATION_FAILED")}]${e?`: ${e}`:""}
2
+ `)}function x(n){if(n===void 0)return void 0;const e=k[n];if(!e){throw new N.UnknownOptionError(`Unknown provider: ${n} (use claude, codex, or antigravity)`)}return e}function B(n){const e={positional:[],json:false};for(let i=0;i<n.length;i+=1){const t=n[i];if(t==="--json"){e.json=true}else if(t==="--provider"||t.startsWith("--provider=")){const o=t.includes("=")?t.slice("--provider=".length):n[++i];e.provider=x(o)}else if(t==="--label"||t.startsWith("--label=")){e.label=t.includes("=")?t.slice("--label=".length):n[++i]}else if(t.startsWith("--")){throw new N.UnknownOptionError(`Unknown option: ${t}`)}else{e.positional.push(t)}}return e}function v(n){let e=0;for(const i of n){const t=i.codePointAt(0)??0;const o=t>=4352&&t<=4447||t>=11904&&t<=42191||t>=44032&&t<=55203||t>=63744&&t<=64255||t>=65280&&t<=65376;e+=o?2:1}return e}function F(n){const e=n.map(r=>[r.provider,r.id,r.active?"*":"",r.label,r.provider===a?"":r.dir]);const i=["PROVIDER","ID","ACTIVE","LABEL","DIR"];const t=i.map((r,s)=>Math.max(v(r),...e.map(c=>v(c[s]))));const o=r=>r.map((s,c)=>s+" ".repeat(t[c]-v(s))).join(" ").trimEnd();return[o(i),...e.map(o)].join("\n")}function V(n){if(n.provider!==a)return n;const{dir:e,...i}=n;return i}function j(n){return n?[n]:["cli/claude","cli/codex",a]}function q(n,e,i,t){if(n==="cli/codex"){const c=e.trim();return{loggedIn:i===0,lines:[...c?[c]:[],`loggedIn:${i===0}`,`configDirectory:${t}`]}}let o={};try{o=JSON.parse(e)}catch{}const r=o.loggedIn===true;const s=[`loggedIn:${r}`];if(typeof o.authMethod==="string")s.push(`authMethod:${o.authMethod}`);if(typeof o.subscriptionType==="string")s.push(`subscriptionType:${o.subscriptionType}`);s.push(`configDirectory:${t}`);return{loggedIn:r,lines:s}}function S(n,e){const i=A(n,"listAiAccounts");return i(e)}function P(n,e,i){if(e===a)return n!=="default";if(e!==void 0)return false;return S(i,a).some(t=>t.id===n&&!t.builtIn&&t.loginKind==="acp-flow")}function J(n,e,i,t){const o=A(t,"getStatusInvocation");const r=A(t,"applyAiAccountEnv");const s=o(n,e);const c=(0,y.spawnSync)(s.command,s.argv,{env:r(process.env,s),encoding:"utf8",timeout:3e4});if(c.error)throw new C("ACCOUNT_COMMAND_FAILED");const u=e??(s.command==="codex"?"cli/codex":s.command==="agy"?a:"cli/claude");if(u===a){const T=c.status===0;if(i)process.stdout.write(`${JSON.stringify({id:n,provider:u,loggedIn:T})}
3
+ `);else process.stdout.write(`loggedIn:${T}
4
+ `);return T?0:1}const d=s.env.CLAUDE_CONFIG_DIR??s.env.CODEX_HOME??Y(t,u);const l=u==="cli/codex"?`${c.stdout??""}${c.stderr??""}`:c.stdout??"";const _=q(u,l,c.status??1,d);if(i){process.stdout.write(`${JSON.stringify({id:n,provider:u,loggedIn:_.loggedIn,configDirectory:d})}
5
+ `)}else{process.stdout.write(`${_.lines.join("\n")}
6
+ `)}return _.loggedIn?0:1}function Y(n,e){return S(n,e).find(i=>i.builtIn)?.dir??""}function H(n,e,i){const t=A(i,"getLoginInvocation");const o=A(i,"applyAiAccountEnv");const r=t(n,e);process.stdout.write(`Running official login: ${r.command} ${r.argv.join(" ")}
7
+ `);const s=(0,y.spawnSync)(r.command,r.argv,{env:o(process.env,r),stdio:"inherit"});if(s.error)throw new C("ACCOUNT_COMMAND_FAILED");return s.status??1}function D(n,e=()=>void 0){const i=n.signalHost??process;const t=new AbortController;let o=false;let r;let s;const c=new Promise(_=>{s=_});const u=_=>{if(o||r)return;r=_;t.abort();e();s(_)};const d=()=>u("SIGINT");const l=()=>u("SIGTERM");i.on("SIGINT",d);i.on("SIGTERM",l);return{signal:t.signal,whenInterrupted:c,interruptedBy:()=>r,isCompleted:()=>o,markComplete:()=>{o=true},dispose:()=>{i.removeListener("SIGINT",d);i.removeListener("SIGTERM",l)}}}function L(n){return n==="SIGINT"?130:143}function z(n){return n.isAgentTask?.()??Boolean(process.env["CREWX_AGENT_ID"])}function W(n){return n.isInteractive?.()??(process.stdin.isTTY===true&&process.stderr.isTTY===true)}function X(n){const e=n.state==="signed-out"?"ACCOUNT_NOT_SIGNED_IN":n.state==="login-in-progress"?"ACCOUNT_LOGIN_IN_PROGRESS":n.state==="login-incomplete"?"ACCOUNT_LOGIN_INCOMPLETE":"ACCOUNT_RUNTIME_UNAVAILABLE";return m(n.code,e)}function K(n){try{const e=new URL(n);if(e.protocol!=="https:"||!e.hostname||e.username||e.password)return void 0;return e.href}catch{return void 0}}const Q=new Set(["signed-in","signed-out","runtime-missing","login-in-progress","login-incomplete","error"]);function Z(n,e,i){const t=typeof e.state==="string"&&Q.has(e.state)?e.state:"error";const o={id:n,provider:a,state:t};if(typeof e.runtimeVersion==="string")o.runtimeVersion=e.runtimeVersion;const r=m(e.code,"ACCOUNT_RUNTIME_UNAVAILABLE");if(e.code!==void 0||t==="error")o.code=r;if(i)process.stdout.write(`${JSON.stringify(o)}
8
+ `);else{process.stdout.write(`state:${t}
9
+ `);if(typeof e.runtimeVersion==="string")process.stdout.write(`runtimeVersion:${e.runtimeVersion}
10
+ `);if(e.code!==void 0||t==="error")process.stdout.write(`code:${r}
11
+ `)}if(t==="error")return 2;return t==="signed-in"?0:1}async function nn(n,e,i){const t=A(i,"getAiAccountStatus");const o=await t(n);if(!I(o))throw new C("ACCOUNT_RUNTIME_UNAVAILABLE");return Z(n,o,e)}async function en(n,e,i,t){if(e||z(t)||!W(t)){p("ACCOUNT_LOGIN_REQUIRES_LOCAL_UI","Sign in from CrewX Settings > Accounts.");return 2}const o=A(i,"startAiAccountLogin");let r;let s;const c=()=>{if(!r||typeof r.cancel!=="function")return Promise.resolve();s??=Promise.resolve().then(()=>(r?.cancel).call(r)).then(()=>void 0,()=>void 0);return s};const u=D(t,()=>{void c()});try{const d=await o(n,{signal:u.signal});if(!I(d))throw new C("ACCOUNT_LOGIN_FAILED");r=d;if(typeof r.cancel!=="function"||!("done"in r)||!("authorizationUrl"in r)){await c();throw new C("ACCOUNT_LOGIN_FAILED")}const l=Promise.resolve(r.done).then(f=>{u.markComplete();return{kind:"done",value:f}},f=>{u.markComplete();return{kind:"error",error:f}});const _=Promise.resolve(r.authorizationUrl).then(f=>{if(typeof f==="string"&&f.length>0&&!u.isCompleted()&&!u.interruptedBy()){const h=K(f);if(h){process.stderr.write(`Open this link in your browser to sign in:
12
+ ${h}
13
+ `)}}return{kind:"authorization"}},()=>({kind:"authorization"}));const T=u.whenInterrupted.then(f=>({kind:"interrupted",signal:f}));const E=await Promise.race([l,_,T]);let O;let g=u.interruptedBy();if(E.kind==="done"||E.kind==="error"){O=E}else if(E.kind==="interrupted"){g=E.signal;await c();O=await l}else{const f=await Promise.race([l,T]);if(f.kind==="interrupted"){g=f.signal;await c();O=await l}else{O=f}}if(O.kind==="done"&&I(O.value)&&O.value.state==="signed-in"&&O.value.browserSuppressionObserved===true){if(e)process.stdout.write(`${JSON.stringify({id:n,provider:a,state:"signed-in"})}
14
+ `);else process.stdout.write(`signed-in:${n}
15
+ `);return 0}if(g){p("ACCOUNT_LOGIN_CANCELLED");return L(g)}p(w(O.kind==="error"?O.error:void 0,"ACCOUNT_LOGIN_FAILED"));return 2}catch(d){const l=u.interruptedBy();if(l){await c();p("ACCOUNT_LOGIN_CANCELLED");return L(l)}p(w(d,"ACCOUNT_LOGIN_FAILED"));return 2}finally{if(u.interruptedBy())await c();u.dispose()}}const tn=new Set(["unsupported_platform","not_installed","digest_mismatch","helper_path_unsupported"]);function rn(n,e){const i={provider:n,installed:e.installed===true,platformSupported:e.platformSupported===true};if(typeof e.version==="string"||e.version===null)i.version=e.version;if(typeof e.reason==="string"&&tn.has(e.reason)){i.reason=e.reason}return i}function $(n,e,i){const t=rn(n,e);if(i)process.stdout.write(`${JSON.stringify(t)}
16
+ `);else{process.stdout.write(`installed:${t.installed}
17
+ `);process.stdout.write(`version:${t.version??"none"}
18
+ `);process.stdout.write(`platformSupported:${t.platformSupported}
19
+ `);if(t.reason!==void 0)process.stdout.write(`reason:${t.reason}
20
+ `)}return t.installed?0:1}async function on(n,e){const i=A(e,"getAiAccountRuntimeStatus");const t=i(a);if(!I(t))throw new C("ACCOUNT_RUNTIME_UNAVAILABLE");return $(a,t,n)}async function sn(n,e,i){const t=A(e,"installAiAccountRuntime");const o=D(i);try{const r=await Promise.resolve().then(()=>t(a,{signal:o.signal})).then(s=>{o.markComplete();return{ok:true,value:s}},s=>{o.markComplete();return{ok:false,error:s}});if(!r.ok){if(o.interruptedBy()){p("ACCOUNT_INSTALL_FAILED");return L(o.interruptedBy())}p(w(r.error,"ACCOUNT_INSTALL_FAILED"));return 2}if(!I(r.value))throw new C("ACCOUNT_INSTALL_FAILED");return $(a,r.value,n)}finally{o.dispose()}}async function cn(n,e){if(n.length!==1||n[0]!=="--json"){p("ACCOUNT_OPTION_UNSUPPORTED");return 2}const i=R(e,"getAiAccountCapabilities");if(!i){p("ACCOUNT_CAPABILITIES_UNSUPPORTED");return 2}try{const t=i();if(!I(t))throw new C("ACCOUNT_CAPABILITIES_UNSUPPORTED");const o=JSON.stringify(t);if(!o)throw new C("ACCOUNT_CAPABILITIES_UNSUPPORTED");process.stdout.write(`${o}
21
+ `);return 0}catch(t){p(w(t,"ACCOUNT_CAPABILITIES_UNSUPPORTED"));return 2}}function un(n){return n.length===3&&n[0]==="ai-account"&&n[1]==="capabilities"&&n[2]==="--json"}async function G(n,e={}){const[i,...t]=n;if(t.includes("--help")||t.includes("-h")){process.stdout.write(`${U.AI_ACCOUNT_USAGE}
22
+ `);return 0}let o;try{o=e.sdk??b()}catch{p(i==="capabilities"?"ACCOUNT_CAPABILITIES_UNSUPPORTED":"ACCOUNT_RUNTIME_CAPABILITY");return 2}if(i==="capabilities")return cn(t,o);try{const r=B(t);const s=r.positional[0];switch(i){case"list":{const c=j(r.provider).flatMap(u=>S(o,u));process.stdout.write(r.json?`${JSON.stringify(c.map(V))}
23
+ `:`${F(c)}
24
+ `);return 0}case"add":{if(!r.provider)throw new N.UnknownOptionError("add requires --provider claude|codex|antigravity");if(r.label===void 0)throw new N.UnknownOptionError("add requires --label <name>");const c=A(o,"addAiAccount");const u=c(r.provider,r.label);if(r.json){const d=r.provider===a?{provider:r.provider,id:u.id}:{provider:r.provider,...u};process.stdout.write(`${JSON.stringify(d)}
25
+ `)}else if(r.provider===a){process.stdout.write(`added ${u.id} for ${r.provider}
26
+ next: crewx ai-account login ${u.id} --provider antigravity
27
+ `)}else{process.stdout.write(`added ${u.id} for ${r.provider}
28
+ configDirectory:${u.dir}
29
+ next: crewx ai-account login ${u.id}
30
+ `)}return 0}case"login":{if(!s)throw new N.UnknownOptionError(`login requires an account id
31
+ ${U.AI_ACCOUNT_USAGE}`);if(P(s,r.provider,o)){return await en(s,r.json,o,e)}return H(s,r.provider,o)}case"status":{if(!s)throw new N.UnknownOptionError(`status requires an account id
32
+ ${U.AI_ACCOUNT_USAGE}`);if(P(s,r.provider,o))return await nn(s,r.json,o);return J(s,r.provider,r.json,o)}case"use":{if(!s)throw new N.UnknownOptionError(`use requires an account id
33
+ ${U.AI_ACCOUNT_USAGE}`);if(!r.provider)throw new N.UnknownOptionError("use requires --provider claude|codex|antigravity");if(r.provider===a&&s!=="default"){const u=A(o,"getAiAccountStatus");const d=await u(s);if(!I(d)||d.state!=="signed-in"){throw new C(I(d)?X(d):"ACCOUNT_RUNTIME_UNAVAILABLE")}}const c=A(o,"setActiveAiAccount");await c(r.provider,s);process.stdout.write(`active account for ${r.provider}: ${s}
34
+ `);return 0}case"remove":{if(!s)throw new N.UnknownOptionError(`remove requires an account id
35
+ ${U.AI_ACCOUNT_USAGE}`);const c=S(o,a).some(l=>l.id===s&&!l.builtIn&&l.loginKind==="acp-flow");const u=c?A(o,"removeAiAccountGuarded"):A(o,"removeAiAccount");const d=await u(s);if(r.json)process.stdout.write(`${JSON.stringify(d)}
36
+ `);else process.stdout.write(`removed ${s}; its config directory was kept on disk
37
+ `);return 0}case"runtime":{const c=s;if(r.positional.length!==1||c!=="status"&&c!=="install"){throw new N.UnknownOptionError(`runtime requires status or install
38
+ ${U.AI_ACCOUNT_USAGE}`)}if(r.provider!==void 0&&r.provider!==a){throw new C("ACCOUNT_PROVIDER_UNSUPPORTED")}return c==="status"?await on(r.json,o):await sn(r.json,o,e)}default:p("ACCOUNT_OPTION_UNSUPPORTED");return 2}}catch(r){if(r instanceof N.UnknownOptionError){p("ACCOUNT_OPTION_UNSUPPORTED");return 2}const s=i==="login"?"ACCOUNT_LOGIN_FAILED":i==="runtime"?"ACCOUNT_RUNTIME_UNAVAILABLE":"ACCOUNT_OPERATION_FAILED";p(w(r,s));return 2}}async function an(n,e={}){process.exitCode=await G(n,e)}
@@ -0,0 +1,15 @@
1
+ import type { ActionContext } from '@crewx/knowledge-core';
2
+ /** Suggested wait rungs in seconds. 540 is the safe caller-harness cap. */
3
+ export declare const WAIT_LADDER_SECONDS: readonly [60, 300, 540];
4
+ export interface SuggestWaitSecondsOptions {
5
+ startedAt?: string | number | Date | null;
6
+ lastWaitSeconds?: number;
7
+ now?: number;
8
+ }
9
+ /**
10
+ * Select the next safe result wait based on task runtime without stepping
11
+ * down from the wait value the caller just used.
12
+ */
13
+ export declare function suggestWaitSeconds(options: SuggestWaitSecondsOptions): number;
14
+ /** Write a human-only CAL footer without contaminating command stdout. */
15
+ export declare function writeCalFooter(context: ActionContext): void;
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.WAIT_LADDER_SECONDS=void 0;exports.suggestWaitSeconds=D;exports.writeCalFooter=a;const i=require("@crewx/knowledge-core");exports.WAIT_LADDER_SECONDS=[60,300,540];function d(e){if(e instanceof Date){return Number.isFinite(e.getTime())?e.getTime():void 0}if(typeof e==="number"){return Number.isFinite(e)?e:void 0}if(typeof e==="string"){const t=Date.parse(e);return Number.isFinite(t)?t:void 0}return void 0}function D(e){const t=Number.isFinite(e.now)?e.now:Date.now();const n=d(e.startedAt);const r=n===void 0?0:Math.max(0,(t-n)/1e3);const s=exports.WAIT_LADDER_SECONDS.find(c=>c>r)??exports.WAIT_LADDER_SECONDS[exports.WAIT_LADDER_SECONDS.length-1];const o=Number.isFinite(e.lastWaitSeconds)?Math.max(0,e.lastWaitSeconds):0;return Math.min(exports.WAIT_LADDER_SECONDS[exports.WAIT_LADDER_SECONDS.length-1],Math.max(s,o))}function a(e){const t=(0,i.formatActions)((0,i.generateNextActions)(e));if(t)process.stderr.write(`${t}
2
+ `)}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * `--help` / `-h` routing for commands that change state.
3
+ *
4
+ * `crewx init --help` used to run init: git init, files, and a workspace row.
5
+ * main.ts asks this module before any handler runs, so a help request prints
6
+ * usage and nothing else.
7
+ */
8
+ export declare const INIT_USAGE = "Usage: crewx init [--force] [--provider cli/claude|cli/codex]\n\nCreate crewx.yaml, support folders, and a git repository in the current folder.\n\n --force Overwrite the existing configuration\n --provider cli/claude|cli/codex Provider for the generated agents\n (detected from PATH when omitted)";
9
+ export declare const STOP_USAGE = "Usage:\n crewx stop <task-id> [--grace=<ms>] Stop a running task\n crewx stop --all Stop all running tasks\n crewx kill <task-id> Alias for stop";
10
+ export declare const RESTART_USAGE = "Usage: crewx restart <task-id>\n\nRestart a failed task as a new task, reusing its thread, agent, and provider.";
11
+ export declare const AI_ACCOUNT_USAGE = "Usage:\n crewx ai-account list [--provider claude|cli/claude|codex|cli/codex|antigravity|cli/antigravity] [--json]\n crewx ai-account add --provider claude|cli/claude|codex|cli/codex|antigravity|cli/antigravity --label <name> [--json]\n crewx ai-account login <id> [--provider claude|cli/claude|codex|cli/codex|antigravity|cli/antigravity] [--json]\n crewx ai-account status <id> [--provider claude|cli/claude|codex|cli/codex|antigravity|cli/antigravity] [--json]\n crewx ai-account use <id> --provider claude|cli/claude|codex|cli/codex|antigravity|cli/antigravity\n crewx ai-account remove <id> [--json]\n crewx ai-account capabilities --json\n crewx ai-account runtime status [--json]\n crewx ai-account runtime install [--json]\n\nAntigravity account login requires a local interactive terminal. If a login is needed\nfrom an agent task or a non-interactive command, sign in from CrewX Settings > Accounts.\nRuntime installation is explicit; list, account status, and task execution never install it.\n\nAntigravity exit codes:\n 0 Operation completed; status commands report signed-in or installed.\n 1 Account is signed-out, or runtime is unsupported, missing, or corrupt.\n 2 Invalid usage or an SDK operation failed; stderr contains a stable error code.\n 130 Cancelled with SIGINT (Ctrl+C), after SDK cleanup.\n 143 Cancelled with SIGTERM, after SDK cleanup.\n\nClaude/Codex login keep the official CLI exit code. Their status commands exit 0\nwhen logged in and 1 when signed out. The native Antigravity default account keeps\nthe existing agy login and status commands; native login keeps the official CLI exit code.";
12
+ export declare const HOOK_USAGE = "Usage: crewx hook install|uninstall|status [options]\n\n install [--yes] [--provider claude|codex] Install the PreToolUse hook in .claude/settings.json\n uninstall [--provider claude|codex] Remove the crewx hook\n status Show hook installation status and plugins";
13
+ export declare const HOOK_DISPATCH_USAGE = "Usage: crewx hook-dispatch --provider <claude|codex>\n\nInternal IPC router: reads one hook payload from stdin and writes the decision to stdout.\nAgent CLI hooks call it; people do not need to run it.";
14
+ export declare const HISTORY_USAGE = "Usage:\n crewx history toc <ref> [--from N] [--limit N]\n crewx history search <ref> (--query <text> | --query-stdin | --query64 <base64url>) [--limit N] [--cursor C]\n crewx history read <ref> --entry N [--offset B] [--bytes B]\n\nRead bounded pages from original messages, activity, and highlights for the current task.\nSearch is literal and accepts up to 256 UTF-8 bytes; --limit accepts 1-20 results.\n--query-stdin reads through EOF, validates UTF-8, and removes at most one trailing LF or CRLF.\nGenerated search continuations use portable --query64 arguments.\n\nExit codes: 2 invalid arguments/query/ref/cursor; 3 missing, expired, out-of-scope, or unavailable data; 4 tampered or unsafe history data.\nSize and I/O failures use exit code 3.";
15
+ export declare const SLACK_USAGE = "Usage: crewx slack:files --thread <thread_ts> [--list | --clean]\n crewx slack --mode <query|execute> --agent <agent-id>\n\nExample:\n crewx slack:files --thread 1234567890.123456";
16
+ export declare const AGENT_USAGE = "Usage: crewx agent [subcommand] [options]\n\n crewx agent # List configured agents (default)\n crewx agent ls # List configured agents\n crewx agent list # Alias for ls\n crewx agent prompt <id> # Inspect rendered agent prompt\n crewx agent interceptor test <id> --phase request|response --text \"<text>\" [--json]\n # Dry-run an agent's interceptor chain on a text (no agent start)\n\nFilter Options (for agent ls):\n --role <value> Filter by agent role (comma-separated for multiple: PM,Dev)\n --team <value> Filter by agent team (comma-separated for multiple)\n --provider <value> Filter by provider (comma-separated, partial match: claude)\n\nExamples:\n crewx agent\n crewx agent ls\n crewx agent ls --role=PM\n crewx agent ls --team=\"CrewX Core Team\"\n crewx agent ls --provider=claude\n crewx agent ls --role=PM --provider=claude\n crewx agent ls --role=PM,general\n CREWX_CONFIG=./crewx.yaml crewx agent list";
17
+ export declare const AGENT_LS_USAGE = "Usage: crewx agent ls [--role <value>] [--team <value>] [--provider <value>]\n\nList configured agents. Filters take comma-separated values; --provider also matches part of a name (claude).";
18
+ export declare const AGENT_PROMPT_USAGE = "Usage: crewx agent prompt <id>\n\nPrint the fully rendered system prompt of one agent.";
19
+ export declare const AGENT_INTERCEPTOR_USAGE = "Usage: crewx agent interceptor test <id> --phase request|response --text \"<text>\" [--json]\n\nRun an agent's interceptor chain once on a text without starting the agent.\nExit 0 when the lane passes; exit 1 when it is blocked or the chain configuration is invalid.";
20
+ /** True when the arguments ask for help. Use only for commands with no free-text message. */
21
+ export declare function isHelpRequest(args: readonly string[]): boolean;
22
+ /**
23
+ * Usage text for `crewx agent … --help`, or undefined when the subcommand should run.
24
+ * The subcommand is `rest[0]`, the same word the agent handler dispatches on.
25
+ */
26
+ export declare function agentHelpUsage(rest: readonly string[]): string | undefined;
27
+ /** Usage text to print instead of running `command`, or undefined when the command should run. */
28
+ export declare function helpUsageFor(command: string, rest: readonly string[]): string | undefined;
@@ -0,0 +1,87 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.AGENT_INTERCEPTOR_USAGE=exports.AGENT_PROMPT_USAGE=exports.AGENT_LS_USAGE=exports.AGENT_USAGE=exports.SLACK_USAGE=exports.HISTORY_USAGE=exports.HOOK_DISPATCH_USAGE=exports.HOOK_USAGE=exports.AI_ACCOUNT_USAGE=exports.RESTART_USAGE=exports.STOP_USAGE=exports.INIT_USAGE=void 0;exports.isHelpRequest=r;exports.agentHelpUsage=i;exports.helpUsageFor=s;exports.INIT_USAGE=`Usage: crewx init [--force] [--provider cli/claude|cli/codex]
2
+
3
+ Create crewx.yaml, support folders, and a git repository in the current folder.
4
+
5
+ --force Overwrite the existing configuration
6
+ --provider cli/claude|cli/codex Provider for the generated agents
7
+ (detected from PATH when omitted)`;exports.STOP_USAGE=`Usage:
8
+ crewx stop <task-id> [--grace=<ms>] Stop a running task
9
+ crewx stop --all Stop all running tasks
10
+ crewx kill <task-id> Alias for stop`;exports.RESTART_USAGE=`Usage: crewx restart <task-id>
11
+
12
+ Restart a failed task as a new task, reusing its thread, agent, and provider.`;exports.AI_ACCOUNT_USAGE=`Usage:
13
+ crewx ai-account list [--provider claude|cli/claude|codex|cli/codex|antigravity|cli/antigravity] [--json]
14
+ crewx ai-account add --provider claude|cli/claude|codex|cli/codex|antigravity|cli/antigravity --label <name> [--json]
15
+ crewx ai-account login <id> [--provider claude|cli/claude|codex|cli/codex|antigravity|cli/antigravity] [--json]
16
+ crewx ai-account status <id> [--provider claude|cli/claude|codex|cli/codex|antigravity|cli/antigravity] [--json]
17
+ crewx ai-account use <id> --provider claude|cli/claude|codex|cli/codex|antigravity|cli/antigravity
18
+ crewx ai-account remove <id> [--json]
19
+ crewx ai-account capabilities --json
20
+ crewx ai-account runtime status [--json]
21
+ crewx ai-account runtime install [--json]
22
+
23
+ Antigravity account login requires a local interactive terminal. If a login is needed
24
+ from an agent task or a non-interactive command, sign in from CrewX Settings > Accounts.
25
+ Runtime installation is explicit; list, account status, and task execution never install it.
26
+
27
+ Antigravity exit codes:
28
+ 0 Operation completed; status commands report signed-in or installed.
29
+ 1 Account is signed-out, or runtime is unsupported, missing, or corrupt.
30
+ 2 Invalid usage or an SDK operation failed; stderr contains a stable error code.
31
+ 130 Cancelled with SIGINT (Ctrl+C), after SDK cleanup.
32
+ 143 Cancelled with SIGTERM, after SDK cleanup.
33
+
34
+ Claude/Codex login keep the official CLI exit code. Their status commands exit 0
35
+ when logged in and 1 when signed out. The native Antigravity default account keeps
36
+ the existing agy login and status commands; native login keeps the official CLI exit code.`;exports.HOOK_USAGE=`Usage: crewx hook install|uninstall|status [options]
37
+
38
+ install [--yes] [--provider claude|codex] Install the PreToolUse hook in .claude/settings.json
39
+ uninstall [--provider claude|codex] Remove the crewx hook
40
+ status Show hook installation status and plugins`;exports.HOOK_DISPATCH_USAGE=`Usage: crewx hook-dispatch --provider <claude|codex>
41
+
42
+ Internal IPC router: reads one hook payload from stdin and writes the decision to stdout.
43
+ Agent CLI hooks call it; people do not need to run it.`;exports.HISTORY_USAGE=`Usage:
44
+ crewx history toc <ref> [--from N] [--limit N]
45
+ crewx history search <ref> (--query <text> | --query-stdin | --query64 <base64url>) [--limit N] [--cursor C]
46
+ crewx history read <ref> --entry N [--offset B] [--bytes B]
47
+
48
+ Read bounded pages from original messages, activity, and highlights for the current task.
49
+ Search is literal and accepts up to 256 UTF-8 bytes; --limit accepts 1-20 results.
50
+ --query-stdin reads through EOF, validates UTF-8, and removes at most one trailing LF or CRLF.
51
+ Generated search continuations use portable --query64 arguments.
52
+
53
+ Exit codes: 2 invalid arguments/query/ref/cursor; 3 missing, expired, out-of-scope, or unavailable data; 4 tampered or unsafe history data.
54
+ Size and I/O failures use exit code 3.`;exports.SLACK_USAGE=`Usage: crewx slack:files --thread <thread_ts> [--list | --clean]
55
+ crewx slack --mode <query|execute> --agent <agent-id>
56
+
57
+ Example:
58
+ crewx slack:files --thread 1234567890.123456`;exports.AGENT_USAGE=`Usage: crewx agent [subcommand] [options]
59
+
60
+ crewx agent # List configured agents (default)
61
+ crewx agent ls # List configured agents
62
+ crewx agent list # Alias for ls
63
+ crewx agent prompt <id> # Inspect rendered agent prompt
64
+ crewx agent interceptor test <id> --phase request|response --text "<text>" [--json]
65
+ # Dry-run an agent's interceptor chain on a text (no agent start)
66
+
67
+ Filter Options (for agent ls):
68
+ --role <value> Filter by agent role (comma-separated for multiple: PM,Dev)
69
+ --team <value> Filter by agent team (comma-separated for multiple)
70
+ --provider <value> Filter by provider (comma-separated, partial match: claude)
71
+
72
+ Examples:
73
+ crewx agent
74
+ crewx agent ls
75
+ crewx agent ls --role=PM
76
+ crewx agent ls --team="CrewX Core Team"
77
+ crewx agent ls --provider=claude
78
+ crewx agent ls --role=PM --provider=claude
79
+ crewx agent ls --role=PM,general
80
+ CREWX_CONFIG=./crewx.yaml crewx agent list`;exports.AGENT_LS_USAGE=`Usage: crewx agent ls [--role <value>] [--team <value>] [--provider <value>]
81
+
82
+ List configured agents. Filters take comma-separated values; --provider also matches part of a name (claude).`;exports.AGENT_PROMPT_USAGE=`Usage: crewx agent prompt <id>
83
+
84
+ Print the fully rendered system prompt of one agent.`;exports.AGENT_INTERCEPTOR_USAGE=`Usage: crewx agent interceptor test <id> --phase request|response --text "<text>" [--json]
85
+
86
+ Run an agent's interceptor chain once on a text without starting the agent.
87
+ Exit 0 when the lane passes; exit 1 when it is blocked or the chain configuration is invalid.`;function r(e){return e.includes("--help")||e.includes("-h")}function i(e){const t=e.filter((a,n)=>e[n-1]!=="--text");if(!r(t))return void 0;switch((e[0]??"").toLowerCase()){case"ls":case"list":return exports.AGENT_LS_USAGE;case"prompt":case"p":return exports.AGENT_PROMPT_USAGE;case"interceptor":return exports.AGENT_INTERCEPTOR_USAGE;default:return exports.AGENT_USAGE}}function s(e,t){if(e==="history"){const a=t[0];if(a==="--help"||a==="-h")return exports.HISTORY_USAGE;if(t.length===2&&(a==="toc"||a==="search"||a==="read")&&(t[1]==="--help"||t[1]==="-h"))return exports.HISTORY_USAGE;return void 0}if(!r(t))return void 0;switch(e){case"agent":return i(t);case"init":return exports.INIT_USAGE;case"stop":case"kill":return exports.STOP_USAGE;case"restart":return exports.RESTART_USAGE;case"ai-account":return exports.AI_ACCOUNT_USAGE;case"hook":return exports.HOOK_USAGE;case"hook-dispatch":return exports.HOOK_DISPATCH_USAGE;case"slack":case"slack:files":return exports.SLACK_USAGE;default:return void 0}}
@@ -6,4 +6,7 @@
6
6
  * crewx db push --force Apply without confirmation + reset migration history
7
7
  * crewx db push --dry-run Show preview only, no changes
8
8
  */
9
+ export declare const TASK_LOG_MIGRATION_HELP = "Usage:\n crewx db migrate-task-logs --dry-run [--db PATH]\n crewx db migrate-task-logs --apply [--db PATH] [--batch-tasks N]\n crewx db migrate-task-logs --verify [--db PATH]\n\nModes:\n --dry-run Read and validate legacy blobs without writing or creating a backup.\n --apply Create a consistent SQLite backup, then migrate one task per transaction.\n --verify Check source invariants, event sequences, counts, and orphan rows.\n\nApply policy:\n Only blob tasks with status success, failed, or completed are migrated.\n pending, running, paused, and unknown statuses are deferred for a later run.\n There is no --force or --include-active option. Apply requires the estimated\n database/event growth plus a 10 GiB free-space reserve.\n\nExit codes:\n 0 Completed with no malformed rows or invariant failures.\n 1 Safe tasks completed but a row/invariant failed, or apply was blocked.\n 2 Invalid command-line arguments.\n\nThe command never runs automatically at server startup and never runs VACUUM.";
10
+ export declare const REQUEST_LOG_MIGRATION_HELP = "Usage:\n crewx db migrate-request-logs [--batch N] [--dry-run]\n\nMoves the request log rows still stored in crewx.db into logs.db, the file next\nto it. Each distinct request/response body is stored once in logs.db, keyed by\nits SHA-256; a row points to its bodies by hash, so nothing is dropped.\n\nOptions:\n --batch N Rows per batch (default 250; a batch is also capped at about 8 MB).\n --dry-run Count rows and distinct bodies without writing anything (logs.db is not created).\n\nSafe while crewx is running: each batch is committed to logs.db, verified there,\nand only then deleted from crewx.db in one short transaction. Interrupt it and run\nit again at any time. The database is chosen like everywhere else (CREWX_DB, else\n~/.crewx/crewx.db). No VACUUM and no DROP: crewx.db keeps its size until a later compaction.\n\nExit codes:\n 0 Every row is in logs.db and none is left in crewx.db (or the dry run finished).\n 1 Rows are still in crewx.db, or an error stopped the move (progress is kept).\n 2 Invalid command-line arguments.";
11
+ export declare const USAGE_BACKFILL_HELP = "Usage:\n crewx db backfill-usage [--dry-run|--apply|--verify] [--db PATH] [--backup PATH]\n crewx db backfill-usage --restore SNAPSHOT [--db PATH]\n\nModes:\n --dry-run Show provider/reason recovery plans without changing the database (default).\n --apply Create a row-level undo snapshot, then account one task per transaction.\n --verify Recheck remaining targets and usageAccounting markers without changing the database.\n --restore Restore rows from SNAPSHOT when their current values still match the snapshot after-state.\n\nApply policy:\n Only success, failed, and completed tasks with zero recorded usage are considered.\n Workflow/MCP anchors and plugin/mock rows are excluded. Rows completed within 24 hours\n are not marked unavailable when their logs do not contain usage.\n\nExit codes:\n 0 Completed successfully.\n 1 Apply was blocked or one or more task updates failed.\n 2 Invalid command-line arguments.";
9
12
  export declare function handleDb(args: string[]): Promise<void>;
@@ -1,125 +1,59 @@
1
- "use strict";
2
- /**
3
- * crewx db push handler.
4
- *
5
- * Usage:
6
- * crewx db push Preview changes → confirm → apply
7
- * crewx db push --force Apply without confirmation + reset migration history
8
- * crewx db push --dry-run Show preview only, no changes
9
- */
10
- var __importDefault = (this && this.__importDefault) || function (mod) {
11
- return (mod && mod.__esModule) ? mod : { "default": mod };
12
- };
13
- Object.defineProperty(exports, "__esModule", { value: true });
14
- exports.handleDb = handleDb;
15
- const path_1 = __importDefault(require("path"));
16
- const os_1 = __importDefault(require("os"));
17
- const readline_1 = __importDefault(require("readline"));
18
- const repository_1 = require("@crewx/sdk/repository");
19
- const repository_2 = require("@crewx/sdk/repository");
20
- function defaultDbPath() {
21
- return path_1.default.join(os_1.default.homedir(), '.crewx', 'crewx.db');
22
- }
23
- function formatPreview(result, dbPath) {
24
- const lines = [];
25
- lines.push(`[crewx] Database push — comparing schema vs ${dbPath}`);
26
- lines.push('');
27
- if (result.created.length > 0) {
28
- lines.push(` Tables to create:`);
29
- for (const t of result.created) {
30
- lines.push(` → ${t}`);
31
- }
32
- }
33
- else {
34
- lines.push(' Tables to create: (none)');
35
- }
36
- if (result.altered.length > 0) {
37
- lines.push(' Columns to add:');
38
- for (const { table, column } of result.altered) {
39
- lines.push(` → ${table}.${column}`);
40
- }
41
- }
42
- else {
43
- lines.push(' Columns to add: (none)');
44
- }
45
- if (result.warnings.length > 0) {
46
- lines.push(' Warnings:');
47
- for (const w of result.warnings) {
48
- lines.push(` ⚠ ${w}`);
49
- }
50
- }
51
- if (result.backupPath) {
52
- lines.push('');
53
- lines.push(` Backup: ${result.backupPath}`);
54
- }
55
- return lines.join('\n');
56
- }
57
- function hasChanges(result) {
58
- return result.created.length > 0 || result.altered.length > 0;
59
- }
60
- function prompt(question) {
61
- const rl = readline_1.default.createInterface({ input: process.stdin, output: process.stdout });
62
- return new Promise((resolve) => {
63
- rl.question(question, (answer) => {
64
- rl.close();
65
- resolve(answer);
66
- });
67
- });
68
- }
69
- async function handleDb(args) {
70
- const subcommand = args[0];
71
- if (!subcommand || subcommand === 'push') {
72
- await handleDbPush(args.slice(subcommand === 'push' ? 1 : 0));
73
- return;
74
- }
75
- console.error(`Unknown db subcommand: ${subcommand}`);
76
- console.error('Usage: crewx db push [--force] [--dry-run]');
77
- process.exit(1);
78
- }
79
- async function handleDbPush(args) {
80
- const force = args.includes('--force');
81
- const dryRun = args.includes('--dry-run');
82
- const dbPath = defaultDbPath();
83
- const handle = (0, repository_1.openDrizzleDb)(dbPath);
84
- try {
85
- // 1. Compute preview (dry-run pass — no changes yet)
86
- const preview = (0, repository_2.pushSchema)(handle.db, { force, dbPath, dryRun: true });
87
- console.log(formatPreview(preview, dbPath));
88
- console.log('');
89
- if (dryRun) {
90
- console.log('[crewx] Dry-run mode — no changes applied.');
91
- return;
92
- }
93
- if (!hasChanges(preview)) {
94
- console.log('[crewx] No changes needed. Database is up to date.');
95
- return;
96
- }
97
- // 2. Confirm unless --force
98
- if (!force) {
99
- const answer = await prompt('Apply changes? (y/N): ');
100
- if (answer.trim().toLowerCase() !== 'y') {
101
- console.log('[crewx] Aborted.');
102
- return;
103
- }
104
- }
105
- // 3. Apply
106
- const result = (0, repository_2.pushSchema)(handle.db, { force, dbPath });
107
- console.log('');
108
- console.log('[crewx] Push complete.');
109
- if (result.created.length > 0) {
110
- console.log(` Tables created: ${result.created.join(', ')}`);
111
- }
112
- if (result.altered.length > 0) {
113
- console.log(` Columns added: ${result.altered.map((a) => `${a.table}.${a.column}`).join(', ')}`);
114
- }
115
- if (result.backupPath) {
116
- console.log(` Backup: ${result.backupPath}`);
117
- }
118
- if (result.created.length === 0 && result.altered.length === 0) {
119
- console.log(' No changes applied.');
120
- }
121
- }
122
- finally {
123
- handle.close();
124
- }
125
- }
1
+ "use strict";var g=exports&&exports.__importDefault||function(e){return e&&e.__esModule?e:{"default":e}};Object.defineProperty(exports,"__esModule",{value:true});exports.USAGE_BACKFILL_HELP=exports.REQUEST_LOG_MIGRATION_HELP=exports.TASK_LOG_MIGRATION_HELP=void 0;exports.handleDb=C;const v=g(require("path"));const R=g(require("os"));const T=g(require("readline"));const x=require("./command-help");const _=require("@crewx/sdk/repository");const m=require("@crewx/sdk/repository");const E=require("@crewx/sdk/repository");const p=require("@crewx/sdk/repository");const S=require("@crewx/sdk/repository");exports.TASK_LOG_MIGRATION_HELP=`Usage:
2
+ crewx db migrate-task-logs --dry-run [--db PATH]
3
+ crewx db migrate-task-logs --apply [--db PATH] [--batch-tasks N]
4
+ crewx db migrate-task-logs --verify [--db PATH]
5
+
6
+ Modes:
7
+ --dry-run Read and validate legacy blobs without writing or creating a backup.
8
+ --apply Create a consistent SQLite backup, then migrate one task per transaction.
9
+ --verify Check source invariants, event sequences, counts, and orphan rows.
10
+
11
+ Apply policy:
12
+ Only blob tasks with status success, failed, or completed are migrated.
13
+ pending, running, paused, and unknown statuses are deferred for a later run.
14
+ There is no --force or --include-active option. Apply requires the estimated
15
+ database/event growth plus a 10 GiB free-space reserve.
16
+
17
+ Exit codes:
18
+ 0 Completed with no malformed rows or invariant failures.
19
+ 1 Safe tasks completed but a row/invariant failed, or apply was blocked.
20
+ 2 Invalid command-line arguments.
21
+
22
+ The command never runs automatically at server startup and never runs VACUUM.`;exports.REQUEST_LOG_MIGRATION_HELP=`Usage:
23
+ crewx db migrate-request-logs [--batch N] [--dry-run]
24
+
25
+ Moves the request log rows still stored in crewx.db into logs.db, the file next
26
+ to it. Each distinct request/response body is stored once in logs.db, keyed by
27
+ its SHA-256; a row points to its bodies by hash, so nothing is dropped.
28
+
29
+ Options:
30
+ --batch N Rows per batch (default 250; a batch is also capped at about 8 MB).
31
+ --dry-run Count rows and distinct bodies without writing anything (logs.db is not created).
32
+
33
+ Safe while crewx is running: each batch is committed to logs.db, verified there,
34
+ and only then deleted from crewx.db in one short transaction. Interrupt it and run
35
+ it again at any time. The database is chosen like everywhere else (CREWX_DB, else
36
+ ~/.crewx/crewx.db). No VACUUM and no DROP: crewx.db keeps its size until a later compaction.
37
+
38
+ Exit codes:
39
+ 0 Every row is in logs.db and none is left in crewx.db (or the dry run finished).
40
+ 1 Rows are still in crewx.db, or an error stopped the move (progress is kept).
41
+ 2 Invalid command-line arguments.`;exports.USAGE_BACKFILL_HELP=`Usage:
42
+ crewx db backfill-usage [--dry-run|--apply|--verify] [--db PATH] [--backup PATH]
43
+ crewx db backfill-usage --restore SNAPSHOT [--db PATH]
44
+
45
+ Modes:
46
+ --dry-run Show provider/reason recovery plans without changing the database (default).
47
+ --apply Create a row-level undo snapshot, then account one task per transaction.
48
+ --verify Recheck remaining targets and usageAccounting markers without changing the database.
49
+ --restore Restore rows from SNAPSHOT when their current values still match the snapshot after-state.
50
+
51
+ Apply policy:
52
+ Only success, failed, and completed tasks with zero recorded usage are considered.
53
+ Workflow/MCP anchors and plugin/mock rows are excluded. Rows completed within 24 hours
54
+ are not marked unavailable when their logs do not contain usage.
55
+
56
+ Exit codes:
57
+ 0 Completed successfully.
58
+ 1 Apply was blocked or one or more task updates failed.
59
+ 2 Invalid command-line arguments.`;function A(){return v.default.join(R.default.homedir(),".crewx","crewx.db")}function L(e,o){const s=[];s.push(`[crewx] Database push \u2014 comparing schema vs ${o}`);s.push("");if(e.created.length>0){s.push(` Tables to create:`);for(const n of e.created){s.push(` \u2192 ${n}`)}}else{s.push(" Tables to create: (none)")}if(e.altered.length>0){s.push(" Columns to add:");for(const{table:n,column:r}of e.altered){s.push(` \u2192 ${n}.${r}`)}}else{s.push(" Columns to add: (none)")}if(e.warnings.length>0){s.push(" Warnings:");for(const n of e.warnings){s.push(` \u26A0 ${n}`)}}if(e.backupPath){s.push("");s.push(` Backup: ${e.backupPath}`)}return s.join("\n")}function P(e){return e.created.length>0||e.altered.length>0}function y(e){const o=Object.entries(e??{});return o.length>0?o.map(([s,n])=>`${s}=${n}`).join(", "):"(none)"}function M(e){const o=T.default.createInterface({input:process.stdin,output:process.stdout});return new Promise(s=>{o.question(e,n=>{o.close();s(n)})})}function k(){console.log("Usage: crewx db push [--force] [--dry-run]");console.log(exports.TASK_LOG_MIGRATION_HELP);console.log(exports.REQUEST_LOG_MIGRATION_HELP)}async function C(e){const o=e[0];if(o==="migrate-task-logs"){await q(e.slice(1));return}if(o==="migrate-request-logs"){await D(e.slice(1));return}if(o==="backfill-usage"){await F(e.slice(1));return}if(o==="--help"||o==="-h"){k();return}if(!o||o==="push"){const s=e.slice(o==="push"?1:0);if((0,x.isHelpRequest)(s)){k();return}await W(s);return}console.error(`Unknown db subcommand: ${o}`);console.error("Usage: crewx db push [--force] [--dry-run]");console.error(exports.TASK_LOG_MIGRATION_HELP);process.exitCode=2}class d extends Error{}class u extends Error{}function B(e){let o;let s;let n;const r=a=>{if(o)throw new d("Choose exactly one of --dry-run, --apply, or --verify.");o=a};const t=(a,c,l)=>{const i=a[c+1];if(!i||i.startsWith("--"))throw new d(`${l} requires a value.`);return i};for(let a=0;a<e.length;a+=1){const c=e[a];if(c==="--help"||c==="-h"){throw new d(exports.TASK_LOG_MIGRATION_HELP)}if(c==="--dry-run"){r("dry-run");continue}if(c==="--apply"){r("apply");continue}if(c==="--verify"){r("verify");continue}if(c==="--db"){s=t(e,a,"--db");a+=1;continue}if(c.startsWith("--db=")){s=c.slice("--db=".length);if(!s)throw new d("--db requires a value.");continue}if(c==="--batch-tasks"){const l=t(e,a,"--batch-tasks");const i=Number(l);if(!Number.isSafeInteger(i)||i<1){throw new d("--batch-tasks must be a positive integer.")}n=i;a+=1;continue}if(c.startsWith("--batch-tasks=")){const l=c.slice("--batch-tasks=".length);const i=Number(l);if(!Number.isSafeInteger(i)||i<1){throw new d("--batch-tasks must be a positive integer.")}n=i;continue}throw new d(`Unknown option: ${c}`)}if(!o)throw new d("Choose one of --dry-run, --apply, or --verify.");if(n!==void 0&&o!=="apply"){throw new d("--batch-tasks is only valid with --apply.")}return{mode:o,dbPath:s,batchTasks:n}}function I(e){const o=e.mode==="dry-run"?"Dry-run":e.mode==="apply"?"Apply":"Verify";const s=[`[crewx] Task-log migration \u2014 ${o}`,` Database: ${e.dbPath}`,` Tasks scanned: ${e.taskCount}`,` Blob candidates: ${e.candidateTaskCount}`,` Eligible terminal blobs: ${e.eligibleTaskCount}`,` Status counts: ${y(e.statusCounts)}`,` Deferred blob tasks: ${e.deferredTaskCount}`,` Deferred statuses: ${y(e.deferredStatusCounts)}`,` Entries: ${e.entryCount}`,` Source bytes: ${e.sourceBytes}`,` Estimated free-space need: ${e.estimatedFreeSpaceBytes}`,` Required free space (with reserve): ${e.requiredFreeSpaceBytes}`,` Available free space: ${e.availableFreeSpaceBytes}`,` Free-space gate: ${e.freeSpaceGatePassed?"PASS":"FAIL"}`,` Migrated: ${e.migratedTasks} task(s), ${e.migratedEntries} entr${e.migratedEntries===1?"y":"ies"}`,` Skipped event-source tasks: ${e.skippedTasks}`,` Failed tasks: ${e.failedTasks}`,` Logical source bytes removed: ${e.logicalSourceBytesRemoved}`];if(e.remainingTaskCount!==void 0)s.push(` Remaining blob tasks: ${e.remainingTaskCount}`);if(e.backupPath){s.push(` Backup: ${e.backupPath}`);if(e.backupMethod)s.push(` Backup method: ${e.backupMethod}`)}if(e.verification){s.push(` Event rows checked: ${e.verification.eventCount}`);s.push(` Verification issues: ${e.verification.issues.length}`)}if(e.blockedReason)s.push(` Blocked: ${e.blockedReason}`);for(const n of e.warnings??[])s.push(` Warning: ${n}`);return s.join("\n")}async function q(e){let o;try{o=B(e)}catch(s){const n=s instanceof Error?s.message:String(s);if(n===exports.TASK_LOG_MIGRATION_HELP){console.log(n)}else{console.error(n);console.error(exports.TASK_LOG_MIGRATION_HELP);process.exitCode=2}return}try{const s=await(0,E.runTaskLogMigration)(o);console.log(I(s));if(!s.ok){if(s.blockedReason)console.error(s.blockedReason);const n=s.failures??s.malformedRows??[];for(const r of n){console.error(` ${r.taskId}: ${r.reason}`)}process.exitCode=1}else{process.exitCode=0}}catch(s){console.error(s instanceof Error?s.message:String(s));process.exitCode=1}}class b extends Error{}function O(e){let o;let s=false;const n=r=>{const t=Number(r);if(!r||!Number.isSafeInteger(t)||t<1){throw new b("--batch must be a positive integer.")}return t};for(let r=0;r<e.length;r+=1){const t=e[r];if(t==="--help"||t==="-h")throw new b(exports.REQUEST_LOG_MIGRATION_HELP);if(t==="--dry-run"){s=true;continue}if(t==="--batch"){o=n(e[r+1]);r+=1;continue}if(t.startsWith("--batch=")){o=n(t.slice("--batch=".length));continue}throw new b(`Unknown option: ${t}`)}return{batchRows:o,dryRun:s}}function h(e){if(e<1024)return`${e} B`;const o=["KiB","MiB","GiB","TiB"];let s=e;let n=-1;while(s>=1024&&n<o.length-1){s/=1024;n+=1}return`${s.toFixed(s>=100?0:1)} ${o[n]} (${e} bytes)`}function $(e,o){const s=[...e].sort((n,r)=>n-r);return s[Math.min(s.length-1,Math.floor(o/100*s.length))]}function w(e){return`${(e/1e3).toFixed(1)}s`}const G=1e4;function U(e,o){if(e.dryRun){const s=e.scan;console.log("[crewx] Dry run finished \u2014 nothing was written.");console.log(` Rows scanned: ${s?.rows??0}`);console.log(` Bodies: ${s?.bodies??0} (${h(s?.bodyBytes??0)})`);console.log(` Distinct bodies: ${s?.distinctBodies??0} (${h(s?.distinctBodyBytes??0)}) \u2014 what logs.db would store`);console.log(` Elapsed: ${w(e.elapsedMs)}`);return}console.log("[crewx] Request-log move finished.");console.log(` Moved rows: ${e.movedRows}`);console.log(` Remaining rows in crewx.db: ${o.crewxRows}`);console.log(` logs.db request_logs: ${o.logsRows??0}`);console.log(` logs.db request_log_bodies: ${o.logsBodies??0}`);console.log(` logs.db size: ${h(o.logsFileBytes)} (+ wal ${h(o.logsWalBytes)})`);console.log(` crewx.db freelist pages: ${o.crewxFreelistPages}`);console.log(` Batches: ${e.batches}, bodies added: ${e.bodiesAdded}`);if(e.deleteTxMs.length>0){console.log(` crewx.db delete transaction per batch: p50 ${$(e.deleteTxMs,50).toFixed(1)} ms, p90 ${$(e.deleteTxMs,90).toFixed(1)} ms, max ${e.maxDeleteTxMs.toFixed(1)} ms`);console.log(` Largest crewx.db -wal seen after a batch: ${h(e.maxWalBytes)}`)}console.log(` Elapsed: ${w(e.elapsedMs)}`);if(o.crewxRows>0){console.log(` ${o.crewxRows} row(s) are still in crewx.db (new rows arrived or the run stopped early). Run it again.`)}}async function D(e){let o;try{o=O(e)}catch(s){const n=s instanceof Error?s.message:String(s);if(n===exports.REQUEST_LOG_MIGRATION_HELP){console.log(n)}else{console.error(n);console.error(exports.REQUEST_LOG_MIGRATION_HELP);process.exitCode=2}return}try{const s=(0,p.inspectRequestLogsMove)();console.log(`[crewx] Request logs \u2192 logs.db${o.dryRun?" (dry run)":""}`);console.log(` crewx.db: ${s.crewxDbPath}`);console.log(` logs.db: ${s.logsDbPath}`);console.log(` Rows to move: ${s.crewxRows}`);let n=Date.now();const r=a=>{const c=Date.now();if(c-n<G)return;n=c;const l=o.dryRun?a.scannedRows:a.movedRows;const i=Math.max(0,s.crewxRows-l);console.log(` ${o.dryRun?"scanned":"moved"} ${l} | remaining ~${i} | elapsed ${w(a.elapsedMs)}`)};const t=(0,p.moveRequestLogsToLogsDb)({batchRows:o.batchRows,dryRun:o.dryRun,onProgress:r});U(t,(0,p.inspectRequestLogsMove)());process.exitCode=o.dryRun||t.remainingRows===0?0:1}catch(s){console.error(s instanceof Error?s.message:String(s));process.exitCode=1}}function H(e){let o;let s;let n;let r;const t=l=>{if(o)throw new u("Choose exactly one of --dry-run, --apply, --verify, or --restore.");o=l};const a=(l,i)=>{const f=e[l+1];if(!f||f.startsWith("--"))throw new u(`${i} requires a value.`);return f};for(let l=0;l<e.length;l+=1){const i=e[l];if(i==="--help"||i==="-h")throw new u(exports.USAGE_BACKFILL_HELP);if(i==="--dry-run"){t("dry-run");continue}if(i==="--apply"){t("apply");continue}if(i==="--verify"){t("verify");continue}if(i==="--restore"){t("restore");r=a(l,"--restore");l+=1;continue}if(i.startsWith("--restore=")){t("restore");r=i.slice("--restore=".length);if(!r)throw new u("--restore requires a value.");continue}if(i==="--db"){s=a(l,"--db");l+=1;continue}if(i.startsWith("--db=")){s=i.slice("--db=".length);if(!s)throw new u("--db requires a value.");continue}if(i==="--backup"){n=a(l,"--backup");l+=1;continue}if(i.startsWith("--backup=")){n=i.slice("--backup=".length);if(!n)throw new u("--backup requires a value.");continue}throw new u(`Unknown option: ${i}`)}const c=o??"dry-run";if(n&&c!=="apply"){throw new u("--backup is only valid with --apply.")}if(r&&c!=="restore"){throw new u("--restore is only valid with restore mode.")}return{mode:c,dbPath:s,backupPath:n,restorePath:r}}function N(e){const o=e.mode==="dry-run"?"Dry-run":e.mode==="apply"?"Apply":e.mode==="restore"?"Restore":"Verify";const s=[`[crewx] Usage backfill \u2014 ${o}`,` Database: ${e.dbPath}`,` Tasks scanned: ${e.scannedTasks}`,` Terminal tasks: ${e.terminalTasks}`,` Raw target tasks: ${e.rawTargetTasks}`,` Candidate tasks: ${e.candidateTasks}`,` Recovered: ${e.recoveredTasks}`,` Unavailable: ${e.unavailableTasks}`,` Deferred (within 24h): ${e.deferredTasks}`,` Changed: ${e.changedTasks}`,` Would change: ${e.wouldChangeTasks}`,` Restored: ${e.restored}`,` Skipped conflicts: ${e.skippedConflict}`,` Remaining target tasks: ${e.remainingTargetTasks}`,` Tasks with usageAccounting: ${e.accountingTasks}`," Provider distribution:"];const n=Object.entries(e.providerDistribution);if(n.length===0){s.push(" (none)")}else{for(const[t,a]of n){s.push(` ${t}: candidates=${a.candidates}, recovered=${a.recovered}, unavailable=${a.unavailable}, deferred=${a.deferred}`)}}s.push(" Reason counts:");for(const[t,a]of Object.entries(e.reasonCounts))s.push(` ${t}: ${a}`);s.push(` Estimated free-space need: ${e.estimatedFreeSpaceBytes}`);s.push(` Required free space (with reserve): ${e.requiredFreeSpaceBytes}`);s.push(` Available free space: ${e.availableFreeSpaceBytes}`);s.push(` Free-space gate: ${e.freeSpaceGatePassed?"PASS":"FAIL"}`);const r=e.snapshotPath??e.backupPath;if(r){s.push(` Undo snapshot: ${r}`);if(e.backupMethod)s.push(` Snapshot method: ${e.backupMethod}`)}if(e.blockedReason)s.push(` Blocked: ${e.blockedReason}`);for(const t of e.conflictSamples){s.push(` Conflict sample: ${t.taskId}: ${t.fields.join(", ")}`)}for(const t of e.failures)s.push(` Failure: ${t.taskId}: ${t.reason}`);for(const t of e.warnings)s.push(` Warning: ${t}`);return s.join("\n")}async function F(e){let o;try{o=H(e)}catch(s){const n=s instanceof Error?s.message:String(s);if(n===exports.USAGE_BACKFILL_HELP){console.log(n)}else{console.error(n);console.error(exports.USAGE_BACKFILL_HELP);process.exitCode=2}return}try{const s=await(0,S.runUsageBackfill)(o);console.log(N(s));process.exitCode=s.ok?0:1}catch(s){console.error(s instanceof Error?s.message:String(s));process.exitCode=1}}async function W(e){const o=e.includes("--force");const s=e.includes("--dry-run");const n=A();const r=(0,_.openDrizzleDb)(n);try{const t=(0,m.pushSchema)(r.db,{force:o,dbPath:n,dryRun:true});console.log(L(t,n));console.log("");if(s){console.log("[crewx] Dry-run mode \u2014 no changes applied.");return}if(!P(t)){console.log("[crewx] No changes needed. Database is up to date.");return}if(!o){const c=await M("Apply changes? (y/N): ");if(c.trim().toLowerCase()!=="y"){console.log("[crewx] Aborted.");return}}const a=(0,m.pushSchema)(r.db,{force:o,dbPath:n});console.log("");console.log("[crewx] Push complete.");if(a.created.length>0){console.log(` Tables created: ${a.created.join(", ")}`)}if(a.altered.length>0){console.log(` Columns added: ${a.altered.map(c=>`${c.table}.${c.column}`).join(", ")}`)}if(a.backupPath){console.log(` Backup: ${a.backupPath}`)}if(a.created.length===0&&a.altered.length===0){console.log(" No changes applied.")}}finally{r.close()}}
@@ -0,0 +1,121 @@
1
+ /**
2
+ * Shared receipt-mode implementation for the query and execute commands.
3
+ *
4
+ * A receipt is persisted before a detached runner is started. The runner gets
5
+ * its own identity variables, while the trace variables remain the caller's
6
+ * trace context and are never repurposed as the runner assignment.
7
+ */
8
+ import { TaskRepository } from '@crewx/sdk/repository';
9
+ import type { DurableTaskAdmission, TaskActor } from '@crewx/sdk';
10
+ export type ReceiptActorKind = 'human' | 'agent' | 'system' | 'unknown';
11
+ export interface ReceiptActor {
12
+ kind: ReceiptActorKind;
13
+ id: string | null;
14
+ }
15
+ /** Resolve the CLI actor from metadata and the caller's current environment. */
16
+ export declare function resolveCliTaskActor(metadata: Record<string, unknown>, agentId?: string | undefined): TaskActor;
17
+ /**
18
+ * Resolve the actor at the receipt boundary while the caller's environment is
19
+ * still available. The receipt and synchronous paths share one predicate so
20
+ * cron runners cannot diverge after root context is stripped.
21
+ */
22
+ export declare function resolveReceiptActor(metadata: Record<string, unknown>, agentId?: string | undefined): ReceiptActor;
23
+ /**
24
+ * Report a blocked direct admission (WI-CTO-20260919-004 R2 finding #1) to
25
+ * the operator. Never called for an adopted (already pending) receipt — see
26
+ * admitDurableTask()'s own doc comment.
27
+ */
28
+ export declare function reportAdmissionBlocked(admission: Extract<DurableTaskAdmission, {
29
+ ok: false;
30
+ }>): void;
31
+ /**
32
+ * Remove receipt-selection flags, respecting the `--` literal-args sentinel.
33
+ */
34
+ export declare function extractReceiptFlags(args: string[]): {
35
+ detach: boolean;
36
+ wait: boolean;
37
+ rest: string[];
38
+ };
39
+ export type ReceiptModeReason = 'explicit-detach' | 'agent-context' | 'detached-runner' | 'wait' | 'default';
40
+ export interface ReceiptModeDecision {
41
+ receipt: boolean;
42
+ reason: ReceiptModeReason;
43
+ }
44
+ /** Resolve the receipt/synchronous mode contract shared by q and x. */
45
+ export declare function resolveReceiptMode(options: {
46
+ detach: boolean;
47
+ wait: boolean;
48
+ detachedRunner: boolean;
49
+ agentContext: boolean;
50
+ }): ReceiptModeDecision;
51
+ /**
52
+ * Rebuild runner argv from the parsed request. The resolved prompt is passed
53
+ * as one argv value after `--`, so stdin is never needed by the detached
54
+ * child and prompt text beginning with a dash remains positional text.
55
+ */
56
+ export declare function buildDetachedRunnerArgs(filteredArgs: string[], agentRef: string, finalMessage: string): string[];
57
+ export type AssignedTaskAdoption = {
58
+ kind: 'adopted';
59
+ taskId: string;
60
+ } | {
61
+ kind: 'stale';
62
+ } | {
63
+ kind: 'failed';
64
+ };
65
+ /**
66
+ * Claim a pre-issued receipt without overwriting an already-owned row.
67
+ * Assignment-only leakage is recoverable: discard the stale id and let the
68
+ * normal SDK path create a fresh task. A real detached runner must fail loud
69
+ * because its receipt would otherwise point at no execution row.
70
+ */
71
+ export declare function adoptAssignedTask(taskRepo: Pick<TaskRepository, 'adoptPendingTask'>, taskId: string, detachedRunner: boolean): AssignedTaskAdoption;
72
+ /** Read the actor persisted on the receipt after the runner adopts it. */
73
+ export declare function readAssignedTaskActor(taskRepo: Pick<TaskRepository, 'getTask'>, taskId: string): TaskActor;
74
+ export interface RecordedTaskProviderAccountBinding {
75
+ provider?: string;
76
+ providerAccountId?: string;
77
+ providerAccountLabel?: string;
78
+ providerRuntime?: string;
79
+ providerRuntimeVersion?: string;
80
+ providerAccountAuthEpoch?: string;
81
+ }
82
+ /** Preserve SDK replay intent for recorded ACP pins, including provider drift. */
83
+ export declare function shouldReplayRecordedAntigravityAcp(binding: RecordedTaskProviderAccountBinding): boolean;
84
+ /** Build SDK option fields only from runtime pins explicitly recorded on a task. */
85
+ export declare function buildRecordedProviderAccountOptions(binding: RecordedTaskProviderAccountBinding | undefined): Record<string, string>;
86
+ /** Parse only provider pins explicitly recorded on a task. */
87
+ export declare function readTaskProviderAccountBinding(metadata: unknown): RecordedTaskProviderAccountBinding;
88
+ /**
89
+ * Read the provider/account/runtime binding from the adopted task row. All
90
+ * values come from task metadata, never from process.env or a conversation id.
91
+ */
92
+ export declare function readAssignedTaskProviderAccountBinding(taskRepo: Pick<TaskRepository, 'getTask'>, taskId: string): RecordedTaskProviderAccountBinding;
93
+ /**
94
+ * Merge authoritative recorded pins into SDK metadata. Caller-supplied pin
95
+ * fields are discarded so they cannot change the adopted task's account.
96
+ */
97
+ export declare function mergeAssignedTaskProviderAccountMetadata(metadata: Record<string, unknown>, binding: RecordedTaskProviderAccountBinding): Record<string, unknown>;
98
+ /** Backward-compatible accessor for callers that only need the account id. */
99
+ export declare function readAssignedTaskProviderAccountId(taskRepo: Pick<TaskRepository, 'getTask'>, taskId: string): string | undefined;
100
+ export interface DetachedMiddleHop {
101
+ taskId: string;
102
+ logPath: string;
103
+ runnerArgs: string[];
104
+ }
105
+ /**
106
+ * Read the private Windows middle-hop contract. Invalid direct invocations
107
+ * are left untouched and therefore fail through the normal unknown-option
108
+ * path instead of becoming an undocumented public command.
109
+ */
110
+ export declare function readDetachedMiddleHop(args: string[]): DetachedMiddleHop | undefined;
111
+ /**
112
+ * Windows middle hop: transfer a transient log handle to the final runner,
113
+ * close the middle process's copy, and exit immediately. The parent treats a
114
+ * successful middle-hop exit as normal and makes adoption a database decision.
115
+ */
116
+ export declare function runDetachedMiddle(command: string, hop: DetachedMiddleHop): Promise<void>;
117
+ /**
118
+ * Persist a receipt and launch its detached runner. Unix uses one hop. Windows
119
+ * uses a short-lived middle hop so the final runner has no live parent link.
120
+ */
121
+ export declare function runDetached(command: string, filteredArgs: string[], reason: ReceiptModeReason, invocationArgs?: string[]): Promise<void>;
@@ -0,0 +1,15 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.resolveCliTaskActor=b;exports.resolveReceiptActor=B;exports.reportAdmissionBlocked=X;exports.extractReceiptFlags=Ae;exports.resolveReceiptMode=me;exports.buildDetachedRunnerArgs=z;exports.adoptAssignedTask=we;exports.readAssignedTaskActor=Te;exports.shouldReplayRecordedAntigravityAcp=ee;exports.buildRecordedProviderAccountOptions=Re;exports.readTaskProviderAccountBinding=re;exports.readAssignedTaskProviderAccountBinding=te;exports.mergeAssignedTaskProviderAccountMetadata=ye;exports.readAssignedTaskProviderAccountId=Ie;exports.readDetachedMiddleHop=De;exports.runDetachedMiddle=$e;exports.runDetached=Ne;const P=require("child_process");const p=require("fs");const E=require("path");const se=require("os");const y=require("@crewx/sdk");const ce=require("@crewx/sdk/node");const de=require("@crewx/sdk/repository");const ae=require("./parse-agent-message");const j=require("./parse-common-flags");const ue=require("./resolve-recipient");const pe=require("./resolve-prompt");const le=require("../utils/version");const G=require("../utils/inherited-trace");const U=require("./cal");const fe=require("./emit-trailer");function F(r){return typeof r==="string"&&r.trim().length>0?r.trim():void 0}function b(r,e=process.env["CREWX_AGENT_ID"]){const t=F(r.schedule_id);if(t)return{actorKind:"system",actorId:`cron:${t}`};const n=r.workflow;const o=n!==null&&typeof n==="object"&&!Array.isArray(n)?n:void 0;const i=F(o?.exec_id);if(i)return{actorKind:"system",actorId:`workflow:${i}`};const s=F(e);if(s)return{actorKind:"agent",actorId:s};if(process.stdin.isTTY===true||process.stderr.isTTY===true){return{actorKind:"human",actorId:(0,ce.getLocalActorId)()}}return{actorKind:"unknown",actorId:null}}function B(r,e=process.env["CREWX_AGENT_ID"]){const t=b(r,e);return{kind:t.actorKind,id:t.actorId}}function X(r){process.stderr.write(`${r.message}
2
+ `)}const _e=200;const J=3e4;const ve=["--to","--thread","--provider","--model","--metadata","--config","-c","--output-format","--effort","--prompt-file","-f","--out","-o"];const Y="--__crewx-detached-middle";const C="--__crewx-detached-task";const L="--__crewx-detached-log";const M="--__crewx-detached-token";const O="CREWX_DETACHED_HOP_TOKEN";function he(r){return ve.some(e=>r===e||r.startsWith(`${e}=`))}function ge(r){return r==="--prompt-file"||r==="-f"||r.startsWith("--prompt-file=")||r.startsWith("-f=")}function Ae(r){const e=[];let t=false;let n=false;let o=false;for(const i of r){if(!o&&i==="--"){o=true;e.push(i);continue}if(!o&&(i==="--detach"||i==="--async")){t=true;continue}if(!o&&(i==="--wait"||i.startsWith("--wait="))){n=true;continue}e.push(i)}return{detach:t,wait:n,rest:e}}function me(r){if(r.wait)return{receipt:false,reason:"wait"};if(r.detachedRunner)return{receipt:false,reason:"detached-runner"};if(r.detach)return{receipt:true,reason:"explicit-detach"};if(r.agentContext)return{receipt:true,reason:"agent-context"};return{receipt:false,reason:"default"}}function v(r){return r instanceof Error?r.message:String(r)}function ke(r,e,t,n={}){return new Promise((o,i)=>{let s=false;let c;let h;const k=()=>{if(c!==void 0)clearInterval(c);if(h!==void 0)clearTimeout(h)};const w=d=>{if(s)return;s=true;k();o(d)};const g=(d,_=false)=>{try{const l=r.getTask(e);if(l&&l.status!=="pending"){w({kind:"adopted"});return}if(d!==void 0){w({kind:"exited",reason:d});return}if(_)w({kind:"timeout"})}catch(l){if(s)return;s=true;k();i(l)}};t.on("error",d=>{g(`Runner failed before adopting task: ${v(d)}`)});t.on("exit",(d,_)=>{if(n.ignoreSuccessfulExit&&d===0&&_===null)return;const l=_?`signal ${_}`:`exit ${d??"unknown"}`;g(`Runner exited before adopting task (${l})`)});c=setInterval(()=>g(),_e);h=setTimeout(()=>g(void 0,true),J);g()})}function q(r,e,t){try{const n=r.failPendingTask(e,t);if(n){process.stderr.write(`Detached task ${e} failed: ${t}
3
+ `);return false}const o=r.getTask(e);if(o&&o.status!=="pending")return true}catch(n){t+=`; could not persist failure: ${v(n)}`}process.stderr.write(`Detached task ${e} failed: ${t}
4
+ `);return false}function I(r,e,t,n,o,i,s){let c="pending";try{const k=r.getTask(e);c=k?.status==="pending"?"pending":"running"}catch{}if(i==="json"){process.stdout.write(`${JSON.stringify({taskId:e,status:c,mode:"receipt",logPath:t})}
5
+ `);return}if(o)process.stderr.write(`mode=receipt reason=${n}
6
+ `);process.stdout.write(`${e}
7
+ `);process.stderr.write(`Task ${e} accepted. This ID is the handle (not a PID).
8
+ `);if(s&&o)process.stderr.write(`${s}
9
+ `);const h=(0,U.suggestWaitSeconds)({startedAt:null});(0,U.writeCalFooter)({commandId:"crewx.receipt",params:{taskId:e,wait:String(h)}})}function z(r,e,t){const n=[];for(let o=0;o<r.length;o+=1){const i=r[o];if(i==="--")break;if(i==="--verbose"||i==="--overdrive"){n.push(i);continue}if(i==="--var"){const s=r[o+1];if(s!==void 0){n.push(i,s);o+=1}continue}if(i.startsWith("--var=")){n.push(i);continue}if(i==="--to"){o+=1;continue}if(i.startsWith("--to="))continue;if(!he(i))continue;if(ge(i)){if(!i.includes("="))o+=1;continue}n.push(i);if(!i.includes("=")){const s=r[o+1];if(s!==void 0){n.push(s);o+=1}}}return[...n,...e?[e]:[],"--",t]}function Q(r){if(r==="execute")return"x";if(r==="query")return"q";return r}function Z(r){const e={...process.env};delete e[O];if(process.versions.electron){e.ELECTRON_RUN_AS_NODE="1"}e.CREWX_DETACHED_RUNNER="1";e.CREWX_ASSIGNED_TASK_ID=r;return e}function we(r,e,t){if(r.adoptPendingTask(e)){return{kind:"adopted",taskId:e}}const n=`stale assigned id ${e}: expected pending task with pid NULL`;if(t){process.stderr.write(`Detached runner failed to adopt task ${e}: ${n}
10
+ `);return{kind:"failed"}}process.stderr.write(`${n}
11
+ `);return{kind:"stale"}}function Te(r,e){const t=r.getTask(e);const n=t?.actor_kind;if(n===null||n===void 0){return{actorKind:"unknown",actorId:null}}if(n==="human"||n==="agent"||n==="system"||n==="unknown"){return{actorKind:n,actorId:t?.actor_id??null}}return{actorKind:"unknown",actorId:t?.actor_id??null}}function ee(r){if(r.providerRuntime==="acp"||r.providerRuntimeVersion!==void 0||r.providerAccountAuthEpoch!==void 0)return true;return r.provider==="cli/antigravity"&&r.providerAccountId!==void 0&&r.providerAccountId!=="default"}function Re(r){const e={};if(r?.providerAccountId!==void 0)e.providerAccountId=r.providerAccountId;if(r?.providerRuntime!==void 0)e.providerAccountRuntime=r.providerRuntime;if(r?.providerRuntimeVersion!==void 0)e.providerAccountRuntimeVersion=r.providerRuntimeVersion;if(r?.providerAccountAuthEpoch!==void 0)e.providerAccountAuthEpoch=r.providerAccountAuthEpoch;return e}const Ee=["provider_account_id","provider_runtime","provider_runtime_version","provider_account_auth_epoch"];function re(r){if(typeof r!=="object"||r===null||Array.isArray(r))return{};const e=r;const t={};if(typeof e.provider==="string"&&e.provider.trim().length>0){t.provider=e.provider}if(typeof e.provider_account_id==="string"&&e.provider_account_id.trim().length>0){t.providerAccountId=e.provider_account_id.trim()}if(typeof e.provider_account_label==="string"&&e.provider_account_label.length>0){t.providerAccountLabel=e.provider_account_label}if(typeof e.provider_runtime==="string"&&e.provider_runtime.trim().length>0){t.providerRuntime=e.provider_runtime}if(typeof e.provider_runtime_version==="string"&&e.provider_runtime_version.trim().length>0){t.providerRuntimeVersion=e.provider_runtime_version}if(typeof e.provider_account_auth_epoch==="string"&&e.provider_account_auth_epoch.trim().length>0){t.providerAccountAuthEpoch=e.provider_account_auth_epoch}return t}function te(r,e){const t=r.getTask(e)?.metadata;if(!t)return{};try{return re(JSON.parse(t))}catch{return{}}}function ye(r,e){const t={...r};for(const n of Ee)delete t[n];if(e.provider!==void 0)t.provider=e.provider;if(e.providerAccountId!==void 0)t.provider_account_id=e.providerAccountId;if(ee(e)){delete t.provider_account_label;if(e.providerAccountLabel!==void 0)t.provider_account_label=e.providerAccountLabel}if(e.providerRuntime!==void 0)t.provider_runtime=e.providerRuntime;if(e.providerRuntimeVersion!==void 0)t.provider_runtime_version=e.providerRuntimeVersion;if(e.providerAccountAuthEpoch!==void 0)t.provider_account_auth_epoch=e.providerAccountAuthEpoch;return t}function Ie(r,e){return te(r,e).providerAccountId}function xe(r){const e={...process.env};if(process.versions.electron){e.ELECTRON_RUN_AS_NODE="1"}e[O]=r;return e}function De(r){let e=false;let t;let n;let o;let i=false;const s=[];for(const c of r){if(!i&&c==="--"){i=true;s.push(c);continue}if(!i&&c===Y){e=true;continue}if(!i&&c.startsWith(`${C}=`)){t=c.slice(`${C}=`.length);continue}if(!i&&c.startsWith(`${L}=`)){n=c.slice(`${L}=`.length);continue}if(!i&&c.startsWith(`${M}=`)){o=c.slice(`${M}=`.length);continue}s.push(c)}if(!e||!t||!n||!o||o!==process.env[O]){return void 0}return{taskId:t,logPath:n,runnerArgs:s}}async function $e(r,e){let t;try{const n=(0,E.dirname)(e.logPath);if(!(0,p.existsSync)(n))(0,p.mkdirSync)(n,{recursive:true});t=(0,p.openSync)(e.logPath,"a");const o=process.argv[1];const i=(0,P.spawn)(process.execPath,[o,Q(r),...e.runnerArgs],{detached:true,windowsHide:true,stdio:["ignore",t,t],env:Z(e.taskId)});(0,p.closeSync)(t);t=void 0;i.unref()}catch(n){if(t!==void 0)(0,p.closeSync)(t);process.stderr.write(`Runner failed before adopting task: ${v(n)}
12
+ `);process.exit(1);return}process.exit(0)}async function Ne(r,e,t,n=e){const o=(0,j.parseCommonFlags)(e);const{thread:i,metadata:s,promptFile:c,rest:h,to:k}=o;const{agentRef:w,message:g}=(0,ae.parseAgentMessage)(h);const d=await(0,pe.resolvePrompt)(g,c);let _;try{({agentRef:_}=(0,ue.resolveRecipient)({positionalRef:w,toFlag:k,agentContext:Boolean(process.env["CREWX_AGENT_ID"]),bodyForHint:d,command:r,invocationArgs:n}))}catch(u){const R=v(u);process.stderr.write(`Error: ${R}
13
+ `);(0,fe.emitDelegationResult)({command:r,trace:(0,G.readInheritedTrace)(),isError:true});process.exit(2);return}if(!d){console.error("Usage: crewx q|x --to <agent> <message> [options]");console.error(" @agent is a positional shorthand for selecting a recipient.");console.error(" Task body can also be supplied via stdin pipe or --prompt-file.");process.exit(1);return}let l;try{l=(0,j.parseMetadata)(s)}catch(u){process.stderr.write(`Error: ${v(u)}
14
+ `);process.exit(2);return}const T=(0,y.admitDurableTask)(`direct-cli:${r}`);if(!T.ok){X(T);process.exit(1);return}const a=T.taskId;const ne=new Date().toISOString();const x=process.cwd();const oe=(0,p.existsSync)((0,E.join)(x,"crewx.yaml"))||(0,p.existsSync)((0,E.join)(x,"crewx.yml"));const N=(0,G.readInheritedTrace)();const ie=N?.rootTraceId||a;const f=new de.TaskRepository;const W=B(l);try{f.startTask({id:a,agentId:_.replace(/^@/,""),actorKind:W.kind,actorId:W.id,prompt:d,mode:r==="q"||r==="query"?"query":"execute",status:"pending",startedAt:ne,pid:null,parentTaskId:N?.parentTaskId??null,callerAgentId:N?.callerAgentId??null,traceId:ie,command:process.argv.join(" "),metadata:Object.keys(l).length>0?JSON.stringify(l):null,workspaceId:oe?(0,y.hashWorkspaceId)((0,y.resolveWorkspaceOwnerPath)(x)):null,cwd:(0,y.normalizeWorkspacePath)(x),projectId:null,platform:"cli",crewxVersion:le.CLI_VERSION,threadId:i??null})}catch(u){T.release();process.stderr.write(`Failed to create detached task receipt: ${v(u)}
15
+ `);process.exit(1);return}T.release();const K=z(e,_,d);const H=Q(r);const S=(0,E.join)((0,se.homedir)(),".crewx","logs");const A=(0,E.join)(S,`${a}.log`);let m;let D;let V=false;try{if(!(0,p.existsSync)(S))(0,p.mkdirSync)(S,{recursive:true});if(process.platform==="win32"){V=true;const u=(0,y.generateId)("req");D=(0,P.spawn)(process.execPath,[process.argv[1],H,Y,`${C}=${a}`,`${L}=${A}`,`${M}=${u}`,...K],{detached:true,windowsHide:true,stdio:"ignore",env:xe(u)})}else{m=(0,p.openSync)(A,"a");D=(0,P.spawn)(process.execPath,[process.argv[1],H,...K],{detached:true,windowsHide:true,stdio:["ignore",m,m],env:Z(a)});(0,p.closeSync)(m);m=void 0}D.unref()}catch(u){if(m!==void 0)(0,p.closeSync)(m);const R=`Runner failed before adopting task: ${v(u)}`;if(!q(f,a,R))process.exit(1);else{I(f,a,A,t,o.verbose,o.outputFormat);process.exit(0)}return}let $;try{$=await ke(f,a,D,{ignoreSuccessfulExit:V})}catch(u){const R=`Runner adoption check failed: ${v(u)}`;if(!q(f,a,R))process.exit(1);else{I(f,a,A,t,o.verbose,o.outputFormat);process.exit(0)}return}if($.kind==="adopted"){I(f,a,A,t,o.verbose,o.outputFormat);process.exit(0);return}if($.kind==="timeout"){I(f,a,A,t,o.verbose,o.outputFormat,`Warning: runner alive, row not yet adopted after ${J/1e3}s.`);process.exit(0);return}if(!q(f,a,$.reason))process.exit(1);else{I(f,a,A,t,o.verbose,o.outputFormat);process.exit(0)}}