@pixelbyte-software/pixcode 1.34.0 → 1.35.1

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 (247) hide show
  1. package/LICENSE +718 -718
  2. package/README.de.md +248 -248
  3. package/README.ja.md +240 -240
  4. package/README.ko.md +240 -240
  5. package/README.md +303 -303
  6. package/README.ru.md +248 -248
  7. package/README.tr.md +250 -250
  8. package/README.zh-CN.md +240 -240
  9. package/dist/api-docs.html +548 -395
  10. package/dist/assets/index-B8w57E1r.css +32 -0
  11. package/dist/assets/index-CBdsvGSR.js +854 -0
  12. package/dist/clear-cache.html +85 -85
  13. package/dist/convert-icons.md +52 -52
  14. package/dist/favicon.svg +8 -8
  15. package/dist/generate-icons.js +48 -48
  16. package/dist/icons/codex-white.svg +3 -3
  17. package/dist/icons/codex.svg +3 -3
  18. package/dist/icons/cursor-white.svg +11 -11
  19. package/dist/icons/icon-128x128.svg +9 -9
  20. package/dist/icons/icon-144x144.svg +9 -9
  21. package/dist/icons/icon-152x152.svg +9 -9
  22. package/dist/icons/icon-192x192.svg +9 -9
  23. package/dist/icons/icon-384x384.svg +9 -9
  24. package/dist/icons/icon-512x512.svg +9 -9
  25. package/dist/icons/icon-72x72.svg +9 -9
  26. package/dist/icons/icon-96x96.svg +9 -9
  27. package/dist/icons/icon-template.svg +9 -9
  28. package/dist/icons/qwen-logo.svg +14 -14
  29. package/dist/index.html +59 -59
  30. package/dist/logo.svg +12 -12
  31. package/dist/manifest.json +60 -60
  32. package/dist/openapi.yaml +1693 -1311
  33. package/dist/sw.js +124 -124
  34. package/dist-server/server/claude-sdk.js +38 -7
  35. package/dist-server/server/claude-sdk.js.map +1 -1
  36. package/dist-server/server/cli.js +107 -112
  37. package/dist-server/server/cli.js.map +1 -1
  38. package/dist-server/server/daemon/manager.js +33 -33
  39. package/dist-server/server/daemon-manager.js +159 -112
  40. package/dist-server/server/daemon-manager.js.map +1 -1
  41. package/dist-server/server/database/json-store.js +8 -5
  42. package/dist-server/server/database/json-store.js.map +1 -1
  43. package/dist-server/server/index.js +31 -10
  44. package/dist-server/server/index.js.map +1 -1
  45. package/dist-server/server/modules/orchestration/a2a/adapter-registry.js +45 -19
  46. package/dist-server/server/modules/orchestration/a2a/adapter-registry.js.map +1 -1
  47. package/dist-server/server/modules/orchestration/a2a/adapters/abstract-a2a.adapter.js.map +1 -1
  48. package/dist-server/server/modules/orchestration/a2a/adapters/claude-code.adapter.js +1 -0
  49. package/dist-server/server/modules/orchestration/a2a/adapters/claude-code.adapter.js.map +1 -1
  50. package/dist-server/server/modules/orchestration/a2a/adapters/codex.adapter.js +202 -0
  51. package/dist-server/server/modules/orchestration/a2a/adapters/codex.adapter.js.map +1 -0
  52. package/dist-server/server/modules/orchestration/a2a/adapters/cursor.adapter.js +205 -0
  53. package/dist-server/server/modules/orchestration/a2a/adapters/cursor.adapter.js.map +1 -0
  54. package/dist-server/server/modules/orchestration/a2a/adapters/gemini.adapter.js +205 -0
  55. package/dist-server/server/modules/orchestration/a2a/adapters/gemini.adapter.js.map +1 -0
  56. package/dist-server/server/modules/orchestration/a2a/adapters/opencode.adapter.js +205 -0
  57. package/dist-server/server/modules/orchestration/a2a/adapters/opencode.adapter.js.map +1 -0
  58. package/dist-server/server/modules/orchestration/a2a/adapters/qwen.adapter.js +205 -0
  59. package/dist-server/server/modules/orchestration/a2a/adapters/qwen.adapter.js.map +1 -0
  60. package/dist-server/server/modules/orchestration/a2a/routes.js +298 -34
  61. package/dist-server/server/modules/orchestration/a2a/routes.js.map +1 -1
  62. package/dist-server/server/modules/orchestration/a2a/task-store.js +144 -0
  63. package/dist-server/server/modules/orchestration/a2a/task-store.js.map +1 -0
  64. package/dist-server/server/modules/orchestration/a2a/validator.js +16 -0
  65. package/dist-server/server/modules/orchestration/a2a/validator.js.map +1 -1
  66. package/dist-server/server/modules/orchestration/index.js +14 -0
  67. package/dist-server/server/modules/orchestration/index.js.map +1 -1
  68. package/dist-server/server/modules/orchestration/preview/port-watcher.js +90 -0
  69. package/dist-server/server/modules/orchestration/preview/port-watcher.js.map +1 -0
  70. package/dist-server/server/modules/orchestration/preview/preview-proxy.js +58 -0
  71. package/dist-server/server/modules/orchestration/preview/preview-proxy.js.map +1 -0
  72. package/dist-server/server/modules/orchestration/preview/types.js +2 -0
  73. package/dist-server/server/modules/orchestration/preview/types.js.map +1 -0
  74. package/dist-server/server/modules/orchestration/tasks/orchestration-task-store.js +37 -0
  75. package/dist-server/server/modules/orchestration/tasks/orchestration-task-store.js.map +1 -0
  76. package/dist-server/server/modules/orchestration/tasks/orchestration-task.routes.js +68 -0
  77. package/dist-server/server/modules/orchestration/tasks/orchestration-task.routes.js.map +1 -0
  78. package/dist-server/server/modules/orchestration/tasks/orchestration-task.service.js +128 -0
  79. package/dist-server/server/modules/orchestration/tasks/orchestration-task.service.js.map +1 -0
  80. package/dist-server/server/modules/orchestration/tasks/orchestration-task.types.js +2 -0
  81. package/dist-server/server/modules/orchestration/tasks/orchestration-task.types.js.map +1 -0
  82. package/dist-server/server/modules/orchestration/workflows/built-in-workflows.js +126 -0
  83. package/dist-server/server/modules/orchestration/workflows/built-in-workflows.js.map +1 -0
  84. package/dist-server/server/modules/orchestration/workflows/workflow-runner.js +1047 -0
  85. package/dist-server/server/modules/orchestration/workflows/workflow-runner.js.map +1 -0
  86. package/dist-server/server/modules/orchestration/workflows/workflow-store.js +76 -0
  87. package/dist-server/server/modules/orchestration/workflows/workflow-store.js.map +1 -0
  88. package/dist-server/server/modules/orchestration/workflows/workflow.routes.js +151 -0
  89. package/dist-server/server/modules/orchestration/workflows/workflow.routes.js.map +1 -0
  90. package/dist-server/server/modules/orchestration/workflows/workflow.types.js +2 -0
  91. package/dist-server/server/modules/orchestration/workflows/workflow.types.js.map +1 -0
  92. package/dist-server/server/modules/orchestration/workflows/workspace-target.js +98 -0
  93. package/dist-server/server/modules/orchestration/workflows/workspace-target.js.map +1 -0
  94. package/dist-server/server/modules/orchestration/workspace/docker-workspace.js +122 -0
  95. package/dist-server/server/modules/orchestration/workspace/docker-workspace.js.map +1 -0
  96. package/dist-server/server/modules/orchestration/workspace/path-safety.js +48 -0
  97. package/dist-server/server/modules/orchestration/workspace/path-safety.js.map +1 -0
  98. package/dist-server/server/modules/orchestration/workspace/types.js +11 -0
  99. package/dist-server/server/modules/orchestration/workspace/types.js.map +1 -0
  100. package/dist-server/server/modules/orchestration/workspace/workspace-manager.js +80 -0
  101. package/dist-server/server/modules/orchestration/workspace/workspace-manager.js.map +1 -0
  102. package/dist-server/server/modules/orchestration/workspace/worktree-workspace.js +96 -0
  103. package/dist-server/server/modules/orchestration/workspace/worktree-workspace.js.map +1 -0
  104. package/dist-server/server/modules/providers/index.js +3 -0
  105. package/dist-server/server/modules/providers/index.js.map +1 -0
  106. package/dist-server/server/openai-codex.js +35 -4
  107. package/dist-server/server/openai-codex.js.map +1 -1
  108. package/dist-server/server/routes/commands.js +25 -25
  109. package/dist-server/server/routes/git.js +17 -17
  110. package/dist-server/server/routes/taskmaster.js +525 -508
  111. package/dist-server/server/routes/taskmaster.js.map +1 -1
  112. package/package.json +180 -178
  113. package/scripts/fix-node-pty.js +67 -67
  114. package/scripts/smoke/a2a-roundtrip.mjs +86 -17
  115. package/scripts/smoke/orchestration-api.mjs +172 -0
  116. package/scripts/smoke/orchestration-live-run.mjs +176 -0
  117. package/server/claude-sdk.js +898 -857
  118. package/server/cli.js +935 -940
  119. package/server/constants/config.js +4 -4
  120. package/server/cursor-cli.js +342 -342
  121. package/server/daemon/manager.js +564 -564
  122. package/server/daemon-manager.js +959 -920
  123. package/server/database/db.js +794 -794
  124. package/server/database/json-store.js +197 -194
  125. package/server/gemini-cli.js +535 -535
  126. package/server/gemini-response-handler.js +79 -79
  127. package/server/index.js +3135 -3104
  128. package/server/load-env.js +34 -34
  129. package/server/middleware/auth.js +173 -173
  130. package/server/modules/orchestration/a2a/adapter-registry.ts +72 -22
  131. package/server/modules/orchestration/a2a/adapters/abstract-a2a.adapter.ts +9 -3
  132. package/server/modules/orchestration/a2a/adapters/claude-code.adapter.ts +1 -0
  133. package/server/modules/orchestration/a2a/adapters/codex.adapter.ts +244 -0
  134. package/server/modules/orchestration/a2a/adapters/cursor.adapter.ts +249 -0
  135. package/server/modules/orchestration/a2a/adapters/gemini.adapter.ts +248 -0
  136. package/server/modules/orchestration/a2a/adapters/opencode.adapter.ts +248 -0
  137. package/server/modules/orchestration/a2a/adapters/qwen.adapter.ts +248 -0
  138. package/server/modules/orchestration/a2a/routes.ts +349 -36
  139. package/server/modules/orchestration/a2a/task-store.ts +178 -0
  140. package/server/modules/orchestration/a2a/types.ts +14 -0
  141. package/server/modules/orchestration/a2a/validator.ts +25 -2
  142. package/server/modules/orchestration/index.ts +40 -0
  143. package/server/modules/orchestration/preview/port-watcher.ts +112 -0
  144. package/server/modules/orchestration/preview/preview-proxy.ts +60 -0
  145. package/server/modules/orchestration/preview/types.ts +19 -0
  146. package/server/modules/orchestration/tasks/orchestration-task-store.ts +45 -0
  147. package/server/modules/orchestration/tasks/orchestration-task.routes.ts +73 -0
  148. package/server/modules/orchestration/tasks/orchestration-task.service.ts +145 -0
  149. package/server/modules/orchestration/tasks/orchestration-task.types.ts +29 -0
  150. package/server/modules/orchestration/workflows/built-in-workflows.ts +127 -0
  151. package/server/modules/orchestration/workflows/workflow-runner.ts +1206 -0
  152. package/server/modules/orchestration/workflows/workflow-store.ts +97 -0
  153. package/server/modules/orchestration/workflows/workflow.routes.ts +169 -0
  154. package/server/modules/orchestration/workflows/workflow.types.ts +70 -0
  155. package/server/modules/orchestration/workflows/workspace-target.ts +120 -0
  156. package/server/modules/orchestration/workspace/docker-workspace.ts +135 -0
  157. package/server/modules/orchestration/workspace/path-safety.ts +55 -0
  158. package/server/modules/orchestration/workspace/types.ts +52 -0
  159. package/server/modules/orchestration/workspace/workspace-manager.ts +97 -0
  160. package/server/modules/orchestration/workspace/worktree-workspace.ts +125 -0
  161. package/server/modules/providers/index.ts +2 -0
  162. package/server/modules/providers/list/claude/claude-auth.provider.ts +145 -145
  163. package/server/modules/providers/list/claude/claude-mcp.provider.ts +135 -135
  164. package/server/modules/providers/list/claude/claude-sessions.provider.ts +306 -306
  165. package/server/modules/providers/list/claude/claude.provider.ts +15 -15
  166. package/server/modules/providers/list/codex/codex-auth.provider.ts +115 -115
  167. package/server/modules/providers/list/codex/codex-mcp.provider.ts +135 -135
  168. package/server/modules/providers/list/codex/codex-sessions.provider.ts +319 -319
  169. package/server/modules/providers/list/codex/codex.provider.ts +15 -15
  170. package/server/modules/providers/list/cursor/cursor-auth.provider.ts +143 -143
  171. package/server/modules/providers/list/cursor/cursor-mcp.provider.ts +108 -108
  172. package/server/modules/providers/list/cursor/cursor-sessions.provider.ts +421 -421
  173. package/server/modules/providers/list/cursor/cursor.provider.ts +15 -15
  174. package/server/modules/providers/list/gemini/gemini-auth.provider.ts +163 -163
  175. package/server/modules/providers/list/gemini/gemini-mcp.provider.ts +110 -110
  176. package/server/modules/providers/list/gemini/gemini-sessions.provider.ts +227 -227
  177. package/server/modules/providers/list/gemini/gemini.provider.ts +15 -15
  178. package/server/modules/providers/list/opencode/opencode-auth.provider.ts +130 -130
  179. package/server/modules/providers/list/opencode/opencode-mcp.provider.ts +126 -126
  180. package/server/modules/providers/list/opencode/opencode-sessions.provider.ts +232 -232
  181. package/server/modules/providers/list/opencode/opencode.provider.ts +29 -29
  182. package/server/modules/providers/list/qwen/qwen-auth.provider.ts +145 -145
  183. package/server/modules/providers/list/qwen/qwen-mcp.provider.ts +114 -114
  184. package/server/modules/providers/list/qwen/qwen-sessions.provider.ts +265 -265
  185. package/server/modules/providers/list/qwen/qwen.provider.ts +21 -21
  186. package/server/modules/providers/provider.registry.ts +40 -40
  187. package/server/modules/providers/provider.routes.ts +819 -819
  188. package/server/modules/providers/services/mcp.service.ts +86 -86
  189. package/server/modules/providers/services/provider-auth.service.ts +26 -26
  190. package/server/modules/providers/services/sessions.service.ts +45 -45
  191. package/server/modules/providers/shared/base/abstract.provider.ts +20 -20
  192. package/server/modules/providers/shared/mcp/mcp.provider.ts +151 -151
  193. package/server/modules/providers/shared/provider-configs.ts +142 -142
  194. package/server/modules/providers/tests/mcp.test.ts +293 -293
  195. package/server/openai-codex.js +462 -426
  196. package/server/opencode-cli.js +459 -459
  197. package/server/opencode-response-handler.js +107 -107
  198. package/server/projects.js +3105 -3105
  199. package/server/qwen-code-cli.js +395 -395
  200. package/server/qwen-response-handler.js +73 -73
  201. package/server/routes/agent.js +1365 -1365
  202. package/server/routes/auth.js +138 -138
  203. package/server/routes/codex.js +19 -19
  204. package/server/routes/commands.js +554 -554
  205. package/server/routes/cursor.js +52 -52
  206. package/server/routes/gemini.js +24 -24
  207. package/server/routes/git.js +1488 -1488
  208. package/server/routes/mcp-utils.js +31 -31
  209. package/server/routes/messages.js +61 -61
  210. package/server/routes/network.js +120 -120
  211. package/server/routes/plugins.js +318 -318
  212. package/server/routes/projects.js +915 -915
  213. package/server/routes/qwen.js +27 -27
  214. package/server/routes/settings.js +286 -286
  215. package/server/routes/taskmaster.js +1496 -1471
  216. package/server/routes/telegram.js +125 -125
  217. package/server/routes/user.js +123 -123
  218. package/server/services/external-access.js +171 -171
  219. package/server/services/install-jobs.js +571 -571
  220. package/server/services/notification-orchestrator.js +242 -242
  221. package/server/services/provider-credentials.js +189 -189
  222. package/server/services/provider-models.js +381 -381
  223. package/server/services/telegram/bot.js +279 -279
  224. package/server/services/telegram/telegram-http-client.js +130 -130
  225. package/server/services/telegram/translations.js +170 -170
  226. package/server/services/vapid-keys.js +36 -36
  227. package/server/sessionManager.js +225 -225
  228. package/server/shared/interfaces.ts +54 -54
  229. package/server/shared/types.ts +172 -172
  230. package/server/shared/utils.ts +193 -193
  231. package/server/tsconfig.json +36 -36
  232. package/server/utils/colors.js +21 -21
  233. package/server/utils/commandParser.js +303 -303
  234. package/server/utils/frontmatter.js +18 -18
  235. package/server/utils/gitConfig.js +34 -34
  236. package/server/utils/mcp-detector.js +147 -147
  237. package/server/utils/plugin-loader.js +457 -457
  238. package/server/utils/plugin-process-manager.js +184 -184
  239. package/server/utils/port-access.js +209 -209
  240. package/server/utils/runtime-paths.js +37 -37
  241. package/server/utils/taskmaster-websocket.js +128 -128
  242. package/server/utils/url-detection.js +71 -71
  243. package/server/vite-daemon.js +78 -78
  244. package/shared/modelConstants.js +162 -162
  245. package/shared/networkHosts.js +22 -22
  246. package/dist/assets/index-B1ghfb4w.css +0 -32
  247. package/dist/assets/index-BvClqlMf.js +0 -852
