agent-relay 1.0.21 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (283) hide show
  1. package/dist/bridge/shadow-cli.d.ts +17 -0
  2. package/dist/bridge/shadow-cli.d.ts.map +1 -0
  3. package/dist/bridge/shadow-cli.js +75 -0
  4. package/dist/bridge/shadow-cli.js.map +1 -0
  5. package/dist/bridge/shadow-config.d.ts +87 -0
  6. package/dist/bridge/shadow-config.d.ts.map +1 -0
  7. package/dist/bridge/shadow-config.js +134 -0
  8. package/dist/bridge/shadow-config.js.map +1 -0
  9. package/dist/bridge/spawner.d.ts +15 -1
  10. package/dist/bridge/spawner.d.ts.map +1 -1
  11. package/dist/bridge/spawner.js +164 -4
  12. package/dist/bridge/spawner.js.map +1 -1
  13. package/dist/bridge/types.d.ts +55 -0
  14. package/dist/bridge/types.d.ts.map +1 -1
  15. package/dist/cli/index.js +796 -11
  16. package/dist/cli/index.js.map +1 -1
  17. package/dist/cloud/api/auth.d.ts +19 -0
  18. package/dist/cloud/api/auth.d.ts.map +1 -0
  19. package/dist/cloud/api/auth.js +216 -0
  20. package/dist/cloud/api/auth.js.map +1 -0
  21. package/dist/cloud/api/billing.d.ts +17 -0
  22. package/dist/cloud/api/billing.d.ts.map +1 -0
  23. package/dist/cloud/api/billing.js +353 -0
  24. package/dist/cloud/api/billing.js.map +1 -0
  25. package/dist/cloud/api/coordinators.d.ts +8 -0
  26. package/dist/cloud/api/coordinators.d.ts.map +1 -0
  27. package/dist/cloud/api/coordinators.js +347 -0
  28. package/dist/cloud/api/coordinators.js.map +1 -0
  29. package/dist/cloud/api/daemons.d.ts +12 -0
  30. package/dist/cloud/api/daemons.d.ts.map +1 -0
  31. package/dist/cloud/api/daemons.js +320 -0
  32. package/dist/cloud/api/daemons.js.map +1 -0
  33. package/dist/cloud/api/middleware/planLimits.d.ts +36 -0
  34. package/dist/cloud/api/middleware/planLimits.d.ts.map +1 -0
  35. package/dist/cloud/api/middleware/planLimits.js +164 -0
  36. package/dist/cloud/api/middleware/planLimits.js.map +1 -0
  37. package/dist/cloud/api/onboarding.d.ts +8 -0
  38. package/dist/cloud/api/onboarding.d.ts.map +1 -0
  39. package/dist/cloud/api/onboarding.js +407 -0
  40. package/dist/cloud/api/onboarding.js.map +1 -0
  41. package/dist/cloud/api/providers.d.ts +7 -0
  42. package/dist/cloud/api/providers.d.ts.map +1 -0
  43. package/dist/cloud/api/providers.js +435 -0
  44. package/dist/cloud/api/providers.js.map +1 -0
  45. package/dist/cloud/api/repos.d.ts +7 -0
  46. package/dist/cloud/api/repos.d.ts.map +1 -0
  47. package/dist/cloud/api/repos.js +314 -0
  48. package/dist/cloud/api/repos.js.map +1 -0
  49. package/dist/cloud/api/teams.d.ts +7 -0
  50. package/dist/cloud/api/teams.d.ts.map +1 -0
  51. package/dist/cloud/api/teams.js +279 -0
  52. package/dist/cloud/api/teams.js.map +1 -0
  53. package/dist/cloud/api/usage.d.ts +7 -0
  54. package/dist/cloud/api/usage.d.ts.map +1 -0
  55. package/dist/cloud/api/usage.js +98 -0
  56. package/dist/cloud/api/usage.js.map +1 -0
  57. package/dist/cloud/api/workspaces.d.ts +7 -0
  58. package/dist/cloud/api/workspaces.d.ts.map +1 -0
  59. package/dist/cloud/api/workspaces.js +510 -0
  60. package/dist/cloud/api/workspaces.js.map +1 -0
  61. package/dist/cloud/billing/index.d.ts +9 -0
  62. package/dist/cloud/billing/index.d.ts.map +1 -0
  63. package/dist/cloud/billing/index.js +9 -0
  64. package/dist/cloud/billing/index.js.map +1 -0
  65. package/dist/cloud/billing/plans.d.ts +39 -0
  66. package/dist/cloud/billing/plans.d.ts.map +1 -0
  67. package/dist/cloud/billing/plans.js +232 -0
  68. package/dist/cloud/billing/plans.js.map +1 -0
  69. package/dist/cloud/billing/service.d.ts +80 -0
  70. package/dist/cloud/billing/service.d.ts.map +1 -0
  71. package/dist/cloud/billing/service.js +388 -0
  72. package/dist/cloud/billing/service.js.map +1 -0
  73. package/dist/cloud/billing/types.d.ts +135 -0
  74. package/dist/cloud/billing/types.d.ts.map +1 -0
  75. package/dist/cloud/billing/types.js +7 -0
  76. package/dist/cloud/billing/types.js.map +1 -0
  77. package/dist/cloud/config.d.ts +59 -0
  78. package/dist/cloud/config.d.ts.map +1 -0
  79. package/dist/cloud/config.js +83 -0
  80. package/dist/cloud/config.js.map +1 -0
  81. package/dist/cloud/db/drizzle.d.ts +132 -0
  82. package/dist/cloud/db/drizzle.d.ts.map +1 -0
  83. package/dist/cloud/db/drizzle.js +613 -0
  84. package/dist/cloud/db/drizzle.js.map +1 -0
  85. package/dist/cloud/db/index.d.ts +30 -0
  86. package/dist/cloud/db/index.d.ts.map +1 -0
  87. package/dist/cloud/db/index.js +44 -0
  88. package/dist/cloud/db/index.js.map +1 -0
  89. package/dist/cloud/db/schema.d.ts +1792 -0
  90. package/dist/cloud/db/schema.d.ts.map +1 -0
  91. package/dist/cloud/db/schema.js +234 -0
  92. package/dist/cloud/db/schema.js.map +1 -0
  93. package/dist/cloud/index.d.ts +11 -0
  94. package/dist/cloud/index.d.ts.map +1 -0
  95. package/dist/cloud/index.js +37 -0
  96. package/dist/cloud/index.js.map +1 -0
  97. package/dist/cloud/provisioner/index.d.ts +51 -0
  98. package/dist/cloud/provisioner/index.d.ts.map +1 -0
  99. package/dist/cloud/provisioner/index.js +676 -0
  100. package/dist/cloud/provisioner/index.js.map +1 -0
  101. package/dist/cloud/server.d.ts +16 -0
  102. package/dist/cloud/server.d.ts.map +1 -0
  103. package/dist/cloud/server.js +190 -0
  104. package/dist/cloud/server.js.map +1 -0
  105. package/dist/cloud/services/coordinator.d.ts +62 -0
  106. package/dist/cloud/services/coordinator.d.ts.map +1 -0
  107. package/dist/cloud/services/coordinator.js +389 -0
  108. package/dist/cloud/services/coordinator.js.map +1 -0
  109. package/dist/cloud/services/planLimits.d.ts +110 -0
  110. package/dist/cloud/services/planLimits.d.ts.map +1 -0
  111. package/dist/cloud/services/planLimits.js +254 -0
  112. package/dist/cloud/services/planLimits.js.map +1 -0
  113. package/dist/cloud/vault/index.d.ts +76 -0
  114. package/dist/cloud/vault/index.d.ts.map +1 -0
  115. package/dist/cloud/vault/index.js +219 -0
  116. package/dist/cloud/vault/index.js.map +1 -0
  117. package/dist/daemon/agent-manager.d.ts +87 -0
  118. package/dist/daemon/agent-manager.d.ts.map +1 -0
  119. package/dist/daemon/agent-manager.js +412 -0
  120. package/dist/daemon/agent-manager.js.map +1 -0
  121. package/dist/daemon/agent-registry.d.ts +2 -0
  122. package/dist/daemon/agent-registry.d.ts.map +1 -1
  123. package/dist/daemon/agent-registry.js +3 -0
  124. package/dist/daemon/agent-registry.js.map +1 -1
  125. package/dist/daemon/api.d.ts +69 -0
  126. package/dist/daemon/api.d.ts.map +1 -0
  127. package/dist/daemon/api.js +425 -0
  128. package/dist/daemon/api.js.map +1 -0
  129. package/dist/daemon/cloud-sync.d.ts +101 -0
  130. package/dist/daemon/cloud-sync.d.ts.map +1 -0
  131. package/dist/daemon/cloud-sync.js +261 -0
  132. package/dist/daemon/cloud-sync.js.map +1 -0
  133. package/dist/daemon/index.d.ts +4 -0
  134. package/dist/daemon/index.d.ts.map +1 -1
  135. package/dist/daemon/index.js +6 -0
  136. package/dist/daemon/index.js.map +1 -1
  137. package/dist/daemon/orchestrator.d.ts +155 -0
  138. package/dist/daemon/orchestrator.d.ts.map +1 -0
  139. package/dist/daemon/orchestrator.js +736 -0
  140. package/dist/daemon/orchestrator.js.map +1 -0
  141. package/dist/daemon/router.d.ts +24 -0
  142. package/dist/daemon/router.d.ts.map +1 -1
  143. package/dist/daemon/router.js +71 -1
  144. package/dist/daemon/router.js.map +1 -1
  145. package/dist/daemon/server.d.ts +37 -0
  146. package/dist/daemon/server.d.ts.map +1 -1
  147. package/dist/daemon/server.js +191 -16
  148. package/dist/daemon/server.js.map +1 -1
  149. package/dist/daemon/types.d.ts +127 -0
  150. package/dist/daemon/types.d.ts.map +1 -0
  151. package/dist/daemon/types.js +6 -0
  152. package/dist/daemon/types.js.map +1 -0
  153. package/dist/daemon/workspace-manager.d.ts +75 -0
  154. package/dist/daemon/workspace-manager.d.ts.map +1 -0
  155. package/dist/daemon/workspace-manager.js +289 -0
  156. package/dist/daemon/workspace-manager.js.map +1 -0
  157. package/dist/dashboard/out/404.html +1 -1
  158. package/dist/dashboard/out/_next/static/chunks/693-7b3301d8f6bc5014.js +1 -0
  159. package/dist/dashboard/out/_next/static/chunks/713-f78477eb185f1f4d.js +1 -0
  160. package/dist/dashboard/out/_next/static/chunks/766-e53e1cfe39b0b5b5.js +1 -0
  161. package/dist/dashboard/out/_next/static/chunks/900-037c64bfd797fb2a.js +1 -0
  162. package/dist/dashboard/out/_next/static/chunks/app/app/page-e3d9e1f4466b9bae.js +1 -0
  163. package/dist/dashboard/out/_next/static/chunks/app/history/page-b6edd4dde8d08194.js +1 -0
  164. package/dist/dashboard/out/_next/static/chunks/app/layout-2433bb48965f4333.js +1 -0
  165. package/dist/dashboard/out/_next/static/chunks/app/metrics/page-e68825a81db67ba1.js +1 -0
  166. package/dist/dashboard/out/_next/static/chunks/app/page-cc108bf68c8a657f.js +1 -0
  167. package/dist/dashboard/out/_next/static/chunks/app/pricing/page-d80e03a5297f95b6.js +1 -0
  168. package/dist/dashboard/out/_next/static/chunks/main-app-5d692157a8eb1fd9.js +1 -0
  169. package/dist/dashboard/out/_next/static/chunks/{main-e0a1f53fe0617a63.js → main-c2f423b9c9f4591b.js} +1 -1
  170. package/dist/dashboard/out/_next/static/chunks/{webpack-c81f7fd28659d64f.js → webpack-a5acc2831d094776.js} +1 -1
  171. package/dist/dashboard/out/_next/static/css/79b80143647a07d7.css +1 -0
  172. package/dist/dashboard/out/_next/static/css/8cf277370ad48cfe.css +1 -0
  173. package/dist/dashboard/out/alt-logos/agent-relay-logo-128.png +0 -0
  174. package/dist/dashboard/out/alt-logos/agent-relay-logo-256.png +0 -0
  175. package/dist/dashboard/out/alt-logos/agent-relay-logo-32.png +0 -0
  176. package/dist/dashboard/out/alt-logos/agent-relay-logo-512.png +0 -0
  177. package/dist/dashboard/out/alt-logos/agent-relay-logo-64.png +0 -0
  178. package/dist/dashboard/out/alt-logos/agent-relay-logo.svg +45 -0
  179. package/dist/dashboard/out/alt-logos/logo.svg +38 -0
  180. package/dist/dashboard/out/alt-logos/monogram-logo-128.png +0 -0
  181. package/dist/dashboard/out/alt-logos/monogram-logo-256.png +0 -0
  182. package/dist/dashboard/out/alt-logos/monogram-logo-32.png +0 -0
  183. package/dist/dashboard/out/alt-logos/monogram-logo-512.png +0 -0
  184. package/dist/dashboard/out/alt-logos/monogram-logo-64.png +0 -0
  185. package/dist/dashboard/out/alt-logos/monogram-logo.svg +38 -0
  186. package/dist/dashboard/out/app.html +14 -0
  187. package/dist/dashboard/out/app.txt +7 -0
  188. package/dist/dashboard/out/history.html +1 -0
  189. package/dist/dashboard/out/history.txt +7 -0
  190. package/dist/dashboard/out/index.html +1 -1
  191. package/dist/dashboard/out/index.txt +2 -2
  192. package/dist/dashboard/out/metrics.html +1 -515
  193. package/dist/dashboard/out/metrics.txt +2 -2
  194. package/dist/dashboard/out/pricing.html +13 -0
  195. package/dist/dashboard/out/pricing.txt +7 -0
  196. package/dist/dashboard-server/metrics.d.ts.map +1 -1
  197. package/dist/dashboard-server/metrics.js +3 -2
  198. package/dist/dashboard-server/metrics.js.map +1 -1
  199. package/dist/dashboard-server/server.d.ts.map +1 -1
  200. package/dist/dashboard-server/server.js +1279 -56
  201. package/dist/dashboard-server/server.js.map +1 -1
  202. package/dist/protocol/types.d.ts +10 -1
  203. package/dist/protocol/types.d.ts.map +1 -1
  204. package/dist/resiliency/context-persistence.d.ts +140 -0
  205. package/dist/resiliency/context-persistence.d.ts.map +1 -0
  206. package/dist/resiliency/context-persistence.js +397 -0
  207. package/dist/resiliency/context-persistence.js.map +1 -0
  208. package/dist/resiliency/health-monitor.d.ts +97 -0
  209. package/dist/resiliency/health-monitor.d.ts.map +1 -0
  210. package/dist/resiliency/health-monitor.js +291 -0
  211. package/dist/resiliency/health-monitor.js.map +1 -0
  212. package/dist/resiliency/index.d.ts +63 -0
  213. package/dist/resiliency/index.d.ts.map +1 -0
  214. package/dist/resiliency/index.js +63 -0
  215. package/dist/resiliency/index.js.map +1 -0
  216. package/dist/resiliency/logger.d.ts +114 -0
  217. package/dist/resiliency/logger.d.ts.map +1 -0
  218. package/dist/resiliency/logger.js +250 -0
  219. package/dist/resiliency/logger.js.map +1 -0
  220. package/dist/resiliency/metrics.d.ts +115 -0
  221. package/dist/resiliency/metrics.d.ts.map +1 -0
  222. package/dist/resiliency/metrics.js +239 -0
  223. package/dist/resiliency/metrics.js.map +1 -0
  224. package/dist/resiliency/provider-context.d.ts +100 -0
  225. package/dist/resiliency/provider-context.d.ts.map +1 -0
  226. package/dist/resiliency/provider-context.js +360 -0
  227. package/dist/resiliency/provider-context.js.map +1 -0
  228. package/dist/resiliency/supervisor.d.ts +109 -0
  229. package/dist/resiliency/supervisor.d.ts.map +1 -0
  230. package/dist/resiliency/supervisor.js +337 -0
  231. package/dist/resiliency/supervisor.js.map +1 -0
  232. package/dist/storage/adapter.d.ts +2 -0
  233. package/dist/storage/adapter.d.ts.map +1 -1
  234. package/dist/storage/adapter.js +12 -2
  235. package/dist/storage/adapter.js.map +1 -1
  236. package/dist/storage/sqlite-adapter.d.ts.map +1 -1
  237. package/dist/storage/sqlite-adapter.js +18 -14
  238. package/dist/storage/sqlite-adapter.js.map +1 -1
  239. package/dist/utils/index.d.ts +1 -0
  240. package/dist/utils/index.d.ts.map +1 -1
  241. package/dist/utils/index.js +1 -0
  242. package/dist/utils/index.js.map +1 -1
  243. package/dist/utils/logger.d.ts +40 -0
  244. package/dist/utils/logger.d.ts.map +1 -0
  245. package/dist/utils/logger.js +84 -0
  246. package/dist/utils/logger.js.map +1 -0
  247. package/dist/wrapper/client.d.ts +16 -1
  248. package/dist/wrapper/client.d.ts.map +1 -1
  249. package/dist/wrapper/client.js +32 -1
  250. package/dist/wrapper/client.js.map +1 -1
  251. package/dist/wrapper/parser.d.ts +3 -0
  252. package/dist/wrapper/parser.d.ts.map +1 -1
  253. package/dist/wrapper/parser.js +121 -18
  254. package/dist/wrapper/parser.js.map +1 -1
  255. package/dist/wrapper/pty-wrapper.d.ts +28 -1
  256. package/dist/wrapper/pty-wrapper.d.ts.map +1 -1
  257. package/dist/wrapper/pty-wrapper.js +166 -30
  258. package/dist/wrapper/pty-wrapper.js.map +1 -1
  259. package/dist/wrapper/tmux-wrapper.d.ts +5 -0
  260. package/dist/wrapper/tmux-wrapper.d.ts.map +1 -1
  261. package/dist/wrapper/tmux-wrapper.js +58 -18
  262. package/dist/wrapper/tmux-wrapper.js.map +1 -1
  263. package/docs/CLOUD-ARCHITECTURE.md +652 -0
  264. package/docs/CLOUD-ONBOARDING-DESIGN.md +1983 -0
  265. package/docs/TESTING_PRESENCE_FEATURES.md +327 -0
  266. package/docs/agent-relay-snippet.md +107 -4
  267. package/docs/guides/CLOUD.md +236 -0
  268. package/docs/guides/LOCAL.md +535 -0
  269. package/docs/guides/SELF-HOSTED.md +494 -0
  270. package/docs/proposals/shadow-as-subagent.md +765 -0
  271. package/docs/proposals/slack-bot-integration.md +1457 -0
  272. package/package.json +33 -4
  273. package/dist/dashboard/out/_next/static/chunks/app/layout-c9d8c5d95e48c6bf.js +0 -1
  274. package/dist/dashboard/out/_next/static/chunks/app/metrics/page-8aa9936bc6c771ab.js +0 -1
  275. package/dist/dashboard/out/_next/static/chunks/app/page-49055e5d2b5e34ec.js +0 -1
  276. package/dist/dashboard/out/_next/static/chunks/main-app-bae2e535de00de50.js +0 -1
  277. package/dist/dashboard/out/_next/static/css/50ed6996e3df7bdd.css +0 -1
  278. /package/dist/dashboard/out/_next/static/{gZXwjIKGDKJ0hiTH-HMeJ → 6HHWb2ZmnJ4OSm0zUP7h4}/_buildManifest.js +0 -0
  279. /package/dist/dashboard/out/_next/static/{gZXwjIKGDKJ0hiTH-HMeJ → 6HHWb2ZmnJ4OSm0zUP7h4}/_ssgManifest.js +0 -0
  280. /package/dist/dashboard/out/_next/static/chunks/{117-3bef7b19f3e60751.js → 117-b2cd8d6485aacf2b.js} +0 -0
  281. /package/dist/dashboard/out/_next/static/chunks/{648-6cf686106c891ad3.js → 648-8f3f26864ce515e5.js} +0 -0
  282. /package/dist/dashboard/out/_next/static/chunks/app/_not-found/{page-8ff6572bc7c9bc61.js → page-0b990dbb71d72a98.js} +0 -0
  283. /package/dist/dashboard/out/_next/static/chunks/{fd9d1056-26bd8d656b496dba.js → fd9d1056-bf46c09eb57e019c.js} +0 -0
