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
|
@@ -20,8 +20,37 @@ export interface WorkflowStep {
|
|
|
20
20
|
budgetUsd?: number;
|
|
21
21
|
/** Per-step runtime override — takes precedence over workflow.runtimeId and global settings */
|
|
22
22
|
runtimeId?: string;
|
|
23
|
+
/**
|
|
24
|
+
* If set, this step is a pure time delay (not a task). Format: Nm|Nh|Nd|Nw
|
|
25
|
+
* (1 minute to 30 days). When the engine reaches a delay step, the workflow
|
|
26
|
+
* is marked paused with resume_at = now + delayDuration. The scheduler tick
|
|
27
|
+
* resumes the workflow when resume_at is reached. Delay steps must NOT have
|
|
28
|
+
* a prompt/profile/runtime. See features/workflow-step-delays.md.
|
|
29
|
+
*/
|
|
30
|
+
delayDuration?: string;
|
|
31
|
+
/**
|
|
32
|
+
* Optional declarative side-effect to apply after the step's task completes
|
|
33
|
+
* successfully. Used by bulk row enrichment to write the agent's result back
|
|
34
|
+
* into a user table cell. Discriminated union — `type` selects the variant.
|
|
35
|
+
* See features/bulk-row-enrichment.md.
|
|
36
|
+
*/
|
|
37
|
+
postAction?: StepPostAction;
|
|
23
38
|
}
|
|
24
39
|
|
|
40
|
+
/**
|
|
41
|
+
* Declarative post-step side effect. Currently only `update_row` is supported;
|
|
42
|
+
* adding new variants is purely additive (extend the union, add a dispatcher
|
|
43
|
+
* branch). The `tableId` is informational/audit-only — `updateRow` finds the
|
|
44
|
+
* row by `rowId`. The `rowId` field may contain `{{itemVariable.field}}`
|
|
45
|
+
* placeholders that are resolved against the current loop iteration's row.
|
|
46
|
+
*/
|
|
47
|
+
export type StepPostAction = {
|
|
48
|
+
type: "update_row";
|
|
49
|
+
tableId: string;
|
|
50
|
+
rowId: string;
|
|
51
|
+
column: string;
|
|
52
|
+
};
|
|
53
|
+
|
|
25
54
|
/** Selector for auto-discovering documents from the project pool */
|
|
26
55
|
export interface DocumentSelector {
|
|
27
56
|
fromWorkflowId?: string;
|
|
@@ -40,6 +69,16 @@ export interface LoopConfig {
|
|
|
40
69
|
assignedAgent?: string;
|
|
41
70
|
agentProfile?: string;
|
|
42
71
|
completionSignals?: string[];
|
|
72
|
+
/**
|
|
73
|
+
* Row-driven loop: when set, the loop iterates once per item instead of
|
|
74
|
+
* looping autonomously until completionSignals fire. Each item is bound
|
|
75
|
+
* into the prompt template under the name in `itemVariable` (default
|
|
76
|
+
* "item"). Used by bulk row enrichment workflows. Iteration count is
|
|
77
|
+
* still capped by `maxIterations`. See features/bulk-row-enrichment.md.
|
|
78
|
+
*/
|
|
79
|
+
items?: unknown[];
|
|
80
|
+
/** Variable name the current item is bound to (default "item"). */
|
|
81
|
+
itemVariable?: string;
|
|
43
82
|
}
|
|
44
83
|
|
|
45
84
|
export interface SwarmConfig {
|
|
@@ -51,10 +90,37 @@ export interface WorkflowDefinition {
|
|
|
51
90
|
steps: WorkflowStep[];
|
|
52
91
|
loopConfig?: LoopConfig;
|
|
53
92
|
swarmConfig?: SwarmConfig;
|
|
93
|
+
metadata?: WorkflowMetadata;
|
|
54
94
|
/** Parent task ID — set when workflow is created from AI assist, used to propagate document context */
|
|
55
95
|
sourceTaskId?: string;
|
|
56
96
|
}
|
|
57
97
|
|
|
98
|
+
export interface WorkflowMetadata {
|
|
99
|
+
enrichment?: WorkflowEnrichmentMetadata;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export interface WorkflowEnrichmentTargetContract {
|
|
103
|
+
columnName: string;
|
|
104
|
+
columnLabel: string;
|
|
105
|
+
dataType: "text" | "number" | "boolean" | "select" | "url" | "email";
|
|
106
|
+
allowedOptions?: string[];
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export interface WorkflowEnrichmentMetadata {
|
|
110
|
+
tableId: string;
|
|
111
|
+
tableName: string;
|
|
112
|
+
targetColumn: string;
|
|
113
|
+
targetColumnLabel: string;
|
|
114
|
+
promptMode: "auto" | "custom";
|
|
115
|
+
strategy:
|
|
116
|
+
| "single-pass-lookup"
|
|
117
|
+
| "single-pass-classify"
|
|
118
|
+
| "research-and-synthesize";
|
|
119
|
+
agentProfile: string;
|
|
120
|
+
eligibleRowCount: number;
|
|
121
|
+
targetContract: WorkflowEnrichmentTargetContract;
|
|
122
|
+
}
|
|
123
|
+
|
|
58
124
|
export type LoopStopReason =
|
|
59
125
|
| "max_iterations"
|
|
60
126
|
| "time_budget"
|
|
@@ -99,7 +165,9 @@ export type WorkflowStepStatus =
|
|
|
99
165
|
| "completed"
|
|
100
166
|
| "failed"
|
|
101
167
|
| "waiting_approval"
|
|
102
|
-
| "waiting_dependencies"
|
|
168
|
+
| "waiting_dependencies"
|
|
169
|
+
/** Step is a time delay and the workflow is paused waiting for resume_at. */
|
|
170
|
+
| "delayed";
|
|
103
171
|
|
|
104
172
|
export interface StepState {
|
|
105
173
|
stepId: string;
|
|
@@ -132,3 +200,100 @@ export function createInitialState(definition: WorkflowDefinition): WorkflowStat
|
|
|
132
200
|
startedAt: new Date().toISOString(),
|
|
133
201
|
};
|
|
134
202
|
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Document reference returned by the workflow status API alongside each step
|
|
206
|
+
* (output) or parent task (input). The shape matches what the API route
|
|
207
|
+
* actually selects from the documents table.
|
|
208
|
+
*/
|
|
209
|
+
export interface WorkflowStatusDocument {
|
|
210
|
+
id: string;
|
|
211
|
+
originalName: string;
|
|
212
|
+
mimeType: string;
|
|
213
|
+
storagePath: string;
|
|
214
|
+
direction: string;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Step with computed state — the shape returned by the status API for every
|
|
219
|
+
* non-loop pattern (sequence, parallel, swarm, planner-executor, checkpoint).
|
|
220
|
+
* `state` is always present because the route synthesizes a pending placeholder
|
|
221
|
+
* when the real stepState hasn't been created yet.
|
|
222
|
+
*/
|
|
223
|
+
export interface StepWithState extends WorkflowStep {
|
|
224
|
+
state: StepState;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Run-history summary row returned alongside every status response — counts
|
|
229
|
+
* of tasks per workflow run number.
|
|
230
|
+
*/
|
|
231
|
+
export interface WorkflowRunHistoryEntry {
|
|
232
|
+
runNumber: number | null;
|
|
233
|
+
taskCount: number;
|
|
234
|
+
completedCount: number;
|
|
235
|
+
failedCount: number;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* All non-loop workflow patterns share one response shape. Alias exists so
|
|
240
|
+
* the union arm and the new-pattern checklist (TDR-031) can both reference
|
|
241
|
+
* it — when a new pattern is added to WorkflowPattern, it automatically
|
|
242
|
+
* joins this arm unless the author explicitly adds a new arm with different
|
|
243
|
+
* fields.
|
|
244
|
+
*/
|
|
245
|
+
export type NonLoopPattern = Exclude<WorkflowPattern, "loop">;
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Discriminated union shape for `GET /api/workflows/[id]/status` responses.
|
|
249
|
+
* Consumers MUST narrow on `pattern` before reading pattern-specific fields.
|
|
250
|
+
* See TDR-031: Workflow status API is a pattern-discriminated union.
|
|
251
|
+
*
|
|
252
|
+
* - Loop arm: raw step definitions (no `.state`), plus `loopState` carrying
|
|
253
|
+
* the real iteration progress in `loopState.iterations[]`. Consumers that
|
|
254
|
+
* need completed outputs for a loop workflow should read from
|
|
255
|
+
* `loopState.iterations[].result`, not `steps[].state.result` (which does
|
|
256
|
+
* not exist on this arm — it's a compile error).
|
|
257
|
+
*
|
|
258
|
+
* - Non-loop arm: each step wrapped with `.state` synthesized from
|
|
259
|
+
* `workflowState.stepStates[i]`, plus `resumeAt` for delay pauses. The
|
|
260
|
+
* non-loop arm covers sequence, parallel, swarm, planner-executor, and
|
|
261
|
+
* checkpoint patterns — they all share the step-state rendering path.
|
|
262
|
+
*/
|
|
263
|
+
export type WorkflowStatusResponse =
|
|
264
|
+
| {
|
|
265
|
+
pattern: "loop";
|
|
266
|
+
id: string;
|
|
267
|
+
name: string;
|
|
268
|
+
status: string;
|
|
269
|
+
projectId?: string | null;
|
|
270
|
+
definition?: string;
|
|
271
|
+
loopConfig?: LoopConfig;
|
|
272
|
+
loopState: LoopState | null;
|
|
273
|
+
swarmConfig?: SwarmConfig;
|
|
274
|
+
/** Raw step definitions — no `.state` on this arm. Reading from the
|
|
275
|
+
* iteration stream (`loopState.iterations[]`) is the correct path. */
|
|
276
|
+
steps: WorkflowStep[];
|
|
277
|
+
stepDocuments?: Record<string, WorkflowStatusDocument[]>;
|
|
278
|
+
parentDocuments?: WorkflowStatusDocument[];
|
|
279
|
+
runNumber?: number;
|
|
280
|
+
runHistory?: WorkflowRunHistoryEntry[];
|
|
281
|
+
}
|
|
282
|
+
| {
|
|
283
|
+
pattern: NonLoopPattern;
|
|
284
|
+
id: string;
|
|
285
|
+
name: string;
|
|
286
|
+
status: string;
|
|
287
|
+
/** Epoch ms for a paused (delay-step) workflow's scheduled resume. */
|
|
288
|
+
resumeAt: number | null;
|
|
289
|
+
projectId?: string | null;
|
|
290
|
+
definition?: string;
|
|
291
|
+
swarmConfig?: SwarmConfig;
|
|
292
|
+
/** Each step wrapped with `.state` — always present on this arm. */
|
|
293
|
+
steps: StepWithState[];
|
|
294
|
+
workflowState: WorkflowState | null;
|
|
295
|
+
stepDocuments?: Record<string, WorkflowStatusDocument[]>;
|
|
296
|
+
parentDocuments?: WorkflowStatusDocument[];
|
|
297
|
+
runNumber?: number;
|
|
298
|
+
runHistory?: WorkflowRunHistoryEntry[];
|
|
299
|
+
};
|
package/src/test/setup.ts
CHANGED
|
@@ -3,6 +3,16 @@ import { mkdtempSync, mkdirSync } from "fs";
|
|
|
3
3
|
import { join } from "path";
|
|
4
4
|
import { tmpdir } from "os";
|
|
5
5
|
|
|
6
|
+
// Mock ResizeObserver for cmdk
|
|
7
|
+
global.ResizeObserver = class ResizeObserver {
|
|
8
|
+
observe() {}
|
|
9
|
+
unobserve() {}
|
|
10
|
+
disconnect() {}
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
// Mock scrollIntoView for cmdk
|
|
14
|
+
HTMLElement.prototype.scrollIntoView = () => {};
|
|
15
|
+
|
|
6
16
|
if (!process.env.STAGENT_DATA_DIR) {
|
|
7
17
|
const tempDataDir = mkdtempSync(join(tmpdir(), "stagent-vitest-"));
|
|
8
18
|
mkdirSync(tempDataDir, { recursive: true });
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { NextRequest, NextResponse } from "next/server";
|
|
2
|
-
import { createCheckoutSession } from "@/lib/billing/stripe";
|
|
3
|
-
import { TIERS } from "@/lib/license/tier-limits";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* POST /api/license/checkout
|
|
7
|
-
* Creates a Stripe Checkout Session and returns the URL.
|
|
8
|
-
* Body: { tier: "solo"|"operator"|"scale", billingPeriod?: "monthly"|"annual" }
|
|
9
|
-
*/
|
|
10
|
-
export async function POST(req: NextRequest) {
|
|
11
|
-
const body = await req.json();
|
|
12
|
-
const { tier, billingPeriod } = body;
|
|
13
|
-
|
|
14
|
-
if (!tier || tier === "community" || !TIERS.includes(tier)) {
|
|
15
|
-
return NextResponse.json(
|
|
16
|
-
{ error: "Valid paid tier required (solo, operator, scale)" },
|
|
17
|
-
{ status: 400 }
|
|
18
|
-
);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const result = await createCheckoutSession(tier, billingPeriod ?? "monthly");
|
|
22
|
-
|
|
23
|
-
if ("error" in result) {
|
|
24
|
-
return NextResponse.json({ error: result.error }, { status: 502 });
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
return NextResponse.json({ url: result.url });
|
|
28
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { NextRequest, NextResponse } from "next/server";
|
|
2
|
-
import { createPortalSession } from "@/lib/billing/stripe";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* GET /api/license/portal
|
|
6
|
-
* Creates a Stripe Customer Portal session and redirects.
|
|
7
|
-
* Query: ?email=user@example.com
|
|
8
|
-
*/
|
|
9
|
-
export async function GET(req: NextRequest) {
|
|
10
|
-
const email = req.nextUrl.searchParams.get("email");
|
|
11
|
-
|
|
12
|
-
if (!email) {
|
|
13
|
-
return NextResponse.json(
|
|
14
|
-
{ error: "email query parameter required" },
|
|
15
|
-
{ status: 400 }
|
|
16
|
-
);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const result = await createPortalSession(email);
|
|
20
|
-
|
|
21
|
-
if ("error" in result) {
|
|
22
|
-
return NextResponse.json({ error: result.error }, { status: 502 });
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
return NextResponse.redirect(result.url);
|
|
26
|
-
}
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
import { NextRequest, NextResponse } from "next/server";
|
|
2
|
-
import { licenseManager } from "@/lib/license/manager";
|
|
3
|
-
import { TIER_LIMITS, type LimitResource } from "@/lib/license/tier-limits";
|
|
4
|
-
import { LICENSE_FEATURES, canAccessFeature } from "@/lib/license/features";
|
|
5
|
-
import { activateLicenseSchema } from "@/lib/validators/license";
|
|
6
|
-
import type { LicenseTier } from "@/lib/license/tier-limits";
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* GET /api/license — current license status, feature flags, and limits.
|
|
10
|
-
*/
|
|
11
|
-
export async function GET() {
|
|
12
|
-
// Read from DB directly — avoids stale singleton cache in Turbopack dev mode
|
|
13
|
-
const status = licenseManager.getStatusFromDb();
|
|
14
|
-
const tier = status.tier;
|
|
15
|
-
|
|
16
|
-
// Build feature access map
|
|
17
|
-
const features: Record<string, boolean> = {};
|
|
18
|
-
for (const feature of LICENSE_FEATURES) {
|
|
19
|
-
features[feature] = canAccessFeature(tier, feature);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// Build limit map
|
|
23
|
-
const limits: Record<string, number> = {};
|
|
24
|
-
for (const key of Object.keys(TIER_LIMITS[tier]) as LimitResource[]) {
|
|
25
|
-
const val = TIER_LIMITS[tier][key];
|
|
26
|
-
limits[key] = val === Infinity ? -1 : val; // -1 = unlimited for JSON
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
return NextResponse.json({
|
|
30
|
-
tier: status.tier,
|
|
31
|
-
status: status.status,
|
|
32
|
-
email: status.email,
|
|
33
|
-
activatedAt: status.activatedAt?.toISOString() ?? null,
|
|
34
|
-
expiresAt: status.expiresAt?.toISOString() ?? null,
|
|
35
|
-
lastValidatedAt: status.lastValidatedAt?.toISOString() ?? null,
|
|
36
|
-
gracePeriodExpiresAt: status.gracePeriodExpiresAt?.toISOString() ?? null,
|
|
37
|
-
isPremium: tier !== "community",
|
|
38
|
-
features,
|
|
39
|
-
limits,
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* POST /api/license — activate a license.
|
|
45
|
-
* Accepts either a license key or direct tier/email/token (from Stripe webhook flow).
|
|
46
|
-
*/
|
|
47
|
-
export async function POST(req: NextRequest) {
|
|
48
|
-
const body = await req.json();
|
|
49
|
-
const parsed = activateLicenseSchema.safeParse(body);
|
|
50
|
-
|
|
51
|
-
if (!parsed.success) {
|
|
52
|
-
return NextResponse.json(
|
|
53
|
-
{ error: "Invalid request", details: parsed.error.flatten() },
|
|
54
|
-
{ status: 400 }
|
|
55
|
-
);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
const { tier, email, token } = parsed.data;
|
|
59
|
-
|
|
60
|
-
if (!tier || !email) {
|
|
61
|
-
return NextResponse.json(
|
|
62
|
-
{ error: "tier and email are required for activation" },
|
|
63
|
-
{ status: 400 }
|
|
64
|
-
);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
licenseManager.activate({
|
|
68
|
-
tier: tier as LicenseTier,
|
|
69
|
-
email,
|
|
70
|
-
encryptedToken: token,
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
return NextResponse.json({
|
|
74
|
-
success: true,
|
|
75
|
-
tier: licenseManager.getTier(),
|
|
76
|
-
status: licenseManager.getStatus().status,
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* DELETE /api/license — deactivate and revert to community.
|
|
82
|
-
*/
|
|
83
|
-
export async function DELETE() {
|
|
84
|
-
licenseManager.deactivate();
|
|
85
|
-
return NextResponse.json({
|
|
86
|
-
success: true,
|
|
87
|
-
tier: "community",
|
|
88
|
-
});
|
|
89
|
-
}
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import { NextResponse } from "next/server";
|
|
2
|
-
import { licenseManager } from "@/lib/license/manager";
|
|
3
|
-
import { getContextVersionCount, getActiveScheduleCount } from "@/lib/license/limit-queries";
|
|
4
|
-
import { getAllExecutions } from "@/lib/agents/execution-manager";
|
|
5
|
-
import { db } from "@/lib/db";
|
|
6
|
-
import { agentMemory } from "@/lib/db/schema";
|
|
7
|
-
import { eq, sql, desc } from "drizzle-orm";
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* GET /api/license/usage
|
|
11
|
-
* Returns current usage counts and limits for the subscription UI.
|
|
12
|
-
*/
|
|
13
|
-
export async function GET() {
|
|
14
|
-
// Find the profile with the most memories for the usage display
|
|
15
|
-
const topProfile = db
|
|
16
|
-
.select({
|
|
17
|
-
profileId: agentMemory.profileId,
|
|
18
|
-
count: sql<number>`count(*)`,
|
|
19
|
-
})
|
|
20
|
-
.from(agentMemory)
|
|
21
|
-
.where(eq(agentMemory.status, "active"))
|
|
22
|
-
.groupBy(agentMemory.profileId)
|
|
23
|
-
.orderBy(desc(sql`count(*)`))
|
|
24
|
-
.limit(1)
|
|
25
|
-
.get();
|
|
26
|
-
|
|
27
|
-
const memoryCount = topProfile?.count ?? 0;
|
|
28
|
-
|
|
29
|
-
// Find the profile with the most context versions
|
|
30
|
-
// Use the same top profile for consistency
|
|
31
|
-
const contextCount = topProfile?.profileId
|
|
32
|
-
? getContextVersionCount(topProfile.profileId)
|
|
33
|
-
: 0;
|
|
34
|
-
|
|
35
|
-
const scheduleCount = getActiveScheduleCount();
|
|
36
|
-
const parallelCount = getAllExecutions().size;
|
|
37
|
-
|
|
38
|
-
const limits = {
|
|
39
|
-
agentMemories: licenseManager.getLimit("agentMemories"),
|
|
40
|
-
contextVersions: licenseManager.getLimit("contextVersions"),
|
|
41
|
-
activeSchedules: licenseManager.getLimit("activeSchedules"),
|
|
42
|
-
parallelWorkflows: licenseManager.getLimit("parallelWorkflows"),
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
return NextResponse.json({
|
|
46
|
-
agentMemories: {
|
|
47
|
-
current: memoryCount,
|
|
48
|
-
limit: limits.agentMemories === Infinity ? -1 : limits.agentMemories,
|
|
49
|
-
},
|
|
50
|
-
contextVersions: {
|
|
51
|
-
current: contextCount,
|
|
52
|
-
limit: limits.contextVersions === Infinity ? -1 : limits.contextVersions,
|
|
53
|
-
},
|
|
54
|
-
activeSchedules: {
|
|
55
|
-
current: scheduleCount,
|
|
56
|
-
limit: limits.activeSchedules === Infinity ? -1 : limits.activeSchedules,
|
|
57
|
-
},
|
|
58
|
-
parallelWorkflows: {
|
|
59
|
-
current: parallelCount,
|
|
60
|
-
limit: limits.parallelWorkflows === Infinity ? -1 : limits.parallelWorkflows,
|
|
61
|
-
},
|
|
62
|
-
});
|
|
63
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { NextRequest, NextResponse } from "next/server";
|
|
2
|
-
import { browseBlueprints } from "@/lib/marketplace/marketplace-client";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* GET /api/marketplace/browse?page=1&category=general
|
|
6
|
-
* Browse published marketplace blueprints. Available to all tiers.
|
|
7
|
-
*/
|
|
8
|
-
export async function GET(req: NextRequest) {
|
|
9
|
-
const { searchParams } = req.nextUrl;
|
|
10
|
-
const page = parseInt(searchParams.get("page") ?? "1", 10);
|
|
11
|
-
const category = searchParams.get("category") ?? undefined;
|
|
12
|
-
|
|
13
|
-
const result = await browseBlueprints(page, category);
|
|
14
|
-
return NextResponse.json(result);
|
|
15
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { NextRequest, NextResponse } from "next/server";
|
|
2
|
-
import { licenseManager } from "@/lib/license/manager";
|
|
3
|
-
import { importBlueprint } from "@/lib/marketplace/marketplace-client";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* POST /api/marketplace/import
|
|
7
|
-
* Import a blueprint from the marketplace. Requires Solo+ tier.
|
|
8
|
-
*/
|
|
9
|
-
export async function POST(req: NextRequest) {
|
|
10
|
-
if (!licenseManager.isFeatureAllowed("marketplace-import")) {
|
|
11
|
-
return NextResponse.json(
|
|
12
|
-
{ error: "Blueprint import requires Solo tier or above" },
|
|
13
|
-
{ status: 402 }
|
|
14
|
-
);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const { blueprintId } = await req.json();
|
|
18
|
-
if (!blueprintId) {
|
|
19
|
-
return NextResponse.json({ error: "blueprintId required" }, { status: 400 });
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const result = await importBlueprint(blueprintId);
|
|
23
|
-
if (!result.success) {
|
|
24
|
-
return NextResponse.json({ error: result.error }, { status: 500 });
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
return NextResponse.json({ content: result.content });
|
|
28
|
-
}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { NextRequest, NextResponse } from "next/server";
|
|
2
|
-
import { licenseManager } from "@/lib/license/manager";
|
|
3
|
-
import { publishBlueprint } from "@/lib/marketplace/marketplace-client";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* POST /api/marketplace/publish
|
|
7
|
-
* Publish a workflow blueprint to the marketplace. Requires Operator+ tier.
|
|
8
|
-
*/
|
|
9
|
-
export async function POST(req: NextRequest) {
|
|
10
|
-
if (!licenseManager.isFeatureAllowed("marketplace-publish")) {
|
|
11
|
-
return NextResponse.json(
|
|
12
|
-
{ error: "Blueprint publishing requires Operator tier or above" },
|
|
13
|
-
{ status: 402 }
|
|
14
|
-
);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const body = await req.json();
|
|
18
|
-
const { title, description, category, content, tags } = body;
|
|
19
|
-
|
|
20
|
-
if (!title || !content) {
|
|
21
|
-
return NextResponse.json(
|
|
22
|
-
{ error: "title and content are required" },
|
|
23
|
-
{ status: 400 }
|
|
24
|
-
);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const result = await publishBlueprint({
|
|
28
|
-
title,
|
|
29
|
-
description: description ?? "",
|
|
30
|
-
category: category ?? "general",
|
|
31
|
-
content,
|
|
32
|
-
tags: tags ?? [],
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
if (!result.success) {
|
|
36
|
-
return NextResponse.json({ error: result.error }, { status: 500 });
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
return NextResponse.json({ id: result.id }, { status: 201 });
|
|
40
|
-
}
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { NextRequest, NextResponse } from "next/server";
|
|
2
|
-
import { z } from "zod";
|
|
3
|
-
import { getSupabaseClient } from "@/lib/cloud/supabase-client";
|
|
4
|
-
|
|
5
|
-
const emailSchema = z.object({
|
|
6
|
-
email: z.string().email(),
|
|
7
|
-
});
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* POST /api/onboarding/email
|
|
11
|
-
* Creates a Supabase Auth user via magic link.
|
|
12
|
-
* Fire-and-forget — does not block any local functionality.
|
|
13
|
-
*/
|
|
14
|
-
export async function POST(req: NextRequest) {
|
|
15
|
-
const body = await req.json();
|
|
16
|
-
const parsed = emailSchema.safeParse(body);
|
|
17
|
-
|
|
18
|
-
if (!parsed.success) {
|
|
19
|
-
return NextResponse.json(
|
|
20
|
-
{ error: "Valid email required" },
|
|
21
|
-
{ status: 400 }
|
|
22
|
-
);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const supabase = getSupabaseClient();
|
|
26
|
-
if (!supabase) {
|
|
27
|
-
// Cloud not configured — silently succeed
|
|
28
|
-
return NextResponse.json({ ok: true });
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
try {
|
|
32
|
-
const { error } = await supabase.auth.signInWithOtp({
|
|
33
|
-
email: parsed.data.email,
|
|
34
|
-
options: {
|
|
35
|
-
emailRedirectTo: `${process.env.NEXT_PUBLIC_SUPABASE_URL ?? "http://localhost:3000"}/auth/callback`,
|
|
36
|
-
},
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
if (error) {
|
|
40
|
-
return NextResponse.json(
|
|
41
|
-
{ error: error.message },
|
|
42
|
-
{ status: 502 }
|
|
43
|
-
);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
return NextResponse.json({ ok: true });
|
|
47
|
-
} catch {
|
|
48
|
-
return NextResponse.json(
|
|
49
|
-
{ error: "Failed to connect to cloud service" },
|
|
50
|
-
{ status: 502 }
|
|
51
|
-
);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { NextRequest, NextResponse } from "next/server";
|
|
2
|
-
import { getSetting, setSetting } from "@/lib/settings/helpers";
|
|
3
|
-
import { SETTINGS_KEYS } from "@/lib/constants/settings";
|
|
4
|
-
|
|
5
|
-
export async function GET() {
|
|
6
|
-
const enabled = await getSetting(SETTINGS_KEYS.TELEMETRY_ENABLED);
|
|
7
|
-
return NextResponse.json({ enabled: enabled === "true" });
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export async function POST(req: NextRequest) {
|
|
11
|
-
const { enabled } = await req.json();
|
|
12
|
-
await setSetting(SETTINGS_KEYS.TELEMETRY_ENABLED, String(!!enabled));
|
|
13
|
-
return NextResponse.json({ enabled: !!enabled });
|
|
14
|
-
}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { NextRequest, NextResponse } from "next/server";
|
|
2
|
-
import { licenseManager } from "@/lib/license/manager";
|
|
3
|
-
import { exportAndUpload } from "@/lib/sync/cloud-sync";
|
|
4
|
-
import { getSettingSync } from "@/lib/settings/helpers";
|
|
5
|
-
import { SETTINGS_KEYS } from "@/lib/constants/settings";
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* POST /api/sync/export
|
|
9
|
-
* Export and encrypt the database, upload to Supabase Storage.
|
|
10
|
-
* Requires Operator+ tier and an authenticated Supabase session.
|
|
11
|
-
* Body: { accessToken: string } — the user's Supabase JWT
|
|
12
|
-
*/
|
|
13
|
-
export async function POST(req: NextRequest) {
|
|
14
|
-
if (!licenseManager.isFeatureAllowed("cloud-sync")) {
|
|
15
|
-
return NextResponse.json(
|
|
16
|
-
{ error: "Cloud sync requires Operator tier or above" },
|
|
17
|
-
{ status: 402 }
|
|
18
|
-
);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const email = licenseManager.getStatus().email;
|
|
22
|
-
if (!email) {
|
|
23
|
-
return NextResponse.json(
|
|
24
|
-
{ error: "Sign in with your email first (Settings → Cloud Account)" },
|
|
25
|
-
{ status: 400 }
|
|
26
|
-
);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// Get the user's access token for authenticated Storage uploads
|
|
30
|
-
const body = await req.json().catch(() => ({}));
|
|
31
|
-
const accessToken = body.accessToken as string | undefined;
|
|
32
|
-
|
|
33
|
-
let deviceId = getSettingSync(SETTINGS_KEYS.DEVICE_ID);
|
|
34
|
-
if (!deviceId) {
|
|
35
|
-
deviceId = crypto.randomUUID();
|
|
36
|
-
const { setSetting } = await import("@/lib/settings/helpers");
|
|
37
|
-
await setSetting(SETTINGS_KEYS.DEVICE_ID, deviceId);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const result = await exportAndUpload(email, deviceId, accessToken);
|
|
41
|
-
|
|
42
|
-
if (!result.success) {
|
|
43
|
-
return NextResponse.json({ error: result.error }, { status: 500 });
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const { setSetting } = await import("@/lib/settings/helpers");
|
|
47
|
-
await setSetting(SETTINGS_KEYS.LAST_SYNC_AT, new Date().toISOString());
|
|
48
|
-
|
|
49
|
-
return NextResponse.json({
|
|
50
|
-
success: true,
|
|
51
|
-
blobPath: result.blobPath,
|
|
52
|
-
sizeBytes: result.sizeBytes,
|
|
53
|
-
});
|
|
54
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { NextResponse } from "next/server";
|
|
2
|
-
import { licenseManager } from "@/lib/license/manager";
|
|
3
|
-
import { downloadAndRestore } from "@/lib/sync/cloud-sync";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* POST /api/sync/restore
|
|
7
|
-
* Download the latest snapshot, decrypt, and restore.
|
|
8
|
-
* Requires Operator+ tier. Creates a safety backup first.
|
|
9
|
-
*/
|
|
10
|
-
export async function POST() {
|
|
11
|
-
if (!licenseManager.isFeatureAllowed("cloud-sync")) {
|
|
12
|
-
return NextResponse.json(
|
|
13
|
-
{ error: "Cloud sync requires Operator tier or above" },
|
|
14
|
-
{ status: 402 }
|
|
15
|
-
);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const email = licenseManager.getStatus().email;
|
|
19
|
-
if (!email) {
|
|
20
|
-
return NextResponse.json(
|
|
21
|
-
{ error: "No license email — activate your license first" },
|
|
22
|
-
{ status: 400 }
|
|
23
|
-
);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const result = await downloadAndRestore(email);
|
|
27
|
-
|
|
28
|
-
if (!result.success) {
|
|
29
|
-
return NextResponse.json({ error: result.error }, { status: 500 });
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
return NextResponse.json({
|
|
33
|
-
success: true,
|
|
34
|
-
sizeBytes: result.sizeBytes,
|
|
35
|
-
message: "Database restored. Restart the app to apply changes.",
|
|
36
|
-
});
|
|
37
|
-
}
|