stagent 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 (333) hide show
  1. package/LICENSE +191 -0
  2. package/README.md +399 -0
  3. package/components.json +21 -0
  4. package/dist/cli.js +171 -0
  5. package/drizzle.config.ts +12 -0
  6. package/next.config.mjs +15 -0
  7. package/package.json +114 -0
  8. package/postcss.config.mjs +8 -0
  9. package/public/icon-512.png +0 -0
  10. package/public/icon.svg +13 -0
  11. package/public/readme/home-workspace.png +0 -0
  12. package/public/readme/inbox-approvals.png +0 -0
  13. package/public/readme/workflow-blueprints.png +0 -0
  14. package/public/stagent-s-128.png +0 -0
  15. package/public/stagent-s-64.png +0 -0
  16. package/src/app/api/blueprints/[id]/instantiate/route.ts +27 -0
  17. package/src/app/api/blueprints/[id]/route.ts +39 -0
  18. package/src/app/api/blueprints/import/route.ts +68 -0
  19. package/src/app/api/blueprints/route.ts +29 -0
  20. package/src/app/api/command-palette/recent/route.ts +31 -0
  21. package/src/app/api/data/clear/route.ts +22 -0
  22. package/src/app/api/data/seed/route.ts +22 -0
  23. package/src/app/api/documents/[id]/file/route.ts +44 -0
  24. package/src/app/api/documents/[id]/route.ts +123 -0
  25. package/src/app/api/documents/route.ts +59 -0
  26. package/src/app/api/logs/stream/route.ts +101 -0
  27. package/src/app/api/notifications/[id]/route.ts +36 -0
  28. package/src/app/api/notifications/mark-all-read/route.ts +13 -0
  29. package/src/app/api/notifications/pending-approvals/route.ts +10 -0
  30. package/src/app/api/notifications/pending-approvals/stream/route.ts +101 -0
  31. package/src/app/api/notifications/route.ts +34 -0
  32. package/src/app/api/permissions/route.ts +46 -0
  33. package/src/app/api/profiles/[id]/route.ts +79 -0
  34. package/src/app/api/profiles/[id]/test/route.ts +42 -0
  35. package/src/app/api/profiles/import/route.ts +108 -0
  36. package/src/app/api/profiles/route.ts +50 -0
  37. package/src/app/api/projects/[id]/route.ts +72 -0
  38. package/src/app/api/projects/route.ts +53 -0
  39. package/src/app/api/schedules/[id]/route.ts +185 -0
  40. package/src/app/api/schedules/route.ts +117 -0
  41. package/src/app/api/settings/budgets/route.ts +24 -0
  42. package/src/app/api/settings/openai/route.ts +24 -0
  43. package/src/app/api/settings/route.ts +21 -0
  44. package/src/app/api/settings/test/route.ts +26 -0
  45. package/src/app/api/tasks/[id]/cancel/route.ts +21 -0
  46. package/src/app/api/tasks/[id]/execute/route.ts +90 -0
  47. package/src/app/api/tasks/[id]/logs/route.ts +95 -0
  48. package/src/app/api/tasks/[id]/output/route.ts +47 -0
  49. package/src/app/api/tasks/[id]/respond/route.ts +64 -0
  50. package/src/app/api/tasks/[id]/resume/route.ts +76 -0
  51. package/src/app/api/tasks/[id]/route.ts +77 -0
  52. package/src/app/api/tasks/assist/route.ts +35 -0
  53. package/src/app/api/tasks/route.ts +82 -0
  54. package/src/app/api/uploads/[id]/route.ts +81 -0
  55. package/src/app/api/uploads/cleanup/route.ts +7 -0
  56. package/src/app/api/uploads/route.ts +66 -0
  57. package/src/app/api/workflows/[id]/execute/route.ts +82 -0
  58. package/src/app/api/workflows/[id]/route.ts +133 -0
  59. package/src/app/api/workflows/[id]/status/route.ts +54 -0
  60. package/src/app/api/workflows/[id]/steps/[stepId]/retry/route.ts +22 -0
  61. package/src/app/api/workflows/route.ts +61 -0
  62. package/src/app/apple-icon.tsx +31 -0
  63. package/src/app/costs/page.tsx +256 -0
  64. package/src/app/dashboard/page.tsx +44 -0
  65. package/src/app/documents/[id]/page.tsx +46 -0
  66. package/src/app/documents/page.tsx +45 -0
  67. package/src/app/error.tsx +26 -0
  68. package/src/app/global-error.tsx +23 -0
  69. package/src/app/globals.css +733 -0
  70. package/src/app/icon.tsx +30 -0
  71. package/src/app/inbox/loading.tsx +15 -0
  72. package/src/app/inbox/page.tsx +35 -0
  73. package/src/app/layout.tsx +78 -0
  74. package/src/app/manifest.ts +32 -0
  75. package/src/app/monitor/page.tsx +37 -0
  76. package/src/app/page.tsx +162 -0
  77. package/src/app/profiles/[id]/edit/page.tsx +39 -0
  78. package/src/app/profiles/[id]/page.tsx +33 -0
  79. package/src/app/profiles/new/page.tsx +22 -0
  80. package/src/app/profiles/page.tsx +19 -0
  81. package/src/app/projects/[id]/page.tsx +134 -0
  82. package/src/app/projects/loading.tsx +17 -0
  83. package/src/app/projects/page.tsx +32 -0
  84. package/src/app/schedules/[id]/page.tsx +47 -0
  85. package/src/app/schedules/page.tsx +18 -0
  86. package/src/app/settings/loading.tsx +24 -0
  87. package/src/app/settings/page.tsx +27 -0
  88. package/src/app/tasks/[id]/page.tsx +45 -0
  89. package/src/app/tasks/new/page.tsx +27 -0
  90. package/src/app/workflows/[id]/edit/page.tsx +66 -0
  91. package/src/app/workflows/[id]/page.tsx +37 -0
  92. package/src/app/workflows/blueprints/[id]/page.tsx +40 -0
  93. package/src/app/workflows/blueprints/new/page.tsx +20 -0
  94. package/src/app/workflows/blueprints/page.tsx +11 -0
  95. package/src/app/workflows/new/page.tsx +36 -0
  96. package/src/app/workflows/page.tsx +18 -0
  97. package/src/components/charts/donut-ring.tsx +64 -0
  98. package/src/components/charts/mini-bar.tsx +75 -0
  99. package/src/components/charts/sparkline.tsx +107 -0
  100. package/src/components/costs/cost-dashboard.tsx +877 -0
  101. package/src/components/costs/cost-filters.tsx +179 -0
  102. package/src/components/dashboard/activity-feed.tsx +95 -0
  103. package/src/components/dashboard/greeting.tsx +30 -0
  104. package/src/components/dashboard/priority-queue.tsx +79 -0
  105. package/src/components/dashboard/quick-actions.tsx +62 -0
  106. package/src/components/dashboard/recent-projects.tsx +79 -0
  107. package/src/components/dashboard/stats-cards.tsx +114 -0
  108. package/src/components/documents/document-browser.tsx +235 -0
  109. package/src/components/documents/document-detail-view.tsx +367 -0
  110. package/src/components/documents/document-grid.tsx +78 -0
  111. package/src/components/documents/document-preview.tsx +68 -0
  112. package/src/components/documents/document-table.tsx +119 -0
  113. package/src/components/documents/document-upload-dialog.tsx +153 -0
  114. package/src/components/documents/types.ts +6 -0
  115. package/src/components/documents/utils.ts +57 -0
  116. package/src/components/monitoring/connection-indicator.tsx +14 -0
  117. package/src/components/monitoring/log-entry.tsx +79 -0
  118. package/src/components/monitoring/log-filters.tsx +57 -0
  119. package/src/components/monitoring/log-stream.tsx +144 -0
  120. package/src/components/monitoring/monitor-overview-wrapper.tsx +64 -0
  121. package/src/components/monitoring/monitor-overview.tsx +119 -0
  122. package/src/components/notifications/failure-action.tsx +38 -0
  123. package/src/components/notifications/inbox-list.tsx +165 -0
  124. package/src/components/notifications/message-response.tsx +196 -0
  125. package/src/components/notifications/notification-item.tsx +250 -0
  126. package/src/components/notifications/pending-approval-host.tsx +478 -0
  127. package/src/components/notifications/permission-action.tsx +37 -0
  128. package/src/components/notifications/permission-response-actions.tsx +126 -0
  129. package/src/components/notifications/unread-badge.tsx +35 -0
  130. package/src/components/profiles/profile-browser.tsx +117 -0
  131. package/src/components/profiles/profile-card.tsx +78 -0
  132. package/src/components/profiles/profile-detail-view.tsx +564 -0
  133. package/src/components/profiles/profile-form-view.tsx +480 -0
  134. package/src/components/profiles/profile-import-dialog.tsx +113 -0
  135. package/src/components/projects/project-card.tsx +58 -0
  136. package/src/components/projects/project-create-dialog.tsx +140 -0
  137. package/src/components/projects/project-detail.tsx +68 -0
  138. package/src/components/projects/project-edit-dialog.tsx +219 -0
  139. package/src/components/projects/project-list.tsx +108 -0
  140. package/src/components/schedules/schedule-create-dialog.tsx +403 -0
  141. package/src/components/schedules/schedule-detail-view.tsx +274 -0
  142. package/src/components/schedules/schedule-list.tsx +242 -0
  143. package/src/components/schedules/schedule-status-badge.tsx +16 -0
  144. package/src/components/settings/api-key-form.tsx +141 -0
  145. package/src/components/settings/auth-config-section.tsx +141 -0
  146. package/src/components/settings/auth-method-selector.tsx +67 -0
  147. package/src/components/settings/auth-status-badge.tsx +40 -0
  148. package/src/components/settings/auth-status-dot.tsx +59 -0
  149. package/src/components/settings/budget-guardrails-section.tsx +842 -0
  150. package/src/components/settings/data-management-section.tsx +141 -0
  151. package/src/components/settings/openai-runtime-section.tsx +104 -0
  152. package/src/components/settings/permissions-section.tsx +91 -0
  153. package/src/components/shared/app-sidebar.tsx +123 -0
  154. package/src/components/shared/card-skeleton.tsx +42 -0
  155. package/src/components/shared/command-palette.tsx +250 -0
  156. package/src/components/shared/confirm-dialog.tsx +52 -0
  157. package/src/components/shared/empty-state.tsx +24 -0
  158. package/src/components/shared/error-state.tsx +32 -0
  159. package/src/components/shared/form-section-card.tsx +33 -0
  160. package/src/components/shared/section-heading.tsx +14 -0
  161. package/src/components/shared/stagent-logo.tsx +21 -0
  162. package/src/components/shared/theme-toggle.tsx +46 -0
  163. package/src/components/tasks/ai-assist-panel.tsx +210 -0
  164. package/src/components/tasks/content-preview.tsx +89 -0
  165. package/src/components/tasks/empty-board.tsx +12 -0
  166. package/src/components/tasks/file-upload.tsx +120 -0
  167. package/src/components/tasks/kanban-board.tsx +275 -0
  168. package/src/components/tasks/kanban-column.tsx +75 -0
  169. package/src/components/tasks/skeleton-board.tsx +21 -0
  170. package/src/components/tasks/task-attachments.tsx +114 -0
  171. package/src/components/tasks/task-card.tsx +101 -0
  172. package/src/components/tasks/task-create-panel.tsx +360 -0
  173. package/src/components/tasks/task-detail-view.tsx +356 -0
  174. package/src/components/ui/alert-dialog.tsx +196 -0
  175. package/src/components/ui/badge.tsx +50 -0
  176. package/src/components/ui/button.tsx +71 -0
  177. package/src/components/ui/card.tsx +92 -0
  178. package/src/components/ui/checkbox.tsx +32 -0
  179. package/src/components/ui/command.tsx +184 -0
  180. package/src/components/ui/dialog.tsx +158 -0
  181. package/src/components/ui/dropdown-menu.tsx +257 -0
  182. package/src/components/ui/form.tsx +167 -0
  183. package/src/components/ui/input.tsx +21 -0
  184. package/src/components/ui/label.tsx +24 -0
  185. package/src/components/ui/popover.tsx +89 -0
  186. package/src/components/ui/progress.tsx +31 -0
  187. package/src/components/ui/radio-group.tsx +45 -0
  188. package/src/components/ui/scroll-area.tsx +58 -0
  189. package/src/components/ui/select.tsx +190 -0
  190. package/src/components/ui/separator.tsx +28 -0
  191. package/src/components/ui/sheet.tsx +143 -0
  192. package/src/components/ui/sidebar.tsx +726 -0
  193. package/src/components/ui/skeleton.tsx +13 -0
  194. package/src/components/ui/slider.tsx +63 -0
  195. package/src/components/ui/sonner.tsx +36 -0
  196. package/src/components/ui/switch.tsx +35 -0
  197. package/src/components/ui/table.tsx +116 -0
  198. package/src/components/ui/tabs.tsx +91 -0
  199. package/src/components/ui/textarea.tsx +18 -0
  200. package/src/components/ui/tooltip.tsx +57 -0
  201. package/src/components/workflows/blueprint-editor.tsx +109 -0
  202. package/src/components/workflows/blueprint-gallery.tsx +155 -0
  203. package/src/components/workflows/blueprint-preview.tsx +240 -0
  204. package/src/components/workflows/loop-status-view.tsx +272 -0
  205. package/src/components/workflows/swarm-dashboard.tsx +185 -0
  206. package/src/components/workflows/workflow-form-view.tsx +1376 -0
  207. package/src/components/workflows/workflow-list.tsx +230 -0
  208. package/src/components/workflows/workflow-status-view.tsx +477 -0
  209. package/src/hooks/use-mobile.ts +19 -0
  210. package/src/instrumentation.ts +7 -0
  211. package/src/lib/agents/claude-agent.ts +737 -0
  212. package/src/lib/agents/execution-manager.ts +27 -0
  213. package/src/lib/agents/profiles/assignment-validation.ts +75 -0
  214. package/src/lib/agents/profiles/builtins/code-reviewer/SKILL.md +21 -0
  215. package/src/lib/agents/profiles/builtins/code-reviewer/profile.yaml +28 -0
  216. package/src/lib/agents/profiles/builtins/data-analyst/SKILL.md +25 -0
  217. package/src/lib/agents/profiles/builtins/data-analyst/profile.yaml +27 -0
  218. package/src/lib/agents/profiles/builtins/devops-engineer/SKILL.md +34 -0
  219. package/src/lib/agents/profiles/builtins/devops-engineer/profile.yaml +27 -0
  220. package/src/lib/agents/profiles/builtins/document-writer/SKILL.md +16 -0
  221. package/src/lib/agents/profiles/builtins/document-writer/profile.yaml +27 -0
  222. package/src/lib/agents/profiles/builtins/general/SKILL.md +13 -0
  223. package/src/lib/agents/profiles/builtins/general/profile.yaml +18 -0
  224. package/src/lib/agents/profiles/builtins/health-fitness-coach/SKILL.md +34 -0
  225. package/src/lib/agents/profiles/builtins/health-fitness-coach/profile.yaml +26 -0
  226. package/src/lib/agents/profiles/builtins/learning-coach/SKILL.md +35 -0
  227. package/src/lib/agents/profiles/builtins/learning-coach/profile.yaml +26 -0
  228. package/src/lib/agents/profiles/builtins/project-manager/SKILL.md +26 -0
  229. package/src/lib/agents/profiles/builtins/project-manager/profile.yaml +26 -0
  230. package/src/lib/agents/profiles/builtins/researcher/SKILL.md +15 -0
  231. package/src/lib/agents/profiles/builtins/researcher/profile.yaml +27 -0
  232. package/src/lib/agents/profiles/builtins/shopping-assistant/SKILL.md +34 -0
  233. package/src/lib/agents/profiles/builtins/shopping-assistant/profile.yaml +26 -0
  234. package/src/lib/agents/profiles/builtins/technical-writer/SKILL.md +31 -0
  235. package/src/lib/agents/profiles/builtins/technical-writer/profile.yaml +29 -0
  236. package/src/lib/agents/profiles/builtins/travel-planner/SKILL.md +23 -0
  237. package/src/lib/agents/profiles/builtins/travel-planner/profile.yaml +26 -0
  238. package/src/lib/agents/profiles/builtins/wealth-manager/SKILL.md +24 -0
  239. package/src/lib/agents/profiles/builtins/wealth-manager/profile.yaml +26 -0
  240. package/src/lib/agents/profiles/compatibility.ts +109 -0
  241. package/src/lib/agents/profiles/registry.ts +293 -0
  242. package/src/lib/agents/profiles/test-runner.ts +18 -0
  243. package/src/lib/agents/profiles/test-types.ts +20 -0
  244. package/src/lib/agents/profiles/types.ts +43 -0
  245. package/src/lib/agents/router.ts +56 -0
  246. package/src/lib/agents/runtime/catalog.ts +85 -0
  247. package/src/lib/agents/runtime/claude-sdk.ts +12 -0
  248. package/src/lib/agents/runtime/claude.ts +370 -0
  249. package/src/lib/agents/runtime/codex-app-server-client.ts +289 -0
  250. package/src/lib/agents/runtime/index.ts +167 -0
  251. package/src/lib/agents/runtime/openai-codex.ts +1089 -0
  252. package/src/lib/agents/runtime/task-assist-types.ts +8 -0
  253. package/src/lib/agents/runtime/types.ts +30 -0
  254. package/src/lib/constants/settings.ts +13 -0
  255. package/src/lib/constants/status-colors.ts +44 -0
  256. package/src/lib/constants/task-status.ts +49 -0
  257. package/src/lib/data/clear.ts +63 -0
  258. package/src/lib/data/seed-data/documents.ts +715 -0
  259. package/src/lib/data/seed-data/logs.ts +195 -0
  260. package/src/lib/data/seed-data/notifications.ts +141 -0
  261. package/src/lib/data/seed-data/profiles.ts +175 -0
  262. package/src/lib/data/seed-data/projects.ts +61 -0
  263. package/src/lib/data/seed-data/schedules.ts +108 -0
  264. package/src/lib/data/seed-data/tasks.ts +341 -0
  265. package/src/lib/data/seed-data/usage-ledger.ts +130 -0
  266. package/src/lib/data/seed-data/workflows.ts +213 -0
  267. package/src/lib/data/seed.ts +129 -0
  268. package/src/lib/db/index.ts +221 -0
  269. package/src/lib/db/migrations/0000_aromatic_gargoyle.sql +59 -0
  270. package/src/lib/db/migrations/0001_first_iron_patriot.sql +6 -0
  271. package/src/lib/db/migrations/0002_add_resume_count.sql +1 -0
  272. package/src/lib/db/migrations/0003_add_settings.sql +5 -0
  273. package/src/lib/db/migrations/0004_add_documents.sql +20 -0
  274. package/src/lib/db/migrations/0005_add_document_preprocessing.sql +4 -0
  275. package/src/lib/db/migrations/0006_add_agent_profile.sql +2 -0
  276. package/src/lib/db/migrations/0007_add_usage_metering_ledger.sql +30 -0
  277. package/src/lib/db/migrations/0008_add_document_version.sql +1 -0
  278. package/src/lib/db/migrations/meta/0000_snapshot.json +416 -0
  279. package/src/lib/db/migrations/meta/0001_snapshot.json +461 -0
  280. package/src/lib/db/migrations/meta/0002_snapshot.json +469 -0
  281. package/src/lib/db/migrations/meta/_journal.json +27 -0
  282. package/src/lib/db/schema.ts +227 -0
  283. package/src/lib/documents/cleanup.ts +50 -0
  284. package/src/lib/documents/context-builder.ts +75 -0
  285. package/src/lib/documents/output-scanner.ts +166 -0
  286. package/src/lib/documents/processor.ts +120 -0
  287. package/src/lib/documents/processors/image.ts +21 -0
  288. package/src/lib/documents/processors/office.ts +36 -0
  289. package/src/lib/documents/processors/pdf.ts +12 -0
  290. package/src/lib/documents/processors/spreadsheet.ts +18 -0
  291. package/src/lib/documents/processors/text.ts +8 -0
  292. package/src/lib/documents/registry.ts +25 -0
  293. package/src/lib/notifications/actionable.ts +108 -0
  294. package/src/lib/notifications/permissions.ts +169 -0
  295. package/src/lib/queries/chart-data.ts +184 -0
  296. package/src/lib/schedules/interval-parser.ts +110 -0
  297. package/src/lib/schedules/scheduler.ts +220 -0
  298. package/src/lib/settings/auth.ts +98 -0
  299. package/src/lib/settings/budget-guardrails.ts +590 -0
  300. package/src/lib/settings/helpers.ts +23 -0
  301. package/src/lib/settings/openai-auth.ts +80 -0
  302. package/src/lib/settings/permissions.ts +102 -0
  303. package/src/lib/usage/ledger.ts +489 -0
  304. package/src/lib/usage/pricing.ts +68 -0
  305. package/src/lib/utils/crypto.ts +90 -0
  306. package/src/lib/utils/format-timestamp.ts +46 -0
  307. package/src/lib/utils/session-cleanup.ts +26 -0
  308. package/src/lib/utils/stagent-paths.ts +18 -0
  309. package/src/lib/utils.ts +6 -0
  310. package/src/lib/validators/blueprint.ts +43 -0
  311. package/src/lib/validators/profile.ts +64 -0
  312. package/src/lib/validators/project.ts +17 -0
  313. package/src/lib/validators/settings.ts +57 -0
  314. package/src/lib/validators/task.ts +30 -0
  315. package/src/lib/workflows/blueprints/builtins/code-review-pipeline.yaml +72 -0
  316. package/src/lib/workflows/blueprints/builtins/documentation-generation.yaml +62 -0
  317. package/src/lib/workflows/blueprints/builtins/investment-research.yaml +81 -0
  318. package/src/lib/workflows/blueprints/builtins/meal-planning.yaml +73 -0
  319. package/src/lib/workflows/blueprints/builtins/product-research.yaml +72 -0
  320. package/src/lib/workflows/blueprints/builtins/research-report.yaml +77 -0
  321. package/src/lib/workflows/blueprints/builtins/sprint-planning.yaml +77 -0
  322. package/src/lib/workflows/blueprints/builtins/travel-planning.yaml +80 -0
  323. package/src/lib/workflows/blueprints/instantiator.ts +131 -0
  324. package/src/lib/workflows/blueprints/registry.ts +128 -0
  325. package/src/lib/workflows/blueprints/template.ts +58 -0
  326. package/src/lib/workflows/blueprints/types.ts +38 -0
  327. package/src/lib/workflows/definition-validation.ts +121 -0
  328. package/src/lib/workflows/engine.ts +1113 -0
  329. package/src/lib/workflows/loop-executor.ts +270 -0
  330. package/src/lib/workflows/parallel.ts +55 -0
  331. package/src/lib/workflows/swarm.ts +97 -0
  332. package/src/lib/workflows/types.ts +112 -0
  333. package/tsconfig.json +41 -0
