@crewx/cli 0.9.0-rc.146 → 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.
Files changed (45) hide show
  1. package/dist/bootstrap/codex-writable-roots.js +1 -113
  2. package/dist/bootstrap/crewx-cli.js +1 -84
  3. package/dist/builtin.js +5 -132
  4. package/dist/commands/agent.js +4 -118
  5. package/dist/commands/cal.js +2 -44
  6. package/dist/commands/db.js +4 -602
  7. package/dist/commands/detached.js +15 -620
  8. package/dist/commands/doctor.js +4 -649
  9. package/dist/commands/emit-trailer.js +2 -33
  10. package/dist/commands/execute.js +15 -294
  11. package/dist/commands/hook/command-marker.js +1 -5
  12. package/dist/commands/hook/install.js +8 -189
  13. package/dist/commands/hook/paths.js +1 -94
  14. package/dist/commands/hook/status.js +1 -86
  15. package/dist/commands/hook/uninstall.js +1 -71
  16. package/dist/commands/hook-dispatch.js +2 -180
  17. package/dist/commands/init.js +31 -437
  18. package/dist/commands/kill.js +1 -11
  19. package/dist/commands/log.js +3 -96
  20. package/dist/commands/parse-agent-message.js +1 -52
  21. package/dist/commands/parse-common-flags.js +3 -212
  22. package/dist/commands/ps.js +2 -117
  23. package/dist/commands/publish.js +7 -283
  24. package/dist/commands/query.js +16 -292
  25. package/dist/commands/registry.js +1 -33
  26. package/dist/commands/resolve-prompt.js +3 -76
  27. package/dist/commands/resolve-recipient.js +3 -47
  28. package/dist/commands/restart.js +18 -172
  29. package/dist/commands/result.js +1 -209
  30. package/dist/commands/shortcut.js +4 -253
  31. package/dist/commands/slack.js +16 -560
  32. package/dist/commands/stop.js +8 -119
  33. package/dist/commands/write-output.js +1 -24
  34. package/dist/index.js +1 -8
  35. package/dist/logging.js +10 -87
  36. package/dist/main.js +6 -289
  37. package/dist/register-builtin-tools.js +1 -9
  38. package/dist/slack/file-download.js +1 -134
  39. package/dist/slack/markdown.js +1 -33
  40. package/dist/utils/env-defaults.js +1 -15
  41. package/dist/utils/inherited-trace.js +1 -65
  42. package/dist/utils/product-package-root.js +1 -39
  43. package/dist/utils/sdk-compat.js +1 -120
  44. package/dist/utils/version.js +1 -28
  45. package/package.json +15 -15
