stagent 0.9.6 → 0.11.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.
- package/README.md +20 -44
- package/dist/cli.js +66 -18
- package/docs/.coverage-gaps.json +144 -56
- package/docs/.last-generated +1 -1
- package/docs/features/agent-intelligence.md +12 -2
- package/docs/features/chat.md +40 -5
- package/docs/features/cost-usage.md +1 -1
- package/docs/features/documents.md +5 -2
- package/docs/features/inbox-notifications.md +10 -2
- package/docs/features/keyboard-navigation.md +12 -3
- package/docs/features/provider-runtimes.md +20 -2
- package/docs/features/schedules.md +32 -4
- package/docs/features/settings.md +28 -5
- package/docs/features/shared-components.md +7 -3
- package/docs/features/tables.md +11 -2
- package/docs/features/tool-permissions.md +6 -2
- package/docs/features/workflows.md +14 -4
- package/docs/index.md +1 -1
- package/docs/journeys/developer.md +39 -2
- package/docs/journeys/personal-use.md +32 -8
- package/docs/journeys/power-user.md +45 -14
- package/docs/journeys/work-use.md +17 -8
- package/docs/manifest.json +15 -15
- package/docs/superpowers/plans/2026-04-07-instance-bootstrap.md +1691 -0
- package/docs/superpowers/plans/2026-04-08-schedule-orchestration.md +2983 -0
- package/docs/superpowers/plans/2026-04-11-schedule-maxturns-api-control.md +551 -0
- package/docs/superpowers/plans/2026-04-11-task-create-profile-validation.md +864 -0
- package/docs/superpowers/plans/2026-04-11-task-runtime-stagent-mcp-injection.md +739 -0
- package/docs/superpowers/plans/2026-04-14-chat-command-namespace-refactor.md +1390 -0
- package/docs/superpowers/plans/2026-04-14-chat-environment-integration.md +1561 -0
- package/docs/superpowers/plans/2026-04-14-chat-polish-bundle-v1.md +1219 -0
- package/docs/superpowers/plans/2026-04-14-chat-session-persistence-provider-closeout.md +399 -0
- package/docs/superpowers/specs/2026-04-08-chat-sse-resilience-hotfix-design.md +201 -0
- package/docs/superpowers/specs/2026-04-08-schedule-orchestration-design.md +371 -0
- package/docs/superpowers/specs/2026-04-08-swarm-visibility-design.md +213 -0
- package/next.config.mjs +1 -0
- package/package.json +3 -2
- package/src/__tests__/instrumentation-smoke.test.ts +15 -0
- package/src/app/analytics/page.tsx +1 -21
- package/src/app/api/chat/conversations/[id]/messages/route.ts +22 -1
- package/src/app/api/chat/conversations/[id]/skills/__tests__/activate.test.ts +141 -0
- package/src/app/api/chat/conversations/[id]/skills/activate/route.ts +74 -0
- package/src/app/api/chat/conversations/[id]/skills/deactivate/route.ts +33 -0
- package/src/app/api/chat/export/route.ts +52 -0
- package/src/app/api/chat/files/search/route.ts +50 -0
- package/src/app/api/diagnostics/chat-streams/route.ts +65 -0
- package/src/app/api/environment/rescan-if-stale/__tests__/route.test.ts +45 -0
- package/src/app/api/environment/rescan-if-stale/route.ts +23 -0
- package/src/app/api/environment/skills/route.ts +13 -0
- package/src/app/api/instance/config/route.ts +41 -0
- package/src/app/api/instance/init/route.ts +34 -0
- package/src/app/api/instance/upgrade/check/route.ts +26 -0
- package/src/app/api/instance/upgrade/route.ts +96 -0
- package/src/app/api/instance/upgrade/status/route.ts +35 -0
- package/src/app/api/memory/route.ts +0 -11
- package/src/app/api/notifications/route.ts +4 -2
- package/src/app/api/projects/[id]/route.ts +5 -155
- package/src/app/api/projects/__tests__/delete-project.test.ts +10 -19
- package/src/app/api/schedules/[id]/execute/route.ts +111 -0
- package/src/app/api/schedules/[id]/route.ts +9 -1
- package/src/app/api/schedules/__tests__/execute-route.test.ts +118 -0
- package/src/app/api/schedules/route.ts +3 -12
- package/src/app/api/settings/chat/pins/route.ts +94 -0
- package/src/app/api/settings/chat/saved-searches/__tests__/route.test.ts +119 -0
- package/src/app/api/settings/chat/saved-searches/route.ts +79 -0
- package/src/app/api/settings/environment/route.ts +26 -0
- package/src/app/api/settings/openai/login/route.ts +22 -0
- package/src/app/api/settings/openai/logout/route.ts +7 -0
- package/src/app/api/settings/openai/route.ts +21 -1
- package/src/app/api/settings/providers/route.ts +35 -8
- package/src/app/api/tables/[id]/enrich/__tests__/route.test.ts +153 -0
- package/src/app/api/tables/[id]/enrich/plan/route.ts +98 -0
- package/src/app/api/tables/[id]/enrich/route.ts +147 -0
- package/src/app/api/tables/[id]/enrich/runs/route.ts +25 -0
- package/src/app/api/tasks/[id]/execute/route.ts +52 -33
- package/src/app/api/tasks/[id]/respond/route.ts +31 -15
- package/src/app/api/tasks/[id]/resume/route.ts +24 -3
- package/src/app/api/workflows/[id]/resume/route.ts +59 -0
- package/src/app/api/workflows/[id]/status/route.ts +22 -8
- package/src/app/api/workspace/context/route.ts +2 -0
- package/src/app/api/workspace/fix-data-dir/route.ts +81 -0
- package/src/app/chat/page.tsx +11 -0
- package/src/app/documents/page.tsx +4 -1
- package/src/app/inbox/page.tsx +12 -5
- package/src/app/layout.tsx +42 -21
- package/src/app/page.tsx +0 -2
- package/src/app/settings/page.tsx +8 -9
- package/src/components/chat/__tests__/capability-banner.test.tsx +38 -0
- package/src/components/chat/__tests__/chat-session-provider.test.tsx +573 -0
- package/src/components/chat/__tests__/skill-row.test.tsx +91 -0
- package/src/components/chat/capability-banner.tsx +68 -0
- package/src/components/chat/chat-command-popover.tsx +670 -49
- package/src/components/chat/chat-input.tsx +104 -10
- package/src/components/chat/chat-message.tsx +12 -3
- package/src/components/chat/chat-session-provider.tsx +790 -0
- package/src/components/chat/chat-shell.tsx +151 -401
- package/src/components/chat/command-tab-bar.tsx +68 -0
- package/src/components/chat/conversation-template-picker.tsx +421 -0
- package/src/components/chat/help-dialog.tsx +39 -0
- package/src/components/chat/skill-composition-conflict-dialog.tsx +96 -0
- package/src/components/chat/skill-row.tsx +147 -0
- package/src/components/documents/document-browser.tsx +37 -19
- package/src/components/instance/__tests__/instance-section.test.tsx +125 -0
- package/src/components/instance/instance-section.tsx +382 -0
- package/src/components/instance/upgrade-badge.tsx +219 -0
- package/src/components/notifications/__tests__/batch-proposal-review.test.tsx +95 -0
- package/src/components/notifications/__tests__/notification-item.test.tsx +106 -0
- package/src/components/notifications/__tests__/permission-response-actions.test.tsx +70 -0
- package/src/components/notifications/batch-proposal-review.tsx +20 -5
- package/src/components/notifications/inbox-list.tsx +11 -2
- package/src/components/notifications/notification-item.tsx +56 -2
- package/src/components/notifications/pending-approval-host.tsx +56 -37
- package/src/components/notifications/permission-response-actions.tsx +155 -1
- package/src/components/schedules/schedule-create-sheet.tsx +19 -1
- package/src/components/schedules/schedule-edit-sheet.tsx +20 -1
- package/src/components/schedules/schedule-form.tsx +31 -0
- package/src/components/settings/__tests__/providers-runtimes-section.test.tsx +149 -0
- package/src/components/settings/auth-method-selector.tsx +19 -4
- package/src/components/settings/auth-status-badge.tsx +28 -3
- package/src/components/settings/environment-section.tsx +102 -0
- package/src/components/settings/openai-chatgpt-auth-control.tsx +278 -0
- package/src/components/settings/openai-runtime-section.tsx +7 -1
- package/src/components/settings/providers-runtimes-section.tsx +138 -19
- package/src/components/shared/__tests__/filter-hint.test.tsx +40 -0
- package/src/components/shared/__tests__/saved-searches-manager.test.tsx +147 -0
- package/src/components/shared/app-sidebar.tsx +4 -3
- package/src/components/shared/command-palette.tsx +266 -7
- package/src/components/shared/filter-hint.tsx +70 -0
- package/src/components/shared/filter-input.tsx +59 -0
- package/src/components/shared/saved-searches-manager.tsx +199 -0
- package/src/components/shared/theme-toggle.tsx +5 -24
- package/src/components/shared/workspace-indicator.tsx +61 -2
- package/src/components/tables/__tests__/table-enrichment-sheet.test.tsx +130 -0
- package/src/components/tables/table-create-sheet.tsx +4 -0
- package/src/components/tables/table-enrichment-runs.tsx +103 -0
- package/src/components/tables/table-enrichment-sheet.tsx +538 -0
- package/src/components/tables/table-spreadsheet.tsx +29 -5
- package/src/components/tables/table-toolbar.tsx +10 -1
- package/src/components/tasks/kanban-board.tsx +1 -0
- package/src/components/tasks/kanban-column.tsx +53 -14
- package/src/components/tasks/task-bento-grid.tsx +31 -2
- package/src/components/tasks/task-card.tsx +29 -3
- package/src/components/tasks/task-chip-bar.tsx +54 -1
- package/src/components/tasks/task-result-renderer.tsx +1 -1
- package/src/components/workflows/delay-step-body.tsx +109 -0
- package/src/components/workflows/hooks/use-workflow-status.ts +50 -0
- package/src/components/workflows/loop-status-view.tsx +1 -1
- package/src/components/workflows/shared/step-result.tsx +78 -0
- package/src/components/workflows/shared/workflow-header.tsx +141 -0
- package/src/components/workflows/shared/workflow-loading-skeleton.tsx +36 -0
- package/src/components/workflows/swarm-dashboard.tsx +2 -15
- package/src/components/workflows/views/loop-pattern-view.tsx +137 -0
- package/src/components/workflows/views/sequence-pattern-view.tsx +511 -0
- package/src/components/workflows/workflow-form-view.tsx +133 -16
- package/src/components/workflows/workflow-status-view.tsx +30 -740
- package/src/hooks/__tests__/use-chat-autocomplete-tabs.test.ts +47 -0
- package/src/hooks/__tests__/use-saved-searches.test.ts +70 -0
- package/src/hooks/use-active-skills.ts +110 -0
- package/src/hooks/use-chat-autocomplete.ts +120 -7
- package/src/hooks/use-enriched-skills.ts +19 -0
- package/src/hooks/use-pinned-entries.ts +104 -0
- package/src/hooks/use-recent-user-messages.ts +19 -0
- package/src/hooks/use-saved-searches.ts +142 -0
- package/src/instrumentation-node.ts +94 -0
- package/src/instrumentation.ts +4 -48
- package/src/lib/agents/__tests__/claude-agent-sdk-options.test.ts +56 -0
- package/src/lib/agents/__tests__/claude-agent.test.ts +212 -0
- package/src/lib/agents/__tests__/execution-manager.test.ts +1 -27
- package/src/lib/agents/__tests__/failure-reason.test.ts +68 -0
- package/src/lib/agents/__tests__/learned-context.test.ts +0 -11
- package/src/lib/agents/__tests__/learning-session.test.ts +158 -0
- package/src/lib/agents/__tests__/pattern-extractor.test.ts +48 -0
- package/src/lib/agents/__tests__/task-dispatch.test.ts +166 -0
- package/src/lib/agents/__tests__/tool-permissions.test.ts +60 -0
- package/src/lib/agents/claude-agent.ts +217 -21
- package/src/lib/agents/execution-manager.ts +0 -35
- package/src/lib/agents/handoff/bus.ts +2 -2
- package/src/lib/agents/learned-context.ts +0 -12
- package/src/lib/agents/learning-session.ts +18 -5
- package/src/lib/agents/profiles/__tests__/list-fused-profiles.test.ts +110 -0
- package/src/lib/agents/profiles/__tests__/registry.test.ts +53 -4
- package/src/lib/agents/profiles/builtins/upgrade-assistant/SKILL.md +97 -0
- package/src/lib/agents/profiles/builtins/upgrade-assistant/profile.yaml +36 -0
- package/src/lib/agents/profiles/list-fused-profiles.ts +104 -0
- package/src/lib/agents/profiles/registry.ts +18 -0
- package/src/lib/agents/profiles/types.ts +7 -1
- package/src/lib/agents/router.ts +3 -6
- package/src/lib/agents/runtime/__tests__/catalog.test.ts +130 -0
- package/src/lib/agents/runtime/__tests__/execution-target.test.ts +183 -0
- package/src/lib/agents/runtime/__tests__/openai-codex-auth.test.ts +118 -0
- package/src/lib/agents/runtime/anthropic-direct.ts +8 -0
- package/src/lib/agents/runtime/catalog.ts +121 -0
- package/src/lib/agents/runtime/claude-sdk.ts +32 -0
- package/src/lib/agents/runtime/codex-app-server-client.ts +11 -5
- package/src/lib/agents/runtime/execution-target.ts +456 -0
- package/src/lib/agents/runtime/index.ts +4 -0
- package/src/lib/agents/runtime/launch-failure.ts +101 -0
- package/src/lib/agents/runtime/openai-codex-auth.ts +389 -0
- package/src/lib/agents/runtime/openai-codex.ts +64 -60
- package/src/lib/agents/runtime/openai-direct.ts +8 -0
- package/src/lib/agents/runtime/types.ts +8 -0
- package/src/lib/agents/task-dispatch.ts +220 -0
- package/src/lib/agents/tool-permissions.ts +16 -1
- package/src/lib/book/chapter-mapping.ts +11 -0
- package/src/lib/book/content.ts +10 -0
- package/src/lib/chat/__tests__/active-skill-injection.test.ts +261 -0
- package/src/lib/chat/__tests__/active-streams.test.ts +49 -0
- package/src/lib/chat/__tests__/clean-filter-input.test.ts +68 -0
- package/src/lib/chat/__tests__/command-tabs.test.ts +68 -0
- package/src/lib/chat/__tests__/context-builder-files.test.ts +112 -0
- package/src/lib/chat/__tests__/dismissals.test.ts +65 -0
- package/src/lib/chat/__tests__/engine-sdk-options.test.ts +117 -0
- package/src/lib/chat/__tests__/finalize-safety-net.test.ts +139 -0
- package/src/lib/chat/__tests__/reconcile.test.ts +137 -0
- package/src/lib/chat/__tests__/skill-conflict.test.ts +35 -0
- package/src/lib/chat/__tests__/stream-telemetry.test.ts +151 -0
- package/src/lib/chat/__tests__/types.test.ts +28 -0
- package/src/lib/chat/active-skills.ts +31 -0
- package/src/lib/chat/active-streams.ts +27 -0
- package/src/lib/chat/clean-filter-input.ts +30 -0
- package/src/lib/chat/codex-engine.ts +46 -24
- package/src/lib/chat/command-tabs.ts +61 -0
- package/src/lib/chat/context-builder.ts +146 -4
- package/src/lib/chat/dismissals.ts +73 -0
- package/src/lib/chat/engine.ts +159 -18
- package/src/lib/chat/files/__tests__/search.test.ts +135 -0
- package/src/lib/chat/files/expand-mention.ts +76 -0
- package/src/lib/chat/files/search.ts +99 -0
- package/src/lib/chat/reconcile.ts +117 -0
- package/src/lib/chat/skill-composition.ts +210 -0
- package/src/lib/chat/skill-conflict.ts +105 -0
- package/src/lib/chat/stagent-tools.ts +7 -19
- package/src/lib/chat/stream-telemetry.ts +137 -0
- package/src/lib/chat/suggested-prompts.ts +28 -1
- package/src/lib/chat/system-prompt.ts +48 -1
- package/src/lib/chat/tool-catalog.ts +35 -4
- package/src/lib/chat/tools/__tests__/enrich-table-tool.test.ts +127 -0
- package/src/lib/chat/tools/__tests__/profile-tools.test.ts +51 -0
- package/src/lib/chat/tools/__tests__/schedule-tools.test.ts +261 -0
- package/src/lib/chat/tools/__tests__/settings-tools.test.ts +294 -0
- package/src/lib/chat/tools/__tests__/skill-tools.test.ts +474 -0
- package/src/lib/chat/tools/__tests__/task-tools.test.ts +399 -0
- package/src/lib/chat/tools/__tests__/workflow-tools-dedup.test.ts +351 -0
- package/src/lib/chat/tools/blueprint-tools.ts +190 -0
- package/src/lib/chat/tools/document-tools.ts +29 -13
- package/src/lib/chat/tools/helpers.ts +41 -0
- package/src/lib/chat/tools/notification-tools.ts +9 -5
- package/src/lib/chat/tools/profile-tools.ts +120 -23
- package/src/lib/chat/tools/project-tools.ts +33 -0
- package/src/lib/chat/tools/schedule-tools.ts +44 -11
- package/src/lib/chat/tools/skill-tools.ts +183 -0
- package/src/lib/chat/tools/table-tools.ts +71 -0
- package/src/lib/chat/tools/task-tools.ts +89 -21
- package/src/lib/chat/tools/workflow-tools.ts +275 -32
- package/src/lib/chat/types.ts +15 -0
- package/src/lib/constants/settings.ts +10 -18
- package/src/lib/data/__tests__/clear.test.ts +56 -2
- package/src/lib/data/clear.ts +17 -16
- package/src/lib/data/delete-project.ts +171 -0
- package/src/lib/db/__tests__/bootstrap.test.ts +1 -1
- package/src/lib/db/bootstrap.ts +62 -16
- package/src/lib/db/index.ts +5 -0
- package/src/lib/db/migrations/0009_add_app_instances.sql +25 -0
- package/src/lib/db/migrations/0024_add_workflow_resume_at.sql +10 -0
- package/src/lib/db/migrations/0025_drop_app_instances.sql +3 -0
- package/src/lib/db/migrations/0026_drop_license.sql +3 -0
- package/src/lib/db/migrations/meta/_journal.json +21 -0
- package/src/lib/db/schema.ts +94 -23
- package/src/lib/environment/__tests__/auto-promote.test.ts +132 -0
- package/src/lib/environment/__tests__/list-skills-enriched.test.ts +55 -0
- package/src/lib/environment/__tests__/skill-enrichment.test.ts +129 -0
- package/src/lib/environment/__tests__/skill-recommendations.test.ts +87 -0
- package/src/lib/environment/data.ts +9 -0
- package/src/lib/environment/list-skills.ts +176 -0
- package/src/lib/environment/parsers/__tests__/skill.test.ts +54 -0
- package/src/lib/environment/parsers/skill.ts +26 -5
- package/src/lib/environment/profile-generator.ts +54 -0
- package/src/lib/environment/skill-enrichment.ts +106 -0
- package/src/lib/environment/skill-recommendations.ts +66 -0
- package/src/lib/environment/workspace-context.ts +13 -1
- package/src/lib/filters/__tests__/parse.quoted.test.ts +40 -0
- package/src/lib/filters/__tests__/parse.test.ts +135 -0
- package/src/lib/filters/parse.ts +86 -0
- package/src/lib/import/dedup.ts +4 -54
- package/src/lib/instance/__tests__/bootstrap.test.ts +362 -0
- package/src/lib/instance/__tests__/detect.test.ts +115 -0
- package/src/lib/instance/__tests__/fingerprint.test.ts +48 -0
- package/src/lib/instance/__tests__/git-ops.test.ts +95 -0
- package/src/lib/instance/__tests__/settings.test.ts +83 -0
- package/src/lib/instance/__tests__/upgrade-poller.test.ts +181 -0
- package/src/lib/instance/bootstrap.ts +270 -0
- package/src/lib/instance/detect.ts +49 -0
- package/src/lib/instance/fingerprint.ts +76 -0
- package/src/lib/instance/git-ops.ts +95 -0
- package/src/lib/instance/settings.ts +61 -0
- package/src/lib/instance/types.ts +77 -0
- package/src/lib/instance/upgrade-poller.ts +205 -0
- package/src/lib/notifications/__tests__/visibility.test.ts +51 -0
- package/src/lib/notifications/visibility.ts +33 -0
- package/src/lib/schedules/__tests__/collision-check.test.ts +93 -0
- package/src/lib/schedules/__tests__/config.test.ts +62 -0
- package/src/lib/schedules/__tests__/firing-metrics.test.ts +99 -0
- package/src/lib/schedules/__tests__/integration.test.ts +82 -0
- package/src/lib/schedules/__tests__/slot-claim.test.ts +242 -0
- package/src/lib/schedules/__tests__/tick-scheduler.test.ts +102 -0
- package/src/lib/schedules/__tests__/turn-budget.test.ts +228 -0
- package/src/lib/schedules/collision-check.ts +105 -0
- package/src/lib/schedules/config.ts +53 -0
- package/src/lib/schedules/scheduler.ts +236 -17
- package/src/lib/schedules/slot-claim.ts +105 -0
- package/src/lib/settings/__tests__/openai-auth.test.ts +101 -0
- package/src/lib/settings/__tests__/openai-login-manager.test.ts +64 -0
- package/src/lib/settings/__tests__/runtime-setup.test.ts +33 -0
- package/src/lib/settings/openai-auth.ts +105 -10
- package/src/lib/settings/openai-login-manager.ts +260 -0
- package/src/lib/settings/runtime-setup.ts +14 -4
- package/src/lib/tables/__tests__/enrichment-planner.test.ts +124 -0
- package/src/lib/tables/__tests__/enrichment.test.ts +147 -0
- package/src/lib/tables/enrichment-planner.ts +454 -0
- package/src/lib/tables/enrichment.ts +328 -0
- package/src/lib/tables/query-builder.ts +5 -2
- package/src/lib/tables/trigger-evaluator.ts +3 -2
- package/src/lib/theme.ts +71 -0
- package/src/lib/usage/ledger.ts +2 -18
- package/src/lib/util/__tests__/similarity.test.ts +106 -0
- package/src/lib/util/similarity.ts +77 -0
- package/src/lib/utils/format-timestamp.ts +24 -0
- package/src/lib/utils/stagent-paths.ts +12 -0
- package/src/lib/validators/__tests__/blueprint.test.ts +172 -0
- package/src/lib/validators/__tests__/settings.test.ts +10 -0
- package/src/lib/validators/blueprint.ts +70 -9
- package/src/lib/validators/profile.ts +2 -2
- package/src/lib/validators/settings.ts +3 -1
- package/src/lib/workflows/__tests__/delay.test.ts +196 -0
- package/src/lib/workflows/__tests__/engine.test.ts +8 -0
- package/src/lib/workflows/__tests__/loop-executor.test.ts +54 -0
- package/src/lib/workflows/__tests__/post-action.test.ts +108 -0
- package/src/lib/workflows/blueprints/__tests__/render-prompt.test.ts +124 -0
- package/src/lib/workflows/blueprints/instantiator.ts +22 -1
- package/src/lib/workflows/blueprints/render-prompt.ts +71 -0
- package/src/lib/workflows/blueprints/types.ts +16 -2
- package/src/lib/workflows/delay.ts +106 -0
- package/src/lib/workflows/engine.ts +212 -7
- package/src/lib/workflows/loop-executor.ts +349 -24
- package/src/lib/workflows/post-action.ts +91 -0
- package/src/lib/workflows/types.ts +166 -1
- package/src/test/setup.ts +10 -0
- package/src/app/api/license/checkout/route.ts +0 -28
- package/src/app/api/license/portal/route.ts +0 -26
- package/src/app/api/license/route.ts +0 -89
- package/src/app/api/license/usage/route.ts +0 -63
- package/src/app/api/marketplace/browse/route.ts +0 -15
- package/src/app/api/marketplace/import/route.ts +0 -28
- package/src/app/api/marketplace/publish/route.ts +0 -40
- package/src/app/api/onboarding/email/route.ts +0 -53
- package/src/app/api/settings/telemetry/route.ts +0 -14
- package/src/app/api/sync/export/route.ts +0 -54
- package/src/app/api/sync/restore/route.ts +0 -37
- package/src/app/api/sync/sessions/route.ts +0 -24
- package/src/app/auth/callback/route.ts +0 -73
- package/src/app/marketplace/page.tsx +0 -19
- package/src/components/analytics/analytics-gate-card.tsx +0 -101
- package/src/components/marketplace/blueprint-card.tsx +0 -61
- package/src/components/marketplace/marketplace-browser.tsx +0 -131
- package/src/components/onboarding/email-capture-card.tsx +0 -104
- package/src/components/settings/activation-form.tsx +0 -95
- package/src/components/settings/cloud-account-section.tsx +0 -147
- package/src/components/settings/cloud-sync-section.tsx +0 -155
- package/src/components/settings/subscription-section.tsx +0 -410
- package/src/components/settings/telemetry-section.tsx +0 -80
- package/src/components/shared/premium-gate-overlay.tsx +0 -50
- package/src/components/shared/schedule-gate-dialog.tsx +0 -64
- package/src/components/shared/upgrade-banner.tsx +0 -112
- package/src/hooks/use-supabase-auth.ts +0 -79
- package/src/lib/billing/email.ts +0 -54
- package/src/lib/billing/products.ts +0 -80
- package/src/lib/billing/stripe.ts +0 -101
- package/src/lib/cloud/supabase-browser.ts +0 -32
- package/src/lib/cloud/supabase-client.ts +0 -56
- package/src/lib/license/__tests__/features.test.ts +0 -56
- package/src/lib/license/__tests__/key-format.test.ts +0 -88
- package/src/lib/license/__tests__/manager.test.ts +0 -64
- package/src/lib/license/__tests__/tier-limits.test.ts +0 -79
- package/src/lib/license/cloud-validation.ts +0 -60
- package/src/lib/license/features.ts +0 -44
- package/src/lib/license/key-format.ts +0 -101
- package/src/lib/license/limit-check.ts +0 -111
- package/src/lib/license/limit-queries.ts +0 -51
- package/src/lib/license/manager.ts +0 -345
- package/src/lib/license/notifications.ts +0 -59
- package/src/lib/license/tier-limits.ts +0 -71
- package/src/lib/marketplace/marketplace-client.ts +0 -107
- package/src/lib/sync/cloud-sync.ts +0 -235
- package/src/lib/telemetry/conversion-events.ts +0 -71
- package/src/lib/telemetry/queue.ts +0 -122
- package/src/lib/validators/license.ts +0 -33
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { NextRequest, NextResponse } from "next/server";
|
|
2
|
+
import { db } from "@/lib/db";
|
|
3
|
+
import { workflows } from "@/lib/db/schema";
|
|
4
|
+
import { eq } from "drizzle-orm";
|
|
5
|
+
import { resumeWorkflow } from "@/lib/workflows/engine";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* POST /api/workflows/[id]/resume
|
|
9
|
+
*
|
|
10
|
+
* Manually resume a workflow that was paused at a delay step. Called by the
|
|
11
|
+
* "Resume Now" button in WorkflowStatusView to skip the remaining delay. The
|
|
12
|
+
* scheduler tick also calls resumeWorkflow() directly (not through this route)
|
|
13
|
+
* when workflows.resume_at is reached.
|
|
14
|
+
*
|
|
15
|
+
* Response codes:
|
|
16
|
+
* 202 Accepted — resume dispatched (fire-and-forget)
|
|
17
|
+
* 404 Not Found — workflow does not exist
|
|
18
|
+
* 409 Conflict — workflow is not in paused state (already resumed, racing
|
|
19
|
+
* scheduler, or was never paused). resumeWorkflow handles
|
|
20
|
+
* this internally with its atomic status transition, so the
|
|
21
|
+
* conflict is reported here for correct UX feedback.
|
|
22
|
+
*/
|
|
23
|
+
export async function POST(
|
|
24
|
+
_req: NextRequest,
|
|
25
|
+
{ params }: { params: Promise<{ id: string }> },
|
|
26
|
+
) {
|
|
27
|
+
const { id } = await params;
|
|
28
|
+
|
|
29
|
+
const [workflow] = await db
|
|
30
|
+
.select()
|
|
31
|
+
.from(workflows)
|
|
32
|
+
.where(eq(workflows.id, id));
|
|
33
|
+
|
|
34
|
+
if (!workflow) {
|
|
35
|
+
return NextResponse.json({ error: "Workflow not found" }, { status: 404 });
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (workflow.status !== "paused") {
|
|
39
|
+
return NextResponse.json(
|
|
40
|
+
{
|
|
41
|
+
error: `Workflow is not paused (current status: ${workflow.status})`,
|
|
42
|
+
status: workflow.status,
|
|
43
|
+
},
|
|
44
|
+
{ status: 409 },
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Fire-and-forget. resumeWorkflow performs its own atomic status check, so
|
|
49
|
+
// if the scheduler tick beats this request by microseconds, the DB UPDATE
|
|
50
|
+
// will match zero rows and resumeWorkflow returns silently without harm.
|
|
51
|
+
resumeWorkflow(id).catch((error) => {
|
|
52
|
+
console.error(`Workflow ${id} resume failed:`, error);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
return NextResponse.json(
|
|
56
|
+
{ status: "resuming", workflowId: id },
|
|
57
|
+
{ status: 202 },
|
|
58
|
+
);
|
|
59
|
+
}
|
|
@@ -3,6 +3,11 @@ import { db } from "@/lib/db";
|
|
|
3
3
|
import { workflows, tasks, documents } from "@/lib/db/schema";
|
|
4
4
|
import { eq, and, inArray, count, desc, sql as drizzleSql } from "drizzle-orm";
|
|
5
5
|
import { parseWorkflowState } from "@/lib/workflows/engine";
|
|
6
|
+
import type {
|
|
7
|
+
WorkflowStatusResponse,
|
|
8
|
+
NonLoopPattern,
|
|
9
|
+
StepWithState,
|
|
10
|
+
} from "@/lib/workflows/types";
|
|
6
11
|
|
|
7
12
|
/** Collect output documents for workflow step tasks + input documents from parent task */
|
|
8
13
|
async function getWorkflowDocuments(
|
|
@@ -97,15 +102,18 @@ export async function GET(
|
|
|
97
102
|
const sourceTaskId: string | undefined = definition.sourceTaskId;
|
|
98
103
|
const { stepDocuments, parentDocuments } = await getWorkflowDocuments(state, sourceTaskId);
|
|
99
104
|
|
|
100
|
-
// Loop pattern returns loop-specific data instead of step states
|
|
105
|
+
// Loop pattern returns loop-specific data instead of step states.
|
|
106
|
+
// The `satisfies` annotation enforces the TDR-031 contract: the loop arm
|
|
107
|
+
// of WorkflowStatusResponse cannot emit `workflowState` or `resumeAt`, and
|
|
108
|
+
// its `steps` field is raw WorkflowStep[] (not StepWithState[]).
|
|
101
109
|
if (definition.pattern === "loop") {
|
|
102
|
-
|
|
110
|
+
const loopBody = {
|
|
103
111
|
id: workflow.id,
|
|
104
112
|
name: workflow.name,
|
|
105
113
|
status: workflow.status,
|
|
106
114
|
projectId: workflow.projectId,
|
|
107
115
|
definition: workflow.definition,
|
|
108
|
-
pattern:
|
|
116
|
+
pattern: "loop" as const,
|
|
109
117
|
loopConfig: definition.loopConfig,
|
|
110
118
|
swarmConfig: definition.swarmConfig,
|
|
111
119
|
loopState,
|
|
@@ -114,18 +122,23 @@ export async function GET(
|
|
|
114
122
|
parentDocuments,
|
|
115
123
|
runNumber: workflow.runNumber,
|
|
116
124
|
runHistory,
|
|
117
|
-
}
|
|
125
|
+
} satisfies WorkflowStatusResponse;
|
|
126
|
+
return NextResponse.json(loopBody);
|
|
118
127
|
}
|
|
119
128
|
|
|
120
|
-
|
|
129
|
+
// Non-loop arm: sequence, parallel, swarm, planner-executor, checkpoint all
|
|
130
|
+
// share the step-state rendering path. `satisfies` enforces that this branch
|
|
131
|
+
// cannot accidentally emit `loopState`, and that every step has `.state`.
|
|
132
|
+
const nonLoopBody = {
|
|
121
133
|
id: workflow.id,
|
|
122
134
|
name: workflow.name,
|
|
123
135
|
status: workflow.status,
|
|
136
|
+
resumeAt: workflow.resumeAt ?? null,
|
|
124
137
|
projectId: workflow.projectId,
|
|
125
138
|
definition: workflow.definition,
|
|
126
|
-
pattern: definition.pattern,
|
|
139
|
+
pattern: definition.pattern as NonLoopPattern,
|
|
127
140
|
swarmConfig: definition.swarmConfig,
|
|
128
|
-
steps: definition.steps.map((step, i) => ({
|
|
141
|
+
steps: definition.steps.map((step, i): StepWithState => ({
|
|
129
142
|
...step,
|
|
130
143
|
state: state?.stepStates[i] ?? { stepId: step.id, status: "pending" },
|
|
131
144
|
})),
|
|
@@ -134,5 +147,6 @@ export async function GET(
|
|
|
134
147
|
parentDocuments,
|
|
135
148
|
runNumber: workflow.runNumber,
|
|
136
149
|
runHistory,
|
|
137
|
-
}
|
|
150
|
+
} satisfies WorkflowStatusResponse;
|
|
151
|
+
return NextResponse.json(nonLoopBody);
|
|
138
152
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { NextResponse } from "next/server";
|
|
2
2
|
import { getWorkspaceContext } from "@/lib/environment/workspace-context";
|
|
3
3
|
|
|
4
|
+
export const dynamic = "force-dynamic";
|
|
5
|
+
|
|
4
6
|
export function GET() {
|
|
5
7
|
const context = getWorkspaceContext();
|
|
6
8
|
return NextResponse.json(context, {
|
|
@@ -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
|
+
}
|
package/src/app/chat/page.tsx
CHANGED
|
@@ -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(),
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Suspense } from "react";
|
|
1
2
|
import { db } from "@/lib/db";
|
|
2
3
|
import { documents, tasks, projects, workflows } from "@/lib/db/schema";
|
|
3
4
|
import { desc, eq } from "drizzle-orm";
|
|
@@ -47,7 +48,9 @@ export default async function DocumentsPage() {
|
|
|
47
48
|
|
|
48
49
|
return (
|
|
49
50
|
<PageShell title="Documents">
|
|
50
|
-
<
|
|
51
|
+
<Suspense fallback={null}>
|
|
52
|
+
<DocumentBrowser initialDocuments={docs} projects={projectList} />
|
|
53
|
+
</Suspense>
|
|
51
54
|
</PageShell>
|
|
52
55
|
);
|
|
53
56
|
}
|
package/src/app/inbox/page.tsx
CHANGED
|
@@ -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 =
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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
|
package/src/app/layout.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Metadata } from "next";
|
|
2
|
-
import
|
|
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
|
-
|
|
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
|
|
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
|
-
<
|
|
83
|
-
<
|
|
84
|
-
|
|
85
|
-
<
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
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";
|
|
@@ -11,32 +7,35 @@ import { ChatSettingsSection } from "@/components/settings/chat-settings-section
|
|
|
11
7
|
import { RuntimeTimeoutSection } from "@/components/settings/runtime-timeout-section";
|
|
12
8
|
import { BrowserToolsSection } from "@/components/settings/browser-tools-section";
|
|
13
9
|
import { WebSearchSection } from "@/components/settings/web-search-section";
|
|
10
|
+
import { EnvironmentSection } from "@/components/settings/environment-section";
|
|
14
11
|
import { LearningContextSection } from "@/components/settings/learning-context-section";
|
|
15
12
|
import { OllamaSection } from "@/components/settings/ollama-section";
|
|
16
13
|
import { ChannelsSection } from "@/components/settings/channels-section";
|
|
14
|
+
import { InstanceSection } from "@/components/instance/instance-section";
|
|
17
15
|
import { PageShell } from "@/components/shared/page-shell";
|
|
18
16
|
|
|
19
17
|
export const dynamic = "force-dynamic";
|
|
20
18
|
|
|
21
19
|
export default function SettingsPage() {
|
|
22
20
|
return (
|
|
23
|
-
<PageShell
|
|
21
|
+
<PageShell
|
|
22
|
+
title="Settings"
|
|
23
|
+
description="Manage your Stagent configuration"
|
|
24
|
+
>
|
|
24
25
|
<div className="space-y-6">
|
|
25
|
-
<
|
|
26
|
-
<CloudAccountSection />
|
|
27
|
-
<CloudSyncSection />
|
|
26
|
+
<InstanceSection />
|
|
28
27
|
<ProvidersAndRuntimesSection />
|
|
29
28
|
<OllamaSection />
|
|
30
29
|
<ChatSettingsSection />
|
|
31
30
|
<RuntimeTimeoutSection />
|
|
32
31
|
<LearningContextSection />
|
|
33
32
|
<WebSearchSection />
|
|
33
|
+
<EnvironmentSection />
|
|
34
34
|
<BrowserToolsSection />
|
|
35
35
|
<ChannelsSection />
|
|
36
36
|
<BudgetGuardrailsSection />
|
|
37
37
|
<PermissionsSections />
|
|
38
38
|
<DatabaseSnapshotsSection />
|
|
39
|
-
<TelemetrySection />
|
|
40
39
|
<DataManagementSection />
|
|
41
40
|
</div>
|
|
42
41
|
</PageShell>
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach } from "vitest";
|
|
2
|
+
import { render, screen, fireEvent } from "@testing-library/react";
|
|
3
|
+
import { CapabilityBanner } from "../capability-banner";
|
|
4
|
+
|
|
5
|
+
describe("CapabilityBanner", () => {
|
|
6
|
+
beforeEach(() => {
|
|
7
|
+
sessionStorage.clear();
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
it("is hidden on claude-code runtime", () => {
|
|
11
|
+
render(<CapabilityBanner runtimeId="claude-code" />);
|
|
12
|
+
expect(screen.queryByRole("status")).toBeNull();
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it("is hidden on openai-codex-app-server runtime", () => {
|
|
16
|
+
render(<CapabilityBanner runtimeId="openai-codex-app-server" />);
|
|
17
|
+
expect(screen.queryByRole("status")).toBeNull();
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it("is visible on ollama runtime with capability message", () => {
|
|
21
|
+
render(<CapabilityBanner runtimeId="ollama" />);
|
|
22
|
+
const status = screen.getByRole("status");
|
|
23
|
+
expect(status.textContent).toContain("file read/write");
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("hides on dismiss and persists to sessionStorage", () => {
|
|
27
|
+
render(<CapabilityBanner runtimeId="ollama" />);
|
|
28
|
+
fireEvent.click(screen.getByRole("button", { name: /dismiss/i }));
|
|
29
|
+
expect(screen.queryByRole("status")).toBeNull();
|
|
30
|
+
expect(sessionStorage.getItem("stagent.capability-banner.dismissed.ollama")).toBe("1");
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it("stays dismissed on remount if sessionStorage flag set", () => {
|
|
34
|
+
sessionStorage.setItem("stagent.capability-banner.dismissed.ollama", "1");
|
|
35
|
+
render(<CapabilityBanner runtimeId="ollama" />);
|
|
36
|
+
expect(screen.queryByRole("status")).toBeNull();
|
|
37
|
+
});
|
|
38
|
+
});
|