@pixelbyte-software/pixcode 1.47.5 → 1.48.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 (109) hide show
  1. package/README.md +16 -30
  2. package/README.tr.md +1 -1
  3. package/dist/api-automation.html +1 -1
  4. package/dist/assets/index-By2TVdoL.css +32 -0
  5. package/dist/assets/index-rGiqd0D-.js +818 -0
  6. package/dist/assets/{vendor-codemirror-CzSp4P1a.js → vendor-codemirror-CIYNS698.js} +8 -8
  7. package/dist/docs.html +10 -10
  8. package/dist/features.html +3 -3
  9. package/dist/index.html +3 -3
  10. package/dist/landing.html +21 -23
  11. package/dist/llms-full.txt +4 -8
  12. package/dist/llms.txt +5 -6
  13. package/dist/openapi.yaml +7 -7
  14. package/dist-server/server/index.js +4 -6
  15. package/dist-server/server/index.js.map +1 -1
  16. package/dist-server/server/modules/orchestration/a2a/adapters/claude-code.adapter.js +1 -1
  17. package/dist-server/server/modules/orchestration/a2a/adapters/claude-code.adapter.js.map +1 -1
  18. package/dist-server/server/modules/orchestration/a2a/adapters/codex.adapter.js +1 -1
  19. package/dist-server/server/modules/orchestration/a2a/adapters/codex.adapter.js.map +1 -1
  20. package/dist-server/server/modules/orchestration/a2a/adapters/cursor.adapter.js +1 -1
  21. package/dist-server/server/modules/orchestration/a2a/adapters/cursor.adapter.js.map +1 -1
  22. package/dist-server/server/modules/orchestration/a2a/adapters/gemini.adapter.js +1 -1
  23. package/dist-server/server/modules/orchestration/a2a/adapters/gemini.adapter.js.map +1 -1
  24. package/dist-server/server/modules/orchestration/a2a/adapters/opencode.adapter.js +1 -1
  25. package/dist-server/server/modules/orchestration/a2a/adapters/opencode.adapter.js.map +1 -1
  26. package/dist-server/server/modules/orchestration/a2a/adapters/qwen.adapter.js +1 -1
  27. package/dist-server/server/modules/orchestration/a2a/adapters/qwen.adapter.js.map +1 -1
  28. package/dist-server/server/modules/orchestration/a2a/agent-card.js +4 -4
  29. package/dist-server/server/modules/orchestration/a2a/agent-card.js.map +1 -1
  30. package/dist-server/server/modules/orchestration/a2a/routes.js +6 -2
  31. package/dist-server/server/modules/orchestration/a2a/routes.js.map +1 -1
  32. package/dist-server/server/modules/orchestration/hermes/hermes.routes.js +62 -0
  33. package/dist-server/server/modules/orchestration/hermes/hermes.routes.js.map +1 -0
  34. package/dist-server/server/modules/orchestration/index.js +2 -1
  35. package/dist-server/server/modules/orchestration/index.js.map +1 -1
  36. package/dist-server/server/modules/orchestration/tasks/orchestration-task-store.js +2 -5
  37. package/dist-server/server/modules/orchestration/tasks/orchestration-task-store.js.map +1 -1
  38. package/dist-server/server/modules/orchestration/tasks/orchestration-task.routes.js +1 -20
  39. package/dist-server/server/modules/orchestration/tasks/orchestration-task.routes.js.map +1 -1
  40. package/dist-server/server/modules/orchestration/tasks/orchestration-task.service.js +4 -37
  41. package/dist-server/server/modules/orchestration/tasks/orchestration-task.service.js.map +1 -1
  42. package/dist-server/server/modules/orchestration/tasks/task-run-graph.js +4 -62
  43. package/dist-server/server/modules/orchestration/tasks/task-run-graph.js.map +1 -1
  44. package/dist-server/server/modules/orchestration/workflows/workflow-runner.js +14 -14
  45. package/dist-server/server/modules/orchestration/workflows/workflow-runner.js.map +1 -1
  46. package/dist-server/server/modules/orchestration/workflows/workflow-trace.js +2 -2
  47. package/dist-server/server/modules/orchestration/workflows/workflow-trace.js.map +1 -1
  48. package/dist-server/server/projects.js +0 -160
  49. package/dist-server/server/projects.js.map +1 -1
  50. package/dist-server/server/routes/mcp-utils.js +0 -18
  51. package/dist-server/server/routes/mcp-utils.js.map +1 -1
  52. package/dist-server/server/services/public-api-manifest.js +0 -5
  53. package/dist-server/server/services/public-api-manifest.js.map +1 -1
  54. package/dist-server/server/services/telegram/control-center.js +2 -144
  55. package/dist-server/server/services/telegram/control-center.js.map +1 -1
  56. package/dist-server/server/services/telegram/translations.js +2 -14
  57. package/dist-server/server/services/telegram/translations.js.map +1 -1
  58. package/package.json +1 -2
  59. package/scripts/smoke/default-landing-routing.mjs +7 -16
  60. package/scripts/smoke/{a2a-roundtrip.mjs → hermes-roundtrip.mjs} +23 -23
  61. package/scripts/smoke/mac-desktop-runtime.mjs +1 -7
  62. package/scripts/smoke/orchestration-live-run.mjs +1 -1
  63. package/scripts/smoke/orchestration-model-sync.mjs +2 -2
  64. package/scripts/smoke/orchestration-user-facing-output.mjs +2 -2
  65. package/scripts/smoke/pixcode-workbench-1-48.mjs +55 -0
  66. package/scripts/smoke/taskmaster-config.mjs +21 -56
  67. package/scripts/smoke/taskmaster-execution-telegram.mjs +1 -50
  68. package/scripts/smoke/taskmaster-onboarding.mjs +1 -50
  69. package/scripts/smoke/taskmaster-run-graph.mjs +1 -53
  70. package/scripts/smoke/vscode-workbench-layout.mjs +25 -62
  71. package/scripts/smoke/vscode-workbench-polish.mjs +77 -5
  72. package/server/index.js +5 -7
  73. package/server/modules/orchestration/a2a/adapters/claude-code.adapter.ts +1 -1
  74. package/server/modules/orchestration/a2a/adapters/codex.adapter.ts +1 -1
  75. package/server/modules/orchestration/a2a/adapters/cursor.adapter.ts +1 -1
  76. package/server/modules/orchestration/a2a/adapters/gemini.adapter.ts +1 -1
  77. package/server/modules/orchestration/a2a/adapters/opencode.adapter.ts +1 -1
  78. package/server/modules/orchestration/a2a/adapters/qwen.adapter.ts +1 -1
  79. package/server/modules/orchestration/a2a/agent-card.ts +4 -4
  80. package/server/modules/orchestration/a2a/routes.ts +7 -2
  81. package/server/modules/orchestration/hermes/hermes.routes.ts +69 -0
  82. package/server/modules/orchestration/index.ts +2 -1
  83. package/server/modules/orchestration/tasks/orchestration-task-store.ts +2 -6
  84. package/server/modules/orchestration/tasks/orchestration-task.routes.ts +1 -20
  85. package/server/modules/orchestration/tasks/orchestration-task.service.ts +4 -41
  86. package/server/modules/orchestration/tasks/orchestration-task.types.ts +2 -4
  87. package/server/modules/orchestration/tasks/task-run-graph.ts +6 -70
  88. package/server/modules/orchestration/workflows/workflow-runner.ts +14 -14
  89. package/server/modules/orchestration/workflows/workflow-trace.ts +2 -2
  90. package/server/modules/orchestration/workflows/workflow.types.ts +1 -1
  91. package/server/projects.js +0 -170
  92. package/server/routes/mcp-utils.js +0 -19
  93. package/server/services/public-api-manifest.js +0 -5
  94. package/server/services/telegram/control-center.js +2 -153
  95. package/server/services/telegram/translations.js +2 -14
  96. package/dist/assets/index-BBdWwJi6.css +0 -32
  97. package/dist/assets/index-DfqcgNYJ.js +0 -889
  98. package/dist-server/server/routes/taskmaster.js +0 -1793
  99. package/dist-server/server/routes/taskmaster.js.map +0 -1
  100. package/dist-server/server/services/taskmaster-config.js +0 -128
  101. package/dist-server/server/services/taskmaster-config.js.map +0 -1
  102. package/dist-server/server/utils/mcp-detector.js +0 -134
  103. package/dist-server/server/utils/mcp-detector.js.map +0 -1
  104. package/dist-server/server/utils/taskmaster-websocket.js +0 -118
  105. package/dist-server/server/utils/taskmaster-websocket.js.map +0 -1
  106. package/server/routes/taskmaster.js +0 -1918
  107. package/server/services/taskmaster-config.js +0 -146
  108. package/server/utils/mcp-detector.js +0 -147
  109. package/server/utils/taskmaster-websocket.js +0 -129
