availsync 0.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 (460) hide show
  1. package/.adal/skills/stripe-best-practices/SKILL.md +42 -0
  2. package/.adal/skills/stripe-best-practices/references/billing.md +36 -0
  3. package/.adal/skills/stripe-best-practices/references/connect.md +48 -0
  4. package/.adal/skills/stripe-best-practices/references/payments.md +79 -0
  5. package/.adal/skills/stripe-best-practices/references/security.md +109 -0
  6. package/.adal/skills/stripe-best-practices/references/treasury.md +16 -0
  7. package/.adal/skills/stripe-projects/SKILL.md +139 -0
  8. package/.adal/skills/upgrade-stripe/SKILL.md +185 -0
  9. package/.agents/skills/stripe-best-practices/SKILL.md +42 -0
  10. package/.agents/skills/stripe-best-practices/references/billing.md +36 -0
  11. package/.agents/skills/stripe-best-practices/references/connect.md +48 -0
  12. package/.agents/skills/stripe-best-practices/references/payments.md +79 -0
  13. package/.agents/skills/stripe-best-practices/references/security.md +109 -0
  14. package/.agents/skills/stripe-best-practices/references/treasury.md +16 -0
  15. package/.agents/skills/stripe-projects/SKILL.md +139 -0
  16. package/.agents/skills/upgrade-stripe/SKILL.md +185 -0
  17. package/.augment/skills/stripe-best-practices/SKILL.md +42 -0
  18. package/.augment/skills/stripe-best-practices/references/billing.md +36 -0
  19. package/.augment/skills/stripe-best-practices/references/connect.md +48 -0
  20. package/.augment/skills/stripe-best-practices/references/payments.md +79 -0
  21. package/.augment/skills/stripe-best-practices/references/security.md +109 -0
  22. package/.augment/skills/stripe-best-practices/references/treasury.md +16 -0
  23. package/.augment/skills/stripe-projects/SKILL.md +139 -0
  24. package/.augment/skills/upgrade-stripe/SKILL.md +185 -0
  25. package/.bob/skills/stripe-best-practices/SKILL.md +42 -0
  26. package/.bob/skills/stripe-best-practices/references/billing.md +36 -0
  27. package/.bob/skills/stripe-best-practices/references/connect.md +48 -0
  28. package/.bob/skills/stripe-best-practices/references/payments.md +79 -0
  29. package/.bob/skills/stripe-best-practices/references/security.md +109 -0
  30. package/.bob/skills/stripe-best-practices/references/treasury.md +16 -0
  31. package/.bob/skills/stripe-projects/SKILL.md +139 -0
  32. package/.bob/skills/upgrade-stripe/SKILL.md +185 -0
  33. package/.claude/settings.local.json +7 -0
  34. package/.claude/skills/stripe-best-practices/SKILL.md +42 -0
  35. package/.claude/skills/stripe-best-practices/references/billing.md +36 -0
  36. package/.claude/skills/stripe-best-practices/references/connect.md +48 -0
  37. package/.claude/skills/stripe-best-practices/references/payments.md +79 -0
  38. package/.claude/skills/stripe-best-practices/references/security.md +109 -0
  39. package/.claude/skills/stripe-best-practices/references/treasury.md +16 -0
  40. package/.claude/skills/stripe-projects/SKILL.md +139 -0
  41. package/.claude/skills/upgrade-stripe/SKILL.md +185 -0
  42. package/.codebuddy/skills/stripe-best-practices/SKILL.md +42 -0
  43. package/.codebuddy/skills/stripe-best-practices/references/billing.md +36 -0
  44. package/.codebuddy/skills/stripe-best-practices/references/connect.md +48 -0
  45. package/.codebuddy/skills/stripe-best-practices/references/payments.md +79 -0
  46. package/.codebuddy/skills/stripe-best-practices/references/security.md +109 -0
  47. package/.codebuddy/skills/stripe-best-practices/references/treasury.md +16 -0
  48. package/.codebuddy/skills/stripe-projects/SKILL.md +139 -0
  49. package/.codebuddy/skills/upgrade-stripe/SKILL.md +185 -0
  50. package/.commandcode/skills/stripe-best-practices/SKILL.md +42 -0
  51. package/.commandcode/skills/stripe-best-practices/references/billing.md +36 -0
  52. package/.commandcode/skills/stripe-best-practices/references/connect.md +48 -0
  53. package/.commandcode/skills/stripe-best-practices/references/payments.md +79 -0
  54. package/.commandcode/skills/stripe-best-practices/references/security.md +109 -0
  55. package/.commandcode/skills/stripe-best-practices/references/treasury.md +16 -0
  56. package/.commandcode/skills/stripe-projects/SKILL.md +139 -0
  57. package/.commandcode/skills/upgrade-stripe/SKILL.md +185 -0
  58. package/.continue/skills/stripe-best-practices/SKILL.md +42 -0
  59. package/.continue/skills/stripe-best-practices/references/billing.md +36 -0
  60. package/.continue/skills/stripe-best-practices/references/connect.md +48 -0
  61. package/.continue/skills/stripe-best-practices/references/payments.md +79 -0
  62. package/.continue/skills/stripe-best-practices/references/security.md +109 -0
  63. package/.continue/skills/stripe-best-practices/references/treasury.md +16 -0
  64. package/.continue/skills/stripe-projects/SKILL.md +139 -0
  65. package/.continue/skills/upgrade-stripe/SKILL.md +185 -0
  66. package/.cortex/skills/stripe-best-practices/SKILL.md +42 -0
  67. package/.cortex/skills/stripe-best-practices/references/billing.md +36 -0
  68. package/.cortex/skills/stripe-best-practices/references/connect.md +48 -0
  69. package/.cortex/skills/stripe-best-practices/references/payments.md +79 -0
  70. package/.cortex/skills/stripe-best-practices/references/security.md +109 -0
  71. package/.cortex/skills/stripe-best-practices/references/treasury.md +16 -0
  72. package/.cortex/skills/stripe-projects/SKILL.md +139 -0
  73. package/.cortex/skills/upgrade-stripe/SKILL.md +185 -0
  74. package/.crush/skills/stripe-best-practices/SKILL.md +42 -0
  75. package/.crush/skills/stripe-best-practices/references/billing.md +36 -0
  76. package/.crush/skills/stripe-best-practices/references/connect.md +48 -0
  77. package/.crush/skills/stripe-best-practices/references/payments.md +79 -0
  78. package/.crush/skills/stripe-best-practices/references/security.md +109 -0
  79. package/.crush/skills/stripe-best-practices/references/treasury.md +16 -0
  80. package/.crush/skills/stripe-projects/SKILL.md +139 -0
  81. package/.crush/skills/upgrade-stripe/SKILL.md +185 -0
  82. package/.env.example +20 -0
  83. package/.factory/skills/stripe-best-practices/SKILL.md +42 -0
  84. package/.factory/skills/stripe-best-practices/references/billing.md +36 -0
  85. package/.factory/skills/stripe-best-practices/references/connect.md +48 -0
  86. package/.factory/skills/stripe-best-practices/references/payments.md +79 -0
  87. package/.factory/skills/stripe-best-practices/references/security.md +109 -0
  88. package/.factory/skills/stripe-best-practices/references/treasury.md +16 -0
  89. package/.factory/skills/stripe-projects/SKILL.md +139 -0
  90. package/.factory/skills/upgrade-stripe/SKILL.md +185 -0
  91. package/.goose/skills/stripe-best-practices/SKILL.md +42 -0
  92. package/.goose/skills/stripe-best-practices/references/billing.md +36 -0
  93. package/.goose/skills/stripe-best-practices/references/connect.md +48 -0
  94. package/.goose/skills/stripe-best-practices/references/payments.md +79 -0
  95. package/.goose/skills/stripe-best-practices/references/security.md +109 -0
  96. package/.goose/skills/stripe-best-practices/references/treasury.md +16 -0
  97. package/.goose/skills/stripe-projects/SKILL.md +139 -0
  98. package/.goose/skills/upgrade-stripe/SKILL.md +185 -0
  99. package/.iflow/skills/stripe-best-practices/SKILL.md +42 -0
  100. package/.iflow/skills/stripe-best-practices/references/billing.md +36 -0
  101. package/.iflow/skills/stripe-best-practices/references/connect.md +48 -0
  102. package/.iflow/skills/stripe-best-practices/references/payments.md +79 -0
  103. package/.iflow/skills/stripe-best-practices/references/security.md +109 -0
  104. package/.iflow/skills/stripe-best-practices/references/treasury.md +16 -0
  105. package/.iflow/skills/stripe-projects/SKILL.md +139 -0
  106. package/.iflow/skills/upgrade-stripe/SKILL.md +185 -0
  107. package/.junie/skills/stripe-best-practices/SKILL.md +42 -0
  108. package/.junie/skills/stripe-best-practices/references/billing.md +36 -0
  109. package/.junie/skills/stripe-best-practices/references/connect.md +48 -0
  110. package/.junie/skills/stripe-best-practices/references/payments.md +79 -0
  111. package/.junie/skills/stripe-best-practices/references/security.md +109 -0
  112. package/.junie/skills/stripe-best-practices/references/treasury.md +16 -0
  113. package/.junie/skills/stripe-projects/SKILL.md +139 -0
  114. package/.junie/skills/upgrade-stripe/SKILL.md +185 -0
  115. package/.kilocode/skills/stripe-best-practices/SKILL.md +42 -0
  116. package/.kilocode/skills/stripe-best-practices/references/billing.md +36 -0
  117. package/.kilocode/skills/stripe-best-practices/references/connect.md +48 -0
  118. package/.kilocode/skills/stripe-best-practices/references/payments.md +79 -0
  119. package/.kilocode/skills/stripe-best-practices/references/security.md +109 -0
  120. package/.kilocode/skills/stripe-best-practices/references/treasury.md +16 -0
  121. package/.kilocode/skills/stripe-projects/SKILL.md +139 -0
  122. package/.kilocode/skills/upgrade-stripe/SKILL.md +185 -0
  123. package/.kiro/skills/stripe-best-practices/SKILL.md +42 -0
  124. package/.kiro/skills/stripe-best-practices/references/billing.md +36 -0
  125. package/.kiro/skills/stripe-best-practices/references/connect.md +48 -0
  126. package/.kiro/skills/stripe-best-practices/references/payments.md +79 -0
  127. package/.kiro/skills/stripe-best-practices/references/security.md +109 -0
  128. package/.kiro/skills/stripe-best-practices/references/treasury.md +16 -0
  129. package/.kiro/skills/stripe-projects/SKILL.md +139 -0
  130. package/.kiro/skills/upgrade-stripe/SKILL.md +185 -0
  131. package/.kode/skills/stripe-best-practices/SKILL.md +42 -0
  132. package/.kode/skills/stripe-best-practices/references/billing.md +36 -0
  133. package/.kode/skills/stripe-best-practices/references/connect.md +48 -0
  134. package/.kode/skills/stripe-best-practices/references/payments.md +79 -0
  135. package/.kode/skills/stripe-best-practices/references/security.md +109 -0
  136. package/.kode/skills/stripe-best-practices/references/treasury.md +16 -0
  137. package/.kode/skills/stripe-projects/SKILL.md +139 -0
  138. package/.kode/skills/upgrade-stripe/SKILL.md +185 -0
  139. package/.mcpjam/skills/stripe-best-practices/SKILL.md +42 -0
  140. package/.mcpjam/skills/stripe-best-practices/references/billing.md +36 -0
  141. package/.mcpjam/skills/stripe-best-practices/references/connect.md +48 -0
  142. package/.mcpjam/skills/stripe-best-practices/references/payments.md +79 -0
  143. package/.mcpjam/skills/stripe-best-practices/references/security.md +109 -0
  144. package/.mcpjam/skills/stripe-best-practices/references/treasury.md +16 -0
  145. package/.mcpjam/skills/stripe-projects/SKILL.md +139 -0
  146. package/.mcpjam/skills/upgrade-stripe/SKILL.md +185 -0
  147. package/.mux/skills/stripe-best-practices/SKILL.md +42 -0
  148. package/.mux/skills/stripe-best-practices/references/billing.md +36 -0
  149. package/.mux/skills/stripe-best-practices/references/connect.md +48 -0
  150. package/.mux/skills/stripe-best-practices/references/payments.md +79 -0
  151. package/.mux/skills/stripe-best-practices/references/security.md +109 -0
  152. package/.mux/skills/stripe-best-practices/references/treasury.md +16 -0
  153. package/.mux/skills/stripe-projects/SKILL.md +139 -0
  154. package/.mux/skills/upgrade-stripe/SKILL.md +185 -0
  155. package/.neovate/skills/stripe-best-practices/SKILL.md +42 -0
  156. package/.neovate/skills/stripe-best-practices/references/billing.md +36 -0
  157. package/.neovate/skills/stripe-best-practices/references/connect.md +48 -0
  158. package/.neovate/skills/stripe-best-practices/references/payments.md +79 -0
  159. package/.neovate/skills/stripe-best-practices/references/security.md +109 -0
  160. package/.neovate/skills/stripe-best-practices/references/treasury.md +16 -0
  161. package/.neovate/skills/stripe-projects/SKILL.md +139 -0
  162. package/.neovate/skills/upgrade-stripe/SKILL.md +185 -0
  163. package/.nixpacksignore +14 -0
  164. package/.openhands/skills/stripe-best-practices/SKILL.md +42 -0
  165. package/.openhands/skills/stripe-best-practices/references/billing.md +36 -0
  166. package/.openhands/skills/stripe-best-practices/references/connect.md +48 -0
  167. package/.openhands/skills/stripe-best-practices/references/payments.md +79 -0
  168. package/.openhands/skills/stripe-best-practices/references/security.md +109 -0
  169. package/.openhands/skills/stripe-best-practices/references/treasury.md +16 -0
  170. package/.openhands/skills/stripe-projects/SKILL.md +139 -0
  171. package/.openhands/skills/upgrade-stripe/SKILL.md +185 -0
  172. package/.pi/skills/stripe-best-practices/SKILL.md +42 -0
  173. package/.pi/skills/stripe-best-practices/references/billing.md +36 -0
  174. package/.pi/skills/stripe-best-practices/references/connect.md +48 -0
  175. package/.pi/skills/stripe-best-practices/references/payments.md +79 -0
  176. package/.pi/skills/stripe-best-practices/references/security.md +109 -0
  177. package/.pi/skills/stripe-best-practices/references/treasury.md +16 -0
  178. package/.pi/skills/stripe-projects/SKILL.md +139 -0
  179. package/.pi/skills/upgrade-stripe/SKILL.md +185 -0
  180. package/.pochi/skills/stripe-best-practices/SKILL.md +42 -0
  181. package/.pochi/skills/stripe-best-practices/references/billing.md +36 -0
  182. package/.pochi/skills/stripe-best-practices/references/connect.md +48 -0
  183. package/.pochi/skills/stripe-best-practices/references/payments.md +79 -0
  184. package/.pochi/skills/stripe-best-practices/references/security.md +109 -0
  185. package/.pochi/skills/stripe-best-practices/references/treasury.md +16 -0
  186. package/.pochi/skills/stripe-projects/SKILL.md +139 -0
  187. package/.pochi/skills/upgrade-stripe/SKILL.md +185 -0
  188. package/.qoder/skills/stripe-best-practices/SKILL.md +42 -0
  189. package/.qoder/skills/stripe-best-practices/references/billing.md +36 -0
  190. package/.qoder/skills/stripe-best-practices/references/connect.md +48 -0
  191. package/.qoder/skills/stripe-best-practices/references/payments.md +79 -0
  192. package/.qoder/skills/stripe-best-practices/references/security.md +109 -0
  193. package/.qoder/skills/stripe-best-practices/references/treasury.md +16 -0
  194. package/.qoder/skills/stripe-projects/SKILL.md +139 -0
  195. package/.qoder/skills/upgrade-stripe/SKILL.md +185 -0
  196. package/.qwen/skills/stripe-best-practices/SKILL.md +42 -0
  197. package/.qwen/skills/stripe-best-practices/references/billing.md +36 -0
  198. package/.qwen/skills/stripe-best-practices/references/connect.md +48 -0
  199. package/.qwen/skills/stripe-best-practices/references/payments.md +79 -0
  200. package/.qwen/skills/stripe-best-practices/references/security.md +109 -0
  201. package/.qwen/skills/stripe-best-practices/references/treasury.md +16 -0
  202. package/.qwen/skills/stripe-projects/SKILL.md +139 -0
  203. package/.qwen/skills/upgrade-stripe/SKILL.md +185 -0
  204. package/.roo/skills/stripe-best-practices/SKILL.md +42 -0
  205. package/.roo/skills/stripe-best-practices/references/billing.md +36 -0
  206. package/.roo/skills/stripe-best-practices/references/connect.md +48 -0
  207. package/.roo/skills/stripe-best-practices/references/payments.md +79 -0
  208. package/.roo/skills/stripe-best-practices/references/security.md +109 -0
  209. package/.roo/skills/stripe-best-practices/references/treasury.md +16 -0
  210. package/.roo/skills/stripe-projects/SKILL.md +139 -0
  211. package/.roo/skills/upgrade-stripe/SKILL.md +185 -0
  212. package/.trae/skills/stripe-best-practices/SKILL.md +42 -0
  213. package/.trae/skills/stripe-best-practices/references/billing.md +36 -0
  214. package/.trae/skills/stripe-best-practices/references/connect.md +48 -0
  215. package/.trae/skills/stripe-best-practices/references/payments.md +79 -0
  216. package/.trae/skills/stripe-best-practices/references/security.md +109 -0
  217. package/.trae/skills/stripe-best-practices/references/treasury.md +16 -0
  218. package/.trae/skills/stripe-projects/SKILL.md +139 -0
  219. package/.trae/skills/upgrade-stripe/SKILL.md +185 -0
  220. package/.vibe/skills/stripe-best-practices/SKILL.md +42 -0
  221. package/.vibe/skills/stripe-best-practices/references/billing.md +36 -0
  222. package/.vibe/skills/stripe-best-practices/references/connect.md +48 -0
  223. package/.vibe/skills/stripe-best-practices/references/payments.md +79 -0
  224. package/.vibe/skills/stripe-best-practices/references/security.md +109 -0
  225. package/.vibe/skills/stripe-best-practices/references/treasury.md +16 -0
  226. package/.vibe/skills/stripe-projects/SKILL.md +139 -0
  227. package/.vibe/skills/upgrade-stripe/SKILL.md +185 -0
  228. package/.windsurf/skills/stripe-best-practices/SKILL.md +42 -0
  229. package/.windsurf/skills/stripe-best-practices/references/billing.md +36 -0
  230. package/.windsurf/skills/stripe-best-practices/references/connect.md +48 -0
  231. package/.windsurf/skills/stripe-best-practices/references/payments.md +79 -0
  232. package/.windsurf/skills/stripe-best-practices/references/security.md +109 -0
  233. package/.windsurf/skills/stripe-best-practices/references/treasury.md +16 -0
  234. package/.windsurf/skills/stripe-projects/SKILL.md +139 -0
  235. package/.windsurf/skills/upgrade-stripe/SKILL.md +185 -0
  236. package/.zencoder/skills/stripe-best-practices/SKILL.md +42 -0
  237. package/.zencoder/skills/stripe-best-practices/references/billing.md +36 -0
  238. package/.zencoder/skills/stripe-best-practices/references/connect.md +48 -0
  239. package/.zencoder/skills/stripe-best-practices/references/payments.md +79 -0
  240. package/.zencoder/skills/stripe-best-practices/references/security.md +109 -0
  241. package/.zencoder/skills/stripe-best-practices/references/treasury.md +16 -0
  242. package/.zencoder/skills/stripe-projects/SKILL.md +139 -0
  243. package/.zencoder/skills/upgrade-stripe/SKILL.md +185 -0
  244. package/AUDIT.md +95 -0
  245. package/BLOCKERS.md +0 -0
  246. package/COOLIFY.md +51 -0
  247. package/MCP_SETUP.md +23 -0
  248. package/PRODUCTION_CHECKLIST.md +246 -0
  249. package/README.md +47 -0
  250. package/ROADMAP.md +91 -0
  251. package/docs/superpowers/plans/2026-05-11-availsync-frontend-sales-flow.md +2445 -0
  252. package/frontend/.env.example +2 -0
  253. package/frontend/app/admin/layout.tsx +13 -0
  254. package/frontend/app/admin/page.tsx +747 -0
  255. package/frontend/app/app/activity/page.tsx +257 -0
  256. package/frontend/app/app/agents/[agentId]/page.tsx +21 -0
  257. package/frontend/app/app/agents/page.tsx +1155 -0
  258. package/frontend/app/app/audit/page.tsx +225 -0
  259. package/frontend/app/app/availability/page.tsx +840 -0
  260. package/frontend/app/app/holds/page.tsx +262 -0
  261. package/frontend/app/app/layout.tsx +19 -0
  262. package/frontend/app/app/onboarding/page.tsx +10 -0
  263. package/frontend/app/app/onboarding/verify/page.tsx +309 -0
  264. package/frontend/app/app/page.tsx +508 -0
  265. package/frontend/app/app/settings/page.tsx +399 -0
  266. package/frontend/app/app/work/page.tsx +426 -0
  267. package/frontend/app/changelog/page.tsx +93 -0
  268. package/frontend/app/checkout/page.tsx +25 -0
  269. package/frontend/app/docs/api/page.tsx +157 -0
  270. package/frontend/app/docs/page.tsx +296 -0
  271. package/frontend/app/docs/pilot/page.tsx +127 -0
  272. package/frontend/app/docs/quickstart/page.tsx +318 -0
  273. package/frontend/app/docs/reliability/page.tsx +78 -0
  274. package/frontend/app/docs/sdk/node/page.tsx +166 -0
  275. package/frontend/app/globals.css +57 -0
  276. package/frontend/app/icon.png +0 -0
  277. package/frontend/app/layout.tsx +87 -0
  278. package/frontend/app/login/page.tsx +14 -0
  279. package/frontend/app/page.tsx +47 -0
  280. package/frontend/app/pricing/page.tsx +66 -0
  281. package/frontend/app/privacy/page.tsx +52 -0
  282. package/frontend/app/robots.ts +26 -0
  283. package/frontend/app/security/page.tsx +74 -0
  284. package/frontend/app/signup/page.tsx +14 -0
  285. package/frontend/app/sitemap.ts +14 -0
  286. package/frontend/app/terms/page.tsx +51 -0
  287. package/frontend/components/brand/AvailsyncLogo.tsx +56 -0
  288. package/frontend/components/checkout/CheckoutClient.tsx +100 -0
  289. package/frontend/components/dashboard/AgentForm.tsx +59 -0
  290. package/frontend/components/dashboard/AppShell.tsx +291 -0
  291. package/frontend/components/dashboard/AvailabilityChecker.tsx +117 -0
  292. package/frontend/components/dashboard/AvailabilityWindowForm.tsx +40 -0
  293. package/frontend/components/dashboard/HoldForm.tsx +133 -0
  294. package/frontend/components/dashboard/MetricCard.tsx +10 -0
  295. package/frontend/components/login/LoginForm.tsx +95 -0
  296. package/frontend/components/marketing/AgentCoordinationStory.tsx +1530 -0
  297. package/frontend/components/marketing/Faq.tsx +41 -0
  298. package/frontend/components/marketing/Hero.tsx +73 -0
  299. package/frontend/components/marketing/HowItWorks.tsx +28 -0
  300. package/frontend/components/marketing/ObserveModeTeaser.tsx +41 -0
  301. package/frontend/components/marketing/PricingTeaser.tsx +23 -0
  302. package/frontend/components/marketing/ProblemSolution.tsx +36 -0
  303. package/frontend/components/marketing/SiteFooter.tsx +59 -0
  304. package/frontend/components/marketing/SiteHeader.tsx +45 -0
  305. package/frontend/components/marketing/UseCases.tsx +27 -0
  306. package/frontend/components/onboarding/OnboardingClient.tsx +278 -0
  307. package/frontend/components/pricing/PricingCards.tsx +65 -0
  308. package/frontend/components/privacy/CookieConsent.tsx +230 -0
  309. package/frontend/components/privacy/CookieSettingsButton.tsx +15 -0
  310. package/frontend/components/seo/JsonLd.tsx +10 -0
  311. package/frontend/components/signup/SignupForm.tsx +55 -0
  312. package/frontend/components/ui/Badge.tsx +23 -0
  313. package/frontend/components/ui/Button.tsx +37 -0
  314. package/frontend/components/ui/Card.tsx +11 -0
  315. package/frontend/components/ui/ConfirmDialog.tsx +77 -0
  316. package/frontend/components/ui/EmptyState.tsx +24 -0
  317. package/frontend/components/ui/Input.tsx +14 -0
  318. package/frontend/components/ui/KeyDisplay.tsx +49 -0
  319. package/frontend/components/ui/Select.tsx +14 -0
  320. package/frontend/components/ui/Skeleton.tsx +24 -0
  321. package/frontend/components/ui/Tabs.tsx +19 -0
  322. package/frontend/components/ui/Textarea.tsx +14 -0
  323. package/frontend/components/ui/Toast.tsx +78 -0
  324. package/frontend/components/waitlist/WaitlistDialog.tsx +128 -0
  325. package/frontend/lib/api.ts +1282 -0
  326. package/frontend/lib/billing.ts +6 -0
  327. package/frontend/lib/cookieConsent.ts +113 -0
  328. package/frontend/lib/format.ts +16 -0
  329. package/frontend/lib/plans.ts +62 -0
  330. package/frontend/lib/schemas.ts +108 -0
  331. package/frontend/lib/seo.ts +376 -0
  332. package/frontend/lib/setupGuides.ts +630 -0
  333. package/frontend/lib/storage.ts +30 -0
  334. package/frontend/next-env.d.ts +6 -0
  335. package/frontend/next.config.mjs +13 -0
  336. package/frontend/package-lock.json +14409 -0
  337. package/frontend/package.json +41 -0
  338. package/frontend/playwright.config.ts +20 -0
  339. package/frontend/postcss.config.mjs +8 -0
  340. package/frontend/public/.gitkeep +0 -0
  341. package/frontend/public/brand/availsync-logo-board.png +0 -0
  342. package/frontend/public/brand/availsync-logo-dark.png +0 -0
  343. package/frontend/public/brand/availsync-mark-dark.png +0 -0
  344. package/frontend/public/brand/availsync-wordmark-dark.png +0 -0
  345. package/frontend/public/marketing/hero-agent-coordination.png +0 -0
  346. package/frontend/tailwind.config.ts +53 -0
  347. package/frontend/tests/smoke.spec.ts +89 -0
  348. package/frontend/tsconfig.json +23 -0
  349. package/jest.config.js +7 -0
  350. package/nixpacks.toml +11 -0
  351. package/package.json +53 -0
  352. package/packages/mcp/LICENSE +21 -0
  353. package/packages/mcp/README.md +60 -0
  354. package/packages/mcp/jest.config.cjs +8 -0
  355. package/packages/mcp/package.json +54 -0
  356. package/packages/mcp/src/helpers.ts +38 -0
  357. package/packages/mcp/src/index.test.ts +60 -0
  358. package/packages/mcp/src/index.ts +387 -0
  359. package/packages/mcp/tsconfig.json +20 -0
  360. package/packages/mcp/tsconfig.test.json +12 -0
  361. package/packages/node/LICENSE +21 -0
  362. package/packages/node/README.md +120 -0
  363. package/packages/node/jest.config.cjs +8 -0
  364. package/packages/node/package.json +46 -0
  365. package/packages/node/src/index.test.ts +360 -0
  366. package/packages/node/src/index.ts +402 -0
  367. package/packages/node/tsconfig.json +20 -0
  368. package/packages/node/tsconfig.test.json +12 -0
  369. package/plan.md +923 -0
  370. package/skills/stripe-best-practices/SKILL.md +42 -0
  371. package/skills/stripe-best-practices/references/billing.md +36 -0
  372. package/skills/stripe-best-practices/references/connect.md +48 -0
  373. package/skills/stripe-best-practices/references/payments.md +79 -0
  374. package/skills/stripe-best-practices/references/security.md +109 -0
  375. package/skills/stripe-best-practices/references/treasury.md +16 -0
  376. package/skills/stripe-projects/SKILL.md +139 -0
  377. package/skills/upgrade-stripe/SKILL.md +185 -0
  378. package/skills-lock.json +20 -0
  379. package/src/core/availability.ts +178 -0
  380. package/src/core/conflict.ts +209 -0
  381. package/src/core/work.ts +490 -0
  382. package/src/db/client.ts +17 -0
  383. package/src/db/migrations/001_init.sql +88 -0
  384. package/src/db/migrations/002_stripe.sql +2 -0
  385. package/src/db/migrations/003_workspace_auth.sql +19 -0
  386. package/src/db/migrations/004_agent_mcp_status.sql +2 -0
  387. package/src/db/migrations/005_hold_event_actor.sql +4 -0
  388. package/src/db/migrations/006_agent_activity.sql +35 -0
  389. package/src/db/migrations/007_work_coordination.sql +60 -0
  390. package/src/db/migrations/008_work_claim_leases.sql +20 -0
  391. package/src/db/migrations/009_billing_subscription_state.sql +23 -0
  392. package/src/db/migrations/010_agent_api_key_prefix.sql +10 -0
  393. package/src/db/migrations/011_org_verified_and_work_event_retention.sql +11 -0
  394. package/src/db/migrations/012_agent_enforcement_mode.sql +12 -0
  395. package/src/db/migrations/013_support_tickets.sql +21 -0
  396. package/src/db/migrations/014_paid_plan_waitlist.sql +23 -0
  397. package/src/db/migrations/015_agent_last_seen.sql +2 -0
  398. package/src/db/migrations.ts +164 -0
  399. package/src/db/run-migrations.ts +13 -0
  400. package/src/index.ts +183 -0
  401. package/src/lib/activity.ts +137 -0
  402. package/src/lib/apiKeys.ts +32 -0
  403. package/src/lib/appInfo.ts +26 -0
  404. package/src/lib/billingConfig.ts +3 -0
  405. package/src/lib/env.ts +75 -0
  406. package/src/lib/logger.ts +8 -0
  407. package/src/lib/plans.ts +204 -0
  408. package/src/mcp/server.js +5 -0
  409. package/src/mcp/server.ts +350 -0
  410. package/src/middleware/auth.ts +342 -0
  411. package/src/middleware/requestId.ts +16 -0
  412. package/src/routes/account.ts +168 -0
  413. package/src/routes/activity.ts +126 -0
  414. package/src/routes/admin.ts +514 -0
  415. package/src/routes/audit.ts +68 -0
  416. package/src/routes/auth.ts +203 -0
  417. package/src/routes/availability.ts +325 -0
  418. package/src/routes/billing.ts +406 -0
  419. package/src/routes/conflicts.ts +131 -0
  420. package/src/routes/holds.ts +437 -0
  421. package/src/routes/mcp.ts +57 -0
  422. package/src/routes/metrics.ts +39 -0
  423. package/src/routes/onboarding.ts +273 -0
  424. package/src/routes/orgs.ts +981 -0
  425. package/src/routes/preferences.ts +132 -0
  426. package/src/routes/session.ts +16 -0
  427. package/src/routes/support.ts +77 -0
  428. package/src/routes/value.ts +186 -0
  429. package/src/routes/waitlist.ts +63 -0
  430. package/src/routes/work.ts +1578 -0
  431. package/src/server.ts +36 -0
  432. package/src/types/index.ts +109 -0
  433. package/tests/integration/activity.route.test.ts +103 -0
  434. package/tests/integration/admin.route.test.ts +143 -0
  435. package/tests/integration/agent-keys.route.test.ts +237 -0
  436. package/tests/integration/availability.route.test.ts +125 -0
  437. package/tests/integration/billing.route.test.ts +393 -0
  438. package/tests/integration/conflicts.route.test.ts +131 -0
  439. package/tests/integration/flows.test.ts +154 -0
  440. package/tests/integration/helpers.ts +134 -0
  441. package/tests/integration/holds.route.test.ts +185 -0
  442. package/tests/integration/metrics.route.test.ts +100 -0
  443. package/tests/integration/onboarding.verify.route.test.ts +163 -0
  444. package/tests/integration/preferences.route.test.ts +53 -0
  445. package/tests/integration/session.route.test.ts +97 -0
  446. package/tests/integration/system.route.test.ts +92 -0
  447. package/tests/integration/value.route.test.ts +235 -0
  448. package/tests/integration/work.route.test.ts +745 -0
  449. package/tests/setup.ts +4 -0
  450. package/tests/smoke.sh +62 -0
  451. package/tests/unit/auth.test.ts +114 -0
  452. package/tests/unit/availability.test.ts +149 -0
  453. package/tests/unit/conflict.test.ts +118 -0
  454. package/tests/unit/env.test.ts +69 -0
  455. package/tests/unit/migrations.test.ts +135 -0
  456. package/tests/unit/request-id.test.ts +37 -0
  457. package/tmp-mobile-agents.png +0 -0
  458. package/tmp-next-mobile.err.log +10 -0
  459. package/tmp-next-mobile.log +5 -0
  460. package/tsconfig.json +16 -0
