crewx 0.8.1 → 0.8.2-rc.2

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 (125) hide show
  1. package/README.md +268 -268
  2. package/bin/cli-commands.js +34 -0
  3. package/bin/crewx-lib.js +213 -108
  4. package/bin/crewx-ui.js +83 -83
  5. package/bin/crewx.js +219 -147
  6. package/bin/launcher-flags.js +29 -0
  7. package/bin/package.json +1 -1
  8. package/dist/assets/MarketPage-DptjaFpT.js +36 -0
  9. package/dist/assets/{PromptTab-DVKc7hJY.js → PromptTab-DZha2_v1.js} +1 -1
  10. package/dist/assets/{_baseUniq-wjlVo2E6.js → _baseUniq-jd6NubI3.js} +1 -1
  11. package/dist/assets/{arc-BfPgRtzW.js → arc-C2te3-8P.js} +1 -1
  12. package/dist/assets/{architectureDiagram-Q4EWVU46-ewcueFAG.js → architectureDiagram-Q4EWVU46-CbIQua02.js} +1 -1
  13. package/dist/assets/{blockDiagram-DXYQGD6D-TxlbbvKn.js → blockDiagram-DXYQGD6D-Cg7qkpSM.js} +1 -1
  14. package/dist/assets/{c4Diagram-AHTNJAMY-C1lT_bl_.js → c4Diagram-AHTNJAMY-BkffDY1F.js} +1 -1
  15. package/dist/assets/channel-beae0DeI.js +1 -0
  16. package/dist/assets/chatgpt-logo-dark.svg +15 -15
  17. package/dist/assets/chatgpt-logo.svg +15 -15
  18. package/dist/assets/{chunk-4BX2VUAB-C41j2mCL.js → chunk-4BX2VUAB-BxHe9wPE.js} +1 -1
  19. package/dist/assets/{chunk-4TB4RGXK-HNNsUbz0.js → chunk-4TB4RGXK--f1tN90O.js} +1 -1
  20. package/dist/assets/{chunk-55IACEB6-qtCgO0r2.js → chunk-55IACEB6-B5QXfPXQ.js} +1 -1
  21. package/dist/assets/{chunk-EDXVE4YY-BSnDYtsd.js → chunk-EDXVE4YY-DqKhblOg.js} +1 -1
  22. package/dist/assets/{chunk-FMBD7UC4-DyHRLQqX.js → chunk-FMBD7UC4-DZ1w_G02.js} +1 -1
  23. package/dist/assets/{chunk-OYMX7WX6-CCjfi6WS.js → chunk-OYMX7WX6-BqAgQpv8.js} +1 -1
  24. package/dist/assets/{chunk-QZHKN3VN-COLty8kd.js → chunk-QZHKN3VN-DPqnGqVi.js} +1 -1
  25. package/dist/assets/{chunk-YZCP3GAM-CHUUnGeN.js → chunk-YZCP3GAM-x-ZYSQLd.js} +1 -1
  26. package/dist/assets/classDiagram-6PBFFD2Q-BquWrs1y.js +1 -0
  27. package/dist/assets/classDiagram-v2-HSJHXN6E-BquWrs1y.js +1 -0
  28. package/dist/assets/clone-C9wSPtDN.js +1 -0
  29. package/dist/assets/{cose-bilkent-S5V4N54A-CSip-V2g.js → cose-bilkent-S5V4N54A-4VCNRP-E.js} +1 -1
  30. package/dist/assets/{dagre-KV5264BT-DkdpnWhv.js → dagre-KV5264BT-DucVi1QS.js} +1 -1
  31. package/dist/assets/{diagram-5BDNPKRD-PH4qc6PV.js → diagram-5BDNPKRD-ChdRA8bE.js} +1 -1
  32. package/dist/assets/{diagram-G4DWMVQ6-Cg5xZcjx.js → diagram-G4DWMVQ6-B1-97yHr.js} +1 -1
  33. package/dist/assets/{diagram-MMDJMWI5-soKmeTCW.js → diagram-MMDJMWI5-CQs3cO7G.js} +1 -1
  34. package/dist/assets/{diagram-TYMM5635-Daq5Mihu.js → diagram-TYMM5635-CuNCxDfO.js} +1 -1
  35. package/dist/assets/{erDiagram-SMLLAGMA-kr2OtY0Y.js → erDiagram-SMLLAGMA-DdR8v8g-.js} +1 -1
  36. package/dist/assets/{flowDiagram-DWJPFMVM-DQZCb8gm.js → flowDiagram-DWJPFMVM-Dt02upId.js} +1 -1
  37. package/dist/assets/{ganttDiagram-T4ZO3ILL-BHkn485T.js → ganttDiagram-T4ZO3ILL-cG_k9VOa.js} +1 -1
  38. package/dist/assets/{gitGraphDiagram-UUTBAWPF-FaCyYFmC.js → gitGraphDiagram-UUTBAWPF-Dz1DjhKq.js} +1 -1
  39. package/dist/assets/{graph-BVJlrP6V.js → graph-CF2NtM33.js} +1 -1
  40. package/dist/assets/{infoDiagram-42DDH7IO-DJOWkKdM.js → infoDiagram-42DDH7IO-tQWKrYM6.js} +1 -1
  41. package/dist/assets/{ishikawaDiagram-UXIWVN3A-VfpvNaIf.js → ishikawaDiagram-UXIWVN3A-CLuUMkF0.js} +1 -1
  42. package/dist/assets/{journeyDiagram-VCZTEJTY-CPzsak-v.js → journeyDiagram-VCZTEJTY-a6JenLCk.js} +1 -1
  43. package/dist/assets/{kanban-definition-6JOO6SKY-DFqLDBU0.js → kanban-definition-6JOO6SKY-rqOxTzYb.js} +1 -1
  44. package/dist/assets/{layout-CCSbNPHm.js → layout-Dvic1Hpy.js} +1 -1
  45. package/dist/assets/{linear-C4T7PCKE.js → linear-CfMV1S6a.js} +1 -1
  46. package/dist/assets/main-05K4ggqd.css +10 -0
  47. package/dist/assets/main-CCM1gtr8.js +1165 -0
  48. package/dist/assets/{min-CGQNEYGh.js → min-GpF3DZux.js} +1 -1
  49. package/dist/assets/{mindmap-definition-QFDTVHPH-AuU1EqwS.js → mindmap-definition-QFDTVHPH-Cg80z0Jx.js} +1 -1
  50. package/dist/assets/{pieDiagram-DEJITSTG-CopkCZwp.js → pieDiagram-DEJITSTG-BrtK7lAq.js} +1 -1
  51. package/dist/assets/{quadrantDiagram-34T5L4WZ-lMKrSv_t.js → quadrantDiagram-34T5L4WZ-BL2txAAS.js} +1 -1
  52. package/dist/assets/{requirementDiagram-MS252O5E-dWUpHOFb.js → requirementDiagram-MS252O5E-Co3wpBnu.js} +1 -1
  53. package/dist/assets/{sankeyDiagram-XADWPNL6-C8UQx9Bb.js → sankeyDiagram-XADWPNL6-B4KJXdQ4.js} +1 -1
  54. package/dist/assets/{sequenceDiagram-FGHM5R23-CUVNIItJ.js → sequenceDiagram-FGHM5R23-xs5OuzvV.js} +1 -1
  55. package/dist/assets/{stateDiagram-FHFEXIEX-Ct0GamGl.js → stateDiagram-FHFEXIEX-bbEP20JD.js} +1 -1
  56. package/dist/assets/stateDiagram-v2-QKLJ7IA2-XYh9U1A7.js +1 -0
  57. package/dist/assets/{timeline-definition-GMOUNBTQ-ul8Po7f7.js → timeline-definition-GMOUNBTQ-CTc2wVwC.js} +1 -1
  58. package/dist/assets/{vennDiagram-DHZGUBPP-B4AOWQnP.js → vennDiagram-DHZGUBPP-oJpXott7.js} +1 -1
  59. package/dist/assets/{wardley-RL74JXVD-Dr7Wp3AJ.js → wardley-RL74JXVD-aTmOXkKh.js} +1 -1
  60. package/dist/assets/{wardleyDiagram-NUSXRM2D-Ck70faXX.js → wardleyDiagram-NUSXRM2D-C83SOkig.js} +1 -1
  61. package/dist/assets/{xychartDiagram-5P7HB3ND-Bsy5-cNt.js → xychartDiagram-5P7HB3ND-BScws0tF.js} +1 -1
  62. package/dist/index.html +13 -13
  63. package/dist-electron/main.js +153 -116
  64. package/dist-electron/overlay.js +102 -65
  65. package/dist-electron/package.json +1 -0
  66. package/dist-electron/preload.js +8 -8
  67. package/dist-server/bootstrap/crewx-server.js +19 -10
  68. package/dist-server/domain/agent/agent.service.js +12 -0
  69. package/dist-server/domain/agent/dto/update-agent.dto.js +20 -1
  70. package/dist-server/domain/mcp/crewx-tool.factory.js +44 -113
  71. package/dist-server/domain/mcp/mcp.module.js +2 -0
  72. package/dist-server/domain/mcp/mcp.service.js +37 -12
  73. package/dist-server/domain/message/message.service.js +21 -13
  74. package/dist-server/domain/skill/skill.service.js +63 -43
  75. package/dist-server/domain/task/task.module.js +2 -0
  76. package/dist-server/domain/task/task.service.js +17 -10
  77. package/dist-server/domain/thread/dto/update-thread.dto.js +23 -0
  78. package/dist-server/domain/thread/thread.controller.js +16 -0
  79. package/dist-server/domain/thread/thread.service.js +9 -0
  80. package/dist-server/main.js +1 -1
  81. package/dist-server/modules/crewx.module.js +16 -1
  82. package/dist-server/repository/box.repository.js +20 -20
  83. package/dist-server/repository/project.repository.js +13 -13
  84. package/dist-server/repository/request-log.repository.js +10 -10
  85. package/dist-server/repository/task.repository.js +72 -72
  86. package/dist-server/repository/thread.repository.js +78 -58
  87. package/package.json +6 -6
  88. package/packages/cli/dist/bootstrap/crewx-cli.js +12 -0
  89. package/packages/cli/dist/commands/agent.js +23 -23
  90. package/packages/cli/dist/commands/init.js +19 -19
  91. package/packages/cli/dist/commands/parse-common-flags.d.ts +19 -3
  92. package/packages/cli/dist/commands/parse-common-flags.js +46 -6
  93. package/packages/cli/dist/commands/registry.d.ts +13 -0
  94. package/packages/cli/dist/commands/registry.js +29 -0
  95. package/packages/cli/dist/commands/task-db.js +7 -7
  96. package/packages/cli/dist/examples/deny-secrets-plugin.d.ts +22 -0
  97. package/packages/cli/dist/examples/deny-secrets-plugin.js +40 -0
  98. package/packages/cli/dist/main.js +134 -68
  99. package/packages/cli/dist/plugins/examples/echo-hook.d.ts +24 -0
  100. package/packages/cli/dist/plugins/examples/echo-hook.js +60 -0
  101. package/packages/cli/dist/plugins/examples/verify-echo-hook.d.ts +8 -0
  102. package/packages/cli/dist/plugins/examples/verify-echo-hook.js +47 -0
  103. package/packages/cli/dist/plugins/sqlite-tracing.d.ts +11 -0
  104. package/packages/cli/dist/plugins/sqlite-tracing.js +19 -0
  105. package/packages/cli/dist/schema/tasks.d.ts +7 -0
  106. package/packages/cli/dist/schema/tasks.js +48 -0
  107. package/packages/cli/package.json +52 -52
  108. package/scripts/analyze-task-logs.mjs +569 -0
  109. package/scripts/build-manual.mjs +266 -266
  110. package/scripts/emit-dist-server-package-json.mjs +7 -7
  111. package/scripts/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
  112. package/scripts/postinstall.mjs +44 -44
  113. package/scripts/smoke-tarball.mjs +285 -285
  114. package/scripts/snapshot-msg-list.sh +52 -52
  115. package/server.js +167 -164
  116. package/dist/assets/MarketPage-Dwsg6K-B.js +0 -31
  117. package/dist/assets/channel-BP4PNMmz.js +0 -1
  118. package/dist/assets/classDiagram-6PBFFD2Q-Upr3UAcM.js +0 -1
  119. package/dist/assets/classDiagram-v2-HSJHXN6E-Upr3UAcM.js +0 -1
  120. package/dist/assets/clone-B8BP7ReZ.js +0 -1
  121. package/dist/assets/main-CELBpK6r.js +0 -1166
  122. package/dist/assets/main-CmP-VosD.css +0 -10
  123. package/dist/assets/stateDiagram-v2-QKLJ7IA2-CFBLQDEx.js +0 -1
  124. package/dist-server/domain/task/dto/project-usage.dto.js +0 -38
  125. package/dist-server/domain/thread/dto/send-message.dto.js +0 -10
