@crewx/cli 0.9.0-rc.47 → 0.9.0-rc.49

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 @@
1
+ export declare function handlePublish(args: string[]): Promise<void>;
@@ -0,0 +1,267 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.handlePublish = handlePublish;
37
+ /**
38
+ * crewx publish handler — thin CLI wrapper over @crewx/sdk/publish.
39
+ *
40
+ * Usage:
41
+ * crewx publish [dir] [--dry-run] [--version <semver>] [--json] [--upload]
42
+ *
43
+ * All scanning, exclusion-rule judgment, secret detection, hashing, and
44
+ * tar.gz packing lives in @crewx/sdk/publish (planPublish / packTemplate).
45
+ * Submit+upload (WI-SHR-20260806-013) lives in the same package
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.
49
+ */
50
+ const fs = __importStar(require("fs"));
51
+ const publish_1 = require("@crewx/sdk/publish");
52
+ const parse_common_flags_1 = require("./parse-common-flags");
53
+ function parsePublishFlags(args) {
54
+ const flags = { dryRun: false, json: false, help: false, upload: false };
55
+ for (let i = 0; i < args.length; i++) {
56
+ const arg = args[i];
57
+ if (arg === '--help' || arg === '-h') {
58
+ flags.help = true;
59
+ continue;
60
+ }
61
+ if (arg === '--dry-run') {
62
+ flags.dryRun = true;
63
+ continue;
64
+ }
65
+ if (arg === '--json') {
66
+ flags.json = true;
67
+ continue;
68
+ }
69
+ if (arg === '--upload') {
70
+ flags.upload = true;
71
+ continue;
72
+ }
73
+ if (arg === '--version') {
74
+ const value = args[i + 1];
75
+ if (value === undefined)
76
+ throw new parse_common_flags_1.UnknownOptionError('--version requires a value');
77
+ flags.version = value;
78
+ i++;
79
+ continue;
80
+ }
81
+ if (arg.startsWith('--version=')) {
82
+ flags.version = arg.slice('--version='.length);
83
+ continue;
84
+ }
85
+ if (arg.startsWith('-')) {
86
+ throw new parse_common_flags_1.UnknownOptionError(`Unknown option: ${arg}`);
87
+ }
88
+ if (flags.dir === undefined) {
89
+ flags.dir = arg;
90
+ continue;
91
+ }
92
+ throw new parse_common_flags_1.UnknownOptionError(`Unknown option: ${arg}`);
93
+ }
94
+ return flags;
95
+ }
96
+ function resolveWorkspaceDir(flags) {
97
+ return flags.dir ?? process.env['CREWX_WORKSPACE'] ?? process.cwd();
98
+ }
99
+ function printJson(payload) {
100
+ console.log(JSON.stringify(payload));
101
+ }
102
+ /** Prints the error and exits 1. Never returns (matches `process.exit`'s `never` type). */
103
+ function failWithError(err, json) {
104
+ const message = err instanceof Error ? err.message : String(err);
105
+ if (json) {
106
+ printJson({ success: false, error: message });
107
+ }
108
+ else {
109
+ console.error(`✗ ${message}`);
110
+ }
111
+ process.exit(1);
112
+ }
113
+ function printHelp() {
114
+ console.log(`
115
+ crewx publish — package a workspace as a distributable template archive
116
+
117
+ Usage:
118
+ crewx publish [dir] [--dry-run] [--version <semver>] [--json] [--upload]
119
+
120
+ Arguments:
121
+ dir Workspace to publish (default: $CREWX_WORKSPACE or cwd)
122
+
123
+ Options:
124
+ --dry-run Scan + build manifest only; do not write a .tgz
125
+ --version <ver> Override manifest version (semver, e.g. 1.0.0)
126
+ --json Print machine-readable JSON to stdout
127
+ --upload Submit + upload the packed archive to marketplace
128
+ (requires CREWX_MARKETPLACE_URL and a prior login;
129
+ ignored when combined with --dry-run)
130
+ --help, -h Show this help
131
+
132
+ Notes:
133
+ Without --upload, this command only scans the workspace, applies
134
+ exclusion rules, checks for secrets, and packs a local
135
+ .crewx/publish/<name>-<version>.tgz archive.
136
+ `.trim());
137
+ }
138
+ /** CREWX_MARKETPLACE_URL — same env var name as the server's MARKETPLACE_DISABLED check, never a second name. */
139
+ function requireMarketplaceUrl() {
140
+ const url = process.env['CREWX_MARKETPLACE_URL'];
141
+ if (!url) {
142
+ throw new Error('CREWX_MARKETPLACE_URL이 설정되지 않았습니다 — 업로드하려면 이 환경변수가 필요합니다');
143
+ }
144
+ return url;
145
+ }
146
+ async function handlePublish(args) {
147
+ const flags = parsePublishFlags(args);
148
+ if (flags.help) {
149
+ printHelp();
150
+ return;
151
+ }
152
+ const dir = resolveWorkspaceDir(flags);
153
+ process.stderr.write(`[publish] scanning ${dir}...\n`);
154
+ let plan;
155
+ try {
156
+ plan = await (0, publish_1.planPublish)(dir, { version: flags.version });
157
+ }
158
+ catch (err) {
159
+ failWithError(err, flags.json);
160
+ }
161
+ if (plan.secretFindings.length > 0) {
162
+ if (flags.json) {
163
+ printJson({ success: false, error: 'secret findings detected', findings: plan.secretFindings });
164
+ }
165
+ else {
166
+ console.error('✗ secret findings detected — publish aborted');
167
+ for (const f of plan.secretFindings) {
168
+ console.error(` ${f.path}:${f.line} (${f.rule})`);
169
+ }
170
+ }
171
+ process.exit(1);
172
+ }
173
+ if (flags.dryRun) {
174
+ if (flags.json) {
175
+ printJson({
176
+ success: true,
177
+ dryRun: true,
178
+ workspace: dir,
179
+ manifest: plan.manifest,
180
+ included: plan.included,
181
+ excluded: plan.excluded,
182
+ });
183
+ }
184
+ else {
185
+ console.log('✓ dry-run — no archive written');
186
+ console.log(` workspace: ${dir}`);
187
+ console.log(` name: ${plan.manifest.name} version: ${plan.manifest.version}`);
188
+ console.log(` included: ${plan.included.length} files`);
189
+ console.log(` excluded: ${plan.excluded.length} entries`);
190
+ for (const e of plan.excluded) {
191
+ console.log(` ${e.path} (${e.rule})`);
192
+ }
193
+ }
194
+ return;
195
+ }
196
+ // Resolved before packing (not after) so a doomed --upload run (no
197
+ // marketplace url / no session) never writes a stray .tgz to the
198
+ // workspace — WI-SHR-20260806-013 AC-U5.
199
+ let marketplaceUrl = '';
200
+ let accessToken = '';
201
+ if (flags.upload) {
202
+ try {
203
+ marketplaceUrl = requireMarketplaceUrl();
204
+ accessToken = (0, publish_1.readAuthJson)().access_token;
205
+ }
206
+ catch (err) {
207
+ failWithError(err, flags.json);
208
+ }
209
+ }
210
+ process.stderr.write(`[publish] packing ${plan.manifest.name}@${plan.manifest.version}...\n`);
211
+ let packed;
212
+ try {
213
+ packed = await (0, publish_1.packTemplate)(dir, { version: flags.version });
214
+ }
215
+ catch (err) {
216
+ failWithError(err, flags.json);
217
+ }
218
+ const fileCount = packed.manifest.files.length;
219
+ const totalBytes = fs.statSync(packed.tgzPath).size;
220
+ let uploadResult;
221
+ if (flags.upload) {
222
+ process.stderr.write(`[publish] uploading ${packed.manifest.name}@${packed.manifest.version} to ${marketplaceUrl}...\n`);
223
+ try {
224
+ uploadResult = await (0, publish_1.uploadToMarketplace)({
225
+ tgzPath: packed.tgzPath,
226
+ manifest: packed.manifest,
227
+ baseUrl: marketplaceUrl,
228
+ accessToken,
229
+ });
230
+ }
231
+ catch (err) {
232
+ failWithError(err, flags.json);
233
+ }
234
+ process.stderr.write(`[publish] submit -> ${uploadResult.submitOutcome}\n`);
235
+ }
236
+ if (flags.json) {
237
+ printJson({
238
+ success: true,
239
+ tgzPath: packed.tgzPath,
240
+ fileCount,
241
+ totalBytes,
242
+ manifest: packed.manifest,
243
+ ...(uploadResult
244
+ ? {
245
+ slug: uploadResult.slug,
246
+ version: uploadResult.version,
247
+ artifactChecksum: uploadResult.artifactChecksum,
248
+ artifactSizeBytes: uploadResult.artifactSizeBytes,
249
+ submitOutcome: uploadResult.submitOutcome,
250
+ versionUpdate: uploadResult.versionUpdate,
251
+ serverVersionBefore: uploadResult.serverVersionBefore,
252
+ }
253
+ : {}),
254
+ });
255
+ }
256
+ else {
257
+ console.log(`✓ packed: ${packed.tgzPath}`);
258
+ console.log(` files: ${fileCount} bytes: ${totalBytes}`);
259
+ if (uploadResult) {
260
+ console.log(`✓ uploaded: ${uploadResult.slug}@${uploadResult.version} (${uploadResult.submitOutcome})`);
261
+ console.log(` artifactChecksum: ${uploadResult.artifactChecksum} artifactSizeBytes: ${uploadResult.artifactSizeBytes}`);
262
+ }
263
+ }
264
+ if (!flags.upload) {
265
+ console.error('⚠ 업로드하려면 --upload 를 사용하세요 — 생성된 파일 경로를 확인하세요');
266
+ }
267
+ }
@@ -18,6 +18,7 @@ exports.KNOWN_COMMANDS = new Set([
18
18
  'db',
19
19
  'help',
20
20
  'shortcut',
21
+ 'publish',
21
22
  'slack', 'slack:files',
22
23
  'hook', 'hook-dispatch',
23
24
  ]);
