@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,198 @@
1
+ import { getDatabase } from './index.js';
2
+ /**
3
+ * Map baris DB sessions ke WSSessionInfo (kontrak WS/HTTP). Satu sumber
4
+ * kebenaran agar token fields konsisten lintas broadcast & route.
5
+ */
6
+ export function dbSessionToInfo(name, project, createdAt, dbSession, overrides) {
7
+ const base = {
8
+ name,
9
+ project,
10
+ createdAt,
11
+ lastActivity: dbSession?.last_activity,
12
+ lastEvent: dbSession?.last_event ?? undefined,
13
+ archivedAt: dbSession?.archived_at ?? undefined,
14
+ status: dbSession?.status ?? undefined,
15
+ statusSource: dbSession?.status_source ?? undefined,
16
+ attentionReason: dbSession?.attention_reason ?? undefined,
17
+ lastStatusChange: dbSession?.last_status_change ?? undefined,
18
+ commandId: dbSession?.command_id ?? undefined,
19
+ };
20
+ if (dbSession) {
21
+ const hasUsage = (dbSession.tokens_input ?? 0) > 0 ||
22
+ (dbSession.tokens_output ?? 0) > 0 ||
23
+ (dbSession.tokens_cache_read ?? 0) > 0 ||
24
+ (dbSession.tokens_cache_creation ?? 0) > 0;
25
+ if (hasUsage) {
26
+ base.usage = {
27
+ inputTokens: dbSession.tokens_input ?? 0,
28
+ outputTokens: dbSession.tokens_output ?? 0,
29
+ cacheReadTokens: dbSession.tokens_cache_read ?? 0,
30
+ cacheCreationTokens: dbSession.tokens_cache_creation ?? 0,
31
+ };
32
+ }
33
+ if (dbSession.model)
34
+ base.model = dbSession.model;
35
+ if (typeof dbSession.cost_usd === 'number')
36
+ base.costUsd = dbSession.cost_usd;
37
+ }
38
+ return { ...base, ...overrides };
39
+ }
40
+ /**
41
+ * Get a session by name
42
+ */
43
+ export function getSession(name) {
44
+ const db = getDatabase();
45
+ const row = db.prepare('SELECT * FROM sessions WHERE name = ?').get(name);
46
+ return row ?? null;
47
+ }
48
+ /**
49
+ * Get all active (non-archived) sessions
50
+ */
51
+ export function getAllSessions() {
52
+ const db = getDatabase();
53
+ return db
54
+ .prepare('SELECT * FROM sessions WHERE archived_at IS NULL ORDER BY last_activity DESC')
55
+ .all();
56
+ }
57
+ /**
58
+ * Get all archived sessions
59
+ */
60
+ export function getArchivedSessions() {
61
+ const db = getDatabase();
62
+ return db
63
+ .prepare('SELECT * FROM sessions WHERE archived_at IS NOT NULL ORDER BY archived_at DESC')
64
+ .all();
65
+ }
66
+ /**
67
+ * Upsert a session (insert or update)
68
+ */
69
+ export function upsertSession(name, input) {
70
+ const db = getDatabase();
71
+ const now = Date.now();
72
+ const existing = getSession(name);
73
+ // Determine if status is changing
74
+ const statusChanging = input.status !== undefined && input.status !== existing?.status;
75
+ const lastStatusChange = statusChanging ? now : (existing?.last_status_change ?? null);
76
+ const stmt = db.prepare(`
77
+ INSERT INTO sessions (
78
+ name, project, last_event,
79
+ last_activity, created_at, updated_at,
80
+ status, status_source, attention_reason, last_status_change,
81
+ tokens_input, tokens_output, tokens_cache_read, tokens_cache_creation,
82
+ model, cost_usd
83
+ )
84
+ VALUES (
85
+ @name, @project, @lastEvent,
86
+ @lastActivity, @createdAt, @updatedAt,
87
+ @status, @statusSource, @attentionReason, @lastStatusChange,
88
+ @tokensInput, @tokensOutput, @tokensCacheRead, @tokensCacheCreation,
89
+ @model, @costUsd
90
+ )
91
+ ON CONFLICT(name) DO UPDATE SET
92
+ last_event = COALESCE(@lastEvent, last_event),
93
+ last_activity = COALESCE(@lastActivity, last_activity),
94
+ updated_at = @updatedAt,
95
+ status = COALESCE(@status, status),
96
+ status_source = COALESCE(@statusSource, status_source),
97
+ attention_reason = CASE WHEN @status IS NOT NULL THEN @attentionReason ELSE attention_reason END,
98
+ last_status_change = COALESCE(@lastStatusChange, last_status_change),
99
+ tokens_input = COALESCE(@tokensInput, tokens_input),
100
+ tokens_output = COALESCE(@tokensOutput, tokens_output),
101
+ tokens_cache_read = COALESCE(@tokensCacheRead, tokens_cache_read),
102
+ tokens_cache_creation = COALESCE(@tokensCacheCreation, tokens_cache_creation),
103
+ model = COALESCE(@model, model),
104
+ cost_usd = COALESCE(@costUsd, cost_usd)
105
+ `);
106
+ stmt.run({
107
+ name,
108
+ project: input.project ?? existing?.project ?? 'unknown',
109
+ lastEvent: input.lastEvent ?? null,
110
+ lastActivity: input.lastActivity ?? now,
111
+ createdAt: existing?.created_at ?? now,
112
+ updatedAt: now,
113
+ status: input.status ?? null,
114
+ statusSource: input.statusSource ?? null,
115
+ attentionReason: input.attentionReason ?? null,
116
+ lastStatusChange,
117
+ tokensInput: input.usage?.inputTokens ?? null,
118
+ tokensOutput: input.usage?.outputTokens ?? null,
119
+ tokensCacheRead: input.usage?.cacheReadTokens ?? null,
120
+ tokensCacheCreation: input.usage?.cacheCreationTokens ?? null,
121
+ model: input.model ?? null,
122
+ costUsd: input.costUsd ?? null,
123
+ });
124
+ return getSession(name);
125
+ }
126
+ /**
127
+ * Delete a session
128
+ */
129
+ export function deleteSession(name) {
130
+ const db = getDatabase();
131
+ const result = db.prepare('DELETE FROM sessions WHERE name = ?').run(name);
132
+ return result.changes > 0;
133
+ }
134
+ /**
135
+ * Archive a session (mark as done and keep in history)
136
+ * Returns the archived session or null if not found
137
+ */
138
+ export function archiveSession(name) {
139
+ const db = getDatabase();
140
+ const now = Date.now();
141
+ const existing = getSession(name);
142
+ if (!existing) {
143
+ return null;
144
+ }
145
+ // Already archived
146
+ if (existing.archived_at) {
147
+ return existing;
148
+ }
149
+ db.prepare(`
150
+ UPDATE sessions SET
151
+ archived_at = ?,
152
+ updated_at = ?
153
+ WHERE name = ?
154
+ `).run(now, now, name);
155
+ console.log(`[DB] Archived session: ${name}`);
156
+ return getSession(name);
157
+ }
158
+ /**
159
+ * Reconcile sessions with active tmux sessions
160
+ * - Sessions in DB but not in tmux: delete if old
161
+ * - Sessions in tmux but not in DB: will be created when they connect
162
+ * - Archived sessions are skipped (they don't have tmux sessions)
163
+ */
164
+ export function reconcileWithTmux(activeTmuxSessions) {
165
+ const dbSessions = getAllSessions(); // Only gets non-archived sessions
166
+ const now = Date.now();
167
+ const maxAge = 24 * 60 * 60 * 1000; // 24 hours
168
+ console.log(`[DB] Reconciling ${dbSessions.length} DB sessions with ${activeTmuxSessions.size} tmux sessions`);
169
+ // Handle sessions in DB but not in tmux (skip archived - they're already handled)
170
+ for (const session of dbSessions) {
171
+ if (!activeTmuxSessions.has(session.name)) {
172
+ const age = now - session.last_activity;
173
+ if (age > maxAge) {
174
+ // Delete old sessions
175
+ deleteSession(session.name);
176
+ console.log(`[DB] Deleted stale session: ${session.name}`);
177
+ }
178
+ }
179
+ }
180
+ // Handle sessions in tmux but not in DB
181
+ // These will be created when they receive their first connection
182
+ // We don't create them here because we don't have project info
183
+ }
184
+ /**
185
+ * Insert session row untuk command yang di-spawn di luar flow WS terminal.
186
+ * Dipakai oleh routes/commands.ts start. Tidak memakai upsertSession agar
187
+ * insert minimal dan benar (upsertSession punya mismatch jumlah kolom/value).
188
+ */
189
+ export function insertCommandSession(name, project, commandId) {
190
+ const db = getDatabase();
191
+ const now = Date.now();
192
+ db.prepare(`INSERT INTO sessions
193
+ (name, project, last_event, last_activity, created_at, updated_at,
194
+ status, status_source, command_id)
195
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(name, project, 'CommandStarted', now, now, now, 'working', 'tmux', commandId);
196
+ return getSession(name);
197
+ }
198
+ //# sourceMappingURL=sessions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessions.js","sourceRoot":"","sources":["../../src/db/sessions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,19 @@
1
+ import { createServer } from './server.js';
2
+ import { config } from './config.js';
3
+ import { logger } from './logger.js';
4
+ const PORT = config.agent?.port || 4678;
5
+ async function main() {
6
+ logger.main.info({ machine: config.machine.name }, 'Starting AgentDeck Agent');
7
+ const server = await createServer();
8
+ server.listen(PORT, () => {
9
+ logger.main.info({ port: PORT }, 'Agent running');
10
+ logger.main.info({ url: `ws://localhost:${PORT}` }, 'Dashboard connection URL');
11
+ logger.main.info({ url: `http://localhost:${PORT}/pair` }, 'Pair with dashboard at');
12
+ logger.main.info('For remote access, use Tailscale Funnel, Cloudflare Tunnel, or SSH tunnel');
13
+ });
14
+ }
15
+ main().catch((err) => {
16
+ logger.main.error(err, 'Agent startup failed');
17
+ process.exit(1);
18
+ });
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,EAAE,IAAI,IAAI,IAAI,CAAC;AAExC,KAAK,UAAU,IAAI;IACjB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,0BAA0B,CAAC,CAAC;IAE/E,MAAM,MAAM,GAAG,MAAM,YAAY,EAAE,CAAC;IAEpC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;QACvB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,eAAe,CAAC,CAAC;QAClD,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,kBAAkB,IAAI,EAAE,EAAE,EAAE,0BAA0B,CAAC,CAAC;QAChF,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,oBAAoB,IAAI,OAAO,EAAE,EAAE,wBAAwB,CAAC,CAAC;QACrF,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,2EAA2E,CAAC,CAAC;IAChG,CAAC,CAAC,CAAC;AACL,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,sBAAsB,CAAC,CAAC;IAC/C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,20 @@
1
+ /** Slug untuk label command: lowercase, non-alphanumeric -> '-', trim. */
2
+ export declare function slugify(s: string): string;
3
+ /**
4
+ * Nama tmux session untuk command: `${project}--cmd--${slug(name)}--${shortId}`.
5
+ * shortId 4-char base36 dari Date.now() + counter monoton agar unik antar call.
6
+ */
7
+ export declare function generateCommandSessionName(project: string, name: string): string;
8
+ /** Cek apakah tmux session ada. */
9
+ export declare function hasCommandSession(name: string): boolean;
10
+ /**
11
+ * Spawn tmux session detached yang langsung menjalankan command (bukan shell
12
+ * interaktif). Command dijalankan via `bash -lc` agar PATH dan parsing shell
13
+ * berlaku (php/composer/npm ter-resolve). Arg array (no shell) supaya cwd dan
14
+ * name diperlakukan literal — tidak meng-expand $VAR / $(...) / backtick.
15
+ * `command` sengaja di-shell oleh bash -lc (user-defined, eksekusi bebas).
16
+ */
17
+ export declare function spawnCommandSession(name: string, cwd: string, command: string): Promise<void>;
18
+ /** Kill tmux session; best-effort, tidak throw jika sudah hilang. */
19
+ export declare function killCommandSession(name: string): Promise<void>;
20
+ //# sourceMappingURL=command-session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-session.d.ts","sourceRoot":"","sources":["../../src/lib/command-session.ts"],"names":[],"mappings":"AAOA,0EAA0E;AAC1E,wBAAgB,OAAO,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAOzC;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAKhF;AAED,mCAAmC;AACnC,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAQvD;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CAYf;AAED,qEAAqE;AACrE,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAMpE"}
@@ -0,0 +1,64 @@
1
+ import { execFile, execFileSync } from 'child_process';
2
+ import { promisify } from 'util';
3
+ const execFileAsync = promisify(execFile);
4
+ let commandNameCounter = 0;
5
+ /** Slug untuk label command: lowercase, non-alphanumeric -> '-', trim. */
6
+ export function slugify(s) {
7
+ const slug = s
8
+ .toLowerCase()
9
+ .trim()
10
+ .replace(/[^a-z0-9]+/g, '-')
11
+ .replace(/^-+|-+$/g, '');
12
+ return slug || 'cmd';
13
+ }
14
+ /**
15
+ * Nama tmux session untuk command: `${project}--cmd--${slug(name)}--${shortId}`.
16
+ * shortId 4-char base36 dari Date.now() + counter monoton agar unik antar call.
17
+ */
18
+ export function generateCommandSessionName(project, name) {
19
+ const ts = Date.now().toString(36);
20
+ const counter = (commandNameCounter++).toString(36);
21
+ const shortId = (ts + counter).slice(-4);
22
+ return `${project}--cmd--${slugify(name)}--${shortId}`;
23
+ }
24
+ /** Cek apakah tmux session ada. */
25
+ export function hasCommandSession(name) {
26
+ try {
27
+ // ponytail: arg array (no shell) supaya nama tidak di-expand shell.
28
+ execFileSync('tmux', ['has-session', '-t', name], { stdio: 'ignore' });
29
+ return true;
30
+ }
31
+ catch {
32
+ return false;
33
+ }
34
+ }
35
+ /**
36
+ * Spawn tmux session detached yang langsung menjalankan command (bukan shell
37
+ * interaktif). Command dijalankan via `bash -lc` agar PATH dan parsing shell
38
+ * berlaku (php/composer/npm ter-resolve). Arg array (no shell) supaya cwd dan
39
+ * name diperlakukan literal — tidak meng-expand $VAR / $(...) / backtick.
40
+ * `command` sengaja di-shell oleh bash -lc (user-defined, eksekusi bebas).
41
+ */
42
+ export async function spawnCommandSession(name, cwd, command) {
43
+ await execFileAsync('tmux', [
44
+ 'new-session',
45
+ '-d',
46
+ '-s',
47
+ name,
48
+ '-c',
49
+ cwd,
50
+ 'bash',
51
+ '-lc',
52
+ command,
53
+ ]);
54
+ }
55
+ /** Kill tmux session; best-effort, tidak throw jika sudah hilang. */
56
+ export async function killCommandSession(name) {
57
+ try {
58
+ await execFileAsync('tmux', ['kill-session', '-t', name]);
59
+ }
60
+ catch {
61
+ // session sudah hilang — bukan error
62
+ }
63
+ }
64
+ //# sourceMappingURL=command-session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-session.js","sourceRoot":"","sources":["../../src/lib/command-session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AAEjC,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAE1C,IAAI,kBAAkB,GAAG,CAAC,CAAC;AAE3B,0EAA0E;AAC1E,MAAM,UAAU,OAAO,CAAC,CAAS;IAC/B,MAAM,IAAI,GAAG,CAAC;SACX,WAAW,EAAE;SACb,IAAI,EAAE;SACN,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;SAC3B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IAC3B,OAAO,IAAI,IAAI,KAAK,CAAC;AACvB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,0BAA0B,CAAC,OAAe,EAAE,IAAY;IACtE,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IACnC,MAAM,OAAO,GAAG,CAAC,kBAAkB,EAAE,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IACpD,MAAM,OAAO,GAAG,CAAC,EAAE,GAAG,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACzC,OAAO,GAAG,OAAO,UAAU,OAAO,CAAC,IAAI,CAAC,KAAK,OAAO,EAAE,CAAC;AACzD,CAAC;AAED,mCAAmC;AACnC,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,IAAI,CAAC;QACH,oEAAoE;QACpE,YAAY,CAAC,MAAM,EAAE,CAAC,aAAa,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;QACvE,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,IAAY,EACZ,GAAW,EACX,OAAe;IAEf,MAAM,aAAa,CAAC,MAAM,EAAE;QAC1B,aAAa;QACb,IAAI;QACJ,IAAI;QACJ,IAAI;QACJ,IAAI;QACJ,GAAG;QACH,MAAM;QACN,KAAK;QACL,OAAO;KACR,CAAC,CAAC;AACL,CAAC;AAED,qEAAqE;AACrE,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,IAAY;IACnD,IAAI,CAAC;QACH,MAAM,aAAa,CAAC,MAAM,EAAE,CAAC,cAAc,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;IAC5D,CAAC;IAAC,MAAM,CAAC;QACP,qCAAqC;IACvC,CAAC;AACH,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { GitHistoryResponse } from '@agentdeck/shared';
2
+ /**
3
+ * Kumpulkan riwayat git untuk direktori kerja tertentu.
4
+ * Jika cwd bukan repo (atau path tidak ada), mengembalikan repo=false tanpa
5
+ * melempar error — ini kondisi normal untuk terminal root non-git.
6
+ */
7
+ export declare function readGitHistory(cwd: string): Promise<GitHistoryResponse>;
8
+ //# sourceMappingURL=git.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/lib/git.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAyC,MAAM,mBAAmB,CAAC;AAyLnG;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAwB7E"}
@@ -0,0 +1,194 @@
1
+ import { execFile } from 'node:child_process';
2
+ import { promisify } from 'node:util';
3
+ const execFileAsync = promisify(execFile);
4
+ const GIT_TIMEOUT_MS = 10_000;
5
+ const GIT_MAX_BUFFER = 4 * 1024 * 1024;
6
+ const COMMIT_LIMIT = 50;
7
+ /**
8
+ * Jalankan `git -C <cwd> <args...>` dan kembalikan stdout.
9
+ * Memakai execFile dengan array args agar tidak terjadi shell injection.
10
+ */
11
+ async function execGit(cwd, args) {
12
+ const { stdout } = await execFileAsync('git', ['-C', cwd, ...args], {
13
+ maxBuffer: GIT_MAX_BUFFER,
14
+ timeout: GIT_TIMEOUT_MS,
15
+ });
16
+ return stdout;
17
+ }
18
+ /**
19
+ * Parse header baris `## branch...upstream [ahead N, behind M]` dari `git status -b`.
20
+ * Mendukung branch tanpa upstream, state detached (`HEAD (no branch)`), dan
21
+ * kombinasi ahead/behind opsional.
22
+ */
23
+ function parseBranchHeader(line) {
24
+ if (!line.startsWith('## '))
25
+ return {};
26
+ const rest = line.slice(3);
27
+ let headPart = rest;
28
+ let ahead;
29
+ let behind;
30
+ const bracketStart = rest.indexOf(' [');
31
+ if (bracketStart >= 0) {
32
+ headPart = rest.slice(0, bracketStart);
33
+ // Isi bracket diakhiri `]`; sudah dipastikan ada karena format porcelain.
34
+ const bracket = rest.slice(bracketStart + 2, rest.length - 1);
35
+ const am = bracket.match(/ahead (\d+)/);
36
+ const bm = bracket.match(/behind (\d+)/);
37
+ if (am)
38
+ ahead = parseInt(am[1], 10);
39
+ if (bm)
40
+ behind = parseInt(bm[1], 10);
41
+ }
42
+ // Detached HEAD: tidak ada branch aktif.
43
+ if (headPart.startsWith('HEAD (no branch)')) {
44
+ return { ahead, behind };
45
+ }
46
+ const dotIdx = headPart.indexOf('...');
47
+ const branch = dotIdx >= 0 ? headPart.slice(0, dotIdx) : headPart;
48
+ return { branch: branch || undefined, ahead, behind };
49
+ }
50
+ function mapStatus(code) {
51
+ switch (code) {
52
+ case 'M':
53
+ return 'M';
54
+ case 'A':
55
+ return 'A';
56
+ case 'D':
57
+ return 'D';
58
+ case 'R':
59
+ return 'R';
60
+ case 'C':
61
+ return 'C';
62
+ case 'U':
63
+ return 'U';
64
+ default:
65
+ return null;
66
+ }
67
+ }
68
+ /**
69
+ * Parse satu baris porcelain status. Format: `<XY> <path>` dengan path
70
+ * berbentuk `oldPath -> newPath` untuk rename/copy. `??` = untracked, `!!`
71
+ * = ignored (dilewati). Untuk status campuran (contoh `AM`), prioritaskan
72
+ * kode staged (X); jika kosong, pakai unstaged (Y).
73
+ */
74
+ function parseStatusLine(line) {
75
+ if (line.length < 3)
76
+ return null;
77
+ const x = line.charAt(0);
78
+ const y = line.charAt(1);
79
+ const filePath = line.slice(3);
80
+ // Abaikan file yang di-ignore.
81
+ if (x === '!' || y === '!')
82
+ return null;
83
+ if (x === '?' && y === '?') {
84
+ return { path: filePath, status: '?' };
85
+ }
86
+ const code = x !== ' ' ? x : y;
87
+ const status = mapStatus(code);
88
+ if (!status)
89
+ return null;
90
+ if (status === 'R' || status === 'C') {
91
+ const arrowIdx = filePath.indexOf(' -> ');
92
+ if (arrowIdx >= 0) {
93
+ return {
94
+ path: filePath.slice(arrowIdx + 4),
95
+ oldPath: filePath.slice(0, arrowIdx),
96
+ status,
97
+ };
98
+ }
99
+ }
100
+ return { path: filePath, status };
101
+ }
102
+ async function readBranchAndChanges(cwd) {
103
+ let out;
104
+ try {
105
+ out = await execGit(cwd, ['status', '--porcelain=v1', '-b']);
106
+ }
107
+ catch {
108
+ return { changes: [] };
109
+ }
110
+ const lines = out.split('\n').filter((l) => l.length > 0);
111
+ if (lines.length === 0)
112
+ return { changes: [] };
113
+ const { branch, ahead, behind } = parseBranchHeader(lines[0]);
114
+ const changes = [];
115
+ for (let i = 1; i < lines.length; i++) {
116
+ const change = parseStatusLine(lines[i]);
117
+ if (change)
118
+ changes.push(change);
119
+ }
120
+ return { branch, ahead, behind, changes };
121
+ }
122
+ async function readCommits(cwd) {
123
+ let out;
124
+ try {
125
+ out = await execGit(cwd, [
126
+ 'log',
127
+ '-n',
128
+ String(COMMIT_LIMIT),
129
+ '--date=iso',
130
+ '--pretty=format:%H%x09%an%x09%ae%x09%aI%x09%s',
131
+ ]);
132
+ }
133
+ catch {
134
+ return [];
135
+ }
136
+ const commits = [];
137
+ for (const line of out.split('\n').filter((l) => l.length > 0)) {
138
+ const parts = line.split('\t');
139
+ if (parts.length < 5)
140
+ continue;
141
+ commits.push({
142
+ sha: parts[0],
143
+ author: parts[1],
144
+ email: parts[2],
145
+ date: parts[3],
146
+ message: parts[4],
147
+ });
148
+ }
149
+ return commits;
150
+ }
151
+ async function readDiffStat(cwd) {
152
+ let out;
153
+ try {
154
+ out = await execGit(cwd, ['diff', '--shortstat']);
155
+ }
156
+ catch {
157
+ return { insertions: 0, deletions: 0 };
158
+ }
159
+ const insMatch = out.match(/(\d+) insertion/);
160
+ const delMatch = out.match(/(\d+) deletion/);
161
+ return {
162
+ insertions: insMatch ? parseInt(insMatch[1], 10) : 0,
163
+ deletions: delMatch ? parseInt(delMatch[1], 10) : 0,
164
+ };
165
+ }
166
+ /**
167
+ * Kumpulkan riwayat git untuk direktori kerja tertentu.
168
+ * Jika cwd bukan repo (atau path tidak ada), mengembalikan repo=false tanpa
169
+ * melempar error — ini kondisi normal untuk terminal root non-git.
170
+ */
171
+ export async function readGitHistory(cwd) {
172
+ const fetchedAt = Date.now();
173
+ try {
174
+ await execGit(cwd, ['rev-parse', '--is-inside-work-tree']);
175
+ }
176
+ catch {
177
+ return { repo: false, commits: [], changes: [], fetchedAt };
178
+ }
179
+ const { branch, ahead, behind, changes } = await readBranchAndChanges(cwd);
180
+ const commits = await readCommits(cwd);
181
+ const { insertions, deletions } = await readDiffStat(cwd);
182
+ return {
183
+ repo: true,
184
+ branch,
185
+ ahead,
186
+ behind,
187
+ commits,
188
+ changes,
189
+ insertions,
190
+ deletions,
191
+ fetchedAt,
192
+ };
193
+ }
194
+ //# sourceMappingURL=git.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/lib/git.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ export interface InitScriptOptions {
2
+ sessionName: string;
3
+ projectName: string;
4
+ customEnvVars?: Record<string, string>;
5
+ /** Shell to use for init script content (prompt, history config). Always 'bash' since bash sources the file. */
6
+ shell?: 'bash' | 'zsh';
7
+ /** Shell to exec into at the end for the interactive session. Defaults to detected user shell. */
8
+ targetShell?: 'bash' | 'zsh';
9
+ }
10
+ /**
11
+ * Detects the user's default shell from environment or /etc/passwd.
12
+ * Falls back to bash if detection fails.
13
+ */
14
+ export declare function detectUserShell(): 'bash' | 'zsh';
15
+ /**
16
+ * Generates a bash/zsh init script for tmux session initialization.
17
+ * Features: adaptive prompt, tmux status bar, useful aliases, welcome message.
18
+ */
19
+ export declare function generateInitScript(options: InitScriptOptions): string;
20
+ /**
21
+ * Writes the init script to a temporary file.
22
+ * @returns The path to the created script file.
23
+ */
24
+ export declare function writeInitScript(sessionName: string, content: string): string;
25
+ /**
26
+ * Removes the init script file.
27
+ */
28
+ export declare function cleanupInitScript(sessionName: string): void;
29
+ /**
30
+ * Gets the path where an init script would be written.
31
+ */
32
+ export declare function getInitScriptPath(sessionName: string): string;
33
+ //# sourceMappingURL=init-script.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init-script.d.ts","sourceRoot":"","sources":["../../src/lib/init-script.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,gHAAgH;IAChH,KAAK,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IACvB,kGAAkG;IAClG,WAAW,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;CAC9B;AAED;;;GAGG;AACH,wBAAgB,eAAe,IAAI,MAAM,GAAG,KAAK,CAmBhD;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,iBAAiB,GAAG,MAAM,CAqdrE;AAaD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAI5E;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAO3D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAE7D"}