@crewx/cli 0.9.0-rc.145 → 0.9.0-rc.147
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bootstrap/codex-writable-roots.js +1 -113
- package/dist/bootstrap/crewx-cli.js +1 -84
- package/dist/builtin.js +5 -132
- package/dist/commands/agent.js +4 -118
- package/dist/commands/cal.js +2 -44
- package/dist/commands/db.js +4 -602
- package/dist/commands/detached.js +15 -620
- package/dist/commands/doctor.js +4 -649
- package/dist/commands/emit-trailer.js +2 -33
- package/dist/commands/execute.js +15 -294
- package/dist/commands/hook/command-marker.js +1 -5
- package/dist/commands/hook/install.js +8 -189
- package/dist/commands/hook/paths.js +1 -94
- package/dist/commands/hook/status.js +1 -86
- package/dist/commands/hook/uninstall.js +1 -71
- package/dist/commands/hook-dispatch.js +2 -180
- package/dist/commands/init.js +31 -437
- package/dist/commands/kill.js +1 -11
- package/dist/commands/log.js +3 -96
- package/dist/commands/parse-agent-message.js +1 -52
- package/dist/commands/parse-common-flags.js +3 -212
- package/dist/commands/ps.js +2 -117
- package/dist/commands/publish.js +7 -283
- package/dist/commands/query.js +16 -292
- package/dist/commands/registry.js +1 -33
- package/dist/commands/resolve-prompt.js +3 -76
- package/dist/commands/resolve-recipient.js +3 -47
- package/dist/commands/restart.js +18 -172
- package/dist/commands/result.js +1 -209
- package/dist/commands/shortcut.js +4 -253
- package/dist/commands/slack.js +16 -560
- package/dist/commands/stop.js +8 -119
- package/dist/commands/write-output.js +1 -24
- package/dist/index.js +1 -8
- package/dist/logging.js +10 -87
- package/dist/main.js +6 -289
- package/dist/register-builtin-tools.js +1 -9
- package/dist/slack/file-download.js +1 -134
- package/dist/slack/markdown.js +1 -33
- package/dist/utils/env-defaults.js +1 -15
- package/dist/utils/inherited-trace.js +1 -65
- package/dist/utils/product-package-root.js +1 -39
- package/dist/utils/sdk-compat.js +1 -120
- package/dist/utils/version.js +1 -28
- package/package.json +15 -15
|
@@ -1,52 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Shared utility for parsing agent reference and message from CLI args.
|
|
4
|
-
*
|
|
5
|
-
* Supported call forms:
|
|
6
|
-
* crewx query '@claude 안녕' → agentRef='@claude', message='안녕'
|
|
7
|
-
* crewx query '@claude' '안녕' → agentRef='@claude', message='안녕'
|
|
8
|
-
* crewx query '@claude' '안녕' '해' → agentRef='@claude', message='안녕 해'
|
|
9
|
-
* crewx query '안녕하세요' → agentRef='', message='안녕하세요' (default agent)
|
|
10
|
-
*
|
|
11
|
-
* Only @mention form triggers explicit agent selection. Input without a
|
|
12
|
-
* leading @mention uses the default agent (@crewx) — callers are responsible
|
|
13
|
-
* for applying the fallback.
|
|
14
|
-
*
|
|
15
|
-
* Reusable by query, execute, and any future command that accepts an agent ref.
|
|
16
|
-
*/
|
|
17
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
-
exports.parseAgentMessage = parseAgentMessage;
|
|
19
|
-
/**
|
|
20
|
-
* Parse agent reference and message from CLI args array.
|
|
21
|
-
*
|
|
22
|
-
* Joins all args with a single space first, then splits on the first
|
|
23
|
-
* whitespace boundary so that both the "single-chunk" form
|
|
24
|
-
* (`'@claude 안녕'`) and the "separated" form (`'@claude', '안녕'`) produce
|
|
25
|
-
* identical results.
|
|
26
|
-
*
|
|
27
|
-
* Returns agentRef='' when no leading @mention is found — the caller should
|
|
28
|
-
* default to '@crewx' in that case.
|
|
29
|
-
*/
|
|
30
|
-
function parseAgentMessage(args) {
|
|
31
|
-
if (args.length === 0) {
|
|
32
|
-
return { agentRef: '', message: '' };
|
|
33
|
-
}
|
|
34
|
-
// Join all args so both forms are handled uniformly
|
|
35
|
-
const combined = args.join(' ').trim();
|
|
36
|
-
if (!combined) {
|
|
37
|
-
return { agentRef: '', message: '' };
|
|
38
|
-
}
|
|
39
|
-
// Only @mention form triggers explicit agent selection
|
|
40
|
-
if (combined.startsWith('@')) {
|
|
41
|
-
const spaceIdx = combined.indexOf(' ');
|
|
42
|
-
if (spaceIdx === -1) {
|
|
43
|
-
return { agentRef: combined, message: '' };
|
|
44
|
-
}
|
|
45
|
-
return {
|
|
46
|
-
agentRef: combined.slice(0, spaceIdx),
|
|
47
|
-
message: combined.slice(spaceIdx + 1).trim(),
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
// No leading @mention — entire input is the message; caller defaults to @crewx
|
|
51
|
-
return { agentRef: '', message: combined };
|
|
52
|
-
}
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.parseAgentMessage=n;function n(s){if(s.length===0){return{agentRef:"",message:""}}const e=s.join(" ").trim();if(!e){return{agentRef:"",message:""}}if(e.startsWith("@")){const t=e.indexOf(" ");if(t===-1){return{agentRef:e,message:""}}return{agentRef:e.slice(0,t),message:e.slice(t+1).trim()}}return{agentRef:"",message:e}}
|
|
@@ -1,212 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
*
|
|
5
|
-
* Supports both `--flag=value` and `--flag value` forms.
|
|
6
|
-
* Handles: --to, --thread, --provider, --model, --metadata, --verbose, --config/-c,
|
|
7
|
-
* --output-format, --effort, --prompt-file/-f, --overdrive.
|
|
8
|
-
*
|
|
9
|
-
* Strict mode: unknown --xxx tokens after known flags are consumed throw an
|
|
10
|
-
* error instead of silently leaking into the message prompt.
|
|
11
|
-
* Use `--` sentinel to pass literal flag-like tokens as positional args.
|
|
12
|
-
*/
|
|
13
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
-
exports.UnknownOptionError = void 0;
|
|
15
|
-
exports.parseCommonFlags = parseCommonFlags;
|
|
16
|
-
exports.parseMetadata = parseMetadata;
|
|
17
|
-
/**
|
|
18
|
-
* Parse a single-value flag from an args array.
|
|
19
|
-
* Supports `--flag=value` and `--flag value` forms.
|
|
20
|
-
* Returns undefined if flag is not present.
|
|
21
|
-
*/
|
|
22
|
-
function parseFlag(args, ...names) {
|
|
23
|
-
for (let i = 0; i < args.length; i++) {
|
|
24
|
-
const arg = args[i];
|
|
25
|
-
for (const name of names) {
|
|
26
|
-
const prefix = `${name}=`;
|
|
27
|
-
if (arg.startsWith(prefix)) {
|
|
28
|
-
return arg.slice(prefix.length);
|
|
29
|
-
}
|
|
30
|
-
if (arg === name && i + 1 < args.length) {
|
|
31
|
-
return args[i + 1];
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
return undefined;
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Check if a boolean flag is present.
|
|
39
|
-
*/
|
|
40
|
-
function hasFlag(args, ...names) {
|
|
41
|
-
return names.some(name => args.includes(name));
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Thrown by parseCommonFlags when an unrecognized --xxx flag is encountered.
|
|
45
|
-
* Callers can distinguish this from other errors to map to exit code 2.
|
|
46
|
-
*/
|
|
47
|
-
class UnknownOptionError extends Error {
|
|
48
|
-
constructor(message) {
|
|
49
|
-
super(message);
|
|
50
|
-
this.name = 'UnknownOptionError';
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
exports.UnknownOptionError = UnknownOptionError;
|
|
54
|
-
/**
|
|
55
|
-
* Parse common CLI flags from an args array.
|
|
56
|
-
*
|
|
57
|
-
* Strict mode: any unconsumed `--xxx` token (outside a `--` escape block)
|
|
58
|
-
* throws `UnknownOptionError: Unknown option: --xxx.`
|
|
59
|
-
*
|
|
60
|
-
* Tokens after `--` are treated as positional and included in `rest` as-is.
|
|
61
|
-
* The `--` sentinel itself is NOT included in `rest`.
|
|
62
|
-
*/
|
|
63
|
-
function parseCommonFlags(args) {
|
|
64
|
-
const { value: to, consumed: toConsumed } = parseToFlag(args);
|
|
65
|
-
const thread = parseFlag(args, '--thread');
|
|
66
|
-
const provider = parseFlag(args, '--provider');
|
|
67
|
-
const model = parseFlag(args, '--model');
|
|
68
|
-
const metadata = parseFlag(args, '--metadata');
|
|
69
|
-
const config = parseFlag(args, '--config', '-c');
|
|
70
|
-
const outputFormat = parseFlag(args, '--output-format');
|
|
71
|
-
const effort = parseFlag(args, '--effort');
|
|
72
|
-
const promptFile = parseFlag(args, '--prompt-file', '-f');
|
|
73
|
-
const out = parseFlag(args, '--out', '-o');
|
|
74
|
-
const verbose = hasFlag(args, '--verbose');
|
|
75
|
-
const overdrive = hasFlag(args, '--overdrive');
|
|
76
|
-
// Collect consumed positions for known flags
|
|
77
|
-
const consumed = new Set(toConsumed);
|
|
78
|
-
const flagPairs = [
|
|
79
|
-
{ names: ['--thread'] },
|
|
80
|
-
{ names: ['--provider'] },
|
|
81
|
-
{ names: ['--model'] },
|
|
82
|
-
{ names: ['--metadata'] },
|
|
83
|
-
{ names: ['--config', '-c'] },
|
|
84
|
-
{ names: ['--output-format'] },
|
|
85
|
-
{ names: ['--effort'] },
|
|
86
|
-
{ names: ['--prompt-file', '-f'] },
|
|
87
|
-
{ names: ['--out', '-o'] },
|
|
88
|
-
];
|
|
89
|
-
// Parse --var key=value flags (multiple allowed; last value wins on duplicate keys)
|
|
90
|
-
const vars = {};
|
|
91
|
-
for (let i = 0; i < args.length; i++) {
|
|
92
|
-
const arg = args[i];
|
|
93
|
-
if (arg === '--verbose') {
|
|
94
|
-
consumed.add(i);
|
|
95
|
-
continue;
|
|
96
|
-
}
|
|
97
|
-
if (arg === '--overdrive') {
|
|
98
|
-
consumed.add(i);
|
|
99
|
-
continue;
|
|
100
|
-
}
|
|
101
|
-
// --var=key=value or --var key=value
|
|
102
|
-
if (arg.startsWith('--var=') || arg === '--var') {
|
|
103
|
-
let kv;
|
|
104
|
-
if (arg.startsWith('--var=')) {
|
|
105
|
-
kv = arg.slice('--var='.length);
|
|
106
|
-
consumed.add(i);
|
|
107
|
-
}
|
|
108
|
-
else {
|
|
109
|
-
if (i + 1 >= args.length) {
|
|
110
|
-
throw new UnknownOptionError('--var requires a key=value argument');
|
|
111
|
-
}
|
|
112
|
-
kv = args[i + 1];
|
|
113
|
-
consumed.add(i);
|
|
114
|
-
consumed.add(i + 1);
|
|
115
|
-
i++; // skip the value token in the outer loop
|
|
116
|
-
}
|
|
117
|
-
const eqIdx = kv.indexOf('=');
|
|
118
|
-
if (eqIdx === -1) {
|
|
119
|
-
throw new UnknownOptionError(`--var requires key=value format. Got: ${kv}`);
|
|
120
|
-
}
|
|
121
|
-
const key = kv.slice(0, eqIdx);
|
|
122
|
-
const value = kv.slice(eqIdx + 1);
|
|
123
|
-
vars[key] = value;
|
|
124
|
-
continue;
|
|
125
|
-
}
|
|
126
|
-
for (const { names } of flagPairs) {
|
|
127
|
-
for (const name of names) {
|
|
128
|
-
if (arg.startsWith(`${name}=`)) {
|
|
129
|
-
consumed.add(i);
|
|
130
|
-
}
|
|
131
|
-
else if (arg === name) {
|
|
132
|
-
consumed.add(i);
|
|
133
|
-
if (i + 1 < args.length)
|
|
134
|
-
consumed.add(i + 1);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
// Build rest with strict unknown-flag detection and -- escape support
|
|
140
|
-
const rest = [];
|
|
141
|
-
let escapeMode = false;
|
|
142
|
-
for (let i = 0; i < args.length; i++) {
|
|
143
|
-
if (consumed.has(i))
|
|
144
|
-
continue;
|
|
145
|
-
const token = args[i];
|
|
146
|
-
if (!escapeMode && token === '--') {
|
|
147
|
-
escapeMode = true; // consume -- sentinel; everything after is positional
|
|
148
|
-
continue;
|
|
149
|
-
}
|
|
150
|
-
if (!escapeMode && token.startsWith('--')) {
|
|
151
|
-
throw new UnknownOptionError(`Unknown option: ${token}. Use "--" to pass literal flag-like tokens as message.\n` +
|
|
152
|
-
` Did you mean: crewx serve ${token}\n` +
|
|
153
|
-
` or: crewx q --to <agent> -- ${token} <message>`);
|
|
154
|
-
}
|
|
155
|
-
// Reject short -x flags that are not numeric (e.g. -f was consumed above)
|
|
156
|
-
if (!escapeMode && token.startsWith('-') && token.length > 1 && !/^-?\d/.test(token)) {
|
|
157
|
-
throw new UnknownOptionError(`Unknown option: ${token}`);
|
|
158
|
-
}
|
|
159
|
-
rest.push(token);
|
|
160
|
-
}
|
|
161
|
-
return { to, thread, provider, model, metadata, verbose, config, outputFormat, effort, promptFile, overdrive, vars, out, rest };
|
|
162
|
-
}
|
|
163
|
-
/** Parse the explicit recipient flag without treating tokens after `--` as flags. */
|
|
164
|
-
function parseToFlag(args) {
|
|
165
|
-
let value;
|
|
166
|
-
const consumed = [];
|
|
167
|
-
for (let index = 0; index < args.length; index += 1) {
|
|
168
|
-
const arg = args[index];
|
|
169
|
-
if (arg === '--')
|
|
170
|
-
break;
|
|
171
|
-
if (arg.startsWith('--to=')) {
|
|
172
|
-
const candidate = arg.slice('--to='.length);
|
|
173
|
-
if (!candidate.trim())
|
|
174
|
-
throw new UnknownOptionError('--to requires an agent id');
|
|
175
|
-
value = candidate;
|
|
176
|
-
consumed.push(index);
|
|
177
|
-
continue;
|
|
178
|
-
}
|
|
179
|
-
if (arg !== '--to')
|
|
180
|
-
continue;
|
|
181
|
-
const candidate = args[index + 1];
|
|
182
|
-
if (candidate === undefined || candidate === '--' || candidate.startsWith('--') || !candidate.trim()) {
|
|
183
|
-
throw new UnknownOptionError('--to requires an agent id');
|
|
184
|
-
}
|
|
185
|
-
value = candidate;
|
|
186
|
-
consumed.push(index, index + 1);
|
|
187
|
-
index += 1;
|
|
188
|
-
}
|
|
189
|
-
return { value, consumed };
|
|
190
|
-
}
|
|
191
|
-
/**
|
|
192
|
-
* Parse metadata JSON string from --metadata flag.
|
|
193
|
-
* Returns empty object when no raw value provided.
|
|
194
|
-
* Throws Error on invalid JSON or non-object values (fail-fast).
|
|
195
|
-
*/
|
|
196
|
-
function parseMetadata(raw) {
|
|
197
|
-
if (!raw)
|
|
198
|
-
return {};
|
|
199
|
-
try {
|
|
200
|
-
const parsed = JSON.parse(raw);
|
|
201
|
-
if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)) {
|
|
202
|
-
return parsed;
|
|
203
|
-
}
|
|
204
|
-
throw new Error(`--metadata must be a JSON object. Got: ${raw}`);
|
|
205
|
-
}
|
|
206
|
-
catch (err) {
|
|
207
|
-
if (err instanceof Error && err.message.startsWith('--metadata must be a JSON object')) {
|
|
208
|
-
throw err;
|
|
209
|
-
}
|
|
210
|
-
throw new Error(`--metadata must be valid JSON (double-quoted). Got: ${raw}`);
|
|
211
|
-
}
|
|
212
|
-
}
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.UnknownOptionError=void 0;exports.parseCommonFlags=F;exports.parseMetadata=S;function d(t,...e){for(let s=0;s<t.length;s++){const r=t[s];for(const i of e){const a=`${i}=`;if(r.startsWith(a)){return r.slice(a.length)}if(r===i&&s+1<t.length){return t[s+1]}}}return void 0}function w(t,...e){return e.some(s=>t.includes(s))}class u extends Error{constructor(e){super(e);this.name="UnknownOptionError"}}exports.UnknownOptionError=u;function F(t){const{value:e,consumed:s}=U(t);const r=d(t,"--thread");const i=d(t,"--provider");const a=d(t,"--model");const m=d(t,"--metadata");const k=d(t,"--config","-c");const b=d(t,"--output-format");const O=d(t,"--effort");const y=d(t,"--prompt-file","-f");const W=d(t,"--out","-o");const $=w(t,"--verbose");const g=w(t,"--overdrive");const c=new Set(s);const E=[{names:["--thread"]},{names:["--provider"]},{names:["--model"]},{names:["--metadata"]},{names:["--config","-c"]},{names:["--output-format"]},{names:["--effort"]},{names:["--prompt-file","-f"]},{names:["--out","-o"]}];const p={};for(let o=0;o<t.length;o++){const n=t[o];if(n==="--verbose"){c.add(o);continue}if(n==="--overdrive"){c.add(o);continue}if(n.startsWith("--var=")||n==="--var"){let f;if(n.startsWith("--var=")){f=n.slice("--var=".length);c.add(o)}else{if(o+1>=t.length){throw new u("--var requires a key=value argument")}f=t[o+1];c.add(o);c.add(o+1);o++}const l=f.indexOf("=");if(l===-1){throw new u(`--var requires key=value format. Got: ${f}`)}const q=f.slice(0,l);const x=f.slice(l+1);p[q]=x;continue}for(const{names:f}of E){for(const l of f){if(n.startsWith(`${l}=`)){c.add(o)}else if(n===l){c.add(o);if(o+1<t.length)c.add(o+1)}}}}const v=[];let h=false;for(let o=0;o<t.length;o++){if(c.has(o))continue;const n=t[o];if(!h&&n==="--"){h=true;continue}if(!h&&n.startsWith("--")){throw new u(`Unknown option: ${n}. Use "--" to pass literal flag-like tokens as message.
|
|
2
|
+
Did you mean: crewx serve ${n}
|
|
3
|
+
or: crewx q --to <agent> -- ${n} <message>`)}if(!h&&n.startsWith("-")&&n.length>1&&!/^-?\d/.test(n)){throw new u(`Unknown option: ${n}`)}v.push(n)}return{to:e,thread:r,provider:i,model:a,metadata:m,verbose:$,config:k,outputFormat:b,effort:O,promptFile:y,overdrive:g,vars:p,out:W,rest:v}}function U(t){let e;const s=[];for(let r=0;r<t.length;r+=1){const i=t[r];if(i==="--")break;if(i.startsWith("--to=")){const m=i.slice("--to=".length);if(!m.trim())throw new u("--to requires an agent id");e=m;s.push(r);continue}if(i!=="--to")continue;const a=t[r+1];if(a===void 0||a==="--"||a.startsWith("--")||!a.trim()){throw new u("--to requires an agent id")}e=a;s.push(r,r+1);r+=1}return{value:e,consumed:s}}function S(t){if(!t)return{};try{const e=JSON.parse(t);if(typeof e==="object"&&e!==null&&!Array.isArray(e)){return e}throw new Error(`--metadata must be a JSON object. Got: ${t}`)}catch(e){if(e instanceof Error&&e.message.startsWith("--metadata must be a JSON object")){throw e}throw new Error(`--metadata must be valid JSON (double-quoted). Got: ${t}`)}}
|
package/dist/commands/ps.js
CHANGED
|
@@ -1,117 +1,2 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
* crewx ps handler.
|
|
4
|
-
* Lists active tasks (pending or running) in table format.
|
|
5
|
-
*
|
|
6
|
-
* Usage:
|
|
7
|
-
* crewx ps List all pending and running tasks
|
|
8
|
-
* crewx ps --json Output as JSON array
|
|
9
|
-
*/
|
|
10
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
-
exports.handlePs = handlePs;
|
|
12
|
-
const repository_1 = require("@crewx/sdk/repository");
|
|
13
|
-
const cal_1 = require("./cal");
|
|
14
|
-
function formatElapsed(ms) {
|
|
15
|
-
const s = Math.floor(ms / 1000);
|
|
16
|
-
if (s < 60)
|
|
17
|
-
return `${s}s`;
|
|
18
|
-
const m = Math.floor(s / 60);
|
|
19
|
-
const rs = s % 60;
|
|
20
|
-
if (m < 60)
|
|
21
|
-
return `${m}m ${rs}s`;
|
|
22
|
-
const h = Math.floor(m / 60);
|
|
23
|
-
return `${h}h ${m % 60}m`;
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* Antigravity-family providers (coding_agent_command starting with 'agy',
|
|
27
|
-
* path-included forms like '/usr/local/bin/agy' also count) don't emit
|
|
28
|
-
* parseable logs, so they get a distinct 'n/a' instead of '—'.
|
|
29
|
-
*/
|
|
30
|
-
function isAgyCommand(codingAgentCommand) {
|
|
31
|
-
const cmd = (codingAgentCommand ?? '').trim();
|
|
32
|
-
if (!cmd)
|
|
33
|
-
return false;
|
|
34
|
-
const firstToken = cmd.split(/\s+/)[0] ?? '';
|
|
35
|
-
const base = firstToken.split('/').pop() ?? firstToken;
|
|
36
|
-
return base.startsWith('agy');
|
|
37
|
-
}
|
|
38
|
-
function getLastActive(task, taskRepo) {
|
|
39
|
-
try {
|
|
40
|
-
const entries = taskRepo.readLogsTail(task.id, 1)?.entries ?? [];
|
|
41
|
-
if (Array.isArray(entries) && entries.length > 0) {
|
|
42
|
-
const lastEntry = entries[entries.length - 1];
|
|
43
|
-
const ts = lastEntry?.timestamp;
|
|
44
|
-
const parsedMs = ts ? new Date(ts).getTime() : NaN;
|
|
45
|
-
if (ts && !Number.isNaN(parsedMs)) {
|
|
46
|
-
const diffMs = Math.max(0, Date.now() - parsedMs);
|
|
47
|
-
return {
|
|
48
|
-
display: `${formatElapsed(diffMs)} ago`,
|
|
49
|
-
isoTimestamp: ts,
|
|
50
|
-
logCapable: true,
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
catch {
|
|
56
|
-
// fall through to antigravity/dash fallback below
|
|
57
|
-
}
|
|
58
|
-
if (isAgyCommand(task.coding_agent_command)) {
|
|
59
|
-
return { display: 'n/a', isoTimestamp: null, logCapable: false };
|
|
60
|
-
}
|
|
61
|
-
return { display: '—', isoTimestamp: null, logCapable: true };
|
|
62
|
-
}
|
|
63
|
-
function taskToRow(task, taskRepo) {
|
|
64
|
-
const elapsed = formatElapsed(Date.now() - new Date(task.started_at).getTime());
|
|
65
|
-
const lastActive = getLastActive(task, taskRepo);
|
|
66
|
-
return [
|
|
67
|
-
task.id,
|
|
68
|
-
task.agent_id ?? '—',
|
|
69
|
-
task.status,
|
|
70
|
-
task.pid !== null && task.pid !== undefined ? String(task.pid) : '—',
|
|
71
|
-
elapsed,
|
|
72
|
-
task.mode ?? '—',
|
|
73
|
-
lastActive.display,
|
|
74
|
-
];
|
|
75
|
-
}
|
|
76
|
-
function renderTable(headers, rows) {
|
|
77
|
-
const colWidths = headers.map((h, i) => Math.max(h.length, ...rows.map(r => (r[i] ?? '').length)));
|
|
78
|
-
const separator = colWidths.map(w => '-'.repeat(w)).join(' ');
|
|
79
|
-
const headerLine = headers.map((h, i) => h.padEnd(colWidths[i] ?? h.length)).join(' ');
|
|
80
|
-
console.log(headerLine);
|
|
81
|
-
console.log(separator);
|
|
82
|
-
for (const row of rows) {
|
|
83
|
-
console.log(row.map((cell, i) => cell.padEnd(colWidths[i] ?? cell.length)).join(' '));
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
async function handlePs(args) {
|
|
87
|
-
const repo = new repository_1.TaskRepository();
|
|
88
|
-
const reaped = repo.reapOrphanedTasks();
|
|
89
|
-
if (reaped > 0)
|
|
90
|
-
console.error(`Reaped ${reaped} orphaned task(s)`);
|
|
91
|
-
repo.reapRunningWorkflowTasks();
|
|
92
|
-
const tasks = repo.getActiveTasks();
|
|
93
|
-
if (args.includes('--json')) {
|
|
94
|
-
const withLastActive = tasks.map((task) => {
|
|
95
|
-
const lastActive = getLastActive(task, repo);
|
|
96
|
-
return {
|
|
97
|
-
...task,
|
|
98
|
-
last_active_at: lastActive.isoTimestamp,
|
|
99
|
-
log_capable: lastActive.logCapable,
|
|
100
|
-
};
|
|
101
|
-
});
|
|
102
|
-
console.log(JSON.stringify(withLastActive, null, 2));
|
|
103
|
-
return;
|
|
104
|
-
}
|
|
105
|
-
if (tasks.length === 0) {
|
|
106
|
-
console.log('No active tasks.');
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
const headers = ['TASK ID', 'AGENT', 'STATUS', 'PID', 'ELAPSED', 'MODE', 'LAST ACTIVE'];
|
|
110
|
-
const rows = tasks.map((task) => taskToRow(task, repo));
|
|
111
|
-
renderTable(headers, rows);
|
|
112
|
-
console.log(`\n ${tasks.length} active task(s)`);
|
|
113
|
-
(0, cal_1.writeCalFooter)({
|
|
114
|
-
commandId: 'crewx.ps',
|
|
115
|
-
params: { taskId: tasks[0].id },
|
|
116
|
-
});
|
|
117
|
-
}
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.handlePs=h;const d=require("@crewx/sdk/repository");const m=require("./cal");function c(t){const n=Math.floor(t/1e3);if(n<60)return`${n}s`;const e=Math.floor(n/60);const o=n%60;if(e<60)return`${e}m ${o}s`;const r=Math.floor(e/60);return`${r}h ${e%60}m`}function u(t){const n=(t??"").trim();if(!n)return false;const e=n.split(/\s+/)[0]??"";const o=e.split("/").pop()??e;return o.startsWith("agy")}function p(t,n){try{const e=n.readLogsTail(t.id,1)?.entries??[];if(Array.isArray(e)&&e.length>0){const o=e[e.length-1];const r=o?.timestamp;const s=r?new Date(r).getTime():NaN;if(r&&!Number.isNaN(s)){const a=Math.max(0,Date.now()-s);return{display:`${c(a)} ago`,isoTimestamp:r,logCapable:true}}}}catch{}if(u(t.coding_agent_command)){return{display:"n/a",isoTimestamp:null,logCapable:false}}return{display:"\u2014",isoTimestamp:null,logCapable:true}}function g(t,n){const e=c(Date.now()-new Date(t.started_at).getTime());const o=p(t,n);return[t.id,t.agent_id??"\u2014",t.status,t.pid!==null&&t.pid!==void 0?String(t.pid):"\u2014",e,t.mode??"\u2014",o.display]}function f(t,n){const e=t.map((s,a)=>Math.max(s.length,...n.map(i=>(i[a]??"").length)));const o=e.map(s=>"-".repeat(s)).join(" ");const r=t.map((s,a)=>s.padEnd(e[a]??s.length)).join(" ");console.log(r);console.log(o);for(const s of n){console.log(s.map((a,i)=>a.padEnd(e[i]??a.length)).join(" "))}}async function h(t){const n=new d.TaskRepository;const e=n.reapOrphanedTasks();if(e>0)console.error(`Reaped ${e} orphaned task(s)`);n.reapRunningWorkflowTasks();const o=n.getActiveTasks();if(t.includes("--json")){const a=o.map(i=>{const l=p(i,n);return{...i,last_active_at:l.isoTimestamp,log_capable:l.logCapable}});console.log(JSON.stringify(a,null,2));return}if(o.length===0){console.log("No active tasks.");return}const r=["TASK ID","AGENT","STATUS","PID","ELAPSED","MODE","LAST ACTIVE"];const s=o.map(a=>g(a,n));f(r,s);console.log(`
|
|
2
|
+
${o.length} active task(s)`);(0,m.writeCalFooter)({commandId:"crewx.ps",params:{taskId:o[0].id}})}
|