@pixelbyte-software/pixcode 1.42.4 → 1.43.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 (52) hide show
  1. package/dist/assets/index-B-_FofJ_.css +32 -0
  2. package/dist/assets/{index-cTGs3Dvx.js → index-CDKI7Ucy.js} +170 -170
  3. package/dist/index.html +2 -2
  4. package/dist-server/server/index.js +3 -0
  5. package/dist-server/server/index.js.map +1 -1
  6. package/dist-server/server/modules/orchestration/index.js +2 -0
  7. package/dist-server/server/modules/orchestration/index.js.map +1 -1
  8. package/dist-server/server/modules/orchestration/workflows/approval-queue.js +72 -0
  9. package/dist-server/server/modules/orchestration/workflows/approval-queue.js.map +1 -0
  10. package/dist-server/server/modules/orchestration/workflows/workflow-runner.js +25 -0
  11. package/dist-server/server/modules/orchestration/workflows/workflow-runner.js.map +1 -1
  12. package/dist-server/server/modules/orchestration/workflows/workflow-templates.js +242 -0
  13. package/dist-server/server/modules/orchestration/workflows/workflow-templates.js.map +1 -0
  14. package/dist-server/server/modules/orchestration/workflows/workflow-trace.js +21 -0
  15. package/dist-server/server/modules/orchestration/workflows/workflow-trace.js.map +1 -1
  16. package/dist-server/server/modules/orchestration/workflows/workflow.routes.js +121 -0
  17. package/dist-server/server/modules/orchestration/workflows/workflow.routes.js.map +1 -1
  18. package/dist-server/server/routes/public-api.js +7 -1
  19. package/dist-server/server/routes/public-api.js.map +1 -1
  20. package/dist-server/server/routes/remote.js +18 -0
  21. package/dist-server/server/routes/remote.js.map +1 -1
  22. package/dist-server/server/routes/webhooks.js +53 -0
  23. package/dist-server/server/routes/webhooks.js.map +1 -0
  24. package/dist-server/server/services/control-room.js +89 -0
  25. package/dist-server/server/services/control-room.js.map +1 -0
  26. package/dist-server/server/services/public-api-manifest.js +96 -0
  27. package/dist-server/server/services/public-api-manifest.js.map +1 -1
  28. package/dist-server/server/services/telegram/control-center.js +110 -0
  29. package/dist-server/server/services/telegram/control-center.js.map +1 -1
  30. package/dist-server/server/services/telegram/translations.js +24 -2
  31. package/dist-server/server/services/telegram/translations.js.map +1 -1
  32. package/dist-server/server/services/webhooks.js +198 -0
  33. package/dist-server/server/services/webhooks.js.map +1 -0
  34. package/package.json +1 -1
  35. package/scripts/smoke/v143-remote-control.mjs +76 -0
  36. package/scripts/smoke/workflow-templates.mjs +43 -0
  37. package/server/index.js +4 -0
  38. package/server/modules/orchestration/index.ts +14 -0
  39. package/server/modules/orchestration/workflows/approval-queue.ts +106 -0
  40. package/server/modules/orchestration/workflows/workflow-runner.ts +25 -0
  41. package/server/modules/orchestration/workflows/workflow-templates.ts +272 -0
  42. package/server/modules/orchestration/workflows/workflow-trace.ts +22 -0
  43. package/server/modules/orchestration/workflows/workflow.routes.ts +139 -0
  44. package/server/routes/public-api.js +14 -1
  45. package/server/routes/remote.js +22 -0
  46. package/server/routes/webhooks.js +63 -0
  47. package/server/services/control-room.js +102 -0
  48. package/server/services/public-api-manifest.js +98 -0
  49. package/server/services/telegram/control-center.js +113 -0
  50. package/server/services/telegram/translations.js +24 -2
  51. package/server/services/webhooks.js +216 -0
  52. package/dist/assets/index-CHa1760s.css +0 -32
@@ -1,5 +1,6 @@
1
1
  import express from 'express';
2
2
  import { checkRemoteConnection, getPublicRemoteConnectionConfig, saveRemoteConnectionConfig, } from '../services/remote-connection.js';
