stagent 0.9.5 → 0.10.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 (277) hide show
  1. package/README.md +5 -42
  2. package/dist/cli.js +42 -18
  3. package/docs/.coverage-gaps.json +13 -55
  4. package/docs/.last-generated +1 -1
  5. package/docs/features/provider-runtimes.md +4 -0
  6. package/docs/features/schedules.md +32 -4
  7. package/docs/features/settings.md +28 -5
  8. package/docs/features/tables.md +9 -2
  9. package/docs/features/workflows.md +10 -4
  10. package/docs/journeys/developer.md +15 -1
  11. package/docs/journeys/personal-use.md +21 -4
  12. package/docs/superpowers/plans/2026-04-07-instance-bootstrap.md +1691 -0
  13. package/docs/superpowers/plans/2026-04-08-schedule-orchestration.md +2983 -0
  14. package/docs/superpowers/plans/2026-04-11-schedule-maxturns-api-control.md +551 -0
  15. package/docs/superpowers/plans/2026-04-11-task-create-profile-validation.md +864 -0
  16. package/docs/superpowers/plans/2026-04-11-task-runtime-stagent-mcp-injection.md +739 -0
  17. package/docs/superpowers/specs/2026-04-08-chat-sse-resilience-hotfix-design.md +201 -0
  18. package/docs/superpowers/specs/2026-04-08-schedule-orchestration-design.md +371 -0
  19. package/docs/superpowers/specs/2026-04-08-swarm-visibility-design.md +213 -0
  20. package/package.json +3 -2
  21. package/src/__tests__/instrumentation-smoke.test.ts +15 -0
  22. package/src/app/analytics/page.tsx +1 -21
  23. package/src/app/api/chat/conversations/[id]/messages/route.ts +22 -1
  24. package/src/app/api/diagnostics/chat-streams/route.ts +65 -0
  25. package/src/app/api/instance/config/route.ts +41 -0
  26. package/src/app/api/instance/init/route.ts +34 -0
  27. package/src/app/api/instance/upgrade/check/route.ts +26 -0
  28. package/src/app/api/instance/upgrade/route.ts +96 -0
  29. package/src/app/api/instance/upgrade/status/route.ts +35 -0
  30. package/src/app/api/memory/route.ts +0 -11
  31. package/src/app/api/notifications/route.ts +4 -2
  32. package/src/app/api/projects/[id]/route.ts +5 -155
  33. package/src/app/api/projects/__tests__/delete-project.test.ts +10 -19
  34. package/src/app/api/schedules/[id]/execute/route.ts +111 -0
  35. package/src/app/api/schedules/[id]/route.ts +9 -1
  36. package/src/app/api/schedules/__tests__/execute-route.test.ts +118 -0
  37. package/src/app/api/schedules/route.ts +3 -12
  38. package/src/app/api/settings/openai/login/route.ts +22 -0
  39. package/src/app/api/settings/openai/logout/route.ts +7 -0
  40. package/src/app/api/settings/openai/route.ts +21 -1
  41. package/src/app/api/settings/providers/route.ts +35 -8
  42. package/src/app/api/tables/[id]/enrich/__tests__/route.test.ts +153 -0
  43. package/src/app/api/tables/[id]/enrich/plan/route.ts +98 -0
  44. package/src/app/api/tables/[id]/enrich/route.ts +147 -0
  45. package/src/app/api/tables/[id]/enrich/runs/route.ts +25 -0
  46. package/src/app/api/tasks/[id]/execute/route.ts +0 -21
  47. package/src/app/api/workflows/[id]/resume/route.ts +59 -0
  48. package/src/app/api/workflows/[id]/status/route.ts +22 -8
  49. package/src/app/api/workspace/context/route.ts +2 -0
  50. package/src/app/api/workspace/fix-data-dir/route.ts +81 -0
  51. package/src/app/chat/page.tsx +11 -0
  52. package/src/app/inbox/page.tsx +12 -5
  53. package/src/app/layout.tsx +42 -21
  54. package/src/app/page.tsx +0 -2
  55. package/src/app/settings/page.tsx +6 -9
  56. package/src/components/chat/__tests__/chat-session-provider.test.tsx +408 -0
  57. package/src/components/chat/chat-command-popover.tsx +2 -2
  58. package/src/components/chat/chat-input.tsx +2 -3
  59. package/src/components/chat/chat-session-provider.tsx +720 -0
  60. package/src/components/chat/chat-shell.tsx +92 -401
  61. package/src/components/instance/__tests__/instance-section.test.tsx +125 -0
  62. package/src/components/instance/instance-section.tsx +382 -0
  63. package/src/components/instance/upgrade-badge.tsx +219 -0
  64. package/src/components/notifications/__tests__/batch-proposal-review.test.tsx +95 -0
  65. package/src/components/notifications/__tests__/notification-item.test.tsx +106 -0
  66. package/src/components/notifications/batch-proposal-review.tsx +20 -5
  67. package/src/components/notifications/inbox-list.tsx +11 -2
  68. package/src/components/notifications/notification-item.tsx +56 -2
  69. package/src/components/notifications/pending-approval-host.tsx +56 -37
  70. package/src/components/schedules/schedule-create-sheet.tsx +19 -1
  71. package/src/components/schedules/schedule-edit-sheet.tsx +20 -1
  72. package/src/components/schedules/schedule-form.tsx +31 -0
  73. package/src/components/settings/__tests__/providers-runtimes-section.test.tsx +149 -0
  74. package/src/components/settings/auth-method-selector.tsx +19 -4
  75. package/src/components/settings/auth-status-badge.tsx +28 -3
  76. package/src/components/settings/openai-chatgpt-auth-control.tsx +278 -0
  77. package/src/components/settings/openai-runtime-section.tsx +7 -1
  78. package/src/components/settings/providers-runtimes-section.tsx +138 -19
  79. package/src/components/shared/app-sidebar.tsx +4 -3
  80. package/src/components/shared/command-palette.tsx +4 -5
  81. package/src/components/shared/theme-toggle.tsx +5 -24
  82. package/src/components/shared/workspace-indicator.tsx +61 -2
  83. package/src/components/tables/__tests__/table-enrichment-sheet.test.tsx +130 -0
  84. package/src/components/tables/table-create-sheet.tsx +4 -0
  85. package/src/components/tables/table-enrichment-runs.tsx +103 -0
  86. package/src/components/tables/table-enrichment-sheet.tsx +538 -0
  87. package/src/components/tables/table-spreadsheet.tsx +29 -5
  88. package/src/components/tables/table-toolbar.tsx +10 -1
  89. package/src/components/tasks/kanban-board.tsx +1 -0
  90. package/src/components/tasks/kanban-column.tsx +53 -14
  91. package/src/components/tasks/task-bento-grid.tsx +19 -0
  92. package/src/components/tasks/task-card.tsx +26 -3
  93. package/src/components/tasks/task-chip-bar.tsx +24 -0
  94. package/src/components/tasks/task-result-renderer.tsx +1 -1
  95. package/src/components/workflows/delay-step-body.tsx +109 -0
  96. package/src/components/workflows/hooks/use-workflow-status.ts +50 -0
  97. package/src/components/workflows/loop-status-view.tsx +1 -1
  98. package/src/components/workflows/shared/step-result.tsx +78 -0
  99. package/src/components/workflows/shared/workflow-header.tsx +141 -0
  100. package/src/components/workflows/shared/workflow-loading-skeleton.tsx +36 -0
  101. package/src/components/workflows/swarm-dashboard.tsx +2 -15
  102. package/src/components/workflows/views/loop-pattern-view.tsx +137 -0
  103. package/src/components/workflows/views/sequence-pattern-view.tsx +511 -0
  104. package/src/components/workflows/workflow-form-view.tsx +133 -16
  105. package/src/components/workflows/workflow-status-view.tsx +30 -740
  106. package/src/instrumentation-node.ts +94 -0
  107. package/src/instrumentation.ts +4 -48
  108. package/src/lib/agents/__tests__/claude-agent.test.ts +199 -0
  109. package/src/lib/agents/__tests__/execution-manager.test.ts +1 -27
  110. package/src/lib/agents/__tests__/failure-reason.test.ts +68 -0
  111. package/src/lib/agents/__tests__/learned-context.test.ts +0 -11
  112. package/src/lib/agents/__tests__/learning-session.test.ts +158 -0
  113. package/src/lib/agents/__tests__/pattern-extractor.test.ts +48 -0
  114. package/src/lib/agents/claude-agent.ts +155 -18
  115. package/src/lib/agents/execution-manager.ts +0 -35
  116. package/src/lib/agents/learned-context.ts +0 -12
  117. package/src/lib/agents/learning-session.ts +18 -5
  118. package/src/lib/agents/profiles/__tests__/registry.test.ts +6 -4
  119. package/src/lib/agents/profiles/builtins/upgrade-assistant/SKILL.md +70 -0
  120. package/src/lib/agents/profiles/builtins/upgrade-assistant/profile.yaml +32 -0
  121. package/src/lib/agents/runtime/__tests__/openai-codex-auth.test.ts +118 -0
  122. package/src/lib/agents/runtime/codex-app-server-client.ts +11 -5
  123. package/src/lib/agents/runtime/openai-codex-auth.ts +389 -0
  124. package/src/lib/agents/runtime/openai-codex.ts +29 -60
  125. package/src/lib/agents/runtime/types.ts +8 -0
  126. package/src/lib/book/chapter-mapping.ts +11 -0
  127. package/src/lib/book/content.ts +10 -0
  128. package/src/lib/chat/__tests__/active-streams.test.ts +49 -0
  129. package/src/lib/chat/__tests__/finalize-safety-net.test.ts +139 -0
  130. package/src/lib/chat/__tests__/reconcile.test.ts +137 -0
  131. package/src/lib/chat/__tests__/stream-telemetry.test.ts +151 -0
  132. package/src/lib/chat/active-streams.ts +27 -0
  133. package/src/lib/chat/codex-engine.ts +16 -17
  134. package/src/lib/chat/context-builder.ts +5 -3
  135. package/src/lib/chat/engine.ts +50 -3
  136. package/src/lib/chat/reconcile.ts +117 -0
  137. package/src/lib/chat/stagent-tools.ts +1 -0
  138. package/src/lib/chat/stream-telemetry.ts +132 -0
  139. package/src/lib/chat/suggested-prompts.ts +28 -1
  140. package/src/lib/chat/system-prompt.ts +26 -1
  141. package/src/lib/chat/tool-catalog.ts +2 -1
  142. package/src/lib/chat/tools/__tests__/enrich-table-tool.test.ts +127 -0
  143. package/src/lib/chat/tools/__tests__/schedule-tools.test.ts +261 -0
  144. package/src/lib/chat/tools/__tests__/task-tools.test.ts +352 -0
  145. package/src/lib/chat/tools/__tests__/workflow-tools-dedup.test.ts +217 -0
  146. package/src/lib/chat/tools/document-tools.ts +29 -13
  147. package/src/lib/chat/tools/helpers.ts +39 -0
  148. package/src/lib/chat/tools/notification-tools.ts +9 -5
  149. package/src/lib/chat/tools/project-tools.ts +33 -0
  150. package/src/lib/chat/tools/schedule-tools.ts +44 -11
  151. package/src/lib/chat/tools/table-tools.ts +71 -0
  152. package/src/lib/chat/tools/task-tools.ts +84 -20
  153. package/src/lib/chat/tools/workflow-tools.ts +234 -32
  154. package/src/lib/constants/settings.ts +8 -18
  155. package/src/lib/data/__tests__/clear.test.ts +56 -2
  156. package/src/lib/data/clear.ts +20 -15
  157. package/src/lib/data/delete-project.ts +171 -0
  158. package/src/lib/db/__tests__/bootstrap.test.ts +1 -1
  159. package/src/lib/db/bootstrap.ts +45 -16
  160. package/src/lib/db/index.ts +5 -0
  161. package/src/lib/db/migrations/0009_add_app_instances.sql +25 -0
  162. package/src/lib/db/migrations/0024_add_workflow_resume_at.sql +10 -0
  163. package/src/lib/db/migrations/0025_drop_app_instances.sql +3 -0
  164. package/src/lib/db/migrations/0026_drop_license.sql +3 -0
  165. package/src/lib/db/migrations/meta/_journal.json +21 -0
  166. package/src/lib/db/schema.ts +68 -23
  167. package/src/lib/environment/workspace-context.ts +13 -1
  168. package/src/lib/import/dedup.ts +4 -54
  169. package/src/lib/instance/__tests__/bootstrap.test.ts +362 -0
  170. package/src/lib/instance/__tests__/detect.test.ts +115 -0
  171. package/src/lib/instance/__tests__/fingerprint.test.ts +48 -0
  172. package/src/lib/instance/__tests__/git-ops.test.ts +95 -0
  173. package/src/lib/instance/__tests__/settings.test.ts +83 -0
  174. package/src/lib/instance/__tests__/upgrade-poller.test.ts +131 -0
  175. package/src/lib/instance/bootstrap.ts +270 -0
  176. package/src/lib/instance/detect.ts +49 -0
  177. package/src/lib/instance/fingerprint.ts +78 -0
  178. package/src/lib/instance/git-ops.ts +95 -0
  179. package/src/lib/instance/settings.ts +61 -0
  180. package/src/lib/instance/types.ts +77 -0
  181. package/src/lib/instance/upgrade-poller.ts +153 -0
  182. package/src/lib/notifications/__tests__/visibility.test.ts +51 -0
  183. package/src/lib/notifications/visibility.ts +33 -0
  184. package/src/lib/schedules/__tests__/collision-check.test.ts +93 -0
  185. package/src/lib/schedules/__tests__/config.test.ts +62 -0
  186. package/src/lib/schedules/__tests__/firing-metrics.test.ts +99 -0
  187. package/src/lib/schedules/__tests__/integration.test.ts +82 -0
  188. package/src/lib/schedules/__tests__/slot-claim.test.ts +242 -0
  189. package/src/lib/schedules/__tests__/tick-scheduler.test.ts +102 -0
  190. package/src/lib/schedules/__tests__/turn-budget.test.ts +228 -0
  191. package/src/lib/schedules/collision-check.ts +105 -0
  192. package/src/lib/schedules/config.ts +53 -0
  193. package/src/lib/schedules/scheduler.ts +232 -13
  194. package/src/lib/schedules/slot-claim.ts +105 -0
  195. package/src/lib/settings/__tests__/openai-auth.test.ts +101 -0
  196. package/src/lib/settings/__tests__/openai-login-manager.test.ts +64 -0
  197. package/src/lib/settings/__tests__/runtime-setup.test.ts +33 -0
  198. package/src/lib/settings/openai-auth.ts +105 -10
  199. package/src/lib/settings/openai-login-manager.ts +260 -0
  200. package/src/lib/settings/runtime-setup.ts +14 -4
  201. package/src/lib/tables/__tests__/enrichment-planner.test.ts +124 -0
  202. package/src/lib/tables/__tests__/enrichment.test.ts +147 -0
  203. package/src/lib/tables/enrichment-planner.ts +454 -0
  204. package/src/lib/tables/enrichment.ts +328 -0
  205. package/src/lib/tables/query-builder.ts +5 -2
  206. package/src/lib/tables/trigger-evaluator.ts +3 -2
  207. package/src/lib/theme.ts +71 -0
  208. package/src/lib/usage/ledger.ts +2 -18
  209. package/src/lib/util/__tests__/similarity.test.ts +106 -0
  210. package/src/lib/util/similarity.ts +77 -0
  211. package/src/lib/utils/format-timestamp.ts +24 -0
  212. package/src/lib/utils/stagent-paths.ts +12 -0
  213. package/src/lib/validators/__tests__/blueprint.test.ts +172 -0
  214. package/src/lib/validators/__tests__/settings.test.ts +10 -0
  215. package/src/lib/validators/blueprint.ts +70 -9
  216. package/src/lib/validators/profile.ts +2 -2
  217. package/src/lib/validators/settings.ts +3 -1
  218. package/src/lib/workflows/__tests__/delay.test.ts +196 -0
  219. package/src/lib/workflows/__tests__/engine.test.ts +8 -0
  220. package/src/lib/workflows/__tests__/loop-executor.test.ts +54 -0
  221. package/src/lib/workflows/__tests__/post-action.test.ts +108 -0
  222. package/src/lib/workflows/blueprints/instantiator.ts +22 -1
  223. package/src/lib/workflows/blueprints/types.ts +10 -2
  224. package/src/lib/workflows/delay.ts +106 -0
  225. package/src/lib/workflows/engine.ts +207 -4
  226. package/src/lib/workflows/loop-executor.ts +349 -24
  227. package/src/lib/workflows/post-action.ts +91 -0
  228. package/src/lib/workflows/types.ts +166 -1
  229. package/src/app/api/license/checkout/route.ts +0 -28
  230. package/src/app/api/license/portal/route.ts +0 -26
  231. package/src/app/api/license/route.ts +0 -89
  232. package/src/app/api/license/usage/route.ts +0 -63
  233. package/src/app/api/marketplace/browse/route.ts +0 -15
  234. package/src/app/api/marketplace/import/route.ts +0 -28
  235. package/src/app/api/marketplace/publish/route.ts +0 -40
  236. package/src/app/api/onboarding/email/route.ts +0 -53
  237. package/src/app/api/settings/telemetry/route.ts +0 -14
  238. package/src/app/api/sync/export/route.ts +0 -54
  239. package/src/app/api/sync/restore/route.ts +0 -37
  240. package/src/app/api/sync/sessions/route.ts +0 -24
  241. package/src/app/auth/callback/route.ts +0 -73
  242. package/src/app/marketplace/page.tsx +0 -19
  243. package/src/components/analytics/analytics-gate-card.tsx +0 -101
  244. package/src/components/marketplace/blueprint-card.tsx +0 -61
  245. package/src/components/marketplace/marketplace-browser.tsx +0 -131
  246. package/src/components/onboarding/email-capture-card.tsx +0 -104
  247. package/src/components/settings/activation-form.tsx +0 -95
  248. package/src/components/settings/cloud-account-section.tsx +0 -147
  249. package/src/components/settings/cloud-sync-section.tsx +0 -155
  250. package/src/components/settings/subscription-section.tsx +0 -410
  251. package/src/components/settings/telemetry-section.tsx +0 -80
  252. package/src/components/shared/premium-gate-overlay.tsx +0 -50
  253. package/src/components/shared/schedule-gate-dialog.tsx +0 -64
  254. package/src/components/shared/upgrade-banner.tsx +0 -112
  255. package/src/hooks/use-supabase-auth.ts +0 -79
  256. package/src/lib/billing/email.ts +0 -54
  257. package/src/lib/billing/products.ts +0 -80
  258. package/src/lib/billing/stripe.ts +0 -101
  259. package/src/lib/cloud/supabase-browser.ts +0 -32
  260. package/src/lib/cloud/supabase-client.ts +0 -56
  261. package/src/lib/license/__tests__/features.test.ts +0 -56
  262. package/src/lib/license/__tests__/key-format.test.ts +0 -88
  263. package/src/lib/license/__tests__/manager.test.ts +0 -64
  264. package/src/lib/license/__tests__/tier-limits.test.ts +0 -79
  265. package/src/lib/license/cloud-validation.ts +0 -60
  266. package/src/lib/license/features.ts +0 -44
  267. package/src/lib/license/key-format.ts +0 -101
  268. package/src/lib/license/limit-check.ts +0 -111
  269. package/src/lib/license/limit-queries.ts +0 -51
  270. package/src/lib/license/manager.ts +0 -345
  271. package/src/lib/license/notifications.ts +0 -59
  272. package/src/lib/license/tier-limits.ts +0 -71
  273. package/src/lib/marketplace/marketplace-client.ts +0 -107
  274. package/src/lib/sync/cloud-sync.ts +0 -235
  275. package/src/lib/telemetry/conversion-events.ts +0 -71
  276. package/src/lib/telemetry/queue.ts +0 -122
  277. package/src/lib/validators/license.ts +0 -33