@@ -1,67 +1,67 @@
1
- #!/usr/bin/env node
2
- /**
3
- * Fix node-pty spawn-helper permissions on macOS
4
- *
5
- * This script fixes a known issue with node-pty where the spawn-helper
6
- * binary is shipped without execute permissions, causing "posix_spawnp failed" errors.
7
- *
8
- * @see https://github.com/microsoft/node-pty/issues/850
9
- * @module scripts/fix-node-pty
10
- */
11
-
12
- import { promises as fs } from 'fs';
13
- import path from 'path';
14
- import { fileURLToPath } from 'url';
15
-
16
- const __filename = fileURLToPath(import.meta.url);
17
- const __dirname = path.dirname(__filename);
18
-
19
- /**
20
- * Fixes the spawn-helper binary permissions for node-pty on macOS.
21
- *
22
- * The node-pty package ships the spawn-helper binary without execute permissions
23
- * (644 instead of 755), which causes "posix_spawnp failed" errors when trying
24
- * to spawn terminal processes.
25
- *
26
- * This function:
27
- * 1. Checks if running on macOS (darwin)
28
- * 2. Locates spawn-helper binaries for both arm64 and x64 architectures
29
- * 3. Sets execute permissions (755) on each binary found
30
- *
31
- * @async
32
- * @function fixSpawnHelper
33
- * @returns {Promise<void>} Resolves when permissions are fixed or skipped
34
- * @example
35
- * // Run as postinstall script
36
- * await fixSpawnHelper();
37
- */
38
- async function fixSpawnHelper() {
39
- const nodeModulesPath = path.join(__dirname, '..', 'node_modules', 'node-pty', 'prebuilds');
40
-
41
- // Only run on macOS
42
- if (process.platform !== 'darwin') {
43
- return;
44
- }
45
-
46
- const darwinDirs = ['darwin-arm64', 'darwin-x64'];
47
-
48
- for (const dir of darwinDirs) {
49
- const spawnHelperPath = path.join(nodeModulesPath, dir, 'spawn-helper');
50
-
51
- try {
52
- // Check if file exists
53
- await fs.access(spawnHelperPath);
54
-
55
- // Make it executable (755)
56
- await fs.chmod(spawnHelperPath, 0o755);
57
- console.log(`[postinstall] Fixed permissions for ${spawnHelperPath}`);
58
- } catch (err) {
59
- // File doesn't exist or other error - ignore
60
- if (err.code !== 'ENOENT') {
61
- console.warn(`[postinstall] Warning: Could not fix ${spawnHelperPath}: ${err.message}`);
62
- }
63
- }
64
- }
65
- }
66
-
67
- fixSpawnHelper().catch(console.error);
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Fix node-pty spawn-helper permissions on macOS
4
+ *
5
+ * This script fixes a known issue with node-pty where the spawn-helper
6
+ * binary is shipped without execute permissions, causing "posix_spawnp failed" errors.
7
+ *
8
+ * @see https://github.com/microsoft/node-pty/issues/850
9
+ * @module scripts/fix-node-pty
10
+ */
11
+
12
+ import { promises as fs } from 'fs';
13
+ import path from 'path';
14
+ import { fileURLToPath } from 'url';
15
+
16
+ const __filename = fileURLToPath(import.meta.url);
17
+ const __dirname = path.dirname(__filename);
18
+
19
+ /**
20
+ * Fixes the spawn-helper binary permissions for node-pty on macOS.
21
+ *
22
+ * The node-pty package ships the spawn-helper binary without execute permissions
23
+ * (644 instead of 755), which causes "posix_spawnp failed" errors when trying
24
+ * to spawn terminal processes.
25
+ *
26
+ * This function:
27
+ * 1. Checks if running on macOS (darwin)
28
+ * 2. Locates spawn-helper binaries for both arm64 and x64 architectures
29
+ * 3. Sets execute permissions (755) on each binary found
30
+ *
31
+ * @async
32
+ * @function fixSpawnHelper
33
+ * @returns {Promise<void>} Resolves when permissions are fixed or skipped
34
+ * @example
35
+ * // Run as postinstall script
36
+ * await fixSpawnHelper();
37
+ */
38
+ async function fixSpawnHelper() {
39
+ const nodeModulesPath = path.join(__dirname, '..', 'node_modules', 'node-pty', 'prebuilds');
40
+
41
+ // Only run on macOS
42
+ if (process.platform !== 'darwin') {
43
+ return;
44
+ }
45
+
46
+ const darwinDirs = ['darwin-arm64', 'darwin-x64'];
47
+
48
+ for (const dir of darwinDirs) {
49
+ const spawnHelperPath = path.join(nodeModulesPath, dir, 'spawn-helper');
50
+
51
+ try {
52
+ // Check if file exists
53
+ await fs.access(spawnHelperPath);
54
+
55
+ // Make it executable (755)
56
+ await fs.chmod(spawnHelperPath, 0o755);
57
+ console.log(`[postinstall] Fixed permissions for ${spawnHelperPath}`);
58
+ } catch (err) {
59
+ // File doesn't exist or other error - ignore
60
+ if (err.code !== 'ENOENT') {
61
+ console.warn(`[postinstall] Warning: Could not fix ${spawnHelperPath}: ${err.message}`);
62
+ }
63
+ }
64
+ }
65
+ }
66
+
67
+ fixSpawnHelper().catch(console.error);
@@ -25,6 +25,15 @@ async function jget(path) {
25
25
  return r.json();
26
26
  }
