@crewx/cli 0.9.0-rc.82 → 0.9.0-rc.84

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.
@@ -0,0 +1,25 @@
1
+ import type { TraceContext } from '@crewx/sdk';
2
+ /** Mutable per-process guard shared by a handler and main()'s error boundary. */
3
+ export interface DelegationEmitState {
4
+ emitted: boolean;
5
+ }
6
+ /** The result fields needed to produce a delegation control line. */
7
+ export interface DelegationEmitOptions {
8
+ command?: string;
9
+ trace?: TraceContext;
10
+ taskId?: string;
11
+ agentId?: string;
12
+ isError: boolean;
13
+ state?: DelegationEmitState;
14
+ }
15
+ export declare function createDelegationEmitState(): DelegationEmitState;
16
+ /**
17
+ * Return true only for an inherited child invocation of q/query/x/execute.
18
+ * Root CLI calls and unrelated built-in commands must remain byte-compatible.
19
+ */
20
+ export declare function shouldEmitDelegationResult(command: string | undefined, trace?: TraceContext | undefined): boolean;
21
+ /**
22
+ * Write one machine-readable result line to stdout when this is a delegated call.
23
+ * The shared SDK formatter owns the wire syntax and validation rules.
24
+ */
25
+ export declare function emitDelegationResult(options: DelegationEmitOptions): boolean;
@@ -0,0 +1,33 @@
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
+ }
@@ -22,10 +22,11 @@
22
22
  * e.g. cat task.md | crewx x "@agent label"
23
23
  * Stdin is ignored when running in an interactive TTY.
24
24
  */
25
+ import { type DelegationEmitState } from './emit-trailer';
25
26
  /**
26
27
  * Handle `crewx execute <agentRef> <message>` command.
27
28
  *
28
29
  * Default output: raw agent response only (stdout).
29
30
  * --verbose: debug info written to stderr, response to stdout.
30
31
  */
31
- export declare function handleExecute(args: string[]): Promise<void>;
32
+ export declare function handleExecute(args: string[], command?: string, emitState?: DelegationEmitState): Promise<void>;
@@ -36,6 +36,7 @@ const resolve_prompt_1 = require("./resolve-prompt");
36
36
  const crewx_cli_1 = require("../bootstrap/crewx-cli");
37
37
  const inherited_trace_1 = require("../utils/inherited-trace");
38
38
  const write_output_1 = require("./write-output");
39
+ const emit_trailer_1 = require("./emit-trailer");
39
40
  /**
40
41
  * Split `--detach` out of argv, respecting the `--` literal-args sentinel
41
42
  * (a `--detach` appearing after `--` is message text, not the flag).
@@ -97,7 +98,7 @@ function runDetached(filteredArgs) {
97
98
  * Default output: raw agent response only (stdout).
98
99
  * --verbose: debug info written to stderr, response to stdout.
99
100
  */