@@ -0,0 +1,81 @@
1
+ import { NextResponse } from "next/server";
2
+ import { basename, join } from "path";
3
+ import { homedir } from "os";
4
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from "fs";
5
+ import Database from "better-sqlite3";
6
+ import { getLaunchCwd } from "@/lib/environment/workspace-context";
7
+ import { isDevMode, isPrivateInstance } from "@/lib/instance/detect";
8
+ import { bootstrapStagentDatabase } from "@/lib/db/bootstrap";
9
+
10
+ export const dynamic = "force-dynamic";
11
+
12
+ /**
13
+ * POST /api/workspace/fix-data-dir
14
+ *
15
+ * Fixes a data-dir mismatch for domain clones by:
16
+ * 1. Deriving the correct STAGENT_DATA_DIR from the folder name
17
+ * 2. Writing it to .env.local (alongside STAGENT_CLOUD_DISABLED=true)
18
+ * 3. Creating the data dir + bootstrapping an empty database there
19
+ *
20
+ * Requires a dev server restart to take effect.
21
+ */
22
+ export async function POST() {
23
+ const cwd = getLaunchCwd();
24
+
25
+ // Guard: main repo doesn't need fixing
26
+ if (isDevMode(cwd)) {
27
+ return NextResponse.json(
28
+ { error: "Main dev repo does not need a data-dir fix" },
29
+ { status: 400 }
30
+ );
31
+ }
32
+
33
+ // Guard: already isolated
34
+ if (isPrivateInstance()) {
35
+ return NextResponse.json(
36
+ { error: "STAGENT_DATA_DIR is already set to a non-default path" },
37
+ { status: 400 }
38
+ );
39
+ }
40
+
41
+ const folderName = basename(cwd);
42
+ const home = homedir();
43
+ // stagent-wealth → ~/.stagent-wealth, stagent-growth → ~/.stagent-growth
44
+ const dataDir = join(home, `.${folderName}`);
45
+ const displayDataDir = `~/.${folderName}`;
46
+
47
+ // --- 1. Update .env.local ---
48
+ const envLocalPath = join(cwd, ".env.local");
49
+ let envContent = "";
50
+ if (existsSync(envLocalPath)) {
51
+ envContent = readFileSync(envLocalPath, "utf-8");
52
+ }
53
+
54
+ // Replace or append STAGENT_DATA_DIR
55
+ if (/^STAGENT_DATA_DIR=.*/m.test(envContent)) {
56
+ envContent = envContent.replace(
57
+ /^STAGENT_DATA_DIR=.*/m,
58
+ `STAGENT_DATA_DIR=${dataDir}`
59
+ );
60
+ } else {
61
+ envContent = envContent.trimEnd() + `\nSTAGENT_DATA_DIR=${dataDir}\n`;
62
+ }
63
+
64
+ writeFileSync(envLocalPath, envContent, "utf-8");
65
+
66
+ // --- 2. Create data dir + bootstrap DB ---
67
+ mkdirSync(dataDir, { recursive: true });
68
+ const dbPath = join(dataDir, "stagent.db");
69
+ const sqlite = new Database(dbPath);
70
+ sqlite.pragma("journal_mode = WAL");
71
+ sqlite.pragma("foreign_keys = ON");
72
+ bootstrapStagentDatabase(sqlite);
73
+ sqlite.close();
74
+
75
+ return NextResponse.json({
76
+ success: true,
77
+ dataDir: displayDataDir,
78
+ envLocalPath,
79
+ needsRestart: true,
80
+ });
81
+ }
@@ -1,5 +1,6 @@
1
1
  import { listConversations } from "@/lib/data/chat";
