@pixelbyte-software/pixcode 1.51.8 → 1.52.0

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 (307) hide show
  1. package/CODE_OF_CONDUCT.md +41 -41
  2. package/CONTRIBUTING.md +155 -155
  3. package/LICENSE +718 -718
  4. package/README.de.md +169 -169
  5. package/README.ja.md +167 -167
  6. package/README.ko.md +167 -167
  7. package/README.md +419 -419
  8. package/README.ru.md +169 -169
  9. package/README.tr.md +298 -298
  10. package/README.zh-CN.md +167 -167
  11. package/SECURITY.md +46 -46
  12. package/dist/api-automation.html +110 -110
  13. package/dist/api-docs.html +548 -548
  14. package/dist/assets/{index--kNEhygZ.js → index-HFIf2iQq.js} +153 -153
  15. package/dist/clear-cache.html +85 -85
  16. package/dist/convert-icons.md +52 -52
  17. package/dist/docs.html +308 -308
  18. package/dist/favicon.svg +8 -8
  19. package/dist/features.html +133 -133
  20. package/dist/generate-icons.js +48 -48
  21. package/dist/humans.txt +15 -15
  22. package/dist/icons/codex-white.svg +3 -3
  23. package/dist/icons/codex.svg +3 -3
  24. package/dist/icons/cursor-white.svg +11 -11
  25. package/dist/icons/icon-128x128.svg +9 -9
  26. package/dist/icons/icon-144x144.svg +9 -9
  27. package/dist/icons/icon-152x152.svg +9 -9
  28. package/dist/icons/icon-192x192.svg +9 -9
  29. package/dist/icons/icon-384x384.svg +9 -9
  30. package/dist/icons/icon-512x512.svg +9 -9
  31. package/dist/icons/icon-72x72.svg +9 -9
  32. package/dist/icons/icon-96x96.svg +9 -9
  33. package/dist/icons/icon-template.svg +9 -9
  34. package/dist/icons/qwen-logo.svg +14 -14
  35. package/dist/index.html +58 -58
  36. package/dist/landing.html +268 -268
  37. package/dist/llms-full.txt +119 -119
  38. package/dist/llms.txt +53 -53
  39. package/dist/logo.svg +12 -12
  40. package/dist/manifest.json +60 -60
  41. package/dist/openapi.yaml +1696 -1696
  42. package/dist/orchestration.html +125 -125
  43. package/dist/robots.txt +4 -4
  44. package/dist/site.css +692 -692
  45. package/dist/sitemap.xml +51 -51
  46. package/dist/sw.js +132 -132
  47. package/dist-server/server/cli.js +96 -96
  48. package/dist-server/server/daemon/manager.js +33 -33
  49. package/dist-server/server/daemon-manager.js +64 -64
  50. package/dist-server/server/index.js +91 -65
  51. package/dist-server/server/index.js.map +1 -1
  52. package/dist-server/server/routes/commands.js +25 -25
  53. package/dist-server/server/routes/git.js +17 -17
  54. package/dist-server/server/routes/live-view.js +46 -46
  55. package/dist-server/server/services/hermes-gateway.js +5 -5
  56. package/dist-server/server/services/public-api-manifest.js +51 -51
  57. package/package.json +222 -222
  58. package/scripts/fix-node-pty.js +67 -67
  59. package/scripts/github/create-v1.38-issues.mjs +351 -351
  60. package/scripts/github/create-vscode-workbench-issues.mjs +121 -121
  61. package/scripts/hermes/configure-pixcode-mcp.mjs +165 -165
  62. package/scripts/hermes/pixcode-mcp-server.mjs +1009 -1009
  63. package/scripts/smoke/changes-panel-layout.mjs +48 -48
  64. package/scripts/smoke/chat-composer-fixed-layout.mjs +55 -55
  65. package/scripts/smoke/chat-message-timeline-order.mjs +41 -41
  66. package/scripts/smoke/chat-realtime-hydration.mjs +44 -44
  67. package/scripts/smoke/chat-session-provider-pools.mjs +35 -35
  68. package/scripts/smoke/chat-session-state.mjs +19 -19
  69. package/scripts/smoke/code-editor-theme.mjs +55 -55
  70. package/scripts/smoke/code-editor-vscode-engine.mjs +91 -91
  71. package/scripts/smoke/command-center-agent-writes.mjs +79 -79
  72. package/scripts/smoke/command-center-non-git.mjs +46 -46
  73. package/scripts/smoke/context-packet.mjs +43 -43
  74. package/scripts/smoke/control-room-ux-redesign.mjs +91 -91
  75. package/scripts/smoke/daemon-entrypoint.mjs +20 -20
  76. package/scripts/smoke/default-landing-routing.mjs +33 -33
  77. package/scripts/smoke/desktop-native-notifications.mjs +30 -30
  78. package/scripts/smoke/desktop-tray-icon.mjs +33 -33
  79. package/scripts/smoke/discord-release-workflow.mjs +24 -24
  80. package/scripts/smoke/git-install-update.mjs +255 -255
  81. package/scripts/smoke/handoff-artifact-protocol.mjs +50 -50
  82. package/scripts/smoke/hermes-api-install.mjs +56 -56
  83. package/scripts/smoke/hermes-gateway-persistence.mjs +104 -104
  84. package/scripts/smoke/hermes-mcp-pixcode-roundtrip.mjs +426 -426
  85. package/scripts/smoke/hermes-rest-chat-api.mjs +162 -162
  86. package/scripts/smoke/hermes-rest-chat-live.mjs +45 -45
  87. package/scripts/smoke/hermes-rest-codex-launch.mjs +209 -209
  88. package/scripts/smoke/hermes-rest-gateway.mjs +79 -79
  89. package/scripts/smoke/hermes-rest-live.mjs +42 -42
  90. package/scripts/smoke/hermes-roundtrip.mjs +167 -167
  91. package/scripts/smoke/hermes-settings-commands.mjs +349 -349
  92. package/scripts/smoke/hermes-smoke-launcher-guard.mjs +34 -34
  93. package/scripts/smoke/live-view-diagnostics.mjs +53 -53
  94. package/scripts/smoke/live-view-environment.mjs +92 -92
  95. package/scripts/smoke/live-view-integration.mjs +450 -450
  96. package/scripts/smoke/mac-desktop-runtime.mjs +37 -37
  97. package/scripts/smoke/mobile-tunnel-guidance.mjs +29 -29
  98. package/scripts/smoke/model-registry.mjs +36 -36
  99. package/scripts/smoke/multi-project-ui.mjs +45 -45
  100. package/scripts/smoke/multi-worker-slots.mjs +42 -42
  101. package/scripts/smoke/notification-center.mjs +87 -87
  102. package/scripts/smoke/notification-inapp-preference.mjs +23 -23
  103. package/scripts/smoke/notification-taxonomy.mjs +58 -58
  104. package/scripts/smoke/orchestration-api.mjs +172 -172
  105. package/scripts/smoke/orchestration-execution-dashboard.mjs +33 -33
  106. package/scripts/smoke/orchestration-live-run.mjs +176 -176
  107. package/scripts/smoke/orchestration-mobile-scroll.mjs +29 -29
  108. package/scripts/smoke/orchestration-model-sync.mjs +30 -30
  109. package/scripts/smoke/orchestration-permission-fallback.mjs +34 -34
  110. package/scripts/smoke/orchestration-runtime-guards.mjs +48 -48
  111. package/scripts/smoke/orchestration-user-facing-output.mjs +25 -25
  112. package/scripts/smoke/permission-policy.mjs +50 -50
  113. package/scripts/smoke/pixcode-workbench-1-48.mjs +167 -167
  114. package/scripts/smoke/provider-models-opencode-live.mjs +66 -66
  115. package/scripts/smoke/provider-rest-api.mjs +124 -124
  116. package/scripts/smoke/provider-selection-status.mjs +52 -52
  117. package/scripts/smoke/run-state-refresh.mjs +52 -52
  118. package/scripts/smoke/runtime-manager.mjs +99 -99
  119. package/scripts/smoke/shell-manual-disconnect.mjs +30 -30
  120. package/scripts/smoke/side-panel-editor-layout.mjs +34 -34
  121. package/scripts/smoke/static-root-routing.mjs +21 -21
  122. package/scripts/smoke/strict-handoff-compact.mjs +60 -60
  123. package/scripts/smoke/taskmaster-config.mjs +24 -24
  124. package/scripts/smoke/taskmaster-execution-telegram.mjs +3 -3
  125. package/scripts/smoke/taskmaster-onboarding.mjs +3 -3
  126. package/scripts/smoke/taskmaster-run-graph.mjs +3 -3
  127. package/scripts/smoke/telegram-control.mjs +242 -242
  128. package/scripts/smoke/tunnel-persistence.mjs +56 -56
  129. package/scripts/smoke/update-issue-progress.mjs +69 -69
  130. package/scripts/smoke/update-ux.mjs +55 -55
  131. package/scripts/smoke/v138-completion.mjs +132 -132
  132. package/scripts/smoke/v138-desktop-release-hardening.mjs +69 -69
  133. package/scripts/smoke/v138-diagnostics.mjs +63 -63
  134. package/scripts/smoke/v138-issue-planner.mjs +33 -33
  135. package/scripts/smoke/v143-remote-control.mjs +76 -76
  136. package/scripts/smoke/v144-production-loop.mjs +47 -47
  137. package/scripts/smoke/v145-platformization.mjs +46 -46
  138. package/scripts/smoke/v146-control-room-ui.mjs +150 -150
  139. package/scripts/smoke/version-modal-autoshow.mjs +29 -29
  140. package/scripts/smoke/vscode-workbench-layout.mjs +63 -63
  141. package/scripts/smoke/vscode-workbench-polish.mjs +461 -461
  142. package/scripts/smoke/workflow-fallback-replay.mjs +56 -56
  143. package/scripts/smoke/workflow-templates.mjs +43 -43
  144. package/scripts/smoke/workflow-trace-timeline.mjs +46 -46
  145. package/scripts/update-git-install.mjs +283 -283
  146. package/server/claude-sdk.js +920 -920
  147. package/server/cli.js +1035 -1035
  148. package/server/constants/config.js +4 -4
  149. package/server/cursor-cli.js +344 -344
  150. package/server/daemon/manager.js +563 -563
  151. package/server/daemon-manager.js +964 -964
  152. package/server/database/db.js +895 -895
  153. package/server/database/json-store.js +197 -197
  154. package/server/gemini-cli.js +550 -550
  155. package/server/gemini-response-handler.js +79 -79
  156. package/server/index.js +111 -81
  157. package/server/load-env.js +35 -35
  158. package/server/middleware/auth.js +155 -155
  159. package/server/modules/orchestration/a2a/adapter-registry.ts +108 -108
  160. package/server/modules/orchestration/a2a/adapters/abstract-a2a.adapter.ts +63 -63
  161. package/server/modules/orchestration/a2a/adapters/claude-code.adapter.ts +286 -286
  162. package/server/modules/orchestration/a2a/adapters/codex.adapter.ts +244 -244
  163. package/server/modules/orchestration/a2a/adapters/cursor.adapter.ts +249 -249
  164. package/server/modules/orchestration/a2a/adapters/gemini.adapter.ts +248 -248
  165. package/server/modules/orchestration/a2a/adapters/json-event.adapter.ts +100 -100
  166. package/server/modules/orchestration/a2a/adapters/opencode.adapter.ts +248 -248
  167. package/server/modules/orchestration/a2a/adapters/qwen.adapter.ts +248 -248
  168. package/server/modules/orchestration/a2a/agent-card.ts +55 -55
  169. package/server/modules/orchestration/a2a/routes.ts +590 -590
  170. package/server/modules/orchestration/a2a/task-store.ts +178 -178
  171. package/server/modules/orchestration/a2a/types.ts +126 -126
  172. package/server/modules/orchestration/a2a/validator.ts +113 -113
  173. package/server/modules/orchestration/hermes/hermes.routes.ts +642 -642
  174. package/server/modules/orchestration/index.ts +101 -101
  175. package/server/modules/orchestration/preview/port-watcher.ts +112 -112
  176. package/server/modules/orchestration/preview/preview-proxy.ts +60 -60
  177. package/server/modules/orchestration/preview/types.ts +19 -19
  178. package/server/modules/orchestration/security/permission-policy.ts +401 -401
  179. package/server/modules/orchestration/tasks/orchestration-task-store.ts +41 -41
  180. package/server/modules/orchestration/tasks/orchestration-task.routes.ts +64 -64
  181. package/server/modules/orchestration/tasks/orchestration-task.service.ts +209 -209
  182. package/server/modules/orchestration/tasks/orchestration-task.types.ts +40 -40
  183. package/server/modules/orchestration/tasks/task-run-graph.ts +155 -155
  184. package/server/modules/orchestration/workflows/approval-queue.ts +106 -106
  185. package/server/modules/orchestration/workflows/built-in-workflows.ts +127 -127
  186. package/server/modules/orchestration/workflows/context-packet.ts +186 -186
  187. package/server/modules/orchestration/workflows/handoff-artifact.ts +175 -175
  188. package/server/modules/orchestration/workflows/workflow-fallback-policy.ts +161 -161
  189. package/server/modules/orchestration/workflows/workflow-replay.ts +254 -254
  190. package/server/modules/orchestration/workflows/workflow-runner.ts +2070 -2070
  191. package/server/modules/orchestration/workflows/workflow-store.ts +97 -97
  192. package/server/modules/orchestration/workflows/workflow-templates.ts +272 -272
  193. package/server/modules/orchestration/workflows/workflow-trace.ts +424 -424
  194. package/server/modules/orchestration/workflows/workflow.routes.ts +586 -586
  195. package/server/modules/orchestration/workflows/workflow.types.ts +111 -111
  196. package/server/modules/orchestration/workflows/workspace-target.ts +122 -122
  197. package/server/modules/orchestration/workspace/docker-workspace.ts +136 -136
  198. package/server/modules/orchestration/workspace/path-safety.ts +55 -55
  199. package/server/modules/orchestration/workspace/types.ts +52 -52
  200. package/server/modules/orchestration/workspace/workspace-manager.ts +102 -102
  201. package/server/modules/orchestration/workspace/worktree-workspace.ts +126 -126
  202. package/server/modules/providers/index.ts +2 -2
  203. package/server/modules/providers/list/claude/claude-auth.provider.ts +146 -146
  204. package/server/modules/providers/list/claude/claude-mcp.provider.ts +135 -135
  205. package/server/modules/providers/list/claude/claude-sessions.provider.ts +306 -306
  206. package/server/modules/providers/list/claude/claude.provider.ts +15 -15
  207. package/server/modules/providers/list/codex/codex-auth.provider.ts +117 -117
  208. package/server/modules/providers/list/codex/codex-mcp.provider.ts +135 -135
  209. package/server/modules/providers/list/codex/codex-sessions.provider.ts +319 -319
  210. package/server/modules/providers/list/codex/codex.provider.ts +15 -15
  211. package/server/modules/providers/list/cursor/cursor-auth.provider.ts +147 -147
  212. package/server/modules/providers/list/cursor/cursor-mcp.provider.ts +108 -108
  213. package/server/modules/providers/list/cursor/cursor-sessions.provider.ts +421 -421
  214. package/server/modules/providers/list/cursor/cursor.provider.ts +15 -15
  215. package/server/modules/providers/list/gemini/gemini-auth.provider.ts +173 -173
  216. package/server/modules/providers/list/gemini/gemini-mcp.provider.ts +110 -110
  217. package/server/modules/providers/list/gemini/gemini-sessions.provider.ts +227 -227
  218. package/server/modules/providers/list/gemini/gemini.provider.ts +15 -15
  219. package/server/modules/providers/list/opencode/opencode-auth.provider.ts +131 -131
  220. package/server/modules/providers/list/opencode/opencode-mcp.provider.ts +126 -126
  221. package/server/modules/providers/list/opencode/opencode-sessions.provider.ts +286 -286
  222. package/server/modules/providers/list/opencode/opencode.provider.ts +29 -29
  223. package/server/modules/providers/list/qwen/qwen-auth.provider.ts +146 -146
  224. package/server/modules/providers/list/qwen/qwen-mcp.provider.ts +114 -114
  225. package/server/modules/providers/list/qwen/qwen-sessions.provider.ts +265 -265
  226. package/server/modules/providers/list/qwen/qwen.provider.ts +21 -21
  227. package/server/modules/providers/provider.registry.ts +40 -40
  228. package/server/modules/providers/provider.routes.ts +891 -891
  229. package/server/modules/providers/services/mcp.service.ts +86 -86
  230. package/server/modules/providers/services/provider-auth.service.ts +26 -26
  231. package/server/modules/providers/services/sessions.service.ts +45 -45
  232. package/server/modules/providers/shared/base/abstract.provider.ts +20 -20
  233. package/server/modules/providers/shared/mcp/mcp.provider.ts +151 -151
  234. package/server/modules/providers/shared/provider-configs.ts +142 -142
  235. package/server/modules/providers/tests/mcp.test.ts +293 -293
  236. package/server/openai-codex.js +462 -462
  237. package/server/opencode-cli.js +491 -491
  238. package/server/opencode-response-handler.js +111 -111
  239. package/server/projects.js +3008 -3008
  240. package/server/qwen-code-cli.js +410 -410
  241. package/server/qwen-response-handler.js +73 -73
  242. package/server/routes/agent.js +1435 -1435
  243. package/server/routes/auth.js +142 -142
  244. package/server/routes/codex.js +20 -20
  245. package/server/routes/commands.js +538 -538
  246. package/server/routes/cursor.js +61 -61
  247. package/server/routes/diagnostics.js +41 -41
  248. package/server/routes/gemini.js +25 -25
  249. package/server/routes/git.js +1641 -1641
  250. package/server/routes/live-view.js +387 -387
  251. package/server/routes/mcp-utils.js +13 -13
  252. package/server/routes/messages.js +50 -50
  253. package/server/routes/network.js +117 -117
  254. package/server/routes/platformization.js +182 -182
  255. package/server/routes/plugins.js +320 -320
  256. package/server/routes/production-agent-loop.js +90 -90
  257. package/server/routes/projects.js +911 -911
  258. package/server/routes/public-api.js +34 -34
  259. package/server/routes/qwen.js +27 -27
  260. package/server/routes/remote.js +50 -50
  261. package/server/routes/settings.js +321 -321
  262. package/server/routes/telegram.js +140 -140
  263. package/server/routes/user.js +125 -125
  264. package/server/routes/webhooks.js +63 -63
  265. package/server/services/control-room.js +102 -102
  266. package/server/services/diagnostics.js +165 -165
  267. package/server/services/external-access.js +375 -375
  268. package/server/services/hermes-gateway.js +1562 -1562
  269. package/server/services/hermes-install-jobs.js +729 -729
  270. package/server/services/install-jobs.js +715 -715
  271. package/server/services/live-view.js +956 -956
  272. package/server/services/managed-runtimes.js +493 -493
  273. package/server/services/model-registry.js +144 -144
  274. package/server/services/notification-orchestrator.js +365 -365
  275. package/server/services/notification-taxonomy.js +204 -204
  276. package/server/services/platformization.js +773 -773
  277. package/server/services/production-agent-loop.js +248 -248
  278. package/server/services/provider-cli-versions.js +149 -149
  279. package/server/services/provider-credentials.js +189 -189
  280. package/server/services/provider-models.js +396 -396
  281. package/server/services/public-api-manifest.js +190 -190
  282. package/server/services/remote-connection.js +127 -127
  283. package/server/services/runtime-manager.js +323 -323
  284. package/server/services/startup-update.js +234 -234
  285. package/server/services/telegram/bot.js +331 -331
  286. package/server/services/telegram/control-center.js +979 -979
  287. package/server/services/telegram/telegram-http-client.js +151 -151
  288. package/server/services/telegram/translations.js +340 -340
  289. package/server/services/vapid-keys.js +36 -36
  290. package/server/services/webhooks.js +216 -216
  291. package/server/sessionManager.js +225 -225
  292. package/server/shared/interfaces.ts +54 -54
  293. package/server/shared/types.ts +172 -172
  294. package/server/shared/utils.ts +193 -193
  295. package/server/tsconfig.json +36 -36
  296. package/server/utils/colors.js +21 -21
  297. package/server/utils/commandParser.js +305 -305
  298. package/server/utils/frontmatter.js +18 -18
  299. package/server/utils/gitConfig.js +34 -34
  300. package/server/utils/plugin-loader.js +457 -457
  301. package/server/utils/plugin-process-manager.js +185 -185
  302. package/server/utils/port-access.js +209 -209
  303. package/server/utils/runtime-paths.js +37 -37
  304. package/server/utils/url-detection.js +71 -71
  305. package/server/vite-daemon.js +79 -79
  306. package/shared/modelConstants.js +161 -161
  307. package/shared/networkHosts.js +22 -22