100
- async function handleExecute(args) {
101
+ async function handleExecute(args, command = 'execute', emitState = (0, emit_trailer_1.createDelegationEmitState)()) {
101
102
  const { detach, rest: detachFilteredArgs } = extractDetachFlag(args);
102
103
  if (detach) {
103
104
  // Recursive-spawn guard: a CREWX_TRACE_ID already present means this
@@ -109,6 +110,7 @@ async function handleExecute(args) {
109
110
  }
110
111
  else if (process.platform === 'win32') {
111
112
  console.error('Error: --detach is not supported on win32.');
113
+ (0, emit_trailer_1.emitDelegationResult)({ command, isError: true, state: emitState });
112
114
  process.exit(1);
113
115
  return;
114
116
  }
@@ -117,12 +119,29 @@ async function handleExecute(args) {
117
119
  return;
118
120
  }
119
121
  }
120
- const { thread, provider, model, metadata, verbose, config, outputFormat, effort, promptFile, overdrive, vars, out, rest } = (0, parse_common_flags_1.parseCommonFlags)(detachFilteredArgs);
121
- const { agentRef: parsedAgentRef, message } = (0, parse_agent_message_1.parseAgentMessage)(rest);
122
- // No @mention → default to @crewx agent (matches cli-bak behaviour)
122
+ let parsedFlags;
123
+ try {
124
+ parsedFlags = (0, parse_common_flags_1.parseCommonFlags)(detachFilteredArgs);
125
+ }
126
+ catch (err) {
127
+ (0, emit_trailer_1.emitDelegationResult)({ command, isError: true, state: emitState });
128
+ throw err;
129
+ }
130
+ const { thread, provider, model, metadata, verbose, config, outputFormat, effort, promptFile, overdrive, vars, out, rest } = parsedFlags;
131
+ const inheritedTrace = (0, inherited_trace_1.readInheritedTrace)();
132
+ let parsedAgentRef;
133
+ let message;
134
+ let finalMessage;
135
+ try {
136
+ ({ agentRef: parsedAgentRef, message } = (0, parse_agent_message_1.parseAgentMessage)(rest));
137
+ // Resolve final prompt: argv | stdin pipe | --prompt-file (or combination)
138
+ finalMessage = await (0, resolve_prompt_1.resolvePrompt)(message, promptFile);
139
+ }
140
+ catch (err) {
141
+ (0, emit_trailer_1.emitDelegationResult)({ command, trace: inheritedTrace, isError: true, state: emitState });
142
+ throw err;
143
+ }
123
144
  const agentRef = parsedAgentRef || '@crewx';
124
- // Resolve final prompt: argv | stdin pipe | --prompt-file (or combination)
125
- const finalMessage = await (0, resolve_prompt_1.resolvePrompt)(message, promptFile);
126
145
  if (!finalMessage) {
127
146
  console.error('Usage: crewx execute [@agent] <task> [options]');
128
147
  console.error(' crewx x [@agent] <task> [options]');
@@ -151,12 +170,21 @@ async function handleExecute(args) {
151
170
  console.error(' -f/--prompt-file <path> Read task body from file');
152
171
  console.error(' --var key=value Template variable (repeatable)');
153
172
  console.error(' --overdrive Activate overdrive (boost) profile for this request');
173
+ (0, emit_trailer_1.emitDelegationResult)({ command, trace: inheritedTrace, isError: true, state: emitState });
154
174
  process.exit(1);
175
+ return;
155
176
  }
156
177
  const configPath = config ?? process.env.CREWX_CONFIG ?? 'crewx.yaml';
157
178
  // Only show exec audit span JSON in verbose mode
158
179
  (0, sdk_1.setAuditVerbose)(verbose);
159
- const crewx = await (0, crewx_cli_1.createCliCrewx)(configPath);
180
+ let crewx;
181
+ try {
182
+ crewx = await (0, crewx_cli_1.createCliCrewx)(configPath);
183
+ }
184
+ catch (err) {
185
+ (0, emit_trailer_1.emitDelegationResult)({ command, trace: inheritedTrace, isError: true, state: emitState });
186
+ throw err;
187
+ }
160
188
  // file:// remote agent delegation is handled transparently inside Crewx.query/execute.
161
189
  if (verbose) {
162
190
  process.stderr.write(`📋 Task: ${finalMessage}\n`);
@@ -182,9 +210,10 @@ async function handleExecute(args) {
182
210
  catch (err) {
183
211
  const msg = err instanceof Error ? err.message : String(err);
184
212
  process.stderr.write(`Error: ${msg}\n`);
213
+ (0, emit_trailer_1.emitDelegationResult)({ command, trace: inheritedTrace, isError: true, state: emitState });
185
214
  process.exit(2);
215
+ return;
186
216
  }
187
- const inheritedTrace = (0, inherited_trace_1.readInheritedTrace)();
188
217
  // A trace with a rootTraceId but no parentTaskId means the id was pre-assigned
189
218
  // to *this* task itself (the detach runner's parent injects only CREWX_TRACE_ID,
190
219
  // never CREWX_PARENT_TASK_ID — see execute.ts's runDetached), not inherited from
@@ -194,8 +223,9 @@ async function handleExecute(args) {
194
223
  ? (inheritedTrace.rootTraceId || undefined)
195
224
  : undefined;
196
225
  let exitCode = 0;
226
+ let result;
197
227
  try {
198
- const result = await crewx.execute(agentRef, finalMessage, {
228
+ result = await crewx.execute(agentRef, finalMessage, {
199
229
  provider,
200
230
  model,
201
231
  effort: effort || undefined,
@@ -235,8 +265,29 @@ async function handleExecute(args) {
235
265
  exitCode = 1;
236
266
  }
237
267
  finally {
238
- await crewx.close();
268
+ try {
269
+ await crewx.close();
270
+ }
271
+ catch (err) {
272
+ (0, emit_trailer_1.emitDelegationResult)({
273
+ command,
274
+ trace: inheritedTrace,
275
+ taskId: result?.meta.taskId,
276
+ agentId: result?.meta.agentId,
277
+ isError: true,
278
+ state: emitState,
279
+ });
280
+ throw err;
281
+ }
239
282
  }
283
+ (0, emit_trailer_1.emitDelegationResult)({
284
+ command,
285
+ trace: inheritedTrace,
286
+ taskId: result?.meta.taskId,
287
+ agentId: result?.meta.agentId,
288
+ isError: exitCode !== 0 || result?.ok === false,
289
+ state: emitState,
290
+ });
240
291
  if (exitCode !== 0)
241
292
  process.exit(exitCode);
242
293
  }
@@ -44,10 +44,11 @@ exports.handlePublish = handlePublish;
44
44
  * tar.gz packing lives in @crewx/sdk/publish (planPublish / packTemplate).
45
45
  * Submit+upload (WI-SHR-20260806-013) lives in the same package
46
46
  * (uploadToMarketplace) for the same reason — see that module's header.
47
- * This command only parses argv, forwards options, reads auth.json
48
- * (read-only see readAuthJson()'s own doc), and renders the result.
47
+ * This command only parses argv, forwards options, asks the SDK SessionManager
48
+ * for a valid account bearer when upload is requested, and renders the result.
49
49
  */
50
50
  const fs = __importStar(require("fs"));
51
+ const account_1 = require("@crewx/sdk/account");
51
52
  const publish_1 = require("@crewx/sdk/publish");
52
53
  const parse_common_flags_1 = require("./parse-common-flags");
53
54
  function parsePublishFlags(args) {
@@ -138,10 +139,26 @@ Notes:
138
139
  /** CREWX_MARKETPLACE_URL — same env var name as the server's MARKETPLACE_DISABLED check, never a second name. */
139
140
  function requireMarketplaceUrl() {
140
141
  const url = process.env['CREWX_MARKETPLACE_URL'];
141
- if (!url) {
142
+ if (!url?.trim()) {
142
143
  throw new Error('publish: [E_ENV_MISSING] CREWX_MARKETPLACE_URL is not set — this environment variable is required for upload');
143
144
  }
144
- return url;
145
+ return url.trim();
146
+ }
147
+ function isMarketplaceUnauthorized(err) {
148
+ return err instanceof Error
149
+ && err.message.includes('publish: [E_AUTH_EXPIRED]')
150
+ && /HTTP 401\b/.test(err.message);
151
+ }
152
+ async function uploadWithSessionRefresh(sessionManager, options, accessToken) {
153
+ try {
154
+ return await (0, publish_1.uploadToMarketplace)({ ...options, accessToken });
155
+ }
156
+ catch (err) {
157
+ if (!isMarketplaceUnauthorized(err))
158
+ throw err;
159
+ const refreshedSession = await sessionManager.refresh();
160
+ return (0, publish_1.uploadToMarketplace)({ ...options, accessToken: refreshedSession.access_token });
161
+ }
145
162
  }
146
163
  async function handlePublish(args) {
147
164
  const flags = parsePublishFlags(args);
@@ -198,10 +215,12 @@ async function handlePublish(args) {
198
215
  // workspace — WI-SHR-20260806-013 AC-U5.
199
216
  let marketplaceUrl = '';
200
217
  let accessToken = '';
218
+ let sessionManager;
201
219
  if (flags.upload) {
202
220
  try {
203
221
  marketplaceUrl = requireMarketplaceUrl();
204
- accessToken = (0, publish_1.readAuthJson)().access_token;
222
+ sessionManager = new account_1.SessionManager({ authClient: new account_1.AuthClient() });
223
+ accessToken = await sessionManager.getAccessToken();
205
224
  }
206
225
  catch (err) {
207
226
  if (err instanceof Error && !err.message.startsWith('publish: [')) {
@@ -224,12 +243,13 @@ async function handlePublish(args) {
224
243
  if (flags.upload) {
225
244
  process.stderr.write(`[publish] uploading ${packed.manifest.name}@${packed.manifest.version} to ${marketplaceUrl}...\n`);
226
245
  try {
227
- uploadResult = await (0, publish_1.uploadToMarketplace)({
246
+ if (!sessionManager)
247
+ throw new Error('publish: [E_AUTH_EXPIRED] Account session is unavailable');
248
+ uploadResult = await uploadWithSessionRefresh(sessionManager, {
228
249
  tgzPath: packed.tgzPath,
229
250
  manifest: packed.manifest,
230
251
  baseUrl: marketplaceUrl,
231
- accessToken,
232
- });
252
+ }, accessToken);
233
253
  }
234
254
  catch (err) {
235
255
  failWithError(err, flags.json);
@@ -19,10 +19,11 @@
19
19
  * e.g. cat brief.md | crewx q "@agent label"
20
20
  * Stdin is ignored when running in an interactive TTY.
21
21
  */
22
+ import { type DelegationEmitState } from './emit-trailer';
22
23
  /**
23
24
  * Handle `crewx query <agentRef> <message>` command.
24
25
  *
25
26
  * Default output: raw agent response only (stdout).
26
27
  * --verbose: debug info written to stderr, response to stdout.
27
28
  */
28
- export declare function handleQuery(args: string[]): Promise<void>;
29
+ export declare function handleQuery(args: string[], command?: string, emitState?: DelegationEmitState): Promise<void>;
@@ -29,19 +29,37 @@ const resolve_prompt_1 = require("./resolve-prompt");
29
29
  const crewx_cli_1 = require("../bootstrap/crewx-cli");
30
30
  const inherited_trace_1 = require("../utils/inherited-trace");
31
31
  const write_output_1 = require("./write-output");
32
+ const emit_trailer_1 = require("./emit-trailer");
32
33
  /**
33
34
  * Handle `crewx query <agentRef> <message>` command.
34
35
  *
35
36
  * Default output: raw agent response only (stdout).
36
37
  * --verbose: debug info written to stderr, response to stdout.
37
38
  */
38
- async function handleQuery(args) {
39
- const { thread, provider, model, metadata, verbose, config, outputFormat, effort, promptFile, overdrive, vars, out, rest } = (0, parse_common_flags_1.parseCommonFlags)(args);
40
- const { agentRef: parsedAgentRef, message } = (0, parse_agent_message_1.parseAgentMessage)(rest);
41
- // No @mention → default to @crewx agent (matches cli-bak behaviour)
39
+ async function handleQuery(args, command = 'query', emitState = (0, emit_trailer_1.createDelegationEmitState)()) {
40
+ let parsedFlags;
41
+ try {
42
+ parsedFlags = (0, parse_common_flags_1.parseCommonFlags)(args);
43
+ }
44
+ catch (err) {
45
+ (0, emit_trailer_1.emitDelegationResult)({ command, isError: true, state: emitState });
46
+ throw err;
47
+ }
48
+ const { thread, provider, model, metadata, verbose, config, outputFormat, effort, promptFile, overdrive, vars, out, rest } = parsedFlags;
49
+ const inheritedTrace = (0, inherited_trace_1.readInheritedTrace)();
50
+ let parsedAgentRef;
51
+ let message;
52
+ let finalMessage;
53
+ try {
54
+ ({ agentRef: parsedAgentRef, message } = (0, parse_agent_message_1.parseAgentMessage)(rest));
55
+ // Resolve final prompt: argv | stdin pipe | --prompt-file (or combination)
56
+ finalMessage = await (0, resolve_prompt_1.resolvePrompt)(message, promptFile);
57
+ }
58
+ catch (err) {
59
+ (0, emit_trailer_1.emitDelegationResult)({ command, trace: inheritedTrace, isError: true, state: emitState });
60
+ throw err;
61
+ }
42
62
  const agentRef = parsedAgentRef || '@crewx';
43
- // Resolve final prompt: argv | stdin pipe | --prompt-file (or combination)
44
- const finalMessage = await (0, resolve_prompt_1.resolvePrompt)(message, promptFile);
45
63
  if (!finalMessage) {
46
64
  console.error('Usage: crewx query [@agent] <message> [options]');
47
65
  console.error(' crewx q [@agent] <message> [options]');
@@ -70,12 +88,21 @@ async function handleQuery(args) {
70
88
  console.error(' -f/--prompt-file <path> Read prompt body from file');
71
89
  console.error(' --var key=value Template variable (repeatable)');
72
90
  console.error(' --overdrive Activate overdrive (boost) profile for this request');
91
+ (0, emit_trailer_1.emitDelegationResult)({ command, trace: inheritedTrace, isError: true, state: emitState });
73
92
  process.exit(1);
93
+ return;
74
94
  }
75
95
  const configPath = config ?? process.env.CREWX_CONFIG ?? 'crewx.yaml';
76
96
  // Only show exec audit span JSON in verbose mode
77
97
  (0, sdk_1.setAuditVerbose)(verbose);
78
- const crewx = await (0, crewx_cli_1.createCliCrewx)(configPath);
98
+ let crewx;
99
+ try {
100
+ crewx = await (0, crewx_cli_1.createCliCrewx)(configPath);
101
+ }
102
+ catch (err) {
103
+ (0, emit_trailer_1.emitDelegationResult)({ command, trace: inheritedTrace, isError: true, state: emitState });
104
+ throw err;
105
+ }
79
106
  // file:// remote agent delegation is handled transparently inside Crewx.query/execute.
80
107
  if (verbose) {
81
108
  process.stderr.write(`📋 Task: ${finalMessage}\n`);
@@ -101,11 +128,14 @@ async function handleQuery(args) {
101
128
  catch (err) {
102
129
  const msg = err instanceof Error ? err.message : String(err);
103
130
  process.stderr.write(`Error: ${msg}\n`);
131
+ (0, emit_trailer_1.emitDelegationResult)({ command, trace: inheritedTrace, isError: true, state: emitState });
104
132
  process.exit(2);
133
+ return;
105
134
  }
106
135
  let exitCode = 0;
136
+ let result;
107
137
  try {
108
- const result = await crewx.query(agentRef, finalMessage, {
138
+ result = await crewx.query(agentRef, finalMessage, {
109
139
  provider,
110
140
  model,
111
141
  effort: effort || undefined,
@@ -113,7 +143,7 @@ async function handleQuery(args) {
113
143
  threadId: thread,
114
144
  metadata: Object.keys(parsedMetadata).length > 0 ? parsedMetadata : undefined,
115
145
  vars: Object.keys(vars).length > 0 ? vars : undefined,
116
- trace: (0, inherited_trace_1.readInheritedTrace)(),
146
+ trace: inheritedTrace,
117
147
  });
118
148
  if (!result.ok) {
119
149
  const errMsg = result.error?.message ?? 'Query failed';
@@ -144,8 +174,29 @@ async function handleQuery(args) {
144
174
  exitCode = 1;
145
175
  }
146
176
  finally {
147
- await crewx.close();
177
+ try {
178
+ await crewx.close();
179
+ }
180
+ catch (err) {
181
+ (0, emit_trailer_1.emitDelegationResult)({
182
+ command,
183
+ trace: inheritedTrace,
184
+ taskId: result?.meta.taskId,
185
+ agentId: result?.meta.agentId,
186
+ isError: true,
187
+ state: emitState,
188
+ });
189
+ throw err;
190
+ }
148
191
  }
192
+ (0, emit_trailer_1.emitDelegationResult)({
193
+ command,
194
+ trace: inheritedTrace,
195
+ taskId: result?.meta.taskId,
196
+ agentId: result?.meta.agentId,
197
+ isError: exitCode !== 0 || result?.ok === false,
198
+ state: emitState,
199
+ });
149
200
  if (exitCode !== 0)
150
201
  process.exit(exitCode);
151
202
  }
package/dist/main.js CHANGED
@@ -84,6 +84,7 @@ const db_1 = require("./commands/db");
84
84
  const parse_common_flags_1 = require("./commands/parse-common-flags");
85
85
  const registry_1 = require("./commands/registry");
86
86
  const version_1 = require("./utils/version");
87
+ const emit_trailer_1 = require("./commands/emit-trailer");
87
88
  /**
88
89
  * Dev-only SSOT assertion: bin/cli-commands.js must be the exact union of
89
90
  * KNOWN_COMMANDS ∪ BUILTIN_COMMAND_NAMES ∪ NOT_YET_MIGRATED from registry.ts.
@@ -108,7 +109,7 @@ async function assertSsotParity() {
108
109
  (extra.length ? ` CLI_SUBCOMMANDS has, registry missing: ${extra.join(', ')}` : ''));
109
110
  }
110
111
  }
111
- async function main() {
112
+ async function main(emitState) {
112
113
  if (process.env['NODE_ENV'] === 'development') {
113
114
  await assertSsotParity();
114
115
  }
@@ -128,11 +129,11 @@ async function main() {
128
129
  // P0-2: q/x aliases
129
130
  case 'q':
130
131
  case 'query':
131
- await (0, query_1.handleQuery)(args.slice(1));
132
+ await (0, query_1.handleQuery)(args.slice(1), command, emitState);
132
133
  return;
133
134
  case 'x':
134
135
  case 'execute':
135
- await (0, execute_1.handleExecute)(args.slice(1));
136
+ await (0, execute_1.handleExecute)(args.slice(1), command, emitState);
136
137
  return;
137
138
  case 'agent':
138
139
  await (0, agent_1.handleAgent)(args.slice(1));
@@ -194,7 +195,7 @@ async function main() {
194
195
  case 'shortcut':
195
196
  await (0, shortcut_1.handleShortcut)(args.slice(1));
196
197
  return;
197
- // WI-20260803-004: crewx publish [dir] [--dry-run] [--version <semver>] [--json]
198
+ // crewx publish [dir] [--dry-run] [--version <semver>] [--json] [--upload]
198
199
  case 'publish':
199
200
  await (0, publish_1.handlePublish)(args.slice(1));
200
201
  return;
@@ -332,7 +333,7 @@ Publish:
332
333
  --dry-run Scan + build manifest only; do not write a .tgz
333
334
  --version <ver> Override manifest version (semver)
334
335
  --json Print machine-readable JSON to stdout
335
- (marketplace upload is not yet supported by this command)
336
+ --upload Submit + upload using the SDK account session
336
337
 
337
338
  Built-in Tools:
338
339
  memory <args> Memory tool
@@ -354,7 +355,9 @@ Global Options:
354
355
  --version, -v Show version
355
356
  `.trim());
356
357
  }
357
- main().catch((err) => {
358
+ const emitState = (0, emit_trailer_1.createDelegationEmitState)();
359
+ main(emitState).catch((err) => {
358
360
  console.error(err instanceof Error ? err.message : String(err));
361
+ (0, emit_trailer_1.emitDelegationResult)({ command: process.argv[2], isError: true, state: emitState });
359
362
  process.exit(err instanceof parse_common_flags_1.UnknownOptionError ? 2 : 1);
360
363
  });
@@ -1,11 +1,14 @@
1
+ import type { CrewxExecutableResolution } from '@crewx/sdk';
1
2
  type PricingInitializer = () => Promise<unknown> | unknown;
2
3
  export interface SdkLike {
3
4
  resolveCrewxCli?: () => string;
5
+ resolveCrewxCliArgv?: () => CrewxExecutableResolution;
4
6
  resolveCrewxWorkspace?: () => string;
5
7
  initPricingRemote?: PricingInitializer;
6
8
  }
7
9
  export interface SdkCompat {
8
10
  resolveCrewxCli(): string;
11
+ resolveCrewxCliArgv(): CrewxExecutableResolution;
9
12
  resolveCrewxWorkspace(): string;
10
13
  initPricingRemote(): void;
11
14
  }
@@ -36,6 +36,38 @@ Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.sdkCompat = void 0;
37
37
  exports.createSdkCompat = createSdkCompat;
38
38
  const sdk = __importStar(require("@crewx/sdk"));
39
+ function formatLegacyArgv(argv) {
40
+ const formatter = sdk.formatCrewxExecutableArgv;
41
+ if (typeof formatter === 'function')
42
+ return formatter(argv);
43
+ // Older SDKs may expose the argv resolver before exposing its formatter.
44
+ // Keep this compatibility-only fallback one-way and quote every token.
45
+ if (process.platform === 'win32') {
46
+ return argv
47
+ .map((value) => {
48
+ const escaped = value
49
+ .replace(/(\\*)"/g, '$1$1\\"')
50
+ .replace(/(\\+)$/g, '$1$1');
51
+ return `"${escaped}"`;
52
+ })
53
+ .join(' ');
54
+ }
55
+ return argv.map((value) => `'${value.replace(/'/g, `'\\''`)}'`).join(' ');
56
+ }
57
+ const FALLBACK_CREWX_CLI_DISPLAY = 'crewx';
58
+ function missingCliResolver() {
59
+ return {
60
+ ok: false,
61
+ reason: 'The installed SDK does not expose the argv-based CrewX CLI resolver.',
62
+ attempts: [
63
+ { stage: 'env', reason: 'argv resolver capability is unavailable' },
64
+ { stage: 'self', reason: 'argv resolver capability is unavailable' },
65
+ { stage: 'workspace', reason: 'argv resolver capability is unavailable' },
66
+ { stage: 'module', reason: 'argv resolver capability is unavailable' },
67
+ { stage: 'path', reason: 'argv resolver capability is unavailable' },
68
+ ],
69
+ };
70
+ }
39
71
  /**
40
72
  * Create the CLI bootstrap capability accessor for the installed SDK.
41
73
  *
@@ -46,10 +78,26 @@ const sdk = __importStar(require("@crewx/sdk"));
46
78
  function createSdkCompat(sdkLike = sdk) {
47
79
  return {
48
80
  resolveCrewxCli: () => {
81
+ const configured = process.env.CREWX_CLI;
82
+ if (configured?.trim())
83
+ return configured;
84
+ if (typeof sdkLike.resolveCrewxCliArgv === 'function') {
85
+ const resolution = sdkLike.resolveCrewxCliArgv();
86
+ if (resolution.ok)
87
+ return formatLegacyArgv(resolution.argv);
88
+ }
49
89
  if (typeof sdkLike.resolveCrewxCli === 'function') {
50
- return sdkLike.resolveCrewxCli();
90
+ const value = sdkLike.resolveCrewxCli();
91
+ if (value.trim())
92
+ return value;
93
+ }
94
+ return FALLBACK_CREWX_CLI_DISPLAY;
95
+ },
96
+ resolveCrewxCliArgv: () => {
97
+ if (typeof sdkLike.resolveCrewxCliArgv === 'function') {
98
+ return sdkLike.resolveCrewxCliArgv();
51
99
  }
52
- return process.env.CREWX_CLI || 'npx crewx';
100
+ return missingCliResolver();
53
101
  },
54
102
  resolveCrewxWorkspace: () => {
55
103
  if (typeof sdkLike.resolveCrewxWorkspace === 'function') {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crewx/cli",
3
- "version": "0.9.0-rc.82",
3
+ "version": "0.9.0-rc.84",
4
4
  "license": "UNLICENSED",
5
5
  "engines": {
6
6
  "node": ">=20.19.0"
@@ -25,18 +25,18 @@
25
25
  "better-sqlite3": "*",
26
26
  "dotenv": "17.2.3",
27
27
  "isomorphic-git": "1.37.1",
28
- "@crewx/sdk": "0.9.0-rc.82",
29
- "@crewx/memory": "0.1.23-rc.99",
30
- "@crewx/search": "0.1.10-rc.78",
31
- "@crewx/doc": "0.1.9-rc.75",
32
- "@crewx/wbs": "0.1.10-rc.108",
33
- "@crewx/cron": "0.1.10-rc.117",
28
+ "@crewx/memory": "0.1.23-rc.101",
29
+ "@crewx/sdk": "0.9.0-rc.84",
30
+ "@crewx/search": "0.1.10-rc.80",
31
+ "@crewx/wbs": "0.1.10-rc.110",
32
+ "@crewx/doc": "0.1.9-rc.77",
33
+ "@crewx/cron": "0.1.10-rc.119",
34
+ "@crewx/wi": "0.1.10-rc.104",
34
35
  "@crewx/skill": "0.1.20",
35
- "@crewx/workflow": "0.3.22-rc.128",
36
- "@crewx/shared": "0.0.6",
37
- "@crewx/wi": "0.1.10-rc.102",
38
- "@crewx/notify": "0.1.0-rc.53",
39
- "@crewx/chromex": "0.1.0-rc.115"
36
+ "@crewx/chromex": "0.1.0-rc.117",
37
+ "@crewx/notify": "0.1.0-rc.55",
38
+ "@crewx/workflow": "0.3.22-rc.130",
39
+ "@crewx/shared": "0.0.6"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@types/better-sqlite3": "*",