2
2
  import { getPromptCategories } from "@/lib/chat/suggested-prompts";
3
+ import { reconcileStreamingMessages } from "@/lib/chat/reconcile";
3
4
  import { ChatShell } from "@/components/chat/chat-shell";
4
5
 
5
6
  export const dynamic = "force-dynamic";
@@ -10,6 +11,16 @@ export default async function ChatPage({
10
11
  searchParams: Promise<{ c?: string }>;
11
12
  }) {
12
13
  const params = await searchParams;
14
+
15
+ // Safety-net sweep: finalize any orphaned streaming rows from crashes,
16
+ // disconnects, or prior releases. Fire-and-forget-ish — we await so the
17
+ // UI never renders stale `streaming` placeholders, but errors are swallowed.
18
+ try {
19
+ await reconcileStreamingMessages();
20
+ } catch (err) {
21
+ console.error("[chat] reconcileStreamingMessages failed:", err);
22
+ }
23
+
13
24
  const [conversations, promptCategories] = await Promise.all([
14
25
  listConversations({ status: "active" }),
15
26
  getPromptCategories(),
@@ -4,6 +4,10 @@ import { desc, eq, and, gte } from "drizzle-orm";
4
4
  import { InboxList } from "@/components/notifications/inbox-list";
5
5
  import { GovernanceStats } from "@/components/notifications/governance-stats";
6
6
  import { PageShell } from "@/components/shared/page-shell";
7
+ import {
8
+ buildDefaultNotificationVisibilityCondition,
9
+ filterDefaultVisibleNotifications,
10
+ } from "@/lib/notifications/visibility";
7
11
 
8
12
  export const dynamic = "force-dynamic";
9
13
 
@@ -16,6 +20,7 @@ export default async function InboxPage() {
16
20
  db
17
21
  .select()
18
22
  .from(notifications)
23
+ .where(buildDefaultNotificationVisibilityCondition())
19
24
  .orderBy(desc(notifications.createdAt))
20
25
  .limit(100),
21
26
  db
@@ -53,11 +58,13 @@ export default async function InboxPage() {
53
58
  ]);
54
59
 
55
60
  // Serialize Date objects for client component consumption
56
- const initialNotifications = rows.map((n) => ({
57
- ...n,
58
- createdAt: n.createdAt.toISOString(),
59
- respondedAt: n.respondedAt?.toISOString() ?? null,
60
- }));
61
+ const initialNotifications = filterDefaultVisibleNotifications(
62
+ rows.map((n) => ({
63
+ ...n,
64
+ createdAt: n.createdAt.toISOString(),
65
+ respondedAt: n.respondedAt?.toISOString() ?? null,
66
+ }))
67
+ );
61
68
 
62
69
  return (
63
70
  <PageShell
@@ -1,5 +1,5 @@
1
1
  import type { Metadata } from "next";
2
- import Script from "next/script";
2
+ import { cookies } from "next/headers";
3
3
  import { Inter, JetBrains_Mono } from "next/font/google";
4
4
  import { SidebarProvider, SidebarInset } from "@/components/ui/sidebar";
5
5
  import { TooltipProvider } from "@/components/ui/tooltip";
@@ -8,6 +8,13 @@ import { CommandPalette } from "@/components/shared/command-palette";
8
8
  import { PendingApprovalHost } from "@/components/notifications/pending-approval-host";
9
9
  import { GlobalShortcuts } from "@/components/shared/global-shortcuts";
10
10
  import { Toaster } from "@/components/ui/sonner";
11
+ import { ChatSessionProvider } from "@/components/chat/chat-session-provider";
12
+ import {
13
+ DEFAULT_THEME,
14
+ THEME_COOKIE,
15
+ isResolvedTheme,
16
+ type ResolvedTheme,
17
+ } from "@/lib/theme";
11
18
  import "./globals.css";
12
19
 
13
20
  const inter = Inter({
@@ -55,22 +62,34 @@ const CRITICAL_THEME_CSS = `
55
62
  html { background: var(--background); font-size: 14px; }
56
63
  `.replace(/\s+/g, " ").trim();
57
64
 
58
- // Light-first: defaults to 'light' when no localStorage preference exists.
59
- // Static theme initialization script — no user input, safe from XSS.
60
- const THEME_INIT_SCRIPT = `(function(){try{var d=document.documentElement;var s=localStorage.getItem('stagent-theme');var t=s==='dark'||s==='light'?s:'light';d.classList.toggle('dark',t==='dark');d.dataset.theme=t;d.style.colorScheme=t;d.style.backgroundColor=t==='dark'?'oklch(0.14 0.02 250)':'oklch(0.985 0.004 250)';document.cookie='stagent-theme='+t+';path=/;max-age=31536000;SameSite=Lax';}catch(e){}})()`;
61
-
62
- export default function RootLayout({
65
+ export default async function RootLayout({
63
66
  children,
64
67
  }: {
65
68
  children: React.ReactNode;
66
69
  }) {
70
+ // Resolve theme server-side from the stagent-theme cookie. Every client-side
71
+ // theme toggle writes this cookie (see src/lib/theme.ts), so SSR stays in
72
+ // sync with the user's preference and there is no FOUC — and no pre-hydration
73
+ // <script> tag, which is what React 19 warns about.
74
+ const cookieStore = await cookies();
75
+ const cookieValue = cookieStore.get(THEME_COOKIE)?.value;
76
+ const theme: ResolvedTheme = isResolvedTheme(cookieValue)
77
+ ? cookieValue
78
+ : DEFAULT_THEME;
79
+ const htmlClass = theme === "dark" ? "dark" : undefined;
80
+ const htmlBackground =
81
+ theme === "dark" ? "oklch(0.14 0.02 250)" : "oklch(0.985 0.004 250)";
67
82
  return (
68
- <html lang="en" suppressHydrationWarning>
83
+ <html
84
+ lang="en"
85
+ className={htmlClass}
86
+ data-theme={theme}
87
+ style={{ colorScheme: theme, backgroundColor: htmlBackground }}
88
+ suppressHydrationWarning
89
+ >
69
90
  <head>
70
91
  {/* Static CSS — no user input, safe from XSS */}
71
92
  <style dangerouslySetInnerHTML={{ __html: CRITICAL_THEME_CSS }} />
72
- {/* Theme bootstrap — runs before paint to prevent FOUC */}
73
- <Script id="theme-init" strategy="beforeInteractive">{THEME_INIT_SCRIPT}</Script>
74
93
  </head>
75
94
  <body
76
95
  className={`${inter.variable} ${jetbrainsMono.variable} font-sans antialiased bg-background text-foreground`}
@@ -79,18 +98,20 @@ export default function RootLayout({
79
98
  Skip to main content
80
99
  </a>
81
100
  <TooltipProvider>
82
- <SidebarProvider>
83
- <AppSidebar />
84
- <SidebarInset className="min-w-0">
85
- <main id="main-content">
86
- {children}
87
- </main>
88
- </SidebarInset>
89
- </SidebarProvider>
90
- <PendingApprovalHost />
91
- <CommandPalette />
92
- <GlobalShortcuts />
93
- <Toaster />
101
+ <ChatSessionProvider>
102
+ <SidebarProvider>
103
+ <AppSidebar />
104
+ <SidebarInset className="min-w-0">
105
+ <main id="main-content">
106
+ {children}
107
+ </main>
108
+ </SidebarInset>
109
+ </SidebarProvider>
110
+ <PendingApprovalHost />
111
+ <CommandPalette />
112
+ <GlobalShortcuts />
113
+ <Toaster />
114
+ </ChatSessionProvider>
94
115
  </TooltipProvider>
95
116
  </body>
96
117
  </html>
package/src/app/page.tsx CHANGED
@@ -12,7 +12,6 @@ import { QuickActions } from "@/components/dashboard/quick-actions";
12
12
  import { RecentProjects } from "@/components/dashboard/recent-projects";
13
13
  import type { RecentProject } from "@/components/dashboard/recent-projects";
14
14
  import { WelcomeLanding } from "@/components/dashboard/welcome-landing";
15
- import { EmailCaptureCard } from "@/components/onboarding/email-capture-card";
16
15
  import { ActivationChecklist } from "@/components/onboarding/activation-checklist";
17
16
  import {
18
17
  getCompletionsByDay,
@@ -107,7 +106,6 @@ export default async function HomePage() {
107
106
  return (
108
107
  <div className="bg-background min-h-screen p-4 sm:p-6">
109
108
  <div className="surface-page-shell min-h-[calc(100dvh-2rem)] rounded-xl p-5 sm:p-6 lg:p-7 space-y-6">
110
- <EmailCaptureCard />
111
109
  <WelcomeLanding />
112
110
  </div>
113
111
  </div>
@@ -1,7 +1,3 @@
1
- import { SubscriptionSection } from "@/components/settings/subscription-section";
2
- import { CloudAccountSection } from "@/components/settings/cloud-account-section";
3
- import { CloudSyncSection } from "@/components/settings/cloud-sync-section";
4
- import { TelemetrySection } from "@/components/settings/telemetry-section";
5
1
  import { ProvidersAndRuntimesSection } from "@/components/settings/providers-runtimes-section";
6
2
  import { PermissionsSections } from "@/components/settings/permissions-sections";
7
3
  import { DataManagementSection } from "@/components/settings/data-management-section";
@@ -14,17 +10,19 @@ import { WebSearchSection } from "@/components/settings/web-search-section";
14
10
  import { LearningContextSection } from "@/components/settings/learning-context-section";
15
11
  import { OllamaSection } from "@/components/settings/ollama-section";
16
12
  import { ChannelsSection } from "@/components/settings/channels-section";
13
+ import { InstanceSection } from "@/components/instance/instance-section";
17
14
  import { PageShell } from "@/components/shared/page-shell";
18
15
 
19
16
  export const dynamic = "force-dynamic";
20
17
 
21
18
  export default function SettingsPage() {
22
19
  return (
23
- <PageShell title="Settings" description="Manage your Stagent configuration">
20
+ <PageShell
21
+ title="Settings"
22
+ description="Manage your Stagent configuration"
23
+ >
24
24
  <div className="space-y-6">
25
- <SubscriptionSection />
26
- <CloudAccountSection />
27
- <CloudSyncSection />
25
+ <InstanceSection />
28
26
  <ProvidersAndRuntimesSection />
29
27
  <OllamaSection />
30
28
  <ChatSettingsSection />
@@ -36,7 +34,6 @@ export default function SettingsPage() {
36
34
  <BudgetGuardrailsSection />
37
35
  <PermissionsSections />
38
36
  <DatabaseSnapshotsSection />
39
- <TelemetrySection />
40
37
  <DataManagementSection />
41
38
  </div>
42
39
  </PageShell>