@@ -0,0 +1,1282 @@
1
+ import {
2
+ agentSchema,
3
+ availabilityWindowSchema,
4
+ holdSchema,
5
+ orgSchema,
6
+ slotSchema,
7
+ workClaimSchema,
8
+ workResourceSchema,
9
+ workspaceUserSchema,
10
+ type AgentType,
11
+ } from './schemas';
12
+
13
+ const API_URL = process.env.NEXT_PUBLIC_API_URL || '';
14
+
15
+ async function request<T>(path: string, options: RequestInit = {}): Promise<T> {
16
+ const response = await fetch(`${API_URL}${path}`, {
17
+ ...options,
18
+ credentials: 'include',
19
+ headers: {
20
+ 'Content-Type': 'application/json',
21
+ ...(options.headers || {}),
22
+ },
23
+ cache: 'no-store',
24
+ });
25
+ const body = await response.json().catch(() => ({}));
26
+ if (!response.ok) {
27
+ throw Object.assign(new Error(body.message || body.error || `Request failed with ${response.status}`), {
28
+ status: response.status,
29
+ body,
30
+ });
31
+ }
32
+ return body as T;
33
+ }
34
+
35
+ function authHeaders(apiKey?: string): Record<string, string> {
36
+ return apiKey ? { Authorization: `Bearer ${apiKey}` } : {};
37
+ }
38
+
39
+ export async function signupWorkspace(input: {
40
+ workspace_name: string;
41
+ email: string;
42
+ password: string;
43
+ agent: {
44
+ name: string;
45
+ agent_type: AgentType;
46
+ priority: number;
47
+ };
48
+ }) {
49
+ const response = await request<{
50
+ org: unknown;
51
+ user: unknown;
52
+ agent: unknown;
53
+ api_key: string;
54
+ }>('/v1/auth/signup', {
55
+ method: 'POST',
56
+ body: JSON.stringify(input),
57
+ });
58
+ return {
59
+ org: orgSchema.parse(response.org),
60
+ user: workspaceUserSchema.parse(response.user),
61
+ agent: agentSchema.parse(response.agent),
62
+ apiKey: response.api_key,
63
+ };
64
+ }
65
+
66
+ export async function loginWorkspace(email: string, password: string) {
67
+ return request<{ ok: boolean }>('/v1/auth/login', {
68
+ method: 'POST',
69
+ body: JSON.stringify({ email, password }),
70
+ });
71
+ }
72
+
73
+ export async function logoutWorkspace() {
74
+ return request<{ ok: boolean }>('/v1/auth/logout', { method: 'POST' });
75
+ }
76
+
77
+ export async function restoreSession() {
78
+ const response = await request<{ org: unknown; user: unknown }>('/v1/session');
79
+ return {
80
+ org: orgSchema.parse(response.org),
81
+ user: workspaceUserSchema.parse(response.user),
82
+ };
83
+ }
84
+
85
+ export async function createOrg(name: string) {
86
+ const response = await request<{ org: unknown }>('/v1/orgs', {
87
+ method: 'POST',
88
+ body: JSON.stringify({ name }),
89
+ });
90
+ return orgSchema.parse(response.org);
91
+ }
92
+
93
+ export async function createAgent(input: {
94
+ orgId: string;
95
+ name: string;
96
+ agent_type: AgentType;
97
+ priority: number;
98
+ }) {
99
+ const response = await request<{ agent: unknown; api_key: string }>(
100
+ `/v1/orgs/${input.orgId}/agents`,
101
+ {
102
+ method: 'POST',
103
+ body: JSON.stringify({
104
+ name: input.name,
105
+ agent_type: input.agent_type,
106
+ priority: input.priority,
107
+ }),
108
+ },
109
+ );
110
+ return {
111
+ agent: agentSchema.parse(response.agent),
112
+ apiKey: response.api_key,
113
+ };
114
+ }
115
+
116
+ export async function updateAgent(input: {
117
+ orgId: string;
118
+ agentId: string;
119
+ name: string;
120
+ agent_type: AgentType;
121
+ priority: number;
122
+ enforcement_mode?: 'enforce' | 'observe';
123
+ }) {
124
+ const response = await request<{ agent: unknown }>(
125
+ `/v1/orgs/${input.orgId}/agents/${input.agentId}`,
126
+ {
127
+ method: 'PUT',
128
+ body: JSON.stringify({
129
+ name: input.name,
130
+ agent_type: input.agent_type,
131
+ priority: input.priority,
132
+ enforcement_mode: input.enforcement_mode,
133
+ }),
134
+ },
135
+ );
136
+ return agentSchema.parse(response.agent);
137
+ }
138
+
139
+ export async function deleteAgent(orgId: string, agentId: string) {
140
+ const response = await request<{ agent: unknown }>(
141
+ `/v1/orgs/${orgId}/agents/${agentId}`,
142
+ { method: 'DELETE' },
143
+ );
144
+ return agentSchema.parse(response.agent);
145
+ }
146
+
147
+ export async function rotateAgentKey(orgId: string, agentId: string) {
148
+ const response = await request<{ agent: unknown; api_key: string }>(
149
+ `/v1/orgs/${orgId}/agents/${agentId}/rotate-key`,
150
+ { method: 'POST' },
151
+ );
152
+ return {
153
+ agent: agentSchema.parse(response.agent),
154
+ apiKey: response.api_key,
155
+ };
156
+ }
157
+
158
+ export async function testAgentConnection(orgId: string, agentId: string) {
159
+ return request<{
160
+ agent_id: string;
161
+ last_seen_at: string | null;
162
+ mcp_status: 'online' | 'recent' | 'offline';
163
+ mcp_last_seen_at: string | null;
164
+ mcp_client_name: string | null;
165
+ last_successful_api_call: {
166
+ activity_type: string;
167
+ endpoint: string | null;
168
+ method: string | null;
169
+ status_code: number | null;
170
+ client_name: string | null;
171
+ created_at: string;
172
+ } | null;
173
+ last_error: {
174
+ activity_type: string;
175
+ endpoint: string | null;
176
+ method: string | null;
177
+ status_code: number | null;
178
+ error_code: string | null;
179
+ error_message: string | null;
180
+ created_at: string;
181
+ } | null;
182
+ setup_readiness: {
183
+ agent_created: boolean;
184
+ availability_window_created: boolean;
185
+ mcp_heartbeat_seen: boolean;
186
+ first_availability_check: boolean;
187
+ first_conflict_preview: boolean;
188
+ first_hold_created: boolean;
189
+ first_work_check: boolean;
190
+ first_work_claim: boolean;
191
+ first_work_extend: boolean;
192
+ first_work_release: boolean;
193
+ latest_activity_at: string | null;
194
+ latest_activity_type: string | null;
195
+ mcp: {
196
+ heartbeat_seen: boolean;
197
+ status: 'online' | 'recent' | 'offline';
198
+ last_seen_at: string | null;
199
+ };
200
+ calendar: {
201
+ availability_window_created: boolean;
202
+ first_availability_check: boolean;
203
+ first_conflict_preview: boolean;
204
+ first_hold_created: boolean;
205
+ };
206
+ work: {
207
+ first_work_check: boolean;
208
+ first_work_claim: boolean;
209
+ first_work_extend: boolean;
210
+ first_work_release: boolean;
211
+ };
212
+ activity: {
213
+ latest_activity_at: string | null;
214
+ latest_activity_type: string | null;
215
+ };
216
+ };
217
+ }>(`/v1/orgs/${orgId}/agents/${agentId}/test-connection`, { method: 'POST' });
218
+ }
219
+
220
+ export type SetupTestStep = {
221
+ name: string;
222
+ status: 'pending' | 'running' | 'success' | 'warning' | 'blocked' | 'error';
223
+ latency_ms: number;
224
+ summary: string;
225
+ next_action: string | null;
226
+ details?: Record<string, unknown>;
227
+ };
228
+
229
+ export type SetupTestRun = {
230
+ run_id: string;
231
+ status: 'success' | 'warning' | 'blocked' | 'error';
232
+ steps: SetupTestStep[];
233
+ started_at: string;
234
+ finished_at: string;
235
+ };
236
+
237
+ export async function runAgentSetupTest(orgId: string, agentId: string, resourceKey = 'setup/demo-repo') {
238
+ return request<SetupTestRun>(`/v1/orgs/${orgId}/agents/${agentId}/setup-test`, {
239
+ method: 'POST',
240
+ body: JSON.stringify({ resource_key: resourceKey }),
241
+ });
242
+ }
243
+
244
+ export type OnboardingVerifyResult = {
245
+ verified_at: string;
246
+ resource_key: string;
247
+ duration_ms: number;
248
+ winner: {
249
+ agent_id: string;
250
+ agent_name: string;
251
+ agent_type: AgentType;
252
+ priority: number;
253
+ claim_id: string;
254
+ completed_at: string;
255
+ outcome: 'claimed';
256
+ };
257
+ loser: {
258
+ agent_id: string;
259
+ agent_name: string;
260
+ agent_type: AgentType;
261
+ priority: number;
262
+ claim_id: null;
263
+ completed_at: string;
264
+ outcome: 'blocked';
265
+ retry_after: string | null;
266
+ };
267
+ rule_applied: 'none' | 'priority_over_agents' | 'agent_type' | 'priority' | 'first_created';
268
+ rule_explanation: string;
269
+ tie_warning?: string;
270
+ };
271
+
272
+ export async function verifyOnboarding(input?: { agent_a_id?: string; agent_b_id?: string }) {
273
+ return request<OnboardingVerifyResult>('/v1/onboarding/verify', {
274
+ method: 'POST',
275
+ body: JSON.stringify(input ?? {}),
276
+ });
277
+ }
278
+
279
+ export async function listAgents(orgId: string) {
280
+ const response = await request<{ agents: unknown[] }>(`/v1/orgs/${orgId}/agents`);
281
+ return response.agents.map((agent) => agentSchema.parse(agent));
282
+ }
283
+
284
+ export async function createAvailabilityWindow(input: {
285
+ agent_id: string;
286
+ start_at: string;
287
+ end_at: string;
288
+ window_type: 'available' | 'focus' | 'blocked';
289
+ apiKey?: string;
290
+ }) {
291
+ const response = await request<{ window: unknown }>('/v1/availability-windows', {
292
+ method: 'POST',
293
+ headers: authHeaders(input.apiKey),
294
+ body: JSON.stringify({
295
+ agent_id: input.agent_id,
296
+ start_at: input.start_at,
297
+ end_at: input.end_at,
298
+ window_type: input.window_type,
299
+ }),
300
+ });
301
+ return availabilityWindowSchema.parse(response.window);
302
+ }
303
+
304
+ export async function updateAvailabilityWindow(input: {
305
+ window_id: string;
306
+ start_at: string;
307
+ end_at: string;
308
+ window_type: 'available' | 'focus' | 'blocked';
309
+ recurrence?: 'daily' | 'weekly' | null;
310
+ apiKey?: string;
311
+ }) {
312
+ const response = await request<{ window: unknown }>(
313
+ `/v1/availability-windows/${input.window_id}`,
314
+ {
315
+ method: 'PUT',
316
+ headers: authHeaders(input.apiKey),
317
+ body: JSON.stringify({
318
+ start_at: input.start_at,
319
+ end_at: input.end_at,
320
+ window_type: input.window_type,
321
+ recurrence: input.recurrence ?? null,
322
+ }),
323
+ },
324
+ );
325
+ return availabilityWindowSchema.parse(response.window);
326
+ }
327
+
328
+ export async function deleteAvailabilityWindow(windowId: string, apiKey?: string) {
329
+ const response = await request<{ window: unknown }>(`/v1/availability-windows/${windowId}`, {
330
+ method: 'DELETE',
331
+ headers: authHeaders(apiKey),
332
+ });
333
+ return availabilityWindowSchema.parse(response.window);
334
+ }
335
+
336
+ export async function checkAvailability(input: {
337
+ agent_id: string;
338
+ from: string;
339
+ to: string;
340
+ duration_minutes: number;
341
+ include_competing_agents?: boolean;
342
+ apiKey?: string;
343
+ }) {
344
+ const query = new URLSearchParams({
345
+ agent_id: input.agent_id,
346
+ from: input.from,
347
+ to: input.to,
348
+ duration_minutes: String(input.duration_minutes),
349
+ });
350
+ if (input.include_competing_agents !== undefined) {
351
+ query.set('include_competing_agents', String(input.include_competing_agents));
352
+ }
353
+ const response = await request<{ slots: unknown[]; total_slots: number }>(
354
+ `/v1/availability?${query.toString()}`,
355
+ { headers: authHeaders(input.apiKey) },
356
+ );
357
+ return {
358
+ slots: response.slots.map((slot) => slotSchema.parse(slot)),
359
+ totalSlots: response.total_slots,
360
+ };
361
+ }
362
+
363
+ export async function checkConflict(input: {
364
+ agent_id: string;
365
+ start_at: string;
366
+ end_at: string;
367
+ reason?: string;
368
+ metadata?: Record<string, unknown>;
369
+ apiKey?: string;
370
+ }) {
371
+ return request<{
372
+ status: 'available' | 'would_win' | 'would_lose';
373
+ would_create_hold: boolean;
374
+ winning_hold_id: string | null;
375
+ losing_hold_ids: string[];
376
+ rule_applied: string;
377
+ explanation: string;
378
+ suggested_alternatives: Array<{ start: string; end: string; confidence: number }>;
379
+ }>('/v1/conflicts/check', {
380
+ method: 'POST',
381
+ headers: authHeaders(input.apiKey),
382
+ body: JSON.stringify({
383
+ agent_id: input.agent_id,
384
+ start_at: input.start_at,
385
+ end_at: input.end_at,
386
+ reason: input.reason,
387
+ metadata: input.metadata,
388
+ }),
389
+ });
390
+ }
391
+
392
+ export async function createHold(input: {
393
+ agent_id: string;
394
+ start_at: string;
395
+ end_at: string;
396
+ reason?: string;
397
+ apiKey?: string;
398
+ }) {
399
+ const response = await request<{ hold: unknown }>('/v1/holds', {
400
+ method: 'POST',
401
+ headers: authHeaders(input.apiKey),
402
+ body: JSON.stringify({
403
+ agent_id: input.agent_id,
404
+ start_at: input.start_at,
405
+ end_at: input.end_at,
406
+ reason: input.reason,
407
+ }),
408
+ });
409
+ return holdSchema.parse(response.hold);
410
+ }
411
+
412
+ export async function listHolds(input: {
413
+ agent_id?: string;
414
+ from?: string;
415
+ to?: string;
416
+ status?: 'confirmed' | 'superseded' | 'released';
417
+ apiKey?: string;
418
+ } = {}) {
419
+ const params = new URLSearchParams();
420
+ if (input.agent_id) params.set('agent_id', input.agent_id);
421
+ if (input.from) params.set('from', input.from);
422
+ if (input.to) params.set('to', input.to);
423
+ if (input.status) params.set('status', input.status);
424
+ const response = await request<{ holds: unknown[] }>(`/v1/holds?${params.toString()}`, {
425
+ headers: authHeaders(input.apiKey),
426
+ });
427
+ return response.holds.map((hold) => holdSchema.parse(hold));
428
+ }
429
+
430
+ export async function releaseHold(holdId: string, apiKey?: string) {
431
+ const response = await request<{ hold: unknown }>(`/v1/holds/${holdId}`, {
432
+ method: 'DELETE',
433
+ headers: authHeaders(apiKey),
434
+ });
435
+ return holdSchema.parse(response.hold);
436
+ }
437
+
438
+ export async function createCheckout(input: {
439
+ plan: 'individual' | 'team';
440
+ org_id?: string;
441
+ }) {
442
+ return request<{ url?: string }>('/v1/billing/checkout', {
443
+ method: 'POST',
444
+ body: JSON.stringify({ plan: input.plan, org_id: input.org_id }),
445
+ });
446
+ }
447
+
448
+ export async function getBillingPortal() {
449
+ return request<{ url: string }>('/v1/billing/portal');
450
+ }
451
+
452
+ export async function getBillingStatus() {
453
+ return request<{
454
+ plan: 'free' | 'individual' | 'team';
455
+ subscription_status: string;
456
+ renewal_date: string | null;
457
+ cancel_at_period_end: boolean;
458
+ billing_email: string | null;
459
+ limits: {
460
+ agents: number | null;
461
+ protected_resources: number;
462
+ active_work_claims: number;
463
+ api_calls_month: number;
464
+ activity_retention_days: number;
465
+ };
466
+ usage: {
467
+ agents: number;
468
+ protected_resources: number;
469
+ active_work_claims: number;
470
+ api_calls_month: number;
471
+ activity_retention_days: number;
472
+ };
473
+ upgrade_reasons: Array<{
474
+ limit_type: string;
475
+ usage: number;
476
+ limit: number;
477
+ state: 'near' | 'reached';
478
+ upgrade_plan: 'individual' | 'team' | null;
479
+ }>;
480
+ agents_used: number;
481
+ agent_limit: number;
482
+ stripe_customer_id: boolean;
483
+ stripe_subscription_id: boolean;
484
+ billing_upgrades_enabled: boolean;
485
+ }>('/v1/billing/status');
486
+ }
487
+
488
+ export async function deleteWorkspaceAccount(input: { confirmation: 'DELETE' }) {
489
+ return request<{ ok: true }>('/v1/account/workspace', {
490
+ method: 'DELETE',
491
+ body: JSON.stringify(input),
492
+ });
493
+ }
494
+
495
+ export async function getMetricsOverview() {
496
+ return request<{
497
+ active_agents: number;
498
+ mcp_online: number;
499
+ confirmed_holds: number;
500
+ conflicts_resolved: number;
501
+ conflicts_blocked: number;
502
+ released_holds: number;
503
+ api_calls_today: number;
504
+ connected_agents: number;
505
+ recent_errors: number;
506
+ token_usage_reported: number;
507
+ active_work_claims: number;
508
+ protected_resources: number;
509
+ blocked_agent_runs: number;
510
+ released_work_slots: number;
511
+ latest_event_at: string | null;
512
+ }>('/v1/metrics/overview');
513
+ }
514
+
515
+ export type AgentHealthStatus = 'healthy' | 'quiet' | 'never_connected' | 'error';
516
+
517
+ export type ValueHealth = {
518
+ window: {
519
+ starts_at: string;
520
+ ends_at: string;
521
+ days: number;
522
+ };
523
+ summary: {
524
+ conflicts_prevented_7d: number;
525
+ blocked_work_runs_7d: number;
526
+ would_have_blocked_runs_7d: number;
527
+ calendar_conflicts_7d: number;
528
+ api_calls_7d: number;
529
+ errors_7d: number;
530
+ latest_real_activity_at: string | null;
531
+ };
532
+ agent_health: Array<{
533
+ agent_id: string;
534
+ name: string;
535
+ status: AgentHealthStatus;
536
+ last_seen_at: string | null;
537
+ last_activity_at: string | null;
538
+ last_success_at: string | null;
539
+ last_error_at: string | null;
540
+ last_error_code: string | null;
541
+ mcp_status: 'online' | 'recent' | 'offline';
542
+ }>;
543
+ next_best_action:
544
+ | 'run_verification'
545
+ | 'connect_first_agent'
546
+ | 'check_inactive_agents'
547
+ | 'review_errors'
548
+ | 'none';
549
+ };
550
+
551
+ export async function getValueHealth() {
552
+ return request<ValueHealth>('/v1/value/health');
553
+ }
554
+
555
+ export async function checkWork(input: {
556
+ agent_id: string;
557
+ resource_type: 'project' | 'repo';
558
+ resource_key: string;
559
+ label?: string;
560
+ start_at?: string;
561
+ duration_minutes?: number;
562
+ reason?: string;
563
+ metadata?: Record<string, unknown>;
564
+ apiKey?: string;
565
+ }) {
566
+ return request<{
567
+ status: 'available' | 'would_win' | 'would_lose';
568
+ resource: {
569
+ id: string | null;
570
+ resource_type: 'project' | 'repo';
571
+ resource_key: string;
572
+ label: string;
573
+ };
574
+ winning_claim_id: string | null;
575
+ losing_claim_ids: string[];
576
+ rule_applied: string;
577
+ explanation: string;
578
+ suggested_retry_at: string | null;
579
+ }>('/v1/work/check', {
580
+ method: 'POST',
581
+ headers: authHeaders(input.apiKey),
582
+ body: JSON.stringify({
583
+ agent_id: input.agent_id,
584
+ resource_type: input.resource_type,
585
+ resource_key: input.resource_key,
586
+ label: input.label,
587
+ start_at: input.start_at,
588
+ duration_minutes: input.duration_minutes,
589
+ reason: input.reason,
590
+ metadata: input.metadata,
591
+ }),
592
+ });
593
+ }
594
+
595
+ export async function claimWork(input: {
596
+ agent_id: string;
597
+ resource_type: 'project' | 'repo';
598
+ resource_key: string;
599
+ label?: string;
600
+ start_at?: string;
601
+ duration_minutes?: number;
602
+ reason?: string;
603
+ metadata?: Record<string, unknown>;
604
+ apiKey?: string;
605
+ idempotencyKey?: string;
606
+ }) {
607
+ const response = await request<{
608
+ claim: unknown;
609
+ resource: unknown;
610
+ status: 'available' | 'would_win' | 'would_lose';
611
+ superseded_claim_ids: string[];
612
+ idempotent_replay?: boolean;
613
+ }>('/v1/work/claim', {
614
+ method: 'POST',
615
+ headers: {
616
+ ...authHeaders(input.apiKey),
617
+ ...(input.idempotencyKey ? { 'Idempotency-Key': input.idempotencyKey } : {}),
618
+ },
619
+ body: JSON.stringify({
620
+ agent_id: input.agent_id,
621
+ resource_type: input.resource_type,
622
+ resource_key: input.resource_key,
623
+ label: input.label,
624
+ start_at: input.start_at,
625
+ duration_minutes: input.duration_minutes,
626
+ reason: input.reason,
627
+ metadata: input.metadata,
628
+ }),
629
+ });
630
+ return {
631
+ claim: workClaimSchema.parse(response.claim),
632
+ resource: workResourceSchema.parse(response.resource),
633
+ status: response.status,
634
+ supersededClaimIds: response.superseded_claim_ids,
635
+ idempotentReplay: Boolean(response.idempotent_replay),
636
+ };
637
+ }
638
+
639
+ export async function startWorkRun(input: {
640
+ agent_id: string;
641
+ resource_type: 'project' | 'repo';
642
+ resource_key: string;
643
+ label?: string;
644
+ start_at?: string;
645
+ duration_minutes?: number;
646
+ reason?: string;
647
+ metadata?: Record<string, unknown>;
648
+ idempotencyKey?: string;
649
+ bodyIdempotencyKey?: string;
650
+ clientName?: string;
651
+ apiKey?: string;
652
+ }) {
653
+ const response = await request<{
654
+ action: 'proceed' | 'skip_run';
655
+ claim: unknown | null;
656
+ resource: unknown;
657
+ reason: string;
658
+ retry_after: string | null;
659
+ blocking_claim: unknown | null;
660
+ status?: 'available' | 'would_win' | 'would_lose';
661
+ superseded_claim_ids?: string[];
662
+ idempotent_replay?: boolean;
663
+ extend_url?: string;
664
+ finish_url?: string;
665
+ shadow_mode?: boolean;
666
+ would_have_blocked?: boolean;
667
+ shadow_decision?: {
668
+ action: 'skip_run';
669
+ reason?: string;
670
+ retry_after?: string | null;
671
+ blocking_claim?: unknown | null;
672
+ rule_applied?: string | null;
673
+ winning_claim_id?: string | null;
674
+ } | null;
675
+ }>('/v1/work/run/start', {
676
+ method: 'POST',
677
+ headers: {
678
+ ...authHeaders(input.apiKey),
679
+ ...(input.idempotencyKey ? { 'Idempotency-Key': input.idempotencyKey } : {}),
680
+ },
681
+ body: JSON.stringify({
682
+ agent_id: input.agent_id,
683
+ resource_type: input.resource_type,
684
+ resource_key: input.resource_key,
685
+ label: input.label,
686
+ start_at: input.start_at,
687
+ duration_minutes: input.duration_minutes,
688
+ reason: input.reason,
689
+ metadata: input.metadata,
690
+ idempotency_key: input.bodyIdempotencyKey,
691
+ client_name: input.clientName,
692
+ }),
693
+ });
694
+ return {
695
+ action: response.action,
696
+ claim: response.claim ? workClaimSchema.parse(response.claim) : null,
697
+ resource: workResourceSchema.parse(response.resource),
698
+ reason: response.reason,
699
+ retryAfter: response.retry_after,
700
+ blockingClaim: response.blocking_claim ? workClaimSchema.parse(response.blocking_claim) : null,
701
+ status: response.status,
702
+ supersededClaimIds: response.superseded_claim_ids ?? [],
703
+ idempotentReplay: Boolean(response.idempotent_replay),
704
+ extendUrl: response.extend_url,
705
+ finishUrl: response.finish_url,
706
+ shadowMode: Boolean(response.shadow_mode),
707
+ wouldHaveBlocked: Boolean(response.would_have_blocked),
708
+ shadowDecision: response.shadow_decision ?? null,
709
+ };
710
+ }
711
+
712
+ export async function extendWorkRun(input: {
713
+ claimId: string;
714
+ duration_minutes?: number;
715
+ clientName?: string;
716
+ apiKey?: string;
717
+ }) {
718
+ const response = await request<{
719
+ action: 'extended';
720
+ claim: unknown;
721
+ expires_at: string;
722
+ seconds_until_expiry: number;
723
+ last_renewed_at: string;
724
+ renewal_count: number;
725
+ max_expires_at: string;
726
+ }>('/v1/work/run/extend', {
727
+ method: 'POST',
728
+ headers: authHeaders(input.apiKey),
729
+ body: JSON.stringify({
730
+ claim_id: input.claimId,
731
+ duration_minutes: input.duration_minutes,
732
+ client_name: input.clientName,
733
+ }),
734
+ });
735
+ return {
736
+ action: response.action,
737
+ claim: workClaimSchema.parse(response.claim),
738
+ expiresAt: response.expires_at,
739
+ secondsUntilExpiry: response.seconds_until_expiry,
740
+ lastRenewedAt: response.last_renewed_at,
741
+ renewalCount: response.renewal_count,
742
+ maxExpiresAt: response.max_expires_at,
743
+ };
744
+ }
745
+
746
+ export async function finishWorkRun(input: {
747
+ claimId: string;
748
+ outcome?: string;
749
+ reason?: string;
750
+ metadata?: Record<string, unknown>;
751
+ clientName?: string;
752
+ apiKey?: string;
753
+ }) {
754
+ const response = await request<{
755
+ action: 'finished' | 'already_finished';
756
+ claim: unknown | null;
757
+ }>('/v1/work/run/finish', {
758
+ method: 'POST',
759
+ headers: authHeaders(input.apiKey),
760
+ body: JSON.stringify({
761
+ claim_id: input.claimId,
762
+ outcome: input.outcome,
763
+ reason: input.reason,
764
+ metadata: input.metadata,
765
+ client_name: input.clientName,
766
+ }),
767
+ });
768
+ return {
769
+ action: response.action,
770
+ claim: response.claim ? workClaimSchema.parse(response.claim) : null,
771
+ };
772
+ }
773
+
774
+ export async function extendWorkClaim(input: {
775
+ claimId: string;
776
+ duration_minutes?: number;
777
+ apiKey?: string;
778
+ }) {
779
+ const response = await request<{
780
+ claim: unknown;
781
+ expires_at: string;
782
+ last_renewed_at: string;
783
+ renewal_count: number;
784
+ max_expires_at: string;
785
+ }>(`/v1/work/claims/${input.claimId}/extend`, {
786
+ method: 'POST',
787
+ headers: authHeaders(input.apiKey),
788
+ body: JSON.stringify({
789
+ duration_minutes: input.duration_minutes,
790
+ }),
791
+ });
792
+ return {
793
+ claim: workClaimSchema.parse(response.claim),
794
+ expiresAt: response.expires_at,
795
+ lastRenewedAt: response.last_renewed_at,
796
+ renewalCount: response.renewal_count,
797
+ maxExpiresAt: response.max_expires_at,
798
+ };
799
+ }
800
+
801
+ export async function releaseWorkClaim(claimId: string, apiKey?: string) {
802
+ const response = await request<{ claim: unknown }>(`/v1/work/claims/${claimId}`, {
803
+ method: 'DELETE',
804
+ headers: authHeaders(apiKey),
805
+ });
806
+ return workClaimSchema.parse(response.claim);
807
+ }
808
+
809
+ export async function listWorkClaims(input: {
810
+ agent_id?: string;
811
+ resource_type?: 'project' | 'repo';
812
+ resource_key?: string;
813
+ status?: 'active' | 'superseded' | 'released' | 'expired' | 'blocked';
814
+ limit?: number;
815
+ apiKey?: string;
816
+ } = {}) {
817
+ const params = new URLSearchParams();
818
+ if (input.agent_id) params.set('agent_id', input.agent_id);
819
+ if (input.resource_type) params.set('resource_type', input.resource_type);
820
+ if (input.resource_key) params.set('resource_key', input.resource_key);
821
+ if (input.status) params.set('status', input.status);
822
+ if (input.limit) params.set('limit', String(input.limit));
823
+ const response = await request<{ claims: unknown[] }>(`/v1/work/claims?${params.toString()}`, {
824
+ headers: authHeaders(input.apiKey),
825
+ });
826
+ return response.claims.map((claim) => workClaimSchema.parse(claim));
827
+ }
828
+
829
+ export async function listWorkResources() {
830
+ const response = await request<{ resources: unknown[] }>('/v1/work/resources');
831
+ return response.resources.map((resource) => workResourceSchema.parse(resource));
832
+ }
833
+
834
+ export type AdminOverview = {
835
+ total_workspaces: number;
836
+ active_workspaces: number;
837
+ free_workspaces: number;
838
+ individual_workspaces: number;
839
+ team_workspaces: number;
840
+ paid_workspaces: number;
841
+ total_agents: number;
842
+ connected_agents: number;
843
+ api_calls_today: number;
844
+ api_calls_month: number;
845
+ errors_today: number;
846
+ active_workspaces_7d: number;
847
+ quiet_agents: number;
848
+ never_connected_agents: number;
849
+ conflicts_prevented_7d: number;
850
+ active_work_claims: number;
851
+ blocked_agent_runs: number;
852
+ latest_signup_at: string | null;
853
+ estimated_mrr: number;
854
+ canceled_workspaces: number;
855
+ waitlist_leads: number;
856
+ waitlist_new: number;
857
+ };
858
+
859
+ export type WaitlistLead = {
860
+ id: string;
861
+ org_id: string | null;
862
+ org_name?: string | null;
863
+ user_id: string | null;
864
+ email: string;
865
+ plan: 'individual' | 'team';
866
+ source: 'pricing' | 'settings' | 'checkout' | 'plan_limit' | 'other' | string;
867
+ message: string;
868
+ status: 'new' | 'contacted' | 'closed';
869
+ context: Record<string, unknown>;
870
+ created_at: string;
871
+ updated_at: string;
872
+ };
873
+
874
+ export type SupportTicket = {
875
+ id: string;
876
+ org_id: string;
877
+ org_name?: string;
878
+ user_id: string | null;
879
+ email: string;
880
+ subject: string;
881
+ category: 'billing' | 'setup' | 'sdk' | 'agent_error' | 'bug' | 'other';
882
+ message: string;
883
+ status: 'open' | 'in_review' | 'closed';
884
+ priority: 'normal' | 'high';
885
+ plan: 'individual' | 'team' | string;
886
+ context: Record<string, unknown>;
887
+ created_at: string;
888
+ updated_at: string;
889
+ };
890
+
891
+ export type AdminOrgRow = {
892
+ id: string;
893
+ name: string;
894
+ owner_email: string | null;
895
+ plan: 'free' | 'individual' | 'team';
896
+ agent_limit: number;
897
+ subscription_status: string;
898
+ current_period_end: string | null;
899
+ cancel_at_period_end: boolean;
900
+ has_stripe_customer: boolean;
901
+ has_stripe_subscription: boolean;
902
+ created_at: string;
903
+ agent_count: number;
904
+ connected_agent_count: number;
905
+ active_work_claims: number;
906
+ protected_resources: number;
907
+ api_calls_24h: number;
908
+ api_calls_month: number;
909
+ errors_24h: number;
910
+ last_activity_at: string | null;
911
+ };
912
+
913
+ export type AdminOrgDetail = {
914
+ org: {
915
+ id: string;
916
+ name: string;
917
+ plan: 'free' | 'individual' | 'team';
918
+ agent_limit: number;
919
+ subscription_status: string;
920
+ current_period_end: string | null;
921
+ cancel_at_period_end: boolean;
922
+ has_stripe_customer: boolean;
923
+ has_stripe_subscription: boolean;
924
+ created_at: string;
925
+ };
926
+ users: Array<{ id: string; email: string; role: string; created_at: string }>;
927
+ agents: Array<{
928
+ id: string;
929
+ name: string;
930
+ agent_type: string;
931
+ priority: number;
932
+ mcp_last_seen_at: string | null;
933
+ mcp_client_name: string | null;
934
+ created_at: string;
935
+ last_activity_at: string | null;
936
+ last_error_at: string | null;
937
+ }>;
938
+ usage: {
939
+ agents: number;
940
+ connected_agents: number;
941
+ protected_resources: number;
942
+ api_calls_24h: number;
943
+ api_calls_month: number;
944
+ errors_24h: number;
945
+ tokens_24h: number;
946
+ quiet_agents: number;
947
+ never_connected_agents: number;
948
+ conflicts_prevented_7d: number;
949
+ active_work_claims: number;
950
+ blocked_agent_runs: number;
951
+ last_activity_at: string | null;
952
+ };
953
+ recent_activity: Array<{
954
+ id: string;
955
+ agent_id: string | null;
956
+ agent_name: string | null;
957
+ activity_type: string;
958
+ endpoint: string | null;
959
+ method: string | null;
960
+ status_code: number | null;
961
+ status: 'success' | 'error';
962
+ error_code: string | null;
963
+ error_message: string | null;
964
+ created_at: string;
965
+ }>;
966
+ recent_hold_events: Array<{
967
+ id: string;
968
+ event_type: string;
969
+ agent_id: string | null;
970
+ agent_name: string | null;
971
+ rule_applied: string | null;
972
+ actor_type: string | null;
973
+ actor_label: string | null;
974
+ created_at: string;
975
+ }>;
976
+ recent_work_events: Array<{
977
+ id: string;
978
+ event_type: string;
979
+ agent_id: string | null;
980
+ agent_name: string | null;
981
+ resource_type: string | null;
982
+ resource_key: string | null;
983
+ rule_applied: string | null;
984
+ actor_type: string | null;
985
+ actor_label: string | null;
986
+ created_at: string;
987
+ }>;
988
+ };
989
+
990
+ export type AdminSystem = {
991
+ status: 'ok' | 'degraded' | 'error';
992
+ app: {
993
+ version: string;
994
+ git_commit: string;
995
+ node_version: string;
996
+ uptime_seconds: number;
997
+ };
998
+ database: {
999
+ connected: boolean;
1000
+ };
1001
+ migrations: {
1002
+ total: number;
1003
+ applied: number;
1004
+ failed: number;
1005
+ pending: number;
1006
+ latest: {
1007
+ filename: string;
1008
+ status: string;
1009
+ finished_at: string | null;
1010
+ error_message: string | null;
1011
+ } | null;
1012
+ };
1013
+ env: {
1014
+ mode: string;
1015
+ required: Array<{ name: string; required: boolean; configured: boolean }>;
1016
+ optional: Array<{ name: string; required: boolean; configured: boolean }>;
1017
+ missing: string[];
1018
+ ok: boolean;
1019
+ };
1020
+ stripe: {
1021
+ configured: boolean;
1022
+ webhook_configured: boolean;
1023
+ individual_price_configured: boolean;
1024
+ team_price_configured: boolean;
1025
+ };
1026
+ latest_events: {
1027
+ latest_activity_at: string | null;
1028
+ latest_hold_event_at: string | null;
1029
+ latest_work_event_at: string | null;
1030
+ };
1031
+ timestamp: string;
1032
+ };
1033
+
1034
+ export async function getAdminOverview() {
1035
+ return request<AdminOverview>('/v1/admin/overview');
1036
+ }
1037
+
1038
+ export async function listAdminOrgs(input: {
1039
+ plan?: 'free' | 'individual' | 'team';
1040
+ q?: string;
1041
+ active?: 'today' | '7d' | '30d';
1042
+ limit?: number;
1043
+ offset?: number;
1044
+ } = {}) {
1045
+ const params = new URLSearchParams();
1046
+ if (input.plan) params.set('plan', input.plan);
1047
+ if (input.q) params.set('q', input.q);
1048
+ if (input.active) params.set('active', input.active);
1049
+ if (input.limit) params.set('limit', String(input.limit));
1050
+ if (input.offset) params.set('offset', String(input.offset));
1051
+
1052
+ return request<{
1053
+ orgs: AdminOrgRow[];
1054
+ limit: number;
1055
+ offset: number;
1056
+ count: number;
1057
+ total: number;
1058
+ }>(`/v1/admin/orgs?${params.toString()}`);
1059
+ }
1060
+
1061
+ export async function getAdminOrgDetail(orgId: string) {
1062
+ return request<AdminOrgDetail>(`/v1/admin/orgs/${orgId}`);
1063
+ }
1064
+
1065
+ export async function getAdminSystem() {
1066
+ return request<AdminSystem>('/v1/admin/system');
1067
+ }
1068
+
1069
+ export async function joinPaidPlanWaitlist(input: {
1070
+ email: string;
1071
+ plan: 'individual' | 'team';
1072
+ source?: WaitlistLead['source'];
1073
+ message?: string;
1074
+ context?: Record<string, unknown>;
1075
+ }) {
1076
+ return request<{ lead: WaitlistLead }>('/v1/waitlist', {
1077
+ method: 'POST',
1078
+ body: JSON.stringify(input),
1079
+ });
1080
+ }
1081
+
1082
+ export async function createSupportTicket(input: {
1083
+ email: string;
1084
+ subject: string;
1085
+ category: SupportTicket['category'];
1086
+ message: string;
1087
+ context?: Record<string, unknown>;
1088
+ }) {
1089
+ return request<{ ticket: SupportTicket }>('/v1/support/tickets', {
1090
+ method: 'POST',
1091
+ body: JSON.stringify(input),
1092
+ });
1093
+ }
1094
+
1095
+ export async function listAdminSupportTickets(input: {
1096
+ status?: SupportTicket['status'];
1097
+ plan?: 'individual' | 'team';
1098
+ q?: string;
1099
+ limit?: number;
1100
+ offset?: number;
1101
+ } = {}) {
1102
+ const params = new URLSearchParams();
1103
+ if (input.status) params.set('status', input.status);
1104
+ if (input.plan) params.set('plan', input.plan);
1105
+ if (input.q) params.set('q', input.q);
1106
+ if (input.limit) params.set('limit', String(input.limit));
1107
+ if (input.offset) params.set('offset', String(input.offset));
1108
+
1109
+ return request<{
1110
+ tickets: SupportTicket[];
1111
+ limit: number;
1112
+ offset: number;
1113
+ count: number;
1114
+ total: number;
1115
+ }>(`/v1/admin/support/tickets?${params.toString()}`);
1116
+ }
1117
+
1118
+ export async function updateAdminSupportTicket(ticketId: string, status: SupportTicket['status']) {
1119
+ return request<{ ticket: SupportTicket }>(`/v1/admin/support/tickets/${ticketId}`, {
1120
+ method: 'PUT',
1121
+ body: JSON.stringify({ status }),
1122
+ });
1123
+ }
1124
+
1125
+ export async function listAdminWaitlist(input: {
1126
+ status?: WaitlistLead['status'];
1127
+ plan?: 'individual' | 'team';
1128
+ q?: string;
1129
+ limit?: number;
1130
+ offset?: number;
1131
+ } = {}) {
1132
+ const params = new URLSearchParams();
1133
+ if (input.status) params.set('status', input.status);
1134
+ if (input.plan) params.set('plan', input.plan);
1135
+ if (input.q) params.set('q', input.q);
1136
+ if (input.limit) params.set('limit', String(input.limit));
1137
+ if (input.offset) params.set('offset', String(input.offset));
1138
+
1139
+ return request<{
1140
+ leads: WaitlistLead[];
1141
+ limit: number;
1142
+ offset: number;
1143
+ count: number;
1144
+ total: number;
1145
+ }>(`/v1/admin/waitlist?${params.toString()}`);
1146
+ }
1147
+
1148
+ export async function updateAdminWaitlistLead(leadId: string, status: WaitlistLead['status']) {
1149
+ return request<{ lead: WaitlistLead }>(`/v1/admin/waitlist/${leadId}`, {
1150
+ method: 'PUT',
1151
+ body: JSON.stringify({ status }),
1152
+ });
1153
+ }
1154
+
1155
+ export async function getActivityLog(input: {
1156
+ limit?: number;
1157
+ offset?: number;
1158
+ agent_id?: string;
1159
+ activity_type?: string;
1160
+ status?: 'success' | 'error';
1161
+ from?: string;
1162
+ to?: string;
1163
+ } = {}) {
1164
+ const params = new URLSearchParams();
1165
+ if (input.limit) params.set('limit', String(input.limit));
1166
+ if (input.offset) params.set('offset', String(input.offset));
1167
+ if (input.agent_id) params.set('agent_id', input.agent_id);
1168
+ if (input.activity_type) params.set('activity_type', input.activity_type);
1169
+ if (input.status) params.set('status', input.status);
1170
+ if (input.from) params.set('from', input.from);
1171
+ if (input.to) params.set('to', input.to);
1172
+
1173
+ return request<{
1174
+ events: Array<{
1175
+ id: string;
1176
+ org_id: string;
1177
+ agent_id: string | null;
1178
+ agent_name: string | null;
1179
+ activity_type: string;
1180
+ endpoint: string | null;
1181
+ method: string | null;
1182
+ status_code: number | null;
1183
+ status: 'success' | 'error';
1184
+ actor_type: string | null;
1185
+ actor_label: string | null;
1186
+ client_name: string | null;
1187
+ latency_ms: number | null;
1188
+ error_code: string | null;
1189
+ error_message: string | null;
1190
+ provider: string | null;
1191
+ model: string | null;
1192
+ input_tokens: number | null;
1193
+ output_tokens: number | null;
1194
+ total_tokens: number | null;
1195
+ estimated_cost_usd: string | number | null;
1196
+ metadata: Record<string, unknown> | null;
1197
+ created_at: string;
1198
+ }>;
1199
+ limit: number;
1200
+ offset: number;
1201
+ count: number;
1202
+ }>(`/v1/activity?${params.toString()}`);
1203
+ }
1204
+
1205
+ export async function getAuditLog(input: {
1206
+ limit?: number;
1207
+ offset?: number;
1208
+ agent_id?: string;
1209
+ event_type?: string;
1210
+ }) {
1211
+ const params = new URLSearchParams();
1212
+ if (input.limit) params.set('limit', String(input.limit));
1213
+ if (input.offset) params.set('offset', String(input.offset));
1214
+ if (input.agent_id) params.set('agent_id', input.agent_id);
1215
+ if (input.event_type) params.set('event_type', input.event_type);
1216
+
1217
+ return request<{
1218
+ events: Array<{
1219
+ id: string;
1220
+ hold_id: string;
1221
+ event_type: string;
1222
+ agent_id: string;
1223
+ agent_name: string;
1224
+ org_id: string;
1225
+ conflicting_hold_id: string | null;
1226
+ rule_applied: string | null;
1227
+ metadata: Record<string, unknown> | null;
1228
+ actor_type: string | null;
1229
+ actor_id: string | null;
1230
+ actor_label: string | null;
1231
+ created_at: string;
1232
+ }>;
1233
+ limit: number;
1234
+ offset: number;
1235
+ count: number;
1236
+ }>(`/v1/audit?${params.toString()}`);
1237
+ }
1238
+
1239
+ export async function getAvailabilityWindows(input: {
1240
+ agent_id: string;
1241
+ from?: string;
1242
+ to?: string;
1243
+ apiKey?: string;
1244
+ }) {
1245
+ const params = new URLSearchParams({ agent_id: input.agent_id });
1246
+ if (input.from) params.set('from', input.from);
1247
+ if (input.to) params.set('to', input.to);
1248
+
1249
+ const response = await request<{ windows: unknown[] }>(
1250
+ `/v1/availability-windows?${params.toString()}`,
1251
+ { headers: authHeaders(input.apiKey) },
1252
+ );
1253
+ return response.windows.map((w) => availabilityWindowSchema.parse(w));
1254
+ }
1255
+
1256
+ export async function getPreferences(agentId: string, apiKey?: string) {
1257
+ return request<{
1258
+ preferences: {
1259
+ agent_id: string;
1260
+ buffer_minutes_after: number;
1261
+ buffer_minutes_before: number;
1262
+ focus_blocks: Array<{ weekday: number; start_time: string; end_time: string }>;
1263
+ priority_over_agents: string[];
1264
+ booking_window_days: number;
1265
+ allow_back_to_back: boolean;
1266
+ };
1267
+ }>(`/v1/preferences/${agentId}`, {
1268
+ headers: authHeaders(apiKey),
1269
+ });
1270
+ }
1271
+
1272
+ export async function updatePreferences(
1273
+ agentId: string,
1274
+ data: Record<string, unknown>,
1275
+ apiKey?: string,
1276
+ ) {
1277
+ return request<{ preferences: unknown }>(`/v1/preferences/${agentId}`, {
1278
+ method: 'PUT',
1279
+ headers: authHeaders(apiKey),
1280
+ body: JSON.stringify(data),
1281
+ });
1282
+ }