@abdasis/agentdeck 2.44.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (196) hide show
  1. package/README.md +122 -0
  2. package/agent/dist/config.d.ts +31 -0
  3. package/agent/dist/config.d.ts.map +1 -0
  4. package/agent/dist/config.js +81 -0
  5. package/agent/dist/config.js.map +1 -0
  6. package/agent/dist/db/commands.d.ts +25 -0
  7. package/agent/dist/db/commands.d.ts.map +1 -0
  8. package/agent/dist/db/commands.js +93 -0
  9. package/agent/dist/db/commands.js.map +1 -0
  10. package/agent/dist/db/index.d.ts +30 -0
  11. package/agent/dist/db/index.d.ts.map +1 -0
  12. package/agent/dist/db/index.js +368 -0
  13. package/agent/dist/db/index.js.map +1 -0
  14. package/agent/dist/db/schema.d.ts +74 -0
  15. package/agent/dist/db/schema.d.ts.map +1 -0
  16. package/agent/dist/db/schema.js +100 -0
  17. package/agent/dist/db/schema.js.map +1 -0
  18. package/agent/dist/db/sessions.d.ts +46 -0
  19. package/agent/dist/db/sessions.d.ts.map +1 -0
  20. package/agent/dist/db/sessions.js +198 -0
  21. package/agent/dist/db/sessions.js.map +1 -0
  22. package/agent/dist/index.d.ts +2 -0
  23. package/agent/dist/index.d.ts.map +1 -0
  24. package/agent/dist/index.js +19 -0
  25. package/agent/dist/index.js.map +1 -0
  26. package/agent/dist/lib/command-session.d.ts +20 -0
  27. package/agent/dist/lib/command-session.d.ts.map +1 -0
  28. package/agent/dist/lib/command-session.js +64 -0
  29. package/agent/dist/lib/command-session.js.map +1 -0
  30. package/agent/dist/lib/git.d.ts +8 -0
  31. package/agent/dist/lib/git.d.ts.map +1 -0
  32. package/agent/dist/lib/git.js +194 -0
  33. package/agent/dist/lib/git.js.map +1 -0
  34. package/agent/dist/lib/init-script.d.ts +33 -0
  35. package/agent/dist/lib/init-script.d.ts.map +1 -0
  36. package/agent/dist/lib/init-script.js +523 -0
  37. package/agent/dist/lib/init-script.js.map +1 -0
  38. package/agent/dist/lib/transcript.d.ts +16 -0
  39. package/agent/dist/lib/transcript.d.ts.map +1 -0
  40. package/agent/dist/lib/transcript.js +64 -0
  41. package/agent/dist/lib/transcript.js.map +1 -0
  42. package/agent/dist/logger.d.ts +12 -0
  43. package/agent/dist/logger.d.ts.map +1 -0
  44. package/agent/dist/logger.js +39 -0
  45. package/agent/dist/logger.js.map +1 -0
  46. package/agent/dist/middleware/auth.d.ts +15 -0
  47. package/agent/dist/middleware/auth.d.ts.map +1 -0
  48. package/agent/dist/middleware/auth.js +55 -0
  49. package/agent/dist/middleware/auth.js.map +1 -0
  50. package/agent/dist/routes/commands.d.ts +8 -0
  51. package/agent/dist/routes/commands.d.ts.map +1 -0
  52. package/agent/dist/routes/commands.js +229 -0
  53. package/agent/dist/routes/commands.js.map +1 -0
  54. package/agent/dist/routes/files.d.ts +7 -0
  55. package/agent/dist/routes/files.d.ts.map +1 -0
  56. package/agent/dist/routes/files.js +206 -0
  57. package/agent/dist/routes/files.js.map +1 -0
  58. package/agent/dist/routes/hooks.d.ts +7 -0
  59. package/agent/dist/routes/hooks.d.ts.map +1 -0
  60. package/agent/dist/routes/hooks.js +147 -0
  61. package/agent/dist/routes/hooks.js.map +1 -0
  62. package/agent/dist/routes/index.d.ts +10 -0
  63. package/agent/dist/routes/index.d.ts.map +1 -0
  64. package/agent/dist/routes/index.js +10 -0
  65. package/agent/dist/routes/index.js.map +1 -0
  66. package/agent/dist/routes/pair.d.ts +26 -0
  67. package/agent/dist/routes/pair.d.ts.map +1 -0
  68. package/agent/dist/routes/pair.js +384 -0
  69. package/agent/dist/routes/pair.js.map +1 -0
  70. package/agent/dist/routes/projects.d.ts +6 -0
  71. package/agent/dist/routes/projects.d.ts.map +1 -0
  72. package/agent/dist/routes/projects.js +121 -0
  73. package/agent/dist/routes/projects.js.map +1 -0
  74. package/agent/dist/routes/sessions-git.d.ts +7 -0
  75. package/agent/dist/routes/sessions-git.d.ts.map +1 -0
  76. package/agent/dist/routes/sessions-git.js +31 -0
  77. package/agent/dist/routes/sessions-git.js.map +1 -0
  78. package/agent/dist/routes/sessions-tmux.d.ts +7 -0
  79. package/agent/dist/routes/sessions-tmux.d.ts.map +1 -0
  80. package/agent/dist/routes/sessions-tmux.js +94 -0
  81. package/agent/dist/routes/sessions-tmux.js.map +1 -0
  82. package/agent/dist/routes/sessions.d.ts +7 -0
  83. package/agent/dist/routes/sessions.d.ts.map +1 -0
  84. package/agent/dist/routes/sessions.js +172 -0
  85. package/agent/dist/routes/sessions.js.map +1 -0
  86. package/agent/dist/server.d.ts +6 -0
  87. package/agent/dist/server.d.ts.map +1 -0
  88. package/agent/dist/server.js +95 -0
  89. package/agent/dist/server.js.map +1 -0
  90. package/agent/dist/terminal.d.ts +19 -0
  91. package/agent/dist/terminal.d.ts.map +1 -0
  92. package/agent/dist/terminal.js +175 -0
  93. package/agent/dist/terminal.js.map +1 -0
  94. package/agent/dist/updater.d.ts +18 -0
  95. package/agent/dist/updater.d.ts.map +1 -0
  96. package/agent/dist/updater.js +122 -0
  97. package/agent/dist/updater.js.map +1 -0
  98. package/agent/dist/version.d.ts +20 -0
  99. package/agent/dist/version.d.ts.map +1 -0
  100. package/agent/dist/version.js +66 -0
  101. package/agent/dist/version.js.map +1 -0
  102. package/agent/dist/websocket-handlers.d.ts +38 -0
  103. package/agent/dist/websocket-handlers.d.ts.map +1 -0
  104. package/agent/dist/websocket-handlers.js +389 -0
  105. package/agent/dist/websocket-handlers.js.map +1 -0
  106. package/agent/node_modules/@agentdeck/shared/dist/index.d.ts +2 -0
  107. package/agent/node_modules/@agentdeck/shared/dist/index.d.ts.map +1 -0
  108. package/agent/node_modules/@agentdeck/shared/dist/index.js +2 -0
  109. package/agent/node_modules/@agentdeck/shared/dist/index.js.map +1 -0
  110. package/agent/node_modules/@agentdeck/shared/dist/types/index.d.ts +235 -0
  111. package/agent/node_modules/@agentdeck/shared/dist/types/index.d.ts.map +1 -0
  112. package/agent/node_modules/@agentdeck/shared/dist/types/index.js +5 -0
  113. package/agent/node_modules/@agentdeck/shared/dist/types/index.js.map +1 -0
  114. package/agent/node_modules/@agentdeck/shared/package.json +29 -0
  115. package/dist/commands/doctor.d.ts +3 -0
  116. package/dist/commands/doctor.d.ts.map +1 -0
  117. package/dist/commands/doctor.js +304 -0
  118. package/dist/commands/doctor.js.map +1 -0
  119. package/dist/commands/hooks.d.ts +3 -0
  120. package/dist/commands/hooks.d.ts.map +1 -0
  121. package/dist/commands/hooks.js +187 -0
  122. package/dist/commands/hooks.js.map +1 -0
  123. package/dist/commands/init.d.ts +3 -0
  124. package/dist/commands/init.d.ts.map +1 -0
  125. package/dist/commands/init.js +109 -0
  126. package/dist/commands/init.js.map +1 -0
  127. package/dist/commands/logs.d.ts +3 -0
  128. package/dist/commands/logs.d.ts.map +1 -0
  129. package/dist/commands/logs.js +38 -0
  130. package/dist/commands/logs.js.map +1 -0
  131. package/dist/commands/profile.d.ts +3 -0
  132. package/dist/commands/profile.d.ts.map +1 -0
  133. package/dist/commands/profile.js +156 -0
  134. package/dist/commands/profile.js.map +1 -0
  135. package/dist/commands/service.d.ts +3 -0
  136. package/dist/commands/service.d.ts.map +1 -0
  137. package/dist/commands/service.js +235 -0
  138. package/dist/commands/service.js.map +1 -0
  139. package/dist/commands/start.d.ts +3 -0
  140. package/dist/commands/start.d.ts.map +1 -0
  141. package/dist/commands/start.js +122 -0
  142. package/dist/commands/start.js.map +1 -0
  143. package/dist/commands/status.d.ts +3 -0
  144. package/dist/commands/status.d.ts.map +1 -0
  145. package/dist/commands/status.js +48 -0
  146. package/dist/commands/status.js.map +1 -0
  147. package/dist/commands/stop.d.ts +3 -0
  148. package/dist/commands/stop.d.ts.map +1 -0
  149. package/dist/commands/stop.js +23 -0
  150. package/dist/commands/stop.js.map +1 -0
  151. package/dist/commands/update.d.ts +3 -0
  152. package/dist/commands/update.d.ts.map +1 -0
  153. package/dist/commands/update.js +129 -0
  154. package/dist/commands/update.js.map +1 -0
  155. package/dist/commands/version.d.ts +3 -0
  156. package/dist/commands/version.d.ts.map +1 -0
  157. package/dist/commands/version.js +39 -0
  158. package/dist/commands/version.js.map +1 -0
  159. package/dist/index.d.ts +5 -0
  160. package/dist/index.d.ts.map +1 -0
  161. package/dist/index.js +45 -0
  162. package/dist/index.js.map +1 -0
  163. package/dist/lib/config.d.ts +68 -0
  164. package/dist/lib/config.d.ts.map +1 -0
  165. package/dist/lib/config.js +156 -0
  166. package/dist/lib/config.js.map +1 -0
  167. package/dist/lib/hooks.d.ts +67 -0
  168. package/dist/lib/hooks.d.ts.map +1 -0
  169. package/dist/lib/hooks.js +353 -0
  170. package/dist/lib/hooks.js.map +1 -0
  171. package/dist/lib/paths.d.ts +36 -0
  172. package/dist/lib/paths.d.ts.map +1 -0
  173. package/dist/lib/paths.js +77 -0
  174. package/dist/lib/paths.js.map +1 -0
  175. package/dist/lib/prerequisites.d.ts +60 -0
  176. package/dist/lib/prerequisites.d.ts.map +1 -0
  177. package/dist/lib/prerequisites.js +266 -0
  178. package/dist/lib/prerequisites.js.map +1 -0
  179. package/dist/lib/process.d.ts +40 -0
  180. package/dist/lib/process.d.ts.map +1 -0
  181. package/dist/lib/process.js +192 -0
  182. package/dist/lib/process.js.map +1 -0
  183. package/dist/service/index.d.ts +44 -0
  184. package/dist/service/index.d.ts.map +1 -0
  185. package/dist/service/index.js +18 -0
  186. package/dist/service/index.js.map +1 -0
  187. package/dist/service/launchd.d.ts +18 -0
  188. package/dist/service/launchd.d.ts.map +1 -0
  189. package/dist/service/launchd.js +208 -0
  190. package/dist/service/launchd.js.map +1 -0
  191. package/dist/service/systemd.d.ts +18 -0
  192. package/dist/service/systemd.d.ts.map +1 -0
  193. package/dist/service/systemd.js +196 -0
  194. package/dist/service/systemd.js.map +1 -0
  195. package/hooks/notify-agentdeck.sh +53 -0
  196. package/package.json +83 -0
