@agent-native/core 0.101.14 → 0.102.1
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/corpus/README.md +1 -1
- package/corpus/core/CHANGELOG.md +12 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/cli/templates-meta.ts +13 -0
- package/corpus/core/src/client/agent-page/AgentTabsPage.tsx +1 -1
- package/corpus/core/src/client/org/OrgSwitcher.tsx +2 -0
- package/corpus/templates/analytics/changelog/2026-07-15-fixed-the-agent-discarding-a-successful-dashboard-edit-and-r.md +6 -0
- package/corpus/templates/analytics/server/lib/real-data-actions.ts +30 -1
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +15 -0
- package/corpus/templates/content/actions/_database-source-utils.ts +59 -4
- package/corpus/templates/content/actions/prepare-builder-source-review.ts +9 -0
- package/corpus/templates/content/actions/preview-builder-source-review.ts +6 -4
- package/corpus/templates/content/app/components/editor/DescriptionField.tsx +10 -2
- package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +4 -0
- package/corpus/templates/content/changelog/2026-07-15-page-and-database-descriptions-now-use-a-clean-single-line-f.md +6 -0
- package/corpus/templates/content/changelog/2026-07-15-selected-builder-reviews-now-load-only-the-chosen-rows-avoid.md +6 -0
- package/corpus/templates/content/shared/api.ts +1 -0
- package/corpus/templates/tasks/.agents/commands/visual-plan.md +9 -0
- package/corpus/templates/tasks/.agents/commands/visual-recap.md +8 -0
- package/corpus/templates/tasks/.agents/skills/actions/SKILL.md +492 -0
- package/corpus/templates/tasks/.agents/skills/adding-a-feature/SKILL.md +189 -0
- package/corpus/templates/tasks/.agents/skills/agent-native-docs/SKILL.md +76 -0
- package/corpus/templates/tasks/.agents/skills/agent-watchdog/README.md +43 -0
- package/corpus/templates/tasks/.agents/skills/agent-watchdog/SKILL.md +110 -0
- package/corpus/templates/tasks/.agents/skills/agent-watchdog/agents/openai.yaml +4 -0
- package/corpus/templates/tasks/.agents/skills/capture-learnings/SKILL.md +89 -0
- package/corpus/templates/tasks/.agents/skills/change-summary/SKILL.md +83 -0
- package/corpus/templates/tasks/.agents/skills/create-skill/SKILL.md +221 -0
- package/corpus/templates/tasks/.agents/skills/delegate-to-agent/SKILL.md +263 -0
- package/corpus/templates/tasks/.agents/skills/efficient-fable/README.md +75 -0
- package/corpus/templates/tasks/.agents/skills/efficient-fable/SKILL.md +95 -0
- package/corpus/templates/tasks/.agents/skills/efficient-frontier/README.md +53 -0
- package/corpus/templates/tasks/.agents/skills/efficient-frontier/SKILL.md +73 -0
- package/corpus/templates/tasks/.agents/skills/frontend-design/SKILL.md +112 -0
- package/corpus/templates/tasks/.agents/skills/plan-arbiter/README.md +41 -0
- package/corpus/templates/tasks/.agents/skills/plan-arbiter/SKILL.md +114 -0
- package/corpus/templates/tasks/.agents/skills/plan-arbiter/agents/openai.yaml +4 -0
- package/corpus/templates/tasks/.agents/skills/plow-ahead/README.md +42 -0
- package/corpus/templates/tasks/.agents/skills/plow-ahead/SKILL.md +104 -0
- package/corpus/templates/tasks/.agents/skills/plow-ahead/agents/openai.yaml +4 -0
- package/corpus/templates/tasks/.agents/skills/quick-recap/README.md +55 -0
- package/corpus/templates/tasks/.agents/skills/quick-recap/SKILL.md +54 -0
- package/corpus/templates/tasks/.agents/skills/read-the-damn-docs/README.md +54 -0
- package/corpus/templates/tasks/.agents/skills/read-the-damn-docs/SKILL.md +126 -0
- package/corpus/templates/tasks/.agents/skills/read-the-damn-docs/agents/openai.yaml +4 -0
- package/corpus/templates/tasks/.agents/skills/real-time-sync/SKILL.md +232 -0
- package/corpus/templates/tasks/.agents/skills/security/SKILL.md +280 -0
- package/corpus/templates/tasks/.agents/skills/self-modifying-code/SKILL.md +106 -0
- package/corpus/templates/tasks/.agents/skills/shadcn-ui/SKILL.md +95 -0
- package/corpus/templates/tasks/.agents/skills/stay-within-limits/README.md +61 -0
- package/corpus/templates/tasks/.agents/skills/stay-within-limits/SKILL.md +83 -0
- package/corpus/templates/tasks/.agents/skills/upgrade-agent-native/SKILL.md +87 -0
- package/corpus/templates/tasks/.agents/skills/visual-plan/SKILL.md +547 -0
- package/corpus/templates/tasks/.agents/skills/visual-plan/agent-native-skill.json +12 -0
- package/corpus/templates/tasks/.agents/skills/visual-plan/references/canvas.md +121 -0
- package/corpus/templates/tasks/.agents/skills/visual-plan/references/document-quality.md +178 -0
- package/corpus/templates/tasks/.agents/skills/visual-plan/references/exemplar.md +62 -0
- package/corpus/templates/tasks/.agents/skills/visual-plan/references/wireframe.md +264 -0
- package/corpus/templates/tasks/.agents/skills/visual-recap/SKILL.md +634 -0
- package/corpus/templates/tasks/.agents/skills/visual-recap/agent-native-skill.json +12 -0
- package/corpus/templates/tasks/.agents/skills/visual-recap/references/wireframe.md +264 -0
- package/corpus/templates/tasks/.claude/commands/visual-plan.md +9 -0
- package/corpus/templates/tasks/.claude/commands/visual-recap.md +8 -0
- package/corpus/templates/tasks/.env.example +5 -0
- package/corpus/templates/tasks/.ignore +0 -0
- package/corpus/templates/tasks/.prettierrc +5 -0
- package/corpus/templates/tasks/AGENTS.md +158 -0
- package/corpus/templates/tasks/DEVELOPING.md +185 -0
- package/corpus/templates/tasks/README.md +16 -0
- package/corpus/templates/tasks/actions/bulk-delete-inbox-items.ts +24 -0
- package/corpus/templates/tasks/actions/bulk-delete-tasks.ts +21 -0
- package/corpus/templates/tasks/actions/bulk-mark-inbox-items-ready.ts +27 -0
- package/corpus/templates/tasks/actions/bulk-update-tasks.ts +35 -0
- package/corpus/templates/tasks/actions/create-custom-field.ts +22 -0
- package/corpus/templates/tasks/actions/create-inbox-item.ts +30 -0
- package/corpus/templates/tasks/actions/create-task.ts +33 -0
- package/corpus/templates/tasks/actions/delete-custom-field.ts +19 -0
- package/corpus/templates/tasks/actions/delete-inbox-item.ts +17 -0
- package/corpus/templates/tasks/actions/delete-task.ts +17 -0
- package/corpus/templates/tasks/actions/lib/boolean-query-param.ts +30 -0
- package/corpus/templates/tasks/actions/list-custom-fields.ts +18 -0
- package/corpus/templates/tasks/actions/list-inbox-items.ts +16 -0
- package/corpus/templates/tasks/actions/list-tasks.ts +52 -0
- package/corpus/templates/tasks/actions/list-visible-task-fields.ts +18 -0
- package/corpus/templates/tasks/actions/mark-inbox-item-ready.ts +31 -0
- package/corpus/templates/tasks/actions/navigate.ts +51 -0
- package/corpus/templates/tasks/actions/reorder-custom-fields.ts +27 -0
- package/corpus/templates/tasks/actions/reorder-inbox-items.ts +24 -0
- package/corpus/templates/tasks/actions/reorder-tasks.ts +29 -0
- package/corpus/templates/tasks/actions/run.ts +2 -0
- package/corpus/templates/tasks/actions/update-custom-field.ts +33 -0
- package/corpus/templates/tasks/actions/update-inbox-item.ts +24 -0
- package/corpus/templates/tasks/actions/update-task.ts +68 -0
- package/corpus/templates/tasks/actions/update-visible-task-fields.ts +27 -0
- package/corpus/templates/tasks/actions/view-screen-helpers.ts +68 -0
- package/corpus/templates/tasks/actions/view-screen.ts +207 -0
- package/corpus/templates/tasks/app/components/custom-fields/FieldCreateBar.tsx +121 -0
- package/corpus/templates/tasks/app/components/custom-fields/FieldListRow.tsx +116 -0
- package/corpus/templates/tasks/app/components/custom-fields/FieldsList.tsx +225 -0
- package/corpus/templates/tasks/app/components/custom-fields/FieldsListSkeleton.tsx +18 -0
- package/corpus/templates/tasks/app/components/custom-fields/FieldsPage.tsx +42 -0
- package/corpus/templates/tasks/app/components/custom-fields/editor/FieldEditorSidebar.tsx +69 -0
- package/corpus/templates/tasks/app/components/custom-fields/editor/FieldTitleSection.tsx +32 -0
- package/corpus/templates/tasks/app/components/custom-fields/editor/config/CurrencyConfigControl.tsx +49 -0
- package/corpus/templates/tasks/app/components/custom-fields/editor/config/FieldConfigControl.tsx +56 -0
- package/corpus/templates/tasks/app/components/custom-fields/editor/config/NumberConfigControl.tsx +52 -0
- package/corpus/templates/tasks/app/components/custom-fields/editor/config/PercentConfigControl.tsx +30 -0
- package/corpus/templates/tasks/app/components/custom-fields/editor/config/SelectConfigControl.tsx +135 -0
- package/corpus/templates/tasks/app/components/custom-fields/editor/config/select-colors.ts +23 -0
- package/corpus/templates/tasks/app/components/custom-fields/editor/config/utils.ts +52 -0
- package/corpus/templates/tasks/app/components/custom-fields/editor/types.ts +7 -0
- package/corpus/templates/tasks/app/components/dnd/SortableItem.tsx +72 -0
- package/corpus/templates/tasks/app/components/dnd/SortableList.tsx +136 -0
- package/corpus/templates/tasks/app/components/dnd/reorder-moving-items.ts +160 -0
- package/corpus/templates/tasks/app/components/dnd/sortable-drag-props.ts +60 -0
- package/corpus/templates/tasks/app/components/inbox/InboxList.tsx +222 -0
- package/corpus/templates/tasks/app/components/inbox/InboxListPage.tsx +39 -0
- package/corpus/templates/tasks/app/components/inbox/InboxListRow.tsx +122 -0
- package/corpus/templates/tasks/app/components/layout/Header.tsx +55 -0
- package/corpus/templates/tasks/app/components/layout/HeaderActions.tsx +84 -0
- package/corpus/templates/tasks/app/components/layout/Layout.tsx +134 -0
- package/corpus/templates/tasks/app/components/layout/Sidebar.tsx +211 -0
- package/corpus/templates/tasks/app/components/shared/AddListItemInput.tsx +57 -0
- package/corpus/templates/tasks/app/components/shared/AlertDialog.tsx +53 -0
- package/corpus/templates/tasks/app/components/shared/BulkDeleteDialog.tsx +76 -0
- package/corpus/templates/tasks/app/components/shared/ChipSelect.tsx +240 -0
- package/corpus/templates/tasks/app/components/shared/DeleteItemDialog.tsx +40 -0
- package/corpus/templates/tasks/app/components/shared/InlineEditable.tsx +166 -0
- package/corpus/templates/tasks/app/components/shared/ListEmptyState.tsx +13 -0
- package/corpus/templates/tasks/app/components/shared/ListErrorMessage.tsx +15 -0
- package/corpus/templates/tasks/app/components/shared/ListViewHeader.tsx +75 -0
- package/corpus/templates/tasks/app/components/shared/PageHeader.tsx +25 -0
- package/corpus/templates/tasks/app/components/shared/RowActionsMenu.tsx +42 -0
- package/corpus/templates/tasks/app/components/shared/SidePanel.tsx +99 -0
- package/corpus/templates/tasks/app/components/shared/dnd/ListRowPreview.tsx +37 -0
- package/corpus/templates/tasks/app/components/shared/list/List.tsx +63 -0
- package/corpus/templates/tasks/app/components/shared/list/ListRow.tsx +159 -0
- package/corpus/templates/tasks/app/components/shared/list/ListRowDragHandle.tsx +52 -0
- package/corpus/templates/tasks/app/components/shared/list/ListSkeletonRows.tsx +11 -0
- package/corpus/templates/tasks/app/components/shared/list/SortableListItemShell.tsx +32 -0
- package/corpus/templates/tasks/app/components/shared/list/types.ts +1 -0
- package/corpus/templates/tasks/app/components/shared/selection/ListSelectionBar.tsx +158 -0
- package/corpus/templates/tasks/app/components/shared/selection/ListSelectionHeaderToggle.tsx +28 -0
- package/corpus/templates/tasks/app/components/shared/selection/ListSelectionToolbar.tsx +81 -0
- package/corpus/templates/tasks/app/components/shared/selection/get-list-row-selection-ui.ts +41 -0
- package/corpus/templates/tasks/app/components/shared/selection/use-list-selection.ts +196 -0
- package/corpus/templates/tasks/app/components/tasks/TaskList.tsx +333 -0
- package/corpus/templates/tasks/app/components/tasks/TaskListHeaderRow.tsx +46 -0
- package/corpus/templates/tasks/app/components/tasks/TaskListPage.tsx +115 -0
- package/corpus/templates/tasks/app/components/tasks/TaskListRow.css +49 -0
- package/corpus/templates/tasks/app/components/tasks/TaskListRow.tsx +307 -0
- package/corpus/templates/tasks/app/components/tasks/fields/TaskFieldsSidebar.tsx +102 -0
- package/corpus/templates/tasks/app/components/tasks/fields/TaskTitleSection.tsx +27 -0
- package/corpus/templates/tasks/app/components/tasks/fields/controls/DateValueControl.tsx +21 -0
- package/corpus/templates/tasks/app/components/tasks/fields/controls/FieldValueControl.tsx +76 -0
- package/corpus/templates/tasks/app/components/tasks/fields/controls/MultiSelectValueControl.tsx +52 -0
- package/corpus/templates/tasks/app/components/tasks/fields/controls/NumberValueControl.tsx +56 -0
- package/corpus/templates/tasks/app/components/tasks/fields/controls/RichTextValueControl.tsx +115 -0
- package/corpus/templates/tasks/app/components/tasks/fields/controls/SingleSelectValueControl.tsx +61 -0
- package/corpus/templates/tasks/app/components/tasks/fields/controls/TextValueControl.tsx +20 -0
- package/corpus/templates/tasks/app/components/tasks/use-task-row-completion-animation.ts +181 -0
- package/corpus/templates/tasks/app/components/ui/accordion.tsx +56 -0
- package/corpus/templates/tasks/app/components/ui/alert-dialog.tsx +1 -0
- package/corpus/templates/tasks/app/components/ui/alert.tsx +1 -0
- package/corpus/templates/tasks/app/components/ui/aspect-ratio.tsx +5 -0
- package/corpus/templates/tasks/app/components/ui/avatar.tsx +1 -0
- package/corpus/templates/tasks/app/components/ui/badge.tsx +1 -0
- package/corpus/templates/tasks/app/components/ui/breadcrumb.tsx +115 -0
- package/corpus/templates/tasks/app/components/ui/button.tsx +1 -0
- package/corpus/templates/tasks/app/components/ui/calendar.tsx +70 -0
- package/corpus/templates/tasks/app/components/ui/card.tsx +1 -0
- package/corpus/templates/tasks/app/components/ui/carousel.tsx +260 -0
- package/corpus/templates/tasks/app/components/ui/chart.tsx +379 -0
- package/corpus/templates/tasks/app/components/ui/checkbox.tsx +1 -0
- package/corpus/templates/tasks/app/components/ui/collapsible.tsx +1 -0
- package/corpus/templates/tasks/app/components/ui/command.tsx +1 -0
- package/corpus/templates/tasks/app/components/ui/context-menu.tsx +1 -0
- package/corpus/templates/tasks/app/components/ui/dialog.tsx +1 -0
- package/corpus/templates/tasks/app/components/ui/drawer.tsx +1 -0
- package/corpus/templates/tasks/app/components/ui/dropdown-menu.tsx +1 -0
- package/corpus/templates/tasks/app/components/ui/form.tsx +177 -0
- package/corpus/templates/tasks/app/components/ui/hover-card.tsx +27 -0
- package/corpus/templates/tasks/app/components/ui/input-otp.tsx +69 -0
- package/corpus/templates/tasks/app/components/ui/input.tsx +1 -0
- package/corpus/templates/tasks/app/components/ui/label.tsx +1 -0
- package/corpus/templates/tasks/app/components/ui/menubar.tsx +254 -0
- package/corpus/templates/tasks/app/components/ui/navigation-menu.tsx +128 -0
- package/corpus/templates/tasks/app/components/ui/pagination.tsx +121 -0
- package/corpus/templates/tasks/app/components/ui/popover.tsx +1 -0
- package/corpus/templates/tasks/app/components/ui/progress.tsx +1 -0
- package/corpus/templates/tasks/app/components/ui/radio-group.tsx +1 -0
- package/corpus/templates/tasks/app/components/ui/resizable.tsx +43 -0
- package/corpus/templates/tasks/app/components/ui/scroll-area.tsx +1 -0
- package/corpus/templates/tasks/app/components/ui/select.tsx +1 -0
- package/corpus/templates/tasks/app/components/ui/separator.tsx +1 -0
- package/corpus/templates/tasks/app/components/ui/sheet.tsx +1 -0
- package/corpus/templates/tasks/app/components/ui/sidebar.tsx +782 -0
- package/corpus/templates/tasks/app/components/ui/skeleton.tsx +1 -0
- package/corpus/templates/tasks/app/components/ui/slider.tsx +1 -0
- package/corpus/templates/tasks/app/components/ui/sonner.tsx +1 -0
- package/corpus/templates/tasks/app/components/ui/spinner.tsx +1 -0
- package/corpus/templates/tasks/app/components/ui/switch.tsx +1 -0
- package/corpus/templates/tasks/app/components/ui/table.tsx +1 -0
- package/corpus/templates/tasks/app/components/ui/tabs.tsx +1 -0
- package/corpus/templates/tasks/app/components/ui/textarea.tsx +1 -0
- package/corpus/templates/tasks/app/components/ui/toast.tsx +1 -0
- package/corpus/templates/tasks/app/components/ui/toaster.tsx +1 -0
- package/corpus/templates/tasks/app/components/ui/toggle-group.tsx +1 -0
- package/corpus/templates/tasks/app/components/ui/toggle.tsx +43 -0
- package/corpus/templates/tasks/app/components/ui/tooltip.tsx +1 -0
- package/corpus/templates/tasks/app/components/ui/use-toast.ts +3 -0
- package/corpus/templates/tasks/app/entry.client.tsx +19 -0
- package/corpus/templates/tasks/app/entry.server.tsx +10 -0
- package/corpus/templates/tasks/app/global.css +93 -0
- package/corpus/templates/tasks/app/hooks/cache.ts +31 -0
- package/corpus/templates/tasks/app/hooks/use-custom-fields.ts +93 -0
- package/corpus/templates/tasks/app/hooks/use-inbox-items.ts +196 -0
- package/corpus/templates/tasks/app/hooks/use-mobile.tsx +21 -0
- package/corpus/templates/tasks/app/hooks/use-navigation-state.ts +40 -0
- package/corpus/templates/tasks/app/hooks/use-tasks.ts +276 -0
- package/corpus/templates/tasks/app/hooks/use-toast.ts +188 -0
- package/corpus/templates/tasks/app/hooks/use-visible-task-fields.ts +140 -0
- package/corpus/templates/tasks/app/lib/app-config.ts +11 -0
- package/corpus/templates/tasks/app/lib/tab-id.ts +1 -0
- package/corpus/templates/tasks/app/lib/utils.ts +1 -0
- package/corpus/templates/tasks/app/root.tsx +130 -0
- package/corpus/templates/tasks/app/routes/_index.tsx +22 -0
- package/corpus/templates/tasks/app/routes/extensions.$id.$slug.tsx +2 -0
- package/corpus/templates/tasks/app/routes/extensions.$id.tsx +11 -0
- package/corpus/templates/tasks/app/routes/extensions._index.tsx +11 -0
- package/corpus/templates/tasks/app/routes/extensions.tsx +5 -0
- package/corpus/templates/tasks/app/routes/fields.tsx +16 -0
- package/corpus/templates/tasks/app/routes/inbox.tsx +16 -0
- package/corpus/templates/tasks/app/routes/tasks.tsx +17 -0
- package/corpus/templates/tasks/app/routes/team.tsx +17 -0
- package/corpus/templates/tasks/app/routes.ts +4 -0
- package/corpus/templates/tasks/app/vite-env.d.ts +6 -0
- package/corpus/templates/tasks/components.json +20 -0
- package/corpus/templates/tasks/data/sync-config.json +1 -0
- package/corpus/templates/tasks/docs/features/README.md +81 -0
- package/corpus/templates/tasks/docs/features/f1-tasks.mdx +67 -0
- package/corpus/templates/tasks/docs/features/f2-custom-fields.mdx +68 -0
- package/corpus/templates/tasks/docs/features/f3-projects.mdx +33 -0
- package/corpus/templates/tasks/docs/features/f4-inbox.mdx +55 -0
- package/corpus/templates/tasks/docs/features/f5-views.mdx +65 -0
- package/corpus/templates/tasks/docs/features/f6-search.mdx +43 -0
- package/corpus/templates/tasks/docs/features/f7-first-run.mdx +66 -0
- package/corpus/templates/tasks/docs/features/f8-chat.mdx +120 -0
- package/corpus/templates/tasks/e2e/global-setup.ts +42 -0
- package/corpus/templates/tasks/e2e/helpers/inbox.ts +71 -0
- package/corpus/templates/tasks/e2e/helpers/tasks.ts +99 -0
- package/corpus/templates/tasks/learnings.defaults.md +5 -0
- package/corpus/templates/tasks/netlify.toml +10 -0
- package/corpus/templates/tasks/package.json +104 -0
- package/corpus/templates/tasks/playwright.config.ts +34 -0
- package/corpus/templates/tasks/public/agent-native-icon-dark.svg +10 -0
- package/corpus/templates/tasks/public/agent-native-icon-light.svg +10 -0
- package/corpus/templates/tasks/public/agent-native-logo-dark.svg +21 -0
- package/corpus/templates/tasks/public/agent-native-logo-light.svg +21 -0
- package/corpus/templates/tasks/public/favicon.svg +1 -0
- package/corpus/templates/tasks/public/icon-180.svg +1 -0
- package/corpus/templates/tasks/public/icon-192.svg +1 -0
- package/corpus/templates/tasks/public/icon-512.svg +1 -0
- package/corpus/templates/tasks/public/manifest.json +21 -0
- package/corpus/templates/tasks/react-router.config.ts +7 -0
- package/corpus/templates/tasks/server/custom-fields/normalize.ts +163 -0
- package/corpus/templates/tasks/server/custom-fields/parse.ts +146 -0
- package/corpus/templates/tasks/server/custom-fields/schema.ts +147 -0
- package/corpus/templates/tasks/server/custom-fields/store.ts +425 -0
- package/corpus/templates/tasks/server/custom-fields/task-fields.ts +104 -0
- package/corpus/templates/tasks/server/custom-fields/types.ts +98 -0
- package/corpus/templates/tasks/server/custom-fields/validate.ts +210 -0
- package/corpus/templates/tasks/server/custom-fields/values/store.ts +386 -0
- package/corpus/templates/tasks/server/db/bulk-write.ts +30 -0
- package/corpus/templates/tasks/server/db/index.ts +5 -0
- package/corpus/templates/tasks/server/db/record-utils.ts +7 -0
- package/corpus/templates/tasks/server/db/schema.ts +67 -0
- package/corpus/templates/tasks/server/db/test-tasks-table.ts +76 -0
- package/corpus/templates/tasks/server/db/transaction.ts +6 -0
- package/corpus/templates/tasks/server/errors.ts +31 -0
- package/corpus/templates/tasks/server/inbox/store.ts +216 -0
- package/corpus/templates/tasks/server/middleware/auth.ts +15 -0
- package/corpus/templates/tasks/server/plugins/agent-chat.ts +46 -0
- package/corpus/templates/tasks/server/plugins/auth.ts +15 -0
- package/corpus/templates/tasks/server/plugins/db.ts +90 -0
- package/corpus/templates/tasks/server/routes/[...page].get.ts +5 -0
- package/corpus/templates/tasks/server/stored-items/store.ts +548 -0
- package/corpus/templates/tasks/server/tasks/store.ts +306 -0
- package/corpus/templates/tasks/server/user-config/store.ts +138 -0
- package/corpus/templates/tasks/shared/app-state-tabs.ts +15 -0
- package/corpus/templates/tasks/shared/boolean-param.ts +22 -0
- package/corpus/templates/tasks/shared/bulk-limits.ts +7 -0
- package/corpus/templates/tasks/shared/list-screen-snapshot.ts +90 -0
- package/corpus/templates/tasks/shared/navigation.ts +104 -0
- package/corpus/templates/tasks/shared/visible-task-fields.ts +2 -0
- package/corpus/templates/tasks/ssr-entry.ts +15 -0
- package/corpus/templates/tasks/tsconfig.json +24 -0
- package/corpus/templates/tasks/vite.config.ts +19 -0
- package/corpus/templates/tasks/vitest.config.ts +8 -0
- package/dist/cli/templates-meta.d.ts.map +1 -1
- package/dist/cli/templates-meta.js +13 -0
- package/dist/cli/templates-meta.js.map +1 -1
- package/dist/client/agent-page/AgentTabsPage.js +1 -1
- package/dist/client/agent-page/AgentTabsPage.js.map +1 -1
- package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
- package/dist/client/org/OrgSwitcher.js +2 -1
- package/dist/client/org/OrgSwitcher.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/notifications/routes.d.ts +2 -2
- package/dist/observability/routes.d.ts +5 -5
- package/dist/resources/handlers.d.ts +3 -3
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: F5
|
|
3
|
+
title: Views
|
|
4
|
+
status: planned
|
|
5
|
+
order: 5
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# F5 — Views
|
|
9
|
+
|
|
10
|
+
<!-- status: todo -->
|
|
11
|
+
|
|
12
|
+
## What it is
|
|
13
|
+
|
|
14
|
+
A **view** is how the [F1 task](./f1-tasks.mdx) list is arranged: what's visible, in what order, and how rows are clustered. **Views** impose structure: filter to a subset, sort by a field, or group under headings. Users change the arrangement ad hoc or **save** it under a name and switch between saved views later.
|
|
15
|
+
|
|
16
|
+
The main task page today uses a simple **completed-task filter** (see F1). Saved views, sort, and group ship with this feature.
|
|
17
|
+
|
|
18
|
+
Examples: "Open", "High priority", "By project".
|
|
19
|
+
|
|
20
|
+
## What users can do
|
|
21
|
+
|
|
22
|
+
### Arrange the list
|
|
23
|
+
|
|
24
|
+
- **Filter** — show only tasks matching criteria (completion, [project](./f3-projects.mdx), [custom fields](./f2-custom-fields.mdx)); multiple filters use AND logic. Quick filter: **Incomplete tasks**.
|
|
25
|
+
- **Sort** — by completion, title, project, custom field, date created, etc., or **None** for manual order.
|
|
26
|
+
- **Group** — cluster rows under headings (by project, completion, custom field, etc.). Grouping is display-only.
|
|
27
|
+
|
|
28
|
+
Filter, sort, and group work together on the current list.
|
|
29
|
+
|
|
30
|
+
### Saved views
|
|
31
|
+
|
|
32
|
+
- **Create** a view with a name and chosen filter, sort, and group settings.
|
|
33
|
+
- **Switch**, **modify**, **duplicate**, or **delete** views.
|
|
34
|
+
- A default view ("All tasks") always exists; it can be renamed but not deleted.
|
|
35
|
+
|
|
36
|
+
### Scope
|
|
37
|
+
|
|
38
|
+
| Where | Views available |
|
|
39
|
+
| ------------------ | ----------------------------------------- |
|
|
40
|
+
| **Main task page** | Global views — all tasks across projects |
|
|
41
|
+
| **Project page** | Project views — only that project's tasks |
|
|
42
|
+
|
|
43
|
+
Global and project view lists are separate; the same name can exist in different projects.
|
|
44
|
+
|
|
45
|
+
## How it behaves
|
|
46
|
+
|
|
47
|
+
### Sort and manual order
|
|
48
|
+
|
|
49
|
+
- **Sort: None** — manual drag-and-drop order applies (F1). This is the only mode where reordering works.
|
|
50
|
+
- **Sort by a field** — tasks order by that field; **drag reorder is disabled** until sort is set back to None.
|
|
51
|
+
- **Group by** a field — tasks cluster under headings. You can **sort within groups** (e.g. group by project, sort by due date inside each group).
|
|
52
|
+
- Switching away from a sorted view and back to **None** restores the last manual order.
|
|
53
|
+
|
|
54
|
+
### Saved views
|
|
55
|
+
|
|
56
|
+
Filter, sort, and group settings are stored in the view. Opening a saved view applies that layout. Starter views ship with the app ([F7](./f7-first-run.mdx)).
|
|
57
|
+
|
|
58
|
+
- Switching views changes display only — tasks are not modified.
|
|
59
|
+
- One view is active at a time per page.
|
|
60
|
+
- Only **ready** tasks appear ([F4 Inbox](./f4-inbox.mdx) excluded).
|
|
61
|
+
|
|
62
|
+
## Limits (v1)
|
|
63
|
+
|
|
64
|
+
- List layout only — no board or calendar view types.
|
|
65
|
+
- No OR filter logic or shared views between users.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: F6
|
|
3
|
+
title: Search
|
|
4
|
+
status: planned
|
|
5
|
+
order: 6
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# F6 — Search
|
|
9
|
+
|
|
10
|
+
<!-- status: todo -->
|
|
11
|
+
|
|
12
|
+
## What it is
|
|
13
|
+
|
|
14
|
+
**Search** finds [F1 tasks](./f1-tasks.mdx) and [F3 projects](./f3-projects.mdx) by typing a query — a fast way to jump to something known instead of browsing [F5 views](./f5-views.mdx) or scrolling the list. Search uses **titles and names only** — not [custom field](./f2-custom-fields.mdx) values.
|
|
15
|
+
|
|
16
|
+
## What users can do
|
|
17
|
+
|
|
18
|
+
- **Search** from a global entry.
|
|
19
|
+
- **Find tasks** by title.
|
|
20
|
+
- **Find projects** by name.
|
|
21
|
+
- **Open** a result to go to that task or project.
|
|
22
|
+
- **Clear** search to return to the previous screen.
|
|
23
|
+
|
|
24
|
+
## How it behaves
|
|
25
|
+
|
|
26
|
+
- **Substring match**, case-insensitive — "report" finds "Draft Q2 report".
|
|
27
|
+
- Results grouped by type (task vs project).
|
|
28
|
+
|
|
29
|
+
### Scope
|
|
30
|
+
|
|
31
|
+
| Search from | Tasks | Projects |
|
|
32
|
+
| ----------------------- | --------------------- | -------- |
|
|
33
|
+
| Global / main | All tasks | All |
|
|
34
|
+
| Project page | Tasks in that project | — |
|
|
35
|
+
| [Inbox](./f4-inbox.mdx) | Not-ready inbox items | — |
|
|
36
|
+
|
|
37
|
+
Search complements views — it jumps to items; views arrange a list you're already on.
|
|
38
|
+
|
|
39
|
+
## Limits (v1)
|
|
40
|
+
|
|
41
|
+
- Task search matches **title** only — not description, due date, or other [custom fields](./f2-custom-fields.mdx).
|
|
42
|
+
- No saved searches — use [F5 views](./f5-views.mdx) for repeatable filters.
|
|
43
|
+
- No fuzzy match or ranking.
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: F7
|
|
3
|
+
title: First-run experience
|
|
4
|
+
status: partial
|
|
5
|
+
order: 7
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# F7 — First-run experience
|
|
9
|
+
|
|
10
|
+
## What it is
|
|
11
|
+
|
|
12
|
+
A new install ships ready to use — with more pre-configuration added over time. **Completion** (complete / incomplete) is built into every task from day one — not a custom field.
|
|
13
|
+
|
|
14
|
+
<!-- status: done -->
|
|
15
|
+
|
|
16
|
+
## First run (shipped)
|
|
17
|
+
|
|
18
|
+
- **Main task page** — empty task list; **completed tasks filtered out** by default (user can show all).
|
|
19
|
+
- **No sample tasks** — a clean slate.
|
|
20
|
+
- **No** projects, custom fields, or saved views yet.
|
|
21
|
+
|
|
22
|
+
<!-- status: partial -->
|
|
23
|
+
|
|
24
|
+
## First run (extended)
|
|
25
|
+
|
|
26
|
+
A fuller install adds custom fields, starter views, and the inbox.
|
|
27
|
+
|
|
28
|
+
<!-- status: todo -->
|
|
29
|
+
|
|
30
|
+
### Custom fields (pre-created)
|
|
31
|
+
|
|
32
|
+
| Field | Type | Starter configuration |
|
|
33
|
+
| ------------ | ------------- | ---------------------------------------- |
|
|
34
|
+
| **Notes** | Rich text | Empty by default — long-form description |
|
|
35
|
+
| **Due date** | Date | Empty by default |
|
|
36
|
+
| **Priority** | Single-select | **Low**, **Medium**, **High** |
|
|
37
|
+
|
|
38
|
+
No other fields should be created automatically. Users may add more fields at any time (e.g. a single-select for workflow stage). Users can rename, extend, or delete any starter custom field.
|
|
39
|
+
|
|
40
|
+
<!-- status: todo -->
|
|
41
|
+
|
|
42
|
+
### Starter views (global)
|
|
43
|
+
|
|
44
|
+
| View | Filter | Sort | Group |
|
|
45
|
+
| --------------- | ------------------------------ | -------------------- | ------- |
|
|
46
|
+
| **All tasks** | None (complete and incomplete) | None (manual order) | None |
|
|
47
|
+
| **Open** | Incomplete tasks | None | None |
|
|
48
|
+
| **By priority** | Incomplete tasks | Priority (ascending) | None |
|
|
49
|
+
| **By project** | None | None | Project |
|
|
50
|
+
|
|
51
|
+
**All tasks** is the required baseline view (renamable, not deletable). **Open** is the **default landing view** — incomplete tasks only, for everyday work.
|
|
52
|
+
|
|
53
|
+
### Starter projects
|
|
54
|
+
|
|
55
|
+
None — the user creates projects as needed. Tasks can exist without a project.
|
|
56
|
+
|
|
57
|
+
### Inbox
|
|
58
|
+
|
|
59
|
+
The inbox starts **empty**. Chat and inbox capture can land here first ([F4](./f4-inbox.mdx)).
|
|
60
|
+
|
|
61
|
+
### What the user sees (full product)
|
|
62
|
+
|
|
63
|
+
1. **Inbox** — empty, ready for capture.
|
|
64
|
+
2. **Main task page** — on **Open** view (incomplete tasks only).
|
|
65
|
+
3. **Custom fields** — Notes, Due date, Priority already defined; completion checkbox on every task.
|
|
66
|
+
4. No sample tasks — a clean slate except for configuration.
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: F8
|
|
3
|
+
title: Chat
|
|
4
|
+
status: partial
|
|
5
|
+
order: 8
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# F8 — Chat
|
|
9
|
+
|
|
10
|
+
## What it is
|
|
11
|
+
|
|
12
|
+
The **chat** is a first-class surface of the Tasks app — not a side panel bolted onto a traditional UI. Users talk to the **agent** in natural language; the agent performs the same operations the UI can, through the same **actions**. There is no separate agent workflow, permission model, or data path.
|
|
13
|
+
|
|
14
|
+
**Parity rule:** whatever a user can do in the UI, the agent can do in chat — and vice versa.
|
|
15
|
+
|
|
16
|
+
## What users can do
|
|
17
|
+
|
|
18
|
+
<!-- status: done -->
|
|
19
|
+
|
|
20
|
+
### Work through conversation
|
|
21
|
+
|
|
22
|
+
- **Capture** ideas ("remind me to call the plumber") — creates an **inbox item** by default; use **create-task** only when the user asks to add directly to the task list.
|
|
23
|
+
- **Manage tasks** — add, edit title, mark complete/incomplete, delete, reorder, bulk complete/delete ([F1](./f1-tasks.mdx)).
|
|
24
|
+
- **Triage inbox** — list, edit, delete, reorder, and **mark ready** ([F4](./f4-inbox.mdx)).
|
|
25
|
+
- **Filter** the task list the same way as the UI (e.g. hide completed tasks).
|
|
26
|
+
- **Ask what's on screen** — the agent can read the user's current view and selection before acting.
|
|
27
|
+
|
|
28
|
+
<!-- status: todo -->
|
|
29
|
+
|
|
30
|
+
### Work through conversation (extended)
|
|
31
|
+
|
|
32
|
+
- **Assign** tasks to a [project](./f3-projects.mdx); open project pages.
|
|
33
|
+
- **Work with custom fields** — set Notes, Due date, Priority, and other fields; define new fields ([F2](./f2-custom-fields.mdx)).
|
|
34
|
+
- **Arrange lists** — filter, sort, group, and switch [saved views](./f5-views.mdx).
|
|
35
|
+
- **Find things** — [search](./f6-search.mdx) by task title or project name and open a result.
|
|
36
|
+
|
|
37
|
+
### Delegate from the UI
|
|
38
|
+
|
|
39
|
+
Buttons and shortcuts in the UI may **send a message to the chat** instead of duplicating logic — e.g. "Add with agent", "Triage inbox", "Summarize my open tasks". The user sees and steers the work in the thread; the agent calls the same actions the UI would.
|
|
40
|
+
|
|
41
|
+
## What the agent can do (parity map)
|
|
42
|
+
|
|
43
|
+
Every UI capability maps to agent tools (actions). The agent uses these — not ad-hoc scripts or direct database access.
|
|
44
|
+
|
|
45
|
+
<!-- status: done -->
|
|
46
|
+
|
|
47
|
+
| Area | Agent can… |
|
|
48
|
+
| ---------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
|
|
49
|
+
| **[F1 Tasks](./f1-tasks.mdx)** | Add, edit, delete tasks; mark complete/incomplete; reorder; bulk complete/delete; apply completed filter |
|
|
50
|
+
| **[F4 Inbox](./f4-inbox.mdx)** | Add, edit, delete inbox items; reorder; mark ready (promote to task) |
|
|
51
|
+
| **[F2 Custom fields](./f2-custom-fields.mdx)** | Create, rename, configure options; set field values; delete fields |
|
|
52
|
+
| **Navigation** | Open inbox, main task page, or a specific task via `navigate` |
|
|
53
|
+
| **Context** | Read current screen and bulk `selection` via `view-screen` |
|
|
54
|
+
|
|
55
|
+
<!-- status: todo -->
|
|
56
|
+
|
|
57
|
+
| Area | Agent can… |
|
|
58
|
+
| ------------------------------------ | --------------------------------------------------------------------- |
|
|
59
|
+
| **[F4 Inbox](./f4-inbox.mdx)** | Bulk mark ready / delete; assign project (hidden until ready) |
|
|
60
|
+
| **[F1 Tasks](./f1-tasks.mdx)** | Bulk assign project |
|
|
61
|
+
| **[F3 Projects](./f3-projects.mdx)** | Create, rename, delete projects; list tasks in a project |
|
|
62
|
+
| **[F5 Views](./f5-views.mdx)** | Apply filter, sort, group; create, switch, rename, delete saved views |
|
|
63
|
+
| **[F6 Search](./f6-search.mdx)** | Search tasks and projects; open a result |
|
|
64
|
+
| **Navigation** | Open inbox, project pages |
|
|
65
|
+
|
|
66
|
+
If a capability is added to the UI, it is exposed as an action and documented for the agent in the same change.
|
|
67
|
+
|
|
68
|
+
## How it behaves
|
|
69
|
+
|
|
70
|
+
### Same rules as the UI
|
|
71
|
+
|
|
72
|
+
The agent follows every product rule that has shipped; extended rules apply as features land.
|
|
73
|
+
|
|
74
|
+
<!-- status: done -->
|
|
75
|
+
|
|
76
|
+
- New capture creates an **inbox item** by default; **create-task** only when the user asks to add directly to the task list.
|
|
77
|
+
- **Destructive** actions require **confirmation** — in chat, the agent asks before delete (same as UI confirmation dialogs).
|
|
78
|
+
|
|
79
|
+
<!-- status: todo -->
|
|
80
|
+
|
|
81
|
+
- **Completion** on inbox items is not allowed until **mark ready**.
|
|
82
|
+
- Inbox items with a project assigned do **not** appear on the project page until **mark ready**.
|
|
83
|
+
- **Bulk** actions require **confirmation**.
|
|
84
|
+
- **Search** matches titles and project names only — not custom field values.
|
|
85
|
+
- **Sort by field** disables manual reorder until sort is **None** again.
|
|
86
|
+
|
|
87
|
+
### Context-aware
|
|
88
|
+
|
|
89
|
+
- **`view-screen`** is the first call when the user's visible context matters — which page, selected tasks, active filter, and (when shipped) project, view, or search query.
|
|
90
|
+
- **`navigation`** application state stays in sync with the UI so the agent knows what the user is looking at without guessing.
|
|
91
|
+
- After the agent changes data, the **UI updates automatically** (same real-time sync as UI-initiated writes).
|
|
92
|
+
|
|
93
|
+
<!-- status: done -->
|
|
94
|
+
|
|
95
|
+
### Capture
|
|
96
|
+
|
|
97
|
+
Typical flow:
|
|
98
|
+
|
|
99
|
+
1. User says something in chat → **inbox item** created (title from the message) unless they ask for the task list directly.
|
|
100
|
+
2. User refines in chat → edit inbox item or mark ready to promote to a task; manage tasks on `/tasks` as usual.
|
|
101
|
+
|
|
102
|
+
<!-- status: todo -->
|
|
103
|
+
|
|
104
|
+
### Capture and triage (extended UI)
|
|
105
|
+
|
|
106
|
+
Full inbox page UI:
|
|
107
|
+
|
|
108
|
+
1. User captures on the inbox page or triages in chat.
|
|
109
|
+
2. User refines on the inbox or task page → edit title, fields, project, etc.
|
|
110
|
+
3. User says "mark it ready" → inbox item becomes an **incomplete** task.
|
|
111
|
+
|
|
112
|
+
### No shadow AI
|
|
113
|
+
|
|
114
|
+
The UI does not call an LLM directly for product work. Generative or interpretive steps go through the **agent chat** so the user can see, correct, and audit what happened.
|
|
115
|
+
|
|
116
|
+
## Limits (v1)
|
|
117
|
+
|
|
118
|
+
- One agent per app instance — no multi-user agent handoff.
|
|
119
|
+
- Chat does not add capabilities beyond what the UI has shipped; it is the conversational interface to the same actions.
|
|
120
|
+
- No voice-only or external messaging channels (Slack, email) in v1.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { mkdirSync, rmSync } from "node:fs";
|
|
2
|
+
import { dirname, resolve } from "node:path";
|
|
3
|
+
|
|
4
|
+
import Database from "better-sqlite3";
|
|
5
|
+
|
|
6
|
+
const DB_PATH = resolve(process.cwd(), "data/e2e-playwright.db");
|
|
7
|
+
|
|
8
|
+
export default async function globalSetup() {
|
|
9
|
+
for (const file of [DB_PATH, `${DB_PATH}-shm`, `${DB_PATH}-wal`]) {
|
|
10
|
+
rmSync(file, { force: true });
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
mkdirSync(dirname(DB_PATH), { recursive: true });
|
|
14
|
+
|
|
15
|
+
const db = new Database(DB_PATH);
|
|
16
|
+
db.exec(`
|
|
17
|
+
CREATE TABLE IF NOT EXISTS tasks_migrations (version INTEGER PRIMARY KEY);
|
|
18
|
+
CREATE TABLE IF NOT EXISTS tasks (
|
|
19
|
+
id TEXT PRIMARY KEY,
|
|
20
|
+
title TEXT NOT NULL,
|
|
21
|
+
done INTEGER NOT NULL DEFAULT 0,
|
|
22
|
+
promoted_to_task INTEGER NOT NULL DEFAULT 1,
|
|
23
|
+
sort_order INTEGER NOT NULL DEFAULT 0,
|
|
24
|
+
owner_email TEXT NOT NULL DEFAULT 'local@localhost',
|
|
25
|
+
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
26
|
+
updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
27
|
+
);
|
|
28
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_owner_done_updated
|
|
29
|
+
ON tasks (owner_email, done, updated_at);
|
|
30
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_owner_sort
|
|
31
|
+
ON tasks (owner_email, sort_order);
|
|
32
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_owner_promoted_sort
|
|
33
|
+
ON tasks (owner_email, promoted_to_task, sort_order);
|
|
34
|
+
INSERT OR IGNORE INTO tasks_migrations VALUES (1);
|
|
35
|
+
INSERT OR IGNORE INTO tasks_migrations VALUES (2);
|
|
36
|
+
INSERT OR IGNORE INTO tasks_migrations VALUES (3);
|
|
37
|
+
INSERT OR IGNORE INTO tasks_migrations VALUES (4);
|
|
38
|
+
INSERT OR IGNORE INTO tasks_migrations VALUES (5);
|
|
39
|
+
INSERT OR IGNORE INTO tasks_migrations VALUES (6);
|
|
40
|
+
`);
|
|
41
|
+
db.close();
|
|
42
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { expect, type APIRequestContext } from "@playwright/test";
|
|
2
|
+
|
|
3
|
+
export async function resetInbox(request: APIRequestContext) {
|
|
4
|
+
const listResponse = await request.get(
|
|
5
|
+
"/_agent-native/actions/list-inbox-items",
|
|
6
|
+
{ headers: { "X-Agent-Native-Frontend": "1" } },
|
|
7
|
+
);
|
|
8
|
+
expect(listResponse.ok()).toBeTruthy();
|
|
9
|
+
const { items } = (await listResponse.json()) as {
|
|
10
|
+
items: Array<{ id: string }>;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
for (const item of items) {
|
|
14
|
+
const deleteResponse = await request.post(
|
|
15
|
+
"/_agent-native/actions/delete-inbox-item",
|
|
16
|
+
{
|
|
17
|
+
headers: {
|
|
18
|
+
"Content-Type": "application/json",
|
|
19
|
+
"X-Agent-Native-Frontend": "1",
|
|
20
|
+
},
|
|
21
|
+
data: { inboxItemId: item.id },
|
|
22
|
+
},
|
|
23
|
+
);
|
|
24
|
+
expect(deleteResponse.ok()).toBeTruthy();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export async function waitForInboxLoaded(
|
|
29
|
+
page: import("@playwright/test").Page,
|
|
30
|
+
) {
|
|
31
|
+
await expect(page.locator(".animate-pulse")).toHaveCount(0);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function inboxItemTitleButton(
|
|
35
|
+
page: import("@playwright/test").Page,
|
|
36
|
+
title: string,
|
|
37
|
+
) {
|
|
38
|
+
return page.getByRole("button", { name: title, exact: true });
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function inboxItemRowByTitle(
|
|
42
|
+
page: import("@playwright/test").Page,
|
|
43
|
+
title: string,
|
|
44
|
+
) {
|
|
45
|
+
return page.locator("[data-inbox-item-id]").filter({
|
|
46
|
+
has: inboxItemTitleButton(page, title),
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export async function createInboxItem(
|
|
51
|
+
request: APIRequestContext,
|
|
52
|
+
title: string,
|
|
53
|
+
) {
|
|
54
|
+
const response = await request.post(
|
|
55
|
+
"/_agent-native/actions/create-inbox-item",
|
|
56
|
+
{
|
|
57
|
+
headers: {
|
|
58
|
+
"Content-Type": "application/json",
|
|
59
|
+
"X-Agent-Native-Frontend": "1",
|
|
60
|
+
},
|
|
61
|
+
data: { title },
|
|
62
|
+
},
|
|
63
|
+
);
|
|
64
|
+
expect(response.ok()).toBeTruthy();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export async function gotoInboxPage(page: import("@playwright/test").Page) {
|
|
68
|
+
await page.goto("/inbox");
|
|
69
|
+
await expect(page.getByRole("heading", { name: "Inbox" })).toBeVisible();
|
|
70
|
+
await waitForInboxLoaded(page);
|
|
71
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { expect, type APIRequestContext } from "@playwright/test";
|
|
2
|
+
|
|
3
|
+
export async function resetTasks(request: APIRequestContext) {
|
|
4
|
+
const listResponse = await request.get(
|
|
5
|
+
"/_agent-native/actions/list-tasks?includeDone=true",
|
|
6
|
+
{ headers: { "X-Agent-Native-Frontend": "1" } },
|
|
7
|
+
);
|
|
8
|
+
expect(listResponse.ok()).toBeTruthy();
|
|
9
|
+
const { tasks } = (await listResponse.json()) as {
|
|
10
|
+
tasks: Array<{ id: string }>;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
for (const task of tasks) {
|
|
14
|
+
const deleteResponse = await request.post(
|
|
15
|
+
"/_agent-native/actions/delete-task",
|
|
16
|
+
{
|
|
17
|
+
headers: {
|
|
18
|
+
"Content-Type": "application/json",
|
|
19
|
+
"X-Agent-Native-Frontend": "1",
|
|
20
|
+
},
|
|
21
|
+
data: { taskId: task.id },
|
|
22
|
+
},
|
|
23
|
+
);
|
|
24
|
+
expect(deleteResponse.ok()).toBeTruthy();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export async function waitForTasksLoaded(
|
|
29
|
+
page: import("@playwright/test").Page,
|
|
30
|
+
) {
|
|
31
|
+
await expect(page.locator(".animate-pulse")).toHaveCount(0);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function taskTitleButton(
|
|
35
|
+
page: import("@playwright/test").Page,
|
|
36
|
+
title: string,
|
|
37
|
+
) {
|
|
38
|
+
return page.getByRole("button", { name: title, exact: true });
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function taskRowByTitle(
|
|
42
|
+
page: import("@playwright/test").Page,
|
|
43
|
+
title: string,
|
|
44
|
+
) {
|
|
45
|
+
return page.locator("[data-task-id]").filter({
|
|
46
|
+
has: page.getByText(title, { exact: true }),
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export async function openTaskRowMenu(
|
|
51
|
+
page: import("@playwright/test").Page,
|
|
52
|
+
title: string,
|
|
53
|
+
) {
|
|
54
|
+
const row = taskRowByTitle(page, title);
|
|
55
|
+
await row
|
|
56
|
+
.getByRole("button", { name: new RegExp(`Actions for ${title}`) })
|
|
57
|
+
.click();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export async function chooseTaskRowMenuItem(
|
|
61
|
+
page: import("@playwright/test").Page,
|
|
62
|
+
itemName: string,
|
|
63
|
+
) {
|
|
64
|
+
await page.getByRole("menuitem", { name: itemName, exact: true }).click();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export async function waitForServerTaskId(
|
|
68
|
+
page: import("@playwright/test").Page,
|
|
69
|
+
title: string,
|
|
70
|
+
) {
|
|
71
|
+
const row = taskRowByTitle(page, title);
|
|
72
|
+
await expect
|
|
73
|
+
.poll(async () => {
|
|
74
|
+
const id = await row.getAttribute("data-task-id");
|
|
75
|
+
return id && !id.startsWith("optimistic-") ? "server" : "pending";
|
|
76
|
+
})
|
|
77
|
+
.toBe("server");
|
|
78
|
+
|
|
79
|
+
const id = await row.getAttribute("data-task-id");
|
|
80
|
+
expect(id).toBeTruthy();
|
|
81
|
+
return id as string;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export async function createTask(request: APIRequestContext, title: string) {
|
|
85
|
+
const response = await request.post("/_agent-native/actions/create-task", {
|
|
86
|
+
headers: {
|
|
87
|
+
"Content-Type": "application/json",
|
|
88
|
+
"X-Agent-Native-Frontend": "1",
|
|
89
|
+
},
|
|
90
|
+
data: { title },
|
|
91
|
+
});
|
|
92
|
+
expect(response.ok()).toBeTruthy();
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export async function gotoTasksPage(page: import("@playwright/test").Page) {
|
|
96
|
+
await page.goto("/tasks");
|
|
97
|
+
await expect(page.getByRole("heading", { name: "Tasks" })).toBeVisible();
|
|
98
|
+
await waitForTasksLoaded(page);
|
|
99
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# Learnings
|
|
2
|
+
|
|
3
|
+
<!-- This file is your app's memory. The AI reads it at the start of every conversation and updates it when it learns something new. -->
|
|
4
|
+
<!-- Your personal learnings.md is gitignored so preferences and private info stay local. -->
|
|
5
|
+
<!-- This defaults file is what new checkouts start with. -->
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
[build]
|
|
2
|
+
ignore = "node ./scripts/netlify-ignore-build.mjs tasks"
|
|
3
|
+
command = "export DATABASE_URL=${NETLIFY_DATABASE_URL:-$DATABASE_URL} && pnpm install && NITRO_PRESET=netlify pnpm --filter tasks build"
|
|
4
|
+
publish = "templates/tasks/dist"
|
|
5
|
+
functions = "templates/tasks/.netlify/functions-internal"
|
|
6
|
+
|
|
7
|
+
[build.environment]
|
|
8
|
+
GA_MEASUREMENT_ID = "G-ESF7FYXGN9"
|
|
9
|
+
NITRO_PRESET = "netlify"
|
|
10
|
+
NPM_CONFIG_PRODUCTION = "false"
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "tasks",
|
|
3
|
+
"displayName": "Tasks",
|
|
4
|
+
"private": true,
|
|
5
|
+
"description": "Task-list-first agent-native app with inbox, custom fields, and drag-and-drop ordering",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"dev": "agent-native dev --open",
|
|
9
|
+
"build": "agent-native build",
|
|
10
|
+
"start": "agent-native start",
|
|
11
|
+
"format.fix": "oxfmt --write .",
|
|
12
|
+
"typecheck": "agent-native typecheck",
|
|
13
|
+
"action": "agent-native action",
|
|
14
|
+
"script": "agent-native script",
|
|
15
|
+
"test": "vitest --run --config vitest.config.ts",
|
|
16
|
+
"test:e2e": "playwright test",
|
|
17
|
+
"test:e2e:install": "playwright install chromium",
|
|
18
|
+
"test:all": "pnpm test && pnpm test:e2e"
|
|
19
|
+
},
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"@agent-native/core": "workspace:*",
|
|
22
|
+
"@agent-native/toolkit": "workspace:*",
|
|
23
|
+
"@dnd-kit/core": "^6.3.1",
|
|
24
|
+
"@dnd-kit/sortable": "^10.0.0",
|
|
25
|
+
"@dnd-kit/utilities": "^3.2.2",
|
|
26
|
+
"@fontsource-variable/inter": "^5.2.8",
|
|
27
|
+
"@libsql/client": "^0.15.8",
|
|
28
|
+
"@tabler/icons-react": "catalog:",
|
|
29
|
+
"h3": "^2.0.1-rc.20",
|
|
30
|
+
"isbot": "^5",
|
|
31
|
+
"node-pty": "^1.1.0",
|
|
32
|
+
"postgres": "^3.4.9",
|
|
33
|
+
"zod": "^4.4.3"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@playwright/test": "^1.61.0",
|
|
37
|
+
"@radix-ui/react-accordion": "^1.2.12",
|
|
38
|
+
"@radix-ui/react-alert-dialog": "^1.1.15",
|
|
39
|
+
"@radix-ui/react-aspect-ratio": "^1.1.8",
|
|
40
|
+
"@radix-ui/react-avatar": "^1.1.11",
|
|
41
|
+
"@radix-ui/react-checkbox": "^1.3.2",
|
|
42
|
+
"@radix-ui/react-collapsible": "^1.1.12",
|
|
43
|
+
"@radix-ui/react-context-menu": "^2.2.16",
|
|
44
|
+
"@radix-ui/react-dialog": "^1.1.14",
|
|
45
|
+
"@radix-ui/react-dropdown-menu": "^2.1.15",
|
|
46
|
+
"@radix-ui/react-hover-card": "^1.1.15",
|
|
47
|
+
"@radix-ui/react-label": "^2.1.7",
|
|
48
|
+
"@radix-ui/react-menubar": "^1.1.16",
|
|
49
|
+
"@radix-ui/react-navigation-menu": "^1.2.14",
|
|
50
|
+
"@radix-ui/react-popover": "^1.1.14",
|
|
51
|
+
"@radix-ui/react-progress": "^1.1.8",
|
|
52
|
+
"@radix-ui/react-radio-group": "^1.3.7",
|
|
53
|
+
"@radix-ui/react-scroll-area": "^1.2.9",
|
|
54
|
+
"@radix-ui/react-select": "^2.2.5",
|
|
55
|
+
"@radix-ui/react-separator": "^1.1.7",
|
|
56
|
+
"@radix-ui/react-slider": "^1.3.5",
|
|
57
|
+
"@radix-ui/react-slot": "^1.2.3",
|
|
58
|
+
"@radix-ui/react-switch": "^1.2.5",
|
|
59
|
+
"@radix-ui/react-tabs": "^1.1.12",
|
|
60
|
+
"@radix-ui/react-toast": "^1.2.15",
|
|
61
|
+
"@radix-ui/react-toggle": "^1.1.10",
|
|
62
|
+
"@radix-ui/react-toggle-group": "^1.1.11",
|
|
63
|
+
"@radix-ui/react-tooltip": "^1.2.7",
|
|
64
|
+
"@react-router/dev": "^8.1.0",
|
|
65
|
+
"@react-router/fs-routes": "^8.1.0",
|
|
66
|
+
"@swc/core": "^1.13.3",
|
|
67
|
+
"@tailwindcss/vite": "catalog:",
|
|
68
|
+
"@tanstack/react-query": "^5.99.2",
|
|
69
|
+
"@types/better-sqlite3": "^7.6.13",
|
|
70
|
+
"@types/node": "^24.2.1",
|
|
71
|
+
"@types/react": "catalog:",
|
|
72
|
+
"@types/react-dom": "catalog:",
|
|
73
|
+
"@vitejs/plugin-react-swc": "^4.0.0",
|
|
74
|
+
"@xterm/addon-fit": "^0.11.0",
|
|
75
|
+
"@xterm/addon-web-links": "^0.12.0",
|
|
76
|
+
"@xterm/xterm": "^6.0.0",
|
|
77
|
+
"better-sqlite3": "^12.11.1",
|
|
78
|
+
"class-variance-authority": "^0.7.1",
|
|
79
|
+
"clsx": "^2.1.1",
|
|
80
|
+
"cmdk": "^1.1.1",
|
|
81
|
+
"drizzle-orm": "^0.45.2",
|
|
82
|
+
"embla-carousel-react": "^8.6.0",
|
|
83
|
+
"input-otp": "^1.4.2",
|
|
84
|
+
"next-themes": "^0.4.6",
|
|
85
|
+
"oxfmt": "catalog:",
|
|
86
|
+
"react": "catalog:",
|
|
87
|
+
"react-day-picker": "^9.14.0",
|
|
88
|
+
"react-dom": "catalog:",
|
|
89
|
+
"react-hook-form": "^7.71.2",
|
|
90
|
+
"react-resizable-panels": "^4.10.0",
|
|
91
|
+
"react-router": "^8.1.0",
|
|
92
|
+
"recharts": "^3.8.1",
|
|
93
|
+
"sonner": "^2.0.7",
|
|
94
|
+
"tailwind-merge": "^3.5.0",
|
|
95
|
+
"tailwindcss": "catalog:",
|
|
96
|
+
"tsx": "^4.20.3",
|
|
97
|
+
"typescript": "catalog:",
|
|
98
|
+
"typescript-7": "catalog:",
|
|
99
|
+
"vaul": "^1.1.2",
|
|
100
|
+
"vite": "catalog:",
|
|
101
|
+
"vitest": "catalog:"
|
|
102
|
+
},
|
|
103
|
+
"packageManager": "pnpm@10.14.0+sha512.ad27a79641b49c3e481a16a805baa71817a04bbe06a38d17e60e2eaee83f6a146c6a688125f5792e48dd5ba30e7da52a5cda4c3992b9ccf333f9ce223af84748"
|
|
104
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { defineConfig, devices } from "@playwright/test";
|
|
2
|
+
|
|
3
|
+
const PORT = Number(process.env.PLAYWRIGHT_PORT ?? 5174);
|
|
4
|
+
const HOST = process.env.PLAYWRIGHT_HOST ?? "127.0.0.1";
|
|
5
|
+
const BASE_URL = `http://${HOST}:${PORT}`;
|
|
6
|
+
const E2E_DB_PATH = "./data/e2e-playwright.db";
|
|
7
|
+
|
|
8
|
+
export default defineConfig({
|
|
9
|
+
testDir: "./e2e",
|
|
10
|
+
fullyParallel: false,
|
|
11
|
+
forbidOnly: !!process.env.CI,
|
|
12
|
+
retries: process.env.CI ? 2 : 0,
|
|
13
|
+
workers: 1,
|
|
14
|
+
reporter: process.env.CI ? "github" : "list",
|
|
15
|
+
timeout: 60_000,
|
|
16
|
+
use: {
|
|
17
|
+
baseURL: BASE_URL,
|
|
18
|
+
trace: "on-first-retry",
|
|
19
|
+
screenshot: "only-on-failure",
|
|
20
|
+
},
|
|
21
|
+
globalSetup: "./e2e/global-setup.ts",
|
|
22
|
+
webServer: {
|
|
23
|
+
command: `AUTH_DISABLED=true DATABASE_URL=file:${E2E_DB_PATH} pnpm exec agent-native dev -- --port ${PORT} --host ${HOST} --strictPort`,
|
|
24
|
+
url: `${BASE_URL}/tasks`,
|
|
25
|
+
reuseExistingServer: false,
|
|
26
|
+
timeout: 120_000,
|
|
27
|
+
},
|
|
28
|
+
projects: [
|
|
29
|
+
{
|
|
30
|
+
name: "chromium",
|
|
31
|
+
use: { ...devices["Desktop Chrome"] },
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<svg width="114" height="66" viewBox="0 0 114 66" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path d="M24.5537 65.7695H0L15.0859 39.4619L37.708 0L60.4912 39.4619H39.6396L24.5537 65.7695Z" fill="white"/>
|
|
3
|
+
<path d="M89.446 0H114L76.2921 65.7704H51.7383L89.446 0Z" fill="url(#paint0_linear_3201_29)"/>
|
|
4
|
+
<defs>
|
|
5
|
+
<linearGradient id="paint0_linear_3201_29" x1="101.702" y1="67.4791" x2="113.672" y2="-37.4275" gradientUnits="userSpaceOnUse">
|
|
6
|
+
<stop stop-color="#00B5FF"/>
|
|
7
|
+
<stop offset="1" stop-color="#48FFE4"/>
|
|
8
|
+
</linearGradient>
|
|
9
|
+
</defs>
|
|
10
|
+
</svg>
|