@@ -1,52 +1,52 @@
1
- #!/bin/bash
2
- # MSG.LIST 스냅샷 캡처 스크립트
3
- # 사용법: ./scripts/snapshot-msg-list.sh <threadId> [interval_sec] [logsTail]
4
- #
5
- # 에이전트에게 메시지를 보낸 뒤 이 스크립트를 돌리면
6
- # running → completed 전 과정의 API 응답이 타임스탬프별로 저장됨.
7
-
8
- THREAD_ID="${1:?threadId를 입력하세요}"
9
- INTERVAL="${2:-3}"
10
- LOGS_TAIL="${3:-3}"
11
- BASE_URL="http://localhost:8150/api/v1"
12
-
13
- OUTDIR="snapshots/${THREAD_ID}"
14
- mkdir -p "$OUTDIR"
15
-
16
- SEQ=0
17
- PREV_HASH=""
18
-
19
- echo "📸 MSG.LIST 스냅샷 캡처 시작"
20
- echo " Thread: $THREAD_ID"
21
- echo " Interval: ${INTERVAL}s"
22
- echo " logsTail: $LOGS_TAIL"
23
- echo " 출력: $OUTDIR/"
24
- echo " Ctrl+C로 중지"
25
- echo ""
26
-
27
- while true; do
28
- TIMESTAMP=$(date +%Y%m%d_%H%M%S)
29
- RESPONSE=$(curl -s "${BASE_URL}/threads/${THREAD_ID}/messages?logsTail=${LOGS_TAIL}")
30
-
31
- # 응답이 비어있으면 스킵
32
- if [ -z "$RESPONSE" ]; then
33
- echo "⚠️ [$TIMESTAMP] 빈 응답 — 서버 확인 필요"
34
- sleep "$INTERVAL"
35
- continue
36
- fi
37
-
38
- # 이전 스냅샷과 비교 (중복 제거)
39
- CURR_HASH=$(echo "$RESPONSE" | shasum -a 256 | cut -d' ' -f1)
40
-
41
- if [ "$CURR_HASH" = "$PREV_HASH" ]; then
42
- echo " [$TIMESTAMP] (변화 없음 — 스킵)"
43
- else
44
- SEQ=$((SEQ + 1))
45
- FILENAME=$(printf "%03d_%s.json" "$SEQ" "$TIMESTAMP")
46
- echo "$RESPONSE" | python3 -m json.tool > "${OUTDIR}/${FILENAME}"
47
- echo "✅ [$TIMESTAMP] → ${FILENAME} ($(echo "$RESPONSE" | wc -c | tr -d ' ') bytes)"
48
- PREV_HASH="$CURR_HASH"
49
- fi
50
-
51
- sleep "$INTERVAL"
52
- done
1
+ #!/bin/bash
2
+ # MSG.LIST 스냅샷 캡처 스크립트
3
+ # 사용법: ./scripts/snapshot-msg-list.sh <threadId> [interval_sec] [logsTail]
4
+ #
5
+ # 에이전트에게 메시지를 보낸 뒤 이 스크립트를 돌리면
6
+ # running → completed 전 과정의 API 응답이 타임스탬프별로 저장됨.
7
+
8
+ THREAD_ID="${1:?threadId를 입력하세요}"
9
+ INTERVAL="${2:-3}"
10
+ LOGS_TAIL="${3:-3}"
11
+ BASE_URL="http://localhost:8150/api/v1"
12
+
13
+ OUTDIR="snapshots/${THREAD_ID}"
14
+ mkdir -p "$OUTDIR"
15
+
16
+ SEQ=0
17
+ PREV_HASH=""
18
+
19
+ echo "📸 MSG.LIST 스냅샷 캡처 시작"
20
+ echo " Thread: $THREAD_ID"
21
+ echo " Interval: ${INTERVAL}s"
22
+ echo " logsTail: $LOGS_TAIL"
23
+ echo " 출력: $OUTDIR/"
24
+ echo " Ctrl+C로 중지"
25
+ echo ""
26
+
27
+ while true; do
28
+ TIMESTAMP=$(date +%Y%m%d_%H%M%S)
29
+ RESPONSE=$(curl -s "${BASE_URL}/threads/${THREAD_ID}/messages?logsTail=${LOGS_TAIL}")
30
+
31
+ # 응답이 비어있으면 스킵
32
+ if [ -z "$RESPONSE" ]; then
33
+ echo "⚠️ [$TIMESTAMP] 빈 응답 — 서버 확인 필요"
34
+ sleep "$INTERVAL"
35
+ continue
36
+ fi
37
+
38
+ # 이전 스냅샷과 비교 (중복 제거)
39
+ CURR_HASH=$(echo "$RESPONSE" | shasum -a 256 | cut -d' ' -f1)
40
+
41
+ if [ "$CURR_HASH" = "$PREV_HASH" ]; then
42
+ echo " [$TIMESTAMP] (변화 없음 — 스킵)"
43
+ else
44
+ SEQ=$((SEQ + 1))
45
+ FILENAME=$(printf "%03d_%s.json" "$SEQ" "$TIMESTAMP")
46
+ echo "$RESPONSE" | python3 -m json.tool > "${OUTDIR}/${FILENAME}"
47
+ echo "✅ [$TIMESTAMP] → ${FILENAME} ($(echo "$RESPONSE" | wc -c | tr -d ' ') bytes)"
48
+ PREV_HASH="$CURR_HASH"
49
+ fi
50
+
51
+ sleep "$INTERVAL"
52
+ done
package/server.js CHANGED
@@ -1,164 +1,167 @@
1
- #!/usr/bin/env node
2
- const { spawn } = require('child_process');
3
- const { join } = require('path');
4
- const { mkdtempSync, writeFileSync, chmodSync, rmSync, existsSync } = require('fs');
5
- const { tmpdir, platform } = require('os');
6
-
7
- // Resolve path to the CLI engine (packages/cli/dist/main.js)
8
- const cliMainPath = join(__dirname, 'packages', 'cli', 'dist', 'main.js');
9
-
10
- // --- Shared: CLI proxy setup ---
11
- // Creates a temp proxy script so child processes can resolve `crewx` in PATH
12
- const PROXY_DIR = mkdtempSync(join(tmpdir(), 'crewx-proxy-'));
13
- const nodeBin = process.execPath;
14
- const serverScript = process.argv[1];
15
-
16
- function setupCliProxy() {
17
- if (platform() === 'win32') {
18
- const cmdPath = join(PROXY_DIR, 'crewx.cmd');
19
- writeFileSync(cmdPath, `@echo off\r\n"${nodeBin}" "${serverScript}" cli %*\r\n`);
20
- } else {
21
- const shPath = join(PROXY_DIR, 'crewx');
22
- writeFileSync(shPath, `#!/bin/sh\nexec "${nodeBin}" "${serverScript}" cli "$@"\n`);
23
- chmodSync(shPath, 0o755);
24
- }
25
- }
26
-
27
- function cleanupCliProxy() {
28
- try {
29
- if (existsSync(PROXY_DIR)) {
30
- rmSync(PROXY_DIR, { recursive: true, force: true });
31
- }
32
- } catch {
33
- // Ignore cleanup errors on exit
34
- }
35
- }
36
-
37
- setupCliProxy();
38
- const envPATH = `${PROXY_DIR}${platform() === 'win32' ? ';' : ':'}${process.env.PATH || ''}`;
39
-
40
- // --- CLI Subcommand Mode ---
41
- // When invoked as `crewx cli <args...>`, forward to packages/cli directly
42
- const args = process.argv.slice(2);
43
- if (args[0] === 'cli') {
44
- const cliArgs = args.slice(1);
45
- const child = spawn(process.execPath, [cliMainPath, ...cliArgs], {
46
- stdio: 'inherit',
47
- env: { ...process.env, PATH: envPATH },
48
- });
49
- child.on('exit', (code) => { cleanupCliProxy(); process.exit(code || 0); });
50
- child.on('error', (err) => {
51
- console.error('Failed to run CLI:', err);
52
- cleanupCliProxy();
53
- process.exit(1);
54
- });
55
- process.on('exit', () => cleanupCliProxy());
56
- } else {
57
- // --- Normal server mode ---
58
-
59
- const PORT = process.env.PORT || 8150;
60
- const OPEN_CMD = platform() === 'darwin' ? 'open' : platform() === 'win32' ? 'start' : 'xdg-open';
61
-
62
- // Graceful shutdown handler
63
- let server;
64
- function shutdown(signal) {
65
- console.log(`\nReceived ${signal}, shutting down gracefully...`);
66
- if (server && !server.killed) {
67
- server.kill('SIGTERM');
68
- }
69
- cleanupCliProxy();
70
- // Give server time to cleanup, then force exit
71
- setTimeout(() => {
72
- process.exit(0);
73
- }, 1000);
74
- }
75
-
76
- // Start NestJS server with proxy PATH injected
77
- // tsc outputs to dist-server/ (rootDir: src/server in tsconfig.server.json)
78
- const distServerPath = join(__dirname, 'dist-server', 'main.js');
79
- const devServerPath = join(__dirname, 'src', 'server', 'main.ts');
80
- const serverEnv = {
81
- ...process.env,
82
- PORT: String(PORT),
83
- SERVE_STATIC: 'true',
84
- PATH: envPATH,
85
- };
86
-
87
- if (existsSync(distServerPath)) {
88
- server = spawn('node', [distServerPath], {
89
- env: serverEnv,
90
- stdio: ['ignore', 'pipe', 'inherit'],
91
- });
92
- } else if (existsSync(devServerPath)) {
93
- // NestJS requires emitDecoratorMetadata for DI — tsx (esbuild) doesn't emit it.
94
- // Use `nest start` which respects tsconfig and emits decorator metadata correctly.
95
- // --watch intentionally omitted: nest's internal restart triggers server.on('exit')
96
- // handler (line ~124), terminating the whole process. Use `npm run dev:server` for watch.
97
- const nestBin = join(__dirname, 'node_modules', '.bin', 'nest');
98
- if (existsSync(nestBin)) {
99
- server = spawn(nestBin, ['start'], {
100
- env: serverEnv,
101
- stdio: ['ignore', 'pipe', 'inherit'],
102
- });
103
- } else {
104
- console.error('❌ NestJS CLI not found. Run `npm install` first.');
105
- cleanupCliProxy();
106
- process.exit(1);
107
- }
108
- } else {
109
- console.error('❌ Server not found. Run `npm run build:server` first.');
110
- cleanupCliProxy();
111
- process.exit(1);
112
- }
113
-
114
- // Open browser when server is ready (detect startup message from stdout).
115
- // Fallback: open after 30s if no ready message detected.
116
- let browserOpened = false;
117
- const READY_PATTERNS = [/running on/i, /Nest application successfully started/i, /listening on/i];
118
-
119
- function openBrowser() {
120
- if (browserOpened) return;
121
- browserOpened = true;
122
- clearTimeout(fallbackTimer);
123
- const url = `http://localhost:${PORT}`;
124
- console.log(`Opening browser: ${url}`);
125
- spawn(OPEN_CMD, [url], { shell: true });
126
- }
127
-
128
- const fallbackTimer = setTimeout(() => {
129
- openBrowser();
130
- }, 30_000);
131
-
132
- if (server.stdout) {
133
- server.stdout.on('data', (chunk) => {
134
- process.stdout.write(chunk);
135
- if (!browserOpened) {
136
- const text = chunk.toString();
137
- if (READY_PATTERNS.some((re) => re.test(text))) {
138
- openBrowser();
139
- }
140
- }
141
- });
142
- }
143
-
144
- server.on('error', (err) => {
145
- console.error('Failed to start server:', err);
146
- cleanupCliProxy();
147
- process.exit(1);
148
- });
149
-
150
- server.on('exit', (code, signal) => {
151
- if (signal) {
152
- console.log(`Server exited with signal ${signal}`);
153
- } else if (code !== 0) {
154
- console.log(`Server exited with code ${code}`);
155
- }
156
- cleanupCliProxy();
157
- process.exit(code || 0);
158
- });
159
-
160
- // Handle signals
161
- process.on('SIGINT', () => shutdown('SIGINT'));
162
- process.on('SIGTERM', () => shutdown('SIGTERM'));
163
- process.on('exit', () => cleanupCliProxy());
164
- }
1
+ #!/usr/bin/env node
2
+ const { spawn } = require('child_process');
3
+ const { join } = require('path');
4
+ const { mkdtempSync, writeFileSync, chmodSync, rmSync, existsSync } = require('fs');
5
+ const { tmpdir, platform } = require('os');
6
+
7
+ // Resolve path to the CLI engine (packages/cli/dist/main.js)
8
+ const cliMainPath = join(__dirname, 'packages', 'cli', 'dist', 'main.js');
9
+
10
+ // --- Shared: CLI proxy setup ---
11
+ // Creates a temp proxy script so child processes can resolve `crewx` in PATH
12
+ const PROXY_DIR = mkdtempSync(join(tmpdir(), 'crewx-proxy-'));
13
+ const nodeBin = process.execPath;
14
+ const serverScript = process.argv[1];
15
+
16
+ function setupCliProxy() {
17
+ if (platform() === 'win32') {
18
+ const cmdPath = join(PROXY_DIR, 'crewx.cmd');
19
+ writeFileSync(cmdPath, `@echo off\r\n"${nodeBin}" "${serverScript}" cli %*\r\n`);
20
+ } else {
21
+ const shPath = join(PROXY_DIR, 'crewx');
22
+ writeFileSync(shPath, `#!/bin/sh\nexec "${nodeBin}" "${serverScript}" cli "$@"\n`);
23
+ chmodSync(shPath, 0o755);
24
+ }
25
+ }
26
+
27
+ function cleanupCliProxy() {
28
+ try {
29
+ if (existsSync(PROXY_DIR)) {
30
+ rmSync(PROXY_DIR, { recursive: true, force: true });
31
+ }
32
+ } catch {
33
+ // Ignore cleanup errors on exit
34
+ }
35
+ }
36
+
37
+ setupCliProxy();
38
+ const envPATH = `${PROXY_DIR}${platform() === 'win32' ? ';' : ':'}${process.env.PATH || ''}`;
39
+
40
+ // --- CLI Subcommand Mode ---
41
+ // When invoked as `crewx cli <args...>`, forward to packages/cli directly
42
+ const args = process.argv.slice(2);
43
+ if (args[0] === 'cli') {
44
+ const cliArgs = args.slice(1);
45
+ const child = spawn(process.execPath, [cliMainPath, ...cliArgs], {
46
+ stdio: 'inherit',
47
+ env: { ...process.env, PATH: envPATH },
48
+ });
49
+ child.on('exit', (code) => { cleanupCliProxy(); process.exit(code || 0); });
50
+ child.on('error', (err) => {
51
+ console.error('Failed to run CLI:', err);
52
+ cleanupCliProxy();
53
+ process.exit(1);
54
+ });
55
+ process.on('exit', () => cleanupCliProxy());
56
+ } else {
57
+ // --- Normal server mode ---
58
+
59
+ const PORT = process.env.PORT || 8150;
60
+ const OPEN_CMD = platform() === 'darwin' ? 'open' : platform() === 'win32' ? 'start' : 'xdg-open';
61
+
62
+ // Graceful shutdown handler
63
+ let server;
64
+ function shutdown(signal) {
65
+ console.log(`\nReceived ${signal}, shutting down gracefully...`);
66
+ if (server && !server.killed) {
67
+ server.kill('SIGTERM');
68
+ }
69
+ cleanupCliProxy();
70
+ // Give server time to cleanup, then force exit
71
+ setTimeout(() => {
72
+ process.exit(0);
73
+ }, 1000);
74
+ }
75
+
76
+ // Start NestJS server with proxy PATH injected
77
+ // tsc outputs to dist-server/ (rootDir: src/server in tsconfig.server.json)
78
+ const distServerPath = join(__dirname, 'dist-server', 'main.js');
79
+ const devServerPath = join(__dirname, 'src', 'server', 'main.ts');
80
+ const serverEnv = {
81
+ ...process.env,
82
+ PORT: String(PORT),
83
+ SERVE_STATIC: 'true',
84
+ PATH: envPATH,
85
+ };
86
+
87
+ if (existsSync(distServerPath)) {
88
+ server = spawn('node', [distServerPath], {
89
+ env: serverEnv,
90
+ stdio: ['ignore', 'pipe', 'inherit'],
91
+ });
92
+ } else if (existsSync(devServerPath)) {
93
+ // NestJS requires emitDecoratorMetadata for DI — tsx (esbuild) doesn't emit it.
94
+ // Use `nest start` which respects tsconfig and emits decorator metadata correctly.
95
+ // --watch intentionally omitted: nest's internal restart triggers server.on('exit')
96
+ // handler (line ~124), terminating the whole process. Use `npm run dev:server` for watch.
97
+ const nestBin = join(__dirname, 'node_modules', '.bin', 'nest');
98
+ if (existsSync(nestBin)) {
99
+ server = spawn(nestBin, ['start'], {
100
+ env: serverEnv,
101
+ stdio: ['ignore', 'pipe', 'inherit'],
102
+ });
103
+ } else {
104
+ console.error('❌ NestJS CLI not found. Run `npm install` first.');
105
+ cleanupCliProxy();
106
+ process.exit(1);
107
+ }
108
+ } else {
109
+ console.error('❌ Server not found. Run `npm run build:server` first.');
110
+ cleanupCliProxy();
111
+ process.exit(1);
112
+ }
113
+
114
+ // Open browser only when explicitly requested via CREWX_OPEN_BROWSER=1.
115
+ // bin/crewx.js sets this env only for the default `crewx` (no-args) route;
116
+ // `crewx serve [--no-open]` never sets it, so the browser stays closed.
117
+ const shouldOpenBrowser = process.env.CREWX_OPEN_BROWSER === '1';
118
+ let browserOpened = false;
119
+ let fallbackTimer;
120
+ const READY_PATTERNS = [/running on/i, /Nest application successfully started/i, /listening on/i];
121
+
122
+ function openBrowser() {
123
+ if (browserOpened) return;
124
+ browserOpened = true;
125
+ if (fallbackTimer) clearTimeout(fallbackTimer);
126
+ const url = `http://localhost:${PORT}`;
127
+ console.log(`Opening browser: ${url}`);
128
+ spawn(OPEN_CMD, [url], { shell: true });
129
+ }
130
+
131
+ if (shouldOpenBrowser) {
132
+ fallbackTimer = setTimeout(openBrowser, 30_000);
133
+ }
134
+
135
+ if (server.stdout) {
136
+ server.stdout.on('data', (chunk) => {
137
+ process.stdout.write(chunk);
138
+ if (shouldOpenBrowser && !browserOpened) {
139
+ const text = chunk.toString();
140
+ if (READY_PATTERNS.some((re) => re.test(text))) {
141
+ openBrowser();
142
+ }
143
+ }
144
+ });
145
+ }
146
+
147
+ server.on('error', (err) => {
148
+ console.error('Failed to start server:', err);
149
+ cleanupCliProxy();
150
+ process.exit(1);
151
+ });
152
+
153
+ server.on('exit', (code, signal) => {
154
+ if (signal) {
155
+ console.log(`Server exited with signal ${signal}`);
156
+ } else if (code !== 0) {
157
+ console.log(`Server exited with code ${code}`);
158
+ }
159
+ cleanupCliProxy();
160
+ process.exit(code || 0);
161
+ });
162
+
163
+ // Handle signals
164
+ process.on('SIGINT', () => shutdown('SIGINT'));
165
+ process.on('SIGTERM', () => shutdown('SIGTERM'));
166
+ process.on('exit', () => cleanupCliProxy());
167
+ }
@@ -1,31 +0,0 @@
1
- import{aO as w,aP as we,aQ as f,aR as N,aS as Se,aT as u,aU as e,aV as ae,aW as se,aX as K,aY as j,aZ as re,a_ as Ie,a$ as le,b0 as U,b1 as ze,b2 as Re,b3 as Ce,b4 as ie,b5 as Me,b6 as De}from"./main-CELBpK6r.js";/**
2
- * @license lucide-react v0.563.0 - ISC
3
- *
4
- * This source code is licensed under the ISC license.
5
- * See the LICENSE file in the root directory of this source tree.
6
- */const Ae=[["path",{d:"M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z",key:"3c2336"}],["path",{d:"m9 12 2 2 4-4",key:"dzmm74"}]],ne=w("badge-check",Ae);/**
7
- * @license lucide-react v0.563.0 - ISC
8
- *
9
- * This source code is licensed under the ISC license.
10
- * See the LICENSE file in the root directory of this source tree.
11
- */const Te=[["rect",{width:"18",height:"7",x:"3",y:"3",rx:"1",key:"f1a2em"}],["rect",{width:"9",height:"7",x:"3",y:"14",rx:"1",key:"jqznyg"}],["rect",{width:"5",height:"7",x:"16",y:"14",rx:"1",key:"q5h2i8"}]],de=w("layout-template",Te);/**
12
- * @license lucide-react v0.563.0 - ISC
13
- *
14
- * This source code is licensed under the ISC license.
15
- * See the LICENSE file in the root directory of this source tree.
16
- */const Le=[["path",{d:"M15.39 4.39a1 1 0 0 0 1.68-.474 2.5 2.5 0 1 1 3.014 3.015 1 1 0 0 0-.474 1.68l1.683 1.682a2.414 2.414 0 0 1 0 3.414L19.61 15.39a1 1 0 0 1-1.68-.474 2.5 2.5 0 1 0-3.014 3.015 1 1 0 0 1 .474 1.68l-1.683 1.682a2.414 2.414 0 0 1-3.414 0L8.61 19.61a1 1 0 0 0-1.68.474 2.5 2.5 0 1 1-3.014-3.015 1 1 0 0 0 .474-1.68l-1.683-1.682a2.414 2.414 0 0 1 0-3.414L4.39 8.61a1 1 0 0 1 1.68.474 2.5 2.5 0 1 0 3.014-3.015 1 1 0 0 1-.474-1.68l1.683-1.682a2.414 2.414 0 0 1 3.414 0z",key:"w46dr5"}]],oe=w("puzzle",Le);/**
17
- * @license lucide-react v0.563.0 - ISC
18
- *
19
- * This source code is licensed under the ISC license.
20
- * See the LICENSE file in the root directory of this source tree.
21
- */const Ee=[["path",{d:"M12 3v18",key:"108xh3"}],["path",{d:"m19 8 3 8a5 5 0 0 1-6 0zV7",key:"zcdpyk"}],["path",{d:"M3 7h1a17 17 0 0 0 8-2 17 17 0 0 0 8 2h1",key:"1yorad"}],["path",{d:"m5 8 3 8a5 5 0 0 1-6 0zV7",key:"eua70x"}],["path",{d:"M7 21h10",key:"1b0cd5"}]],$e=w("scale",Ee);/**
22
- * @license lucide-react v0.563.0 - ISC
23
- *
24
- * This source code is licensed under the ISC license.
25
- * See the LICENSE file in the root directory of this source tree.
26
- */const _e=[["path",{d:"M14 17H5",key:"gfn3mx"}],["path",{d:"M19 7h-9",key:"6i9tg"}],["circle",{cx:"17",cy:"17",r:"3",key:"18b49y"}],["circle",{cx:"7",cy:"7",r:"3",key:"dfmy0x"}]],Ve=w("settings-2",_e);/**
27
- * @license lucide-react v0.563.0 - ISC
28
- *
29
- * This source code is licensed under the ISC license.
30
- * See the LICENSE file in the root directory of this source tree.
31
- */const Fe=[["path",{d:"M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z",key:"r04s7s"}]],Pe=w("star",Fe);function I(t){return t instanceof Error?t.message:String(t)}function Oe(t){return[...t].sort((a,s)=>a.isInstalled!==s.isInstalled?a.isInstalled?-1:1:(a.displayName||a.name).localeCompare(s.displayName||s.name))}function Ue(t=[],a=[]){return Array.from(new Set([...t,...a]))}function Be(t,a){var s;return t?{...t,...a,displayName:a.displayName||t.displayName||a.name,description:a.description||t.description,author:a.author||t.author,version:a.version||t.version,tags:Ue(t.tags,a.tags),type:a.type||t.type,isVerified:t.isVerified||a.isVerified,isInstalled:t.isInstalled||a.isInstalled,registryId:a.registryId??t.registryId,registryName:a.registryName??t.registryName,installSource:a.installSource??t.installSource,authors:(s=a.authors)!=null&&s.length?a.authors:t.authors,updatedAt:a.updatedAt??t.updatedAt,stars:a.stars??t.stars,license:a.license??t.license,installCount:a.installCount??t.installCount}:a}function L(t){const a=new Map;for(const s of t){const r=a.get(s.name);a.set(s.name,Be(r,s))}return Oe(Array.from(a.values()))}function He(t,a){return t.map(s=>({...s,registryId:s.registryId??a.id,registryName:s.registryName??a.name,isVerified:s.isVerified||a.isVerified}))}function Qe(t){return t.find(a=>a.isDefault)??t.find(a=>a.isVerified)??t[0]??null}function qe(t,a){return L([...t,...a])}function O(t,a){var s;return a&&t.some(r=>r.name===a)?a:((s=t[0])==null?void 0:s.name)??null}const We=we((t,a)=>({initialized:!1,loading:!1,loadingOfficial:!1,loadingInstalled:!1,savingRegistry:!1,deletingRegistryId:null,mutatingSkillName:null,error:null,registries:[],officialRegistryId:null,allSkills:[],activeFilter:"all",searchQuery:"",selectedSkillName:null,setActiveFilter:s=>t({activeFilter:s}),setSearchQuery:s=>t({searchQuery:s}),setSelectedSkill:s=>t({selectedSkillName:s}),initialize:async()=>{const s=a().selectedSkillName;t({loading:!0,loadingOfficial:!0,loadingInstalled:!0,error:null});try{const n=(await f.getSkillRegistries()).registries,o=Qe(n),[d,m]=await Promise.all([o?f.getRegistrySkills(o.id):Promise.resolve({skills:[]}),f.getInstalledSkills()]),y=o?He(d.skills,o):[],c=L(m.skills),h=qe(y,c);t({initialized:!0,loading:!1,loadingOfficial:!1,loadingInstalled:!1,registries:n,officialRegistryId:(o==null?void 0:o.id)??null,allSkills:h,selectedSkillName:O(h,s)})}catch(r){throw t({loading:!1,loadingOfficial:!1,loadingInstalled:!1,error:I(r)}),r}},refresh:async()=>{await a().initialize()},addRegistry:async s=>{const r=s.trim();if(!r){const n=new Error("Registry URL is required");throw t({error:n.message}),n}t({savingRegistry:!0,error:null});try{await f.addSkillRegistry(r),await a().initialize(),t({savingRegistry:!1})}catch(n){throw t({savingRegistry:!1,error:I(n)}),n}},deleteRegistry:async s=>{t({deletingRegistryId:s,error:null});try{await f.deleteSkillRegistry(s),await a().initialize(),t({deletingRegistryId:null})}catch(r){throw t({deletingRegistryId:null,error:I(r)}),r}},installSkill:async(s,r)=>{t({mutatingSkillName:r,error:null});try{await f.installSkill(s,r),t(n=>{const o=n.registries.find(m=>m.id===s),d=L(n.allSkills.map(m=>m.name===r?{...m,isInstalled:!0,registryId:m.registryId??s,registryName:m.registryName??(o==null?void 0:o.name)}:m));return{allSkills:d,mutatingSkillName:null,selectedSkillName:O(d,n.selectedSkillName??r)}})}catch(n){throw t({mutatingSkillName:null,error:I(n)}),n}},uninstallSkill:async s=>{t({mutatingSkillName:s,error:null});try{await f.uninstallSkill(s),t(r=>{const n=L(r.allSkills.map(o=>o.name===s?{...o,isInstalled:!1}:o));return{allSkills:n,mutatingSkillName:null,selectedSkillName:O(n,r.selectedSkillName)}})}catch(r){throw t({mutatingSkillName:null,error:I(r)}),r}},clearError:()=>t({error:null})}));function ce(t,a){if(!t)return"—";const s=new Date(t);return Number.isNaN(s.getTime())?"—":new Intl.DateTimeFormat(a,{year:"numeric",month:"short",day:"numeric"}).format(s)}function Ze(t,a){if(!t)return null;const s=new Date(t);if(Number.isNaN(s.getTime()))return null;const r=s.getTime()-Date.now(),n=[{unit:"year",ms:1e3*60*60*24*365},{unit:"month",ms:1e3*60*60*24*30},{unit:"week",ms:1e3*60*60*24*7},{unit:"day",ms:1e3*60*60*24},{unit:"hour",ms:1e3*60*60},{unit:"minute",ms:1e3*60}],o=new Intl.RelativeTimeFormat(a,{numeric:"auto"});for(const d of n)if(Math.abs(r)>=d.ms||d.unit==="minute")return o.format(Math.round(r/d.ms),d.unit);return null}function ee(t,a){return typeof t!="number"?"—":new Intl.NumberFormat(a,{notation:"compact",compactDisplay:"short",maximumFractionDigits:1}).format(t)}function B(t){switch(t==null?void 0:t.toLowerCase()){case"template":return"template";case"agent":return"agent";default:return"skill"}}function me({type:t}){const{t:a}=N(),s=B(t),r={skill:"bg-violet-50 text-violet-700",template:"bg-amber-50 text-amber-700",agent:"bg-emerald-50 text-emerald-700"},n={skill:oe,template:de,agent:re},o={skill:a("market.types.skill"),template:a("market.types.template"),agent:a("market.types.agent")},d=n[s];return e.jsxs("span",{className:`inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-[10px] font-medium ${r[s]}`,children:[e.jsx(d,{size:12}),o[s]]})}function Xe({url:t,error:a,submitting:s,onChange:r,onClose:n,onSubmit:o}){const{t:d}=N(),m=y=>{y.preventDefault(),o()};return e.jsx("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4",children:e.jsxs("div",{role:"dialog","aria-modal":"true",className:"w-full max-w-xl overflow-hidden rounded-2xl border border-gray-200 bg-white shadow-xl",children:[e.jsxs("div",{className:"border-b border-gray-200 px-6 py-5",children:[e.jsx("h2",{className:"text-lg font-semibold text-gray-900",children:d("market.addRegistryModal.title")}),e.jsx("p",{className:"mt-1 text-sm text-gray-500",children:d("market.addRegistryModal.description")})]}),e.jsxs("form",{onSubmit:m,children:[e.jsxs("div",{className:"space-y-4 px-6 py-5",children:[e.jsxs("div",{children:[e.jsx("label",{htmlFor:"registry-url",className:"mb-2 block text-sm font-medium text-gray-700",children:d("market.addRegistryModal.urlLabel")}),e.jsx("input",{id:"registry-url",type:"url",value:t,onChange:y=>r(y.target.value),placeholder:d("market.addRegistryModal.urlPlaceholder"),className:"w-full rounded-lg border border-gray-300 px-4 py-3 text-sm text-gray-900 placeholder:text-gray-400 focus:border-blue-500 focus:outline-none focus:ring-2 focus:ring-blue-500",autoFocus:!0})]}),e.jsx("div",{className:"rounded-xl border border-blue-200 bg-blue-50 px-4 py-4",children:e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsx("div",{className:"flex h-9 w-9 shrink-0 items-center justify-center rounded-lg bg-white text-blue-600",children:e.jsx(Me,{size:18})}),e.jsxs("div",{children:[e.jsx("p",{className:"text-sm font-semibold text-blue-900",children:d("market.addRegistryModal.compatibilityTitle")}),e.jsx("p",{className:"mt-1 text-sm leading-6 text-blue-800",children:d("market.addRegistryModal.compatibilityDescription")})]})]})}),a&&e.jsxs("div",{className:"flex items-start gap-3 rounded-xl border border-red-200 bg-red-50 px-4 py-3 text-red-700",children:[e.jsx(se,{size:18,className:"mt-0.5 shrink-0"}),e.jsx("p",{className:"text-sm",children:a})]})]}),e.jsxs("div",{className:"flex items-center justify-end gap-2 border-t border-gray-200 px-6 py-4",children:[e.jsx("button",{type:"button",onClick:n,disabled:s,className:"rounded-lg bg-gray-100 px-4 py-2 text-sm font-medium text-gray-700 transition-colors hover:bg-gray-200 disabled:cursor-not-allowed disabled:opacity-50",children:d("market.actions.cancel")}),e.jsxs("button",{type:"submit",disabled:s,className:"inline-flex items-center gap-2 rounded-lg bg-blue-500 px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-blue-600 disabled:cursor-not-allowed disabled:opacity-50",children:[s?e.jsx(j,{size:16,className:"animate-spin"}):e.jsx(U,{size:16}),d("market.actions.addRegistry")]})]})]})]})})}function Ye({registry:t,deleting:a,onDelete:s}){const{t:r,i18n:n}=N();return e.jsxs("article",{className:"flex flex-col gap-4 rounded-xl border border-gray-200 bg-white p-5 shadow-sm",children:[e.jsxs("div",{className:"flex items-start justify-between gap-4",children:[e.jsxs("div",{className:"flex min-w-0 items-start gap-3",children:[e.jsx("div",{className:`flex h-11 w-11 shrink-0 items-center justify-center rounded-xl ${t.isVerified?"bg-blue-50 text-blue-600":"bg-gray-100 text-gray-500"}`,children:e.jsx(ie,{size:20})}),e.jsxs("div",{className:"min-w-0",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx("h3",{className:"truncate text-base font-semibold text-gray-900",children:t.name}),e.jsx("span",{className:`inline-flex items-center rounded-full px-2 py-1 text-xs font-medium ${t.isDefault?"bg-amber-50 text-amber-700":"bg-gray-100 text-gray-600"}`,children:t.isDefault?r("market.registryCard.defaultBadge"):r("market.registryCard.customBadge")})]}),e.jsxs("a",{href:t.url,target:"_blank",rel:"noreferrer",className:"mt-2 inline-flex break-all text-sm text-blue-600 hover:text-blue-700",children:[e.jsx("span",{children:t.url}),e.jsx(De,{size:14,className:"ml-1 mt-0.5 shrink-0"})]})]})]}),e.jsxs("button",{type:"button",onClick:()=>s(t.id),disabled:t.isDefault||a,className:`inline-flex items-center gap-2 rounded-lg px-3 py-2 text-sm font-medium transition-colors ${t.isDefault?"cursor-not-allowed bg-gray-100 text-gray-400":"bg-red-50 text-red-600 hover:bg-red-100 disabled:cursor-not-allowed disabled:opacity-50"}`,children:[a?e.jsx(j,{size:15,className:"animate-spin"}):e.jsx(le,{size:15}),t.isDefault?r("market.registryCard.lockedAction"):r("market.actions.deleteRegistry")]})]}),e.jsxs("div",{className:"grid gap-3 sm:grid-cols-2",children:[e.jsxs("div",{className:"rounded-lg border border-gray-200 bg-gray-50 px-4 py-3",children:[e.jsx("p",{className:"text-xs text-gray-500",children:r("market.registryCard.skillCount")}),e.jsx("p",{className:"mt-1 text-lg font-semibold text-gray-900",children:t.skillCount})]}),e.jsxs("div",{className:"rounded-lg border border-gray-200 bg-gray-50 px-4 py-3",children:[e.jsx("p",{className:"text-xs text-gray-500",children:r("market.registryCard.addedAt")}),e.jsx("p",{className:"mt-1 text-sm font-medium text-gray-900",children:ce(t.addedAt,n.language)})]})]}),e.jsx("p",{className:"text-xs text-gray-500",children:t.isDefault?r("market.registryCard.defaultHint"):r("market.registryCard.customHint")})]})}function Ge({registries:t,loading:a,deletingRegistryId:s,onAdd:r,onClose:n,onDelete:o}){const{t:d}=N();return e.jsx("div",{className:"fixed inset-0 z-40 flex items-center justify-center bg-black/40 p-4",children:e.jsxs("div",{role:"dialog","aria-modal":"true",className:"flex max-h-[85vh] w-full max-w-4xl flex-col overflow-hidden rounded-2xl border border-gray-200 bg-white shadow-xl",children:[e.jsxs("div",{className:"flex items-start justify-between gap-4 border-b border-gray-200 px-6 py-5",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"text-lg font-semibold text-gray-900",children:d("market.registryModal.title")}),e.jsx("p",{className:"mt-1 text-sm text-gray-500",children:d("market.registryModal.description")})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs("button",{type:"button",onClick:r,className:"inline-flex items-center gap-2 rounded-lg bg-blue-500 px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-blue-600",children:[e.jsx(U,{size:16}),d("market.actions.addRegistry")]}),e.jsx("button",{type:"button",onClick:n,className:"rounded-lg bg-gray-100 px-4 py-2 text-sm font-medium text-gray-700 transition-colors hover:bg-gray-200",children:d("market.actions.close")})]})]}),e.jsx("div",{className:"min-h-0 flex-1 overflow-y-auto px-6 py-5",children:a?e.jsx("div",{className:"flex items-center justify-center py-16",children:e.jsx(j,{size:22,className:"animate-spin text-gray-400"})}):t.length===0?e.jsxs("div",{className:"rounded-xl border border-dashed border-gray-300 px-6 py-16 text-center",children:[e.jsx("div",{className:"mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-gray-100 text-gray-400",children:e.jsx(ie,{size:20})}),e.jsx("h3",{className:"mt-4 text-base font-semibold text-gray-900",children:d("market.empty.registryTitle")}),e.jsx("p",{className:"mt-2 text-sm text-gray-500",children:d("market.empty.registryDescription")})]}):e.jsx("div",{className:"grid gap-4 xl:grid-cols-2",children:t.map(m=>e.jsx(Ye,{registry:m,deleting:s===m.id,onDelete:o},m.id))})})]})})}function te({skill:t,selected:a,onSelect:s}){const{t:r,i18n:n}=N(),o=Ze(t.updatedAt,n.language),d=B(t.type),m={skill:oe,template:de,agent:re},y={skill:t.isInstalled?"bg-blue-100 text-blue-600":"bg-gray-100 text-gray-500",template:"bg-amber-100 text-amber-700",agent:"bg-emerald-100 text-emerald-700"},c=m[d];return e.jsx("button",{type:"button",onClick:()=>s(t.name),className:`w-full rounded-xl border p-3 text-left transition-colors ${a?"border-blue-200 bg-blue-50 shadow-sm":"border-transparent bg-white hover:border-gray-200 hover:bg-gray-50"}`,children:e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsx("div",{className:`flex h-10 w-10 shrink-0 items-center justify-center rounded-xl ${y[d]}`,children:e.jsx(c,{size:18})}),e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-1.5",children:[e.jsx("span",{className:"truncate text-sm font-semibold text-gray-900",children:t.displayName||t.name}),t.isVerified&&e.jsx(ne,{className:"h-3.5 w-3.5 shrink-0 text-blue-500"}),e.jsx(me,{type:t.type})]}),e.jsx("p",{className:"mt-1 line-clamp-2 text-xs text-gray-500",children:t.description||r("market.card.noDescription")}),e.jsxs("p",{className:"mt-2 text-[11px] text-gray-400",children:[t.registryName||t.author||r("market.card.unknownAuthor"),o?` · ${r("market.list.updatedLabel",{time:o})}`:""]})]}),t.isInstalled&&e.jsx("span",{className:"shrink-0 rounded-full bg-green-100 px-2 py-0.5 text-[10px] font-medium text-green-700",children:r("market.badges.installed")})]})})}function T({icon:t,label:a,value:s}){return e.jsxs("div",{className:"rounded-xl border border-gray-200 bg-gray-50 px-4 py-3",children:[e.jsxs("div",{className:"flex items-center gap-2 text-xs text-gray-500",children:[e.jsx("span",{className:"text-gray-400",children:t}),e.jsx("span",{children:a})]}),e.jsx("p",{className:"mt-2 text-sm font-semibold text-gray-900",children:s})]})}function Je({skill:t,markdownBody:a,descriptionLoading:s,descriptionError:r,busy:n,canInstall:o,onInstall:d,onUninstall:m,onRefresh:y}){const{t:c,i18n:h}=N(),S=typeof(t==null?void 0:t.installCount)=="number";return t?e.jsxs("section",{className:"flex h-full min-h-[520px] flex-col rounded-2xl border border-gray-200 bg-white p-6 shadow-sm",children:[e.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-4 border-b border-gray-200 pb-5",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx("h2",{className:"text-2xl font-semibold text-gray-900",children:t.displayName||t.name}),e.jsxs("span",{className:"rounded-full bg-gray-100 px-2.5 py-1 text-xs font-medium text-gray-600",children:["v",t.version]}),e.jsx(me,{type:t.type}),t.isVerified&&e.jsxs("span",{className:"inline-flex items-center gap-1 rounded-full bg-blue-50 px-2.5 py-1 text-xs font-medium text-blue-700",children:[e.jsx(ne,{size:13}),c("market.badges.verified")]})]}),e.jsx("p",{className:"mt-2 text-sm text-gray-500",children:t.registryName||t.author||c("market.card.unknownAuthor")})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[t.isInstalled?e.jsxs("button",{type:"button",onClick:()=>m(t.name),disabled:n,className:"inline-flex items-center gap-2 rounded-lg bg-red-50 px-4 py-2 text-sm font-medium text-red-600 transition-colors hover:bg-red-100 disabled:cursor-not-allowed disabled:opacity-50",children:[n?e.jsx(j,{size:16,className:"animate-spin"}):e.jsx(le,{size:16}),c("market.actions.uninstall")]}):e.jsxs("button",{type:"button",onClick:()=>d(t),disabled:n||!o,className:"inline-flex items-center gap-2 rounded-lg bg-blue-500 px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-blue-600 disabled:cursor-not-allowed disabled:opacity-50",children:[n?e.jsx(j,{size:16,className:"animate-spin"}):e.jsx(U,{size:16}),c("market.actions.install")]}),e.jsxs("button",{type:"button",onClick:y,className:"inline-flex items-center gap-2 rounded-lg bg-gray-100 px-4 py-2 text-sm font-medium text-gray-700 transition-colors hover:bg-gray-200",children:[e.jsx(ae,{size:16}),c("market.actions.checkUpdates")]})]})]}),e.jsxs("div",{className:"space-y-6 py-6",children:[e.jsxs("div",{children:[e.jsx("h3",{className:"text-sm font-semibold text-gray-900",children:c("market.detail.description")}),e.jsx("div",{className:"mt-2",children:s?e.jsxs("div",{className:"flex items-center gap-2 text-sm text-gray-500",children:[e.jsx(j,{size:16,className:"animate-spin"}),e.jsx("span",{children:c("market.detail.loadingBody")})]}):t.isInstalled?a!=null&&a.trim()?e.jsx(ze,{content:a,className:"text-sm"}):e.jsxs(e.Fragment,{children:[r&&e.jsx("div",{className:"mb-3 rounded-xl border border-amber-200 bg-amber-50 px-4 py-3 text-sm text-amber-800",children:r}),e.jsx("p",{className:"whitespace-pre-wrap text-sm leading-6 text-gray-600",children:t.description||c("market.card.noDescription")})]}):e.jsxs("div",{className:"space-y-3",children:[e.jsx("p",{className:"whitespace-pre-wrap text-sm leading-6 text-gray-600",children:t.description||c("market.card.noDescription")}),e.jsx("div",{className:"rounded-xl border border-blue-200 bg-blue-50 px-4 py-3 text-sm text-blue-800",children:c("market.detail.installToViewBody")})]})})]}),t.tags.length>0&&e.jsxs("div",{children:[e.jsx("h3",{className:"text-sm font-semibold text-gray-900",children:c("market.detail.tags")}),e.jsx("div",{className:"mt-3 flex flex-wrap gap-2",children:t.tags.map(p=>e.jsxs("span",{className:"rounded-full border border-gray-200 bg-gray-50 px-2.5 py-1 text-xs text-gray-600",children:["#",p]},p))})]}),t.authors&&t.authors.length>0&&e.jsxs("div",{children:[e.jsx("h3",{className:"text-sm font-semibold text-gray-900",children:c("market.detail.developers")}),e.jsx("div",{className:"mt-3 space-y-3",children:t.authors.map(p=>e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("img",{src:p.avatarUrl,alt:`@${p.login}`,className:"h-8 w-8 rounded-full border border-gray-200 object-cover"}),e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsx("div",{className:"truncate text-sm font-medium text-gray-900",children:p.name||p.login}),e.jsxs("div",{className:"text-xs text-gray-500",children:["@",p.login]})]}),typeof p.contributions=="number"&&e.jsx("div",{className:"text-xs text-gray-400",children:c("market.detail.contributions",{count:p.contributions})})]},`${t.name}-${p.login}`))})]})]}),e.jsxs("div",{className:`mt-auto grid gap-3 border-t border-gray-200 pt-6 sm:grid-cols-2 ${S?"xl:grid-cols-4":"xl:grid-cols-3"}`,children:[e.jsx(T,{icon:e.jsx(Pe,{size:14}),label:c("market.detail.stats.stars"),value:ee(t.stars,h.language)}),S&&e.jsx(T,{icon:e.jsx(Re,{size:14}),label:c("market.detail.stats.installs"),value:ee(t.installCount,h.language)}),e.jsx(T,{icon:e.jsx($e,{size:14}),label:c("market.detail.stats.license"),value:t.license||c("market.detail.unavailable")}),e.jsx(T,{icon:e.jsx(Ce,{size:14}),label:c("market.detail.stats.updatedAt"),value:ce(t.updatedAt,h.language)})]})]}):e.jsx("div",{className:"flex h-full min-h-[520px] items-center justify-center rounded-2xl border border-gray-200 bg-white p-8 shadow-sm",children:e.jsxs("div",{className:"max-w-sm text-center",children:[e.jsx("div",{className:"mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-gray-100 text-gray-400",children:e.jsx(Ie,{size:20})}),e.jsx("h3",{className:"mt-4 text-base font-semibold text-gray-900",children:c("market.detail.emptyTitle")}),e.jsx("p",{className:"mt-2 text-sm text-gray-500",children:c("market.detail.emptyDescription")})]})})}function et(){const{t}=N(),{setPageHeader:a}=Se(),[s,r]=u.useState(!1),[n,o]=u.useState(!1),[d,m]=u.useState(""),[y,c]=u.useState(null),[h,S]=u.useState({}),[p,E]=u.useState(null),[xe,z]=u.useState(null),{initialized:H,loading:R,savingRegistry:ue,deletingRegistryId:ge,mutatingSkillName:pe,error:Q,registries:ye,officialRegistryId:$,allSkills:v,activeFilter:k,searchQuery:_,selectedSkillName:C,setActiveFilter:he,setSearchQuery:fe,setSelectedSkill:M,initialize:q,refresh:D,addRegistry:W,deleteRegistry:Z,installSkill:X,uninstallSkill:Y,clearError:A}=We();u.useEffect(()=>{H||q().catch(()=>{})},[H,q]);const G=u.useMemo(()=>v.filter(l=>l.isInstalled).length,[v]),b=u.useMemo(()=>{const l=_.trim().toLowerCase();return v.filter(x=>k==="installed"&&!x.isInstalled||k!=="all"&&k!=="installed"&&B(x.type)!==k?!1:l?[x.displayName,x.name,x.description,x.author,x.registryName,...x.tags].filter(g=>!!g).some(g=>g.toLowerCase().includes(l)):!0)},[k,v,_]),i=u.useMemo(()=>b.find(l=>l.name===C)??b[0]??null,[b,C]),V=i?h[i.name]:void 0;u.useEffect(()=>{const l=(i==null?void 0:i.name)??null;l!==C&&M(l)},[i,C,M]),u.useEffect(()=>{if(!(i!=null&&i.isInstalled)){z(null),E(g=>g===(i==null?void 0:i.name)?null:g);return}if(V!==void 0){z(null);return}let l=!1;const x=i.name;return E(x),z(null),f.getInstalledSkillDetail(x).then(g=>{l||S(ke=>({...ke,[x]:g.body??""}))}).catch(g=>{l||z(g instanceof Error?g.message:t("market.errors.detailLoad"))}).finally(()=>{l||E(g=>g===x?null:g)}),()=>{l=!0}},[i==null?void 0:i.isInstalled,i==null?void 0:i.name,V,t]);const F=u.useCallback(l=>{l&&S(x=>{if(!(l in x))return x;const g={...x};return delete g[l],g})},[]);u.useEffect(()=>{a({title:t("market.title"),subtitle:t("market.subtitle.summary",{total:v.length,installed:G}),actions:e.jsxs("button",{type:"button",onClick:()=>{A(),F((i==null?void 0:i.name)??null),D().catch(()=>{})},className:"inline-flex items-center gap-2 rounded-lg bg-gray-100 px-3 py-2 text-sm font-medium text-gray-700 transition-colors hover:bg-gray-200",children:[e.jsx(ae,{size:16,className:R?"animate-spin":""}),t("market.actions.refresh")]})})},[v.length,A,R,D,F,i==null?void 0:i.name,a,t,G]);const be=u.useCallback(l=>{const x=l.registryId??$;x&&X(x,l.name).catch(()=>{})},[X,$]),je=u.useCallback(l=>{window.confirm(t("market.actions.confirmUninstall",{name:l}))&&Y(l).catch(()=>{})},[t,Y]),Ne=u.useCallback(l=>{Z(l).catch(()=>{})},[Z]),ve=u.useCallback(async()=>{c(null);try{await W(d),m(""),o(!1)}catch(l){c(l instanceof Error?l.message:t("market.errors.addRegistry"))}},[W,d,t]),P=b.filter(l=>l.isInstalled),J=b.filter(l=>!l.isInstalled);return e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"flex flex-col gap-6",children:[Q&&e.jsxs("div",{className:"flex items-start gap-3 rounded-xl border border-red-200 bg-red-50 px-4 py-3 text-red-700",children:[e.jsx(se,{size:18,className:"mt-0.5 shrink-0"}),e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsx("p",{className:"text-sm font-medium",children:t("market.errors.bannerTitle")}),e.jsx("p",{className:"mt-1 break-words text-sm",children:Q})]}),e.jsx("button",{type:"button",onClick:()=>{A(),D().catch(()=>{})},className:"shrink-0 rounded-md bg-red-100 px-3 py-1.5 text-xs font-medium text-red-700 transition-colors hover:bg-red-200",children:t("market.actions.retry")})]}),e.jsxs("div",{className:"flex flex-col gap-3 rounded-2xl border border-gray-200 bg-white p-4 shadow-sm lg:flex-row lg:items-center",children:[e.jsxs("div",{className:"relative flex-1",children:[e.jsx(K,{size:16,className:"pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-gray-400"}),e.jsx("input",{type:"search",value:_,onChange:l=>fe(l.target.value),placeholder:t("market.searchPlaceholder"),className:"w-full rounded-xl border border-gray-300 py-2.5 pl-10 pr-4 text-sm text-gray-900 placeholder:text-gray-400 focus:border-blue-500 focus:outline-none focus:ring-2 focus:ring-blue-500"})]}),e.jsxs("button",{type:"button",onClick:()=>r(!0),className:"inline-flex items-center justify-center gap-2 rounded-xl border border-gray-200 bg-gray-50 px-4 py-2.5 text-sm font-medium text-gray-700 transition-colors hover:bg-gray-100",children:[e.jsx(Ve,{size:16}),t("market.actions.manageSources")]})]}),e.jsx("div",{className:"flex flex-wrap gap-2",children:["all","installed","skill","template","agent"].map(l=>e.jsx("button",{type:"button",onClick:()=>he(l),className:`rounded-full border px-3 py-1.5 text-sm font-medium transition-colors ${k===l?"border-blue-500 bg-blue-500 text-white":"border-gray-200 bg-white text-gray-600 hover:bg-gray-50"}`,children:t(`market.filters.${l}`)},l))}),e.jsxs("div",{className:"grid gap-6 lg:grid-cols-[360px_minmax(0,1fr)]",children:[e.jsxs("section",{className:"rounded-2xl border border-gray-200 bg-white shadow-sm",children:[e.jsxs("div",{className:"border-b border-gray-200 px-4 py-3",children:[e.jsx("h2",{className:"text-sm font-semibold text-gray-900",children:t("market.list.title")}),e.jsx("p",{className:"mt-1 text-xs text-gray-500",children:t("market.list.count",{count:b.length})})]}),e.jsx("div",{className:"max-h-[640px] overflow-y-auto p-3",children:R?e.jsx("div",{className:"flex items-center justify-center py-16",children:e.jsx(j,{size:22,className:"animate-spin text-gray-400"})}):b.length===0?e.jsxs("div",{className:"rounded-xl border border-dashed border-gray-300 px-4 py-12 text-center",children:[e.jsx("div",{className:"mx-auto flex h-10 w-10 items-center justify-center rounded-full bg-gray-100 text-gray-400",children:e.jsx(K,{size:18})}),e.jsx("h3",{className:"mt-3 text-sm font-semibold text-gray-900",children:t("market.empty.filteredTitle")}),e.jsx("p",{className:"mt-2 text-xs leading-5 text-gray-500",children:t("market.empty.filteredDescription")})]}):e.jsxs("div",{className:"space-y-3",children:[P.length>0&&e.jsxs("div",{className:"space-y-2",children:[e.jsx("p",{className:"px-1 text-xs font-semibold uppercase tracking-wide text-gray-400",children:t("market.list.installedHeading")}),P.map(l=>e.jsx(te,{skill:l,selected:(i==null?void 0:i.name)===l.name,onSelect:M},l.name))]}),J.length>0&&e.jsxs("div",{className:"space-y-2",children:[P.length>0&&e.jsx("p",{className:"px-1 pt-2 text-xs font-semibold uppercase tracking-wide text-gray-400",children:t("market.list.availableHeading")}),J.map(l=>e.jsx(te,{skill:l,selected:(i==null?void 0:i.name)===l.name,onSelect:M},l.name))]})]})})]}),e.jsx(Je,{skill:i,markdownBody:V,descriptionLoading:i?p===i.name:!1,descriptionError:xe,busy:i?pe===i.name:!1,canInstall:!!((i==null?void 0:i.registryId)??$),onInstall:be,onUninstall:je,onRefresh:()=>{A(),F((i==null?void 0:i.name)??null),D().catch(()=>{})}})]})]}),s&&e.jsx(Ge,{registries:ye,loading:R,deletingRegistryId:ge,onAdd:()=>{c(null),m(""),o(!0)},onClose:()=>r(!1),onDelete:Ne}),n&&e.jsx(Xe,{url:d,error:y,submitting:ue,onChange:m,onClose:()=>{c(null),o(!1)},onSubmit:ve})]})}export{et as default};
@@ -1 +0,0 @@
1
- import{aq as o,ar as n}from"./main-CELBpK6r.js";const t=(r,a)=>o.lang.round(n.parse(r)[a]);export{t as c};
@@ -1 +0,0 @@
1
- import{s as a,c as s,a as e,C as t}from"./chunk-4TB4RGXK-HNNsUbz0.js";import{_ as i}from"./main-CELBpK6r.js";import"./chunk-FMBD7UC4-DyHRLQqX.js";import"./chunk-YZCP3GAM-CHUUnGeN.js";import"./chunk-55IACEB6-qtCgO0r2.js";import"./chunk-EDXVE4YY-BSnDYtsd.js";var u={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{u as diagram};
@@ -1 +0,0 @@
1
- import{s as a,c as s,a as e,C as t}from"./chunk-4TB4RGXK-HNNsUbz0.js";import{_ as i}from"./main-CELBpK6r.js";import"./chunk-FMBD7UC4-DyHRLQqX.js";import"./chunk-YZCP3GAM-CHUUnGeN.js";import"./chunk-55IACEB6-qtCgO0r2.js";import"./chunk-EDXVE4YY-BSnDYtsd.js";var u={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{u as diagram};
@@ -1 +0,0 @@
1
- import{b as r}from"./graph-BVJlrP6V.js";var e=4;function a(o){return r(o,e)}export{a as c};