27
27
 
28
+ async function jpost(path, body) {
29
+ const r = await fetch(`${baseUrl}${path}`, {
30
+ method: 'POST',
31
+ headers: { 'content-type': 'application/json' },
32
+ body: JSON.stringify(body),
33
+ });
34
+ return { status: r.status, json: await r.json() };
35
+ }
36
+
28
37
  async function main() {
29
38
  console.log('1) /a2a/.well-known/agent-card.json');
30
39
  const card = await jget('/a2a/.well-known/agent-card.json');
@@ -35,28 +44,88 @@ async function main() {
35
44
  const agents = await jget('/a2a/agents');
36
45
  const ids = agents.agents.map((a) => a.name);
37
46
  console.log(' registered:', ids.join(', '));
38
- if (!ids.includes('pixcode-claude-code')) {
39
- throw new Error('claude-code adapter not registered');
47
+ const expectedAgents = [
48
+ 'pixcode-claude-code',
49
+ 'pixcode-codex',
50
+ 'pixcode-cursor',
51
+ 'pixcode-gemini',
52
+ 'pixcode-qwen',
53
+ 'pixcode-opencode',
54
+ ];
55
+ for (const expected of expectedAgents) {
56
+ if (!ids.includes(expected)) {
57
+ throw new Error(`${expected} adapter not registered`);
58
+ }
40
59
  }
41
60
 
42
- console.log('3) POST /a2a/tasks');
43
- const submitRes = await fetch(`${baseUrl}/a2a/tasks`, {
44
- method: 'POST',
45
- headers: { 'content-type': 'application/json' },
46
- body: JSON.stringify({
47
- adapterId: 'claude-code',
48
- message: {
49
- messageId: 'm_smoke_1',
50
- role: 'user',
51
- parts: [{ kind: 'text', text: 'Reply with the single word: ok' }],
52
- },
53
- }),
61
+ console.log('3) POST /a2a/adapters/resolve');
62
+ const resolveRes = await jpost('/a2a/adapters/resolve', {
63
+ adapterId: 'skill:typescript-edit',
64
+ routing: { preferredAdapterId: 'codex' },
65
+ });
66
+ if (resolveRes.status !== 200) throw new Error(`resolve -> ${resolveRes.status}`);
67
+ console.log(' resolved=', resolveRes.json.resolvedAdapterId);
68
+ if (resolveRes.json.resolvedAdapterId !== 'codex') {
69
+ throw new Error('skill resolution did not honor preferredAdapterId=codex');
70
+ }
71
+
72
+ console.log('4) POST /a2a/tasks (invalid adapter)');
73
+ const invalidSubmit = await jpost('/a2a/tasks', {
74
+ adapterId: 'missing-adapter',
75
+ message: {
76
+ messageId: 'm_invalid_adapter',
77
+ role: 'user',
78
+ parts: [{ kind: 'text', text: 'noop' }],
79
+ },
54
80
  });
55
- if (!submitRes.ok) throw new Error(`submit -> ${submitRes.status}`);
56
- const task = await submitRes.json();
81
+ if (invalidSubmit.status !== 404) {
82
+ throw new Error(`invalid submit -> expected 404, got ${invalidSubmit.status}`);
83
+ }
84
+
85
+ console.log('5) POST /a2a/messages (missing task)');
86
+ const missingTaskMessage = await jpost('/a2a/messages', {
87
+ messageId: 'm_missing_task',
88
+ role: 'user',
89
+ taskId: 'task_missing',
90
+ parts: [{ kind: 'text', text: 'noop' }],
91
+ });
92
+ if (missingTaskMessage.status !== 404) {
93
+ throw new Error(`missing task message -> expected 404, got ${missingTaskMessage.status}`);
94
+ }
95
+
96
+ console.log('6) POST /a2a/tasks');
97
+ const submitRes = await jpost('/a2a/tasks', {
98
+ adapterId: 'claude-code',
99
+ message: {
100
+ messageId: 'm_smoke_1',
101
+ role: 'user',
102
+ parts: [{ kind: 'text', text: 'Reply with the single word: ok' }],
103
+ },
104
+ });
105
+ if (submitRes.status !== 202) throw new Error(`submit -> ${submitRes.status}`);
106
+ const task = submitRes.json;
57
107
  console.log(' task.id=', task.id, 'state=', task.state);
108
+ if (task.history?.[0]?.taskId !== task.id) {
109
+ throw new Error('task-scoped initial history message is missing taskId');
110
+ }
111
+ if (task.metadata?.adapterId !== 'claude-code') {
112
+ throw new Error('resolved adapterId was not persisted to task metadata');
113
+ }
114
+
115
+ console.log('7) GET /a2a/tasks?adapterId=claude-code&limit=5');
116
+ const listedTasks = await jget('/a2a/tasks?adapterId=claude-code&limit=5');
117
+ if (!Array.isArray(listedTasks.tasks) || listedTasks.count < 1) {
118
+ throw new Error('task listing did not return any tasks');
119
+ }
120
+ const listedTask = listedTasks.tasks.find((entry) => entry.id === task.id);
121
+ if (!listedTask) {
122
+ throw new Error('submitted task did not appear in filtered task listing');
123
+ }
124
+ if (listedTask.adapterId !== 'claude-code') {
125
+ throw new Error('task summary adapterId mismatch');
126
+ }
58
127
 
59
- console.log('4) GET /a2a/tasks/:id/stream (SSE)');
128
+ console.log('8) GET /a2a/tasks/:id/stream (SSE)');
60
129
  const streamRes = await fetch(`${baseUrl}/a2a/tasks/${task.id}/stream`);
61
130
  if (!streamRes.ok) throw new Error(`stream -> ${streamRes.status}`);
62
131
 
@@ -0,0 +1,172 @@
1
+ #!/usr/bin/env node
2
+
3
+ const baseUrl = process.env.PIXCODE_BASE_URL || 'http://127.0.0.1:3001';
4
+ const apiKey = process.env.PIXCODE_API_KEY;
5
+
6
+ if (!apiKey) {
7
+ console.error('PIXCODE_API_KEY is required.');
8
+ process.exit(1);
9
+ }
10
+
11
+ async function request(path, options = {}) {
12
+ const response = await fetch(`${baseUrl}${path}`, {
13
+ ...options,
14
+ headers: {
15
+ authorization: `Bearer ${apiKey}`,
16
+ 'content-type': 'application/json',
17
+ ...(options.headers || {}),
18
+ },
19
+ });
20
+ const text = await response.text();
21
+ const body = text ? JSON.parse(text) : null;
22
+ if (!response.ok) {
23
+ throw new Error(`${options.method || 'GET'} ${path} failed: ${response.status} ${text}`);
24
+ }
25
+ return body;
26
+ }
27
+
28
+ function assert(condition, message) {
29
+ if (!condition) {
30
+ throw new Error(message);
31
+ }
32
+ }
33
+
34
+ function nodeById(nodes, id) {
35
+ const node = nodes.find((candidate) => candidate.id === id);
36
+ assert(node, `Missing workflow node: ${id}`);
37
+ return node;
38
+ }
39
+
40
+ function parseJsonEnv(name, fallback) {
41
+ if (!process.env[name]) return fallback;
42
+ try {
43
+ return JSON.parse(process.env[name]);
44
+ } catch (error) {
45
+ throw new Error(`${name} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`);
46
+ }
47
+ }
48
+
49
+ function safeNodeId(adapterId, suffix) {
50
+ return `${adapterId.replace(/[^a-zA-Z0-9_]+/g, '_')}_${suffix}`;
51
+ }
52
+
53
+ function safeAgentNodeId(agent, index, suffix) {
54
+ return `agent_${index + 1}_${safeNodeId(agent.adapterId, suffix)}`;
55
+ }
56
+
57
+ const smokeAgents = parseJsonEnv('PIXCODE_SMOKE_AGENTS_JSON', [
58
+ {
59
+ instanceId: 'codex-frontend',
60
+ adapterId: 'codex',
61
+ label: 'Agent #1',
62
+ role: 'frontend',
63
+ enabled: true,
64
+ },
65
+ {
66
+ instanceId: 'codex-backend',
67
+ adapterId: 'codex',
68
+ label: 'Agent #2',
69
+ role: 'backend',
70
+ enabled: true,
71
+ },
72
+ {
73
+ instanceId: 'codex-review',
74
+ adapterId: 'codex',
75
+ label: 'Agent #3',
76
+ role: 'review',
77
+ enabled: true,
78
+ },
79
+ ]);
80
+
81
+ const teamMetadata = {
82
+ agents: smokeAgents,
83
+ settings: {
84
+ ...parseJsonEnv('PIXCODE_SMOKE_SETTINGS_JSON', {}),
85
+ maxParallelAgents: Number.parseInt(process.env.PIXCODE_SMOKE_MAX_PARALLEL || '3', 10),
86
+ isolation: process.env.PIXCODE_SMOKE_ISOLATION || 'host',
87
+ keepWorkspace: process.env.PIXCODE_SMOKE_KEEP_WORKSPACE !== 'false',
88
+ },
89
+ };
90
+
91
+ async function main() {
92
+ const health = await fetch(`${baseUrl}/health`).then((response) => response.json());
93
+ assert(health.status === 'ok', 'Health check did not return ok.');
94
+
95
+ const workflows = await request('/api/orchestration/workflows');
96
+ assert(Array.isArray(workflows.workflows), 'Workflow list payload is invalid.');
97
+ assert(workflows.workflows.some((workflow) => workflow.id === 'agent_team'), 'agent_team workflow is missing.');
98
+
99
+ const preview = await request('/api/orchestration/workflows/agent_team/preview', {
100
+ method: 'POST',
101
+ body: JSON.stringify({ metadata: teamMetadata }),
102
+ });
103
+ assert(preview.workflow?.id === 'agent_team', 'Preview did not return the agent_team workflow.');
104
+ assert(preview.nodeCount === preview.nodes.length, 'Preview nodeCount does not match nodes length.');
105
+
106
+ const backendIndex = smokeAgents.findIndex((agent) => agent.role === 'backend');
107
+ const frontendIndex = smokeAgents.findIndex((agent) => agent.role === 'frontend');
108
+ const reviewIndex = smokeAgents.findIndex((agent) => agent.role === 'review');
109
+ assert(backendIndex >= 0, 'Smoke agents must include one role=backend agent.');
110
+ assert(frontendIndex >= 0, 'Smoke agents must include one role=frontend agent.');
111
+ assert(reviewIndex >= 0, 'Smoke agents must include one role=review agent.');
112
+
113
+ const backendAgent = smokeAgents[backendIndex];
114
+ const frontendAgent = smokeAgents[frontendIndex];
115
+ const reviewAgent = smokeAgents[reviewIndex];
116
+ const backendHandoffId = safeAgentNodeId(backendAgent, backendIndex, 'handoff');
117
+ const backendWorkId = safeAgentNodeId(backendAgent, backendIndex, 'work');
118
+ const frontendWorkId = safeAgentNodeId(frontendAgent, frontendIndex, 'work');
119
+ const reviewWorkId = safeAgentNodeId(reviewAgent, reviewIndex, 'work');
120
+
121
+ const backendHandoff = nodeById(preview.nodes, backendHandoffId);
122
+ const backendWork = nodeById(preview.nodes, backendWorkId);
123
+ const frontendWork = nodeById(preview.nodes, frontendWorkId);
124
+ const reviewWork = nodeById(preview.nodes, reviewWorkId);
125
+ const finalReport = nodeById(preview.nodes, 'final_report');
126
+
127
+ assert(backendHandoff.timeoutMs === 120000, 'Backend handoff timeout is not set to 120000ms.');
128
+ assert(backendHandoff.inputs.includes('coordinator'), 'Backend handoff must depend on coordinator.');
129
+ assert(backendWork.inputs.includes(backendHandoffId), 'Backend work must depend on backend handoff.');
130
+ assert(frontendWork.inputs.includes(backendHandoffId), 'Frontend work must depend on backend handoff.');
131
+ assert(!frontendWork.inputs.includes(backendWorkId), 'Frontend must not wait for full backend implementation.');
132
+ assert(reviewWork.inputs.includes(frontendWorkId), 'Review must depend on frontend work.');
133
+ assert(reviewWork.inputs.includes(backendWorkId), 'Review must depend on backend work.');
134
+ assert(finalReport.inputs.includes(reviewWorkId), 'Final report must include review output.');
135
+
136
+ const runs = await request('/api/orchestration/workflows/runs?limit=5');
137
+ assert(Array.isArray(runs.runs), 'Runs payload is invalid.');
138
+
139
+ let eventsChecked = false;
140
+ if (runs.runs[0]?.id) {
141
+ const controller = new AbortController();
142
+ const response = await fetch(
143
+ `${baseUrl}/api/orchestration/workflows/runs/${encodeURIComponent(runs.runs[0].id)}/events`,
144
+ {
145
+ headers: { authorization: `Bearer ${apiKey}` },
146
+ signal: controller.signal,
147
+ },
148
+ );
149
+ assert(response.ok, `Run events endpoint returned ${response.status}.`);
150
+ assert(response.body, 'Run events endpoint did not return a readable body.');
151
+ const reader = response.body.getReader();
152
+ const firstChunk = await reader.read();
153
+ controller.abort();
154
+ const eventText = new TextDecoder().decode(firstChunk.value || new Uint8Array());
155
+ assert(eventText.includes('event: snapshot'), 'Run events endpoint did not emit an initial snapshot.');
156
+ eventsChecked = true;
157
+ }
158
+
159
+ console.log(JSON.stringify({
160
+ ok: true,
161
+ baseUrl,
162
+ workflowCount: workflows.workflows.length,
163
+ previewNodeIds: preview.nodes.map((node) => node.id),
164
+ recentRunCount: runs.runs.length,
165
+ eventsChecked,
166
+ }, null, 2));
167
+ }
168
+
169
+ main().catch((error) => {
170
+ console.error(error instanceof Error ? error.message : String(error));
171
+ process.exit(1);
172
+ });
@@ -0,0 +1,176 @@
1
+ #!/usr/bin/env node
2
+
3
+ const baseUrl = process.env.PIXCODE_BASE_URL || 'http://127.0.0.1:3001';
4
+ const apiKey = process.env.PIXCODE_API_KEY;
5
+ const goal = process.env.PIXCODE_LIVE_GOAL;
6
+ const timeoutMs = Number.parseInt(process.env.PIXCODE_LIVE_TIMEOUT_MS || '1200000', 10);
7
+ const minAgentOutputs = Number.parseInt(process.env.PIXCODE_LIVE_MIN_AGENT_OUTPUTS || '2', 10);
8
+ const workflowId = process.env.PIXCODE_LIVE_WORKFLOW_ID || 'agent_team';
9
+
10
+ if (!apiKey) {
11
+ console.error('PIXCODE_API_KEY is required.');
12
+ process.exit(1);
13
+ }
14
+
15
+ if (!goal) {
16
+ console.error('PIXCODE_LIVE_GOAL is required.');
17
+ process.exit(1);
18
+ }
19
+
20
+ function parseJsonEnv(name) {
21
+ const raw = process.env[name];
22
+ if (!raw) {
23
+ throw new Error(`${name} is required.`);
24
+ }
25
+ try {
26
+ return JSON.parse(raw);
27
+ } catch (error) {
28
+ throw new Error(`${name} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`);
29
+ }
30
+ }
31
+
32
+ function assert(condition, message) {
33
+ if (!condition) throw new Error(message);
34
+ }
35
+
36
+ function headers(extra = {}) {
37
+ return {
38
+ authorization: `Bearer ${apiKey}`,
39
+ 'content-type': 'application/json',
40
+ ...extra,
41
+ };
42
+ }
43
+
44
+ async function request(path, options = {}) {
45
+ const response = await fetch(`${baseUrl}${path}`, {
46
+ ...options,
47
+ headers: headers(options.headers || {}),
48
+ });
49
+ const text = await response.text();
50
+ const body = text ? JSON.parse(text) : null;
51
+ if (!response.ok) {
52
+ throw new Error(`${options.method || 'GET'} ${path} failed: ${response.status} ${text}`);
53
+ }
54
+ return body;
55
+ }
56
+
57
+ function terminal(status) {
58
+ return status === 'completed' || status === 'failed' || status === 'canceled';
59
+ }
60
+
61
+ function agentTextCount(run) {
62
+ return (run.nodeRuns || []).filter((node) =>
63
+ (node.messages || []).some((message) => message.role !== 'user' && message.text?.trim()) ||
64
+ Boolean(node.outputText?.trim()),
65
+ ).length;
66
+ }
67
+
68
+ function compactNodes(run) {
69
+ return (run.nodeRuns || []).map((node) => ({
70
+ nodeId: node.nodeId,
71
+ label: node.agentLabel,
72
+ status: node.status,
73
+ taskId: node.a2aTaskId,
74
+ messageCount: (node.messages || []).filter((message) => message.role !== 'user').length,
75
+ hasOutput: Boolean(node.outputText?.trim()),
76
+ error: node.error,
77
+ }));
78
+ }
79
+
80
+ async function cancelRun(runId) {
81
+ try {
82
+ await request(`/api/orchestration/workflows/runs/${encodeURIComponent(runId)}/cancel`, {
83
+ method: 'POST',
84
+ body: '{}',
85
+ });
86
+ } catch {
87
+ // Best-effort cleanup only.
88
+ }
89
+ }
90
+
91
+ async function main() {
92
+ const agents = parseJsonEnv('PIXCODE_LIVE_AGENTS_JSON');
93
+ assert(Array.isArray(agents) && agents.length > 0, 'PIXCODE_LIVE_AGENTS_JSON must be a non-empty array.');
94
+
95
+ const settings = process.env.PIXCODE_LIVE_SETTINGS_JSON
96
+ ? JSON.parse(process.env.PIXCODE_LIVE_SETTINGS_JSON)
97
+ : {};
98
+ const metadata = {
99
+ agents,
100
+ projectPath: process.env.PIXCODE_LIVE_PROJECT_PATH,
101
+ projectId: process.env.PIXCODE_LIVE_PROJECT_ID,
102
+ settings: {
103
+ maxParallelAgents: Number.parseInt(process.env.PIXCODE_LIVE_MAX_PARALLEL || '3', 10),
104
+ isolation: process.env.PIXCODE_LIVE_ISOLATION || 'host',
105
+ keepWorkspace: process.env.PIXCODE_LIVE_KEEP_WORKSPACE !== 'false',
106
+ ...settings,
107
+ },
108
+ };
109
+
110
+ const preview = await request(`/api/orchestration/workflows/${encodeURIComponent(workflowId)}/preview`, {
111
+ method: 'POST',
112
+ body: JSON.stringify({ metadata }),
113
+ });
114
+ assert(preview.nodeCount >= agents.length + 1, 'Preview did not expand enough nodes for the requested agents.');
115
+ console.log(JSON.stringify({ event: 'preview', nodeIds: preview.nodes.map((node) => node.id) }));
116
+
117
+ const started = await request(`/api/orchestration/workflows/${encodeURIComponent(workflowId)}/runs`, {
118
+ method: 'POST',
119
+ body: JSON.stringify({ input: goal, metadata }),
120
+ });
121
+ const runId = started.id;
122
+ assert(runId, 'Run id missing from start response.');
123
+ console.log(JSON.stringify({ event: 'started', runId, contextId: started.contextId }));
124
+
125
+ const deadline = Date.now() + timeoutMs;
126
+ let lastSignature = '';
127
+ let latest = started;
128
+ while (!terminal(latest.status) && Date.now() < deadline) {
129
+ await new Promise((resolve) => setTimeout(resolve, 5000));
130
+ latest = await request(`/api/orchestration/workflows/runs/${encodeURIComponent(runId)}`);
131
+ const nodes = compactNodes(latest);
132
+ const signature = JSON.stringify(nodes.map((node) => [
133
+ node.nodeId,
134
+ node.status,
135
+ node.messageCount,
136
+ node.hasOutput,
137
+ node.error,
138
+ ]));
139
+ if (signature !== lastSignature) {
140
+ lastSignature = signature;
141
+ console.log(JSON.stringify({
142
+ event: 'progress',
143
+ status: latest.status,
144
+ agentOutputs: agentTextCount(latest),
145
+ nodes,
146
+ }));
147
+ }
148
+ }
149
+
150
+ if (!terminal(latest.status)) {
151
+ await cancelRun(runId);
152
+ throw new Error(`Run ${runId} did not finish before ${timeoutMs}ms; canceled.`);
153
+ }
154
+
155
+ const outputCount = agentTextCount(latest);
156
+ if (outputCount < minAgentOutputs) {
157
+ throw new Error(`Expected at least ${minAgentOutputs} nodes with agent output; got ${outputCount}.`);
158
+ }
159
+
160
+ if (latest.status !== 'completed') {
161
+ throw new Error(`Run ended with ${latest.status}: ${JSON.stringify(compactNodes(latest))}`);
162
+ }
163
+
164
+ console.log(JSON.stringify({
165
+ event: 'completed',
166
+ runId,
167
+ contextId: latest.contextId,
168
+ outputCount,
169
+ nodes: compactNodes(latest),
170
+ }, null, 2));
171
+ }
172
+
173
+ main().catch((error) => {
174
+ console.error(error instanceof Error ? error.message : String(error));
175
+ process.exit(1);
176
+ });