@@ -0,0 +1,147 @@
1
+ /**
2
+ * Hook API routes for Claude Code / Codex hook notifications.
3
+ * Receives status updates from hook scripts and broadcasts to WebSocket subscribers.
4
+ */
5
+ import { Router } from 'express';
6
+ import * as sessionsDb from '../db/sessions.js';
7
+ import { broadcastStatusUpdate } from '../websocket-handlers.js';
8
+ import { loadConfig } from '../config.js';
9
+ import { parseTranscriptUsage } from '../lib/transcript.js';
10
+ const AGENTDECK_URL = process.env.AGENTDECK_URL || 'https://agentdeck.dev';
11
+ const WEB_PUSH_URL = `${AGENTDECK_URL}/api/push/notify`;
12
+ /**
13
+ * Send push notification to web API
14
+ */
15
+ async function sendPushNotification(sessionName) {
16
+ try {
17
+ const config = loadConfig();
18
+ const machineId = config.machine.id;
19
+ if (!machineId) {
20
+ console.log('[Hooks] No machineId configured, skipping push');
21
+ return;
22
+ }
23
+ const response = await fetch(WEB_PUSH_URL, {
24
+ method: 'POST',
25
+ headers: { 'Content-Type': 'application/json' },
26
+ body: JSON.stringify({ machineId, sessionName }),
27
+ });
28
+ if (!response.ok) {
29
+ const error = await response.text();
30
+ console.error(`[Hooks] Push notification failed: ${response.status} ${error}`);
31
+ return;
32
+ }
33
+ const result = await response.json();
34
+ console.log(`[Hooks] Push notification: ${result.sent} sent`);
35
+ }
36
+ catch (_err) {
37
+ // Don't log full error to avoid noise - push is best effort
38
+ console.log('[Hooks] Push notification skipped (web unreachable)');
39
+ }
40
+ }
41
+ /**
42
+ * Validate that a value is a valid SessionStatus
43
+ */
44
+ function isValidStatus(value) {
45
+ return value === 'init' || value === 'working' || value === 'needs_attention' || value === 'idle';
46
+ }
47
+ /**
48
+ * Validate that a value is a valid AttentionReason (now accepts any string for pass-through)
49
+ */
50
+ function isValidAttentionReason(value) {
51
+ // Accept any string, null, or undefined (pass-through from Claude Code notification_type)
52
+ return typeof value === 'string' || value === null || value === undefined;
53
+ }
54
+ /**
55
+ * Validate that a value is a valid StatusSource
56
+ */
57
+ function isValidStatusSource(value) {
58
+ return value === 'hook' || value === 'tmux';
59
+ }
60
+ export function createHooksRoutes() {
61
+ const router = Router();
62
+ /**
63
+ * POST /api/hooks/status
64
+ * Receives status updates from Claude Code / Codex hooks (notify-agentdeck.sh)
65
+ *
66
+ * Body: AttentionNotification
67
+ * - sessionId: string (tmux session name, e.g., "project--abc123")
68
+ * - status: SessionStatus
69
+ * - attentionReason?: AttentionReason
70
+ * - source: StatusSource
71
+ * - timestamp: number
72
+ * - eventType: string
73
+ */
74
+ router.post('/status', async (req, res) => {
75
+ try {
76
+ const notification = req.body;
77
+ // Validate required fields
78
+ if (!notification.sessionId || typeof notification.sessionId !== 'string') {
79
+ return res.status(400).json({ error: 'sessionId is required' });
80
+ }
81
+ if (!isValidStatus(notification.status)) {
82
+ return res.status(400).json({ error: 'Invalid status value' });
83
+ }
84
+ if (!isValidAttentionReason(notification.attentionReason)) {
85
+ return res.status(400).json({ error: 'Invalid attentionReason value' });
86
+ }
87
+ if (!isValidStatusSource(notification.source)) {
88
+ return res.status(400).json({ error: 'Invalid source value' });
89
+ }
90
+ const sessionName = notification.sessionId;
91
+ const now = Date.now();
92
+ console.log(`[Hooks] Received status update: session=${sessionName} status=${notification.status} reason=${notification.attentionReason} event=${notification.eventType}`);
93
+ // Parse transcript sekali untuk token usage + model + cost (jika ada).
94
+ const parsed = notification.transcriptPath
95
+ ? await parseTranscriptUsage(notification.transcriptPath)
96
+ : null;
97
+ if (parsed) {
98
+ console.log(`[Hooks] Transcript parsed: in=${parsed.usage.inputTokens} out=${parsed.usage.outputTokens} cache_read=${parsed.usage.cacheReadTokens} cache_create=${parsed.usage.cacheCreationTokens} model=${parsed.model ?? '-'}`);
99
+ }
100
+ const upsertInput = {
101
+ status: notification.status,
102
+ statusSource: notification.source,
103
+ attentionReason: notification.attentionReason,
104
+ lastEvent: notification.eventType,
105
+ lastActivity: now,
106
+ usage: parsed?.usage,
107
+ model: parsed?.model,
108
+ costUsd: parsed?.costUsd,
109
+ };
110
+ // Check if session exists in DB
111
+ let session = sessionsDb.getSession(sessionName);
112
+ if (!session) {
113
+ // Session doesn't exist in DB yet - create it
114
+ // Extract project from session name (format: project--timestamp)
115
+ const [project] = sessionName.split('--');
116
+ session = sessionsDb.upsertSession(sessionName, {
117
+ project,
118
+ ...upsertInput,
119
+ });
120
+ console.log(`[Hooks] Created new session from hook: ${sessionName}`);
121
+ }
122
+ else {
123
+ // Update existing session
124
+ session = sessionsDb.upsertSession(sessionName, upsertInput);
125
+ }
126
+ // Broadcast status update to WebSocket subscribers
127
+ broadcastStatusUpdate(sessionsDb.dbSessionToInfo(session.name, session.project, session.created_at, session));
128
+ // Send push notification if needs_attention
129
+ if (notification.status === 'needs_attention') {
130
+ // Fire and forget - don't block the response
131
+ sendPushNotification(sessionName).catch(() => { });
132
+ }
133
+ res.json({
134
+ success: true,
135
+ sessionName,
136
+ status: notification.status,
137
+ attentionReason: notification.attentionReason,
138
+ });
139
+ }
140
+ catch (err) {
141
+ console.error('[Hooks] Error processing status update:', err);
142
+ res.status(500).json({ error: 'Internal server error' });
143
+ }
144
+ });
145
+ return router;
146
+ }
147
+ //# sourceMappingURL=hooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../src/routes/hooks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Route aggregation - exports all route creators.
3
+ */
4
+ export { createProjectRoutes } from './projects.js';
5
+ export { createSessionRoutes } from './sessions.js';
6
+ export { createPairRoutes, verifyToken } from './pair.js';
7
+ export { createHooksRoutes } from './hooks.js';
8
+ export { createCommandRoutes } from './commands.js';
9
+ export { createFileRoutes } from './files.js';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/routes/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Route aggregation - exports all route creators.
3
+ */
4
+ export { createProjectRoutes } from './projects.js';
5
+ export { createSessionRoutes } from './sessions.js';
6
+ export { createPairRoutes, verifyToken } from './pair.js';
7
+ export { createHooksRoutes } from './hooks.js';
8
+ export { createCommandRoutes } from './commands.js';
9
+ export { createFileRoutes } from './files.js';
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/routes/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Pairing routes: Allow users to pair their agent with the dashboard.
3
+ * Provides a web page with pairing link, QR code, and 6-digit fallback code.
4
+ */
5
+ import { Router } from 'express';
6
+ interface PairingCode {
7
+ code: string;
8
+ machineId: string;
9
+ machineName: string;
10
+ agentUrl: string;
11
+ createdAt: number;
12
+ expiresAt: number;
13
+ }
14
+ declare const pairingCodes: Map<string, PairingCode>;
15
+ declare function generateCode(): string;
16
+ declare function createToken(payload: object, secret: string, expiresInMs: number): string;
17
+ export declare function verifyToken(token: string, secret: string): {
18
+ valid: boolean;
19
+ payload?: Record<string, unknown>;
20
+ error?: string;
21
+ };
22
+ declare function getAgentUrl(): string;
23
+ declare function getDashboardUrl(): string;
24
+ export declare function createPairRoutes(): Router;
25
+ export { pairingCodes, generateCode, createToken, getAgentUrl, getDashboardUrl };
26
+ //# sourceMappingURL=pair.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pair.d.ts","sourceRoot":"","sources":["../../src/routes/pair.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAKjC,UAAU,WAAW;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,QAAA,MAAM,YAAY,0BAAiC,CAAC;AAapD,iBAAS,YAAY,IAAI,MAAM,CAO9B;AAGD,iBAAS,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAMjF;AAGD,wBAAgB,WAAW,CACzB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,GACb;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAsBvE;AAGD,iBAAS,WAAW,IAAI,MAAM,CAM7B;AAGD,iBAAS,eAAe,IAAI,MAAM,CAOjC;AAWD,wBAAgB,gBAAgB,IAAI,MAAM,CA6UzC;AAGD,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,eAAe,EAAE,CAAC"}
@@ -0,0 +1,384 @@
1
+ /**
2
+ * Pairing routes: Allow users to pair their agent with the dashboard.
3
+ * Provides a web page with pairing link, QR code, and 6-digit fallback code.
4
+ */
5
+ import { Router } from 'express';
6
+ import { createHmac } from 'crypto';
7
+ import { config, getAccessToken } from '../config.js';
8
+ const pairingCodes = new Map();
9
+ // Clean up expired codes every minute
10
+ setInterval(() => {
11
+ const now = Date.now();
12
+ for (const [code, data] of pairingCodes.entries()) {
13
+ if (data.expiresAt < now) {
14
+ pairingCodes.delete(code);
15
+ }
16
+ }
17
+ }, 60 * 1000);
18
+ // Generate a 6-digit code
19
+ function generateCode() {
20
+ const code = Math.floor(100000 + Math.random() * 900000).toString();
21
+ // Ensure uniqueness
22
+ if (pairingCodes.has(code)) {
23
+ return generateCode();
24
+ }
25
+ return code;
26
+ }
27
+ // Create a signed token
28
+ function createToken(payload, secret, expiresInMs) {
29
+ const exp = Date.now() + expiresInMs;
30
+ const data = { ...payload, iat: Date.now(), exp };
31
+ const payloadStr = Buffer.from(JSON.stringify(data)).toString('base64url');
32
+ const signature = createHmac('sha256', secret).update(payloadStr).digest('base64url');
33
+ return `${payloadStr}.${signature}`;
34
+ }
35
+ // Verify and decode a token
36
+ export function verifyToken(token, secret) {
37
+ try {
38
+ const [payloadStr, signature] = token.split('.');
39
+ if (!payloadStr || !signature) {
40
+ return { valid: false, error: 'Invalid token format' };
41
+ }
42
+ const expectedSignature = createHmac('sha256', secret).update(payloadStr).digest('base64url');
43
+ if (signature !== expectedSignature) {
44
+ return { valid: false, error: 'Invalid signature' };
45
+ }
46
+ const payload = JSON.parse(Buffer.from(payloadStr, 'base64url').toString());
47
+ if (payload.exp && payload.exp < Date.now()) {
48
+ return { valid: false, error: 'Token expired' };
49
+ }
50
+ return { valid: true, payload };
51
+ }
52
+ catch {
53
+ return { valid: false, error: 'Failed to parse token' };
54
+ }
55
+ }
56
+ // Get agent URL - prefer config, fallback to localhost
57
+ function getAgentUrl() {
58
+ if (config.agent?.url) {
59
+ return config.agent.url;
60
+ }
61
+ const port = config.agent?.port || 4678;
62
+ return `localhost:${port}`;
63
+ }
64
+ // Get dashboard URL
65
+ function getDashboardUrl() {
66
+ // Use config if available, otherwise default to production
67
+ if (config.dashboard?.apiUrl) {
68
+ // Extract base URL from API URL (remove /api suffix)
69
+ return config.dashboard.apiUrl.replace(/\/api\/?$/, '');
70
+ }
71
+ return process.env.AGENTDECK_URL || 'https://agentdeck.dev';
72
+ }
73
+ // Generate QR code as SVG using a simple implementation
74
+ function generateQRCodeSVG(data) {
75
+ // Use a simple QR code approach - encode the URL in a data URI
76
+ // For production, you'd use a proper QR library like 'qrcode'
77
+ // Here we'll use Google Charts API as a simple fallback
78
+ const encoded = encodeURIComponent(data);
79
+ return `<img src="https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${encoded}" alt="QR Code" width="200" height="200" style="image-rendering: pixelated;" />`;
80
+ }
81
+ export function createPairRoutes() {
82
+ const router = Router();
83
+ // GET /pair - HTML page with pairing info
84
+ router.get('/', (_req, res) => {
85
+ const machineId = config.machine.id;
86
+ const machineName = config.machine.name;
87
+ const agentUrl = getAgentUrl();
88
+ const dashboardUrl = getDashboardUrl();
89
+ // Create token (10 minute expiry)
90
+ const token = createToken({
91
+ mid: machineId,
92
+ mn: machineName,
93
+ url: agentUrl,
94
+ atk: getAccessToken(),
95
+ }, machineId, 10 * 60 * 1000);
96
+ // Generate or reuse existing code for this machine
97
+ let existingCode;
98
+ for (const [code, data] of pairingCodes.entries()) {
99
+ if (data.machineId === machineId && data.expiresAt > Date.now()) {
100
+ existingCode = code;
101
+ break;
102
+ }
103
+ }
104
+ const code = existingCode ||
105
+ (() => {
106
+ const newCode = generateCode();
107
+ pairingCodes.set(newCode, {
108
+ code: newCode,
109
+ machineId,
110
+ machineName,
111
+ agentUrl,
112
+ createdAt: Date.now(),
113
+ expiresAt: Date.now() + 10 * 60 * 1000,
114
+ });
115
+ return newCode;
116
+ })();
117
+ const pairingLink = `${dashboardUrl}/connect?token=${encodeURIComponent(token)}`;
118
+ const qrCodeSvg = generateQRCodeSVG(pairingLink);
119
+ // Calculate time remaining
120
+ const codeData = pairingCodes.get(code);
121
+ const secondsRemaining = Math.floor((codeData.expiresAt - Date.now()) / 1000);
122
+ const html = `<!DOCTYPE html>
123
+ <html lang="en">
124
+ <head>
125
+ <meta charset="UTF-8">
126
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
127
+ <title>Pair Agent - ${machineName}</title>
128
+ <style>
129
+ * { box-sizing: border-box; margin: 0; padding: 0; }
130
+ body {
131
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
132
+ background: linear-gradient(135deg, #0a0a10 0%, #1a1a2e 100%);
133
+ min-height: 100vh;
134
+ display: flex;
135
+ align-items: center;
136
+ justify-content: center;
137
+ padding: 20px;
138
+ color: #fff;
139
+ }
140
+ .container {
141
+ background: rgba(255, 255, 255, 0.03);
142
+ border: 1px solid rgba(255, 255, 255, 0.1);
143
+ border-radius: 24px;
144
+ padding: 40px;
145
+ max-width: 480px;
146
+ width: 100%;
147
+ text-align: center;
148
+ }
149
+ .machine-icon {
150
+ width: 80px;
151
+ height: 80px;
152
+ background: linear-gradient(135deg, #f97316 0%, #f59e0b 100%);
153
+ border-radius: 20px;
154
+ display: flex;
155
+ align-items: center;
156
+ justify-content: center;
157
+ margin: 0 auto 24px;
158
+ font-size: 40px;
159
+ }
160
+ h1 {
161
+ font-size: 24px;
162
+ font-weight: 600;
163
+ margin-bottom: 8px;
164
+ }
165
+ .machine-name {
166
+ color: #f97316;
167
+ font-size: 20px;
168
+ font-weight: 500;
169
+ margin-bottom: 32px;
170
+ }
171
+ .qr-section {
172
+ background: #fff;
173
+ border-radius: 16px;
174
+ padding: 20px;
175
+ margin-bottom: 24px;
176
+ display: inline-block;
177
+ }
178
+ .qr-section img {
179
+ display: block;
180
+ }
181
+ .link-section {
182
+ margin-bottom: 24px;
183
+ }
184
+ .pair-button {
185
+ display: inline-block;
186
+ background: linear-gradient(135deg, #f97316 0%, #f59e0b 100%);
187
+ color: #fff;
188
+ text-decoration: none;
189
+ padding: 16px 32px;
190
+ border-radius: 12px;
191
+ font-weight: 600;
192
+ font-size: 16px;
193
+ transition: transform 0.2s, box-shadow 0.2s;
194
+ }
195
+ .pair-button:hover {
196
+ transform: translateY(-2px);
197
+ box-shadow: 0 8px 24px rgba(249, 115, 22, 0.3);
198
+ }
199
+ .divider {
200
+ display: flex;
201
+ align-items: center;
202
+ margin: 24px 0;
203
+ color: rgba(255, 255, 255, 0.4);
204
+ font-size: 14px;
205
+ }
206
+ .divider::before, .divider::after {
207
+ content: '';
208
+ flex: 1;
209
+ height: 1px;
210
+ background: rgba(255, 255, 255, 0.1);
211
+ }
212
+ .divider span {
213
+ padding: 0 16px;
214
+ }
215
+ .code-section {
216
+ background: rgba(255, 255, 255, 0.05);
217
+ border: 1px solid rgba(255, 255, 255, 0.1);
218
+ border-radius: 12px;
219
+ padding: 20px;
220
+ }
221
+ .code-label {
222
+ font-size: 14px;
223
+ color: rgba(255, 255, 255, 0.6);
224
+ margin-bottom: 12px;
225
+ }
226
+ .code {
227
+ font-family: 'SF Mono', Monaco, monospace;
228
+ font-size: 36px;
229
+ font-weight: 700;
230
+ letter-spacing: 8px;
231
+ color: #f97316;
232
+ }
233
+ .expires {
234
+ font-size: 12px;
235
+ color: rgba(255, 255, 255, 0.4);
236
+ margin-top: 12px;
237
+ }
238
+ .refresh-note {
239
+ font-size: 12px;
240
+ color: rgba(255, 255, 255, 0.3);
241
+ margin-top: 24px;
242
+ }
243
+ .agent-info {
244
+ font-size: 12px;
245
+ color: rgba(255, 255, 255, 0.4);
246
+ margin-top: 16px;
247
+ padding-top: 16px;
248
+ border-top: 1px solid rgba(255, 255, 255, 0.1);
249
+ }
250
+ </style>
251
+ </head>
252
+ <body>
253
+ <div class="container">
254
+ <div class="machine-icon">💻</div>
255
+ <h1>Pair Your Agent</h1>
256
+ <p class="machine-name">${machineName}</p>
257
+
258
+ <div class="qr-section">
259
+ ${qrCodeSvg}
260
+ </div>
261
+
262
+ <div class="link-section">
263
+ <a href="${pairingLink}" class="pair-button" target="_blank">Open Dashboard to Pair</a>
264
+ </div>
265
+
266
+ <div class="divider"><span>or enter this code</span></div>
267
+
268
+ <div class="code-section">
269
+ <p class="code-label">Pairing Code</p>
270
+ <p class="code">${code}</p>
271
+ <p class="expires">Expires in <span id="countdown">${Math.floor(secondsRemaining / 60)}:${String(secondsRemaining % 60).padStart(2, '0')}</span></p>
272
+ </div>
273
+
274
+ <p class="refresh-note">Page will auto-refresh when code expires</p>
275
+
276
+ <p class="agent-info">
277
+ Agent URL: ${agentUrl}<br>
278
+ Machine ID: ${machineId}
279
+ </p>
280
+ </div>
281
+
282
+ <script>
283
+ let remaining = ${secondsRemaining};
284
+ const countdown = document.getElementById('countdown');
285
+
286
+ setInterval(() => {
287
+ remaining--;
288
+ if (remaining <= 0) {
289
+ location.reload();
290
+ return;
291
+ }
292
+ const mins = Math.floor(remaining / 60);
293
+ const secs = remaining % 60;
294
+ countdown.textContent = mins + ':' + String(secs).padStart(2, '0');
295
+ }, 1000);
296
+ </script>
297
+ </body>
298
+ </html>`;
299
+ res.setHeader('Content-Type', 'text/html');
300
+ res.send(html);
301
+ });
302
+ // GET /pair/info - JSON API for pairing info
303
+ router.get('/info', (_req, res) => {
304
+ const machineId = config.machine.id;
305
+ const machineName = config.machine.name;
306
+ const agentUrl = getAgentUrl();
307
+ const dashboardUrl = getDashboardUrl();
308
+ // Create token (10 minute expiry)
309
+ const token = createToken({
310
+ mid: machineId,
311
+ mn: machineName,
312
+ url: agentUrl,
313
+ atk: getAccessToken(),
314
+ }, machineId, 10 * 60 * 1000);
315
+ // Generate or reuse existing code
316
+ let existingCode;
317
+ for (const [code, data] of pairingCodes.entries()) {
318
+ if (data.machineId === machineId && data.expiresAt > Date.now()) {
319
+ existingCode = code;
320
+ break;
321
+ }
322
+ }
323
+ const code = existingCode ||
324
+ (() => {
325
+ const newCode = generateCode();
326
+ pairingCodes.set(newCode, {
327
+ code: newCode,
328
+ machineId,
329
+ machineName,
330
+ agentUrl,
331
+ createdAt: Date.now(),
332
+ expiresAt: Date.now() + 10 * 60 * 1000,
333
+ });
334
+ return newCode;
335
+ })();
336
+ const codeData = pairingCodes.get(code);
337
+ res.json({
338
+ machineId,
339
+ machineName,
340
+ agentUrl,
341
+ token,
342
+ code,
343
+ pairingLink: `${dashboardUrl}/connect?token=${encodeURIComponent(token)}`,
344
+ expiresAt: codeData.expiresAt,
345
+ });
346
+ });
347
+ // GET /pair/code/:code - Lookup a pairing code (for dashboard to verify)
348
+ router.get('/code/:code', (req, res) => {
349
+ const { code } = req.params;
350
+ const data = pairingCodes.get(code);
351
+ if (!data || data.expiresAt < Date.now()) {
352
+ return res.status(404).json({ error: 'Code not found or expired' });
353
+ }
354
+ res.json({
355
+ machineId: data.machineId,
356
+ machineName: data.machineName,
357
+ agentUrl: data.agentUrl,
358
+ expiresAt: data.expiresAt,
359
+ });
360
+ });
361
+ // POST /pair/verify - Verify a token (for dashboard to validate)
362
+ router.post('/verify', (req, res) => {
363
+ const { token } = req.body;
364
+ if (!token || typeof token !== 'string') {
365
+ return res.status(400).json({ error: 'Token is required' });
366
+ }
367
+ const machineId = config.machine.id;
368
+ const result = verifyToken(token, machineId);
369
+ if (!result.valid) {
370
+ return res.status(401).json({ error: result.error });
371
+ }
372
+ res.json({
373
+ valid: true,
374
+ machineId: result.payload?.mid,
375
+ machineName: result.payload?.mn,
376
+ agentUrl: result.payload?.url,
377
+ accessToken: result.payload?.atk,
378
+ });
379
+ });
380
+ return router;
381
+ }
382
+ // Export for testing
383
+ export { pairingCodes, generateCode, createToken, getAgentUrl, getDashboardUrl };
384
+ //# sourceMappingURL=pair.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pair.js","sourceRoot":"","sources":["../../src/routes/pair.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Project-related API routes: listing, folder scanning, and git clone.
3
+ */
4
+ import { Router } from 'express';
5
+ export declare function createProjectRoutes(): Router;
6
+ //# sourceMappingURL=projects.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projects.d.ts","sourceRoot":"","sources":["../../src/routes/projects.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAKjC,wBAAgB,mBAAmB,IAAI,MAAM,CA4H5C"}