stagent 0.6.3 → 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.
Files changed (123) hide show
  1. package/README.md +21 -2
  2. package/dist/cli.js +226 -1
  3. package/docs/.coverage-gaps.json +66 -16
  4. package/docs/.last-generated +1 -1
  5. package/docs/features/dashboard-kanban.md +13 -7
  6. package/docs/features/settings.md +15 -3
  7. package/docs/features/tables.md +122 -0
  8. package/docs/index.md +3 -2
  9. package/docs/journeys/developer.md +26 -16
  10. package/docs/journeys/personal-use.md +23 -9
  11. package/docs/journeys/power-user.md +40 -14
  12. package/docs/journeys/work-use.md +43 -15
  13. package/docs/manifest.json +27 -17
  14. package/package.json +3 -1
  15. package/src/app/api/chat/entities/search/route.ts +12 -3
  16. package/src/app/api/projects/[id]/route.ts +37 -0
  17. package/src/app/api/projects/__tests__/delete-project.test.ts +12 -0
  18. package/src/app/api/snapshots/[id]/restore/route.ts +62 -0
  19. package/src/app/api/snapshots/[id]/route.ts +44 -0
  20. package/src/app/api/snapshots/route.ts +54 -0
  21. package/src/app/api/snapshots/settings/route.ts +67 -0
  22. package/src/app/api/tables/[id]/charts/[chartId]/route.ts +89 -0
  23. package/src/app/api/tables/[id]/charts/route.ts +72 -0
  24. package/src/app/api/tables/[id]/columns/route.ts +70 -0
  25. package/src/app/api/tables/[id]/export/route.ts +94 -0
  26. package/src/app/api/tables/[id]/history/route.ts +15 -0
  27. package/src/app/api/tables/[id]/import/route.ts +111 -0
  28. package/src/app/api/tables/[id]/route.ts +86 -0
  29. package/src/app/api/tables/[id]/rows/[rowId]/history/route.ts +32 -0
  30. package/src/app/api/tables/[id]/rows/[rowId]/route.ts +51 -0
  31. package/src/app/api/tables/[id]/rows/route.ts +101 -0
  32. package/src/app/api/tables/[id]/triggers/[triggerId]/route.ts +65 -0
  33. package/src/app/api/tables/[id]/triggers/route.ts +122 -0
  34. package/src/app/api/tables/route.ts +65 -0
  35. package/src/app/api/tables/templates/route.ts +92 -0
  36. package/src/app/settings/page.tsx +2 -0
  37. package/src/app/tables/[id]/page.tsx +67 -0
  38. package/src/app/tables/page.tsx +21 -0
  39. package/src/app/tables/templates/page.tsx +19 -0
  40. package/src/components/chat/chat-table-result.tsx +139 -0
  41. package/src/components/documents/document-browser.tsx +1 -1
  42. package/src/components/projects/project-form-sheet.tsx +3 -27
  43. package/src/components/schedules/schedule-form.tsx +5 -27
  44. package/src/components/settings/data-management-section.tsx +17 -12
  45. package/src/components/settings/database-snapshots-section.tsx +469 -0
  46. package/src/components/shared/app-sidebar.tsx +2 -0
  47. package/src/components/shared/document-picker-sheet.tsx +214 -11
  48. package/src/components/tables/table-browser.tsx +234 -0
  49. package/src/components/tables/table-cell-editor.tsx +226 -0
  50. package/src/components/tables/table-chart-builder.tsx +288 -0
  51. package/src/components/tables/table-chart-view.tsx +146 -0
  52. package/src/components/tables/table-column-header.tsx +103 -0
  53. package/src/components/tables/table-column-sheet.tsx +331 -0
  54. package/src/components/tables/table-create-sheet.tsx +240 -0
  55. package/src/components/tables/table-detail-sheet.tsx +144 -0
  56. package/src/components/tables/table-detail-tabs.tsx +278 -0
  57. package/src/components/tables/table-grid.tsx +61 -0
  58. package/src/components/tables/table-history-tab.tsx +148 -0
  59. package/src/components/tables/table-import-wizard.tsx +542 -0
  60. package/src/components/tables/table-list-table.tsx +95 -0
  61. package/src/components/tables/table-relation-combobox.tsx +217 -0
  62. package/src/components/tables/table-spreadsheet.tsx +499 -0
  63. package/src/components/tables/table-template-gallery.tsx +162 -0
  64. package/src/components/tables/table-template-preview.tsx +219 -0
  65. package/src/components/tables/table-toolbar.tsx +79 -0
  66. package/src/components/tables/table-triggers-tab.tsx +446 -0
  67. package/src/components/tables/types.ts +6 -0
  68. package/src/components/tables/use-spreadsheet-keys.ts +171 -0
  69. package/src/components/tables/utils.ts +29 -0
  70. package/src/components/tasks/task-create-panel.tsx +5 -31
  71. package/src/components/tasks/task-edit-dialog.tsx +5 -27
  72. package/src/components/workflows/workflow-form-view.tsx +5 -29
  73. package/src/components/workflows/workflow-status-view.tsx +1 -1
  74. package/src/instrumentation.ts +3 -0
  75. package/src/lib/agents/__tests__/claude-agent.test.ts +5 -1
  76. package/src/lib/agents/claude-agent.ts +3 -1
  77. package/src/lib/agents/runtime/anthropic-direct.ts +29 -0
  78. package/src/lib/agents/runtime/openai-direct.ts +29 -0
  79. package/src/lib/chat/stagent-tools.ts +2 -0
  80. package/src/lib/chat/tool-catalog.ts +34 -0
  81. package/src/lib/chat/tools/table-tools.ts +955 -0
  82. package/src/lib/constants/table-status.ts +68 -0
  83. package/src/lib/data/__tests__/clear.test.ts +1 -1
  84. package/src/lib/data/clear.ts +45 -0
  85. package/src/lib/data/seed-data/__tests__/profiles.test.ts +28 -23
  86. package/src/lib/data/seed-data/conversations.ts +350 -42
  87. package/src/lib/data/seed-data/documents.ts +564 -591
  88. package/src/lib/data/seed-data/learned-context.ts +101 -22
  89. package/src/lib/data/seed-data/notifications.ts +344 -70
  90. package/src/lib/data/seed-data/profile-test-results.ts +92 -11
  91. package/src/lib/data/seed-data/profiles.ts +144 -46
  92. package/src/lib/data/seed-data/projects.ts +50 -18
  93. package/src/lib/data/seed-data/repo-imports.ts +28 -13
  94. package/src/lib/data/seed-data/schedules.ts +208 -41
  95. package/src/lib/data/seed-data/table-templates.ts +234 -0
  96. package/src/lib/data/seed-data/tasks.ts +614 -116
  97. package/src/lib/data/seed-data/usage-ledger.ts +182 -103
  98. package/src/lib/data/seed-data/user-tables.ts +203 -0
  99. package/src/lib/data/seed-data/views.ts +52 -7
  100. package/src/lib/data/seed-data/workflows.ts +231 -84
  101. package/src/lib/data/seed.ts +55 -14
  102. package/src/lib/data/tables.ts +417 -0
  103. package/src/lib/db/bootstrap.ts +227 -0
  104. package/src/lib/db/index.ts +9 -0
  105. package/src/lib/db/migrations/0019_add_tables_feature.sql +160 -0
  106. package/src/lib/db/migrations/0020_add_table_triggers.sql +19 -0
  107. package/src/lib/db/migrations/0021_add_row_history.sql +15 -0
  108. package/src/lib/db/schema.ts +368 -0
  109. package/src/lib/snapshots/auto-backup.ts +132 -0
  110. package/src/lib/snapshots/retention.ts +64 -0
  111. package/src/lib/snapshots/snapshot-manager.ts +429 -0
  112. package/src/lib/tables/computed.ts +61 -0
  113. package/src/lib/tables/context-builder.ts +139 -0
  114. package/src/lib/tables/formula-engine.ts +415 -0
  115. package/src/lib/tables/history.ts +115 -0
  116. package/src/lib/tables/import.ts +343 -0
  117. package/src/lib/tables/query-builder.ts +152 -0
  118. package/src/lib/tables/trigger-evaluator.ts +146 -0
  119. package/src/lib/tables/types.ts +141 -0
  120. package/src/lib/tables/validation.ts +119 -0
  121. package/src/lib/utils/stagent-paths.ts +20 -0
  122. package/tsconfig.json +3 -1
  123. /package/docs/features/{playbook.md → user-guide.md} +0 -0
