@crewx/cli 0.9.0-rc.93 → 0.9.0-rc.95
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/crewx-cli.js +5 -1
- package/dist/commands/cal.d.ts +3 -0
- package/dist/commands/cal.js +10 -0
- package/dist/commands/db.d.ts +1 -0
- package/dist/commands/db.js +191 -1
- package/dist/commands/detached.d.ts +65 -0
- package/dist/commands/detached.js +506 -0
- package/dist/commands/execute.d.ts +4 -6
- package/dist/commands/execute.js +46 -96
- package/dist/commands/kill.d.ts +2 -8
- package/dist/commands/kill.js +6 -47
- package/dist/commands/ps.d.ts +2 -2
- package/dist/commands/ps.js +18 -9
- package/dist/commands/publish.js +19 -6
- package/dist/commands/query.d.ts +2 -0
- package/dist/commands/query.js +39 -7
- package/dist/commands/registry.js +1 -1
- package/dist/commands/result.d.ts +1 -1
- package/dist/commands/result.js +72 -5
- package/dist/commands/stop.d.ts +8 -0
- package/dist/commands/stop.js +119 -0
- package/dist/main.d.ts +1 -1
- package/dist/main.js +22 -17
- package/dist/utils/inherited-trace.d.ts +24 -0
- package/dist/utils/inherited-trace.js +40 -0
- package/package.json +13 -12
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stop a running task through the SDK's cooperative-stop pipeline.
|
|
3
|
+
*
|
|
4
|
+
* `kill` is kept as a compatibility alias; both entry points use this same
|
|
5
|
+
* handler so server, CLI, and future adapters share one stop contract.
|
|
6
|
+
*/
|
|
7
|
+
/** Handle `crewx stop` and the compatibility `crewx kill` alias. */
|
|
8
|
+
export declare function handleStop(args: string[], invokedAs?: 'stop' | 'kill'): Promise<void>;
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Stop a running task through the SDK's cooperative-stop pipeline.
|
|
4
|
+
*
|
|
5
|
+
* `kill` is kept as a compatibility alias; both entry points use this same
|
|
6
|
+
* handler so server, CLI, and future adapters share one stop contract.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.handleStop = handleStop;
|
|
10
|
+
const sdk_1 = require("@crewx/sdk");
|
|
11
|
+
const repository_1 = require("@crewx/sdk/repository");
|
|
12
|
+
const cal_1 = require("./cal");
|
|
13
|
+
function parseGrace(args) {
|
|
14
|
+
const flag = args.find((arg) => arg === '--grace' || arg.startsWith('--grace='));
|
|
15
|
+
if (!flag)
|
|
16
|
+
return { graceMs: 5_000 };
|
|
17
|
+
const raw = flag === '--grace'
|
|
18
|
+
? args[args.indexOf(flag) + 1]
|
|
19
|
+
: flag.slice('--grace='.length);
|
|
20
|
+
const value = Number(raw);
|
|
21
|
+
if (!raw || !Number.isFinite(value) || value < 0) {
|
|
22
|
+
return { graceMs: 5_000, error: `Invalid --grace value: ${raw ?? '(missing)'}` };
|
|
23
|
+
}
|
|
24
|
+
return { graceMs: Math.trunc(value) };
|
|
25
|
+
}
|
|
26
|
+
function taskIdFromArgs(args) {
|
|
27
|
+
return args.find((arg, index) => {
|
|
28
|
+
if (arg === '--grace')
|
|
29
|
+
return false;
|
|
30
|
+
if (index > 0 && args[index - 1] === '--grace')
|
|
31
|
+
return false;
|
|
32
|
+
return !arg.startsWith('--');
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
function writeUsage() {
|
|
36
|
+
process.stderr.write('Error: Please provide a task ID or use --all to stop all running tasks.\n');
|
|
37
|
+
process.stderr.write('\nUsage:\n');
|
|
38
|
+
process.stderr.write(' crewx stop <task-id> Stop a running task\n');
|
|
39
|
+
process.stderr.write(' crewx stop --all Stop all running tasks\n');
|
|
40
|
+
process.stderr.write(' crewx stop <task-id> --grace=<ms>\n');
|
|
41
|
+
}
|
|
42
|
+
function formatGrace(graceMs) {
|
|
43
|
+
return `${graceMs / 1000}s`;
|
|
44
|
+
}
|
|
45
|
+
function reportResult(taskId, result, elapsedMs, graceMs) {
|
|
46
|
+
if (result.status === 'stopped') {
|
|
47
|
+
if (result.method === 'forced') {
|
|
48
|
+
process.stdout.write(`Stopped ${taskId} (forced after ${formatGrace(graceMs)} grace)\n`);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
process.stdout.write(`Stopped ${taskId} (cooperative, ${(elapsedMs / 1000).toFixed(1)}s)\n`);
|
|
52
|
+
}
|
|
53
|
+
return 0;
|
|
54
|
+
}
|
|
55
|
+
if (result.status === 'not_running') {
|
|
56
|
+
process.stdout.write(`Task ${taskId} is not running (${result.finalStatus ?? 'unknown'})\n`);
|
|
57
|
+
return 0;
|
|
58
|
+
}
|
|
59
|
+
if (result.status === 'already_requested') {
|
|
60
|
+
process.stderr.write(`Task ${taskId} already has a stop request; it remains ${result.finalStatus ?? 'running'}.\n`);
|
|
61
|
+
return 2;
|
|
62
|
+
}
|
|
63
|
+
if (result.status === 'ownership_unverified') {
|
|
64
|
+
const pid = result.pid ? ` (pid ${result.pid})` : '';
|
|
65
|
+
process.stderr.write(`Could not verify the process owner of ${taskId}; not terminated${pid}. ` +
|
|
66
|
+
'Row stays running — the reaper will settle it.\n');
|
|
67
|
+
return 2;
|
|
68
|
+
}
|
|
69
|
+
process.stderr.write(`Could not stop ${taskId}: ${result.error ?? 'unknown error'}\n`);
|
|
70
|
+
return 1;
|
|
71
|
+
}
|
|
72
|
+
/** Handle `crewx stop` and the compatibility `crewx kill` alias. */
|
|
73
|
+
async function handleStop(args, invokedAs = 'stop') {
|
|
74
|
+
if (invokedAs === 'kill')
|
|
75
|
+
process.stderr.write('kill is an alias of stop\n');
|
|
76
|
+
const stopAll = args.includes('--all');
|
|
77
|
+
const { graceMs, error } = parseGrace(args);
|
|
78
|
+
if (error) {
|
|
79
|
+
process.stderr.write(`Error: ${error}\n`);
|
|
80
|
+
process.exitCode = 1;
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const taskId = taskIdFromArgs(args);
|
|
84
|
+
if (!taskId && !stopAll) {
|
|
85
|
+
writeUsage();
|
|
86
|
+
process.exitCode = 1;
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
const repo = new repository_1.TaskRepository();
|
|
90
|
+
const stopOne = async (id, withFooter) => {
|
|
91
|
+
const startedAt = Date.now();
|
|
92
|
+
const result = await (0, sdk_1.stopTask)(repo, id, { graceMs });
|
|
93
|
+
const exitCode = reportResult(id, result, Date.now() - startedAt, graceMs);
|
|
94
|
+
if (withFooter && (result.status === 'stopped' || result.status === 'not_running')) {
|
|
95
|
+
(0, cal_1.writeCalFooter)({
|
|
96
|
+
commandId: 'crewx.stop.done',
|
|
97
|
+
params: { taskId: id },
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
return exitCode;
|
|
101
|
+
};
|
|
102
|
+
if (stopAll) {
|
|
103
|
+
const running = repo.getRunningTasks();
|
|
104
|
+
if (running.length === 0) {
|
|
105
|
+
process.stdout.write('No running tasks found.\n');
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
let exitCode = 0;
|
|
109
|
+
for (const task of running) {
|
|
110
|
+
exitCode = Math.max(exitCode, await stopOne(task.id, false));
|
|
111
|
+
}
|
|
112
|
+
if (exitCode > 0)
|
|
113
|
+
process.exitCode = exitCode;
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
const exitCode = await stopOne(taskId, true);
|
|
117
|
+
if (exitCode > 0)
|
|
118
|
+
process.exitCode = exitCode;
|
|
119
|
+
}
|
package/dist/main.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*
|
|
6
6
|
* Boot sequence:
|
|
7
7
|
* 1. Inject CREWX_CLI / CREWX_WORKSPACE env defaults (must be first)
|
|
8
|
-
* 2. Load workspace .env (does not override
|
|
8
|
+
* 2. Load workspace and ~/.crewx .env files (does not override process.env)
|
|
9
9
|
* 3. Parse command
|
|
10
10
|
* 4. Dispatch to handler
|
|
11
11
|
*/
|
package/dist/main.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* Boot sequence:
|
|
8
8
|
* 1. Inject CREWX_CLI / CREWX_WORKSPACE env defaults (must be first)
|
|
9
|
-
* 2. Load workspace .env (does not override
|
|
9
|
+
* 2. Load workspace and ~/.crewx .env files (does not override process.env)
|
|
10
10
|
* 3. Parse command
|
|
11
11
|
* 4. Dispatch to handler
|
|
12
12
|
*/
|
|
@@ -47,15 +47,16 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
47
47
|
// ─── P0-1: Env Bootstrap ─────────────────────────────────────────────────────
|
|
48
48
|
// Must run before any other code that might use process.env.CREWX_CLI.
|
|
49
49
|
const sdk_compat_1 = require("./utils/sdk-compat");
|
|
50
|
-
const
|
|
51
|
-
const
|
|
50
|
+
const account_1 = require("@crewx/sdk/account");
|
|
51
|
+
const inherited_trace_1 = require("./utils/inherited-trace");
|
|
52
52
|
process.env.CREWX_CLI ??= sdk_compat_1.sdkCompat.resolveCrewxCli();
|
|
53
53
|
process.env.CREWX_WORKSPACE ??= sdk_compat_1.sdkCompat.resolveCrewxWorkspace();
|
|
54
|
-
// Load
|
|
55
|
-
// the
|
|
56
|
-
|
|
57
|
-
//
|
|
58
|
-
|
|
54
|
+
// Load workspace .env before ~/.crewx/.env. The SDK-owned loader keeps CLI and
|
|
55
|
+
// server bootstrap on the same process > workspace > home precedence contract.
|
|
56
|
+
(0, account_1.loadCrewxEnvFiles)();
|
|
57
|
+
// Receipt runner identity is a one-hop capability. Consume it before any
|
|
58
|
+
// command/provider code can spawn a child process.
|
|
59
|
+
(0, inherited_trace_1.consumeInheritedRunnerIdentity)();
|
|
59
60
|
// ─── Pricing remote override (WI-20260701-002) ───────────────────────────────
|
|
60
61
|
// Best-effort, non-blocking: fetch remote model registry so new models get
|
|
61
62
|
// accurate pricing without a CLI republish. Falls back to bundled table on
|
|
@@ -66,7 +67,7 @@ const query_1 = require("./commands/query");
|
|
|
66
67
|
const execute_1 = require("./commands/execute");
|
|
67
68
|
const agent_1 = require("./commands/agent");
|
|
68
69
|
const ps_1 = require("./commands/ps");
|
|
69
|
-
const
|
|
70
|
+
const stop_1 = require("./commands/stop");
|
|
70
71
|
const result_1 = require("./commands/result");
|
|
71
72
|
const restart_1 = require("./commands/restart");
|
|
72
73
|
const log_1 = require("./commands/log");
|
|
@@ -142,9 +143,12 @@ async function main(emitState) {
|
|
|
142
143
|
case 'ps':
|
|
143
144
|
await (0, ps_1.handlePs)(args.slice(1));
|
|
144
145
|
return;
|
|
145
|
-
//
|
|
146
|
+
// Task stop (kill is a compatibility alias)
|
|
147
|
+
case 'stop':
|
|
148
|
+
await (0, stop_1.handleStop)(args.slice(1), 'stop');
|
|
149
|
+
return;
|
|
146
150
|
case 'kill':
|
|
147
|
-
await (0,
|
|
151
|
+
await (0, stop_1.handleStop)(args.slice(1), 'kill');
|
|
148
152
|
return;
|
|
149
153
|
// P0-6: result
|
|
150
154
|
case 'result':
|
|
@@ -287,10 +291,10 @@ Query / Execute:
|
|
|
287
291
|
-- End of flags; remaining tokens treated as message text
|
|
288
292
|
e.g. crewx q "@agent label" -- --flag-in-message
|
|
289
293
|
|
|
290
|
-
x/execute
|
|
291
|
-
--detach
|
|
292
|
-
|
|
293
|
-
|
|
294
|
+
q/query/x/execute:
|
|
295
|
+
--detach/--async Persist a receipt, launch a detached runner, and print task-id
|
|
296
|
+
(automatic inside an agent process; q/x stay synchronous elsewhere).
|
|
297
|
+
--wait Force synchronous execution, including inside an agent process.
|
|
294
298
|
e.g. crewx x "@agent label" --detach
|
|
295
299
|
|
|
296
300
|
Agent Management:
|
|
@@ -302,8 +306,9 @@ Agent Management:
|
|
|
302
306
|
|
|
303
307
|
Task Management:
|
|
304
308
|
ps List running tasks
|
|
305
|
-
|
|
306
|
-
|
|
309
|
+
stop <task-id> Stop a running task (cooperative, then forced)
|
|
310
|
+
stop --all Stop all running tasks
|
|
311
|
+
kill <task-id> Alias for stop
|
|
307
312
|
result [task-id] Get task result (or list recent tasks)
|
|
308
313
|
--wait=N Poll (1s interval) up to N seconds for the task to
|
|
309
314
|
finish. Exit 124 on timeout. --wait=0 = single check.
|
|
@@ -1,4 +1,19 @@
|
|
|
1
1
|
import type { TraceContext } from '@crewx/sdk';
|
|
2
|
+
export interface InheritedRunnerIdentity {
|
|
3
|
+
assignedTaskId?: string;
|
|
4
|
+
detachedRunner: boolean;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Consume the runner-only identity exactly once.
|
|
8
|
+
*
|
|
9
|
+
* These variables are a one-hop capability, not trace context. Keeping the
|
|
10
|
+
* values in this module lets the current CLI process use them while deleting
|
|
11
|
+
* them from process.env prevents later child processes from inheriting the
|
|
12
|
+
* receipt runner identity.
|
|
13
|
+
*/
|
|
14
|
+
export declare function consumeInheritedRunnerIdentity(): InheritedRunnerIdentity;
|
|
15
|
+
/** Test-only reset for the module-level one-shot cache. */
|
|
16
|
+
export declare function resetInheritedRunnerIdentityForTests(): void;
|
|
2
17
|
/**
|
|
3
18
|
* Read cross-process trace context from inherited environment variables.
|
|
4
19
|
*
|
|
@@ -10,3 +25,12 @@ import type { TraceContext } from '@crewx/sdk';
|
|
|
10
25
|
* Returns undefined when none of the three vars are set (root invocation).
|
|
11
26
|
*/
|
|
12
27
|
export declare function readInheritedTrace(): TraceContext | undefined;
|
|
28
|
+
/**
|
|
29
|
+
* Read the pre-assigned task id carried only by a detached runner.
|
|
30
|
+
*
|
|
31
|
+
* This is deliberately separate from readInheritedTrace(): trace variables
|
|
32
|
+
* describe the caller's chain and must not be used as this task's identity.
|
|
33
|
+
*/
|
|
34
|
+
export declare function readRunnerAssignment(): string | undefined;
|
|
35
|
+
/** Return true only for the final detached runner process. */
|
|
36
|
+
export declare function isDetachedRunner(): boolean;
|
|
@@ -1,6 +1,33 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.consumeInheritedRunnerIdentity = consumeInheritedRunnerIdentity;
|
|
4
|
+
exports.resetInheritedRunnerIdentityForTests = resetInheritedRunnerIdentityForTests;
|
|
3
5
|
exports.readInheritedTrace = readInheritedTrace;
|
|
6
|
+
exports.readRunnerAssignment = readRunnerAssignment;
|
|
7
|
+
exports.isDetachedRunner = isDetachedRunner;
|
|
8
|
+
let inheritedRunnerIdentity;
|
|
9
|
+
/**
|
|
10
|
+
* Consume the runner-only identity exactly once.
|
|
11
|
+
*
|
|
12
|
+
* These variables are a one-hop capability, not trace context. Keeping the
|
|
13
|
+
* values in this module lets the current CLI process use them while deleting
|
|
14
|
+
* them from process.env prevents later child processes from inheriting the
|
|
15
|
+
* receipt runner identity.
|
|
16
|
+
*/
|
|
17
|
+
function consumeInheritedRunnerIdentity() {
|
|
18
|
+
if (inheritedRunnerIdentity !== undefined)
|
|
19
|
+
return inheritedRunnerIdentity;
|
|
20
|
+
const assignedTaskId = process.env['CREWX_ASSIGNED_TASK_ID']?.trim() || undefined;
|
|
21
|
+
const detachedRunner = process.env['CREWX_DETACHED_RUNNER'] === '1';
|
|
22
|
+
delete process.env['CREWX_ASSIGNED_TASK_ID'];
|
|
23
|
+
delete process.env['CREWX_DETACHED_RUNNER'];
|
|
24
|
+
inheritedRunnerIdentity = { assignedTaskId, detachedRunner };
|
|
25
|
+
return inheritedRunnerIdentity;
|
|
26
|
+
}
|
|
27
|
+
/** Test-only reset for the module-level one-shot cache. */
|
|
28
|
+
function resetInheritedRunnerIdentityForTests() {
|
|
29
|
+
inheritedRunnerIdentity = undefined;
|
|
30
|
+
}
|
|
4
31
|
/**
|
|
5
32
|
* Read cross-process trace context from inherited environment variables.
|
|
6
33
|
*
|
|
@@ -23,3 +50,16 @@ function readInheritedTrace() {
|
|
|
23
50
|
callerAgentId,
|
|
24
51
|
};
|
|
25
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* Read the pre-assigned task id carried only by a detached runner.
|
|
55
|
+
*
|
|
56
|
+
* This is deliberately separate from readInheritedTrace(): trace variables
|
|
57
|
+
* describe the caller's chain and must not be used as this task's identity.
|
|
58
|
+
*/
|
|
59
|
+
function readRunnerAssignment() {
|
|
60
|
+
return consumeInheritedRunnerIdentity().assignedTaskId;
|
|
61
|
+
}
|
|
62
|
+
/** Return true only for the final detached runner process. */
|
|
63
|
+
function isDetachedRunner() {
|
|
64
|
+
return consumeInheritedRunnerIdentity().detachedRunner;
|
|
65
|
+
}
|
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.95",
|
|
4
4
|
"license": "UNLICENSED",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=20.19.0"
|
|
@@ -25,18 +25,19 @@
|
|
|
25
25
|
"better-sqlite3": "*",
|
|
26
26
|
"dotenv": "17.2.3",
|
|
27
27
|
"isomorphic-git": "1.37.1",
|
|
28
|
-
"@crewx/sdk": "0.9.0-rc.
|
|
29
|
-
"@crewx/memory": "0.1.23-rc.
|
|
30
|
-
"@crewx/search": "0.1.10-rc.
|
|
31
|
-
"@crewx/
|
|
32
|
-
"@crewx/
|
|
33
|
-
"@crewx/
|
|
28
|
+
"@crewx/sdk": "0.9.0-rc.95",
|
|
29
|
+
"@crewx/memory": "0.1.23-rc.112",
|
|
30
|
+
"@crewx/search": "0.1.10-rc.91",
|
|
31
|
+
"@crewx/doc": "0.1.9-rc.88",
|
|
32
|
+
"@crewx/knowledge-core": "0.1.17-rc.105",
|
|
33
|
+
"@crewx/wbs": "0.1.10-rc.121",
|
|
34
|
+
"@crewx/workflow": "0.3.22-rc.141",
|
|
34
35
|
"@crewx/skill": "0.1.20",
|
|
35
|
-
"@crewx/
|
|
36
|
-
"@crewx/
|
|
37
|
-
"@crewx/chromex": "0.1.0-rc.
|
|
38
|
-
"@crewx/
|
|
39
|
-
"@crewx/
|
|
36
|
+
"@crewx/wi": "0.1.10-rc.115",
|
|
37
|
+
"@crewx/cron": "0.1.10-rc.130",
|
|
38
|
+
"@crewx/chromex": "0.1.0-rc.128",
|
|
39
|
+
"@crewx/shared": "0.0.6",
|
|
40
|
+
"@crewx/notify": "0.1.0-rc.66"
|
|
40
41
|
},
|
|
41
42
|
"devDependencies": {
|
|
42
43
|
"@types/better-sqlite3": "*",
|