@@ -0,0 +1,141 @@
1
+ "use client";
2
+
3
+ import { useState } from "react";
4
+ import {
5
+ Card,
6
+ CardContent,
7
+ CardDescription,
8
+ CardHeader,
9
+ CardTitle,
10
+ } from "@/components/ui/card";
11
+ import { Button } from "@/components/ui/button";
12
+ import { Separator } from "@/components/ui/separator";
13
+ import { Badge } from "@/components/ui/badge";
14
+ import { ConfirmDialog } from "@/components/shared/confirm-dialog";
15
+ import { toast } from "sonner";
16
+ import { Loader2, Trash2, Database } from "lucide-react";
17
+
18
+ export function DataManagementSection() {
19
+ const [clearOpen, setClearOpen] = useState(false);
20
+ const [seedOpen, setSeedOpen] = useState(false);
21
+ const [loading, setLoading] = useState(false);
22
+
23
+ async function handleClear() {
24
+ setLoading(true);
25
+ try {
26
+ const res = await fetch("/api/data/clear", { method: "POST" });
27
+ const data = await res.json();
28
+ if (data.success) {
29
+ const d = data.deleted;
30
+ toast.success(
31
+ `Cleared ${d.projects} projects, ${d.tasks} tasks, ${d.workflows} workflows, ${d.schedules} schedules, ${d.documents} documents, ${d.agentLogs} logs, ${d.notifications} notifications, ${d.sampleProfiles} sample profiles, ${d.files} files`
32
+ );
33
+ } else {
34
+ toast.error(`Clear failed: ${data.error}`);
35
+ }
36
+ } catch {
37
+ toast.error("Clear failed — network error");
38
+ } finally {
39
+ setLoading(false);
40
+ }
41
+ }
42
+
43
+ async function handleSeed() {
44
+ setLoading(true);
45
+ try {
46
+ const res = await fetch("/api/data/seed", { method: "POST" });
47
+ const data = await res.json();
48
+ if (data.success) {
49
+ const s = data.seeded;
50
+ toast.success(
51
+ `Seeded ${s.profiles} profiles, ${s.projects} projects, ${s.tasks} tasks, ${s.workflows} workflows, ${s.schedules} schedules, ${s.documents} documents, ${s.agentLogs} logs, ${s.notifications} notifications`
52
+ );
53
+ } else {
54
+ toast.error(`Seed failed: ${data.error}`);
55
+ }
56
+ } catch {
57
+ toast.error("Seed failed — network error");
58
+ } finally {
59
+ setLoading(false);
60
+ }
61
+ }
62
+
63
+ return (
64
+ <>
65
+ <Card className="surface-card">
66
+ <CardHeader>
67
+ <CardTitle>Data Management</CardTitle>
68
+ <CardDescription>
69
+ Reset or populate your Stagent instance
70
+ </CardDescription>
71
+ </CardHeader>
72
+ <CardContent className="space-y-6">
73
+ <div className="space-y-3">
74
+ <div className="flex items-center gap-2">
75
+ <p className="text-sm text-muted-foreground">
76
+ Delete all projects, tasks, workflows, schedules, documents,
77
+ agent logs, notifications, seeded sample profiles, and uploaded
78
+ files. Authentication settings are preserved.
79
+ </p>
80
+ <Badge variant="destructive" className="shrink-0">Irreversible</Badge>
81
+ </div>
82
+ <Button
83
+ variant="destructive"
84
+ onClick={() => setClearOpen(true)}
85
+ disabled={loading}
86
+ >
87
+ {loading ? (
88
+ <Loader2 className="mr-2 h-4 w-4 animate-spin" />
89
+ ) : (
90
+ <Trash2 className="mr-2 h-4 w-4" />
91
+ )}
92
+ Clear All Data
93
+ </Button>
94
+ </div>
95
+
96
+ <Separator />
97
+
98
+ <div className="space-y-3">
99
+ <p className="text-sm text-muted-foreground">
100
+ Populate with 3 custom profiles, 5 realistic projects, 25 tasks
101
+ across varied statuses, 5 workflows, 4 schedules, 12 documents
102
+ (XLSX, PDF, DOCX, PPTX), agent logs, and notifications. Existing
103
+ data is cleared first.
104
+ </p>
105
+ <Button
106
+ variant="outline"
107
+ onClick={() => setSeedOpen(true)}
108
+ disabled={loading}
109
+ >
110
+ {loading ? (
111
+ <Loader2 className="mr-2 h-4 w-4 animate-spin" />
112
+ ) : (
113
+ <Database className="mr-2 h-4 w-4" />
114
+ )}
115
+ Seed Sample Data
116
+ </Button>
117
+ </div>
118
+ </CardContent>
119
+ </Card>
120
+
121
+ <ConfirmDialog
122
+ open={clearOpen}
123
+ onOpenChange={setClearOpen}
124
+ title="Clear all data?"
125
+ description="This will permanently delete all projects, tasks, workflows, schedules, documents, agent logs, notifications, seeded sample profiles, and uploaded files. Authentication settings will be preserved. This action cannot be undone."
126
+ confirmLabel="Clear All Data"
127
+ onConfirm={handleClear}
128
+ destructive
129
+ />
130
+
131
+ <ConfirmDialog
132
+ open={seedOpen}
133
+ onOpenChange={setSeedOpen}
134
+ title="Seed sample data?"
135
+ description="This will clear all existing data first, then populate with 3 custom profiles, 5 projects, 25 tasks, 5 workflows, 4 schedules, 12 documents (XLSX, PDF, DOCX, PPTX), agent logs, and notifications. Any current data will be lost."
136
+ confirmLabel="Seed Data"
137
+ onConfirm={handleSeed}
138
+ />
139
+ </>
140
+ );
141
+ }
@@ -0,0 +1,104 @@
1
+ "use client";
2
+
3
+ import { useEffect, useState, useCallback } from "react";
4
+ import {
5
+ Card,
6
+ CardContent,
7
+ CardDescription,
8
+ CardHeader,
9
+ CardTitle,
10
+ } from "@/components/ui/card";
11
+ import { Separator } from "@/components/ui/separator";
12
+ import { ApiKeyForm } from "./api-key-form";
13
+ import { AuthStatusBadge } from "./auth-status-badge";
14
+
15
+ interface OpenAISettings {
16
+ hasKey: boolean;
17
+ apiKeySource: "db" | "env" | "unknown";
18
+ }
19
+
20
+ export function OpenAIRuntimeSection() {
21
+ const [settings, setSettings] = useState<OpenAISettings>({
22
+ hasKey: false,
23
+ apiKeySource: "unknown",
24
+ });
25
+ const [connected, setConnected] = useState(false);
26
+
27
+ const fetchSettings = useCallback(async () => {
28
+ const res = await fetch("/api/settings/openai");
29
+ if (res.ok) {
30
+ const data = (await res.json()) as OpenAISettings;
31
+ setSettings(data);
32
+ setConnected(data.hasKey);
33
+ }
34
+ }, []);
35
+
36
+ useEffect(() => {
37
+ fetchSettings();
38
+ }, [fetchSettings]);
39
+
40
+ async function handleSaveKey(apiKey: string) {
41
+ const res = await fetch("/api/settings/openai", {
42
+ method: "POST",
43
+ headers: { "Content-Type": "application/json" },
44
+ body: JSON.stringify({ apiKey }),
45
+ });
46
+ if (res.ok) {
47
+ const data = (await res.json()) as OpenAISettings;
48
+ setSettings(data);
49
+ setConnected(true);
50
+ }
51
+ }
52
+
53
+ async function handleTestConnection() {
54
+ const res = await fetch("/api/settings/test", {
55
+ method: "POST",
56
+ headers: { "Content-Type": "application/json" },
57
+ body: JSON.stringify({ runtime: "openai-codex-app-server" }),
58
+ });
59
+ const data = await res.json();
60
+ setConnected(data.connected);
61
+ if (data.connected) {
62
+ setSettings((prev) => ({
63
+ ...prev,
64
+ apiKeySource: (data.apiKeySource || "unknown") as OpenAISettings["apiKeySource"],
65
+ }));
66
+ }
67
+ return data;
68
+ }
69
+
70
+ return (
71
+ <Card className="surface-card">
72
+ <CardHeader>
73
+ <div className="flex items-center justify-between gap-4">
74
+ <div>
75
+ <CardTitle>OpenAI Codex Runtime</CardTitle>
76
+ <CardDescription>
77
+ Configure the OpenAI API key used by the Codex app-server runtime.
78
+ </CardDescription>
79
+ </div>
80
+ <AuthStatusBadge
81
+ connected={connected}
82
+ apiKeySource={settings.apiKeySource}
83
+ />
84
+ </div>
85
+ </CardHeader>
86
+ <CardContent className="space-y-6">
87
+ <p className="text-sm text-muted-foreground">
88
+ This runtime uses `codex app-server` with resumable threads, inbox approvals, and the same workflow/schedule pipeline as Claude-backed tasks.
89
+ </p>
90
+ <Separator />
91
+ <ApiKeyForm
92
+ hasKey={settings.hasKey}
93
+ onSave={handleSaveKey}
94
+ onTest={handleTestConnection}
95
+ keyPrefix="sk-"
96
+ placeholder="sk-..."
97
+ maskedPrefix="sk-••••••"
98
+ envVarName="OPENAI_API_KEY"
99
+ testButtonLabel="Test Codex Runtime"
100
+ />
101
+ </CardContent>
102
+ </Card>
103
+ );
104
+ }
@@ -0,0 +1,91 @@
1
+ "use client";
2
+
3
+ import { useEffect, useState } from "react";
4
+ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
5
+ import { Button } from "@/components/ui/button";
6
+ import { Badge } from "@/components/ui/badge";
7
+ import { ShieldCheck, X } from "lucide-react";
8
+
9
+ export function PermissionsSection() {
10
+ const [permissions, setPermissions] = useState<string[]>([]);
11
+ const [loading, setLoading] = useState(true);
12
+ const [revoking, setRevoking] = useState<string | null>(null);
13
+
14
+ useEffect(() => {
15
+ fetchPermissions();
16
+ }, []);
17
+
18
+ async function fetchPermissions() {
19
+ try {
20
+ const res = await fetch("/api/permissions");
21
+ if (res.ok) {
22
+ const data = await res.json();
23
+ setPermissions(data.permissions ?? []);
24
+ }
25
+ } finally {
26
+ setLoading(false);
27
+ }
28
+ }
29
+
30
+ async function handleRevoke(pattern: string) {
31
+ setRevoking(pattern);
32
+ try {
33
+ const res = await fetch("/api/permissions", {
34
+ method: "DELETE",
35
+ headers: { "Content-Type": "application/json" },
36
+ body: JSON.stringify({ pattern }),
37
+ });
38
+ if (res.ok) {
39
+ setPermissions((prev) => prev.filter((p) => p !== pattern));
40
+ }
41
+ } finally {
42
+ setRevoking(null);
43
+ }
44
+ }
45
+
46
+ return (
47
+ <Card className="surface-card">
48
+ <CardHeader>
49
+ <CardTitle className="flex items-center gap-2">
50
+ <ShieldCheck className="h-5 w-5" />
51
+ Tool Permissions
52
+ </CardTitle>
53
+ <CardDescription>
54
+ Tools matching these patterns are automatically approved when agents request permission.
55
+ Revoke a pattern to require manual approval again.
56
+ </CardDescription>
57
+ </CardHeader>
58
+ <CardContent>
59
+ {loading ? (
60
+ <p className="text-sm text-muted-foreground">Loading...</p>
61
+ ) : permissions.length === 0 ? (
62
+ <p className="text-sm text-muted-foreground">
63
+ No saved permissions. Click &quot;Always Allow&quot; on a tool permission request in the Inbox to add one.
64
+ </p>
65
+ ) : (
66
+ <div className="flex flex-wrap gap-2">
67
+ {permissions.map((pattern) => (
68
+ <Badge
69
+ key={pattern}
70
+ variant="secondary"
71
+ className="font-mono text-xs px-3 py-1.5 gap-1.5"
72
+ >
73
+ {pattern}
74
+ <Button
75
+ variant="ghost"
76
+ size="icon"
77
+ className="h-4 w-4 p-0 hover:bg-transparent"
78
+ onClick={() => handleRevoke(pattern)}
79
+ disabled={revoking === pattern}
80
+ aria-label={`Revoke ${pattern}`}
81
+ >
82
+ <X className="h-3 w-3" />
83
+ </Button>
84
+ </Badge>
85
+ ))}
86
+ </div>
87
+ )}
88
+ </CardContent>
89
+ </Card>
90
+ );
91
+ }
@@ -0,0 +1,123 @@
1
+ "use client";
2
+
3
+ import Link from "next/link";
4
+ import { usePathname } from "next/navigation";
5
+ import {
6
+ Home,
7
+ LayoutDashboard,
8
+ Inbox,
9
+ Activity,
10
+ FolderKanban,
11
+ GitBranch,
12
+ FileText,
13
+ Bot,
14
+ Clock,
15
+ Wallet,
16
+ Settings,
17
+ } from "lucide-react";
18
+ import {
19
+ Sidebar,
20
+ SidebarContent,
21
+ SidebarFooter,
22
+ SidebarGroup,
23
+ SidebarGroupContent,
24
+ SidebarMenu,
25
+ SidebarMenuButton,
26
+ SidebarMenuItem,
27
+ SidebarHeader,
28
+ SidebarTrigger,
29
+ SidebarRail,
30
+ } from "@/components/ui/sidebar";
31
+ import { ThemeToggle } from "@/components/shared/theme-toggle";
32
+ import { UnreadBadge } from "@/components/notifications/unread-badge";
33
+ import { AuthStatusDot } from "@/components/settings/auth-status-dot";
34
+ import { StagentLogo } from "@/components/shared/stagent-logo";
35
+
36
+ const navItems = [
37
+ { title: "Home", href: "/", icon: Home, badge: false },
38
+ { title: "Dashboard", href: "/dashboard", icon: LayoutDashboard, badge: false, alsoMatches: ["/tasks"] },
39
+ { title: "Inbox", href: "/inbox", icon: Inbox, badge: true },
40
+ { title: "Monitor", href: "/monitor", icon: Activity, badge: false },
41
+ { title: "Projects", href: "/projects", icon: FolderKanban, badge: false },
42
+ { title: "Workflows", href: "/workflows", icon: GitBranch, badge: false },
43
+ { title: "Documents", href: "/documents", icon: FileText, badge: false },
44
+ { title: "Profiles", href: "/profiles", icon: Bot, badge: false },
45
+ { title: "Schedules", href: "/schedules", icon: Clock, badge: false },
46
+ { title: "Cost & Usage", href: "/costs", icon: Wallet, badge: false },
47
+ { title: "Settings", href: "/settings", icon: Settings, badge: false },
48
+ ];
49
+
50
+ export function AppSidebar() {
51
+ const pathname = usePathname();
52
+
53
+ return (
54
+ <Sidebar collapsible="icon" className="glass-sidebar">
55
+ <SidebarHeader className="px-4 py-3">
56
+ <div className="flex items-center justify-between">
57
+ <Link href="/" className="flex items-center gap-2 group-data-[collapsible=icon]:hidden">
58
+ <StagentLogo size={24} className="shrink-0" />
59
+ <span className="text-lg font-bold tracking-tight">Stagent</span>
60
+ </Link>
61
+ <Link href="/" className="hidden group-data-[collapsible=icon]:flex items-center justify-center" aria-label="Stagent home">
62
+ <StagentLogo size={20} />
63
+ </Link>
64
+ <SidebarTrigger className="group-data-[collapsible=icon]:hidden" />
65
+ </div>
66
+ </SidebarHeader>
67
+ <SidebarContent>
68
+ <SidebarGroup>
69
+ <SidebarGroupContent>
70
+ <SidebarMenu>
71
+ {navItems.map((item) => (
72
+ <SidebarMenuItem key={item.href}>
73
+ <SidebarMenuButton
74
+ asChild
75
+ tooltip={item.title}
76
+ isActive={
77
+ item.href === "/"
78
+ ? pathname === "/"
79
+ : pathname === item.href || pathname.startsWith(item.href + "/")
80
+ || (item.alsoMatches?.some(p => pathname.startsWith(p)) ?? false)
81
+ }
82
+ >
83
+ <Link href={item.href}>
84
+ <item.icon className="h-4 w-4" aria-hidden="true" />
85
+ <span>{item.title}</span>
86
+ {item.badge && <span className="group-data-[collapsible=icon]:hidden"><UnreadBadge /></span>}
87
+ </Link>
88
+ </SidebarMenuButton>
89
+ </SidebarMenuItem>
90
+ ))}
91
+ </SidebarMenu>
92
+ </SidebarGroupContent>
93
+ </SidebarGroup>
94
+ </SidebarContent>
95
+ <SidebarFooter className="px-4 py-3">
96
+ <div className="flex items-center justify-between group-data-[collapsible=icon]:justify-center">
97
+ <div className="flex items-center gap-2 group-data-[collapsible=icon]:hidden">
98
+ <AuthStatusDot />
99
+ </div>
100
+ <div className="flex items-center gap-1">
101
+ <button
102
+ onClick={() =>
103
+ document.dispatchEvent(
104
+ new KeyboardEvent("keydown", {
105
+ key: "k",
106
+ metaKey: true,
107
+ bubbles: true,
108
+ })
109
+ )
110
+ }
111
+ className="h-7 px-1.5 rounded-md border border-border/50 text-[10px] font-medium text-muted-foreground hover:bg-accent/50 transition-colors cursor-pointer group-data-[collapsible=icon]:hidden"
112
+ aria-label="Open command palette (⌘K)"
113
+ >
114
+ <kbd>⌘K</kbd>
115
+ </button>
116
+ <ThemeToggle />
117
+ </div>
118
+ </div>
119
+ </SidebarFooter>
120
+ <SidebarRail />
121
+ </Sidebar>
122
+ );
123
+ }
@@ -0,0 +1,42 @@
1
+ import { Card, CardHeader, CardContent } from "@/components/ui/card";
2
+ import { Skeleton } from "@/components/ui/skeleton";
3
+ import { cn } from "@/lib/utils";
4
+
5
+ interface CardSkeletonProps {
6
+ /** Width class for the title skeleton (default: "w-24") */
7
+ titleWidth?: string;
8
+ /** Number of body skeleton lines (default: 2) */
9
+ lines?: number;
10
+ /** Additional className on the Card */
11
+ className?: string;
12
+ /** Show a subtitle skeleton below the title */
13
+ subtitle?: boolean;
14
+ /** Custom skeleton content instead of default lines */
15
+ children?: React.ReactNode;
16
+ }
17
+
18
+ export function CardSkeleton({
19
+ titleWidth = "w-24",
20
+ lines = 2,
21
+ className,
22
+ subtitle,
23
+ children,
24
+ }: CardSkeletonProps) {
25
+ return (
26
+ <Card className={cn(className)}>
27
+ <CardHeader className="pb-2">
28
+ <Skeleton className={cn("h-4", titleWidth)} />
29
+ {subtitle && <Skeleton className="h-3 w-32 mt-1" />}
30
+ </CardHeader>
31
+ <CardContent className="space-y-2">
32
+ {children ??
33
+ Array.from({ length: lines }, (_, i) => (
34
+ <Skeleton
35
+ key={i}
36
+ className={cn("h-3", i === lines - 1 ? "w-3/4" : "w-full")}
37
+ />
38
+ ))}
39
+ </CardContent>
40
+ </Card>
41
+ );
42
+ }