@@ -0,0 +1,219 @@
1
+ "use client";
2
+
3
+ import { useState } from "react";
4
+ import { Button } from "@/components/ui/button";
5
+ import { Input } from "@/components/ui/input";
6
+ import { Label } from "@/components/ui/label";
7
+ import { Badge } from "@/components/ui/badge";
8
+ import { Switch } from "@/components/ui/switch";
9
+ import {
10
+ Sheet,
11
+ SheetContent,
12
+ SheetHeader,
13
+ SheetTitle,
14
+ SheetFooter,
15
+ } from "@/components/ui/sheet";
16
+ import {
17
+ Table,
18
+ TableBody,
19
+ TableCell,
20
+ TableHead,
21
+ TableHeader,
22
+ TableRow,
23
+ } from "@/components/ui/table";
24
+ import { toast } from "sonner";
25
+ import type { UserTableTemplateRow } from "@/lib/db/schema";
26
+ import type { ColumnDef } from "@/lib/tables/types";
27
+
28
+ interface TableTemplatePreviewProps {
29
+ template: UserTableTemplateRow;
30
+ open: boolean;
31
+ onOpenChange: (open: boolean) => void;
32
+ onCloned: (tableId: string) => void;
33
+ }
34
+
35
+ export function TableTemplatePreview({
36
+ template,
37
+ open,
38
+ onOpenChange,
39
+ onCloned,
40
+ }: TableTemplatePreviewProps) {
41
+ const [step, setStep] = useState<"preview" | "clone">("preview");
42
+ const [name, setName] = useState(template.name);
43
+ const [includeSampleData, setIncludeSampleData] = useState(true);
44
+ const [saving, setSaving] = useState(false);
45
+
46
+ let columns: ColumnDef[] = [];
47
+ try {
48
+ columns = JSON.parse(template.columnSchema) as ColumnDef[];
49
+ } catch { /* */ }
50
+
51
+ let sampleData: Record<string, unknown>[] = [];
52
+ try {
53
+ if (template.sampleData) {
54
+ sampleData = JSON.parse(template.sampleData) as Record<string, unknown>[];
55
+ }
56
+ } catch { /* */ }
57
+
58
+ async function handleClone() {
59
+ if (!name.trim()) {
60
+ toast.error("Table name is required");
61
+ return;
62
+ }
63
+
64
+ setSaving(true);
65
+ try {
66
+ const res = await fetch("/api/tables", {
67
+ method: "POST",
68
+ headers: { "Content-Type": "application/json" },
69
+ body: JSON.stringify({
70
+ templateId: template.id,
71
+ name: name.trim(),
72
+ includeSampleData,
73
+ }),
74
+ });
75
+
76
+ if (!res.ok) {
77
+ toast.error("Failed to create table from template");
78
+ return;
79
+ }
80
+
81
+ const table = await res.json();
82
+ toast.success(`Table "${name}" created from template`);
83
+ onCloned(table.id);
84
+ } catch {
85
+ toast.error("Failed to create table from template");
86
+ } finally {
87
+ setSaving(false);
88
+ }
89
+ }
90
+
91
+ return (
92
+ <Sheet
93
+ open={open}
94
+ onOpenChange={(v) => {
95
+ if (!v) setStep("preview");
96
+ onOpenChange(v);
97
+ }}
98
+ >
99
+ <SheetContent side="right" className="w-[520px] sm:max-w-[520px]">
100
+ <SheetHeader>
101
+ <SheetTitle>
102
+ {step === "preview" ? template.name : "Create from Template"}
103
+ </SheetTitle>
104
+ </SheetHeader>
105
+
106
+ <div className="px-6 pb-6 space-y-4 overflow-y-auto">
107
+ {step === "preview" ? (
108
+ <>
109
+ {template.description && (
110
+ <p className="text-sm text-muted-foreground">
111
+ {template.description}
112
+ </p>
113
+ )}
114
+
115
+ <div className="space-y-1">
116
+ <h4 className="text-sm font-medium">
117
+ Columns ({columns.length})
118
+ </h4>
119
+ <div className="rounded-md border divide-y">
120
+ {columns.map((col) => (
121
+ <div
122
+ key={col.name}
123
+ className="flex items-center justify-between px-3 py-2 text-sm"
124
+ >
125
+ <span>{col.displayName}</span>
126
+ <Badge variant="outline" className="text-xs">
127
+ {col.dataType}
128
+ </Badge>
129
+ </div>
130
+ ))}
131
+ </div>
132
+ </div>
133
+
134
+ {sampleData.length > 0 && (
135
+ <div className="space-y-1">
136
+ <h4 className="text-sm font-medium">Sample Data</h4>
137
+ <div className="rounded-md border overflow-auto max-h-[200px]">
138
+ <Table>
139
+ <TableHeader>
140
+ <TableRow>
141
+ {columns.map((col) => (
142
+ <TableHead key={col.name} className="text-xs">
143
+ {col.displayName}
144
+ </TableHead>
145
+ ))}
146
+ </TableRow>
147
+ </TableHeader>
148
+ <TableBody>
149
+ {sampleData.slice(0, 5).map((row, i) => (
150
+ <TableRow key={i}>
151
+ {columns.map((col) => (
152
+ <TableCell key={col.name} className="text-xs">
153
+ {String(row[col.name] ?? "—")}
154
+ </TableCell>
155
+ ))}
156
+ </TableRow>
157
+ ))}
158
+ </TableBody>
159
+ </Table>
160
+ </div>
161
+ </div>
162
+ )}
163
+ </>
164
+ ) : (
165
+ <>
166
+ <div className="space-y-2">
167
+ <Label htmlFor="clone-name">Table Name</Label>
168
+ <Input
169
+ id="clone-name"
170
+ value={name}
171
+ onChange={(e) => setName(e.target.value)}
172
+ />
173
+ </div>
174
+
175
+ <div className="flex items-center justify-between">
176
+ <Label htmlFor="include-data">Include sample data</Label>
177
+ <Switch
178
+ id="include-data"
179
+ checked={includeSampleData}
180
+ onCheckedChange={setIncludeSampleData}
181
+ />
182
+ </div>
183
+
184
+ <p className="text-xs text-muted-foreground">
185
+ Creates a new table with {columns.length} columns
186
+ {includeSampleData && sampleData.length > 0
187
+ ? ` and ${sampleData.length} sample rows`
188
+ : ""}
189
+ .
190
+ </p>
191
+ </>
192
+ )}
193
+ </div>
194
+
195
+ <SheetFooter className="px-6">
196
+ {step === "preview" ? (
197
+ <>
198
+ <Button variant="outline" onClick={() => onOpenChange(false)}>
199
+ Close
200
+ </Button>
201
+ <Button onClick={() => setStep("clone")}>
202
+ Use This Template
203
+ </Button>
204
+ </>
205
+ ) : (
206
+ <>
207
+ <Button variant="outline" onClick={() => setStep("preview")}>
208
+ Back
209
+ </Button>
210
+ <Button onClick={handleClone} disabled={saving}>
211
+ {saving ? "Creating..." : "Create Table"}
212
+ </Button>
213
+ </>
214
+ )}
215
+ </SheetFooter>
216
+ </SheetContent>
217
+ </Sheet>
218
+ );
219
+ }
@@ -0,0 +1,79 @@
1
+ "use client";
2
+
3
+ import { Button } from "@/components/ui/button";
4
+ import {
5
+ DropdownMenu,
6
+ DropdownMenuContent,
7
+ DropdownMenuItem,
8
+ DropdownMenuTrigger,
9
+ } from "@/components/ui/dropdown-menu";
10
+ import { Plus, Columns3, Trash2, Upload, Download } from "lucide-react";
11
+
12
+ interface TableToolbarProps {
13
+ tableId: string;
14
+ rowCount: number;
15
+ selectedCount: number;
16
+ onAddRow: () => void;
17
+ onAddColumn: () => void;
18
+ onBulkDelete: () => void;
19
+ onImport?: () => void;
20
+ }
21
+
22
+ export function TableToolbar({
23
+ tableId,
24
+ rowCount,
25
+ selectedCount,
26
+ onAddRow,
27
+ onAddColumn,
28
+ onBulkDelete,
29
+ onImport,
30
+ }: TableToolbarProps) {
31
+ function handleExport(format: string) {
32
+ window.open(`/api/tables/${tableId}/export?format=${format}`, "_blank");
33
+ }
34
+
35
+ return (
36
+ <div className="flex items-center gap-2 py-2">
37
+ <Button variant="outline" size="sm" onClick={onAddColumn}>
38
+ <Columns3 className="h-4 w-4 mr-1" />
39
+ Column
40
+ </Button>
41
+ <Button variant="outline" size="sm" onClick={onAddRow}>
42
+ <Plus className="h-4 w-4 mr-1" />
43
+ Row
44
+ </Button>
45
+
46
+ {onImport && (
47
+ <Button variant="outline" size="sm" onClick={onImport}>
48
+ <Upload className="h-4 w-4 mr-1" />
49
+ Import
50
+ </Button>
51
+ )}
52
+
53
+ <DropdownMenu>
54
+ <DropdownMenuTrigger asChild>
55
+ <Button variant="outline" size="sm">
56
+ <Download className="h-4 w-4 mr-1" />
57
+ Export
58
+ </Button>
59
+ </DropdownMenuTrigger>
60
+ <DropdownMenuContent align="start">
61
+ <DropdownMenuItem onClick={() => handleExport("csv")}>Export CSV</DropdownMenuItem>
62
+ <DropdownMenuItem onClick={() => handleExport("xlsx")}>Export Excel</DropdownMenuItem>
63
+ <DropdownMenuItem onClick={() => handleExport("json")}>Export JSON</DropdownMenuItem>
64
+ </DropdownMenuContent>
65
+ </DropdownMenu>
66
+
67
+ {selectedCount > 0 && (
68
+ <Button variant="destructive" size="sm" onClick={onBulkDelete}>
69
+ <Trash2 className="h-4 w-4 mr-1" />
70
+ Delete ({selectedCount})
71
+ </Button>
72
+ )}
73
+
74
+ <span className="ml-auto text-xs text-muted-foreground">
75
+ {rowCount} {rowCount === 1 ? "row" : "rows"}
76
+ </span>
77
+ </div>
78
+ );
79
+ }