@@ -0,0 +1,254 @@
1
+ /**
2
+ * Plan Limits Service
3
+ *
4
+ * Defines resource limits for each plan tier and provides
5
+ * functions to check if users are within their limits.
6
+ */
7
+ import { db, usageRecordsTable } from '../db/index.js';
8
+ import { eq, and, gte, sql } from 'drizzle-orm';
9
+ import { getDb } from '../db/drizzle.js';
10
+ /**
11
+ * Plan limits configuration
12
+ *
13
+ * Free: Try it out on a side project
14
+ * Pro: Professional developers, coordinators enabled
15
+ * Team: Growing teams with advanced needs
16
+ * Enterprise: Unlimited everything
17
+ */
18
+ export const PLAN_LIMITS = {
19
+ free: {
20
+ maxWorkspaces: 1,
21
+ maxRepos: 3,
22
+ maxConcurrentAgents: 2,
23
+ maxComputeHoursPerMonth: 10,
24
+ coordinatorsEnabled: false,
25
+ },
26
+ pro: {
27
+ maxWorkspaces: 5,
28
+ maxRepos: 20,
29
+ maxConcurrentAgents: 10,
30
+ maxComputeHoursPerMonth: 100,
31
+ coordinatorsEnabled: true,
32
+ },
33
+ team: {
34
+ maxWorkspaces: 20,
35
+ maxRepos: 100,
36
+ maxConcurrentAgents: 50,
37
+ maxComputeHoursPerMonth: 500,
38
+ coordinatorsEnabled: true,
39
+ },
40
+ enterprise: {
41
+ maxWorkspaces: Infinity,
42
+ maxRepos: Infinity,
43
+ maxConcurrentAgents: Infinity,
44
+ maxComputeHoursPerMonth: Infinity,
45
+ coordinatorsEnabled: true,
46
+ },
47
+ };
48
+ /**
49
+ * Get plan limits for a given plan type
50
+ */
51
+ export function getPlanLimits(plan) {
52
+ return PLAN_LIMITS[plan];
53
+ }
54
+ /**
55
+ * Get current usage for a user
56
+ */
57
+ export async function getUserUsage(userId) {
58
+ // Get workspace count
59
+ const workspaces = await db.workspaces.findByUserId(userId);
60
+ const workspaceCount = workspaces.length;
61
+ // Get repo count across all workspaces
62
+ let repoCount = 0;
63
+ for (const workspace of workspaces) {
64
+ const repos = await db.repositories.findByWorkspaceId(workspace.id);
65
+ repoCount += repos.length;
66
+ }
67
+ // Get concurrent agents (currently running)
68
+ // For now, we'll track this via usage_records with metric 'active_agents'
69
+ // In production, this would query the actual running agent count
70
+ const drizzleDb = getDb();
71
+ const activeAgentsResult = await drizzleDb
72
+ .select({ total: sql `COALESCE(MAX(${usageRecordsTable.value}), 0)` })
73
+ .from(usageRecordsTable)
74
+ .where(and(eq(usageRecordsTable.userId, userId), eq(usageRecordsTable.metric, 'active_agents')));
75
+ const concurrentAgents = Number(activeAgentsResult[0]?.total || 0);
76
+ // Get compute hours this month
77
+ const startOfMonth = new Date();
78
+ startOfMonth.setDate(1);
79
+ startOfMonth.setHours(0, 0, 0, 0);
80
+ const computeHoursResult = await drizzleDb
81
+ .select({ total: sql `COALESCE(SUM(${usageRecordsTable.value}), 0)` })
82
+ .from(usageRecordsTable)
83
+ .where(and(eq(usageRecordsTable.userId, userId), eq(usageRecordsTable.metric, 'compute_hours'), gte(usageRecordsTable.recordedAt, startOfMonth)));
84
+ const computeHoursThisMonth = Number(computeHoursResult[0]?.total || 0);
85
+ return {
86
+ workspaceCount,
87
+ repoCount,
88
+ concurrentAgents,
89
+ computeHoursThisMonth,
90
+ };
91
+ }
92
+ /**
93
+ * Check if user can create a new workspace
94
+ */
95
+ export async function canCreateWorkspace(userId) {
96
+ const user = await db.users.findById(userId);
97
+ if (!user) {
98
+ return { allowed: false, reason: 'User not found' };
99
+ }
100
+ const plan = user.plan || 'free';
101
+ const limits = getPlanLimits(plan);
102
+ const usage = await getUserUsage(userId);
103
+ if (usage.workspaceCount >= limits.maxWorkspaces) {
104
+ return {
105
+ allowed: false,
106
+ reason: `Workspace limit reached for ${plan} plan`,
107
+ limit: limits.maxWorkspaces,
108
+ current: usage.workspaceCount,
109
+ };
110
+ }
111
+ return { allowed: true };
112
+ }
113
+ /**
114
+ * Check if user can add a new repo
115
+ */
116
+ export async function canAddRepo(userId) {
117
+ const user = await db.users.findById(userId);
118
+ if (!user) {
119
+ return { allowed: false, reason: 'User not found' };
120
+ }
121
+ const plan = user.plan || 'free';
122
+ const limits = getPlanLimits(plan);
123
+ const usage = await getUserUsage(userId);
124
+ if (usage.repoCount >= limits.maxRepos) {
125
+ return {
126
+ allowed: false,
127
+ reason: `Repository limit reached for ${plan} plan`,
128
+ limit: limits.maxRepos,
129
+ current: usage.repoCount,
130
+ };
131
+ }
132
+ return { allowed: true };
133
+ }
134
+ /**
135
+ * Check if user can spawn another agent (concurrent agent limit)
136
+ */
137
+ export async function canSpawnAgent(userId, currentRunningAgents) {
138
+ const user = await db.users.findById(userId);
139
+ if (!user) {
140
+ return { allowed: false, reason: 'User not found' };
141
+ }
142
+ const plan = user.plan || 'free';
143
+ const limits = getPlanLimits(plan);
144
+ // Use provided count or fetch from usage
145
+ let concurrentAgents;
146
+ if (currentRunningAgents !== undefined) {
147
+ concurrentAgents = currentRunningAgents;
148
+ }
149
+ else {
150
+ const usage = await getUserUsage(userId);
151
+ concurrentAgents = usage.concurrentAgents;
152
+ }
153
+ if (concurrentAgents >= limits.maxConcurrentAgents) {
154
+ return {
155
+ allowed: false,
156
+ reason: `Concurrent agent limit reached for ${plan} plan`,
157
+ limit: limits.maxConcurrentAgents,
158
+ current: concurrentAgents,
159
+ };
160
+ }
161
+ return { allowed: true };
162
+ }
163
+ /**
164
+ * Check if user can use coordinator agents
165
+ */
166
+ export async function canUseCoordinator(userId) {
167
+ const user = await db.users.findById(userId);
168
+ if (!user) {
169
+ return { allowed: false, reason: 'User not found' };
170
+ }
171
+ const plan = user.plan || 'free';
172
+ const limits = getPlanLimits(plan);
173
+ if (!limits.coordinatorsEnabled) {
174
+ return {
175
+ allowed: false,
176
+ reason: 'Coordinator agents require a Pro plan or higher',
177
+ requiredPlan: 'pro',
178
+ };
179
+ }
180
+ return { allowed: true };
181
+ }
182
+ /**
183
+ * Check if user has compute hours available
184
+ */
185
+ export async function hasComputeHoursAvailable(userId) {
186
+ const user = await db.users.findById(userId);
187
+ if (!user) {
188
+ return { available: false, reason: 'User not found' };
189
+ }
190
+ const plan = user.plan || 'free';
191
+ const limits = getPlanLimits(plan);
192
+ const usage = await getUserUsage(userId);
193
+ // Enterprise has unlimited
194
+ if (limits.maxComputeHoursPerMonth === Infinity) {
195
+ return { available: true };
196
+ }
197
+ if (usage.computeHoursThisMonth >= limits.maxComputeHoursPerMonth) {
198
+ return {
199
+ available: false,
200
+ reason: `Compute hours limit reached for ${plan} plan`,
201
+ limit: limits.maxComputeHoursPerMonth,
202
+ current: usage.computeHoursThisMonth,
203
+ };
204
+ }
205
+ return { available: true };
206
+ }
207
+ /**
208
+ * Get remaining quota for a user
209
+ */
210
+ export async function getRemainingQuota(userId) {
211
+ const user = await db.users.findById(userId);
212
+ const plan = (user?.plan || 'free');
213
+ const limits = getPlanLimits(plan);
214
+ const usage = await getUserUsage(userId);
215
+ const calcRemaining = (limit, current) => limit === Infinity ? Infinity : Math.max(0, limit - current);
216
+ return {
217
+ plan,
218
+ limits,
219
+ usage,
220
+ remaining: {
221
+ workspaces: calcRemaining(limits.maxWorkspaces, usage.workspaceCount),
222
+ repos: calcRemaining(limits.maxRepos, usage.repoCount),
223
+ concurrentAgents: calcRemaining(limits.maxConcurrentAgents, usage.concurrentAgents),
224
+ computeHours: calcRemaining(limits.maxComputeHoursPerMonth, usage.computeHoursThisMonth),
225
+ },
226
+ };
227
+ }
228
+ /**
229
+ * Record compute usage
230
+ */
231
+ export async function recordComputeUsage(userId, workspaceId, hours) {
232
+ const drizzleDb = getDb();
233
+ await drizzleDb.insert(usageRecordsTable).values({
234
+ userId,
235
+ workspaceId,
236
+ metric: 'compute_hours',
237
+ value: Math.round(hours * 100) / 100, // Round to 2 decimal places
238
+ recordedAt: new Date(),
239
+ });
240
+ }
241
+ /**
242
+ * Update active agent count for a user
243
+ */
244
+ export async function updateActiveAgentCount(userId, workspaceId, count) {
245
+ const drizzleDb = getDb();
246
+ await drizzleDb.insert(usageRecordsTable).values({
247
+ userId,
248
+ workspaceId,
249
+ metric: 'active_agents',
250
+ value: count,
251
+ recordedAt: new Date(),
252
+ });
253
+ }
254
+ //# sourceMappingURL=planLimits.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"planLimits.js","sourceRoot":"","sources":["../../../src/cloud/services/planLimits.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Agent Relay Cloud - Credential Vault
3
+ *
4
+ * Secure storage for OAuth tokens with AES-256-GCM encryption.
5
+ */
6
+ export interface StoredCredential {
7
+ userId: string;
8
+ provider: string;
9
+ accessToken: string;
10
+ refreshToken?: string;
11
+ tokenExpiresAt?: Date;
12
+ scopes?: string[];
13
+ providerAccountId?: string;
14
+ providerAccountEmail?: string;
15
+ }
16
+ export interface DecryptedCredential {
17
+ accessToken: string;
18
+ refreshToken?: string;
19
+ tokenExpiresAt?: Date;
20
+ scopes?: string[];
21
+ providerAccountId?: string;
22
+ providerAccountEmail?: string;
23
+ }
24
+ export declare class CredentialVault {
25
+ private masterKey;
26
+ constructor();
27
+ /**
28
+ * Encrypt a string value
29
+ */
30
+ private encrypt;
31
+ /**
32
+ * Decrypt a string value
33
+ */
34
+ private decrypt;
35
+ /**
36
+ * Store encrypted credential
37
+ */
38
+ storeCredential(credential: StoredCredential): Promise<void>;
39
+ /**
40
+ * Retrieve and decrypt credential
41
+ */
42
+ getCredential(userId: string, provider: string): Promise<DecryptedCredential | null>;
43
+ /**
44
+ * Get all credentials for a user (decrypted)
45
+ */
46
+ getUserCredentials(userId: string): Promise<Map<string, DecryptedCredential>>;
47
+ /**
48
+ * Update tokens (e.g., after refresh)
49
+ */
50
+ updateTokens(userId: string, provider: string, accessToken: string, refreshToken?: string, expiresAt?: Date): Promise<void>;
51
+ /**
52
+ * Delete credential
53
+ */
54
+ deleteCredential(userId: string, provider: string): Promise<void>;
55
+ /**
56
+ * Check if credential needs refresh (within 5 minutes of expiry)
57
+ */
58
+ needsRefresh(userId: string, provider: string): Promise<boolean>;
59
+ /**
60
+ * Refresh OAuth token for a provider
61
+ */
62
+ refreshToken(userId: string, provider: string): Promise<boolean>;
63
+ }
64
+ export declare function getVault(): CredentialVault;
65
+ export declare const vault: {
66
+ readonly instance: CredentialVault;
67
+ storeCredential: (cred: StoredCredential) => Promise<void>;
68
+ getCredential: (userId: string, provider: string) => Promise<DecryptedCredential | null>;
69
+ getUserCredentials: (userId: string) => Promise<Map<string, DecryptedCredential>>;
70
+ updateTokens: (userId: string, provider: string, accessToken: string, refreshToken?: string, expiresAt?: Date) => Promise<void>;
71
+ deleteCredential: (userId: string, provider: string) => Promise<void>;
72
+ needsRefresh: (userId: string, provider: string) => Promise<boolean>;
73
+ refreshToken: (userId: string, provider: string) => Promise<boolean>;
74
+ };
75
+ export declare function generateMasterKey(): string;
76
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cloud/vault/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAUH,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,IAAI,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,IAAI,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,qBAAa,eAAe;IAC1B,OAAO,CAAC,SAAS,CAAS;;IAW1B;;OAEG;IACH,OAAO,CAAC,OAAO;IAgBf;;OAEG;IACH,OAAO,CAAC,OAAO;IAkBf;;OAEG;IACG,eAAe,CAAC,UAAU,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBlE;;OAEG;IACG,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC;IAkB1F;;OAEG;IACG,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;IAoBnF;;OAEG;IACG,YAAY,CAChB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,YAAY,CAAC,EAAE,MAAM,EACrB,SAAS,CAAC,EAAE,IAAI,GACf,OAAO,CAAC,IAAI,CAAC;IAehB;;OAEG;IACG,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvE;;OAEG;IACG,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAUtE;;OAEG;IACG,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAuEvE;AAKD,wBAAgB,QAAQ,IAAI,eAAe,CAK1C;AAED,eAAO,MAAM,KAAK;;4BAIQ,gBAAgB;4BAChB,MAAM,YAAY,MAAM;iCAEnB,MAAM;2BAEzB,MAAM,YACJ,MAAM,eACH,MAAM,iBACJ,MAAM,cACT,IAAI;+BAES,MAAM,YAAY,MAAM;2BAE5B,MAAM,YAAY,MAAM;2BAExB,MAAM,YAAY,MAAM;CAEhD,CAAC;AAGF,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C"}
@@ -0,0 +1,219 @@
1
+ /**
2
+ * Agent Relay Cloud - Credential Vault
3
+ *
4
+ * Secure storage for OAuth tokens with AES-256-GCM encryption.
5
+ */
6
+ import crypto from 'crypto';
7
+ import { getConfig } from '../config.js';
8
+ import { db } from '../db/index.js';
9
+ const ALGORITHM = 'aes-256-gcm';
10
+ const IV_LENGTH = 12;
11
+ const AUTH_TAG_LENGTH = 16;
12
+ export class CredentialVault {
13
+ masterKey;
14
+ constructor() {
15
+ const config = getConfig();
16
+ this.masterKey = Buffer.from(config.vault.masterKey, 'base64');
17
+ if (this.masterKey.length !== 32) {
18
+ throw new Error('Vault master key must be 32 bytes (base64 encoded)');
19
+ }
20
+ }
21
+ /**
22
+ * Encrypt a string value
23
+ */
24
+ encrypt(plaintext) {
25
+ const iv = crypto.randomBytes(IV_LENGTH);
26
+ const cipher = crypto.createCipheriv(ALGORITHM, this.masterKey, iv);
27
+ const encrypted = Buffer.concat([
28
+ cipher.update(plaintext, 'utf8'),
29
+ cipher.final(),
30
+ ]);
31
+ const authTag = cipher.getAuthTag();
32
+ // Format: base64(iv + authTag + ciphertext)
33
+ const combined = Buffer.concat([iv, authTag, encrypted]);
34
+ return combined.toString('base64');
35
+ }
36
+ /**
37
+ * Decrypt a string value
38
+ */
39
+ decrypt(ciphertext) {
40
+ const combined = Buffer.from(ciphertext, 'base64');
41
+ const iv = combined.subarray(0, IV_LENGTH);
42
+ const authTag = combined.subarray(IV_LENGTH, IV_LENGTH + AUTH_TAG_LENGTH);
43
+ const encrypted = combined.subarray(IV_LENGTH + AUTH_TAG_LENGTH);
44
+ const decipher = crypto.createDecipheriv(ALGORITHM, this.masterKey, iv);
45
+ decipher.setAuthTag(authTag);
46
+ const decrypted = Buffer.concat([
47
+ decipher.update(encrypted),
48
+ decipher.final(),
49
+ ]);
50
+ return decrypted.toString('utf8');
51
+ }
52
+ /**
53
+ * Store encrypted credential
54
+ */
55
+ async storeCredential(credential) {
56
+ const encryptedAccessToken = this.encrypt(credential.accessToken);
57
+ const encryptedRefreshToken = credential.refreshToken
58
+ ? this.encrypt(credential.refreshToken)
59
+ : undefined;
60
+ await db.credentials.upsert({
61
+ userId: credential.userId,
62
+ provider: credential.provider,
63
+ accessToken: encryptedAccessToken,
64
+ refreshToken: encryptedRefreshToken,
65
+ tokenExpiresAt: credential.tokenExpiresAt,
66
+ scopes: credential.scopes,
67
+ providerAccountId: credential.providerAccountId,
68
+ providerAccountEmail: credential.providerAccountEmail,
69
+ });
70
+ }
71
+ /**
72
+ * Retrieve and decrypt credential
73
+ */
74
+ async getCredential(userId, provider) {
75
+ const credential = await db.credentials.findByUserAndProvider(userId, provider);
76
+ if (!credential) {
77
+ return null;
78
+ }
79
+ return {
80
+ accessToken: this.decrypt(credential.accessToken),
81
+ refreshToken: credential.refreshToken
82
+ ? this.decrypt(credential.refreshToken)
83
+ : undefined,
84
+ tokenExpiresAt: credential.tokenExpiresAt ?? undefined,
85
+ scopes: credential.scopes ?? undefined,
86
+ providerAccountId: credential.providerAccountId ?? undefined,
87
+ providerAccountEmail: credential.providerAccountEmail ?? undefined,
88
+ };
89
+ }
90
+ /**
91
+ * Get all credentials for a user (decrypted)
92
+ */
93
+ async getUserCredentials(userId) {
94
+ const credentials = await db.credentials.findByUserId(userId);
95
+ const result = new Map();
96
+ for (const cred of credentials) {
97
+ result.set(cred.provider, {
98
+ accessToken: this.decrypt(cred.accessToken),
99
+ refreshToken: cred.refreshToken
100
+ ? this.decrypt(cred.refreshToken)
101
+ : undefined,
102
+ tokenExpiresAt: cred.tokenExpiresAt ?? undefined,
103
+ scopes: cred.scopes ?? undefined,
104
+ providerAccountId: cred.providerAccountId ?? undefined,
105
+ providerAccountEmail: cred.providerAccountEmail ?? undefined,
106
+ });
107
+ }
108
+ return result;
109
+ }
110
+ /**
111
+ * Update tokens (e.g., after refresh)
112
+ */
113
+ async updateTokens(userId, provider, accessToken, refreshToken, expiresAt) {
114
+ const encryptedAccessToken = this.encrypt(accessToken);
115
+ const encryptedRefreshToken = refreshToken
116
+ ? this.encrypt(refreshToken)
117
+ : undefined;
118
+ await db.credentials.updateTokens(userId, provider, encryptedAccessToken, encryptedRefreshToken, expiresAt);
119
+ }
120
+ /**
121
+ * Delete credential
122
+ */
123
+ async deleteCredential(userId, provider) {
124
+ await db.credentials.delete(userId, provider);
125
+ }
126
+ /**
127
+ * Check if credential needs refresh (within 5 minutes of expiry)
128
+ */
129
+ async needsRefresh(userId, provider) {
130
+ const credential = await db.credentials.findByUserAndProvider(userId, provider);
131
+ if (!credential || !credential.tokenExpiresAt) {
132
+ return false;
133
+ }
134
+ const fiveMinutes = 5 * 60 * 1000;
135
+ return Date.now() > credential.tokenExpiresAt.getTime() - fiveMinutes;
136
+ }
137
+ /**
138
+ * Refresh OAuth token for a provider
139
+ */
140
+ async refreshToken(userId, provider) {
141
+ const credential = await this.getCredential(userId, provider);
142
+ if (!credential?.refreshToken) {
143
+ return false;
144
+ }
145
+ // Provider-specific refresh endpoints
146
+ const refreshEndpoints = {
147
+ anthropic: 'https://api.anthropic.com/oauth/token',
148
+ openai: 'https://auth.openai.com/oauth/token',
149
+ google: 'https://oauth2.googleapis.com/token',
150
+ github: 'https://github.com/login/oauth/access_token',
151
+ };
152
+ const endpoint = refreshEndpoints[provider];
153
+ if (!endpoint) {
154
+ console.error(`Unknown provider for refresh: ${provider}`);
155
+ return false;
156
+ }
157
+ try {
158
+ const config = getConfig();
159
+ const providerConfig = config.providers[provider];
160
+ const response = await fetch(endpoint, {
161
+ method: 'POST',
162
+ headers: {
163
+ 'Content-Type': 'application/x-www-form-urlencoded',
164
+ Accept: 'application/json',
165
+ },
166
+ body: new URLSearchParams({
167
+ grant_type: 'refresh_token',
168
+ refresh_token: credential.refreshToken,
169
+ client_id: providerConfig?.clientId || config.github.clientId,
170
+ ...(provider === 'google' && {
171
+ client_secret: providerConfig?.clientSecret,
172
+ }),
173
+ ...(provider === 'github' && {
174
+ client_secret: config.github.clientSecret,
175
+ }),
176
+ }),
177
+ });
178
+ if (!response.ok) {
179
+ const error = await response.text();
180
+ console.error(`Token refresh failed for ${provider}:`, error);
181
+ return false;
182
+ }
183
+ const data = await response.json();
184
+ await this.updateTokens(userId, provider, data.access_token, data.refresh_token, data.expires_in
185
+ ? new Date(Date.now() + data.expires_in * 1000)
186
+ : undefined);
187
+ return true;
188
+ }
189
+ catch (error) {
190
+ console.error(`Error refreshing token for ${provider}:`, error);
191
+ return false;
192
+ }
193
+ }
194
+ }
195
+ // Singleton instance
196
+ let _vault = null;
197
+ export function getVault() {
198
+ if (!_vault) {
199
+ _vault = new CredentialVault();
200
+ }
201
+ return _vault;
202
+ }
203
+ export const vault = {
204
+ get instance() {
205
+ return getVault();
206
+ },
207
+ storeCredential: (cred) => getVault().storeCredential(cred),
208
+ getCredential: (userId, provider) => getVault().getCredential(userId, provider),
209
+ getUserCredentials: (userId) => getVault().getUserCredentials(userId),
210
+ updateTokens: (userId, provider, accessToken, refreshToken, expiresAt) => getVault().updateTokens(userId, provider, accessToken, refreshToken, expiresAt),
211
+ deleteCredential: (userId, provider) => getVault().deleteCredential(userId, provider),
212
+ needsRefresh: (userId, provider) => getVault().needsRefresh(userId, provider),
213
+ refreshToken: (userId, provider) => getVault().refreshToken(userId, provider),
214
+ };
215
+ // Generate a new master key (for setup)
216
+ export function generateMasterKey() {
217
+ return crypto.randomBytes(32).toString('base64');
218
+ }
219
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cloud/vault/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Agent Manager
3
+ * Manages agents across workspaces with integrated resiliency.
4
+ */
5
+ import { EventEmitter } from 'events';
6
+ import type { Agent, SpawnAgentRequest } from './types.js';
7
+ export declare class AgentManager extends EventEmitter {
8
+ private agents;
9
+ private supervisor;
10
+ private dataDir;
11
+ private logsDir;
12
+ constructor(dataDir: string);
13
+ /**
14
+ * Spawn a new agent in a workspace
15
+ */
16
+ spawn(workspaceId: string, workspacePath: string, request: SpawnAgentRequest): Promise<Agent>;
17
+ /**
18
+ * Stop an agent
19
+ */
20
+ stop(agentId: string): Promise<boolean>;
21
+ /**
22
+ * Stop all agents in a workspace
23
+ */
24
+ stopAllInWorkspace(workspaceId: string): Promise<void>;
25
+ /**
26
+ * Stop all agents
27
+ */
28
+ stopAll(): Promise<void>;
29
+ /**
30
+ * Get an agent by ID
31
+ */
32
+ get(agentId: string): Agent | undefined;
33
+ /**
34
+ * Get all agents in a workspace
35
+ */
36
+ getByWorkspace(workspaceId: string): Agent[];
37
+ /**
38
+ * Get all agents
39
+ */
40
+ getAll(): Agent[];
41
+ /**
42
+ * Find agent by name in a workspace
43
+ */
44
+ findByName(workspaceId: string, name: string): Agent | undefined;
45
+ /**
46
+ * Get agent output/logs
47
+ */
48
+ getOutput(agentId: string, limit?: number): string[] | null;
49
+ /**
50
+ * Get raw output from agent
51
+ */
52
+ getRawOutput(agentId: string): string | null;
53
+ /**
54
+ * Send input to an agent
55
+ */
56
+ sendInput(agentId: string, input: string): boolean;
57
+ /**
58
+ * Restart an agent
59
+ */
60
+ private restartAgent;
61
+ /**
62
+ * Handle agent exit
63
+ */
64
+ private handleAgentExit;
65
+ /**
66
+ * Setup supervisor event handlers
67
+ */
68
+ private setupSupervisorEvents;
69
+ /**
70
+ * Get CLI command for provider
71
+ */
72
+ private getCliCommand;
73
+ /**
74
+ * Convert internal agent to public agent (without pty reference)
75
+ */
76
+ private toPublicAgent;
77
+ /**
78
+ * Emit a daemon event
79
+ */
80
+ private emitEvent;
81
+ /**
82
+ * Shutdown the agent manager
83
+ */
84
+ shutdown(): Promise<void>;
85
+ }
86
+ export declare function getAgentManager(dataDir?: string): AgentManager;
87
+ //# sourceMappingURL=agent-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-manager.d.ts","sourceRoot":"","sources":["../../src/daemon/agent-manager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAMtC,OAAO,KAAK,EACV,KAAK,EAGL,iBAAiB,EAClB,MAAM,YAAY,CAAC;AAYpB,qBAAa,YAAa,SAAQ,YAAY;IAC5C,OAAO,CAAC,MAAM,CAAmC;IACjD,OAAO,CAAC,UAAU,CAOf;IACH,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,OAAO,CAAS;gBAEZ,OAAO,EAAE,MAAM;IAmB3B;;OAEG;IACG,KAAK,CACT,WAAW,EAAE,MAAM,EACnB,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,KAAK,CAAC;IA2HjB;;OAEG;IACG,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IA2C7C;;OAEG;IACG,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAO5D;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAO9B;;OAEG;IACH,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS;IAKvC;;OAEG;IACH,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,KAAK,EAAE;IAM5C;;OAEG;IACH,MAAM,IAAI,KAAK,EAAE;IAIjB;;OAEG;IACH,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS;IAOhE;;OAEG;IACH,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI;IAM3D;;OAEG;IACH,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAM5C;;OAEG;IACH,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO;IAOlD;;OAEG;YACW,YAAY;IA0D1B;;OAEG;IACH,OAAO,CAAC,eAAe;IAmBvB;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAmB7B;;OAEG;IACH,OAAO,CAAC,aAAa;IAarB;;OAEG;IACH,OAAO,CAAC,aAAa;IAgBrB;;OAEG;IACH,OAAO,CAAC,SAAS;IAIjB;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAKhC;AAID,wBAAgB,eAAe,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,YAAY,CAM9D"}