@@ -1,33 +1,2 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createDelegationEmitState = createDelegationEmitState;
4
- exports.shouldEmitDelegationResult = shouldEmitDelegationResult;
5
- exports.emitDelegationResult = emitDelegationResult;
6
- const sdk_1 = require("@crewx/sdk");
7
- const inherited_trace_1 = require("../utils/inherited-trace");
8
- const DELEGATION_COMMANDS = new Set(['q', 'query', 'x', 'execute']);
9
- function createDelegationEmitState() {
10
- return { emitted: false };
11
- }
12
- /**
13
- * Return true only for an inherited child invocation of q/query/x/execute.
14
- * Root CLI calls and unrelated built-in commands must remain byte-compatible.
15
- */
16
- function shouldEmitDelegationResult(command, trace = (0, inherited_trace_1.readInheritedTrace)()) {
17
- return DELEGATION_COMMANDS.has(command ?? '') && Boolean(trace?.parentTaskId);
18
- }
19
- /**
20
- * Write one machine-readable result line to stdout when this is a delegated call.
21
- * The shared SDK formatter owns the wire syntax and validation rules.
22
- */
23
- function emitDelegationResult(options) {
24
- const { command, trace, state, taskId, agentId, isError } = options;
25
- if (state?.emitted || !shouldEmitDelegationResult(command, trace))
26
- return false;
27
- const line = (0, sdk_1.formatDelegationResult)({ taskId, agentId, isError });
28
- // Mark before writing so an EPIPE/error boundary cannot accidentally retry.
29
- if (state)
30
- state.emitted = true;
31
- process.stdout.write(`${line}\n`);
32
- return true;
33
- }
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.createDelegationEmitState=m;exports.shouldEmitDelegationResult=n;exports.emitDelegationResult=f;const l=require("@crewx/sdk");const c=require("../utils/inherited-trace");const d=new Set(["q","query","x","execute"]);function m(){return{emitted:false}}function n(e,t=(0,c.readInheritedTrace)()){return d.has(e??"")&&Boolean(t?.parentTaskId)}function f(e){const{command:t,trace:i,state:r,taskId:a,agentId:o,isError:s}=e;if(r?.emitted||!n(t,i))return false;const u=(0,l.formatDelegationResult)({taskId:a,agentId:o,isError:s});if(r)r.emitted=true;process.stdout.write(`${u}
2
+ `);return true}
@@ -1,294 +1,15 @@
1
- "use strict";
2
- /**
3
- * crewx execute handler.
4
- * Parses args, loads config via Crewx SDK, and executes the task.
5
- *
6
- * Flags:
7
- * --to <agent> Explicit recipient (the positional @agent form is shorthand)
8
- * --thread <name> Conversation thread name
9
- * --provider <cli/xxx> Provider override
10
- * --model <name> Model override (e.g. claude-sonnet-5)
11
- * --metadata <json> Extra metadata JSON (double-quoted object). Propagated to events/hooks/tracing.
12
- * --verbose Debug output mode (default: raw agent response only)
13
- * --config/-c <path> Config file path override
14
- * --output-format <fmt> Output format (json|text|stream-json)
15
- * --effort <level> Model effort (high|medium|low)
16
- * -f/--prompt-file <path> Read task body from file
17
- * --detach/--async Persist a receipt and launch a detached runner
18
- * --wait Force synchronous execution
19
- *
20
- * Stdin support:
21
- * Pipe or redirect content into crewx x to supply the task body via stdin.
22
- * Stdin is ignored when running in an interactive TTY.
23
- */
24
- Object.defineProperty(exports, "__esModule", { value: true });
25
- exports.runDetachedMiddle = void 0;
26
- exports.handleExecute = handleExecute;
27
- const sdk_1 = require("@crewx/sdk");
28
- const repository_1 = require("@crewx/sdk/repository");
29
- const parse_agent_message_1 = require("./parse-agent-message");
30
- const parse_common_flags_1 = require("./parse-common-flags");
31
- const resolve_recipient_1 = require("./resolve-recipient");
32
- const resolve_prompt_1 = require("./resolve-prompt");
33
- const crewx_cli_1 = require("../bootstrap/crewx-cli");
34
- const inherited_trace_1 = require("../utils/inherited-trace");
35
- const write_output_1 = require("./write-output");
36
- const detached_1 = require("./detached");
37
- const emit_trailer_1 = require("./emit-trailer");
38
- // Exported for platform-focused tests; the middle hop remains an internal CLI
39
- // contract and is not routed through the public command registry.
40
- var detached_2 = require("./detached");
41
- Object.defineProperty(exports, "runDetachedMiddle", { enumerable: true, get: function () { return detached_2.runDetachedMiddle; } });
42
- /**
43
- * Handle `crewx execute <agentRef> <message>` command.
44
- *
45
- * Default output: raw agent response only (stdout).
46
- * --verbose: debug info written to stderr, response to stdout.
47
- */
48
- async function handleExecute(args, command = 'execute', emitState = (0, emit_trailer_1.createDelegationEmitState)()) {
49
- // The private middle-hop marker is consumed before public flag parsing. An
50
- // invalid direct use remains an unknown option and is rejected normally.
51
- const middleHop = (0, detached_1.readDetachedMiddleHop)(args);
52
- if (middleHop) {
53
- await (0, detached_1.runDetachedMiddle)(command, middleHop);
54
- return;
55
- }
56
- const receiptFlags = (0, detached_1.extractReceiptFlags)(args);
57
- const receiptMode = (0, detached_1.resolveReceiptMode)({
58
- detach: receiptFlags.detach,
59
- wait: receiptFlags.wait,
60
- detachedRunner: (0, inherited_trace_1.isDetachedRunner)(),
61
- agentContext: Boolean(process.env['CREWX_AGENT_ID']),
62
- });
63
- if (receiptMode.receipt) {
64
- await (0, detached_1.runDetached)(command, receiptFlags.rest, receiptMode.reason, args);
65
- return;
66
- }
67
- let parsedFlags;
68
- try {
69
- parsedFlags = (0, parse_common_flags_1.parseCommonFlags)(receiptFlags.rest);
70
- }
71
- catch (err) {
72
- (0, emit_trailer_1.emitDelegationResult)({ command, isError: true, state: emitState });
73
- throw err;
74
- }
75
- const { thread, provider, model, metadata, verbose, config, outputFormat, effort, promptFile, overdrive, vars, out, rest, to } = parsedFlags;
76
- const inheritedTrace = (0, inherited_trace_1.readInheritedTrace)();
77
- let parsedAgentRef;
78
- let message;
79
- let finalMessage;
80
- try {
81
- ({ agentRef: parsedAgentRef, message } = (0, parse_agent_message_1.parseAgentMessage)(rest));
82
- // Resolve final prompt: argv | stdin pipe | --prompt-file (or combination)
83
- finalMessage = await (0, resolve_prompt_1.resolvePrompt)(message, promptFile);
84
- }
85
- catch (err) {
86
- (0, emit_trailer_1.emitDelegationResult)({ command, trace: inheritedTrace, isError: true, state: emitState });
87
- throw err;
88
- }
89
- let agentRef;
90
- try {
91
- ({ agentRef } = (0, resolve_recipient_1.resolveRecipient)({
92
- positionalRef: parsedAgentRef,
93
- toFlag: to,
94
- agentContext: Boolean(process.env['CREWX_AGENT_ID']),
95
- bodyForHint: finalMessage,
96
- command,
97
- invocationArgs: args,
98
- }));
99
- }
100
- catch (err) {
101
- const message = err instanceof Error ? err.message : String(err);
102
- process.stderr.write(`Error: ${message}\n`);
103
- (0, emit_trailer_1.emitDelegationResult)({ command, trace: inheritedTrace, isError: true, state: emitState });
104
- process.exit(2);
105
- return;
106
- }
107
- if (!finalMessage) {
108
- console.error('Usage: crewx execute --to <agent> <task> [options]');
109
- console.error(' crewx x --to <agent> <task> [options]');
110
- console.error(' Human-terminal shorthand: crewx x "@agent <task>"');
111
- console.error('');
112
- console.error(' Agent calls require --to or a positional @agent recipient.');
113
- console.error(' Human terminal and cron calls default to @crewx when omitted.');
114
- console.error(' Task body can also be supplied via stdin pipe or --prompt-file.');
115
- console.error('');
116
- console.error('Examples:');
117
- console.error(' crewx x --to agent "do something"');
118
- console.error(' crewx x --to agent -f task.md');
119
- console.error(' Prompt files contain only the body; set the recipient separately with --to.');
120
- console.error('');
121
- console.error('Options:');
122
- console.error(' --to <agent> Explicit agent recipient');
123
- console.error(' --thread <name> Conversation thread name');
124
- console.error(' --provider <cli/xxx> Provider override');
125
- console.error(' --model <name> Model override (e.g. claude-sonnet-5)');
126
- console.error(' --metadata <json> Extra metadata (JSON object, double-quoted).');
127
- console.error(' Propagated to events/hooks/tracing.');
128
- console.error(' Invalid JSON aborts with exit code 2.');
129
- console.error(' e.g. --metadata=\'{"workflow_id":"wf-1"}\'');
130
- console.error(' --verbose Debug output mode');
131
- console.error(' --config/-c <path> Config file path');
132
- console.error(' --output-format <fmt> Output format (json|text|stream-json)');
133
- console.error(' --out/-o <path> Save result to file (stdout suppressed)');
134
- console.error(' --effort <level> Model effort (high|medium|low)');
135
- console.error(' -f/--prompt-file <path> Read body only from file; set recipient separately with --to');
136
- console.error(' --var key=value Template variable (repeatable)');
137
- console.error(' --overdrive Activate overdrive (boost) profile for this request');
138
- (0, emit_trailer_1.emitDelegationResult)({ command, trace: inheritedTrace, isError: true, state: emitState });
139
- process.exit(1);
140
- return;
141
- }
142
- const configPath = config ?? process.env.CREWX_CONFIG ?? 'crewx.yaml';
143
- // Only show exec audit span JSON in verbose mode
144
- (0, sdk_1.setAuditVerbose)(verbose);
145
- let crewx;
146
- try {
147
- crewx = await (0, crewx_cli_1.createCliCrewx)(configPath);
148
- }
149
- catch (err) {
150
- (0, emit_trailer_1.emitDelegationResult)({ command, trace: inheritedTrace, isError: true, state: emitState });
151
- throw err;
152
- }
153
- // file:// remote agent delegation is handled transparently inside Crewx.query/execute.
154
- if (verbose) {
155
- process.stderr.write(`mode=sync reason=${receiptMode.reason}\n`);
156
- process.stderr.write(`📋 Task: ${finalMessage}\n`);
157
- process.stderr.write(`🤖 Agent: ${agentRef}\n`);
158
- if (thread)
159
- process.stderr.write(`🔗 Thread: ${thread}\n`);
160
- if (provider)
161
- process.stderr.write(`🔌 Provider: ${provider}\n`);
162
- if (model)
163
- process.stderr.write(`🧠 Model: ${model}\n`);
164
- if (outputFormat)
165
- process.stderr.write(`📄 Output-format: ${outputFormat}\n`);
166
- if (effort)
167
- process.stderr.write(`⚡ Effort: ${effort}\n`);
168
- if (overdrive)
169
- process.stderr.write('🚀 Overdrive: ON\n');
170
- process.stderr.write('─'.repeat(60) + '\n');
171
- }
172
- let parsedMetadata = {};
173
- try {
174
- parsedMetadata = (0, parse_common_flags_1.parseMetadata)(metadata);
175
- }
176
- catch (err) {
177
- const msg = err instanceof Error ? err.message : String(err);
178
- process.stderr.write(`Error: ${msg}\n`);
179
- (0, emit_trailer_1.emitDelegationResult)({ command, trace: inheritedTrace, isError: true, state: emitState });
180
- process.exit(2);
181
- return;
182
- }
183
- const actor = (0, detached_1.resolveCliTaskActor)(parsedMetadata);
184
- // Only the detached runner may adopt a pre-issued task row. Trace variables
185
- // describe the caller chain and are never used as this task's identity.
186
- const detachedRunner = (0, inherited_trace_1.isDetachedRunner)();
187
- const assignedTaskId = (0, inherited_trace_1.readRunnerAssignment)();
188
- let selfTaskId;
189
- let taskActor;
190
- if (assignedTaskId !== undefined) {
191
- const taskRepo = new repository_1.TaskRepository();
192
- const adoption = (0, detached_1.adoptAssignedTask)(taskRepo, assignedTaskId, detachedRunner);
193
- if (adoption.kind === 'failed') {
194
- (0, emit_trailer_1.emitDelegationResult)({ command, trace: inheritedTrace, isError: true, state: emitState });
195
- process.exit(1);
196
- return;
197
- }
198
- if (adoption.kind === 'adopted') {
199
- selfTaskId = adoption.taskId;
200
- taskActor = (0, detached_1.readAssignedTaskActor)(taskRepo, adoption.taskId);
201
- }
202
- }
203
- // A synchronous `crewx x` runs in this same process, but this process is
204
- // still separate from the embedded server and never sees its in-memory
205
- // UpdateGateService (WI-CTO-20260919-004 R2 finding #1) — only the durable
206
- // marker it writes. Reserve-then-check before calling into the SDK below,
207
- // not after; see admitDurableTask()'s own doc comment. Never checked for
208
- // an adopted receipt (selfTaskId set): that work was already admitted by
209
- // whichever process first created its pending DB row.
210
- let admission;
211
- if (selfTaskId === undefined) {
212
- admission = (0, sdk_1.admitDurableTask)(`direct-cli:${command}`);
213
- if (!admission.ok) {
214
- (0, detached_1.reportAdmissionBlocked)(admission);
215
- (0, emit_trailer_1.emitDelegationResult)({ command, trace: inheritedTrace, isError: true, state: emitState });
216
- process.exit(1);
217
- return;
218
- }
219
- }
220
- let exitCode = 0;
221
- let result;
222
- try {
223
- try {
224
- result = await crewx.execute(agentRef, finalMessage, {
225
- provider,
226
- model,
227
- effort: effort || undefined,
228
- overdrive: overdrive || undefined,
229
- threadId: thread,
230
- taskId: selfTaskId,
231
- actor: selfTaskId === undefined ? actor : taskActor,
232
- metadata: Object.keys(parsedMetadata).length > 0 ? parsedMetadata : undefined,
233
- vars: Object.keys(vars).length > 0 ? vars : undefined,
234
- trace: inheritedTrace,
235
- });
236
- if (!result.ok) {
237
- const errMsg = result.error?.message ?? 'Execute failed';
238
- console.error(errMsg);
239
- (0, write_output_1.appendError)(out, errMsg);
240
- exitCode = 1;
241
- }
242
- else {
243
- if (verbose) {
244
- process.stderr.write(`\n📊 Results from ${agentRef}:\n`);
245
- process.stderr.write('═'.repeat(60) + '\n');
246
- process.stderr.write('🟢 Status: Success\n');
247
- process.stderr.write(`🤖 Provider: ${result.meta.provider}\n`);
248
- process.stderr.write(`⏱️ Duration: ${result.meta.durationMs}ms\n`);
249
- process.stderr.write('\n📄 Response:\n');
250
- process.stderr.write('─'.repeat(40) + '\n');
251
- }
252
- (0, write_output_1.writeResult)(out, result.data);
253
- if (verbose)
254
- process.stderr.write('\n✅ Execute completed successfully\n');
255
- }
256
- }
257
- catch (err) {
258
- const errMsg = err instanceof Error ? err.message : String(err);
259
- console.error(`Error: ${errMsg}`);
260
- (0, write_output_1.appendError)(out, `Error: ${errMsg}`);
261
- exitCode = 1;
262
- }
263
- finally {
264
- try {
265
- await crewx.close();
266
- }
267
- catch (err) {
268
- (0, emit_trailer_1.emitDelegationResult)({
269
- command,
270
- trace: inheritedTrace,
271
- taskId: result?.meta.taskId,
272
- agentId: result?.meta.agentId,
273
- isError: true,
274
- state: emitState,
275
- });
276
- throw err;
277
- }
278
- }
279
- }
280
- finally {
281
- if (admission?.ok)
282
- admission.release();
283
- }
284
- (0, emit_trailer_1.emitDelegationResult)({
285
- command,
286
- trace: inheritedTrace,
287
- taskId: result?.meta.taskId,
288
- agentId: result?.meta.agentId,
289
- isError: exitCode !== 0 || result?.ok === false,
290
- state: emitState,
291
- });
292
- if (exitCode !== 0)
293
- process.exit(exitCode);
294
- }
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.runDetachedMiddle=void 0;exports.handleExecute=S;const F=require("@crewx/sdk");const U=require("@crewx/sdk/repository");const V=require("./parse-agent-message");const P=require("./parse-common-flags");const z=require("./resolve-recipient");const K=require("./resolve-prompt");const L=require("../bootstrap/crewx-cli");const v=require("../utils/inherited-trace");const D=require("./write-output");const i=require("./detached");const s=require("./emit-trailer");var Q=require("./detached");Object.defineProperty(exports,"runDetachedMiddle",{enumerable:true,get:function(){return Q.runDetachedMiddle}});async function S(u,r="execute",a=(0,s.createDelegationEmitState)()){const b=(0,i.readDetachedMiddleHop)(u);if(b){await(0,i.runDetachedMiddle)(r,b);return}const p=(0,i.extractReceiptFlags)(u);const m=(0,i.resolveReceiptMode)({detach:p.detach,wait:p.wait,detachedRunner:(0,v.isDetachedRunner)(),agentContext:Boolean(process.env["CREWX_AGENT_ID"])});if(m.receipt){await(0,i.runDetached)(r,p.rest,m.reason,u);return}let I;try{I=(0,P.parseCommonFlags)(p.rest)}catch(e){(0,s.emitDelegationResult)({command:r,isError:true,state:a});throw e}const{thread:x,provider:k,model:E,metadata:j,verbose:f,config:N,outputFormat:M,effort:R,promptFile:H,overdrive:A,vars:$,out:_,rest:B,to:G}=I;const n=(0,v.readInheritedTrace)();let q;let T;let c;try{({agentRef:q,message:T}=(0,V.parseAgentMessage)(B));c=await(0,K.resolvePrompt)(T,H)}catch(e){(0,s.emitDelegationResult)({command:r,trace:n,isError:true,state:a});throw e}let g;try{({agentRef:g}=(0,z.resolveRecipient)({positionalRef:q,toFlag:G,agentContext:Boolean(process.env["CREWX_AGENT_ID"]),bodyForHint:c,command:r,invocationArgs:u}))}catch(e){const o=e instanceof Error?e.message:String(e);process.stderr.write(`Error: ${o}
2
+ `);(0,s.emitDelegationResult)({command:r,trace:n,isError:true,state:a});process.exit(2);return}if(!c){console.error("Usage: crewx execute --to <agent> <task> [options]");console.error(" crewx x --to <agent> <task> [options]");console.error(' Human-terminal shorthand: crewx x "@agent <task>"');console.error("");console.error(" Agent calls require --to or a positional @agent recipient.");console.error(" Human terminal and cron calls default to @crewx when omitted.");console.error(" Task body can also be supplied via stdin pipe or --prompt-file.");console.error("");console.error("Examples:");console.error(' crewx x --to agent "do something"');console.error(" crewx x --to agent -f task.md");console.error(" Prompt files contain only the body; set the recipient separately with --to.");console.error("");console.error("Options:");console.error(" --to <agent> Explicit agent recipient");console.error(" --thread <name> Conversation thread name");console.error(" --provider <cli/xxx> Provider override");console.error(" --model <name> Model override (e.g. claude-sonnet-5)");console.error(" --metadata <json> Extra metadata (JSON object, double-quoted).");console.error(" Propagated to events/hooks/tracing.");console.error(" Invalid JSON aborts with exit code 2.");console.error(` e.g. --metadata='{"workflow_id":"wf-1"}'`);console.error(" --verbose Debug output mode");console.error(" --config/-c <path> Config file path");console.error(" --output-format <fmt> Output format (json|text|stream-json)");console.error(" --out/-o <path> Save result to file (stdout suppressed)");console.error(" --effort <level> Model effort (high|medium|low)");console.error(" -f/--prompt-file <path> Read body only from file; set recipient separately with --to");console.error(" --var key=value Template variable (repeatable)");console.error(" --overdrive Activate overdrive (boost) profile for this request");(0,s.emitDelegationResult)({command:r,trace:n,isError:true,state:a});process.exit(1);return}const W=N??process.env.CREWX_CONFIG??"crewx.yaml";(0,F.setAuditVerbose)(f);let y;try{y=await(0,L.createCliCrewx)(W)}catch(e){(0,s.emitDelegationResult)({command:r,trace:n,isError:true,state:a});throw e}if(f){process.stderr.write(`mode=sync reason=${m.reason}
3
+ `);process.stderr.write(`\u{1F4CB} Task: ${c}
4
+ `);process.stderr.write(`\u{1F916} Agent: ${g}
5
+ `);if(x)process.stderr.write(`\u{1F517} Thread: ${x}
6
+ `);if(k)process.stderr.write(`\u{1F50C} Provider: ${k}
7
+ `);if(E)process.stderr.write(`\u{1F9E0} Model: ${E}
8
+ `);if(M)process.stderr.write(`\u{1F4C4} Output-format: ${M}
9
+ `);if(R)process.stderr.write(`\u26A1 Effort: ${R}
10
+ `);if(A)process.stderr.write("\u{1F680} Overdrive: ON\n");process.stderr.write("\u2500".repeat(60)+"\n")}let h={};try{h=(0,P.parseMetadata)(j)}catch(e){const o=e instanceof Error?e.message:String(e);process.stderr.write(`Error: ${o}
11
+ `);(0,s.emitDelegationResult)({command:r,trace:n,isError:true,state:a});process.exit(2);return}const X=(0,i.resolveCliTaskActor)(h);const J=(0,v.isDetachedRunner)();const C=(0,v.readRunnerAssignment)();let w;let O;if(C!==void 0){const e=new U.TaskRepository;const o=(0,i.adoptAssignedTask)(e,C,J);if(o.kind==="failed"){(0,s.emitDelegationResult)({command:r,trace:n,isError:true,state:a});process.exit(1);return}if(o.kind==="adopted"){w=o.taskId;O=(0,i.readAssignedTaskActor)(e,o.taskId)}}let d;if(w===void 0){d=(0,F.admitDurableTask)(`direct-cli:${r}`);if(!d.ok){(0,i.reportAdmissionBlocked)(d);(0,s.emitDelegationResult)({command:r,trace:n,isError:true,state:a});process.exit(1);return}}let l=0;let t;try{try{t=await y.execute(g,c,{provider:k,model:E,effort:R||void 0,overdrive:A||void 0,threadId:x,taskId:w,actor:w===void 0?X:O,metadata:Object.keys(h).length>0?h:void 0,vars:Object.keys($).length>0?$:void 0,trace:n});if(!t.ok){const e=t.error?.message??"Execute failed";console.error(e);(0,D.appendError)(_,e);l=1}else{if(f){process.stderr.write(`
12
+ \u{1F4CA} Results from ${g}:
13
+ `);process.stderr.write("\u2550".repeat(60)+"\n");process.stderr.write("\u{1F7E2} Status: Success\n");process.stderr.write(`\u{1F916} Provider: ${t.meta.provider}
14
+ `);process.stderr.write(`\u23F1\uFE0F Duration: ${t.meta.durationMs}ms
15
+ `);process.stderr.write("\n\u{1F4C4} Response:\n");process.stderr.write("\u2500".repeat(40)+"\n")}(0,D.writeResult)(_,t.data);if(f)process.stderr.write("\n\u2705 Execute completed successfully\n")}}catch(e){const o=e instanceof Error?e.message:String(e);console.error(`Error: ${o}`);(0,D.appendError)(_,`Error: ${o}`);l=1}finally{try{await y.close()}catch(e){(0,s.emitDelegationResult)({command:r,trace:n,taskId:t?.meta.taskId,agentId:t?.meta.agentId,isError:true,state:a});throw e}}}finally{if(d?.ok)d.release()}(0,s.emitDelegationResult)({command:r,trace:n,taskId:t?.meta.taskId,agentId:t?.meta.agentId,isError:l!==0||t?.ok===false,state:a});if(l!==0)process.exit(l)}
@@ -1,5 +1 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.CREWX_HOOK_COMMAND_RE = void 0;
4
- /** Match only commands that invoke CrewX's hook-dispatch subcommand. */
5
- exports.CREWX_HOOK_COMMAND_RE = /crewx(?:\.js|\.cmd|\.exe)?['"]?\s+hook-dispatch\b/i;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.CREWX_HOOK_COMMAND_RE=void 0;exports.CREWX_HOOK_COMMAND_RE=/crewx(?:\.js|\.cmd|\.exe)?['"]?\s+hook-dispatch\b/i;
@@ -1,189 +1,8 @@
1
- "use strict";
2
- /**
3
- * crewx hook install — Register crewx-hook-dispatch as a PreToolUse hook
4
- * in <projectRoot>/.claude/settings.json and/or <projectRoot>/.codex/hooks.json.
5
- *
6
- * Security:
7
- * - Prompts user before modifying settings (R1)
8
- * - Uses absolute path for crewx binary (PATH manipulation prevention)
9
- * - Backs up original settings files
10
- * - Preserves existing user hooks
11
- * - Never traverses parent directories — project root determined by crewx.yaml
12
- */
13
- Object.defineProperty(exports, "__esModule", { value: true });
14
- exports.resolveCrewxBinary = resolveCrewxBinary;
15
- exports.handleHookInstall = handleHookInstall;
16
- const fs_1 = require("fs");
17
- const sdk_1 = require("@crewx/sdk");
18
- const paths_1 = require("./paths");
19
- const command_marker_1 = require("./command-marker");
20
- function getProviderConfigs(projectRoot, providers) {
21
- return providers.map((provider) => ({
22
- settingsPath: provider === 'claude'
23
- ? (0, paths_1.getClaudeSettingsPath)(projectRoot)
24
- : (0, paths_1.getCodexHooksPath)(projectRoot),
25
- provider,
26
- matcher: provider === 'claude' ? '' : 'Bash',
27
- commandArg: `--provider ${provider}`,
28
- }));
29
- }
30
- function resolveCrewxBinary() {
31
- const resolution = (0, sdk_1.resolveCrewxExecutable)();
32
- if (!resolution.ok) {
33
- throw new Error((0, sdk_1.formatCrewxExecutableFailure)(resolution));
34
- }
35
- let stableEntrypoint;
36
- try {
37
- stableEntrypoint = (0, sdk_1.materializeCrewxStableEntrypoint)(resolution, { allowEnvStage: true });
38
- }
39
- catch (error) {
40
- if (resolution.requiredEnv && Object.keys(resolution.requiredEnv).length > 0) {
41
- throw new Error(`CrewX hook entrypoint could not preserve required environment: ${error instanceof Error ? error.message : String(error)}`);
42
- }
43
- throw error;
44
- }
45
- if (stableEntrypoint) {
46
- return (0, sdk_1.formatCrewxExecutableArgv)([stableEntrypoint]);
47
- }
48
- // A required runtime environment cannot be represented by a raw argv string,
49
- // and the fingerprint shim directory is doctor-GC managed. Refuse to write
50
- // either representation when the stable hook path was not eligible.
51
- if (resolution.requiredEnv && Object.keys(resolution.requiredEnv).length > 0) {
52
- throw new Error('CrewX hook entrypoint could not preserve required environment: stable entrypoint is not eligible for this executable');
53
- }
54
- return (0, sdk_1.formatCrewxExecutableArgv)(resolution.argv);
55
- }
56
- function readSettingsTyped(settingsPath) {
57
- return (0, paths_1.readSettings)(settingsPath);
58
- }
59
- function findCrewxEntry(preToolUse) {
60
- if (!preToolUse)
61
- return -1;
62
- return preToolUse.findIndex((entry) => entry.hooks?.some((h) => command_marker_1.CREWX_HOOK_COMMAND_RE.test(h.command)));
63
- }
64
- function findCrewxHook(entry) {
65
- if (!entry.hooks)
66
- return undefined;
67
- const index = entry.hooks.findIndex((hook) => command_marker_1.CREWX_HOOK_COMMAND_RE.test(hook.command));
68
- if (index < 0)
69
- return undefined;
70
- return { index, command: entry.hooks[index].command };
71
- }
72
- function installForProvider(projectRoot, config, crewxBin, yes) {
73
- const { settingsPath, provider, matcher, commandArg } = config;
74
- const command = `${crewxBin} hook-dispatch ${commandArg}`;
75
- const settings = readSettingsTyped(settingsPath);
76
- if (!settings.hooks)
77
- settings.hooks = {};
78
- if (!settings.hooks.PreToolUse)
79
- settings.hooks.PreToolUse = [];
80
- const existingIdx = findCrewxEntry(settings.hooks.PreToolUse);
81
- if (existingIdx >= 0) {
82
- const existingEntry = settings.hooks.PreToolUse[existingIdx];
83
- const existingHook = findCrewxHook(existingEntry);
84
- if (existingHook?.command === command) {
85
- console.log(`[crewx] Hook already installed in ${settingsPath} (${provider})`);
86
- return false;
87
- }
88
- if (!yes) {
89
- console.log(`[crewx] Existing CrewX hook needs an install-path refresh in ${settingsPath} (${provider})`);
90
- return false;
91
- }
92
- if ((0, fs_1.existsSync)(settingsPath)) {
93
- const backupPath = settingsPath + '.crewx-backup';
94
- (0, fs_1.copyFileSync)(settingsPath, backupPath);
95
- console.log(`[crewx] Backup created: ${backupPath}`);
96
- }
97
- if (existingHook) {
98
- existingEntry.hooks[existingHook.index] = { ...existingEntry.hooks[existingHook.index], command };
99
- }
100
- (0, fs_1.writeFileSync)(settingsPath, JSON.stringify(settings, null, 2) + '\n', 'utf8');
101
- console.log(`[crewx] Hook updated (${provider}): ${command}`);
102
- console.log(`[crewx] Settings: ${settingsPath}`);
103
- return true;
104
- }
105
- if (!yes) {
106
- console.log(`⚠️ crewx hook install will register crewx-hook-dispatch as a PreToolUse hook.\n` +
107
- ` This gives crewx authority to allow/deny ALL ${provider} tool calls.\n` +
108
- ` ${settingsPath} will be patched (backup at ${settingsPath}.crewx-backup).\n`);
109
- return false;
110
- }
111
- if ((0, fs_1.existsSync)(settingsPath)) {
112
- const backupPath = settingsPath + '.crewx-backup';
113
- (0, fs_1.copyFileSync)(settingsPath, backupPath);
114
- console.log(`[crewx] Backup created: ${backupPath}`);
115
- }
116
- if (provider === 'claude') {
117
- (0, paths_1.ensureClaudeSettings)(projectRoot);
118
- }
119
- else {
120
- (0, paths_1.ensureCodexHooks)(projectRoot);
121
- }
122
- settings.hooks.PreToolUse.push({
123
- matcher,
124
- hooks: [{ type: 'command', command }],
125
- });
126
- (0, fs_1.writeFileSync)(settingsPath, JSON.stringify(settings, null, 2) + '\n', 'utf8');
127
- console.log(`[crewx] Hook installed (${provider}): ${command}`);
128
- console.log(`[crewx] Settings: ${settingsPath}`);
129
- return true;
130
- }
131
- async function handleHookInstall(argsOrOpts) {
132
- if (!Array.isArray(argsOrOpts)) {
133
- const { projectRoot, yes, provider } = argsOrOpts;
134
- const providers = (0, paths_1.providersFromFilter)(provider ?? 'all');
135
- let crewxBin;
136
- try {
137
- crewxBin = resolveCrewxBinary();
138
- }
139
- catch (error) {
140
- console.error(`[crewx] ${error instanceof Error ? error.message : String(error)}`);
141
- return;
142
- }
143
- const configs = getProviderConfigs(projectRoot, providers);
144
- for (const config of configs) {
145
- installForProvider(projectRoot, config, crewxBin, yes);
146
- }
147
- return;
148
- }
149
- const args = argsOrOpts;
150
- const yes = args.includes('--yes') || args.includes('-y');
151
- const cwd = process.cwd();
152
- const projectRoot = (0, paths_1.findProjectRoot)(cwd);
153
- if (!projectRoot) {
154
- console.error('[crewx] No crewx.yaml found in current or ancestor directories.');
155
- console.error('[crewx] Run this command from within a CrewX project.');
156
- process.exitCode = 1;
157
- return;
158
- }
159
- const providerFilter = (0, paths_1.parseProviderArg)(args);
160
- const providers = (0, paths_1.providersFromFilter)(providerFilter);
161
- let crewxBin;
162
- try {
163
- crewxBin = resolveCrewxBinary();
164
- }
165
- catch (error) {
166
- console.error(`[crewx] ${error instanceof Error ? error.message : String(error)}`);
167
- process.exitCode = 1;
168
- return;
169
- }
170
- const configs = getProviderConfigs(projectRoot, providers);
171
- if (!yes) {
172
- const targets = configs.map((c) => ` - ${c.provider}: ${c.settingsPath}`).join('\n');
173
- console.log(`⚠️ crewx hook install will register crewx-hook-dispatch as a PreToolUse hook.\n` +
174
- ` This gives crewx authority to allow/deny ALL tool calls.\n` +
175
- ` Target providers: ${providers.join(', ')}\n` +
176
- `${targets}\n`);
177
- process.stdout.write('Continue? [y/N] ');
178
- const answer = await new Promise((resolve) => {
179
- process.stdin.once('data', (data) => resolve(data.toString().trim().toLowerCase()));
180
- });
181
- if (answer !== 'y' && answer !== 'yes') {
182
- console.log('Aborted.');
183
- return;
184
- }
185
- }
186
- for (const config of configs) {
187
- installForProvider(projectRoot, config, crewxBin, true);
188
- }
189
- }
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.resolveCrewxBinary=m;exports.handleHookInstall=P;const u=require("fs");const w=require("@crewx/sdk");const i=require("./paths");const p=require("./command-marker");function y(e,n){return n.map(t=>({settingsPath:t==="claude"?(0,i.getClaudeSettingsPath)(e):(0,i.getCodexHooksPath)(e),provider:t,matcher:t==="claude"?"":"Bash",commandArg:`--provider ${t}`}))}function m(){const e=(0,w.resolveCrewxExecutable)();if(!e.ok){throw new Error((0,w.formatCrewxExecutableFailure)(e))}let n;try{n=(0,w.materializeCrewxStableEntrypoint)(e,{allowEnvStage:true})}catch(t){if(e.requiredEnv&&Object.keys(e.requiredEnv).length>0){throw new Error(`CrewX hook entrypoint could not preserve required environment: ${t instanceof Error?t.message:String(t)}`)}throw t}if(n){return(0,w.formatCrewxExecutableArgv)([n])}if(e.requiredEnv&&Object.keys(e.requiredEnv).length>0){throw new Error("CrewX hook entrypoint could not preserve required environment: stable entrypoint is not eligible for this executable")}return(0,w.formatCrewxExecutableArgv)(e.argv)}function $(e){return(0,i.readSettings)(e)}function E(e){if(!e)return-1;return e.findIndex(n=>n.hooks?.some(t=>p.CREWX_HOOK_COMMAND_RE.test(t.command)))}function b(e){if(!e.hooks)return void 0;const n=e.hooks.findIndex(t=>p.CREWX_HOOK_COMMAND_RE.test(t.command));if(n<0)return void 0;return{index:n,command:e.hooks[n].command}}function v(e,n,t,g){const{settingsPath:r,provider:c,matcher:x,commandArg:k}=n;const a=`${t} hook-dispatch ${k}`;const o=$(r);if(!o.hooks)o.hooks={};if(!o.hooks.PreToolUse)o.hooks.PreToolUse=[];const d=E(o.hooks.PreToolUse);if(d>=0){const s=o.hooks.PreToolUse[d];const l=b(s);if(l?.command===a){console.log(`[crewx] Hook already installed in ${r} (${c})`);return false}if(!g){console.log(`[crewx] Existing CrewX hook needs an install-path refresh in ${r} (${c})`);return false}if((0,u.existsSync)(r)){const f=r+".crewx-backup";(0,u.copyFileSync)(r,f);console.log(`[crewx] Backup created: ${f}`)}if(l){s.hooks[l.index]={...s.hooks[l.index],command:a}}(0,u.writeFileSync)(r,JSON.stringify(o,null,2)+"\n","utf8");console.log(`[crewx] Hook updated (${c}): ${a}`);console.log(`[crewx] Settings: ${r}`);return true}if(!g){console.log(`\u26A0\uFE0F crewx hook install will register crewx-hook-dispatch as a PreToolUse hook.
2
+ This gives crewx authority to allow/deny ALL ${c} tool calls.
3
+ ${r} will be patched (backup at ${r}.crewx-backup).
4
+ `);return false}if((0,u.existsSync)(r)){const s=r+".crewx-backup";(0,u.copyFileSync)(r,s);console.log(`[crewx] Backup created: ${s}`)}if(c==="claude"){(0,i.ensureClaudeSettings)(e)}else{(0,i.ensureCodexHooks)(e)}o.hooks.PreToolUse.push({matcher:x,hooks:[{type:"command",command:a}]});(0,u.writeFileSync)(r,JSON.stringify(o,null,2)+"\n","utf8");console.log(`[crewx] Hook installed (${c}): ${a}`);console.log(`[crewx] Settings: ${r}`);return true}async function P(e){if(!Array.isArray(e)){const{projectRoot:o,yes:d,provider:s}=e;const l=(0,i.providersFromFilter)(s??"all");let f;try{f=m()}catch(h){console.error(`[crewx] ${h instanceof Error?h.message:String(h)}`);return}const C=y(o,l);for(const h of C){v(o,h,f,d)}return}const n=e;const t=n.includes("--yes")||n.includes("-y");const g=process.cwd();const r=(0,i.findProjectRoot)(g);if(!r){console.error("[crewx] No crewx.yaml found in current or ancestor directories.");console.error("[crewx] Run this command from within a CrewX project.");process.exitCode=1;return}const c=(0,i.parseProviderArg)(n);const x=(0,i.providersFromFilter)(c);let k;try{k=m()}catch(o){console.error(`[crewx] ${o instanceof Error?o.message:String(o)}`);process.exitCode=1;return}const a=y(r,x);if(!t){const o=a.map(s=>` - ${s.provider}: ${s.settingsPath}`).join("\n");console.log(`\u26A0\uFE0F crewx hook install will register crewx-hook-dispatch as a PreToolUse hook.
5
+ This gives crewx authority to allow/deny ALL tool calls.
6
+ Target providers: ${x.join(", ")}
7
+ ${o}
8
+ `);process.stdout.write("Continue? [y/N] ");const d=await new Promise(s=>{process.stdin.once("data",l=>s(l.toString().trim().toLowerCase()))});if(d!=="y"&&d!=="yes"){console.log("Aborted.");return}}for(const o of a){v(r,o,k,true)}}