@@ -1,351 +1,351 @@
1
- #!/usr/bin/env node
2
- import fs from 'node:fs';
3
- import https from 'node:https';
4
- import { fileURLToPath } from 'node:url';
5
-
6
- const OWNER = 'alicomert';
7
- const REPO = 'pixcode';
8
- const TRACKING_FILE = 'RELEASE_TRACKING_v1.38.md';
9
-
10
- const issues = [
11
- {
12
- key: 'remote',
13
- placeholder: 'GH-TBD-remote',
14
- title: 'feat(remote): add first-run local/remote connection mode and API URL pairing',
15
- body: [
16
- '## Problem',
17
- 'Pixcode can run on a server, desktop, or local machine, but first-run setup still assumes the current machine is the primary runtime. Users need to choose whether they are using this computer directly or connecting to a remote Pixcode server.',
18
- '',
19
- '## Goal',
20
- 'Add a first-run connection mode before normal setup and update checks: local computer mode or remote server mode. Remote mode should accept an API URL, handle login/register/pairing, show connection health, and keep the app usable when the controlled server continues running.',
21
- '',
22
- '## Requirements',
23
- '- Ask local vs remote before normal onboarding and before startup update flow.',
24
- '- Remote mode accepts server URL and API key/session credentials.',
25
- '- If login/register is needed, guide the user inside the app instead of failing silently.',
26
- '- Show a full-width connection warning when the remote server is unreachable or degraded.',
27
- '- Persist the selected mode and allow changing it from Settings.',
28
- '- Keep update checks and release notes aware of the selected runtime.',
29
- '',
30
- '## Acceptance Criteria',
31
- '- New users can choose remote mode and connect to an existing Pixcode server.',
32
- '- A disconnected remote server shows a clear banner and retry action.',
33
- '- Local mode behavior remains unchanged.',
34
- '- Smoke coverage verifies local/remote mode persistence and health banner behavior.',
35
- ].join('\n'),
36
- },
37
- {
38
- key: 'api',
39
- placeholder: 'GH-TBD-api',
40
- title: 'feat(api): expose complete Pixcode control surface through API keys',
41
- body: [
42
- '## Problem',
43
- 'Pixcode has many internal endpoints, but users need a clean public API model so every major feature can be automated from external clients, scripts, Telegram, or another UI.',
44
- '',
45
- '## Goal',
46
- 'Create a stable API key and base URL system that exposes projects, sessions, providers, orchestration, tasks, files, source-control state, notifications, and settings through documented endpoints.',
47
- '',
48
- '## Requirements',
49
- '- Define public API groups for auth, projects, sessions, provider runs, orchestration, Taskmaster tasks, notifications, files, git/source-control, settings, and update status.',
50
- '- Keep px_ API key prefix and support scoped/revocable keys.',
51
- '- Add OpenAPI coverage for the public routes.',
52
- '- Ensure Telegram and future remote clients use the same API/service layer instead of separate logic.',
53
- '- Add rate limits and audit records for sensitive actions.',
54
- '',
55
- '## Acceptance Criteria',
56
- '- A user can operate core Pixcode flows using API URL + API key without the web UI.',
57
- '- OpenAPI docs include authenticated examples.',
58
- '- Invalid/missing scopes produce clear 401/403 responses.',
59
- '- Smoke coverage validates at least one full API-key flow: create/list project -> run provider prompt -> fetch result.',
60
- ].join('\n'),
61
- },
62
- {
63
- key: 'telegram',
64
- placeholder: 'GH-TBD-telegram',
65
- title: 'feat(telegram): reach web UI feature parity for remote control',
66
- body: [
67
- '## Problem',
68
- 'Telegram control exists, but the long-term product goal is to manage Pixcode without opening the web UI. Telegram should not be just completion notifications or simple forwarding.',
69
- '',
70
- '## Goal',
71
- 'Make Telegram a first-class Pixcode control client for sessions, projects, providers, models, orchestration, Taskmaster, settings, notifications, and progress/output preferences.',
72
- '',
73
- '## Requirements',
74
- '- Add structured menus for active sessions, new chat, existing project, provider/model selection, orchestration workflows, Taskmaster tasks, and settings.',
75
- '- Let users choose notification granularity: final result only, step summaries, all agent outputs, errors only.',
76
- '- Allow selecting active worker slot and project from Telegram.',
77
- '- Support task creation/start/stop/status from Telegram.',
78
- '- Keep inline menus edited in place to avoid chat spam.',
79
- '- Respect user language preference across every menu.',
80
- '',
81
- '## Acceptance Criteria',
82
- '- A linked Telegram user can start an orchestration run and monitor it without the web UI.',
83
- '- A linked Telegram user can create and run a Taskmaster task.',
84
- '- Telegram can switch active project/session/provider/model.',
85
- '- Smoke coverage verifies command routing, callback routing, language, and task/run status messages.',
86
- ].join('\n'),
87
- },
88
- {
89
- key: 'taskmaster',
90
- placeholder: 'GH-TBD-taskmaster',
91
- title: 'feat(tasks): make Taskmaster the shared execution queue for CLI agents',
92
- body: [
93
- '## Problem',
94
- 'Taskmaster setup and Telegram execution foundations exist, but tasks are not yet the shared queue that coordinates all CLI agents and long-running project work.',
95
- '',
96
- '## Goal',
97
- 'Make Taskmaster a first-class execution backbone: create tasks, assign provider/model, run until completion, update progress, retry/fallback on errors, and expose the same state in UI, API, and Telegram.',
98
- '',
99
- '## Requirements',
100
- '- Add task create/edit/list/detail flows in the web UI.',
101
- '- Bind tasks to project path, provider, model, permission mode, fallback provider, and worker slot.',
102
- '- Persist step summaries, final output, failure reasons, and changed files per task.',
103
- '- Support retry, pause/cancel, fallback, and continue-from-last-output.',
104
- '- Emit notifications for task started, waiting, completed, failed, fallback used.',
105
- '- Make Telegram and API operate the same task model.',
106
- '',
107
- '## Acceptance Criteria',
108
- '- A task can be created in UI/API/Telegram and run by a selected CLI provider.',
109
- '- Failed provider execution can route to configured fallback.',
110
- '- Task detail shows progress, outputs, changed files, and final summary.',
111
- '- Smoke coverage validates create -> dispatch -> progress -> completion/failure state.',
112
- ].join('\n'),
113
- },
114
- {
115
- key: 'plugins',
116
- placeholder: 'GH-TBD-plugins',
117
- title: 'feat(providers): expose CLI plugin and external tool configuration',
118
- body: [
119
- '## Problem',
120
- 'Claude, Codex, OpenCode, Gemini, Qwen, and Cursor have their own plugin/MCP/tool configuration surfaces, but Pixcode does not yet make those external configurations visible and manageable in one place.',
121
- '',
122
- '## Goal',
123
- 'Add provider plugin/tool configuration management so users can inspect, enable, disable, update, and validate provider-specific plugins/MCP/tool integrations without leaving Pixcode.',
124
- '',
125
- '## Requirements',
126
- '- Detect provider-specific plugin/tool config locations where supported.',
127
- '- Show installed/available plugin state per provider.',
128
- '- Allow safe enable/disable/update with preview and backup.',
129
- '- Add validation and repair hints for broken plugin configs.',
130
- '- Avoid IDE-specific integrations unless explicitly requested.',
131
- '- Keep secrets redacted.',
132
- '',
133
- '## Acceptance Criteria',
134
- '- Settings shows provider plugin/tool state without slow repeated checks.',
135
- '- Users can refresh plugin state manually.',
136
- '- Broken config produces actionable diagnostics.',
137
- '- Smoke coverage validates config discovery/parsing for sample provider configs.',
138
- ].join('\n'),
139
- },
140
- {
141
- key: 'desktop',
142
- placeholder: 'GH-TBD-desktop',
143
- title: 'build(desktop): harden installer release, signing, and update recovery',
144
- body: [
145
- '## Problem',
146
- 'Desktop installers build, but macOS unsigned-app warnings, release artifact confidence, and update recovery need a dedicated release-hardening pass.',
147
- '',
148
- '## Goal',
149
- 'Improve desktop release quality for .exe, .dmg, and AppImage users while keeping npm/server update recovery reliable.',
150
- '',
151
- '## Requirements',
152
- '- Document and/or implement macOS signing/notarization path.',
153
- '- Surface unsigned macOS warning guidance in README/release docs until signing is complete.',
154
- '- Verify installer artifacts against the app version and bundled Pixcode dependency.',
155
- '- Keep startup update/recovery visible to users.',
156
- '- Add release checklist coverage for desktop artifacts.',
157
- '',
158
- '## Acceptance Criteria',
159
- '- Desktop artifact versions match package version.',
160
- '- Release notes clearly explain macOS unsigned behavior until signing is complete.',
161
- '- Installer build workflow status is tracked as part of release readiness.',
162
- '- Smoke or script coverage verifies desktop package version alignment.',
163
- ].join('\n'),
164
- },
165
- {
166
- key: 'observability',
167
- placeholder: 'GH-TBD-observability',
168
- title: 'feat(observability): add run diagnostics and provider health visibility',
169
- body: [
170
- '## Problem',
171
- 'When a provider, workflow, Telegram action, or task stalls, users need a clear reason instead of guessing from blank screens or network panels.',
172
- '',
173
- '## Goal',
174
- 'Add a diagnostics surface that explains provider availability, run state, queued work, recent errors, CLI auth/install status, WebSocket health, and notification delivery.',
175
- '',
176
- '## Requirements',
177
- '- Add a diagnostics page/panel for provider health, active runs, WebSocket state, notification channel status, and recent errors.',
178
- '- Add lightweight server-side event/error records for provider runs and workflow tasks.',
179
- '- Show stalled/waiting/error states in user language.',
180
- '- Add manual refresh instead of expensive repeated checks.',
181
- '- Include copyable diagnostics bundle for support/debugging.',
182
- '',
183
- '## Acceptance Criteria',
184
- '- Users can see why a CLI is unavailable or why a run is waiting.',
185
- '- Settings no longer blocks on repeated provider checks.',
186
- '- Diagnostics can be copied without leaking secrets.',
187
- '- Smoke coverage validates health-state aggregation and secret redaction.',
188
- ].join('\n'),
189
- },
190
- ];
191
-
192
- function buildPayload(issueNumbers = new Map()) {
193
- const scope = issues
194
- .map(issue => {
195
- const reference = issueNumbers.has(issue.key) ? `#${issueNumbers.get(issue.key)}` : issue.placeholder;
196
- return `- ${reference} ${issue.title}`;
197
- })
198
- .join('\n');
199
-
200
- const epic = {
201
- key: 'epic',
202
- placeholder: 'GH-TBD-epic',
203
- title: 'epic(product): track v1.38 remote API and task operations',
204
- body: [
205
- '## Goal',
206
- 'Track the v1.38 remote-control, API, task, provider, desktop, and diagnostics package as a GitHub-native work plan. v1.37 shipped the orchestration reliability foundation; v1.38 should make Pixcode easier to operate remotely, automate externally, and diagnose confidently.',
207
- '',
208
- '## Scope',
209
- scope,
210
- '',
211
- '## Release Strategy',
212
- '1. Stabilize remote/local first-run mode and public API foundation.',
213
- '2. Build Telegram and Taskmaster on the same API/task service model.',
214
- '3. Add provider plugin/tool configuration visibility and diagnostics.',
215
- '4. Harden desktop installer/signing/update recovery paths.',
216
- '5. Ship release notes with issue-backed progress metadata.',
217
- '',
218
- '## Acceptance Criteria',
219
- '- Each child issue has implementation and smoke coverage before closure.',
220
- '- The v1.38 release notes reference completed issue numbers.',
221
- '- Update UI can show issue-backed progress for v1.38.',
222
- '- API/Telegram/Taskmaster work share service contracts instead of divergent behavior.',
223
- ].join('\n'),
224
- };
225
-
226
- return {
227
- version: '1.38',
228
- owner: OWNER,
229
- repo: REPO,
230
- issues,
231
- epic,
232
- trackingReplacements: [
233
- ...issues.map(issue => ({
234
- placeholder: issue.placeholder,
235
- value: issueNumbers.has(issue.key) ? `#${issueNumbers.get(issue.key)}` : issue.placeholder,
236
- })),
237
- {
238
- placeholder: epic.placeholder,
239
- value: issueNumbers.has('epic') ? `#${issueNumbers.get('epic')}` : epic.placeholder,
240
- },
241
- ],
242
- };
243
- }
244
-
245
- function githubRequest(method, path, payload) {
246
- const token = process.env.GITHUB_TOKEN;
247
- if (!token) {
248
- throw new Error('GITHUB_TOKEN is required for --apply');
249
- }
250
-
251
- const data = payload ? JSON.stringify(payload) : undefined;
252
- return new Promise((resolve, reject) => {
253
- const req = https.request({
254
- hostname: 'api.github.com',
255
- path,
256
- method,
257
- headers: {
258
- Authorization: `Bearer ${token}`,
259
- Accept: 'application/vnd.github+json',
260
- 'User-Agent': 'pixcode-v138-issue-planner',
261
- 'X-GitHub-Api-Version': '2022-11-28',
262
- ...(data ? { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(data) } : {}),
263
- },
264
- }, res => {
265
- let raw = '';
266
- res.setEncoding('utf8');
267
- res.on('data', chunk => {
268
- raw += chunk;
269
- });
270
- res.on('end', () => {
271
- if (res.statusCode >= 200 && res.statusCode < 300) {
272
- resolve(raw ? JSON.parse(raw) : null);
273
- return;
274
- }
275
- reject(new Error(`${method} ${path} -> ${res.statusCode}: ${raw}`));
276
- });
277
- });
278
- req.on('error', reject);
279
- if (data) {
280
- req.write(data);
281
- }
282
- req.end();
283
- });
284
- }
285
-
286
- async function findExistingIssue(title) {
287
- const q = encodeURIComponent(`repo:${OWNER}/${REPO} type:issue in:title "${title}"`);
288
- const result = await githubRequest('GET', `/search/issues?q=${q}&per_page=10`);
289
- return result.items?.find(item => item.title === title) || null;
290
- }
291
-
292
- async function createOrReuseIssue(issue) {
293
- const existing = await findExistingIssue(issue.title);
294
- if (existing) {
295
- return existing;
296
- }
297
- return await githubRequest('POST', `/repos/${OWNER}/${REPO}/issues`, {
298
- title: issue.title,
299
- body: issue.body,
300
- });
301
- }
302
-
303
- function writeTracking(payload) {
304
- let content = fs.readFileSync(TRACKING_FILE, 'utf8');
305
- for (const replacement of payload.trackingReplacements) {
306
- content = content.replaceAll(replacement.placeholder, replacement.value);
307
- }
308
- fs.writeFileSync(TRACKING_FILE, content);
309
- }
310
-
311
- async function main() {
312
- const args = new Set(process.argv.slice(2));
313
- const dryRun = args.has('--dry-run') || !args.has('--apply');
314
- const shouldWriteTracking = args.has('--write-tracking') || args.has('--apply');
315
-
316
- if (dryRun) {
317
- process.stdout.write(`${JSON.stringify(buildPayload(), null, 2)}\n`);
318
- return;
319
- }
320
-
321
- const numbers = new Map();
322
- for (const issue of issues) {
323
- const created = await createOrReuseIssue(issue);
324
- numbers.set(issue.key, created.number);
325
- console.log(`#${created.number} ${created.title}`);
326
- }
327
-
328
- const payloadBeforeEpic = buildPayload(numbers);
329
- const epic = await createOrReuseIssue(payloadBeforeEpic.epic);
330
- numbers.set('epic', epic.number);
331
- console.log(`#${epic.number} ${epic.title}`);
332
-
333
- const finalPayload = buildPayload(numbers);
334
- if (shouldWriteTracking) {
335
- writeTracking(finalPayload);
336
- console.log(`${TRACKING_FILE} updated`);
337
- }
338
- }
339
-
340
- const invokedPath = process.argv[1] ? fileURLToPath(import.meta.url) === process.argv[1] : false;
341
- if (invokedPath) {
342
- try {
343
- await main();
344
- } catch (error) {
345
- const message = error instanceof Error ? error.message : String(error);
346
- console.error(`Failed to create v1.38 issues: ${message}`);
347
- process.exitCode = 1;
348
- }
349
- }
350
-
351
- export { buildPayload, issues };
1
+ #!/usr/bin/env node
2
+ import fs from 'node:fs';
3
+ import https from 'node:https';
4
+ import { fileURLToPath } from 'node:url';
5
+
6
+ const OWNER = 'alicomert';
7
+ const REPO = 'pixcode';
8
+ const TRACKING_FILE = 'RELEASE_TRACKING_v1.38.md';
9
+
10
+ const issues = [
11
+ {
12
+ key: 'remote',
13
+ placeholder: 'GH-TBD-remote',
14
+ title: 'feat(remote): add first-run local/remote connection mode and API URL pairing',
15
+ body: [
16
+ '## Problem',
17
+ 'Pixcode can run on a server, desktop, or local machine, but first-run setup still assumes the current machine is the primary runtime. Users need to choose whether they are using this computer directly or connecting to a remote Pixcode server.',
18
+ '',
19
+ '## Goal',
20
+ 'Add a first-run connection mode before normal setup and update checks: local computer mode or remote server mode. Remote mode should accept an API URL, handle login/register/pairing, show connection health, and keep the app usable when the controlled server continues running.',
21
+ '',
22
+ '## Requirements',
23
+ '- Ask local vs remote before normal onboarding and before startup update flow.',
24
+ '- Remote mode accepts server URL and API key/session credentials.',
25
+ '- If login/register is needed, guide the user inside the app instead of failing silently.',
26
+ '- Show a full-width connection warning when the remote server is unreachable or degraded.',
27
+ '- Persist the selected mode and allow changing it from Settings.',
28
+ '- Keep update checks and release notes aware of the selected runtime.',
29
+ '',
30
+ '## Acceptance Criteria',
31
+ '- New users can choose remote mode and connect to an existing Pixcode server.',
32
+ '- A disconnected remote server shows a clear banner and retry action.',
33
+ '- Local mode behavior remains unchanged.',
34
+ '- Smoke coverage verifies local/remote mode persistence and health banner behavior.',
35
+ ].join('\n'),
36
+ },
37
+ {
38
+ key: 'api',
39
+ placeholder: 'GH-TBD-api',
40
+ title: 'feat(api): expose complete Pixcode control surface through API keys',
41
+ body: [
42
+ '## Problem',
43
+ 'Pixcode has many internal endpoints, but users need a clean public API model so every major feature can be automated from external clients, scripts, Telegram, or another UI.',
44
+ '',
45
+ '## Goal',
46
+ 'Create a stable API key and base URL system that exposes projects, sessions, providers, orchestration, tasks, files, source-control state, notifications, and settings through documented endpoints.',
47
+ '',
48
+ '## Requirements',
49
+ '- Define public API groups for auth, projects, sessions, provider runs, orchestration, Taskmaster tasks, notifications, files, git/source-control, settings, and update status.',
50
+ '- Keep px_ API key prefix and support scoped/revocable keys.',
51
+ '- Add OpenAPI coverage for the public routes.',
52
+ '- Ensure Telegram and future remote clients use the same API/service layer instead of separate logic.',
53
+ '- Add rate limits and audit records for sensitive actions.',
54
+ '',
55
+ '## Acceptance Criteria',
56
+ '- A user can operate core Pixcode flows using API URL + API key without the web UI.',
57
+ '- OpenAPI docs include authenticated examples.',
58
+ '- Invalid/missing scopes produce clear 401/403 responses.',
59
+ '- Smoke coverage validates at least one full API-key flow: create/list project -> run provider prompt -> fetch result.',
60
+ ].join('\n'),
61
+ },
62
+ {
63
+ key: 'telegram',
64
+ placeholder: 'GH-TBD-telegram',
65
+ title: 'feat(telegram): reach web UI feature parity for remote control',
66
+ body: [
67
+ '## Problem',
68
+ 'Telegram control exists, but the long-term product goal is to manage Pixcode without opening the web UI. Telegram should not be just completion notifications or simple forwarding.',
69
+ '',
70
+ '## Goal',
71
+ 'Make Telegram a first-class Pixcode control client for sessions, projects, providers, models, orchestration, Taskmaster, settings, notifications, and progress/output preferences.',
72
+ '',
73
+ '## Requirements',
74
+ '- Add structured menus for active sessions, new chat, existing project, provider/model selection, orchestration workflows, Taskmaster tasks, and settings.',
75
+ '- Let users choose notification granularity: final result only, step summaries, all agent outputs, errors only.',
76
+ '- Allow selecting active worker slot and project from Telegram.',
77
+ '- Support task creation/start/stop/status from Telegram.',
78
+ '- Keep inline menus edited in place to avoid chat spam.',
79
+ '- Respect user language preference across every menu.',
80
+ '',
81
+ '## Acceptance Criteria',
82
+ '- A linked Telegram user can start an orchestration run and monitor it without the web UI.',
83
+ '- A linked Telegram user can create and run a Taskmaster task.',
84
+ '- Telegram can switch active project/session/provider/model.',
85
+ '- Smoke coverage verifies command routing, callback routing, language, and task/run status messages.',
86
+ ].join('\n'),
87
+ },
88
+ {
89
+ key: 'taskmaster',
90
+ placeholder: 'GH-TBD-taskmaster',
91
+ title: 'feat(tasks): make Taskmaster the shared execution queue for CLI agents',
92
+ body: [
93
+ '## Problem',
94
+ 'Taskmaster setup and Telegram execution foundations exist, but tasks are not yet the shared queue that coordinates all CLI agents and long-running project work.',
95
+ '',
96
+ '## Goal',
97
+ 'Make Taskmaster a first-class execution backbone: create tasks, assign provider/model, run until completion, update progress, retry/fallback on errors, and expose the same state in UI, API, and Telegram.',
98
+ '',
99
+ '## Requirements',
100
+ '- Add task create/edit/list/detail flows in the web UI.',
101
+ '- Bind tasks to project path, provider, model, permission mode, fallback provider, and worker slot.',
102
+ '- Persist step summaries, final output, failure reasons, and changed files per task.',
103
+ '- Support retry, pause/cancel, fallback, and continue-from-last-output.',
104
+ '- Emit notifications for task started, waiting, completed, failed, fallback used.',
105
+ '- Make Telegram and API operate the same task model.',
106
+ '',
107
+ '## Acceptance Criteria',
108
+ '- A task can be created in UI/API/Telegram and run by a selected CLI provider.',
109
+ '- Failed provider execution can route to configured fallback.',
110
+ '- Task detail shows progress, outputs, changed files, and final summary.',
111
+ '- Smoke coverage validates create -> dispatch -> progress -> completion/failure state.',
112
+ ].join('\n'),
113
+ },
114
+ {
115
+ key: 'plugins',
116
+ placeholder: 'GH-TBD-plugins',
117
+ title: 'feat(providers): expose CLI plugin and external tool configuration',
118
+ body: [
119
+ '## Problem',
120
+ 'Claude, Codex, OpenCode, Gemini, Qwen, and Cursor have their own plugin/MCP/tool configuration surfaces, but Pixcode does not yet make those external configurations visible and manageable in one place.',
121
+ '',
122
+ '## Goal',
123
+ 'Add provider plugin/tool configuration management so users can inspect, enable, disable, update, and validate provider-specific plugins/MCP/tool integrations without leaving Pixcode.',
124
+ '',
125
+ '## Requirements',
126
+ '- Detect provider-specific plugin/tool config locations where supported.',
127
+ '- Show installed/available plugin state per provider.',
128
+ '- Allow safe enable/disable/update with preview and backup.',
129
+ '- Add validation and repair hints for broken plugin configs.',
130
+ '- Avoid IDE-specific integrations unless explicitly requested.',
131
+ '- Keep secrets redacted.',
132
+ '',
133
+ '## Acceptance Criteria',
134
+ '- Settings shows provider plugin/tool state without slow repeated checks.',
135
+ '- Users can refresh plugin state manually.',
136
+ '- Broken config produces actionable diagnostics.',
137
+ '- Smoke coverage validates config discovery/parsing for sample provider configs.',
138
+ ].join('\n'),
139
+ },
140
+ {
141
+ key: 'desktop',
142
+ placeholder: 'GH-TBD-desktop',
143
+ title: 'build(desktop): harden installer release, signing, and update recovery',
144
+ body: [
145
+ '## Problem',
146
+ 'Desktop installers build, but macOS unsigned-app warnings, release artifact confidence, and update recovery need a dedicated release-hardening pass.',
147
+ '',
148
+ '## Goal',
149
+ 'Improve desktop release quality for .exe, .dmg, and AppImage users while keeping npm/server update recovery reliable.',
150
+ '',
151
+ '## Requirements',
152
+ '- Document and/or implement macOS signing/notarization path.',
153
+ '- Surface unsigned macOS warning guidance in README/release docs until signing is complete.',
154
+ '- Verify installer artifacts against the app version and bundled Pixcode dependency.',
155
+ '- Keep startup update/recovery visible to users.',
156
+ '- Add release checklist coverage for desktop artifacts.',
157
+ '',
158
+ '## Acceptance Criteria',
159
+ '- Desktop artifact versions match package version.',
160
+ '- Release notes clearly explain macOS unsigned behavior until signing is complete.',
161
+ '- Installer build workflow status is tracked as part of release readiness.',
162
+ '- Smoke or script coverage verifies desktop package version alignment.',
163
+ ].join('\n'),
164
+ },
165
+ {
166
+ key: 'observability',
167
+ placeholder: 'GH-TBD-observability',
168
+ title: 'feat(observability): add run diagnostics and provider health visibility',
169
+ body: [
170
+ '## Problem',
171
+ 'When a provider, workflow, Telegram action, or task stalls, users need a clear reason instead of guessing from blank screens or network panels.',
172
+ '',
173
+ '## Goal',
174
+ 'Add a diagnostics surface that explains provider availability, run state, queued work, recent errors, CLI auth/install status, WebSocket health, and notification delivery.',
175
+ '',
176
+ '## Requirements',
177
+ '- Add a diagnostics page/panel for provider health, active runs, WebSocket state, notification channel status, and recent errors.',
178
+ '- Add lightweight server-side event/error records for provider runs and workflow tasks.',
179
+ '- Show stalled/waiting/error states in user language.',
180
+ '- Add manual refresh instead of expensive repeated checks.',
181
+ '- Include copyable diagnostics bundle for support/debugging.',
182
+ '',
183
+ '## Acceptance Criteria',
184
+ '- Users can see why a CLI is unavailable or why a run is waiting.',
185
+ '- Settings no longer blocks on repeated provider checks.',
186
+ '- Diagnostics can be copied without leaking secrets.',
187
+ '- Smoke coverage validates health-state aggregation and secret redaction.',
188
+ ].join('\n'),
189
+ },
190
+ ];
191
+
192
+ function buildPayload(issueNumbers = new Map()) {
193
+ const scope = issues
194
+ .map(issue => {
195
+ const reference = issueNumbers.has(issue.key) ? `#${issueNumbers.get(issue.key)}` : issue.placeholder;
196
+ return `- ${reference} ${issue.title}`;
197
+ })
198
+ .join('\n');
199
+
200
+ const epic = {
201
+ key: 'epic',
202
+ placeholder: 'GH-TBD-epic',
203
+ title: 'epic(product): track v1.38 remote API and task operations',
204
+ body: [
205
+ '## Goal',
206
+ 'Track the v1.38 remote-control, API, task, provider, desktop, and diagnostics package as a GitHub-native work plan. v1.37 shipped the orchestration reliability foundation; v1.38 should make Pixcode easier to operate remotely, automate externally, and diagnose confidently.',
207
+ '',
208
+ '## Scope',
209
+ scope,
210
+ '',
211
+ '## Release Strategy',
212
+ '1. Stabilize remote/local first-run mode and public API foundation.',
213
+ '2. Build Telegram and Taskmaster on the same API/task service model.',
214
+ '3. Add provider plugin/tool configuration visibility and diagnostics.',
215
+ '4. Harden desktop installer/signing/update recovery paths.',
216
+ '5. Ship release notes with issue-backed progress metadata.',
217
+ '',
218
+ '## Acceptance Criteria',
219
+ '- Each child issue has implementation and smoke coverage before closure.',
220
+ '- The v1.38 release notes reference completed issue numbers.',
221
+ '- Update UI can show issue-backed progress for v1.38.',
222
+ '- API/Telegram/Taskmaster work share service contracts instead of divergent behavior.',
223
+ ].join('\n'),
224
+ };
225
+
226
+ return {
227
+ version: '1.38',
228
+ owner: OWNER,
229
+ repo: REPO,
230
+ issues,
231
+ epic,
232
+ trackingReplacements: [
233
+ ...issues.map(issue => ({
234
+ placeholder: issue.placeholder,
235
+ value: issueNumbers.has(issue.key) ? `#${issueNumbers.get(issue.key)}` : issue.placeholder,
236
+ })),
237
+ {
238
+ placeholder: epic.placeholder,
239
+ value: issueNumbers.has('epic') ? `#${issueNumbers.get('epic')}` : epic.placeholder,
240
+ },
241
+ ],
242
+ };
243
+ }
244
+
245
+ function githubRequest(method, path, payload) {
246
+ const token = process.env.GITHUB_TOKEN;
247
+ if (!token) {
248
+ throw new Error('GITHUB_TOKEN is required for --apply');
249
+ }
250
+
251
+ const data = payload ? JSON.stringify(payload) : undefined;
252
+ return new Promise((resolve, reject) => {
253
+ const req = https.request({
254
+ hostname: 'api.github.com',
255
+ path,
256
+ method,
257
+ headers: {
258
+ Authorization: `Bearer ${token}`,
259
+ Accept: 'application/vnd.github+json',
260
+ 'User-Agent': 'pixcode-v138-issue-planner',
261
+ 'X-GitHub-Api-Version': '2022-11-28',
262
+ ...(data ? { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(data) } : {}),
263
+ },
264
+ }, res => {
265
+ let raw = '';
266
+ res.setEncoding('utf8');
267
+ res.on('data', chunk => {
268
+ raw += chunk;
269
+ });
270
+ res.on('end', () => {
271
+ if (res.statusCode >= 200 && res.statusCode < 300) {
272
+ resolve(raw ? JSON.parse(raw) : null);
273
+ return;
274
+ }
275
+ reject(new Error(`${method} ${path} -> ${res.statusCode}: ${raw}`));
276
+ });
277
+ });
278
+ req.on('error', reject);
279
+ if (data) {
280
+ req.write(data);
281
+ }
282
+ req.end();
283
+ });
284
+ }
285
+
286
+ async function findExistingIssue(title) {
287
+ const q = encodeURIComponent(`repo:${OWNER}/${REPO} type:issue in:title "${title}"`);
288
+ const result = await githubRequest('GET', `/search/issues?q=${q}&per_page=10`);
289
+ return result.items?.find(item => item.title === title) || null;
290
+ }
291
+
292
+ async function createOrReuseIssue(issue) {
293
+ const existing = await findExistingIssue(issue.title);
294
+ if (existing) {
295
+ return existing;
296
+ }
297
+ return await githubRequest('POST', `/repos/${OWNER}/${REPO}/issues`, {
298
+ title: issue.title,
299
+ body: issue.body,
300
+ });
301
+ }
302
+
303
+ function writeTracking(payload) {
304
+ let content = fs.readFileSync(TRACKING_FILE, 'utf8');
305
+ for (const replacement of payload.trackingReplacements) {
306
+ content = content.replaceAll(replacement.placeholder, replacement.value);
307
+ }
308
+ fs.writeFileSync(TRACKING_FILE, content);
309
+ }
310
+
311
+ async function main() {
312
+ const args = new Set(process.argv.slice(2));
313
+ const dryRun = args.has('--dry-run') || !args.has('--apply');
314
+ const shouldWriteTracking = args.has('--write-tracking') || args.has('--apply');
315
+
316
+ if (dryRun) {
317
+ process.stdout.write(`${JSON.stringify(buildPayload(), null, 2)}\n`);
318
+ return;
319
+ }
320
+
321
+ const numbers = new Map();
322
+ for (const issue of issues) {
323
+ const created = await createOrReuseIssue(issue);
324
+ numbers.set(issue.key, created.number);
325
+ console.log(`#${created.number} ${created.title}`);
326
+ }
327
+
328
+ const payloadBeforeEpic = buildPayload(numbers);
329
+ const epic = await createOrReuseIssue(payloadBeforeEpic.epic);
330
+ numbers.set('epic', epic.number);
331
+ console.log(`#${epic.number} ${epic.title}`);
332
+
333
+ const finalPayload = buildPayload(numbers);
334
+ if (shouldWriteTracking) {
335
+ writeTracking(finalPayload);
336
+ console.log(`${TRACKING_FILE} updated`);
337
+ }
338
+ }
339
+
340
+ const invokedPath = process.argv[1] ? fileURLToPath(import.meta.url) === process.argv[1] : false;
341
+ if (invokedPath) {
342
+ try {
343
+ await main();
344
+ } catch (error) {
345
+ const message = error instanceof Error ? error.message : String(error);
346
+ console.error(`Failed to create v1.38 issues: ${message}`);
347
+ process.exitCode = 1;
348
+ }
349
+ }
350
+
351
+ export { buildPayload, issues };