@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,121 @@
1
+ /**
2
+ * Project-related API routes: listing, folder scanning, and git clone.
3
+ */
4
+ import { Router } from 'express';
5
+ import { spawn } from 'child_process';
6
+ import { config } from '../config.js';
7
+ import { authMiddleware } from '../middleware/auth.js';
8
+ export function createProjectRoutes() {
9
+ const router = Router();
10
+ // List whitelisted projects
11
+ router.get('/projects', authMiddleware, (_req, res) => {
12
+ res.json(config.projects.whitelist);
13
+ });
14
+ // Dynamic folder listing - scans basePath for directories
15
+ router.get('/folders', authMiddleware, async (_req, res) => {
16
+ try {
17
+ const fs = await import('fs/promises');
18
+ const basePath = config.projects.basePath.replace('~', process.env.HOME);
19
+ const entries = await fs.readdir(basePath, { withFileTypes: true });
20
+ const folders = entries
21
+ .filter((entry) => entry.isDirectory() && !entry.name.startsWith('.'))
22
+ .map((entry) => entry.name)
23
+ .sort();
24
+ res.json(folders);
25
+ }
26
+ catch (err) {
27
+ console.error('Failed to list folders:', err);
28
+ res.status(500).json({ error: 'Failed to list folders' });
29
+ }
30
+ });
31
+ // Clone a git repository
32
+ router.post('/clone', authMiddleware, async (req, res) => {
33
+ const { url } = req.body;
34
+ if (!url) {
35
+ return res.status(400).json({ success: false, error: 'URL is required' });
36
+ }
37
+ // Validate URL format (https:// or git@)
38
+ const httpsPattern = /^https:\/\/.+\/.+/;
39
+ const sshPattern = /^git@.+:.+/;
40
+ if (!httpsPattern.test(url) && !sshPattern.test(url)) {
41
+ return res.status(400).json({ success: false, error: 'Invalid URL format' });
42
+ }
43
+ // Extract repo name from URL
44
+ let repoName;
45
+ try {
46
+ if (url.startsWith('git@')) {
47
+ // git@github.com:user/repo.git -> repo
48
+ const match = url.match(/:([^/]+\/)?(.+?)(\.git)?$/);
49
+ repoName = match?.[2] || '';
50
+ }
51
+ else {
52
+ // https://github.com/user/repo.git -> repo
53
+ const urlObj = new URL(url);
54
+ const pathParts = urlObj.pathname.split('/').filter(Boolean);
55
+ repoName = pathParts[pathParts.length - 1]?.replace(/\.git$/, '') || '';
56
+ }
57
+ if (!repoName) {
58
+ return res
59
+ .status(400)
60
+ .json({ success: false, error: 'Could not extract repo name from URL' });
61
+ }
62
+ }
63
+ catch (_err) {
64
+ return res.status(400).json({ success: false, error: 'Invalid URL format' });
65
+ }
66
+ const fs = await import('fs/promises');
67
+ const path = await import('path');
68
+ const basePath = config.projects.basePath.replace('~', process.env.HOME);
69
+ const targetPath = path.join(basePath, repoName);
70
+ // Check if folder already exists
71
+ try {
72
+ await fs.access(targetPath);
73
+ return res.status(400).json({
74
+ success: false,
75
+ error: `Folder "${repoName}" already exists`,
76
+ });
77
+ }
78
+ catch (_err) {
79
+ // Folder doesn't exist, good to proceed
80
+ }
81
+ // Clone the repository
82
+ return new Promise((resolve) => {
83
+ const gitProcess = spawn('git', ['clone', url, repoName], {
84
+ cwd: basePath,
85
+ env: process.env,
86
+ });
87
+ let stderr = '';
88
+ gitProcess.stderr.on('data', (data) => {
89
+ stderr += data.toString();
90
+ });
91
+ gitProcess.on('close', (code) => {
92
+ if (code === 0) {
93
+ console.log(`Successfully cloned ${url} to ${targetPath}`);
94
+ res.json({
95
+ success: true,
96
+ project: repoName,
97
+ path: targetPath,
98
+ });
99
+ }
100
+ else {
101
+ console.error(`Git clone failed: ${stderr}`);
102
+ res.status(500).json({
103
+ success: false,
104
+ error: stderr.trim() || 'Git clone failed',
105
+ });
106
+ }
107
+ resolve();
108
+ });
109
+ gitProcess.on('error', (err) => {
110
+ console.error('Failed to spawn git:', err);
111
+ res.status(500).json({
112
+ success: false,
113
+ error: 'Failed to execute git command',
114
+ });
115
+ resolve();
116
+ });
117
+ });
118
+ });
119
+ return router;
120
+ }
121
+ //# sourceMappingURL=projects.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projects.js","sourceRoot":"","sources":["../../src/routes/projects.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,MAAM,UAAU,mBAAmB;IACjC,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC;IAExB,4BAA4B;IAC5B,MAAM,CAAC,GAAG,CAAC,WAAW,EAAE,cAAc,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;QACpD,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,0DAA0D;IAC1D,MAAM,CAAC,GAAG,CAAC,UAAU,EAAE,cAAc,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE;QACzD,IAAI,CAAC;YACH,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC;YACvC,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,IAAK,CAAC,CAAC;YAE1E,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;YACpE,MAAM,OAAO,GAAG,OAAO;iBACpB,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;iBACrE,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC;iBAC1B,IAAI,EAAE,CAAC;YAEV,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACpB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,yBAAyB,EAAE,GAAG,CAAC,CAAC;YAC9C,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,wBAAwB,EAAE,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,yBAAyB;IACzB,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,cAAc,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;QACvD,MAAM,EAAE,GAAG,EAAE,GAAG,GAAG,CAAC,IAAwB,CAAC;QAE7C,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAC,CAAC;QAC5E,CAAC;QAED,yCAAyC;QACzC,MAAM,YAAY,GAAG,mBAAmB,CAAC;QACzC,MAAM,UAAU,GAAG,YAAY,CAAC;QAChC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACrD,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,oBAAoB,EAAE,CAAC,CAAC;QAC/E,CAAC;QAED,6BAA6B;QAC7B,IAAI,QAAgB,CAAC;QACrB,IAAI,CAAC;YACH,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC3B,uCAAuC;gBACvC,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;gBACrD,QAAQ,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YAC9B,CAAC;iBAAM,CAAC;gBACN,2CAA2C;gBAC3C,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;gBAC5B,MAAM,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;gBAC7D,QAAQ,GAAG,SAAS,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC;YAC1E,CAAC;YAED,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,OAAO,GAAG;qBACP,MAAM,CAAC,GAAG,CAAC;qBACX,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,sCAAsC,EAAE,CAAC,CAAC;YAC7E,CAAC;QACH,CAAC;QAAC,OAAO,IAAI,EAAE,CAAC;YACd,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,oBAAoB,EAAE,CAAC,CAAC;QAC/E,CAAC;QAED,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC;QACvC,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC;QAClC,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,IAAK,CAAC,CAAC;QAC1E,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAEjD,iCAAiC;QACjC,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YAC5B,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;gBAC1B,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,WAAW,QAAQ,kBAAkB;aAC7C,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,IAAI,EAAE,CAAC;YACd,wCAAwC;QAC1C,CAAC;QAED,uBAAuB;QACvB,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;YACnC,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,QAAQ,CAAC,EAAE;gBACxD,GAAG,EAAE,QAAQ;gBACb,GAAG,EAAE,OAAO,CAAC,GAAG;aACjB,CAAC,CAAC;YAEH,IAAI,MAAM,GAAG,EAAE,CAAC;YAEhB,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;gBACpC,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC5B,CAAC,CAAC,CAAC;YAEH,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;gBAC9B,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;oBACf,OAAO,CAAC,GAAG,CAAC,uBAAuB,GAAG,OAAO,UAAU,EAAE,CAAC,CAAC;oBAC3D,GAAG,CAAC,IAAI,CAAC;wBACP,OAAO,EAAE,IAAI;wBACb,OAAO,EAAE,QAAQ;wBACjB,IAAI,EAAE,UAAU;qBACjB,CAAC,CAAC;gBACL,CAAC;qBAAM,CAAC;oBACN,OAAO,CAAC,KAAK,CAAC,qBAAqB,MAAM,EAAE,CAAC,CAAC;oBAC7C,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;wBACnB,OAAO,EAAE,KAAK;wBACd,KAAK,EAAE,MAAM,CAAC,IAAI,EAAE,IAAI,kBAAkB;qBAC3C,CAAC,CAAC;gBACL,CAAC;gBACD,OAAO,EAAE,CAAC;YACZ,CAAC,CAAC,CAAC;YAEH,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;gBAC7B,OAAO,CAAC,KAAK,CAAC,sBAAsB,EAAE,GAAG,CAAC,CAAC;gBAC3C,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;oBACnB,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE,+BAA+B;iBACvC,CAAC,CAAC;gBACH,OAAO,EAAE,CAAC;YACZ,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Git history route for a session's project.
3
+ * Dipasang sebagai sub-router dari sessions.ts di /api/sessions.
4
+ */
5
+ import { Router } from 'express';
6
+ export declare function createSessionGitRoutes(): Router;
7
+ //# sourceMappingURL=sessions-git.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessions-git.d.ts","sourceRoot":"","sources":["../../src/routes/sessions-git.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAIjC,wBAAgB,sBAAsB,IAAI,MAAM,CAsB/C"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Git history route for a session's project.
3
+ * Dipasang sebagai sub-router dari sessions.ts di /api/sessions.
4
+ */
5
+ import path from 'node:path';
6
+ import { Router } from 'express';
7
+ import { config } from '../config.js';
8
+ import { readGitHistory } from '../lib/git.js';
9
+ export function createSessionGitRoutes() {
10
+ const router = Router();
11
+ // Git history for a session's project (polled by web right-sidebar)
12
+ router.get('/:sessionName/git', async (req, res) => {
13
+ const { sessionName } = req.params;
14
+ if (!/^[\w-]+$/.test(sessionName)) {
15
+ return res.status(400).json({ error: 'Invalid session name' });
16
+ }
17
+ const project = sessionName.split('--')[0];
18
+ const basePath = config.projects.basePath.replace('~', process.env.HOME);
19
+ const cwd = project === '' ? basePath : path.join(basePath, project);
20
+ try {
21
+ const data = await readGitHistory(cwd);
22
+ res.json(data);
23
+ }
24
+ catch {
25
+ // Non-repo / missing path is a normal state, not a server error
26
+ res.json({ repo: false, commits: [], changes: [], fetchedAt: Date.now() });
27
+ }
28
+ });
29
+ return router;
30
+ }
31
+ //# sourceMappingURL=sessions-git.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessions-git.js","sourceRoot":"","sources":["../../src/routes/sessions-git.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C,MAAM,UAAU,sBAAsB;IACpC,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC;IAExB,oEAAoE;IACpE,MAAM,CAAC,GAAG,CAAC,mBAAmB,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;QACjD,MAAM,EAAE,WAAW,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC;QACnC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;YAClC,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,sBAAsB,EAAE,CAAC,CAAC;QACjE,CAAC;QACD,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3C,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,IAAK,CAAC,CAAC;QAC1E,MAAM,GAAG,GAAG,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACrE,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,cAAc,CAAC,GAAG,CAAC,CAAC;YACvC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjB,CAAC;QAAC,MAAM,CAAC;YACP,gEAAgE;YAChE,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QAC7E,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Tmux-direct session routes: terminal scrollback capture and input injection.
3
+ * Dipasang sebagai sub-router dari sessions.ts di /api/sessions.
4
+ */
5
+ import { Router } from 'express';
6
+ export declare function createSessionTmuxRoutes(): Router;
7
+ //# sourceMappingURL=sessions-tmux.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessions-tmux.d.ts","sourceRoot":"","sources":["../../src/routes/sessions-tmux.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAGjC,wBAAgB,uBAAuB,IAAI,MAAM,CAyGhD"}
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Tmux-direct session routes: terminal scrollback capture and input injection.
3
+ * Dipasang sebagai sub-router dari sessions.ts di /api/sessions.
4
+ */
5
+ import { Router } from 'express';
6
+ import * as sessionsDb from '../db/sessions.js';
7
+ export function createSessionTmuxRoutes() {
8
+ const router = Router();
9
+ // Get session output (terminal scrollback)
10
+ router.get('/:sessionName/output', async (req, res) => {
11
+ const { sessionName } = req.params;
12
+ const lines = parseInt(req.query.lines) || 1000;
13
+ const format = req.query.format || 'plain';
14
+ const { exec } = await import('child_process');
15
+ const { promisify } = await import('util');
16
+ const execAsync = promisify(exec);
17
+ if (!/^[\w-]+$/.test(sessionName)) {
18
+ return res.status(400).json({ error: 'Invalid session name' });
19
+ }
20
+ // Limit lines to prevent memory issues
21
+ const maxLines = Math.min(lines, 50000);
22
+ try {
23
+ const { stdout } = await execAsync(`tmux capture-pane -t "${sessionName}" -p -S -${maxLines} -J 2>/dev/null`);
24
+ let output = stdout;
25
+ // Strip ANSI codes if plain format requested
26
+ if (format === 'plain') {
27
+ // eslint-disable-next-line no-control-regex
28
+ output = output.replace(/\x1B\[[0-9;]*[a-zA-Z]/g, '');
29
+ }
30
+ const outputLines = output.split('\n');
31
+ // Check if session is still running
32
+ let isRunning = true;
33
+ try {
34
+ await execAsync(`tmux has-session -t "${sessionName}" 2>/dev/null`);
35
+ }
36
+ catch {
37
+ isRunning = false;
38
+ }
39
+ res.json({
40
+ sessionName,
41
+ output,
42
+ totalLines: outputLines.length,
43
+ returnedLines: outputLines.length,
44
+ isRunning,
45
+ capturedAt: Date.now(),
46
+ source: 'live',
47
+ });
48
+ }
49
+ catch {
50
+ res.status(404).json({ error: 'Session not found' });
51
+ }
52
+ });
53
+ // Send input to a session
54
+ router.post('/:sessionName/input', async (req, res) => {
55
+ const { sessionName } = req.params;
56
+ const { text, sendEnter = true } = req.body;
57
+ const { exec } = await import('child_process');
58
+ const { promisify } = await import('util');
59
+ const execAsync = promisify(exec);
60
+ if (!/^[\w-]+$/.test(sessionName)) {
61
+ return res.status(400).json({ success: false, error: 'Invalid session name' });
62
+ }
63
+ if (!text || typeof text !== 'string') {
64
+ return res.status(400).json({ success: false, error: 'Text is required' });
65
+ }
66
+ try {
67
+ // Check if session exists
68
+ await execAsync(`tmux has-session -t "${sessionName}" 2>/dev/null`);
69
+ // Escape special characters for tmux send-keys
70
+ const escapedText = text.replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/;/g, '\\;');
71
+ // Send the text
72
+ if (sendEnter) {
73
+ await execAsync(`tmux send-keys -t "${sessionName}" "${escapedText}" Enter`);
74
+ }
75
+ else {
76
+ await execAsync(`tmux send-keys -t "${sessionName}" "${escapedText}"`);
77
+ }
78
+ // Update last activity
79
+ sessionsDb.upsertSession(sessionName, {
80
+ lastEvent: 'Input sent',
81
+ });
82
+ res.json({
83
+ success: true,
84
+ sessionName,
85
+ bytesSent: text.length,
86
+ });
87
+ }
88
+ catch {
89
+ res.status(404).json({ success: false, error: 'Session not found' });
90
+ }
91
+ });
92
+ return router;
93
+ }
94
+ //# sourceMappingURL=sessions-tmux.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessions-tmux.js","sourceRoot":"","sources":["../../src/routes/sessions-tmux.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Session API routes: list, preview, kill, archive tmux sessions.
3
+ * Simplified version without spawn, worktree, push, or PR features.
4
+ */
5
+ import { Router } from 'express';
6
+ export declare function createSessionRoutes(): Router;
7
+ //# sourceMappingURL=sessions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../../src/routes/sessions.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAYjC,wBAAgB,mBAAmB,IAAI,MAAM,CAgN5C"}
@@ -0,0 +1,172 @@
1
+ /**
2
+ * Session API routes: list, preview, kill, archive tmux sessions.
3
+ * Simplified version without spawn, worktree, push, or PR features.
4
+ */
5
+ import { Router } from 'express';
6
+ import * as sessionsDb from '../db/sessions.js';
7
+ import { broadcastSessionRemoved, broadcastSessionArchived, broadcastStatusUpdate, } from '../websocket-handlers.js';
8
+ import { createSessionTmuxRoutes } from './sessions-tmux.js';
9
+ import { createSessionGitRoutes } from './sessions-git.js';
10
+ import { authMiddleware } from '../middleware/auth.js';
11
+ export function createSessionRoutes() {
12
+ const router = Router();
13
+ router.use(authMiddleware);
14
+ // Sub-routers: /:sessionName/output, /:sessionName/input, /:sessionName/git.
15
+ // Path relatif tetap sama karena router ini sendiri dipasang di /api/sessions.
16
+ router.use('/', createSessionTmuxRoutes());
17
+ router.use('/', createSessionGitRoutes());
18
+ // Enhanced sessions endpoint with detailed info
19
+ router.get('/', async (_req, res) => {
20
+ const { exec } = await import('child_process');
21
+ const { promisify } = await import('util');
22
+ const execAsync = promisify(exec);
23
+ try {
24
+ const { stdout } = await execAsync('tmux list-sessions -F "#{session_name}|#{session_created}" 2>/dev/null');
25
+ const sessions = [];
26
+ for (const line of stdout.trim().split('\n').filter(Boolean)) {
27
+ const [name, created] = line.split('|');
28
+ const [project] = name.split('--');
29
+ // Get DB data if available
30
+ const dbSession = sessionsDb.getSession(name);
31
+ sessions.push(sessionsDb.dbSessionToInfo(name, project, parseInt(created) * 1000, dbSession));
32
+ }
33
+ res.json(sessions);
34
+ }
35
+ catch {
36
+ res.json([]);
37
+ }
38
+ });
39
+ // Get archived sessions
40
+ router.get('/archived', (_req, res) => {
41
+ const archivedSessions = sessionsDb.getArchivedSessions();
42
+ const sessions = archivedSessions.map((session) => ({
43
+ name: session.name,
44
+ project: session.project,
45
+ createdAt: session.created_at,
46
+ lastEvent: session.last_event ?? undefined,
47
+ archivedAt: session.archived_at ?? undefined,
48
+ }));
49
+ res.json(sessions);
50
+ });
51
+ // Get single session info by name
52
+ router.get('/:sessionName/status', (req, res) => {
53
+ const { sessionName } = req.params;
54
+ if (!/^[\w-]+$/.test(sessionName)) {
55
+ return res.status(400).json({ error: 'Invalid session name' });
56
+ }
57
+ const dbSession = sessionsDb.getSession(sessionName);
58
+ if (!dbSession) {
59
+ return res.status(404).json({ error: 'Session not found' });
60
+ }
61
+ res.json(sessionsDb.dbSessionToInfo(sessionName, dbSession.project, dbSession.created_at, dbSession));
62
+ });
63
+ // Acknowledge session - reset needs_attention status
64
+ router.post('/:sessionName/acknowledge', (req, res) => {
65
+ const { sessionName } = req.params;
66
+ if (!/^[\w-]+$/.test(sessionName)) {
67
+ return res.status(400).json({ error: 'Invalid session name' });
68
+ }
69
+ const session = sessionsDb.getSession(sessionName);
70
+ if (!session) {
71
+ return res.status(404).json({ error: 'Session not found' });
72
+ }
73
+ // Only reset if currently needs_attention
74
+ if (session.status === 'needs_attention') {
75
+ const updatedSession = sessionsDb.upsertSession(sessionName, {
76
+ status: 'working',
77
+ attentionReason: null,
78
+ });
79
+ // Broadcast status change to all WebSocket clients
80
+ broadcastStatusUpdate({
81
+ name: sessionName,
82
+ project: updatedSession.project,
83
+ status: 'working',
84
+ attentionReason: undefined,
85
+ statusSource: 'hook',
86
+ createdAt: updatedSession.created_at,
87
+ lastActivity: updatedSession.last_activity,
88
+ });
89
+ }
90
+ res.json({ success: true });
91
+ });
92
+ // Get terminal preview (last N lines from tmux pane)
93
+ router.get('/:sessionName/preview', async (req, res) => {
94
+ const { sessionName } = req.params;
95
+ const { exec } = await import('child_process');
96
+ const { promisify } = await import('util');
97
+ const execAsync = promisify(exec);
98
+ if (!/^[\w-]+$/.test(sessionName)) {
99
+ return res.status(400).json({ error: 'Invalid session name' });
100
+ }
101
+ try {
102
+ const { stdout } = await execAsync(`tmux capture-pane -t "${sessionName}" -p -S -20 2>/dev/null`);
103
+ const allLines = stdout.split('\n');
104
+ const lines = allLines
105
+ .slice(-16, -1)
106
+ .filter((line) => line.trim() !== '' || allLines.indexOf(line) > allLines.length - 5);
107
+ res.json({
108
+ lines: lines.length > 0 ? lines : ['(empty terminal)'],
109
+ timestamp: Date.now(),
110
+ });
111
+ }
112
+ catch {
113
+ res.status(404).json({ error: 'Session not found' });
114
+ }
115
+ });
116
+ // Kill a tmux session
117
+ router.delete('/:sessionName', async (req, res) => {
118
+ const { sessionName } = req.params;
119
+ const { exec } = await import('child_process');
120
+ const { promisify } = await import('util');
121
+ const execAsync = promisify(exec);
122
+ if (!/^[\w-]+$/.test(sessionName)) {
123
+ return res.status(400).json({ error: 'Invalid session name' });
124
+ }
125
+ try {
126
+ await execAsync(`tmux kill-session -t "${sessionName}" 2>/dev/null`);
127
+ console.log(`Killed tmux session: ${sessionName}`);
128
+ sessionsDb.deleteSession(sessionName);
129
+ broadcastSessionRemoved(sessionName);
130
+ res.json({ success: true, message: `Session ${sessionName} killed` });
131
+ }
132
+ catch {
133
+ res.status(404).json({ error: 'Session not found or already killed' });
134
+ }
135
+ });
136
+ // Archive a session (mark as done and keep in history)
137
+ router.post('/:sessionName/archive', async (req, res) => {
138
+ const { sessionName } = req.params;
139
+ const { exec } = await import('child_process');
140
+ const { promisify } = await import('util');
141
+ const execAsync = promisify(exec);
142
+ if (!/^[\w-]+$/.test(sessionName)) {
143
+ return res.status(400).json({ error: 'Invalid session name' });
144
+ }
145
+ const archivedSession = sessionsDb.archiveSession(sessionName);
146
+ if (!archivedSession) {
147
+ return res.status(404).json({ error: 'Session not found' });
148
+ }
149
+ try {
150
+ await execAsync(`tmux kill-session -t "${sessionName}" 2>/dev/null`);
151
+ console.log(`[Archive] Killed tmux session: ${sessionName}`);
152
+ }
153
+ catch {
154
+ console.log(`[Archive] Tmux session ${sessionName} was already gone`);
155
+ }
156
+ const archivedInfo = {
157
+ name: sessionName,
158
+ project: archivedSession.project,
159
+ createdAt: archivedSession.created_at,
160
+ lastEvent: archivedSession.last_event ?? undefined,
161
+ archivedAt: archivedSession.archived_at ?? undefined,
162
+ };
163
+ broadcastSessionArchived(sessionName, archivedInfo);
164
+ res.json({
165
+ success: true,
166
+ message: `Session ${sessionName} archived`,
167
+ session: archivedInfo,
168
+ });
169
+ });
170
+ return router;
171
+ }
172
+ //# sourceMappingURL=sessions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessions.js","sourceRoot":"","sources":["../../src/routes/sessions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Main server entry point - Express HTTP server with WebSocket support.
3
+ * Routes and handlers are split into separate modules for maintainability.
4
+ */
5
+ export declare function createServer(): Promise<import("http").Server<typeof import("http").IncomingMessage, typeof import("http").ServerResponse>>;
6
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAyCH,wBAAsB,YAAY,gHA8EjC"}
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Main server entry point - Express HTTP server with WebSocket support.
3
+ * Routes and handlers are split into separate modules for maintainability.
4
+ */
5
+ import express from 'express';
6
+ import cors from 'cors';
7
+ import { WebSocketServer } from 'ws';
8
+ import { createServer as createHttpServer } from 'http';
9
+ import { execSync } from 'child_process';
10
+ import { initDatabase, closeDatabase } from './db/index.js';
11
+ import * as sessionsDb from './db/sessions.js';
12
+ // Routes
13
+ import { createProjectRoutes, createSessionRoutes, createPairRoutes, createHooksRoutes, createCommandRoutes, createFileRoutes, } from './routes/index.js';
14
+ // WebSocket
15
+ import { handleTerminalConnection, handleSessionsConnection } from './websocket-handlers.js';
16
+ import { authenticateToken } from './middleware/auth.js';
17
+ // Utility to get active tmux sessions
18
+ function getActiveTmuxSessions() {
19
+ try {
20
+ const output = execSync('tmux list-sessions -F "#{session_name}" 2>/dev/null', {
21
+ encoding: 'utf-8',
22
+ });
23
+ return new Set(output
24
+ .trim()
25
+ .split('\n')
26
+ .filter((s) => s));
27
+ }
28
+ catch {
29
+ return new Set();
30
+ }
31
+ }
32
+ export async function createServer() {
33
+ const app = express();
34
+ app.use(cors());
35
+ app.use(express.json());
36
+ const server = createHttpServer(app);
37
+ const wss = new WebSocketServer({ noServer: true });
38
+ // Initialize SQLite database
39
+ initDatabase();
40
+ // Reconcile sessions with active tmux sessions
41
+ const activeTmuxSessions = getActiveTmuxSessions();
42
+ sessionsDb.reconcileWithTmux(activeTmuxSessions);
43
+ // Load existing sessions
44
+ const dbSessions = sessionsDb.getAllSessions();
45
+ console.log(`[DB] Loaded ${dbSessions.length} sessions from database`);
46
+ // Health check endpoint for container orchestration
47
+ app.get('/health', (_req, res) => {
48
+ res.json({ status: 'ok', timestamp: Date.now() });
49
+ });
50
+ // Mount API routes
51
+ app.use('/api', createProjectRoutes());
52
+ app.use('/api/sessions', createSessionRoutes());
53
+ app.use('/api', createCommandRoutes());
54
+ app.use('/api', createFileRoutes());
55
+ // Mount pairing routes (both at /pair and /api/pair for flexibility)
56
+ app.use('/pair', createPairRoutes());
57
+ app.use('/api/pair', createPairRoutes());
58
+ // Mount hooks routes for Claude Code hook notifications
59
+ app.use('/api/hooks', createHooksRoutes());
60
+ // Handle WebSocket upgrades
61
+ server.on('upgrade', async (req, socket, head) => {
62
+ const url = new URL(req.url, `http://${req.headers.host}`);
63
+ // Auth per-machine: bila agent punya accessToken, wajib ?token= yang cocok.
64
+ // Install lama tanpa accessToken → authenticateToken true (opt-in).
65
+ if (!authenticateToken(url.searchParams.get('token') ?? undefined)) {
66
+ socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n');
67
+ socket.destroy();
68
+ return;
69
+ }
70
+ if (url.pathname === '/terminal') {
71
+ wss.handleUpgrade(req, socket, head, (ws) => {
72
+ handleTerminalConnection(ws, url);
73
+ });
74
+ return;
75
+ }
76
+ if (url.pathname === '/sessions') {
77
+ wss.handleUpgrade(req, socket, head, (ws) => {
78
+ handleSessionsConnection(ws, url);
79
+ });
80
+ return;
81
+ }
82
+ socket.destroy();
83
+ });
84
+ // Graceful shutdown
85
+ const shutdown = () => {
86
+ console.log('[Server] Shutting down...');
87
+ closeDatabase();
88
+ server.close();
89
+ process.exit(0);
90
+ };
91
+ process.on('SIGTERM', shutdown);
92
+ process.on('SIGINT', shutdown);
93
+ return server;
94
+ }
95
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ export interface Terminal {
2
+ write(data: string): void;
3
+ resize(cols: number, rows: number): void;
4
+ onData(callback: (data: string) => void): void;
5
+ onExit(callback: (info: {
6
+ exitCode: number;
7
+ }) => void): void;
8
+ kill(): void;
9
+ detach(): void;
10
+ captureHistory(lines?: number): Promise<string>;
11
+ isExistingSession(): boolean;
12
+ onReady(callback: () => void): void;
13
+ }
14
+ export interface CreateTerminalOptions {
15
+ /** Custom environment variables to inject into the session */
16
+ customEnvVars?: Record<string, string>;
17
+ }
18
+ export declare function createTerminal(cwd: string, sessionName: string, options?: CreateTerminalOptions | Record<string, string>): Terminal;
19
+ //# sourceMappingURL=terminal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminal.d.ts","sourceRoot":"","sources":["../src/terminal.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,QAAQ;IACvB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACzC,MAAM,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;IAC/C,MAAM,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,GAAG,IAAI,CAAC;IAC7D,IAAI,IAAI,IAAI,CAAC;IACb,MAAM,IAAI,IAAI,CAAC;IACf,cAAc,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAChD,iBAAiB,IAAI,OAAO,CAAC;IAC7B,OAAO,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;CACrC;AAED,MAAM,WAAW,qBAAqB;IACpC,8DAA8D;IAC9D,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACxC;AAED,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,EACX,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,qBAAqB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GAC3D,QAAQ,CAiMV"}