package/dist/main.js CHANGED
@@ -46,12 +46,11 @@ var __importStar = (this && this.__importStar) || (function () {
46
46
  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
- const env_defaults_1 = require("./utils/env-defaults");
50
- const sdk_1 = require("@crewx/sdk");
49
+ const sdk_compat_1 = require("./utils/sdk-compat");
51
50
  const dotenv = __importStar(require("dotenv"));
52
51
  const path_1 = require("path");
53
- process.env.CREWX_CLI ??= (0, env_defaults_1.resolveCrewxCli)();
54
- process.env.CREWX_WORKSPACE ??= (0, env_defaults_1.resolveCrewxWorkspace)();
52
+ process.env.CREWX_CLI ??= sdk_compat_1.sdkCompat.resolveCrewxCli();
53
+ process.env.CREWX_WORKSPACE ??= sdk_compat_1.sdkCompat.resolveCrewxWorkspace();
55
54
  // Load the workspace .env (WI-20260725-010): keeps CLI (crewx q/x) in parity with
56
55
  // the server's ConfigModule, which already reads cwd/.env. override:false so a
57
56
  // value already present in the shell/environment always wins over the file.
@@ -61,7 +60,7 @@ dotenv.config({ path: (0, path_1.join)(process.env.CREWX_WORKSPACE, '.env'), ove
61
60
  // Best-effort, non-blocking: fetch remote model registry so new models get
62
61
  // accurate pricing without a CLI republish. Falls back to bundled table on
63
62
  // failure / offline. Browser entry does not call this automatically.
64
- void (0, sdk_1.initPricingRemote)();
63
+ sdk_compat_1.sdkCompat.initPricingRemote();
65
64
  // ─── Command Imports ──────────────────────────────────────────────────────────
66
65
  const query_1 = require("./commands/query");
67
66
  const execute_1 = require("./commands/execute");
@@ -74,6 +73,7 @@ const log_1 = require("./commands/log");
74
73
  const doctor_1 = require("./commands/doctor");
75
74
  const init_1 = require("./commands/init");
76
75
  const shortcut_1 = require("./commands/shortcut");
76
+ const publish_1 = require("./commands/publish");
77
77
  const builtin_1 = require("./builtin");
78
78
  const slack_1 = require("./commands/slack");
79
79
  const install_1 = require("./commands/hook/install");
@@ -194,6 +194,10 @@ async function main() {
194
194
  case 'shortcut':
195
195
  await (0, shortcut_1.handleShortcut)(args.slice(1));
196
196
  return;
197
+ // WI-20260803-004: crewx publish [dir] [--dry-run] [--version <semver>] [--json]
198
+ case 'publish':
199
+ await (0, publish_1.handlePublish)(args.slice(1));
200
+ return;
197
201
  // SDK-009: slack / slack:files
198
202
  case 'slack':
199
203
  case 'slack:files':
@@ -319,6 +323,13 @@ Desktop Shortcut (Windows only):
319
323
  shortcut install [--force] [--json] Install/repair the Desktop shortcut
320
324
  shortcut uninstall [--json] Remove the Desktop shortcut
321
325
 
326
+ Publish:
327
+ publish [dir] [options] Package a workspace as a distributable template archive
328
+ --dry-run Scan + build manifest only; do not write a .tgz
329
+ --version <ver> Override manifest version (semver)
330
+ --json Print machine-readable JSON to stdout
331
+ (marketplace upload is not yet supported by this command)
332
+
322
333
  Built-in Tools:
323
334
  memory <args> Memory tool
324
335
  search <args> Search tool
@@ -1,5 +1,2 @@
1
- /**
2
- * CREWX_* environment variable defaults for CLI bootstrap.
3
- * Re-exported from @crewx/sdk for convenience.
4
- */
5
- export { resolveCrewxCli, resolveCrewxWorkspace } from '@crewx/sdk';
1
+ export declare function resolveCrewxCli(): string;
2
+ export declare function resolveCrewxWorkspace(): string;
@@ -1,10 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.resolveCrewxWorkspace = exports.resolveCrewxCli = void 0;
3
+ exports.resolveCrewxCli = resolveCrewxCli;
4
+ exports.resolveCrewxWorkspace = resolveCrewxWorkspace;
4
5
  /**
5
6
  * CREWX_* environment variable defaults for CLI bootstrap.
6
- * Re-exported from @crewx/sdk for convenience.
7
+ * Routed through the SDK compatibility accessor for older SDK installations.
7
8
  */
8
- var sdk_1 = require("@crewx/sdk");
9
- Object.defineProperty(exports, "resolveCrewxCli", { enumerable: true, get: function () { return sdk_1.resolveCrewxCli; } });
10
- Object.defineProperty(exports, "resolveCrewxWorkspace", { enumerable: true, get: function () { return sdk_1.resolveCrewxWorkspace; } });
9
+ const sdk_compat_1 = require("./sdk-compat");
10
+ function resolveCrewxCli() {
11
+ return sdk_compat_1.sdkCompat.resolveCrewxCli();
12
+ }
13
+ function resolveCrewxWorkspace() {
14
+ return sdk_compat_1.sdkCompat.resolveCrewxWorkspace();
15
+ }
@@ -0,0 +1,21 @@
1
+ type PricingInitializer = () => Promise<unknown> | unknown;
2
+ export interface SdkLike {
3
+ resolveCrewxCli?: () => string;
4
+ resolveCrewxWorkspace?: () => string;
5
+ initPricingRemote?: PricingInitializer;
6
+ }
7
+ export interface SdkCompat {
8
+ resolveCrewxCli(): string;
9
+ resolveCrewxWorkspace(): string;
10
+ initPricingRemote(): void;
11
+ }
12
+ /**
13
+ * Create the CLI bootstrap capability accessor for the installed SDK.
14
+ *
15
+ * SDK exports are additive across compatible majors, so an older SDK may not
16
+ * expose every capability that a newer CLI knows about. Optional capabilities
17
+ * are checked here rather than at each bootstrap call site.
18
+ */
19
+ export declare function createSdkCompat(sdkLike?: SdkLike): SdkCompat;
20
+ export declare const sdkCompat: SdkCompat;
21
+ export {};
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.sdkCompat = void 0;
37
+ exports.createSdkCompat = createSdkCompat;
38
+ const sdk = __importStar(require("@crewx/sdk"));
39
+ /**
40
+ * Create the CLI bootstrap capability accessor for the installed SDK.
41
+ *
42
+ * SDK exports are additive across compatible majors, so an older SDK may not
43
+ * expose every capability that a newer CLI knows about. Optional capabilities
44
+ * are checked here rather than at each bootstrap call site.
45
+ */
46
+ function createSdkCompat(sdkLike = sdk) {
47
+ return {
48
+ resolveCrewxCli: () => {
49
+ if (typeof sdkLike.resolveCrewxCli === 'function') {
50
+ return sdkLike.resolveCrewxCli();
51
+ }
52
+ return process.env.CREWX_CLI || 'npx crewx';
53
+ },
54
+ resolveCrewxWorkspace: () => {
55
+ if (typeof sdkLike.resolveCrewxWorkspace === 'function') {
56
+ return sdkLike.resolveCrewxWorkspace();
57
+ }
58
+ return process.env.CREWX_WORKSPACE || process.cwd();
59
+ },
60
+ initPricingRemote: () => {
61
+ if (typeof sdkLike.initPricingRemote !== 'function')
62
+ return;
63
+ try {
64
+ void Promise.resolve(sdkLike.initPricingRemote()).catch(() => undefined);
65
+ }
66
+ catch {
67
+ // Remote pricing is optional and must not block CLI startup.
68
+ }
69
+ },
70
+ };
71
+ }
72
+ exports.sdkCompat = createSdkCompat();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crewx/cli",
3
- "version": "0.9.0-rc.47",
3
+ "version": "0.9.0-rc.49",
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/doc": "0.1.9-rc.39",
29
- "@crewx/cron": "0.1.10-rc.81",
30
- "@crewx/workflow": "0.3.22-rc.93",
31
- "@crewx/search": "0.1.10-rc.42",
32
- "@crewx/memory": "0.1.23-rc.63",
28
+ "@crewx/sdk": "0.9.0-rc.49",
29
+ "@crewx/memory": "0.1.23-rc.65",
30
+ "@crewx/doc": "0.1.9-rc.41",
31
+ "@crewx/search": "0.1.10-rc.44",
32
+ "@crewx/wbs": "0.1.10-rc.74",
33
+ "@crewx/cron": "0.1.10-rc.83",
33
34
  "@crewx/skill": "0.1.20",
34
- "@crewx/wi": "0.1.10-rc.67",
35
- "@crewx/chromex": "0.1.0-rc.79",
36
- "@crewx/sdk": "0.9.0-rc.0",
37
- "@crewx/notify": "0.1.0-rc.17",
35
+ "@crewx/workflow": "0.3.22-rc.95",
36
+ "@crewx/wi": "0.1.10-rc.69",
38
37
  "@crewx/shared": "0.0.6",
39
- "@crewx/wbs": "0.1.10-rc.72"
38
+ "@crewx/chromex": "0.1.0-rc.81",
39
+ "@crewx/notify": "0.1.0-rc.19"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@types/better-sqlite3": "*",