@@ -41,6 +41,76 @@ assert.match(
41
41
  'Projects activity should use a dedicated project-directory panel.',
42
42
  );
43
43
 
44
+ assert.match(
45
+ workbench,
46
+ /function WorkbenchProjectLanding/,
47
+ 'Workbench center should show a project landing page instead of a blank editor when no project is selected.',
48
+ );
49
+
50
+ assert.match(
51
+ workbench,
52
+ /function WorkbenchCliPanel/,
53
+ 'Right workbench pane should use a terminal-only CLI panel.',
54
+ );
55
+
56
+ assert.match(
57
+ workbench,
58
+ /function WorkbenchWorkspaceTabs/,
59
+ 'Workbench should render Chrome-style workspace tabs directly under the menu bar.',
60
+ );
61
+
62
+ assert.match(
63
+ workbench,
64
+ /WORKBENCH_WORKSPACE_TABS_STORAGE_KEY/,
65
+ 'Workspace tabs should persist names, stars, and open tabs across reloads.',
66
+ );
67
+
68
+ assert.doesNotMatch(
69
+ workbench,
70
+ /workspaceSlots/,
71
+ 'Workspace controls should no longer occupy space inside the Explorer panel.',
72
+ );
73
+
74
+ assert.match(
75
+ workbench,
76
+ /editorTabStripRef/,
77
+ 'Editor tabs should have a scrollable strip instead of shrinking every tab.',
78
+ );
79
+
80
+ assert.match(
81
+ workbench,
82
+ /handleEditorTabContextMenu/,
83
+ 'Editor tabs should expose a right-click context menu.',
84
+ );
85
+
86
+ for (const token of ['closeAllTabs', 'copyPath', 'splitRight', 'splitMoveRight']) {
87
+ assert.match(workbench, new RegExp(token), `Editor tab context menu should support ${token}.`);
88
+ }
89
+
90
+ assert.match(
91
+ workbench,
92
+ /SessionProviderLogo/,
93
+ 'CLI provider picker should keep provider icons visible.',
94
+ );
95
+
96
+ assert.match(
97
+ workbench,
98
+ /useProviderAuthStatus/,
99
+ 'CLI provider picker should show install/update status without opening Settings.',
100
+ );
101
+
102
+ assert.match(
103
+ workbench,
104
+ /autoConnect=\{canAutoConnect\}/,
105
+ 'Right CLI terminal should auto-connect when the selected provider can run.',
106
+ );
107
+
108
+ assert.match(
109
+ workbench,
110
+ /function WorkbenchSessionHistory/,
111
+ 'CLI history should be integrated as a polished project-scoped panel.',
112
+ );
113
+
44
114
  assert.doesNotMatch(
45
115
  workbench,
46
116
  /return <Sidebar \{\.\.\.sidebarProps\} isMobile=\{false\} \/>/,
@@ -59,6 +129,12 @@ assert.match(
59
129
  'Projects panel should show file counts.',
60
130
  );
61
131
 
132
+ assert.match(
133
+ workbench,
134
+ /Work in this folder/,
135
+ 'Project cards should make the folder binding explicit.',
136
+ );
137
+
62
138
  assert.match(projectType, /fileCount\?: number/, 'Project type should expose optional fileCount metadata.');
63
139
  assert.match(projectsServer, /async function countProjectFiles/, 'Backend should count project files for the workbench project list.');
64
140
 
@@ -74,11 +150,7 @@ assert.doesNotMatch(
74
150
  'Workbench center panel should be allowed to shrink with narrow three-pane layouts.',
75
151
  );
76
152
 
77
- assert.match(
78
- workbench,
79
- /compactComposer/,
80
- 'Workbench should request compact composer behavior in the right CLI pane.',
81
- );
153
+ assert.doesNotMatch(workbench, /<ChatInterface/, 'Workbench should not embed the chat composer in the right CLI pane.');
82
154
 
83
155
  assert.match(
84
156
  workbench,
package/server/index.js CHANGED
@@ -58,7 +58,6 @@ import sessionManager from './sessionManager.js';
58
58
  import gitRoutes from './routes/git.js';
59
59
  import authRoutes from './routes/auth.js';
60
60
  import cursorRoutes from './routes/cursor.js';
61
- import taskmasterRoutes from './routes/taskmaster.js';
62
61
  import mcpUtilsRoutes from './routes/mcp-utils.js';
63
62
  import commandsRoutes from './routes/commands.js';
64
63
  import settingsRoutes from './routes/settings.js';
@@ -84,7 +83,7 @@ import platformizationRoutes from './routes/platformization.js';
84
83
  import liveViewRoutes, { createLiveViewPublicRouter } from './routes/live-view.js';
85
84
  import providerRoutes from './modules/providers/provider.routes.js';
86
85
  import {
87
- createA2ARouter,
86
+ createHermesTaskRouter,
88
87
  adapterRegistry,
89
88
  ClaudeCodeA2AAdapter,
90
89
  CodexA2AAdapter,
@@ -94,6 +93,7 @@ import {
94
93
  QwenA2AAdapter,
95
94
  createPreviewProxyRouter,
96
95
  createOrchestrationTaskRouter,
96
+ createHermesRouter,
97
97
  createWorkflowRouter,
98
98
  } from './modules/orchestration/index.js';
99
99
  import networkRoutes from './routes/network.js';
@@ -370,9 +370,6 @@ app.use('/api/git', authenticateToken, gitRoutes);
370
370
  // Cursor API Routes (protected)
371
371
  app.use('/api/cursor', authenticateToken, cursorRoutes);
372
372
 
373
- // TaskMaster API Routes (protected)
374
- app.use('/api/taskmaster', authenticateToken, taskmasterRoutes);
375
-
376
373
  // MCP utilities
377
374
  app.use('/api/mcp-utils', authenticateToken, mcpUtilsRoutes);
378
375
 
@@ -424,16 +421,17 @@ app.use('/api/live-view', authenticateToken, liveViewRoutes);
424
421
  // Unified provider MCP routes (protected)
425
422
  app.use('/api/providers', authenticateToken, providerRoutes);
426
423
 
427
- // A2A protocol router has its own auth middleware, do NOT wrap with authenticateToken
424
+ // Hermes internal task router has its own localhost/auth middleware; do not wrap with authenticateToken.
428
425
  adapterRegistry.register(new ClaudeCodeA2AAdapter());
429
426
  adapterRegistry.register(new CodexA2AAdapter());
430
427
  adapterRegistry.register(new CursorA2AAdapter());
431
428
  adapterRegistry.register(new GeminiA2AAdapter());
432
429
  adapterRegistry.register(new QwenA2AAdapter());
433
430
  adapterRegistry.register(new OpenCodeA2AAdapter());
434
- app.use('/a2a', createA2ARouter());
431
+ app.use('/hermes', createHermesTaskRouter());
435
432
  app.use('/preview', authenticateToken, createPreviewProxyRouter());
436
433
  app.use('/api/orchestration', authenticateToken, createOrchestrationTaskRouter());
434
+ app.use('/api/orchestration/hermes', authenticateToken, createHermesRouter());
437
435
  app.use('/api/orchestration', authenticateToken, createWorkflowRouter());
438
436
  app.use('/live', createLiveViewPublicRouter());
439
437
 
@@ -49,7 +49,7 @@ export class ClaudeCodeA2AAdapter extends AbstractA2AAdapter {
49
49
  readonly agentCard: AgentCard = {
50
50
  name: 'pixcode-claude-code',
51
51
  description: 'Anthropic Claude Code, accessed via Pixcode',
52
- url: '/a2a/agents/claude-code',
52
+ url: '/hermes/agents/claude-code',
53
53
  version: '1.0.0',
54
54
  capabilities: ['streaming', 'fileEdit', 'commandExec', 'mcp'],
55
55
  skills: [
@@ -40,7 +40,7 @@ export class CodexA2AAdapter extends AbstractA2AAdapter {
40
40
  readonly agentCard: AgentCard = {
41
41
  name: 'pixcode-codex',
42
42
  description: 'OpenAI Codex, accessed via Pixcode',
43
- url: '/a2a/agents/codex',
43
+ url: '/hermes/agents/codex',
44
44
  version: '1.0.0',
45
45
  capabilities: ['streaming', 'fileEdit', 'commandExec', 'webSearch', 'mcp'],
46
46
  skills: [
@@ -40,7 +40,7 @@ export class CursorA2AAdapter extends AbstractA2AAdapter {
40
40
  readonly agentCard: AgentCard = {
41
41
  name: 'pixcode-cursor',
42
42
  description: 'Cursor CLI, accessed via Pixcode',
43
- url: '/a2a/agents/cursor',
43
+ url: '/hermes/agents/cursor',
44
44
  version: '1.0.0',
45
45
  capabilities: ['streaming', 'fileEdit', 'commandExec'],
46
46
  skills: [
@@ -40,7 +40,7 @@ export class GeminiA2AAdapter extends AbstractA2AAdapter {
40
40
  readonly agentCard: AgentCard = {
41
41
  name: 'pixcode-gemini',
42
42
  description: 'Google Gemini CLI, accessed via Pixcode',
43
- url: '/a2a/agents/gemini',
43
+ url: '/hermes/agents/gemini',
44
44
  version: '1.0.0',
45
45
  capabilities: ['streaming', 'fileEdit', 'commandExec', 'mcp'],
46
46
  skills: [
@@ -40,7 +40,7 @@ export class OpenCodeA2AAdapter extends AbstractA2AAdapter {
40
40
  readonly agentCard: AgentCard = {
41
41
  name: 'pixcode-opencode',
42
42
  description: 'OpenCode CLI, accessed via Pixcode',
43
- url: '/a2a/agents/opencode',
43
+ url: '/hermes/agents/opencode',
44
44
  version: '1.0.0',
45
45
  capabilities: ['streaming', 'fileEdit', 'commandExec', 'multiProvider'],
46
46
  skills: [
@@ -40,7 +40,7 @@ export class QwenA2AAdapter extends AbstractA2AAdapter {
40
40
  readonly agentCard: AgentCard = {
41
41
  name: 'pixcode-qwen',
42
42
  description: 'Qwen Code CLI, accessed via Pixcode',
43
- url: '/a2a/agents/qwen',
43
+ url: '/hermes/agents/qwen',
44
44
  version: '1.0.0',
45
45
  capabilities: ['streaming', 'fileEdit', 'commandExec', 'mcp'],
46
46
  skills: [
@@ -1,6 +1,6 @@
1
1
  // server/modules/orchestration/a2a/agent-card.ts
2
- // Pixcode advertises itself as one A2A agent at /a2a/.well-known/agent-card.json.
3
- // Per-CLI adapters publish their own cards under /a2a/agents/:id/agent-card.
2
+ // Pixcode advertises Hermes as one local control agent at /hermes/.well-known/agent-card.json.
3
+ // Per-CLI adapters publish their own cards under /hermes/agents/:id/agent-card.
4
4
 
5
5
  import { readFileSync } from 'node:fs';
6
6
  import { dirname, resolve } from 'node:path';
@@ -44,9 +44,9 @@ export function buildPixcodeAgentCard(baseUrl: string): AgentCard {
44
44
  return {
45
45
  name: 'pixcode',
46
46
  description:
47
- 'Pixcode multi-CLI orchestration platform. Routes A2A tasks to ' +
47
+ 'Pixcode Hermes multi-CLI orchestration platform. Routes Hermes tasks to ' +
48
48
  'Claude Code, Codex, Cursor, Gemini, Qwen, or OpenCode adapters.',
49
- url: `${baseUrl.replace(/\/$/, '')}/a2a`,
49
+ url: `${baseUrl.replace(/\/$/, '')}/hermes`,
50
50
  version: VERSION,
51
51
  capabilities: ['streaming', 'taskRouting'],
52
52
  skills,
@@ -1,5 +1,6 @@
1
1
  // server/modules/orchestration/a2a/routes.ts
2
- // HTTP surface for A2A v0.2. Mounted at /a2a in server/index.js.
2
+ // Internal Hermes task router. The adapter primitives still live in this legacy
3
+ // folder, but the public mount is /hermes.
3
4
 
4
5
  import crypto from 'node:crypto';
5
6
 
@@ -257,7 +258,7 @@ for (const task of taskStore.values()) {
257
258
  }
258
259
  }
259
260
 
260
- export function createA2ARouter(): Router {
261
+ function createA2ARouter(): Router {
261
262
  const router: Router = express.Router();
262
263
 
263
264
  router.use(express.json({ limit: '5mb' }));
@@ -583,3 +584,7 @@ export function createA2ARouter(): Router {
583
584
 
584
585
  return router;
585
586
  }
587
+
588
+ export function createHermesTaskRouter(): Router {
589
+ return createA2ARouter();
590
+ }
@@ -0,0 +1,69 @@
1
+ import os from 'node:os';
2
+
3
+ import express, { type Router } from 'express';
4
+
5
+ import { adapterRegistry } from '@/modules/orchestration/a2a/adapter-registry.js';
6
+ import { a2aTaskStore as hermesTaskStore } from '@/modules/orchestration/a2a/task-store.js';
7
+
8
+ export function createHermesRouter(): Router {
9
+ const router = express.Router();
10
+
11
+ router.get('/status', (_req, res) => {
12
+ res.json({
13
+ id: 'hermes',
14
+ name: 'Hermes Agent',
15
+ product: 'Pixcode',
16
+ runtime: {
17
+ mode: process.env.PIXCODE_MANAGED_PLATFORM === '1' ? 'managed' : 'local',
18
+ host: os.hostname(),
19
+ node: process.version,
20
+ pid: process.pid,
21
+ },
22
+ capabilities: [
23
+ 'project-aware CLI orchestration',
24
+ 'background checks and tests',
25
+ 'workspace-scoped terminal operations',
26
+ 'run history and artifact review',
27
+ ],
28
+ });
29
+ });
30
+
31
+ router.get('/context', (req, res) => {
32
+ const project = typeof req.query.project === 'string' ? req.query.project : null;
33
+ const cwd = typeof req.query.cwd === 'string' ? req.query.cwd : process.cwd();
34
+ res.json({
35
+ agent: 'Hermes Agent',
36
+ product: 'Pixcode',
37
+ project,
38
+ cwd,
39
+ local: true,
40
+ message: project
41
+ ? `Hermes is operating inside Pixcode for ${project}.`
42
+ : 'Hermes is operating inside Pixcode.',
43
+ });
44
+ });
45
+
46
+ router.get('/agents', (_req, res) => {
47
+ res.json({
48
+ agent: 'hermes',
49
+ agents: adapterRegistry.agentCards().map((agent) => ({
50
+ ...agent,
51
+ coordinator: 'hermes',
52
+ })),
53
+ });
54
+ });
55
+
56
+ router.get('/tasks/:id', (req, res) => {
57
+ const task = hermesTaskStore.get(req.params.id);
58
+ if (!task) {
59
+ res.status(404).json({ error: { code: 'HERMES_TASK_NOT_FOUND', message: req.params.id } });
60
+ return;
61
+ }
62
+ res.json({
63
+ ...task,
64
+ hermesTaskId: task.id,
65
+ });
66
+ });
67
+
68
+ return router;
69
+ }
@@ -3,7 +3,7 @@
3
3
  // All cross-module consumers must import from here per
4
4
  // eslint.config.js boundaries rules.
5
5
 
6
- export { createA2ARouter } from './a2a/routes.js';
6
+ export { createHermesTaskRouter } from './a2a/routes.js';
7
7
  export { adapterRegistry } from './a2a/adapter-registry.js';
8
8
  export { ClaudeCodeA2AAdapter } from './a2a/adapters/claude-code.adapter.js';
9
9
  export { CodexA2AAdapter } from './a2a/adapters/codex.adapter.js';
@@ -30,6 +30,7 @@ export {
30
30
  } from './security/permission-policy.js';
31
31
  export { createOrchestrationTaskRouter } from './tasks/orchestration-task.routes.js';
32
32
  export { orchestrationTaskService } from './tasks/orchestration-task.service.js';
33
+ export { createHermesRouter } from './hermes/hermes.routes.js';
33
34
  export { createWorkflowRouter } from './workflows/workflow.routes.js';
34
35
  export {
35
36
  listPendingApprovals,
@@ -20,12 +20,8 @@ export class OrchestrationTaskStore {
20
20
  return this.store.findWhere('orchestration_tasks', (r: OrchestrationTask) => r.id === id) ?? undefined;
21
21
  }
22
22
 
23
- getByA2ATaskId(a2aTaskId: string): OrchestrationTask | undefined {
24
- return this.store.findWhere('orchestration_tasks', (r: OrchestrationTask) => r.a2aTaskId === a2aTaskId) ?? undefined;
25
- }
26
-
27
- getByTaskMasterId(taskmasterId: string): OrchestrationTask | undefined {
28
- return this.store.findWhere('orchestration_tasks', (r: OrchestrationTask) => r.taskmasterId === taskmasterId) ?? undefined;
23
+ getByHermesTaskId(hermesTaskId: string): OrchestrationTask | undefined {
24
+ return this.store.findWhere('orchestration_tasks', (r: OrchestrationTask) => r.hermesTaskId === hermesTaskId) ?? undefined;
29
25
  }
30
26
 
31
27
  list(projectId?: string): OrchestrationTask[] {
@@ -15,35 +15,16 @@ export function createOrchestrationTaskRouter(): Router {
15
15
  const projectId = typeof req.body?.projectId === 'string' ? req.body.projectId : 'default';
16
16
  const title = typeof req.body?.title === 'string' ? req.body.title.trim() : '';
17
17
  const description = typeof req.body?.description === 'string' ? req.body.description : undefined;
18
- const taskmasterId = typeof req.body?.taskmasterId === 'string' ? req.body.taskmasterId : undefined;
19
18
 
20
19
  if (!title) {
21
20
  res.status(400).json({ error: { code: 'TITLE_REQUIRED', message: 'title is required' } });
22
21
  return;
23
22
  }
24
23
 
25
- const task = orchestrationTaskService.create({ projectId, title, description, taskmasterId });
24
+ const task = orchestrationTaskService.create({ projectId, title, description });
26
25
  res.status(201).json(task);
27
26
  });
28
27
 
29
- router.post('/tasks/import-taskmaster', (req, res) => {
30
- const projectId = typeof req.body?.projectId === 'string' ? req.body.projectId : 'default';
31
- const entries = Array.isArray(req.body?.tasks) ? req.body.tasks : [];
32
- const imported = entries
33
- .map((entry: unknown) => {
34
- if (!entry || typeof entry !== 'object') return null;
35
- const record = entry as Record<string, unknown>;
36
- const taskmasterId = typeof record.id === 'string' ? record.id : undefined;
37
- const title = typeof record.title === 'string' ? record.title : undefined;
38
- const description = typeof record.description === 'string' ? record.description : undefined;
39
- if (!taskmasterId || !title) return null;
40
- return orchestrationTaskService.upsertFromTaskMaster({ projectId, title, description, taskmasterId });
41
- })
42
- .filter(Boolean);
43
-
44
- res.json({ tasks: imported, count: imported.length });
45
- });
46
-
47
28
  router.post('/tasks/:id/dispatch', async (req, res) => {
48
29
  try {
49
30
  const adapterId = typeof req.body?.adapterId === 'string' ? req.body.adapterId : '';
@@ -79,7 +79,6 @@ class OrchestrationTaskService {
79
79
  projectId: input.projectId,
80
80
  title: input.title,
81
81
  description: input.description,
82
- taskmasterId: input.taskmasterId,
83
82
  acceptanceCriteria: input.acceptanceCriteria,
84
83
  changedFiles: input.changedFiles,
85
84
  state: 'todo',
@@ -90,27 +89,11 @@ class OrchestrationTaskService {
90
89
  return task;
91
90
  }
92
91
 
93
- upsertFromTaskMaster(input: CreateOrchestrationTaskInput): OrchestrationTask {
94
- const existing = this.store.list(input.projectId).find((task) =>
95
- task.taskmasterId === input.taskmasterId,
96
- );
97
- if (existing) {
98
- existing.title = input.title;
99
- existing.description = input.description;
100
- existing.acceptanceCriteria = input.acceptanceCriteria ?? existing.acceptanceCriteria;
101
- existing.changedFiles = uniqueStrings([...(existing.changedFiles ?? []), ...(input.changedFiles ?? [])]);
102
- existing.updatedAt = Date.now();
103
- this.store.set(existing);
104
- return existing;
105
- }
106
- return this.create(input);
107
- }
108
-
109
92
  async dispatch(taskId: string, input: DispatchOrchestrationTaskInput): Promise<OrchestrationTask> {
110
93
  const task = this.store.get(taskId);
111
94
  if (!task) throw new Error('TASK_NOT_FOUND');
112
95
 
113
- const a2aResponse = await fetch(`http://127.0.0.1:${process.env.SERVER_PORT ?? '3001'}/a2a/tasks`, {
96
+ const a2aResponse = await fetch(`http://127.0.0.1:${process.env.SERVER_PORT ?? '3001'}/hermes/tasks`, {
114
97
  method: 'POST',
115
98
  headers: { 'Content-Type': 'application/json' },
116
99
  body: JSON.stringify({
@@ -129,7 +112,6 @@ class OrchestrationTaskService {
129
112
  projectPath: input.projectPath,
130
113
  },
131
114
  orchestrationTaskId: task.id,
132
- taskmasterId: task.taskmasterId,
133
115
  },
134
116
  }),
135
117
  });
@@ -139,7 +121,7 @@ class OrchestrationTaskService {
139
121
  throw new Error(body?.error?.message ?? 'DISPATCH_FAILED');
140
122
  }
141
123
 
142
- task.a2aTaskId = body.id;
124
+ task.hermesTaskId = body.id;
143
125
  task.adapterId = input.adapterId;
144
126
  task.adapterSelector = input.adapterId;
145
127
  task.workspaceKind = input.isolation ?? 'worktree';
@@ -163,12 +145,7 @@ class OrchestrationTaskService {
163
145
  updateFromWorkflowRun(run: WorkflowRun): OrchestrationTask | undefined {
164
146
  const metadata = run.metadata ?? {};
165
147
  const taskId = readString(metadata.orchestrationTaskId);
166
- const taskmasterId = readString(metadata.taskmasterId);
167
- const task = taskId
168
- ? this.store.get(taskId)
169
- : taskmasterId
170
- ? this.store.list(readString(metadata.projectId)).find((candidate) => candidate.taskmasterId === taskmasterId)
171
- : undefined;
148
+ const task = taskId ? this.store.get(taskId) : undefined;
172
149
  if (!task) return undefined;
173
150
 
174
151
  const changedFiles = changedFilesFromWorkflowRun(run);
@@ -187,9 +164,6 @@ class OrchestrationTaskService {
187
164
  task.updatedAt = Date.now();
188
165
  this.store.set(task);
189
166
 
190
- if (task.taskmasterId && task.state === 'done') {
191
- this.syncTaskMasterStatus(task.taskmasterId, 'done');
192
- }
193
167
  return task;
194
168
  }
195
169
 
@@ -207,7 +181,7 @@ class OrchestrationTaskService {
207
181
  if (event.kind !== 'task-state') return;
208
182
  if (!TERMINAL_A2A_STATES.includes(event.state)) return;
209
183
 
210
- const orchTask = this.store.getByA2ATaskId(event.taskId);
184
+ const orchTask = this.store.getByHermesTaskId(event.taskId);
211
185
  if (!orchTask) return;
212
186
  if (orchTask.state === 'done' || orchTask.state === 'failed' || orchTask.state === 'canceled') return;
213
187
 
@@ -219,20 +193,9 @@ class OrchestrationTaskService {
219
193
  orchTask.updatedAt = Date.now();
220
194
  this.store.set(orchTask);
221
195
 
222
- if (orchTask.taskmasterId && mapped === 'done') {
223
- this.syncTaskMasterStatus(orchTask.taskmasterId, 'done');
224
- }
225
196
  });
226
197
  }
227
198
 
228
- private syncTaskMasterStatus(taskmasterId: string, status: string): void {
229
- const { spawn } = require('node:child_process') as typeof import('node:child_process');
230
- spawn('task-master', ['set-status', '--id', taskmasterId, '--status', status], {
231
- stdio: 'ignore',
232
- detached: true,
233
- }).unref();
234
- }
235
-
236
199
  cancel(taskId: string): OrchestrationTask {
237
200
  const task = this.store.get(taskId);
238
201
  if (!task) throw new Error('TASK_NOT_FOUND');
@@ -2,9 +2,8 @@ export type OrchestrationTaskState = 'todo' | 'in_progress' | 'in_review' | 'don
2
2
 
3
3
  export interface OrchestrationTask {
4
4
  id: string;
5
- a2aTaskId?: string;
5
+ hermesTaskId?: string;
6
6
  workflowRunIds?: string[];
7
- taskmasterId?: string;
8
7
  projectId: string;
9
8
  title: string;
10
9
  description?: string;
@@ -13,7 +12,7 @@ export interface OrchestrationTask {
13
12
  id: string;
14
13
  label: string;
15
14
  status: 'pending' | 'passed' | 'failed';
16
- source: 'taskmaster' | 'workflow';
15
+ source: 'workflow' | 'hermes';
17
16
  }>;
18
17
  changedFiles?: string[];
19
18
  adapterId?: string;
@@ -28,7 +27,6 @@ export interface CreateOrchestrationTaskInput {
28
27
  projectId: string;
29
28
  title: string;
30
29
  description?: string;
31
- taskmasterId?: string;
32
30
  acceptanceCriteria?: OrchestrationTask['acceptanceCriteria'];
33
31
  changedFiles?: string[];
34
32
  }