@crewx/cli 0.9.0-rc.30 → 0.9.0-rc.32
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/builtin.js +1 -0
- package/dist/commands/execute.d.ts +3 -0
- package/dist/commands/execute.js +93 -2
- package/dist/commands/registry.js +1 -1
- package/dist/commands/result.d.ts +7 -3
- package/dist/commands/result.js +38 -4
- package/dist/main.js +8 -0
- package/package.json +9 -8
package/dist/builtin.js
CHANGED
|
@@ -55,6 +55,7 @@ const BUILTIN_MAP = {
|
|
|
55
55
|
dreaming: () => Promise.resolve().then(() => __importStar(require('@crewx/dreaming/cli'))),
|
|
56
56
|
wi: () => Promise.resolve().then(() => __importStar(require('@crewx/wi/cli'))),
|
|
57
57
|
chromex: () => Promise.resolve().then(() => __importStar(require('@crewx/chromex/cli'))),
|
|
58
|
+
notify: () => Promise.resolve().then(() => __importStar(require('@crewx/notify/cli'))),
|
|
58
59
|
};
|
|
59
60
|
exports.BUILTIN_COMMANDS = new Set(Object.keys(BUILTIN_MAP));
|
|
60
61
|
// Load skill-tracer for observability (graceful degradation if unavailable)
|
|
@@ -12,6 +12,9 @@
|
|
|
12
12
|
* --output-format <fmt> Output format (json|text|stream-json)
|
|
13
13
|
* --effort <level> Model effort (high|medium|low)
|
|
14
14
|
* -f/--prompt-file <path> Read task body from file (bypasses cmd.exe argv truncation)
|
|
15
|
+
* --detach Re-spawn as a detached runner; print task-id and exit 0 immediately.
|
|
16
|
+
* Ignored when CREWX_TRACE_ID is already set (recursive-spawn guard) or
|
|
17
|
+
* on win32 (unsupported — exits with an error).
|
|
15
18
|
*
|
|
16
19
|
* Stdin support:
|
|
17
20
|
* Pipe or redirect content into crewx x to supply the task body via stdin.
|
package/dist/commands/execute.js
CHANGED
|
@@ -13,6 +13,9 @@
|
|
|
13
13
|
* --output-format <fmt> Output format (json|text|stream-json)
|
|
14
14
|
* --effort <level> Model effort (high|medium|low)
|
|
15
15
|
* -f/--prompt-file <path> Read task body from file (bypasses cmd.exe argv truncation)
|
|
16
|
+
* --detach Re-spawn as a detached runner; print task-id and exit 0 immediately.
|
|
17
|
+
* Ignored when CREWX_TRACE_ID is already set (recursive-spawn guard) or
|
|
18
|
+
* on win32 (unsupported — exits with an error).
|
|
16
19
|
*
|
|
17
20
|
* Stdin support:
|
|
18
21
|
* Pipe or redirect content into crewx x to supply the task body via stdin.
|
|
@@ -21,6 +24,10 @@
|
|
|
21
24
|
*/
|
|
22
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
26
|
exports.handleExecute = handleExecute;
|
|
27
|
+
const child_process_1 = require("child_process");
|
|
28
|
+
const fs_1 = require("fs");
|
|
29
|
+
const path_1 = require("path");
|
|
30
|
+
const os_1 = require("os");
|
|
24
31
|
const sdk_1 = require("@crewx/sdk");
|
|
25
32
|
const parse_agent_message_1 = require("./parse-agent-message");
|
|
26
33
|
const parse_common_flags_1 = require("./parse-common-flags");
|
|
@@ -28,6 +35,61 @@ const resolve_prompt_1 = require("./resolve-prompt");
|
|
|
28
35
|
const crewx_cli_1 = require("../bootstrap/crewx-cli");
|
|
29
36
|
const inherited_trace_1 = require("../utils/inherited-trace");
|
|
30
37
|
const write_output_1 = require("./write-output");
|
|
38
|
+
/**
|
|
39
|
+
* Split `--detach` out of argv, respecting the `--` literal-args sentinel
|
|
40
|
+
* (a `--detach` appearing after `--` is message text, not the flag).
|
|
41
|
+
*/
|
|
42
|
+
function extractDetachFlag(args) {
|
|
43
|
+
const rest = [];
|
|
44
|
+
let detach = false;
|
|
45
|
+
let escapeMode = false;
|
|
46
|
+
for (const arg of args) {
|
|
47
|
+
if (!escapeMode && arg === '--') {
|
|
48
|
+
escapeMode = true;
|
|
49
|
+
rest.push(arg);
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
if (!escapeMode && arg === '--detach') {
|
|
53
|
+
detach = true;
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
rest.push(arg);
|
|
57
|
+
}
|
|
58
|
+
return { detach, rest };
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Double-detach: re-spawn this same CLI entry (minus --detach) as a detached
|
|
62
|
+
* process so it survives the parent's exit. The task-id is pre-generated here
|
|
63
|
+
* and injected as CREWX_TRACE_ID so the runner's own task row is created under
|
|
64
|
+
* this id (see handleExecute's `selfTaskId` derivation below) — it doubles as
|
|
65
|
+
* both this task's row id and the root of any further delegation it spawns.
|
|
66
|
+
*
|
|
67
|
+
* stdout contract (script-parseable): task-id only, on the first line.
|
|
68
|
+
* Everything else goes to stderr.
|
|
69
|
+
*/
|
|
70
|
+
function runDetached(filteredArgs) {
|
|
71
|
+
const taskId = (0, sdk_1.generateId)('tsk');
|
|
72
|
+
const logDir = (0, path_1.join)((0, os_1.homedir)(), '.crewx', 'logs');
|
|
73
|
+
if (!(0, fs_1.existsSync)(logDir))
|
|
74
|
+
(0, fs_1.mkdirSync)(logDir, { recursive: true });
|
|
75
|
+
const logPath = (0, path_1.join)(logDir, `${taskId}.log`);
|
|
76
|
+
const logFd = (0, fs_1.openSync)(logPath, 'a');
|
|
77
|
+
const entry = process.argv[1];
|
|
78
|
+
const child = (0, child_process_1.spawn)(process.execPath, [entry, 'x', ...filteredArgs], {
|
|
79
|
+
detached: true,
|
|
80
|
+
stdio: ['ignore', logFd, logFd],
|
|
81
|
+
env: { ...process.env, CREWX_TRACE_ID: taskId },
|
|
82
|
+
});
|
|
83
|
+
(0, fs_1.closeSync)(logFd);
|
|
84
|
+
child.on('error', (err) => {
|
|
85
|
+
process.stderr.write(`Failed to spawn detached runner: ${err.message}\n`);
|
|
86
|
+
});
|
|
87
|
+
child.unref();
|
|
88
|
+
console.log(taskId);
|
|
89
|
+
process.stderr.write(`Detached task ${taskId} started (log: ${logPath}).\n`);
|
|
90
|
+
process.stderr.write(`Use \`crewx result ${taskId} --wait=N\` to wait for completion.\n`);
|
|
91
|
+
process.exit(0);
|
|
92
|
+
}
|
|
31
93
|
/**
|
|
32
94
|
* Handle `crewx execute <agentRef> <message>` command.
|
|
33
95
|
*
|
|
@@ -35,7 +97,26 @@ const write_output_1 = require("./write-output");
|
|
|
35
97
|
* --verbose: debug info written to stderr, response to stdout.
|
|
36
98
|
*/
|
|
37
99
|
async function handleExecute(args) {
|
|
38
|
-
const {
|
|
100
|
+
const { detach, rest: detachFilteredArgs } = extractDetachFlag(args);
|
|
101
|
+
if (detach) {
|
|
102
|
+
// Recursive-spawn guard: a CREWX_TRACE_ID already present means this
|
|
103
|
+
// process is itself running inside a traced context (either the
|
|
104
|
+
// respawned runner, or a delegated sub-call) — never chain a second
|
|
105
|
+
// detach off of it. Silently fall through to normal (synchronous) execution.
|
|
106
|
+
if (process.env['CREWX_TRACE_ID']) {
|
|
107
|
+
process.stderr.write('Note: --detach ignored (already running inside a traced context; CREWX_TRACE_ID is set).\n');
|
|
108
|
+
}
|
|
109
|
+
else if (process.platform === 'win32') {
|
|
110
|
+
console.error('Error: --detach is not supported on win32.');
|
|
111
|
+
process.exit(1);
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
runDetached(detachFilteredArgs);
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
const { thread, provider, metadata, verbose, config, outputFormat, effort, promptFile, overdrive, vars, out, rest } = (0, parse_common_flags_1.parseCommonFlags)(detachFilteredArgs);
|
|
39
120
|
const { agentRef: parsedAgentRef, message } = (0, parse_agent_message_1.parseAgentMessage)(rest);
|
|
40
121
|
// No @mention → default to @crewx agent (matches cli-bak behaviour)
|
|
41
122
|
const agentRef = parsedAgentRef || '@crewx';
|
|
@@ -99,6 +180,15 @@ async function handleExecute(args) {
|
|
|
99
180
|
process.stderr.write(`Error: ${msg}\n`);
|
|
100
181
|
process.exit(2);
|
|
101
182
|
}
|
|
183
|
+
const inheritedTrace = (0, inherited_trace_1.readInheritedTrace)();
|
|
184
|
+
// A trace with a rootTraceId but no parentTaskId means the id was pre-assigned
|
|
185
|
+
// to *this* task itself (the detach runner's parent injects only CREWX_TRACE_ID,
|
|
186
|
+
// never CREWX_PARENT_TASK_ID — see execute.ts's runDetached), not inherited from
|
|
187
|
+
// an ancestor task in a delegation chain (which always carries both). It doubles
|
|
188
|
+
// as this task's own row id so `crewx result <task-id>` can find it.
|
|
189
|
+
const selfTaskId = inheritedTrace && !inheritedTrace.parentTaskId
|
|
190
|
+
? (inheritedTrace.rootTraceId || undefined)
|
|
191
|
+
: undefined;
|
|
102
192
|
let exitCode = 0;
|
|
103
193
|
try {
|
|
104
194
|
const result = await crewx.execute(agentRef, finalMessage, {
|
|
@@ -106,9 +196,10 @@ async function handleExecute(args) {
|
|
|
106
196
|
effort: effort || undefined,
|
|
107
197
|
overdrive: overdrive || undefined,
|
|
108
198
|
threadId: thread,
|
|
199
|
+
taskId: selfTaskId,
|
|
109
200
|
metadata: Object.keys(parsedMetadata).length > 0 ? parsedMetadata : undefined,
|
|
110
201
|
vars: Object.keys(vars).length > 0 ? vars : undefined,
|
|
111
|
-
trace:
|
|
202
|
+
trace: inheritedTrace,
|
|
112
203
|
});
|
|
113
204
|
if (!result.ok) {
|
|
114
205
|
const errMsg = result.error?.message ?? 'Execute failed';
|
|
@@ -23,7 +23,7 @@ exports.KNOWN_COMMANDS = new Set([
|
|
|
23
23
|
/** Built-in tool commands routed via handleBuiltin(). */
|
|
24
24
|
exports.BUILTIN_COMMAND_NAMES = new Set([
|
|
25
25
|
'memory', 'search', 'doc', 'wbs', 'cron', 'workflow', 'skill', 'dreaming',
|
|
26
|
-
'wi', 'chromex',
|
|
26
|
+
'wi', 'chromex', 'notify',
|
|
27
27
|
]);
|
|
28
28
|
/** Commands not yet migrated from cli-bak — show a migration message. */
|
|
29
29
|
exports.NOT_YET_MIGRATED = new Set([
|
|
@@ -3,8 +3,12 @@
|
|
|
3
3
|
* Retrieves the result of a completed task by its ID.
|
|
4
4
|
*
|
|
5
5
|
* Usage:
|
|
6
|
-
* crewx result <task-id>
|
|
7
|
-
* crewx result <task-id> --json
|
|
8
|
-
* crewx result
|
|
6
|
+
* crewx result <task-id> Print raw result
|
|
7
|
+
* crewx result <task-id> --json Print full task record as JSON
|
|
8
|
+
* crewx result <task-id> --wait=N Poll (1s interval) up to N seconds for
|
|
9
|
+
* the task to leave 'running'. Exit 124 on
|
|
10
|
+
* timeout. --wait=0 behaves like no --wait
|
|
11
|
+
* (single immediate check).
|
|
12
|
+
* crewx result List recent tasks (latest 10)
|
|
9
13
|
*/
|
|
10
14
|
export declare function handleResult(args: string[]): Promise<void>;
|
package/dist/commands/result.js
CHANGED
|
@@ -4,13 +4,18 @@
|
|
|
4
4
|
* Retrieves the result of a completed task by its ID.
|
|
5
5
|
*
|
|
6
6
|
* Usage:
|
|
7
|
-
* crewx result <task-id>
|
|
8
|
-
* crewx result <task-id> --json
|
|
9
|
-
* crewx result
|
|
7
|
+
* crewx result <task-id> Print raw result
|
|
8
|
+
* crewx result <task-id> --json Print full task record as JSON
|
|
9
|
+
* crewx result <task-id> --wait=N Poll (1s interval) up to N seconds for
|
|
10
|
+
* the task to leave 'running'. Exit 124 on
|
|
11
|
+
* timeout. --wait=0 behaves like no --wait
|
|
12
|
+
* (single immediate check).
|
|
13
|
+
* crewx result List recent tasks (latest 10)
|
|
10
14
|
*/
|
|
11
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
16
|
exports.handleResult = handleResult;
|
|
13
17
|
const repository_1 = require("@crewx/sdk/repository");
|
|
18
|
+
const POLL_INTERVAL_MS = 1000;
|
|
14
19
|
function statusIcon(status) {
|
|
15
20
|
switch (status) {
|
|
16
21
|
case 'running': return '⏳';
|
|
@@ -19,8 +24,20 @@ function statusIcon(status) {
|
|
|
19
24
|
default: return '❓';
|
|
20
25
|
}
|
|
21
26
|
}
|
|
27
|
+
function sleep(ms) {
|
|
28
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
29
|
+
}
|
|
30
|
+
/** Parses `--wait=N` (seconds). Returns undefined when the flag is absent. */
|
|
31
|
+
function parseWaitSeconds(args) {
|
|
32
|
+
const arg = args.find(a => a.startsWith('--wait='));
|
|
33
|
+
if (arg === undefined)
|
|
34
|
+
return undefined;
|
|
35
|
+
const n = Number(arg.slice('--wait='.length));
|
|
36
|
+
return Number.isFinite(n) && n >= 0 ? n : 0;
|
|
37
|
+
}
|
|
22
38
|
async function handleResult(args) {
|
|
23
39
|
const jsonMode = args.includes('--json');
|
|
40
|
+
const waitSeconds = parseWaitSeconds(args);
|
|
24
41
|
const taskId = args.find(a => !a.startsWith('--'));
|
|
25
42
|
const repo = new repository_1.TaskRepository();
|
|
26
43
|
if (!taskId) {
|
|
@@ -45,12 +62,29 @@ async function handleResult(args) {
|
|
|
45
62
|
console.log('Tip: Run `crewx result <task-id>` to see full output.');
|
|
46
63
|
return;
|
|
47
64
|
}
|
|
48
|
-
|
|
65
|
+
let task = repo.getTask(taskId);
|
|
49
66
|
if (!task) {
|
|
50
67
|
console.error(`Error: Task not found: ${taskId}`);
|
|
51
68
|
process.exit(1);
|
|
52
69
|
return;
|
|
53
70
|
}
|
|
71
|
+
if (waitSeconds !== undefined && waitSeconds > 0 && task.status === 'running') {
|
|
72
|
+
const deadline = Date.now() + waitSeconds * 1000;
|
|
73
|
+
while (task && task.status === 'running') {
|
|
74
|
+
if (Date.now() >= deadline) {
|
|
75
|
+
console.error(`Task ${taskId} did not complete within --wait=${waitSeconds}s (status: running).`);
|
|
76
|
+
process.exit(124);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
await sleep(Math.min(POLL_INTERVAL_MS, Math.max(0, deadline - Date.now())));
|
|
80
|
+
task = repo.getTask(taskId);
|
|
81
|
+
if (!task) {
|
|
82
|
+
console.error(`Error: Task not found: ${taskId}`);
|
|
83
|
+
process.exit(1);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
54
88
|
if (jsonMode) {
|
|
55
89
|
console.log(JSON.stringify(task, null, 2));
|
|
56
90
|
return;
|
package/dist/main.js
CHANGED
|
@@ -269,6 +269,12 @@ Query / Execute:
|
|
|
269
269
|
-- End of flags; remaining tokens treated as message text
|
|
270
270
|
e.g. crewx q "@agent label" -- --flag-in-message
|
|
271
271
|
|
|
272
|
+
x/execute only:
|
|
273
|
+
--detach Re-spawn as a detached background runner; print task-id
|
|
274
|
+
and exit 0 immediately. Ignored if CREWX_TRACE_ID is
|
|
275
|
+
already set (recursive-spawn guard). Unsupported on win32.
|
|
276
|
+
e.g. crewx x "@agent label" --detach
|
|
277
|
+
|
|
272
278
|
Agent Management:
|
|
273
279
|
agent ls [options] List configured agents
|
|
274
280
|
--role <value> Filter by role (comma-separated for OR match)
|
|
@@ -281,6 +287,8 @@ Task Management:
|
|
|
281
287
|
kill <task-id> Kill a running task
|
|
282
288
|
kill --all Kill all running tasks
|
|
283
289
|
result [task-id] Get task result (or list recent tasks)
|
|
290
|
+
--wait=N Poll (1s interval) up to N seconds for the task to
|
|
291
|
+
finish. Exit 124 on timeout. --wait=0 = single check.
|
|
284
292
|
restart <task-id> Restart a failed task as a new task
|
|
285
293
|
|
|
286
294
|
Logs & Diagnostics:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crewx/cli",
|
|
3
|
-
"version": "0.9.0-rc.
|
|
3
|
+
"version": "0.9.0-rc.32",
|
|
4
4
|
"license": "UNLICENSED",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=20.19.0"
|
|
@@ -24,16 +24,17 @@
|
|
|
24
24
|
"@crewx/adapter-slack": "0.1.4",
|
|
25
25
|
"better-sqlite3": "*",
|
|
26
26
|
"isomorphic-git": "1.37.1",
|
|
27
|
-
"@crewx/
|
|
28
|
-
"@crewx/sdk": "0.9.0-rc.30",
|
|
27
|
+
"@crewx/sdk": "0.9.0-rc.32",
|
|
29
28
|
"@crewx/memory": "0.1.23",
|
|
30
|
-
"@crewx/cron": "0.1.10",
|
|
31
|
-
"@crewx/wbs": "0.1.10",
|
|
32
29
|
"@crewx/doc": "0.1.9",
|
|
33
|
-
"@crewx/
|
|
34
|
-
"@crewx/
|
|
35
|
-
"@crewx/
|
|
30
|
+
"@crewx/wbs": "0.1.10",
|
|
31
|
+
"@crewx/search": "0.1.10",
|
|
32
|
+
"@crewx/cron": "0.1.10",
|
|
36
33
|
"@crewx/skill": "0.1.20",
|
|
34
|
+
"@crewx/workflow": "0.3.22-rc.78",
|
|
35
|
+
"@crewx/wi": "0.1.10-rc.52",
|
|
36
|
+
"@crewx/notify": "0.1.0-rc.2",
|
|
37
|
+
"@crewx/chromex": "0.1.0",
|
|
37
38
|
"@crewx/shared": "0.0.6"
|
|
38
39
|
},
|
|
39
40
|
"devDependencies": {
|