stagent 0.6.2 → 0.7.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 +21 -2
- package/dist/cli.js +272 -1
- package/docs/.coverage-gaps.json +66 -16
- package/docs/.last-generated +1 -1
- package/docs/features/dashboard-kanban.md +13 -7
- package/docs/features/settings.md +15 -3
- package/docs/features/tables.md +122 -0
- package/docs/index.md +3 -2
- package/docs/journeys/developer.md +26 -16
- package/docs/journeys/personal-use.md +23 -9
- package/docs/journeys/power-user.md +40 -14
- package/docs/journeys/work-use.md +43 -15
- package/docs/manifest.json +27 -17
- package/package.json +3 -2
- package/src/app/api/chat/entities/search/route.ts +12 -3
- package/src/app/api/documents/[id]/route.ts +5 -1
- package/src/app/api/documents/[id]/versions/route.ts +53 -0
- package/src/app/api/documents/route.ts +5 -1
- package/src/app/api/projects/[id]/documents/route.ts +124 -0
- package/src/app/api/projects/[id]/route.ts +72 -3
- package/src/app/api/projects/__tests__/delete-project.test.ts +13 -0
- package/src/app/api/schedules/route.ts +19 -1
- package/src/app/api/snapshots/[id]/restore/route.ts +62 -0
- package/src/app/api/snapshots/[id]/route.ts +44 -0
- package/src/app/api/snapshots/route.ts +54 -0
- package/src/app/api/snapshots/settings/route.ts +67 -0
- package/src/app/api/tables/[id]/charts/[chartId]/route.ts +89 -0
- package/src/app/api/tables/[id]/charts/route.ts +72 -0
- package/src/app/api/tables/[id]/columns/route.ts +70 -0
- package/src/app/api/tables/[id]/export/route.ts +94 -0
- package/src/app/api/tables/[id]/history/route.ts +15 -0
- package/src/app/api/tables/[id]/import/route.ts +111 -0
- package/src/app/api/tables/[id]/route.ts +86 -0
- package/src/app/api/tables/[id]/rows/[rowId]/history/route.ts +32 -0
- package/src/app/api/tables/[id]/rows/[rowId]/route.ts +51 -0
- package/src/app/api/tables/[id]/rows/route.ts +101 -0
- package/src/app/api/tables/[id]/triggers/[triggerId]/route.ts +65 -0
- package/src/app/api/tables/[id]/triggers/route.ts +122 -0
- package/src/app/api/tables/route.ts +65 -0
- package/src/app/api/tables/templates/route.ts +92 -0
- package/src/app/api/tasks/[id]/route.ts +37 -2
- package/src/app/api/tasks/[id]/siblings/route.ts +48 -0
- package/src/app/api/tasks/route.ts +8 -9
- package/src/app/api/workflows/[id]/documents/route.ts +209 -0
- package/src/app/api/workflows/[id]/execute/route.ts +6 -2
- package/src/app/api/workflows/[id]/route.ts +16 -3
- package/src/app/api/workflows/[id]/status/route.ts +18 -2
- package/src/app/api/workflows/route.ts +13 -2
- package/src/app/documents/page.tsx +5 -1
- package/src/app/layout.tsx +0 -1
- package/src/app/manifest.ts +3 -3
- package/src/app/projects/[id]/page.tsx +62 -2
- package/src/app/settings/page.tsx +2 -0
- package/src/app/tables/[id]/page.tsx +67 -0
- package/src/app/tables/page.tsx +21 -0
- package/src/app/tables/templates/page.tsx +19 -0
- package/src/components/chat/chat-table-result.tsx +139 -0
- package/src/components/documents/document-browser.tsx +1 -1
- package/src/components/documents/document-chip-bar.tsx +17 -1
- package/src/components/documents/document-detail-view.tsx +51 -0
- package/src/components/documents/document-grid.tsx +5 -0
- package/src/components/documents/document-table.tsx +4 -0
- package/src/components/documents/types.ts +3 -0
- package/src/components/projects/project-form-sheet.tsx +109 -2
- package/src/components/schedules/schedule-form.tsx +91 -1
- package/src/components/settings/data-management-section.tsx +17 -12
- package/src/components/settings/database-snapshots-section.tsx +469 -0
- package/src/components/shared/app-sidebar.tsx +2 -0
- package/src/components/shared/document-picker-sheet.tsx +486 -0
- package/src/components/tables/table-browser.tsx +234 -0
- package/src/components/tables/table-cell-editor.tsx +226 -0
- package/src/components/tables/table-chart-builder.tsx +288 -0
- package/src/components/tables/table-chart-view.tsx +146 -0
- package/src/components/tables/table-column-header.tsx +103 -0
- package/src/components/tables/table-column-sheet.tsx +331 -0
- package/src/components/tables/table-create-sheet.tsx +240 -0
- package/src/components/tables/table-detail-sheet.tsx +144 -0
- package/src/components/tables/table-detail-tabs.tsx +278 -0
- package/src/components/tables/table-grid.tsx +61 -0
- package/src/components/tables/table-history-tab.tsx +148 -0
- package/src/components/tables/table-import-wizard.tsx +542 -0
- package/src/components/tables/table-list-table.tsx +95 -0
- package/src/components/tables/table-relation-combobox.tsx +217 -0
- package/src/components/tables/table-spreadsheet.tsx +499 -0
- package/src/components/tables/table-template-gallery.tsx +162 -0
- package/src/components/tables/table-template-preview.tsx +219 -0
- package/src/components/tables/table-toolbar.tsx +79 -0
- package/src/components/tables/table-triggers-tab.tsx +446 -0
- package/src/components/tables/types.ts +6 -0
- package/src/components/tables/use-spreadsheet-keys.ts +171 -0
- package/src/components/tables/utils.ts +29 -0
- package/src/components/tasks/task-card.tsx +8 -1
- package/src/components/tasks/task-create-panel.tsx +111 -14
- package/src/components/tasks/task-detail-view.tsx +47 -0
- package/src/components/tasks/task-edit-dialog.tsx +103 -2
- package/src/components/workflows/workflow-form-view.tsx +207 -7
- package/src/components/workflows/workflow-kanban-card.tsx +8 -1
- package/src/components/workflows/workflow-list.tsx +90 -45
- package/src/components/workflows/workflow-status-view.tsx +168 -23
- package/src/instrumentation.ts +3 -0
- package/src/lib/__tests__/npx-process-cwd.test.ts +17 -2
- package/src/lib/agents/__tests__/claude-agent.test.ts +5 -1
- package/src/lib/agents/claude-agent.ts +3 -1
- package/src/lib/agents/profiles/registry.ts +6 -3
- package/src/lib/agents/runtime/anthropic-direct.ts +29 -0
- package/src/lib/agents/runtime/openai-direct.ts +29 -0
- package/src/lib/book/__tests__/chapter-slugs.test.ts +80 -0
- package/src/lib/book/chapter-generator.ts +4 -19
- package/src/lib/book/chapter-mapping.ts +17 -0
- package/src/lib/book/content.ts +5 -16
- package/src/lib/book/update-detector.ts +3 -16
- package/src/lib/chat/engine.ts +1 -0
- package/src/lib/chat/stagent-tools.ts +2 -0
- package/src/lib/chat/system-prompt.ts +9 -1
- package/src/lib/chat/tool-catalog.ts +35 -0
- package/src/lib/chat/tools/settings-tools.ts +109 -0
- package/src/lib/chat/tools/table-tools.ts +955 -0
- package/src/lib/chat/tools/workflow-tools.ts +145 -2
- package/src/lib/constants/table-status.ts +68 -0
- package/src/lib/data/__tests__/clear.test.ts +1 -1
- package/src/lib/data/clear.ts +57 -0
- package/src/lib/data/seed-data/__tests__/profiles.test.ts +28 -23
- package/src/lib/data/seed-data/conversations.ts +350 -42
- package/src/lib/data/seed-data/documents.ts +564 -591
- package/src/lib/data/seed-data/learned-context.ts +101 -22
- package/src/lib/data/seed-data/notifications.ts +344 -70
- package/src/lib/data/seed-data/profile-test-results.ts +92 -11
- package/src/lib/data/seed-data/profiles.ts +144 -46
- package/src/lib/data/seed-data/projects.ts +50 -18
- package/src/lib/data/seed-data/repo-imports.ts +28 -13
- package/src/lib/data/seed-data/schedules.ts +208 -41
- package/src/lib/data/seed-data/table-templates.ts +234 -0
- package/src/lib/data/seed-data/tasks.ts +614 -116
- package/src/lib/data/seed-data/usage-ledger.ts +182 -103
- package/src/lib/data/seed-data/user-tables.ts +203 -0
- package/src/lib/data/seed-data/views.ts +52 -7
- package/src/lib/data/seed-data/workflows.ts +231 -84
- package/src/lib/data/seed.ts +55 -14
- package/src/lib/data/tables.ts +417 -0
- package/src/lib/db/bootstrap.ts +275 -0
- package/src/lib/db/index.ts +9 -0
- package/src/lib/db/migrations/0016_add_workflow_document_inputs.sql +13 -0
- package/src/lib/db/migrations/0017_add_document_picker_tables.sql +25 -0
- package/src/lib/db/migrations/0018_add_workflow_run_number.sql +2 -0
- package/src/lib/db/migrations/0019_add_tables_feature.sql +160 -0
- package/src/lib/db/migrations/0020_add_table_triggers.sql +19 -0
- package/src/lib/db/migrations/0021_add_row_history.sql +15 -0
- package/src/lib/db/schema.ts +445 -0
- package/src/lib/docs/reader.ts +2 -3
- package/src/lib/documents/context-builder.ts +75 -2
- package/src/lib/documents/document-resolver.ts +119 -0
- package/src/lib/documents/processors/spreadsheet.ts +2 -1
- package/src/lib/schedules/scheduler.ts +31 -1
- package/src/lib/snapshots/auto-backup.ts +132 -0
- package/src/lib/snapshots/retention.ts +64 -0
- package/src/lib/snapshots/snapshot-manager.ts +429 -0
- package/src/lib/tables/computed.ts +61 -0
- package/src/lib/tables/context-builder.ts +139 -0
- package/src/lib/tables/formula-engine.ts +415 -0
- package/src/lib/tables/history.ts +115 -0
- package/src/lib/tables/import.ts +343 -0
- package/src/lib/tables/query-builder.ts +152 -0
- package/src/lib/tables/trigger-evaluator.ts +146 -0
- package/src/lib/tables/types.ts +141 -0
- package/src/lib/tables/validation.ts +119 -0
- package/src/lib/utils/app-root.ts +20 -0
- package/src/lib/utils/stagent-paths.ts +20 -0
- package/src/lib/validators/__tests__/task.test.ts +43 -10
- package/src/lib/validators/task.ts +7 -1
- package/src/lib/workflows/blueprints/registry.ts +3 -3
- package/src/lib/workflows/engine.ts +24 -8
- package/src/lib/workflows/types.ts +14 -0
- package/tsconfig.json +3 -1
- package/public/icon.svg +0 -13
- package/src/components/tasks/file-upload.tsx +0 -120
- /package/docs/features/{playbook.md → user-guide.md} +0 -0
|
@@ -15,6 +15,12 @@ export interface ScheduleSeed {
|
|
|
15
15
|
expiresAt: Date | null;
|
|
16
16
|
lastFiredAt: Date | null;
|
|
17
17
|
nextFireAt: Date | null;
|
|
18
|
+
type: "scheduled" | "heartbeat";
|
|
19
|
+
heartbeatChecklist: string | null;
|
|
20
|
+
activeHoursStart: number | null;
|
|
21
|
+
activeHoursEnd: number | null;
|
|
22
|
+
activeTimezone: string | null;
|
|
23
|
+
deliveryChannels: string | null;
|
|
18
24
|
createdAt: Date;
|
|
19
25
|
updatedAt: Date;
|
|
20
26
|
}
|
|
@@ -23,85 +29,246 @@ export function createSchedules(projectIds: string[]): ScheduleSeed[] {
|
|
|
23
29
|
const now = Date.now();
|
|
24
30
|
const DAY = 86_400_000;
|
|
25
31
|
const HOUR = 3_600_000;
|
|
26
|
-
const [
|
|
27
|
-
|
|
32
|
+
const [
|
|
33
|
+
launchProject,
|
|
34
|
+
contentProject,
|
|
35
|
+
csProject,
|
|
36
|
+
tvpProject,
|
|
37
|
+
greenleafProject,
|
|
38
|
+
medreachProject,
|
|
39
|
+
revopsProject,
|
|
40
|
+
complianceProject,
|
|
41
|
+
] = projectIds;
|
|
28
42
|
|
|
29
|
-
const
|
|
30
|
-
const
|
|
31
|
-
const
|
|
32
|
-
const
|
|
43
|
+
const daily8am = "0 8 * * *";
|
|
44
|
+
const mwf9am = "0 9 * * 1,3,5";
|
|
45
|
+
const every6h = "0 */6 * * *";
|
|
46
|
+
const weeklyMon7am = "0 7 * * 1";
|
|
47
|
+
const every4h = "0 */4 * * *";
|
|
48
|
+
const daily6am = "0 6 * * *";
|
|
49
|
+
const every8h = "0 */8 * * *";
|
|
50
|
+
const monthly1st = "0 9 1 * *";
|
|
33
51
|
|
|
34
52
|
return [
|
|
53
|
+
// 1. Launch Metrics Digest — daily, Slack delivery
|
|
35
54
|
{
|
|
36
55
|
id: crypto.randomUUID(),
|
|
37
|
-
projectId:
|
|
38
|
-
name: "
|
|
56
|
+
projectId: launchProject,
|
|
57
|
+
name: "Launch Metrics Digest",
|
|
58
|
+
prompt:
|
|
59
|
+
"Pull yesterday's launch metrics: landing page visits, signup conversions, email open rates, and social engagement. Highlight any metric that moved >10% and flag channels underperforming targets.",
|
|
60
|
+
cronExpression: daily8am,
|
|
61
|
+
agentProfile: SAMPLE_PROFILE_IDS[0], // GTM Launch Strategist
|
|
62
|
+
recurs: true,
|
|
63
|
+
status: "active",
|
|
64
|
+
maxFirings: null,
|
|
65
|
+
firingCount: 12,
|
|
66
|
+
expiresAt: null,
|
|
67
|
+
lastFiredAt: new Date(now - 16 * HOUR),
|
|
68
|
+
nextFireAt: computeNextFireTime(daily8am, new Date(now)),
|
|
69
|
+
type: "scheduled",
|
|
70
|
+
heartbeatChecklist: null,
|
|
71
|
+
activeHoursStart: null,
|
|
72
|
+
activeHoursEnd: null,
|
|
73
|
+
activeTimezone: null,
|
|
74
|
+
deliveryChannels: JSON.stringify(["slack"]),
|
|
75
|
+
createdAt: new Date(now - 18 * DAY),
|
|
76
|
+
updatedAt: new Date(now - 1 * HOUR),
|
|
77
|
+
},
|
|
78
|
+
|
|
79
|
+
// 2. Content Calendar Check-In — MWF, Content Editor
|
|
80
|
+
{
|
|
81
|
+
id: crypto.randomUUID(),
|
|
82
|
+
projectId: contentProject,
|
|
83
|
+
name: "Content Calendar Check-In",
|
|
84
|
+
prompt:
|
|
85
|
+
"Review the editorial calendar for this week. Confirm articles in progress have outlines approved, flag any pieces behind schedule, and suggest topic swaps if a trending topic emerged overnight.",
|
|
86
|
+
cronExpression: mwf9am,
|
|
87
|
+
agentProfile: SAMPLE_PROFILE_IDS[1], // Content Production Editor
|
|
88
|
+
recurs: true,
|
|
89
|
+
status: "active",
|
|
90
|
+
maxFirings: null,
|
|
91
|
+
firingCount: 8,
|
|
92
|
+
expiresAt: null,
|
|
93
|
+
lastFiredAt: new Date(now - 2 * DAY),
|
|
94
|
+
nextFireAt: computeNextFireTime(mwf9am, new Date(now)),
|
|
95
|
+
type: "scheduled",
|
|
96
|
+
heartbeatChecklist: null,
|
|
97
|
+
activeHoursStart: null,
|
|
98
|
+
activeHoursEnd: null,
|
|
99
|
+
activeTimezone: null,
|
|
100
|
+
deliveryChannels: null,
|
|
101
|
+
createdAt: new Date(now - 15 * DAY),
|
|
102
|
+
updatedAt: new Date(now - 2 * DAY),
|
|
103
|
+
},
|
|
104
|
+
|
|
105
|
+
// 3. Churn Risk Heartbeat — intelligence-driven, every 6h
|
|
106
|
+
{
|
|
107
|
+
id: crypto.randomUUID(),
|
|
108
|
+
projectId: csProject,
|
|
109
|
+
name: "Churn Risk Heartbeat",
|
|
110
|
+
prompt:
|
|
111
|
+
"Evaluate the customer health checklist. Only take action if a signal fires — otherwise suppress and log. When action is needed, draft the intervention and notify via Slack and email.",
|
|
112
|
+
cronExpression: every6h,
|
|
113
|
+
agentProfile: SAMPLE_PROFILE_IDS[2], // Customer Success Analyst
|
|
114
|
+
recurs: true,
|
|
115
|
+
status: "active",
|
|
116
|
+
maxFirings: null,
|
|
117
|
+
firingCount: 22,
|
|
118
|
+
expiresAt: null,
|
|
119
|
+
lastFiredAt: new Date(now - 4 * HOUR),
|
|
120
|
+
nextFireAt: computeNextFireTime(every6h, new Date(now)),
|
|
121
|
+
type: "heartbeat",
|
|
122
|
+
heartbeatChecklist: JSON.stringify([
|
|
123
|
+
"Any account NPS dropped below 30?",
|
|
124
|
+
"Any account usage declined >40% week-over-week?",
|
|
125
|
+
"Any account filed >3 support tickets this week?",
|
|
126
|
+
"Any enterprise renewal within 60 days with no CSM touchpoint?",
|
|
127
|
+
]),
|
|
128
|
+
activeHoursStart: 8,
|
|
129
|
+
activeHoursEnd: 20,
|
|
130
|
+
activeTimezone: "America/Los_Angeles",
|
|
131
|
+
deliveryChannels: JSON.stringify(["slack", "email"]),
|
|
132
|
+
createdAt: new Date(now - 14 * DAY),
|
|
133
|
+
updatedAt: new Date(now - 4 * HOUR),
|
|
134
|
+
},
|
|
135
|
+
|
|
136
|
+
// 4. Portfolio KPI Tracker — weekly Monday 7am
|
|
137
|
+
{
|
|
138
|
+
id: crypto.randomUUID(),
|
|
139
|
+
projectId: tvpProject,
|
|
140
|
+
name: "Portfolio KPI Tracker",
|
|
141
|
+
prompt:
|
|
142
|
+
"Pull the weekly KPI snapshot for all 4 portfolio companies: MRR, burn rate, net retention, and headcount. Flag any company with MRR growth <5% or burn rate acceleration >15%. Format as a board-ready summary.",
|
|
143
|
+
cronExpression: weeklyMon7am,
|
|
144
|
+
agentProfile: SAMPLE_PROFILE_IDS[3], // Due Diligence Analyst
|
|
145
|
+
recurs: true,
|
|
146
|
+
status: "active",
|
|
147
|
+
maxFirings: null,
|
|
148
|
+
firingCount: 3,
|
|
149
|
+
expiresAt: null,
|
|
150
|
+
lastFiredAt: new Date(now - 5 * DAY),
|
|
151
|
+
nextFireAt: computeNextFireTime(weeklyMon7am, new Date(now)),
|
|
152
|
+
type: "scheduled",
|
|
153
|
+
heartbeatChecklist: null,
|
|
154
|
+
activeHoursStart: null,
|
|
155
|
+
activeHoursEnd: null,
|
|
156
|
+
activeTimezone: null,
|
|
157
|
+
deliveryChannels: JSON.stringify(["slack"]),
|
|
158
|
+
createdAt: new Date(now - 12 * DAY),
|
|
159
|
+
updatedAt: new Date(now - 5 * DAY),
|
|
160
|
+
},
|
|
161
|
+
|
|
162
|
+
// 5. Review Sentiment Heartbeat — every 4h, e-commerce monitoring
|
|
163
|
+
{
|
|
164
|
+
id: crypto.randomUUID(),
|
|
165
|
+
projectId: greenleafProject,
|
|
166
|
+
name: "Review Sentiment Heartbeat",
|
|
39
167
|
prompt:
|
|
40
|
-
"
|
|
41
|
-
cronExpression:
|
|
42
|
-
agentProfile:
|
|
168
|
+
"Check the product review feeds for new negative reviews, competitor price changes, and inventory alerts. Only act when a signal fires — draft a response template for 1-2 star reviews and alert the client.",
|
|
169
|
+
cronExpression: every4h,
|
|
170
|
+
agentProfile: "general",
|
|
43
171
|
recurs: true,
|
|
44
172
|
status: "active",
|
|
45
173
|
maxFirings: null,
|
|
46
|
-
firingCount:
|
|
174
|
+
firingCount: 35,
|
|
47
175
|
expiresAt: null,
|
|
48
|
-
lastFiredAt:
|
|
49
|
-
nextFireAt: computeNextFireTime(
|
|
176
|
+
lastFiredAt: new Date(now - 2 * HOUR),
|
|
177
|
+
nextFireAt: computeNextFireTime(every4h, new Date(now)),
|
|
178
|
+
type: "heartbeat",
|
|
179
|
+
heartbeatChecklist: JSON.stringify([
|
|
180
|
+
"New 1-star or 2-star product review?",
|
|
181
|
+
"Competitor price drop >10% on a tracked SKU?",
|
|
182
|
+
"Inventory below reorder threshold for top 10 SKUs?",
|
|
183
|
+
]),
|
|
184
|
+
activeHoursStart: 6,
|
|
185
|
+
activeHoursEnd: 22,
|
|
186
|
+
activeTimezone: "America/New_York",
|
|
187
|
+
deliveryChannels: null,
|
|
50
188
|
createdAt: new Date(now - 10 * DAY),
|
|
51
189
|
updatedAt: new Date(now - 2 * HOUR),
|
|
52
190
|
},
|
|
191
|
+
|
|
192
|
+
// 6. Compliance Scan — daily 6am, paused (client paused)
|
|
53
193
|
{
|
|
54
194
|
id: crypto.randomUUID(),
|
|
55
|
-
projectId:
|
|
56
|
-
name: "
|
|
195
|
+
projectId: medreachProject,
|
|
196
|
+
name: "HIPAA Compliance Scan",
|
|
57
197
|
prompt:
|
|
58
|
-
"
|
|
59
|
-
cronExpression:
|
|
60
|
-
agentProfile:
|
|
198
|
+
"Scan all pending marketing content for HIPAA violations, unsubstantiated health claims, and missing disclaimers. Generate a compliance scorecard and route flagged items to legal.",
|
|
199
|
+
cronExpression: daily6am,
|
|
200
|
+
agentProfile: "general",
|
|
61
201
|
recurs: true,
|
|
62
202
|
status: "paused",
|
|
63
203
|
maxFirings: null,
|
|
64
|
-
firingCount:
|
|
204
|
+
firingCount: 6,
|
|
65
205
|
expiresAt: null,
|
|
66
|
-
lastFiredAt:
|
|
206
|
+
lastFiredAt: new Date(now - 5 * DAY),
|
|
67
207
|
nextFireAt: null,
|
|
68
|
-
|
|
69
|
-
|
|
208
|
+
type: "scheduled",
|
|
209
|
+
heartbeatChecklist: null,
|
|
210
|
+
activeHoursStart: null,
|
|
211
|
+
activeHoursEnd: null,
|
|
212
|
+
activeTimezone: null,
|
|
213
|
+
deliveryChannels: JSON.stringify(["email"]),
|
|
214
|
+
createdAt: new Date(now - 9 * DAY),
|
|
215
|
+
updatedAt: new Date(now - 4 * DAY),
|
|
70
216
|
},
|
|
217
|
+
|
|
218
|
+
// 7. Deal Stall Heartbeat — every 8h, RevOps
|
|
71
219
|
{
|
|
72
220
|
id: crypto.randomUUID(),
|
|
73
|
-
projectId:
|
|
74
|
-
name: "
|
|
221
|
+
projectId: revopsProject,
|
|
222
|
+
name: "Deal Stall Heartbeat",
|
|
75
223
|
prompt:
|
|
76
|
-
"
|
|
77
|
-
cronExpression:
|
|
78
|
-
agentProfile: SAMPLE_PROFILE_IDS[
|
|
224
|
+
"Evaluate stalled deal checklist. When a signal fires, draft a coaching note for the rep and suggest a specific unblocking action. Deliver via Slack to the #revenue-ops channel.",
|
|
225
|
+
cronExpression: every8h,
|
|
226
|
+
agentProfile: SAMPLE_PROFILE_IDS[4], // Revenue Ops Analyst
|
|
79
227
|
recurs: true,
|
|
80
228
|
status: "active",
|
|
81
229
|
maxFirings: null,
|
|
82
|
-
firingCount:
|
|
230
|
+
firingCount: 14,
|
|
83
231
|
expiresAt: null,
|
|
84
|
-
lastFiredAt:
|
|
85
|
-
nextFireAt: computeNextFireTime(
|
|
86
|
-
|
|
87
|
-
|
|
232
|
+
lastFiredAt: new Date(now - 6 * HOUR),
|
|
233
|
+
nextFireAt: computeNextFireTime(every8h, new Date(now)),
|
|
234
|
+
type: "heartbeat",
|
|
235
|
+
heartbeatChecklist: JSON.stringify([
|
|
236
|
+
"Any deal stalled >5 business days with no activity?",
|
|
237
|
+
"Any deal missing a defined next step?",
|
|
238
|
+
"Any champion gone dark (no email open in 7 days)?",
|
|
239
|
+
"Any deal pushed close date more than twice?",
|
|
240
|
+
]),
|
|
241
|
+
activeHoursStart: 7,
|
|
242
|
+
activeHoursEnd: 19,
|
|
243
|
+
activeTimezone: "America/Chicago",
|
|
244
|
+
deliveryChannels: JSON.stringify(["slack"]),
|
|
245
|
+
createdAt: new Date(now - 7 * DAY),
|
|
246
|
+
updatedAt: new Date(now - 6 * HOUR),
|
|
88
247
|
},
|
|
248
|
+
|
|
249
|
+
// 8. Monthly Audit Run — 1st of month, expired
|
|
89
250
|
{
|
|
90
251
|
id: crypto.randomUUID(),
|
|
91
|
-
projectId:
|
|
92
|
-
name: "
|
|
252
|
+
projectId: complianceProject,
|
|
253
|
+
name: "Monthly Compliance Audit",
|
|
93
254
|
prompt:
|
|
94
|
-
"
|
|
95
|
-
cronExpression:
|
|
96
|
-
agentProfile: "
|
|
255
|
+
"Run the full monthly compliance audit: gather execution logs, analyze against SOC 2 controls, generate the report, and prepare the executive brief. Deliver to the compliance-reviews channel.",
|
|
256
|
+
cronExpression: monthly1st,
|
|
257
|
+
agentProfile: "general",
|
|
97
258
|
recurs: false,
|
|
98
259
|
status: "expired",
|
|
99
260
|
maxFirings: 1,
|
|
100
|
-
firingCount:
|
|
261
|
+
firingCount: 1,
|
|
101
262
|
expiresAt: new Date(now - 1 * DAY),
|
|
102
|
-
lastFiredAt:
|
|
263
|
+
lastFiredAt: new Date(now - 3 * DAY),
|
|
103
264
|
nextFireAt: null,
|
|
104
|
-
|
|
265
|
+
type: "scheduled",
|
|
266
|
+
heartbeatChecklist: null,
|
|
267
|
+
activeHoursStart: null,
|
|
268
|
+
activeHoursEnd: null,
|
|
269
|
+
activeTimezone: null,
|
|
270
|
+
deliveryChannels: JSON.stringify(["slack", "email"]),
|
|
271
|
+
createdAt: new Date(now - 5 * DAY),
|
|
105
272
|
updatedAt: new Date(now - 1 * DAY),
|
|
106
273
|
},
|
|
107
274
|
];
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import { randomUUID } from "crypto";
|
|
2
|
+
import { db } from "@/lib/db";
|
|
3
|
+
import { userTableTemplates } from "@/lib/db/schema";
|
|
4
|
+
import { eq, and } from "drizzle-orm";
|
|
5
|
+
|
|
6
|
+
interface TemplateSeed {
|
|
7
|
+
name: string;
|
|
8
|
+
description: string;
|
|
9
|
+
category: "business" | "personal" | "pm" | "finance" | "content";
|
|
10
|
+
icon: string;
|
|
11
|
+
columns: Array<{
|
|
12
|
+
name: string;
|
|
13
|
+
displayName: string;
|
|
14
|
+
dataType: string;
|
|
15
|
+
config?: Record<string, unknown>;
|
|
16
|
+
}>;
|
|
17
|
+
sampleData?: Record<string, unknown>[];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const TEMPLATES: TemplateSeed[] = [
|
|
21
|
+
// ── Business ───────────────────────────────────────────────────────
|
|
22
|
+
{
|
|
23
|
+
name: "Customer List",
|
|
24
|
+
description: "Track customers with contact info and status",
|
|
25
|
+
category: "business",
|
|
26
|
+
icon: "Building2",
|
|
27
|
+
columns: [
|
|
28
|
+
{ name: "name", displayName: "Name", dataType: "text" },
|
|
29
|
+
{ name: "email", displayName: "Email", dataType: "email" },
|
|
30
|
+
{ name: "company", displayName: "Company", dataType: "text" },
|
|
31
|
+
{ name: "status", displayName: "Status", dataType: "select", config: { options: ["Lead", "Active", "Churned"] } },
|
|
32
|
+
{ name: "notes", displayName: "Notes", dataType: "text" },
|
|
33
|
+
],
|
|
34
|
+
sampleData: [
|
|
35
|
+
{ name: "Alice Johnson", email: "alice@example.com", company: "Acme Corp", status: "Active", notes: "" },
|
|
36
|
+
{ name: "Bob Smith", email: "bob@example.com", company: "Widget Inc", status: "Lead", notes: "Follow up next week" },
|
|
37
|
+
],
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
name: "Product Inventory",
|
|
41
|
+
description: "Track products, quantities, and pricing",
|
|
42
|
+
category: "business",
|
|
43
|
+
icon: "Package",
|
|
44
|
+
columns: [
|
|
45
|
+
{ name: "product", displayName: "Product", dataType: "text" },
|
|
46
|
+
{ name: "sku", displayName: "SKU", dataType: "text" },
|
|
47
|
+
{ name: "quantity", displayName: "Quantity", dataType: "number" },
|
|
48
|
+
{ name: "price", displayName: "Price", dataType: "number" },
|
|
49
|
+
{ name: "category", displayName: "Category", dataType: "select", config: { options: ["Electronics", "Clothing", "Food", "Other"] } },
|
|
50
|
+
],
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: "Meeting Notes",
|
|
54
|
+
description: "Log meetings with attendees and action items",
|
|
55
|
+
category: "business",
|
|
56
|
+
icon: "Users",
|
|
57
|
+
columns: [
|
|
58
|
+
{ name: "date", displayName: "Date", dataType: "date" },
|
|
59
|
+
{ name: "title", displayName: "Title", dataType: "text" },
|
|
60
|
+
{ name: "attendees", displayName: "Attendees", dataType: "text" },
|
|
61
|
+
{ name: "notes", displayName: "Notes", dataType: "text" },
|
|
62
|
+
{ name: "action_items", displayName: "Action Items", dataType: "text" },
|
|
63
|
+
],
|
|
64
|
+
},
|
|
65
|
+
|
|
66
|
+
// ── Personal ───────────────────────────────────────────────────────
|
|
67
|
+
{
|
|
68
|
+
name: "Reading List",
|
|
69
|
+
description: "Books and articles to read",
|
|
70
|
+
category: "personal",
|
|
71
|
+
icon: "BookOpen",
|
|
72
|
+
columns: [
|
|
73
|
+
{ name: "title", displayName: "Title", dataType: "text" },
|
|
74
|
+
{ name: "author", displayName: "Author", dataType: "text" },
|
|
75
|
+
{ name: "status", displayName: "Status", dataType: "select", config: { options: ["To Read", "Reading", "Finished"] } },
|
|
76
|
+
{ name: "rating", displayName: "Rating", dataType: "number" },
|
|
77
|
+
{ name: "notes", displayName: "Notes", dataType: "text" },
|
|
78
|
+
],
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
name: "Habit Tracker",
|
|
82
|
+
description: "Daily habits and streaks",
|
|
83
|
+
category: "personal",
|
|
84
|
+
icon: "Target",
|
|
85
|
+
columns: [
|
|
86
|
+
{ name: "habit", displayName: "Habit", dataType: "text" },
|
|
87
|
+
{ name: "frequency", displayName: "Frequency", dataType: "select", config: { options: ["Daily", "Weekly", "Monthly"] } },
|
|
88
|
+
{ name: "streak", displayName: "Streak", dataType: "number" },
|
|
89
|
+
{ name: "completed", displayName: "Completed Today", dataType: "boolean" },
|
|
90
|
+
],
|
|
91
|
+
},
|
|
92
|
+
|
|
93
|
+
// ── Project Management ─────────────────────────────────────────────
|
|
94
|
+
{
|
|
95
|
+
name: "Sprint Board",
|
|
96
|
+
description: "Track sprint tasks with points and assignees",
|
|
97
|
+
category: "pm",
|
|
98
|
+
icon: "KanbanSquare",
|
|
99
|
+
columns: [
|
|
100
|
+
{ name: "task", displayName: "Task", dataType: "text" },
|
|
101
|
+
{ name: "assignee", displayName: "Assignee", dataType: "text" },
|
|
102
|
+
{ name: "status", displayName: "Status", dataType: "select", config: { options: ["Backlog", "In Progress", "Review", "Done"] } },
|
|
103
|
+
{ name: "points", displayName: "Points", dataType: "number" },
|
|
104
|
+
{ name: "due_date", displayName: "Due Date", dataType: "date" },
|
|
105
|
+
],
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
name: "Bug Tracker",
|
|
109
|
+
description: "Track bugs with severity and reproduction steps",
|
|
110
|
+
category: "pm",
|
|
111
|
+
icon: "Bug",
|
|
112
|
+
columns: [
|
|
113
|
+
{ name: "title", displayName: "Title", dataType: "text" },
|
|
114
|
+
{ name: "severity", displayName: "Severity", dataType: "select", config: { options: ["Critical", "High", "Medium", "Low"] } },
|
|
115
|
+
{ name: "status", displayName: "Status", dataType: "select", config: { options: ["Open", "In Progress", "Fixed", "Closed"] } },
|
|
116
|
+
{ name: "reported_by", displayName: "Reported By", dataType: "text" },
|
|
117
|
+
{ name: "steps", displayName: "Steps to Reproduce", dataType: "text" },
|
|
118
|
+
],
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
name: "Feature Requests",
|
|
122
|
+
description: "Collect and prioritize feature ideas",
|
|
123
|
+
category: "pm",
|
|
124
|
+
icon: "Lightbulb",
|
|
125
|
+
columns: [
|
|
126
|
+
{ name: "feature", displayName: "Feature", dataType: "text" },
|
|
127
|
+
{ name: "requester", displayName: "Requester", dataType: "text" },
|
|
128
|
+
{ name: "priority", displayName: "Priority", dataType: "select", config: { options: ["P0", "P1", "P2", "P3"] } },
|
|
129
|
+
{ name: "votes", displayName: "Votes", dataType: "number" },
|
|
130
|
+
{ name: "status", displayName: "Status", dataType: "select", config: { options: ["Proposed", "Approved", "Building", "Shipped"] } },
|
|
131
|
+
],
|
|
132
|
+
},
|
|
133
|
+
|
|
134
|
+
// ── Finance ────────────────────────────────────────────────────────
|
|
135
|
+
{
|
|
136
|
+
name: "Expense Tracker",
|
|
137
|
+
description: "Log expenses with categories and receipts",
|
|
138
|
+
category: "finance",
|
|
139
|
+
icon: "Receipt",
|
|
140
|
+
columns: [
|
|
141
|
+
{ name: "date", displayName: "Date", dataType: "date" },
|
|
142
|
+
{ name: "description", displayName: "Description", dataType: "text" },
|
|
143
|
+
{ name: "amount", displayName: "Amount", dataType: "number" },
|
|
144
|
+
{ name: "category", displayName: "Category", dataType: "select", config: { options: ["Food", "Transport", "Software", "Office", "Other"] } },
|
|
145
|
+
{ name: "receipt_url", displayName: "Receipt", dataType: "url" },
|
|
146
|
+
],
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
name: "Invoice Log",
|
|
150
|
+
description: "Track invoices and payment status",
|
|
151
|
+
category: "finance",
|
|
152
|
+
icon: "FileText",
|
|
153
|
+
columns: [
|
|
154
|
+
{ name: "invoice_number", displayName: "Invoice #", dataType: "text" },
|
|
155
|
+
{ name: "client", displayName: "Client", dataType: "text" },
|
|
156
|
+
{ name: "amount", displayName: "Amount", dataType: "number" },
|
|
157
|
+
{ name: "issued_date", displayName: "Issued", dataType: "date" },
|
|
158
|
+
{ name: "status", displayName: "Status", dataType: "select", config: { options: ["Draft", "Sent", "Paid", "Overdue"] } },
|
|
159
|
+
],
|
|
160
|
+
},
|
|
161
|
+
|
|
162
|
+
// ── Content ────────────────────────────────────────────────────────
|
|
163
|
+
{
|
|
164
|
+
name: "Content Calendar",
|
|
165
|
+
description: "Plan and schedule content across channels",
|
|
166
|
+
category: "content",
|
|
167
|
+
icon: "Calendar",
|
|
168
|
+
columns: [
|
|
169
|
+
{ name: "title", displayName: "Title", dataType: "text" },
|
|
170
|
+
{ name: "channel", displayName: "Channel", dataType: "select", config: { options: ["Blog", "Twitter", "LinkedIn", "Newsletter", "YouTube"] } },
|
|
171
|
+
{ name: "publish_date", displayName: "Publish Date", dataType: "date" },
|
|
172
|
+
{ name: "status", displayName: "Status", dataType: "select", config: { options: ["Idea", "Drafting", "Review", "Scheduled", "Published"] } },
|
|
173
|
+
{ name: "url", displayName: "URL", dataType: "url" },
|
|
174
|
+
],
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
name: "Research Notes",
|
|
178
|
+
description: "Organize research with sources and tags",
|
|
179
|
+
category: "content",
|
|
180
|
+
icon: "Search",
|
|
181
|
+
columns: [
|
|
182
|
+
{ name: "topic", displayName: "Topic", dataType: "text" },
|
|
183
|
+
{ name: "source", displayName: "Source", dataType: "url" },
|
|
184
|
+
{ name: "key_findings", displayName: "Key Findings", dataType: "text" },
|
|
185
|
+
{ name: "relevance", displayName: "Relevance", dataType: "select", config: { options: ["High", "Medium", "Low"] } },
|
|
186
|
+
{ name: "date_added", displayName: "Date Added", dataType: "date" },
|
|
187
|
+
],
|
|
188
|
+
},
|
|
189
|
+
];
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Seed system templates if not already present.
|
|
193
|
+
* Idempotent — checks for existing templates by name + scope='system'.
|
|
194
|
+
*/
|
|
195
|
+
export async function seedTableTemplates(): Promise<number> {
|
|
196
|
+
let created = 0;
|
|
197
|
+
const now = new Date();
|
|
198
|
+
|
|
199
|
+
for (const t of TEMPLATES) {
|
|
200
|
+
const existing = db
|
|
201
|
+
.select()
|
|
202
|
+
.from(userTableTemplates)
|
|
203
|
+
.where(
|
|
204
|
+
and(
|
|
205
|
+
eq(userTableTemplates.name, t.name),
|
|
206
|
+
eq(userTableTemplates.scope, "system")
|
|
207
|
+
)
|
|
208
|
+
)
|
|
209
|
+
.get();
|
|
210
|
+
|
|
211
|
+
if (existing) continue;
|
|
212
|
+
|
|
213
|
+
const columnsWithPositions = t.columns.map((col, i) => ({
|
|
214
|
+
...col,
|
|
215
|
+
position: i,
|
|
216
|
+
}));
|
|
217
|
+
|
|
218
|
+
await db.insert(userTableTemplates).values({
|
|
219
|
+
id: randomUUID(),
|
|
220
|
+
name: t.name,
|
|
221
|
+
description: t.description,
|
|
222
|
+
category: t.category,
|
|
223
|
+
columnSchema: JSON.stringify(columnsWithPositions),
|
|
224
|
+
sampleData: t.sampleData ? JSON.stringify(t.sampleData) : null,
|
|
225
|
+
scope: "system",
|
|
226
|
+
icon: t.icon,
|
|
227
|
+
createdAt: now,
|
|
228
|
+
updatedAt: now,
|
|
229
|
+
});
|
|
230
|
+
created++;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
return created;
|
|
234
|
+
}
|