3
+ import { buildControlRoomSnapshot, buildMobileConsoleLayout, } from '../services/control-room.js';
3
4
  const router = express.Router();
4
5
  router.get('/config', (req, res) => {
5
6
  res.json({ success: true, connection: getPublicRemoteConnectionConfig() });
@@ -22,5 +23,22 @@ router.post('/check', async (req, res) => {
22
23
  res.status(400).json({ success: false, error: error.message });
23
24
  }
24
25
  });
26
+ router.get('/control-room', async (_req, res) => {
27
+ try {
28
+ res.json({
29
+ success: true,
30
+ controlRoom: await buildControlRoomSnapshot(),
31
+ });
32
+ }
33
+ catch (error) {
34
+ res.status(500).json({ success: false, error: error.message });
35
+ }
36
+ });
37
+ router.get('/console-layout', (_req, res) => {
38
+ res.json({
39
+ success: true,
40
+ layout: buildMobileConsoleLayout(),
41
+ });
42
+ });
25
43
  export default router;
26
44
  //# sourceMappingURL=remote.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"remote.js","sourceRoot":"","sources":["../../../server/routes/remote.js"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAE9B,OAAO,EACL,qBAAqB,EACrB,+BAA+B,EAC/B,0BAA0B,GAC3B,MAAM,kCAAkC,CAAC;AAE1C,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;AAEhC,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;IACjC,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,+BAA+B,EAAE,EAAE,CAAC,CAAC;AAC7E,CAAC,CAAC,CAAC;AAEH,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;IACjC,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,0BAA0B,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;QAC9D,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;IAC1C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IACjE,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;IACvC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,qBAAqB,CAAC,GAAG,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QAC5G,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,+BAA+B,EAAE,EAAE,CAAC,CAAC;IACrF,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IACjE,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,eAAe,MAAM,CAAC"}
1
+ {"version":3,"file":"remote.js","sourceRoot":"","sources":["../../../server/routes/remote.js"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAE9B,OAAO,EACL,qBAAqB,EACrB,+BAA+B,EAC/B,0BAA0B,GAC3B,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EACL,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,6BAA6B,CAAC;AAErC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;AAEhC,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;IACjC,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,+BAA+B,EAAE,EAAE,CAAC,CAAC;AAC7E,CAAC,CAAC,CAAC;AAEH,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;IACjC,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,0BAA0B,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;QAC9D,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;IAC1C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IACjE,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;IACvC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,qBAAqB,CAAC,GAAG,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QAC5G,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,+BAA+B,EAAE,EAAE,CAAC,CAAC;IACrF,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IACjE,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,MAAM,CAAC,GAAG,CAAC,eAAe,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE;IAC9C,IAAI,CAAC;QACH,GAAG,CAAC,IAAI,CAAC;YACP,OAAO,EAAE,IAAI;YACb,WAAW,EAAE,MAAM,wBAAwB,EAAE;SAC9C,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IACjE,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,MAAM,CAAC,GAAG,CAAC,iBAAiB,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;IAC1C,GAAG,CAAC,IAAI,CAAC;QACP,OAAO,EAAE,IAAI;QACb,MAAM,EAAE,wBAAwB,EAAE;KACnC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,eAAe,MAAM,CAAC"}
@@ -0,0 +1,53 @@
1
+ import express from 'express';
2
+ import { PIXCODE_WEBHOOK_EVENT_TYPES, deleteWebhook, deliverWebhookEvent, listWebhooks, upsertWebhook, } from '../services/webhooks.js';
3
+ const router = express.Router();
4
+ router.get('/', (_req, res) => {
5
+ res.json({
6
+ success: true,
7
+ eventTypes: PIXCODE_WEBHOOK_EVENT_TYPES,
8
+ webhooks: listWebhooks(),
9
+ });
10
+ });
11
+ router.post('/', (req, res) => {
12
+ try {
13
+ const webhook = upsertWebhook(req.body || {});
14
+ res.status(201).json({ success: true, webhook });
15
+ }
16
+ catch (error) {
17
+ res.status(400).json({ success: false, error: error.message });
18
+ }
19
+ });
20
+ router.patch('/:id', (req, res) => {
21
+ try {
22
+ const webhook = upsertWebhook({ ...(req.body || {}), id: req.params.id });
23
+ res.json({ success: true, webhook });
24
+ }
25
+ catch (error) {
26
+ res.status(400).json({ success: false, error: error.message });
27
+ }
28
+ });
29
+ router.delete('/:id', (req, res) => {
30
+ if (!deleteWebhook(req.params.id)) {
31
+ res.status(404).json({ success: false, error: 'Webhook not found.' });
32
+ return;
33
+ }
34
+ res.json({ success: true });
35
+ });
36
+ router.post('/test', async (req, res) => {
37
+ try {
38
+ const result = await deliverWebhookEvent({
39
+ type: req.body?.type || 'run.completed',
40
+ payload: {
41
+ test: true,
42
+ message: 'Pixcode webhook test delivery',
43
+ sentBy: req.user?.id ?? null,
44
+ },
45
+ });
46
+ res.json({ success: true, result });
47
+ }
48
+ catch (error) {
49
+ res.status(500).json({ success: false, error: error.message });
50
+ }
51
+ });
52
+ export default router;
53
+ //# sourceMappingURL=webhooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhooks.js","sourceRoot":"","sources":["../../../server/routes/webhooks.js"],"names":[],"mappings":"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"}
@@ -0,0 +1,89 @@
1
+ import { listPendingApprovals, workflowStore } from '../modules/orchestration/index.js';
2
+ import { getProjects } from '../projects.js';
3
+ import { listWebhooks } from './webhooks.js';
4
+ const TERMINAL_RUN_STATES = new Set(['completed', 'failed', 'canceled']);
5
+ function projectPath(project) {
6
+ return project.fullPath || project.path || '';
7
+ }
8
+ function runBelongsToProject(run, project) {
9
+ const projectId = run.metadata?.projectId;
10
+ const path = run.metadata?.projectPath;
11
+ return projectId === project.name || path === projectPath(project);
12
+ }
13
+ function countSessions(project) {
14
+ return [
15
+ project.sessions,
16
+ project.codexSessions,
17
+ project.cursorSessions,
18
+ project.geminiSessions,
19
+ project.qwenSessions,
20
+ project.opencodeSessions,
21
+ ].reduce((total, sessions) => total + (Array.isArray(sessions) ? sessions.length : 0), 0);
22
+ }
23
+ function summarizeProject(project, runs, approvals) {
24
+ const projectRuns = runs.filter((run) => runBelongsToProject(run, project));
25
+ const runningRuns = projectRuns.filter((run) => !TERMINAL_RUN_STATES.has(run.status));
26
+ const failedRuns = projectRuns.filter((run) => run.status === 'failed');
27
+ const projectApprovals = approvals.filter((approval) => (approval.runId && projectRuns.some((run) => run.id === approval.runId)));
28
+ return {
29
+ id: project.name,
30
+ name: project.displayName || project.name,
31
+ path: projectPath(project),
32
+ sessionCount: countSessions(project),
33
+ activeRunCount: runningRuns.length,
34
+ failedRunCount: failedRuns.length,
35
+ pendingApprovalCount: projectApprovals.length,
36
+ latestRuns: projectRuns.slice(0, 4).map((run) => ({
37
+ id: run.id,
38
+ workflowId: run.workflowId,
39
+ status: run.status,
40
+ startedAt: run.startedAt,
41
+ finishedAt: run.finishedAt,
42
+ })),
43
+ };
44
+ }
45
+ export async function buildControlRoomSnapshot({ maxProjects = 4 } = {}) {
46
+ const projects = await getProjects();
47
+ const runs = workflowStore.listRuns();
48
+ const pendingApprovals = listPendingApprovals();
49
+ const webhooks = listWebhooks();
50
+ const projectCards = projects
51
+ .map((project) => summarizeProject(project, runs, pendingApprovals))
52
+ .sort((a, b) => (b.pendingApprovalCount - a.pendingApprovalCount ||
53
+ b.activeRunCount - a.activeRunCount ||
54
+ b.failedRunCount - a.failedRunCount ||
55
+ a.name.localeCompare(b.name)))
56
+ .slice(0, maxProjects);
57
+ return {
58
+ protocol: 'pixcode.control-room.v1',
59
+ generatedAt: new Date().toISOString(),
60
+ maxProjects,
61
+ mobileFirst: true,
62
+ totals: {
63
+ projects: projects.length,
64
+ activeRuns: runs.filter((run) => !TERMINAL_RUN_STATES.has(run.status)).length,
65
+ failedRuns: runs.filter((run) => run.status === 'failed').length,
66
+ pendingApprovals: pendingApprovals.length,
67
+ webhooks: webhooks.length,
68
+ enabledWebhooks: webhooks.filter((webhook) => webhook.enabled).length,
69
+ },
70
+ projects: projectCards,
71
+ approvals: pendingApprovals.slice(0, 20),
72
+ webhooks,
73
+ };
74
+ }
75
+ export function buildMobileConsoleLayout() {
76
+ return {
77
+ protocol: 'pixcode.remote-console-layout.v1',
78
+ mobileFirst: true,
79
+ sections: [
80
+ { id: 'projects', title: 'Projects', priority: 1 },
81
+ { id: 'approvals', title: 'Approval queue', priority: 2 },
82
+ { id: 'runs', title: 'Runs', priority: 3 },
83
+ { id: 'webhooks', title: 'Webhooks', priority: 4 },
84
+ { id: 'api', title: 'API SDK', priority: 5 },
85
+ ],
86
+ maxVisibleProjects: 4,
87
+ };
88
+ }
89
+ //# sourceMappingURL=control-room.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"control-room.js","sourceRoot":"","sources":["../../../server/services/control-room.js"],"names":[],"mappings":"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"}
@@ -13,6 +13,7 @@ const API_GROUPS = [
13
13
  { id: 'diagnostics', title: 'Diagnostics', basePath: '/api/diagnostics', scopes: ['diagnostics:read'] },
14
14
  { id: 'remote', title: 'Remote connection', basePath: '/api/remote', scopes: ['remote:read', 'remote:write'] },
15
15
  { id: 'telegram', title: 'Telegram control', basePath: '/api/telegram', scopes: ['telegram:read', 'telegram:write'] },
16
+ { id: 'webhooks', title: 'Outbound webhooks', basePath: '/api/webhooks', scopes: ['webhooks:read', 'webhooks:write'] },
16
17
  { id: 'plugins', title: 'Plugins and MCP tools', basePath: '/api/plugins', scopes: ['plugins:read', 'plugins:write'] },
17
18
  ];
18
19
  const API_SCOPES = Array.from(new Set(API_GROUPS.flatMap((group) => group.scopes))).sort();
@@ -46,6 +47,101 @@ export function buildPublicApiManifest({ baseUrl = '' } = {}) {
46
47
  title: 'Fetch diagnostics bundle',
47
48
  curl: `curl -H "X-API-Key: px_your_key" ${origin || 'http://127.0.0.1:3001'}/api/diagnostics/bundle`,
48
49
  },
50
+ {
51
+ title: 'Read the mobile remote control room',
52
+ curl: `curl -H "X-API-Key: px_your_key" ${origin || 'http://127.0.0.1:3001'}/api/remote/control-room`,
53
+ },
54
+ {
55
+ title: 'Register an outbound webhook',
56
+ curl: `curl -X POST -H "Content-Type: application/json" -H "X-API-Key: px_your_key" -d '{"name":"CI listener","url":"https://example.com/pixcode","events":["run.completed","approval.needed"]}' ${origin || 'http://127.0.0.1:3001'}/api/webhooks`,
57
+ },
58
+ ],
59
+ };
60
+ }
61
+ export function buildTypeScriptSdkStarter({ baseUrl = '' } = {}) {
62
+ const origin = String(baseUrl || 'http://127.0.0.1:3001').replace(/\/+$/, '');
63
+ return `export type PixcodeRun = {
64
+ id: string;
65
+ workflowId: string;
66
+ status: 'queued' | 'running' | 'completed' | 'failed' | 'canceled';
67
+ };
68
+
69
+ export class PixcodeClient {
70
+ constructor(
71
+ private readonly apiKey: string,
72
+ private readonly baseUrl = '${origin}',
73
+ ) {}
74
+
75
+ private async request<T>(path: string, init: RequestInit = {}): Promise<T> {
76
+ const response = await fetch(new URL(path, this.baseUrl), {
77
+ ...init,
78
+ headers: {
79
+ 'Content-Type': 'application/json',
80
+ 'X-API-Key': this.apiKey,
81
+ ...(init.headers || {}),
82
+ },
83
+ });
84
+ if (!response.ok) throw new Error(\`Pixcode API \${response.status}: \${await response.text()}\`);
85
+ return response.json() as Promise<T>;
86
+ }
87
+
88
+ projects() {
89
+ return this.request<{ projects: unknown[] }>('/api/projects');
90
+ }
91
+
92
+ controlRoom() {
93
+ return this.request<{ success: true; controlRoom: unknown }>('/api/remote/control-room');
94
+ }
95
+
96
+ approvals() {
97
+ return this.request<{ pendingApprovals: unknown[] }>('/api/orchestration/workflows/approvals');
98
+ }
99
+
100
+ decideApproval(approvalId: string, allow: boolean) {
101
+ return this.request(\`/api/orchestration/workflows/approvals/\${encodeURIComponent(approvalId)}\`, {
102
+ method: 'POST',
103
+ body: JSON.stringify({ allow, source: 'api' }),
104
+ });
105
+ }
106
+
107
+ startWorkflow(workflowId: string, input: string, metadata: Record<string, unknown> = {}) {
108
+ return this.request<PixcodeRun>(\`/api/orchestration/workflows/\${encodeURIComponent(workflowId)}/runs\`, {
109
+ method: 'POST',
110
+ body: JSON.stringify({ input, metadata }),
111
+ });
112
+ }
113
+ }
114
+ `;
115
+ }
116
+ export function buildCurlCookbook({ baseUrl = '' } = {}) {
117
+ const origin = String(baseUrl || 'http://127.0.0.1:3001').replace(/\/+$/, '');
118
+ return {
119
+ title: 'Pixcode Public API Cookbook',
120
+ variables: {
121
+ PIXCODE_URL: origin,
122
+ PIXCODE_API_KEY: 'px_your_key',
123
+ },
124
+ examples: [
125
+ {
126
+ title: 'List projects',
127
+ command: `curl -H "X-API-Key: $PIXCODE_API_KEY" "$PIXCODE_URL/api/projects"`,
128
+ },
129
+ {
130
+ title: 'Read the mobile control room',
131
+ command: `curl -H "X-API-Key: $PIXCODE_API_KEY" "$PIXCODE_URL/api/remote/control-room"`,
132
+ },
133
+ {
134
+ title: 'List pending approvals',
135
+ command: `curl -H "X-API-Key: $PIXCODE_API_KEY" "$PIXCODE_URL/api/orchestration/workflows/approvals"`,
136
+ },
137
+ {
138
+ title: 'Approve a pending action',
139
+ command: `curl -X POST -H "Content-Type: application/json" -H "X-API-Key: $PIXCODE_API_KEY" -d '{"allow":true,"source":"api"}' "$PIXCODE_URL/api/orchestration/workflows/approvals/approval_id"`,
140
+ },
141
+ {
142
+ title: 'Create a webhook',
143
+ command: `curl -X POST -H "Content-Type: application/json" -H "X-API-Key: $PIXCODE_API_KEY" -d '{"name":"CI listener","url":"https://example.com/pixcode","events":["run.completed","run.failed","approval.needed"]}' "$PIXCODE_URL/api/webhooks"`,
144
+ },
49
145
  ],
50
146
  };
51
147
  }
@@ -1 +1 @@
1
- {"version":3,"file":"public-api-manifest.js","sourceRoot":"","sources":["../../../server/services/public-api-manifest.js"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"public-api-manifest.js","sourceRoot":"","sources":["../../../server/services/public-api-manifest.js"],"names":[],"mappings":"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"}
@@ -29,6 +29,10 @@ const CONTROL_COMMANDS = new Set([
29
29
  '/workflows',
30
30
  '/orchestration',
31
31
  '/runs',
32
+ '/approvals',
33
+ '/controlroom',
34
+ '/control-room',
35
+ '/webhooks',
32
36
  '/sessions',
33
37
  '/newchat',
34
38
  '/tasks',
@@ -183,6 +187,8 @@ function mainMenuKeyboard(lang) {
183
187
  [button(t(lang, 'control.button.projects'), 'projects'), button(t(lang, 'control.button.provider'), 'providers')],
184
188
  [button(t(lang, 'control.button.models'), 'models'), button(t(lang, 'control.button.workflows'), 'workflows')],
185
189
  [button(t(lang, 'control.button.tasks'), 'tasks'), button(t(lang, 'control.button.runs'), 'runs')],
190
+ [button(t(lang, 'control.button.approvals'), 'approvals'), button(t(lang, 'control.button.controlRoom'), 'control_room')],
191
+ [button(t(lang, 'control.button.webhooks'), 'webhooks')],
186
192
  [button(t(lang, 'control.button.sessions'), 'sessions'), button(t(lang, 'control.button.newChat'), 'new_chat')],
187
193
  [button(t(lang, 'control.button.install'), 'install_menu'), button(t(lang, 'control.button.auth'), 'auth_menu')],
188
194
  [button(t(lang, 'control.button.settings'), 'settings')],
@@ -291,6 +297,76 @@ async function showRuns({ bot, chatId, link, editMessageId }) {
291
297
  reply_markup: { inline_keyboard: rows(buttons, 1) },
292
298
  });
293
299
  }
300
+ async function showApprovalQueue({ bot, chatId, link, editMessageId }) {
301
+ const lang = languageFor(link);
302
+ const data = await localApi(link.user_id, '/api/orchestration/workflows/approvals');
303
+ const approvals = Array.isArray(data?.pendingApprovals) ? data.pendingApprovals : [];
304
+ if (approvals.length === 0) {
305
+ await send(bot, chatId, t(lang, 'control.noApprovals'), { editMessageId });
306
+ return;
307
+ }
308
+ const keyboard = [];
309
+ const lines = approvals.slice(0, 8).map((approval, index) => {
310
+ const label = compact(approval.summary || approval.reason || approval.id, 70);
311
+ keyboard.push([
312
+ button(t(lang, 'control.button.approve'), 'approval_decide', { approvalId: approval.id, allow: true }),
313
+ button(t(lang, 'control.button.deny'), 'approval_decide', { approvalId: approval.id, allow: false }),
314
+ ]);
315
+ return `${index + 1}. ${label}\nRun: ${approval.runId}`;
316
+ });
317
+ keyboard.push([button(t(lang, 'control.button.refresh'), 'approvals'), button(t(lang, 'control.button.mainMenu'), 'menu')]);
318
+ await send(bot, chatId, `${t(lang, 'control.approvalQueue')}\n\n${lines.join('\n\n')}`, {
319
+ editMessageId,
320
+ reply_markup: { inline_keyboard: keyboard },
321
+ });
322
+ }
323
+ async function showControlRoom({ bot, chatId, link, editMessageId }) {
324
+ const lang = languageFor(link);
325
+ const data = await localApi(link.user_id, '/api/remote/control-room');
326
+ const snapshot = data?.controlRoom || data;
327
+ const projects = Array.isArray(snapshot?.projects) ? snapshot.projects : [];
328
+ const totals = snapshot?.totals || {};
329
+ const lines = projects.map((project, index) => [
330
+ `${index + 1}. ${compact(project.name || project.id, 44)}`,
331
+ `Runs: ${project.activeRunCount || 0} active / ${project.failedRunCount || 0} failed`,
332
+ `Approvals: ${project.pendingApprovalCount || 0}`,
333
+ ].join('\n'));
334
+ await send(bot, chatId, [
335
+ t(lang, 'control.controlRoomTitle'),
336
+ '',
337
+ `Projects: ${totals.projects || 0}`,
338
+ `Active runs: ${totals.activeRuns || 0}`,
339
+ `Pending approvals: ${totals.pendingApprovals || 0}`,
340
+ '',
341
+ lines.join('\n\n') || t(lang, 'control.noProjects'),
342
+ ].join('\n'), {
343
+ editMessageId,
344
+ reply_markup: {
345
+ inline_keyboard: [
346
+ [button(t(lang, 'control.button.approvals'), 'approvals'), button(t(lang, 'control.button.runs'), 'runs')],
347
+ [button(t(lang, 'control.button.mainMenu'), 'menu')],
348
+ ],
349
+ },
350
+ });
351
+ }
352
+ async function showWebhookMenu({ bot, chatId, link, editMessageId }) {
353
+ const lang = languageFor(link);
354
+ const data = await localApi(link.user_id, '/api/webhooks');
355
+ const webhooks = Array.isArray(data?.webhooks) ? data.webhooks : [];
356
+ const lines = webhooks.slice(0, 10).map((webhook, index) => (`${index + 1}. ${webhook.enabled ? 'on' : 'off'} ${compact(webhook.name || webhook.url, 50)}\n${compact(webhook.events?.join(', ') || webhook.url, 90)}`));
357
+ await send(bot, chatId, [
358
+ t(lang, 'control.webhookTitle'),
359
+ '',
360
+ lines.join('\n\n') || t(lang, 'control.noWebhooks'),
361
+ ].join('\n'), {
362
+ editMessageId,
363
+ reply_markup: {
364
+ inline_keyboard: [
365
+ [button(t(lang, 'control.button.refresh'), 'webhooks'), button(t(lang, 'control.button.mainMenu'), 'menu')],
366
+ ],
367
+ },
368
+ });
369
+ }
294
370
  async function showSessions({ bot, chatId, link, editMessageId }) {
295
371
  const lang = languageFor(link);
296
372
  const state = getState(link.user_id);
@@ -704,6 +780,18 @@ async function handleCommand({ bot, chatId, link, text }) {
704
780
  await showRuns({ bot, chatId, link });
705
781
  return true;
706
782
  }
783
+ if (command === '/approvals') {
784
+ await showApprovalQueue({ bot, chatId, link });
785
+ return true;
786
+ }
787
+ if (command === '/controlroom' || command === '/control-room') {
788
+ await showControlRoom({ bot, chatId, link });
789
+ return true;
790
+ }
791
+ if (command === '/webhooks') {
792
+ await showWebhookMenu({ bot, chatId, link });
793
+ return true;
794
+ }
707
795
  if (command === '/sessions') {
708
796
  await showSessions({ bot, chatId, link });
709
797
  return true;
@@ -855,6 +943,12 @@ export async function handleTelegramControlCallback({ bot, query, link }) {
855
943
  return showWorkflowMenu({ bot, chatId, link, editMessageId });
856
944
  if (action === 'runs')
857
945
  return showRuns({ bot, chatId, link, editMessageId });
946
+ if (action === 'approvals')
947
+ return showApprovalQueue({ bot, chatId, link, editMessageId });
948
+ if (action === 'control_room')
949
+ return showControlRoom({ bot, chatId, link, editMessageId });
950
+ if (action === 'webhooks')
951
+ return showWebhookMenu({ bot, chatId, link, editMessageId });
858
952
  if (action === 'sessions')
859
953
  return showSessions({ bot, chatId, link, editMessageId });
860
954
  if (action === 'new_chat')
@@ -925,6 +1019,22 @@ export async function handleTelegramControlCallback({ bot, query, link }) {
925
1019
  await send(bot, chatId, t(languageFor(link), 'control.runStatus', { runId: run.id, status: run.status }), { editMessageId });
926
1020
  return;
927
1021
  }
1022
+ if (action === 'approval_decide') {
1023
+ const result = await localApi(link.user_id, `/api/orchestration/workflows/approvals/${encodeURIComponent(payload.approvalId)}`, {
1024
+ method: 'POST',
1025
+ body: {
1026
+ allow: payload.allow === true,
1027
+ source: 'telegram',
1028
+ },
1029
+ });
1030
+ const lang = languageFor(link);
1031
+ await send(bot, chatId, t(lang, 'control.approvalDecided', {
1032
+ approvalId: payload.approvalId,
1033
+ status: payload.allow === true ? 'approved' : 'denied',
1034
+ runId: result?.runId || '',
1035
+ }), { editMessageId });
1036
+ return showApprovalQueue({ bot, chatId, link });
1037
+ }
928
1038
  if (action === 'task_run')
929
1039
  return runTaskMasterTask({ bot, chatId, link, taskId: payload.taskId });
930
1040
  if (action === 'install_provider')