@oneie/sdk 0.13.9 → 0.14.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/dist/receivers.d.ts +74 -0
- package/dist/receivers.d.ts.map +1 -1
- package/dist/receivers.js +81 -2
- package/dist/receivers.js.map +1 -1
- package/dist/skills.d.ts +7 -5
- package/dist/skills.d.ts.map +1 -1
- package/dist/skills.js.map +1 -1
- package/dist/templates.d.ts +1 -0
- package/dist/templates.d.ts.map +1 -1
- package/dist/templates.js +919 -72
- package/dist/templates.js.map +1 -1
- package/package.json +1 -1
package/dist/templates.js
CHANGED
|
@@ -1,125 +1,931 @@
|
|
|
1
|
+
// ─── Industry & department resource-type templates ───────────────────────────
|
|
2
|
+
//
|
|
3
|
+
// Each template is a ready-made ontology a workspace can seed into its manifest
|
|
4
|
+
// (world:declare-types { template }). Every type maps to one of the 6 ONE
|
|
5
|
+
// dimensions (groups · actors · things · paths · events · learning) and the
|
|
6
|
+
// `/u/{slug}/types` canvas renders them — dimension sets the node tone, and a
|
|
7
|
+
// `relation` field whose option names a sibling key draws an edge between nodes.
|
|
8
|
+
//
|
|
9
|
+
// The library is layered:
|
|
10
|
+
// • one / world — the substrate itself and an operating workspace
|
|
11
|
+
// • crm — the shared contact graph every department reads
|
|
12
|
+
// • sales · marketing · service · education · staff — the departments
|
|
13
|
+
// • ecommerce — a store
|
|
14
|
+
// • roofers · movers — field-service verticals
|
|
15
|
+
//
|
|
16
|
+
// Authoring rules that keep the graph clean:
|
|
17
|
+
// • columns = the 2–4 fields shown on the card and the table list
|
|
18
|
+
// • fields = the full edit form
|
|
19
|
+
// • filters = the select/tag fields worth faceting on
|
|
20
|
+
// • relation field options MUST name a key in the SAME template, or no edge
|
|
21
|
+
// is drawn (extractRelationEdges drops dangling targets).
|
|
22
|
+
// • `ecommerce` is intentionally relation-free — a unit test pins that.
|
|
23
|
+
const THING_ACTIONS = ["world:create-thing", "world:update-thing", "world:remove-thing"];
|
|
24
|
+
const ACTOR_ACTIONS = ["world:create-actor", "world:update-actor"];
|
|
25
|
+
const GROUP_ACTIONS = ["world:create-group", "world:update-group"];
|
|
1
26
|
export const TEMPLATES = {
|
|
2
|
-
|
|
27
|
+
// ── one — the substrate itself: the 6 dimensions as a living graph ──────────
|
|
28
|
+
one: [
|
|
3
29
|
{
|
|
4
|
-
key: "
|
|
30
|
+
key: "groups", label: "Groups", dimension: "groups", type: "group", icon: "Boxes",
|
|
5
31
|
columns: [
|
|
6
32
|
{ field: "name", label: "Name", kind: "text", required: true },
|
|
7
|
-
{ field: "
|
|
33
|
+
{ field: "group_type", label: "Type", kind: "select", options: ["world", "team", "org", "community", "dao", "workspace", "personal"] },
|
|
34
|
+
{ field: "plan", label: "Plan", kind: "select", options: ["starter", "growth", "enterprise"] },
|
|
35
|
+
],
|
|
36
|
+
fields: [
|
|
37
|
+
{ field: "name", label: "Name", kind: "text", required: true },
|
|
38
|
+
{ field: "group_type", label: "Group type", kind: "select", options: ["world", "team", "org", "community", "dao", "workspace", "personal"] },
|
|
39
|
+
{ field: "brand", label: "Brand", kind: "text" },
|
|
40
|
+
{ field: "plan", label: "Plan", kind: "select", options: ["starter", "growth", "enterprise"] },
|
|
41
|
+
{ field: "visibility", label: "Visibility", kind: "select", options: ["private", "group", "public"] },
|
|
42
|
+
],
|
|
43
|
+
filters: [{ field: "group_type", label: "Type", kind: "select", options: ["world", "team", "org", "community", "dao", "workspace", "personal"] }],
|
|
44
|
+
actions: GROUP_ACTIONS,
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
key: "actors", label: "Actors", dimension: "actors", type: "actor", icon: "Users",
|
|
48
|
+
columns: [
|
|
49
|
+
{ field: "name", label: "Name", kind: "text", required: true },
|
|
50
|
+
{ field: "actor_type", label: "Kind", kind: "select", options: ["human", "agent", "world", "animal"] },
|
|
51
|
+
{ field: "model", label: "Model", kind: "text" },
|
|
52
|
+
],
|
|
53
|
+
fields: [
|
|
54
|
+
{ field: "name", label: "Name", kind: "text", required: true },
|
|
55
|
+
{ field: "actor_type", label: "Actor type", kind: "select", options: ["human", "agent", "world", "animal"] },
|
|
56
|
+
{ field: "model", label: "LLM model", kind: "text" },
|
|
57
|
+
{ field: "prompt", label: "System prompt", kind: "markdown" },
|
|
58
|
+
{ field: "wallet", label: "Wallet", kind: "text" },
|
|
8
59
|
{ field: "tags", label: "Tags", kind: "tags" },
|
|
60
|
+
{ field: "group", label: "Member of", kind: "relation", options: ["groups"] },
|
|
61
|
+
],
|
|
62
|
+
filters: [{ field: "actor_type", label: "Kind", kind: "select", options: ["human", "agent", "world", "animal"] }],
|
|
63
|
+
actions: ACTOR_ACTIONS,
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
key: "things", label: "Things", dimension: "things", type: "thing", icon: "Box",
|
|
67
|
+
columns: [
|
|
68
|
+
{ field: "name", label: "Name", kind: "text", required: true },
|
|
69
|
+
{ field: "thing_type", label: "Type", kind: "select", options: ["skill", "task", "token", "service", "plan"] },
|
|
70
|
+
{ field: "price", label: "Price", kind: "currency" },
|
|
9
71
|
],
|
|
10
72
|
fields: [
|
|
11
73
|
{ field: "name", label: "Name", kind: "text", required: true },
|
|
74
|
+
{ field: "thing_type", label: "Thing type", kind: "select", options: ["skill", "task", "token", "service", "plan"] },
|
|
12
75
|
{ field: "price", label: "Price", kind: "currency" },
|
|
13
|
-
{ field: "
|
|
14
|
-
{ field: "image", label: "Image", kind: "image" },
|
|
76
|
+
{ field: "status", label: "Status", kind: "text" },
|
|
15
77
|
{ field: "tags", label: "Tags", kind: "tags" },
|
|
78
|
+
{ field: "provider", label: "Provided by", kind: "relation", options: ["actors"] },
|
|
16
79
|
],
|
|
17
|
-
filters: [{ field: "
|
|
18
|
-
actions:
|
|
80
|
+
filters: [{ field: "thing_type", label: "Type", kind: "select", options: ["skill", "task", "token", "service", "plan"] }],
|
|
81
|
+
actions: THING_ACTIONS,
|
|
19
82
|
},
|
|
20
83
|
{
|
|
21
|
-
key: "
|
|
84
|
+
key: "paths", label: "Paths", dimension: "paths", type: "path", icon: "Spline",
|
|
22
85
|
columns: [
|
|
23
|
-
{ field: "name", label: "
|
|
24
|
-
{ field: "
|
|
25
|
-
{ field: "
|
|
86
|
+
{ field: "name", label: "Path", kind: "text", required: true },
|
|
87
|
+
{ field: "strength", label: "Strength", kind: "number" },
|
|
88
|
+
{ field: "resistance", label: "Resistance", kind: "number" },
|
|
26
89
|
],
|
|
27
90
|
fields: [
|
|
28
|
-
{ field: "name", label: "
|
|
29
|
-
{ field: "
|
|
30
|
-
{ field: "
|
|
91
|
+
{ field: "name", label: "Path", kind: "text", required: true },
|
|
92
|
+
{ field: "strength", label: "Strength (mark)", kind: "number" },
|
|
93
|
+
{ field: "resistance", label: "Resistance (warn)", kind: "number" },
|
|
94
|
+
{ field: "traversals", label: "Traversals", kind: "number" },
|
|
95
|
+
{ field: "scope", label: "Scope", kind: "select", options: ["private", "group", "public"] },
|
|
96
|
+
{ field: "from", label: "Source", kind: "relation", options: ["actors"] },
|
|
97
|
+
{ field: "to", label: "Target", kind: "relation", options: ["actors"] },
|
|
31
98
|
],
|
|
32
|
-
filters: [{ field: "
|
|
33
|
-
actions: [
|
|
99
|
+
filters: [{ field: "scope", label: "Scope", kind: "select", options: ["private", "group", "public"] }],
|
|
100
|
+
actions: [],
|
|
34
101
|
},
|
|
35
102
|
{
|
|
36
|
-
key: "
|
|
103
|
+
key: "events", label: "Events", dimension: "events", type: "signal", icon: "Zap",
|
|
104
|
+
columns: [
|
|
105
|
+
{ field: "name", label: "Signal", kind: "text", required: true },
|
|
106
|
+
{ field: "amount", label: "Amount", kind: "currency" },
|
|
107
|
+
{ field: "ts", label: "When", kind: "date" },
|
|
108
|
+
],
|
|
109
|
+
fields: [
|
|
110
|
+
{ field: "name", label: "Receiver", kind: "text", required: true },
|
|
111
|
+
{ field: "payload", label: "Payload", kind: "markdown" },
|
|
112
|
+
{ field: "amount", label: "Amount", kind: "currency" },
|
|
113
|
+
{ field: "success", label: "Success", kind: "select", options: ["yes", "no"] },
|
|
114
|
+
{ field: "latency", label: "Latency (ms)", kind: "number" },
|
|
115
|
+
{ field: "ts", label: "Timestamp", kind: "date" },
|
|
116
|
+
{ field: "sender", label: "Sender", kind: "relation", options: ["actors"] },
|
|
117
|
+
{ field: "receiver", label: "Receiver", kind: "relation", options: ["actors"] },
|
|
118
|
+
],
|
|
119
|
+
filters: [{ field: "success", label: "Success", kind: "select", options: ["yes", "no"] }],
|
|
120
|
+
actions: [],
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
key: "learning", label: "Learning", dimension: "learning", type: "hypothesis", icon: "Lightbulb",
|
|
124
|
+
columns: [
|
|
125
|
+
{ field: "name", label: "Statement", kind: "text", required: true },
|
|
126
|
+
{ field: "status", label: "Status", kind: "select", options: ["pending", "confirmed", "rejected"] },
|
|
127
|
+
{ field: "confidence", label: "Confidence", kind: "number" },
|
|
128
|
+
],
|
|
129
|
+
fields: [
|
|
130
|
+
{ field: "name", label: "Statement", kind: "text", required: true },
|
|
131
|
+
{ field: "status", label: "Status", kind: "select", options: ["pending", "confirmed", "rejected"] },
|
|
132
|
+
{ field: "confidence", label: "Confidence", kind: "number" },
|
|
133
|
+
{ field: "p_value", label: "p-value", kind: "number" },
|
|
134
|
+
{ field: "observations", label: "Observations", kind: "number" },
|
|
135
|
+
{ field: "source", label: "Source receiver", kind: "text" },
|
|
136
|
+
{ field: "about", label: "Belongs to", kind: "relation", options: ["groups"] },
|
|
137
|
+
],
|
|
138
|
+
filters: [{ field: "status", label: "Status", kind: "select", options: ["pending", "confirmed", "rejected"] }],
|
|
139
|
+
actions: ["world:create-hypothesis"],
|
|
140
|
+
},
|
|
141
|
+
],
|
|
142
|
+
// ── world — an operating workspace: who acts, what they make, what they aim at ─
|
|
143
|
+
world: [
|
|
144
|
+
{
|
|
145
|
+
key: "members", label: "Members", dimension: "actors", type: "member", icon: "Users",
|
|
37
146
|
columns: [
|
|
38
147
|
{ field: "name", label: "Name", kind: "text", required: true },
|
|
39
|
-
{ field: "
|
|
148
|
+
{ field: "role", label: "Role", kind: "select", options: ["owner", "admin", "member", "viewer", "agent", "auditor"] },
|
|
149
|
+
{ field: "actor_type", label: "Kind", kind: "select", options: ["human", "agent"] },
|
|
40
150
|
],
|
|
41
151
|
fields: [
|
|
42
152
|
{ field: "name", label: "Name", kind: "text", required: true },
|
|
153
|
+
{ field: "role", label: "Role", kind: "select", options: ["owner", "admin", "member", "viewer", "agent", "auditor"] },
|
|
154
|
+
{ field: "actor_type", label: "Kind", kind: "select", options: ["human", "agent"] },
|
|
43
155
|
{ field: "tags", label: "Tags", kind: "tags" },
|
|
44
156
|
],
|
|
45
|
-
filters: [],
|
|
46
|
-
actions:
|
|
157
|
+
filters: [{ field: "role", label: "Role", kind: "select", options: ["owner", "admin", "member", "viewer", "agent", "auditor"] }],
|
|
158
|
+
actions: ACTOR_ACTIONS,
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
key: "skills", label: "Skills", dimension: "things", type: "skill", icon: "Sparkles",
|
|
162
|
+
columns: [
|
|
163
|
+
{ field: "name", label: "Skill", kind: "text", required: true },
|
|
164
|
+
{ field: "price", label: "Price", kind: "currency" },
|
|
165
|
+
{ field: "tags", label: "Tags", kind: "tags" },
|
|
166
|
+
],
|
|
167
|
+
fields: [
|
|
168
|
+
{ field: "name", label: "Skill", kind: "text", required: true },
|
|
169
|
+
{ field: "description", label: "Description", kind: "markdown" },
|
|
170
|
+
{ field: "price", label: "Price", kind: "currency" },
|
|
171
|
+
{ field: "tags", label: "Tags", kind: "tags" },
|
|
172
|
+
{ field: "provider", label: "Provider", kind: "relation", options: ["members"] },
|
|
173
|
+
],
|
|
174
|
+
filters: [{ field: "tags", label: "Tags", kind: "tags" }],
|
|
175
|
+
actions: THING_ACTIONS,
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
key: "tasks", label: "Tasks", dimension: "things", type: "task", icon: "ListTodo",
|
|
179
|
+
columns: [
|
|
180
|
+
{ field: "name", label: "Task", kind: "text", required: true },
|
|
181
|
+
{ field: "status", label: "Status", kind: "select", options: ["open", "blocked", "picked", "done", "verified", "failed"] },
|
|
182
|
+
{ field: "wave", label: "Wave", kind: "select", options: ["W1", "W2", "W3", "W4"] },
|
|
183
|
+
],
|
|
184
|
+
fields: [
|
|
185
|
+
{ field: "name", label: "Task", kind: "text", required: true },
|
|
186
|
+
{ field: "status", label: "Status", kind: "select", options: ["open", "blocked", "picked", "done", "verified", "failed"] },
|
|
187
|
+
{ field: "wave", label: "Wave", kind: "select", options: ["W1", "W2", "W3", "W4"] },
|
|
188
|
+
{ field: "effort", label: "Effort", kind: "number" },
|
|
189
|
+
{ field: "value", label: "Value", kind: "number" },
|
|
190
|
+
{ field: "assignee", label: "Assignee", kind: "relation", options: ["members"] },
|
|
191
|
+
],
|
|
192
|
+
filters: [{ field: "status", label: "Status", kind: "select", options: ["open", "blocked", "picked", "done", "verified", "failed"] }],
|
|
193
|
+
actions: THING_ACTIONS,
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
key: "objectives", label: "Objectives", dimension: "things", type: "objective", icon: "Target",
|
|
197
|
+
columns: [
|
|
198
|
+
{ field: "name", label: "Objective", kind: "text", required: true },
|
|
199
|
+
{ field: "status", label: "Status", kind: "select", options: ["pending", "active", "complete"] },
|
|
200
|
+
{ field: "progress", label: "Progress", kind: "number" },
|
|
201
|
+
],
|
|
202
|
+
fields: [
|
|
203
|
+
{ field: "name", label: "Objective", kind: "text", required: true },
|
|
204
|
+
{ field: "status", label: "Status", kind: "select", options: ["pending", "active", "complete"] },
|
|
205
|
+
{ field: "priority", label: "Priority", kind: "number" },
|
|
206
|
+
{ field: "progress", label: "Progress", kind: "number" },
|
|
207
|
+
{ field: "frontier", label: "Spawned from", kind: "relation", options: ["frontiers"] },
|
|
208
|
+
],
|
|
209
|
+
filters: [{ field: "status", label: "Status", kind: "select", options: ["pending", "active", "complete"] }],
|
|
210
|
+
actions: THING_ACTIONS,
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
key: "frontiers", label: "Frontiers", dimension: "learning", type: "frontier", icon: "Compass",
|
|
214
|
+
columns: [
|
|
215
|
+
{ field: "name", label: "Frontier", kind: "text", required: true },
|
|
216
|
+
{ field: "status", label: "Status", kind: "select", options: ["unexplored", "exploring", "exhausted"] },
|
|
217
|
+
{ field: "expected_value", label: "Expected value", kind: "number" },
|
|
218
|
+
],
|
|
219
|
+
fields: [
|
|
220
|
+
{ field: "name", label: "Frontier", kind: "text", required: true },
|
|
221
|
+
{ field: "frontier_type", label: "Type", kind: "text" },
|
|
222
|
+
{ field: "status", label: "Status", kind: "select", options: ["unexplored", "exploring", "exhausted"] },
|
|
223
|
+
{ field: "expected_value", label: "Expected value", kind: "number" },
|
|
224
|
+
],
|
|
225
|
+
filters: [{ field: "status", label: "Status", kind: "select", options: ["unexplored", "exploring", "exhausted"] }],
|
|
226
|
+
actions: [],
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
key: "contributions", label: "Contributions", dimension: "events", type: "contribution", icon: "Activity",
|
|
230
|
+
columns: [
|
|
231
|
+
{ field: "name", label: "Contribution", kind: "text", required: true },
|
|
232
|
+
{ field: "contribution_type", label: "Type", kind: "select", options: ["signal", "payment", "discovery"] },
|
|
233
|
+
{ field: "impact", label: "Impact", kind: "number" },
|
|
234
|
+
],
|
|
235
|
+
fields: [
|
|
236
|
+
{ field: "name", label: "Contribution", kind: "text", required: true },
|
|
237
|
+
{ field: "contribution_type", label: "Type", kind: "select", options: ["signal", "payment", "discovery"] },
|
|
238
|
+
{ field: "impact", label: "Impact score", kind: "number" },
|
|
239
|
+
{ field: "contributor", label: "Contributor", kind: "relation", options: ["members"] },
|
|
240
|
+
],
|
|
241
|
+
filters: [{ field: "contribution_type", label: "Type", kind: "select", options: ["signal", "payment", "discovery"] }],
|
|
242
|
+
actions: [],
|
|
47
243
|
},
|
|
48
244
|
],
|
|
245
|
+
// ── crm — contacts, the companies they belong to, deals, and the work ───────
|
|
49
246
|
crm: [
|
|
50
247
|
{
|
|
51
248
|
key: "contacts", label: "Contacts", dimension: "actors", type: "contact", icon: "UserRound",
|
|
52
249
|
columns: [
|
|
53
250
|
{ field: "name", label: "Name", kind: "text", required: true },
|
|
54
|
-
{ field: "
|
|
251
|
+
{ field: "lifecycle", label: "Stage", kind: "select", options: ["lead", "mql", "sql", "customer", "churned"] },
|
|
252
|
+
{ field: "company", label: "Company", kind: "relation", options: ["companies"] },
|
|
55
253
|
],
|
|
56
254
|
fields: [
|
|
57
255
|
{ field: "name", label: "Name", kind: "text", required: true },
|
|
256
|
+
{ field: "email", label: "Email", kind: "text" },
|
|
257
|
+
{ field: "phone", label: "Phone", kind: "text" },
|
|
258
|
+
{ field: "title", label: "Job title", kind: "text" },
|
|
259
|
+
{ field: "lifecycle", label: "Lifecycle", kind: "select", options: ["lead", "mql", "sql", "customer", "churned"] },
|
|
58
260
|
{ field: "tags", label: "Tags", kind: "tags" },
|
|
261
|
+
{ field: "company", label: "Company", kind: "relation", options: ["companies"] },
|
|
59
262
|
],
|
|
60
|
-
filters: [],
|
|
61
|
-
actions:
|
|
263
|
+
filters: [{ field: "lifecycle", label: "Stage", kind: "select", options: ["lead", "mql", "sql", "customer", "churned"] }],
|
|
264
|
+
actions: ACTOR_ACTIONS,
|
|
265
|
+
},
|
|
266
|
+
{
|
|
267
|
+
key: "companies", label: "Companies", dimension: "groups", type: "company", icon: "Building2",
|
|
268
|
+
columns: [
|
|
269
|
+
{ field: "name", label: "Company", kind: "text", required: true },
|
|
270
|
+
{ field: "industry", label: "Industry", kind: "text" },
|
|
271
|
+
{ field: "size", label: "Size", kind: "select", options: ["1-10", "11-50", "51-200", "201-1000", "1000+"] },
|
|
272
|
+
],
|
|
273
|
+
fields: [
|
|
274
|
+
{ field: "name", label: "Company", kind: "text", required: true },
|
|
275
|
+
{ field: "domain", label: "Domain", kind: "text" },
|
|
276
|
+
{ field: "industry", label: "Industry", kind: "text" },
|
|
277
|
+
{ field: "size", label: "Headcount", kind: "select", options: ["1-10", "11-50", "51-200", "201-1000", "1000+"] },
|
|
278
|
+
{ field: "tags", label: "Tags", kind: "tags" },
|
|
279
|
+
],
|
|
280
|
+
filters: [{ field: "size", label: "Size", kind: "select", options: ["1-10", "11-50", "51-200", "201-1000", "1000+"] }],
|
|
281
|
+
actions: GROUP_ACTIONS,
|
|
62
282
|
},
|
|
63
283
|
{
|
|
64
284
|
key: "deals", label: "Deals", dimension: "things", type: "deal", icon: "Handshake",
|
|
65
285
|
columns: [
|
|
66
286
|
{ field: "name", label: "Deal", kind: "text", required: true },
|
|
67
|
-
{ field: "
|
|
68
|
-
{ field: "
|
|
287
|
+
{ field: "value", label: "Value", kind: "currency" },
|
|
288
|
+
{ field: "stage", label: "Stage", kind: "select", options: ["prospect", "qualified", "proposal", "negotiation", "closed-won", "closed-lost"] },
|
|
69
289
|
],
|
|
70
290
|
fields: [
|
|
71
291
|
{ field: "name", label: "Deal", kind: "text", required: true },
|
|
72
|
-
{ field: "
|
|
73
|
-
{ field: "
|
|
292
|
+
{ field: "value", label: "Value", kind: "currency" },
|
|
293
|
+
{ field: "stage", label: "Stage", kind: "select", options: ["prospect", "qualified", "proposal", "negotiation", "closed-won", "closed-lost"] },
|
|
294
|
+
{ field: "close_date", label: "Close date", kind: "date" },
|
|
295
|
+
{ field: "probability", label: "Probability %", kind: "number" },
|
|
296
|
+
{ field: "contact", label: "Primary contact", kind: "relation", options: ["contacts"] },
|
|
297
|
+
{ field: "company", label: "Company", kind: "relation", options: ["companies"] },
|
|
74
298
|
],
|
|
75
|
-
filters: [{ field: "
|
|
76
|
-
actions:
|
|
299
|
+
filters: [{ field: "stage", label: "Stage", kind: "select", options: ["prospect", "qualified", "proposal", "negotiation", "closed-won", "closed-lost"] }],
|
|
300
|
+
actions: THING_ACTIONS,
|
|
77
301
|
},
|
|
78
302
|
{
|
|
79
|
-
key: "
|
|
303
|
+
key: "activities", label: "Activities", dimension: "events", type: "activity", icon: "CalendarClock",
|
|
80
304
|
columns: [
|
|
81
|
-
{ field: "name", label: "
|
|
82
|
-
{ field: "
|
|
305
|
+
{ field: "name", label: "Activity", kind: "text", required: true },
|
|
306
|
+
{ field: "kind", label: "Kind", kind: "select", options: ["call", "email", "meeting", "note", "task"] },
|
|
307
|
+
{ field: "date", label: "Date", kind: "date" },
|
|
308
|
+
],
|
|
309
|
+
fields: [
|
|
310
|
+
{ field: "name", label: "Activity", kind: "text", required: true },
|
|
311
|
+
{ field: "kind", label: "Kind", kind: "select", options: ["call", "email", "meeting", "note", "task"] },
|
|
312
|
+
{ field: "date", label: "Date", kind: "date" },
|
|
313
|
+
{ field: "notes", label: "Notes", kind: "markdown" },
|
|
314
|
+
{ field: "contact", label: "Contact", kind: "relation", options: ["contacts"] },
|
|
315
|
+
{ field: "deal", label: "Deal", kind: "relation", options: ["deals"] },
|
|
316
|
+
],
|
|
317
|
+
filters: [{ field: "kind", label: "Kind", kind: "select", options: ["call", "email", "meeting", "note", "task"] }],
|
|
318
|
+
actions: [],
|
|
319
|
+
},
|
|
320
|
+
{
|
|
321
|
+
key: "tasks", label: "Tasks", dimension: "things", type: "task", icon: "CheckSquare",
|
|
322
|
+
columns: [
|
|
323
|
+
{ field: "name", label: "Task", kind: "text", required: true },
|
|
324
|
+
{ field: "status", label: "Status", kind: "select", options: ["open", "done"] },
|
|
325
|
+
{ field: "due", label: "Due", kind: "date" },
|
|
326
|
+
],
|
|
327
|
+
fields: [
|
|
328
|
+
{ field: "name", label: "Task", kind: "text", required: true },
|
|
329
|
+
{ field: "status", label: "Status", kind: "select", options: ["open", "done"] },
|
|
330
|
+
{ field: "priority", label: "Priority", kind: "select", options: ["high", "medium", "low"] },
|
|
331
|
+
{ field: "due", label: "Due date", kind: "date" },
|
|
332
|
+
{ field: "deal", label: "Deal", kind: "relation", options: ["deals"] },
|
|
333
|
+
],
|
|
334
|
+
filters: [{ field: "status", label: "Status", kind: "select", options: ["open", "done"] }],
|
|
335
|
+
actions: THING_ACTIONS,
|
|
336
|
+
},
|
|
337
|
+
],
|
|
338
|
+
// ── sales — pipeline: lead → opportunity → quote → order, worked by reps ─────
|
|
339
|
+
sales: [
|
|
340
|
+
{
|
|
341
|
+
key: "leads", label: "Leads", dimension: "actors", type: "lead", icon: "Flame",
|
|
342
|
+
columns: [
|
|
343
|
+
{ field: "name", label: "Name", kind: "text", required: true },
|
|
344
|
+
{ field: "status", label: "Status", kind: "select", options: ["new", "contacted", "qualified", "unqualified"] },
|
|
345
|
+
{ field: "source", label: "Source", kind: "select", options: ["inbound", "outbound", "referral", "event", "ads"] },
|
|
346
|
+
],
|
|
347
|
+
fields: [
|
|
348
|
+
{ field: "name", label: "Name", kind: "text", required: true },
|
|
349
|
+
{ field: "email", label: "Email", kind: "text" },
|
|
350
|
+
{ field: "phone", label: "Phone", kind: "text" },
|
|
351
|
+
{ field: "status", label: "Status", kind: "select", options: ["new", "contacted", "qualified", "unqualified"] },
|
|
352
|
+
{ field: "source", label: "Source", kind: "select", options: ["inbound", "outbound", "referral", "event", "ads"] },
|
|
353
|
+
{ field: "owner", label: "Owner", kind: "relation", options: ["reps"] },
|
|
354
|
+
],
|
|
355
|
+
filters: [{ field: "status", label: "Status", kind: "select", options: ["new", "contacted", "qualified", "unqualified"] }],
|
|
356
|
+
actions: ACTOR_ACTIONS,
|
|
357
|
+
},
|
|
358
|
+
{
|
|
359
|
+
key: "opportunities", label: "Opportunities", dimension: "things", type: "opportunity", icon: "TrendingUp",
|
|
360
|
+
columns: [
|
|
361
|
+
{ field: "name", label: "Opportunity", kind: "text", required: true },
|
|
362
|
+
{ field: "value", label: "Value", kind: "currency" },
|
|
363
|
+
{ field: "stage", label: "Stage", kind: "select", options: ["prospecting", "qualification", "proposal", "negotiation", "closed-won", "closed-lost"] },
|
|
364
|
+
],
|
|
365
|
+
fields: [
|
|
366
|
+
{ field: "name", label: "Opportunity", kind: "text", required: true },
|
|
367
|
+
{ field: "value", label: "Value", kind: "currency" },
|
|
368
|
+
{ field: "stage", label: "Stage", kind: "select", options: ["prospecting", "qualification", "proposal", "negotiation", "closed-won", "closed-lost"] },
|
|
369
|
+
{ field: "close_date", label: "Expected close", kind: "date" },
|
|
370
|
+
{ field: "probability", label: "Probability %", kind: "number" },
|
|
371
|
+
{ field: "lead", label: "Lead", kind: "relation", options: ["leads"] },
|
|
372
|
+
{ field: "rep", label: "Owner", kind: "relation", options: ["reps"] },
|
|
373
|
+
],
|
|
374
|
+
filters: [{ field: "stage", label: "Stage", kind: "select", options: ["prospecting", "qualification", "proposal", "negotiation", "closed-won", "closed-lost"] }],
|
|
375
|
+
actions: THING_ACTIONS,
|
|
376
|
+
},
|
|
377
|
+
{
|
|
378
|
+
key: "quotes", label: "Quotes", dimension: "things", type: "quote", icon: "FileText",
|
|
379
|
+
columns: [
|
|
380
|
+
{ field: "name", label: "Quote", kind: "text", required: true },
|
|
381
|
+
{ field: "amount", label: "Amount", kind: "currency" },
|
|
382
|
+
{ field: "status", label: "Status", kind: "select", options: ["draft", "sent", "accepted", "expired"] },
|
|
383
|
+
],
|
|
384
|
+
fields: [
|
|
385
|
+
{ field: "name", label: "Quote", kind: "text", required: true },
|
|
386
|
+
{ field: "amount", label: "Amount", kind: "currency" },
|
|
387
|
+
{ field: "status", label: "Status", kind: "select", options: ["draft", "sent", "accepted", "expired"] },
|
|
388
|
+
{ field: "valid_until", label: "Valid until", kind: "date" },
|
|
389
|
+
{ field: "opportunity", label: "Opportunity", kind: "relation", options: ["opportunities"] },
|
|
390
|
+
],
|
|
391
|
+
filters: [{ field: "status", label: "Status", kind: "select", options: ["draft", "sent", "accepted", "expired"] }],
|
|
392
|
+
actions: THING_ACTIONS,
|
|
393
|
+
},
|
|
394
|
+
{
|
|
395
|
+
key: "orders", label: "Orders", dimension: "things", type: "order", icon: "ShoppingBag",
|
|
396
|
+
columns: [
|
|
397
|
+
{ field: "name", label: "Order #", kind: "text", required: true },
|
|
398
|
+
{ field: "total", label: "Total", kind: "currency" },
|
|
399
|
+
{ field: "status", label: "Status", kind: "select", options: ["pending", "paid", "fulfilled", "refunded"] },
|
|
400
|
+
],
|
|
401
|
+
fields: [
|
|
402
|
+
{ field: "name", label: "Order #", kind: "text", required: true },
|
|
403
|
+
{ field: "total", label: "Total", kind: "currency" },
|
|
404
|
+
{ field: "status", label: "Status", kind: "select", options: ["pending", "paid", "fulfilled", "refunded"] },
|
|
405
|
+
{ field: "ordered_at", label: "Ordered", kind: "date" },
|
|
406
|
+
{ field: "quote", label: "Quote", kind: "relation", options: ["quotes"] },
|
|
407
|
+
],
|
|
408
|
+
filters: [{ field: "status", label: "Status", kind: "select", options: ["pending", "paid", "fulfilled", "refunded"] }],
|
|
409
|
+
actions: THING_ACTIONS,
|
|
410
|
+
},
|
|
411
|
+
{
|
|
412
|
+
key: "reps", label: "Reps", dimension: "actors", type: "rep", icon: "UserRound",
|
|
413
|
+
columns: [
|
|
414
|
+
{ field: "name", label: "Name", kind: "text", required: true },
|
|
415
|
+
{ field: "region", label: "Region", kind: "text" },
|
|
416
|
+
{ field: "quota", label: "Quota", kind: "currency" },
|
|
83
417
|
],
|
|
84
418
|
fields: [
|
|
85
419
|
{ field: "name", label: "Name", kind: "text", required: true },
|
|
420
|
+
{ field: "region", label: "Region", kind: "text" },
|
|
421
|
+
{ field: "quota", label: "Quota", kind: "currency" },
|
|
86
422
|
{ field: "tags", label: "Tags", kind: "tags" },
|
|
87
423
|
],
|
|
88
424
|
filters: [],
|
|
89
|
-
actions:
|
|
425
|
+
actions: ACTOR_ACTIONS,
|
|
426
|
+
},
|
|
427
|
+
],
|
|
428
|
+
// ── marketing — campaigns → audiences → content → leads, with experiments ───
|
|
429
|
+
marketing: [
|
|
430
|
+
{
|
|
431
|
+
key: "campaigns", label: "Campaigns", dimension: "groups", type: "campaign", icon: "Megaphone",
|
|
432
|
+
columns: [
|
|
433
|
+
{ field: "name", label: "Campaign", kind: "text", required: true },
|
|
434
|
+
{ field: "status", label: "Status", kind: "select", options: ["draft", "scheduled", "running", "paused", "shipped", "killed"] },
|
|
435
|
+
{ field: "budget", label: "Budget", kind: "currency" },
|
|
436
|
+
],
|
|
437
|
+
fields: [
|
|
438
|
+
{ field: "name", label: "Campaign", kind: "text", required: true },
|
|
439
|
+
{ field: "status", label: "Status", kind: "select", options: ["draft", "scheduled", "running", "paused", "shipped", "killed"] },
|
|
440
|
+
{ field: "budget", label: "Budget", kind: "currency" },
|
|
441
|
+
{ field: "spend", label: "Spend", kind: "currency" },
|
|
442
|
+
{ field: "north_star", label: "North-star KPI", kind: "text" },
|
|
443
|
+
{ field: "start", label: "Start", kind: "date" },
|
|
444
|
+
{ field: "end", label: "End", kind: "date" },
|
|
445
|
+
{ field: "audience", label: "Audience", kind: "relation", options: ["audiences"] },
|
|
446
|
+
{ field: "channel", label: "Channel", kind: "relation", options: ["channels"] },
|
|
447
|
+
],
|
|
448
|
+
filters: [{ field: "status", label: "Status", kind: "select", options: ["draft", "scheduled", "running", "paused", "shipped", "killed"] }],
|
|
449
|
+
actions: GROUP_ACTIONS,
|
|
450
|
+
},
|
|
451
|
+
{
|
|
452
|
+
key: "audiences", label: "Audiences", dimension: "groups", type: "audience", icon: "Target",
|
|
453
|
+
columns: [
|
|
454
|
+
{ field: "name", label: "Audience", kind: "text", required: true },
|
|
455
|
+
{ field: "stage", label: "Stage", kind: "select", options: ["awareness", "consideration", "decision", "retention", "advocacy"] },
|
|
456
|
+
{ field: "size", label: "Size", kind: "number" },
|
|
457
|
+
],
|
|
458
|
+
fields: [
|
|
459
|
+
{ field: "name", label: "Audience", kind: "text", required: true },
|
|
460
|
+
{ field: "stage", label: "Lifecycle stage", kind: "select", options: ["awareness", "consideration", "decision", "retention", "advocacy"] },
|
|
461
|
+
{ field: "size", label: "Estimated size", kind: "number" },
|
|
462
|
+
{ field: "geo", label: "Geo", kind: "text" },
|
|
463
|
+
{ field: "tags", label: "Tags", kind: "tags" },
|
|
464
|
+
],
|
|
465
|
+
filters: [{ field: "stage", label: "Stage", kind: "select", options: ["awareness", "consideration", "decision", "retention", "advocacy"] }],
|
|
466
|
+
actions: GROUP_ACTIONS,
|
|
467
|
+
},
|
|
468
|
+
{
|
|
469
|
+
key: "offers", label: "Offers", dimension: "things", type: "offer", icon: "Gift",
|
|
470
|
+
columns: [
|
|
471
|
+
{ field: "name", label: "Offer", kind: "text", required: true },
|
|
472
|
+
{ field: "price", label: "Price", kind: "currency" },
|
|
473
|
+
{ field: "guarantee", label: "Guarantee", kind: "select", options: ["money-back", "better-than", "service", "conditional", "reverse"] },
|
|
474
|
+
],
|
|
475
|
+
fields: [
|
|
476
|
+
{ field: "name", label: "Offer", kind: "text", required: true },
|
|
477
|
+
{ field: "dream_outcome", label: "Dream outcome", kind: "text" },
|
|
478
|
+
{ field: "price", label: "Price", kind: "currency" },
|
|
479
|
+
{ field: "guarantee", label: "Guarantee", kind: "select", options: ["money-back", "better-than", "service", "conditional", "reverse"] },
|
|
480
|
+
{ field: "value_score", label: "Value score", kind: "number" },
|
|
481
|
+
{ field: "tags", label: "Tags", kind: "tags" },
|
|
482
|
+
],
|
|
483
|
+
filters: [{ field: "guarantee", label: "Guarantee", kind: "select", options: ["money-back", "better-than", "service", "conditional", "reverse"] }],
|
|
484
|
+
actions: THING_ACTIONS,
|
|
485
|
+
},
|
|
486
|
+
{
|
|
487
|
+
key: "content", label: "Content", dimension: "things", type: "content", icon: "FileText",
|
|
488
|
+
columns: [
|
|
489
|
+
{ field: "name", label: "Title", kind: "text", required: true },
|
|
490
|
+
{ field: "state", label: "State", kind: "select", options: ["draft", "review", "approved", "scheduled", "published", "live", "archived"] },
|
|
491
|
+
{ field: "variant", label: "Variant", kind: "select", options: ["a", "b", "c"] },
|
|
492
|
+
],
|
|
493
|
+
fields: [
|
|
494
|
+
{ field: "name", label: "Title", kind: "text", required: true },
|
|
495
|
+
{ field: "headline", label: "Headline", kind: "text" },
|
|
496
|
+
{ field: "cta", label: "Call to action", kind: "text" },
|
|
497
|
+
{ field: "image", label: "Creative", kind: "image" },
|
|
498
|
+
{ field: "state", label: "Workflow state", kind: "select", options: ["draft", "review", "approved", "scheduled", "published", "live", "archived"] },
|
|
499
|
+
{ field: "variant", label: "Variant", kind: "select", options: ["a", "b", "c"] },
|
|
500
|
+
{ field: "publish_at", label: "Publish at", kind: "date" },
|
|
501
|
+
{ field: "campaign", label: "Campaign", kind: "relation", options: ["campaigns"] },
|
|
502
|
+
{ field: "offer", label: "Offer", kind: "relation", options: ["offers"] },
|
|
503
|
+
],
|
|
504
|
+
filters: [{ field: "state", label: "State", kind: "select", options: ["draft", "review", "approved", "scheduled", "published", "live", "archived"] }],
|
|
505
|
+
actions: THING_ACTIONS,
|
|
506
|
+
},
|
|
507
|
+
{
|
|
508
|
+
key: "leads", label: "Leads", dimension: "actors", type: "lead", icon: "UserPlus",
|
|
509
|
+
columns: [
|
|
510
|
+
{ field: "name", label: "Name", kind: "text", required: true },
|
|
511
|
+
{ field: "lifecycle", label: "Lifecycle", kind: "select", options: ["anonymous", "lead", "mql", "sql", "customer", "advocate", "churned"] },
|
|
512
|
+
{ field: "ltv", label: "LTV", kind: "currency" },
|
|
513
|
+
],
|
|
514
|
+
fields: [
|
|
515
|
+
{ field: "name", label: "Name", kind: "text", required: true },
|
|
516
|
+
{ field: "lifecycle", label: "Lifecycle", kind: "select", options: ["anonymous", "lead", "mql", "sql", "customer", "advocate", "churned"] },
|
|
517
|
+
{ field: "ltv", label: "Lifetime value", kind: "currency" },
|
|
518
|
+
{ field: "cac", label: "Acquisition cost", kind: "currency" },
|
|
519
|
+
{ field: "fit_score", label: "Fit score", kind: "number" },
|
|
520
|
+
{ field: "consent", label: "Consent", kind: "tags" },
|
|
521
|
+
{ field: "audience", label: "Audience", kind: "relation", options: ["audiences"] },
|
|
522
|
+
],
|
|
523
|
+
filters: [{ field: "lifecycle", label: "Lifecycle", kind: "select", options: ["anonymous", "lead", "mql", "sql", "customer", "advocate", "churned"] }],
|
|
524
|
+
actions: ACTOR_ACTIONS,
|
|
525
|
+
},
|
|
526
|
+
{
|
|
527
|
+
key: "channels", label: "Channels", dimension: "groups", type: "channel", icon: "Radio",
|
|
528
|
+
columns: [
|
|
529
|
+
{ field: "name", label: "Channel", kind: "text", required: true },
|
|
530
|
+
{ field: "kind", label: "Kind", kind: "select", options: ["email", "meta", "google-ads", "tiktok", "seo", "sms"] },
|
|
531
|
+
{ field: "roas", label: "ROAS", kind: "number" },
|
|
532
|
+
],
|
|
533
|
+
fields: [
|
|
534
|
+
{ field: "name", label: "Channel", kind: "text", required: true },
|
|
535
|
+
{ field: "kind", label: "Kind", kind: "select", options: ["email", "meta", "google-ads", "tiktok", "seo", "sms"] },
|
|
536
|
+
{ field: "spend", label: "Spend", kind: "currency" },
|
|
537
|
+
{ field: "roas", label: "ROAS", kind: "number" },
|
|
538
|
+
],
|
|
539
|
+
filters: [{ field: "kind", label: "Kind", kind: "select", options: ["email", "meta", "google-ads", "tiktok", "seo", "sms"] }],
|
|
540
|
+
actions: GROUP_ACTIONS,
|
|
541
|
+
},
|
|
542
|
+
{
|
|
543
|
+
key: "experiments", label: "Experiments", dimension: "learning", type: "experiment", icon: "FlaskConical",
|
|
544
|
+
columns: [
|
|
545
|
+
{ field: "name", label: "Hypothesis", kind: "text", required: true },
|
|
546
|
+
{ field: "status", label: "Status", kind: "select", options: ["backlog", "running", "shipped", "killed", "inconclusive"] },
|
|
547
|
+
{ field: "metric", label: "Metric", kind: "select", options: ["ctr", "cvr", "aov", "ltv", "cac", "roas", "open-rate"] },
|
|
548
|
+
],
|
|
549
|
+
fields: [
|
|
550
|
+
{ field: "name", label: "Hypothesis", kind: "text", required: true },
|
|
551
|
+
{ field: "metric", label: "Target metric", kind: "select", options: ["ctr", "cvr", "aov", "ltv", "cac", "roas", "open-rate"] },
|
|
552
|
+
{ field: "status", label: "Status", kind: "select", options: ["backlog", "running", "shipped", "killed", "inconclusive"] },
|
|
553
|
+
{ field: "ice_score", label: "ICE score", kind: "number" },
|
|
554
|
+
{ field: "observed_lift", label: "Observed lift", kind: "number" },
|
|
555
|
+
{ field: "p_value", label: "p-value", kind: "number" },
|
|
556
|
+
{ field: "campaign", label: "Campaign", kind: "relation", options: ["campaigns"] },
|
|
557
|
+
],
|
|
558
|
+
filters: [{ field: "status", label: "Status", kind: "select", options: ["backlog", "running", "shipped", "killed", "inconclusive"] }],
|
|
559
|
+
actions: ["world:create-hypothesis"],
|
|
90
560
|
},
|
|
91
561
|
],
|
|
92
|
-
|
|
562
|
+
// ── service — support desk: tickets worked by agents for customers ──────────
|
|
563
|
+
service: [
|
|
564
|
+
{
|
|
565
|
+
key: "tickets", label: "Tickets", dimension: "things", type: "ticket", icon: "Ticket",
|
|
566
|
+
columns: [
|
|
567
|
+
{ field: "name", label: "Subject", kind: "text", required: true },
|
|
568
|
+
{ field: "priority", label: "Priority", kind: "select", options: ["urgent", "high", "normal", "low"] },
|
|
569
|
+
{ field: "status", label: "Status", kind: "select", options: ["open", "pending", "on-hold", "solved", "closed"] },
|
|
570
|
+
],
|
|
571
|
+
fields: [
|
|
572
|
+
{ field: "name", label: "Subject", kind: "text", required: true },
|
|
573
|
+
{ field: "description", label: "Description", kind: "markdown" },
|
|
574
|
+
{ field: "priority", label: "Priority", kind: "select", options: ["urgent", "high", "normal", "low"] },
|
|
575
|
+
{ field: "status", label: "Status", kind: "select", options: ["open", "pending", "on-hold", "solved", "closed"] },
|
|
576
|
+
{ field: "channel", label: "Channel", kind: "select", options: ["email", "chat", "phone", "web", "social"] },
|
|
577
|
+
{ field: "customer", label: "Customer", kind: "relation", options: ["customers"] },
|
|
578
|
+
{ field: "agent", label: "Assigned agent", kind: "relation", options: ["agents"] },
|
|
579
|
+
],
|
|
580
|
+
filters: [
|
|
581
|
+
{ field: "priority", label: "Priority", kind: "select", options: ["urgent", "high", "normal", "low"] },
|
|
582
|
+
{ field: "status", label: "Status", kind: "select", options: ["open", "pending", "on-hold", "solved", "closed"] },
|
|
583
|
+
],
|
|
584
|
+
actions: THING_ACTIONS,
|
|
585
|
+
},
|
|
93
586
|
{
|
|
94
|
-
key: "
|
|
587
|
+
key: "customers", label: "Customers", dimension: "actors", type: "customer", icon: "UserRound",
|
|
95
588
|
columns: [
|
|
589
|
+
{ field: "name", label: "Name", kind: "text", required: true },
|
|
590
|
+
{ field: "tier", label: "Tier", kind: "select", options: ["free", "pro", "enterprise"] },
|
|
591
|
+
{ field: "email", label: "Email", kind: "text" },
|
|
592
|
+
],
|
|
593
|
+
fields: [
|
|
594
|
+
{ field: "name", label: "Name", kind: "text", required: true },
|
|
595
|
+
{ field: "email", label: "Email", kind: "text" },
|
|
596
|
+
{ field: "tier", label: "Plan tier", kind: "select", options: ["free", "pro", "enterprise"] },
|
|
597
|
+
{ field: "tags", label: "Tags", kind: "tags" },
|
|
598
|
+
],
|
|
599
|
+
filters: [{ field: "tier", label: "Tier", kind: "select", options: ["free", "pro", "enterprise"] }],
|
|
600
|
+
actions: ACTOR_ACTIONS,
|
|
601
|
+
},
|
|
602
|
+
{
|
|
603
|
+
key: "agents", label: "Agents", dimension: "actors", type: "support-agent", icon: "Headset",
|
|
604
|
+
columns: [
|
|
605
|
+
{ field: "name", label: "Name", kind: "text", required: true },
|
|
606
|
+
{ field: "team", label: "Team", kind: "text" },
|
|
607
|
+
{ field: "status", label: "Status", kind: "select", options: ["online", "away", "offline"] },
|
|
608
|
+
],
|
|
609
|
+
fields: [
|
|
610
|
+
{ field: "name", label: "Name", kind: "text", required: true },
|
|
611
|
+
{ field: "team", label: "Team", kind: "text" },
|
|
612
|
+
{ field: "status", label: "Status", kind: "select", options: ["online", "away", "offline"] },
|
|
613
|
+
{ field: "tags", label: "Skills", kind: "tags" },
|
|
614
|
+
],
|
|
615
|
+
filters: [{ field: "status", label: "Status", kind: "select", options: ["online", "away", "offline"] }],
|
|
616
|
+
actions: ACTOR_ACTIONS,
|
|
617
|
+
},
|
|
618
|
+
{
|
|
619
|
+
key: "messages", label: "Messages", dimension: "events", type: "message", icon: "MessageSquare",
|
|
620
|
+
columns: [
|
|
621
|
+
{ field: "name", label: "Message", kind: "text", required: true },
|
|
622
|
+
{ field: "direction", label: "Direction", kind: "select", options: ["inbound", "outbound"] },
|
|
623
|
+
{ field: "date", label: "Date", kind: "date" },
|
|
624
|
+
],
|
|
625
|
+
fields: [
|
|
626
|
+
{ field: "name", label: "Message", kind: "text", required: true },
|
|
627
|
+
{ field: "body", label: "Body", kind: "markdown" },
|
|
628
|
+
{ field: "direction", label: "Direction", kind: "select", options: ["inbound", "outbound"] },
|
|
629
|
+
{ field: "date", label: "Date", kind: "date" },
|
|
630
|
+
{ field: "ticket", label: "Ticket", kind: "relation", options: ["tickets"] },
|
|
631
|
+
],
|
|
632
|
+
filters: [{ field: "direction", label: "Direction", kind: "select", options: ["inbound", "outbound"] }],
|
|
633
|
+
actions: [],
|
|
634
|
+
},
|
|
635
|
+
{
|
|
636
|
+
key: "articles", label: "Help articles", dimension: "things", type: "article", icon: "BookOpen",
|
|
637
|
+
columns: [
|
|
638
|
+
{ field: "name", label: "Title", kind: "text", required: true },
|
|
639
|
+
{ field: "category", label: "Category", kind: "text" },
|
|
640
|
+
{ field: "status", label: "Status", kind: "select", options: ["draft", "published", "archived"] },
|
|
641
|
+
],
|
|
642
|
+
fields: [
|
|
96
643
|
{ field: "name", label: "Title", kind: "text", required: true },
|
|
644
|
+
{ field: "category", label: "Category", kind: "text" },
|
|
645
|
+
{ field: "body", label: "Body", kind: "markdown" },
|
|
646
|
+
{ field: "status", label: "Status", kind: "select", options: ["draft", "published", "archived"] },
|
|
97
647
|
{ field: "tags", label: "Tags", kind: "tags" },
|
|
98
648
|
],
|
|
649
|
+
filters: [{ field: "status", label: "Status", kind: "select", options: ["draft", "published", "archived"] }],
|
|
650
|
+
actions: THING_ACTIONS,
|
|
651
|
+
},
|
|
652
|
+
],
|
|
653
|
+
// ── education — courses, learners, lessons, mastery, attempts, certificates ──
|
|
654
|
+
education: [
|
|
655
|
+
{
|
|
656
|
+
key: "courses", label: "Courses", dimension: "groups", type: "course", icon: "BookOpen",
|
|
657
|
+
columns: [
|
|
658
|
+
{ field: "name", label: "Title", kind: "text", required: true },
|
|
659
|
+
{ field: "level", label: "Level", kind: "select", options: ["beginner", "intermediate", "advanced"] },
|
|
660
|
+
{ field: "status", label: "Status", kind: "select", options: ["draft", "published", "archived"] },
|
|
661
|
+
],
|
|
99
662
|
fields: [
|
|
100
663
|
{ field: "name", label: "Title", kind: "text", required: true },
|
|
101
664
|
{ field: "description", label: "Description", kind: "markdown" },
|
|
102
665
|
{ field: "image", label: "Cover", kind: "image" },
|
|
666
|
+
{ field: "level", label: "Level", kind: "select", options: ["beginner", "intermediate", "advanced"] },
|
|
667
|
+
{ field: "status", label: "Status", kind: "select", options: ["draft", "published", "archived"] },
|
|
103
668
|
{ field: "tags", label: "Tags", kind: "tags" },
|
|
104
669
|
],
|
|
105
|
-
filters: [{ field: "
|
|
106
|
-
actions:
|
|
670
|
+
filters: [{ field: "level", label: "Level", kind: "select", options: ["beginner", "intermediate", "advanced"] }],
|
|
671
|
+
actions: GROUP_ACTIONS,
|
|
672
|
+
},
|
|
673
|
+
{
|
|
674
|
+
key: "learners", label: "Learners", dimension: "actors", type: "learner", icon: "GraduationCap",
|
|
675
|
+
columns: [
|
|
676
|
+
{ field: "name", label: "Name", kind: "text", required: true },
|
|
677
|
+
{ field: "status", label: "Status", kind: "select", options: ["active", "paused", "completed"] },
|
|
678
|
+
{ field: "email", label: "Email", kind: "text" },
|
|
679
|
+
],
|
|
680
|
+
fields: [
|
|
681
|
+
{ field: "name", label: "Name", kind: "text", required: true },
|
|
682
|
+
{ field: "email", label: "Email", kind: "text" },
|
|
683
|
+
{ field: "status", label: "Status", kind: "select", options: ["active", "paused", "completed"] },
|
|
684
|
+
{ field: "tags", label: "Tags", kind: "tags" },
|
|
685
|
+
],
|
|
686
|
+
filters: [{ field: "status", label: "Status", kind: "select", options: ["active", "paused", "completed"] }],
|
|
687
|
+
actions: ACTOR_ACTIONS,
|
|
688
|
+
},
|
|
689
|
+
{
|
|
690
|
+
key: "lessons", label: "Lessons", dimension: "things", type: "lesson", icon: "PlayCircle",
|
|
691
|
+
columns: [
|
|
692
|
+
{ field: "name", label: "Lesson", kind: "text", required: true },
|
|
693
|
+
{ field: "kind", label: "Kind", kind: "select", options: ["reading", "video", "quiz", "interactive", "problem"] },
|
|
694
|
+
{ field: "order", label: "Order", kind: "number" },
|
|
695
|
+
],
|
|
696
|
+
fields: [
|
|
697
|
+
{ field: "name", label: "Lesson", kind: "text", required: true },
|
|
698
|
+
{ field: "kind", label: "Kind", kind: "select", options: ["reading", "video", "quiz", "interactive", "problem"] },
|
|
699
|
+
{ field: "order", label: "Order", kind: "number" },
|
|
700
|
+
{ field: "duration", label: "Duration (min)", kind: "number" },
|
|
701
|
+
{ field: "course", label: "Course", kind: "relation", options: ["courses"] },
|
|
702
|
+
{ field: "skill", label: "Teaches skill", kind: "relation", options: ["skills"] },
|
|
703
|
+
],
|
|
704
|
+
filters: [{ field: "kind", label: "Kind", kind: "select", options: ["reading", "video", "quiz", "interactive", "problem"] }],
|
|
705
|
+
actions: THING_ACTIONS,
|
|
706
|
+
},
|
|
707
|
+
{
|
|
708
|
+
key: "skills", label: "Skills", dimension: "things", type: "skill", icon: "Award",
|
|
709
|
+
columns: [
|
|
710
|
+
{ field: "name", label: "Skill", kind: "text", required: true },
|
|
711
|
+
{ field: "domain", label: "Domain", kind: "tags" },
|
|
712
|
+
],
|
|
713
|
+
fields: [
|
|
714
|
+
{ field: "name", label: "Skill", kind: "text", required: true },
|
|
715
|
+
{ field: "description", label: "Description", kind: "markdown" },
|
|
716
|
+
{ field: "domain", label: "Domain", kind: "tags" },
|
|
717
|
+
],
|
|
718
|
+
filters: [{ field: "domain", label: "Domain", kind: "tags" }],
|
|
719
|
+
actions: THING_ACTIONS,
|
|
107
720
|
},
|
|
108
721
|
{
|
|
109
722
|
key: "enrollments", label: "Enrollments", dimension: "paths", type: "enrollment", icon: "UserCheck",
|
|
110
723
|
columns: [
|
|
111
724
|
{ field: "name", label: "Enrollment", kind: "text", required: true },
|
|
112
|
-
{ field: "
|
|
725
|
+
{ field: "status", label: "Status", kind: "select", options: ["active", "completed", "paused", "dropped"] },
|
|
726
|
+
{ field: "progress", label: "Progress", kind: "number" },
|
|
113
727
|
],
|
|
114
728
|
fields: [
|
|
115
729
|
{ field: "name", label: "Enrollment", kind: "text", required: true },
|
|
116
|
-
{ field: "
|
|
730
|
+
{ field: "status", label: "Status", kind: "select", options: ["active", "completed", "paused", "dropped"] },
|
|
731
|
+
{ field: "progress", label: "Progress %", kind: "number" },
|
|
732
|
+
{ field: "enrolled_at", label: "Enrolled", kind: "date" },
|
|
733
|
+
{ field: "learner", label: "Learner", kind: "relation", options: ["learners"] },
|
|
734
|
+
{ field: "course", label: "Course", kind: "relation", options: ["courses"] },
|
|
735
|
+
],
|
|
736
|
+
filters: [{ field: "status", label: "Status", kind: "select", options: ["active", "completed", "paused", "dropped"] }],
|
|
737
|
+
actions: [],
|
|
738
|
+
},
|
|
739
|
+
{
|
|
740
|
+
key: "attempts", label: "Attempts", dimension: "events", type: "attempt", icon: "ClipboardCheck",
|
|
741
|
+
columns: [
|
|
742
|
+
{ field: "name", label: "Attempt", kind: "text", required: true },
|
|
743
|
+
{ field: "verb", label: "Verb", kind: "select", options: ["started", "submitted", "completed", "scored"] },
|
|
744
|
+
{ field: "score", label: "Score", kind: "number" },
|
|
745
|
+
],
|
|
746
|
+
fields: [
|
|
747
|
+
{ field: "name", label: "Attempt", kind: "text", required: true },
|
|
748
|
+
{ field: "verb", label: "Verb", kind: "select", options: ["started", "submitted", "completed", "scored"] },
|
|
749
|
+
{ field: "correct", label: "Correct", kind: "select", options: ["yes", "no"] },
|
|
750
|
+
{ field: "score", label: "Score", kind: "number" },
|
|
751
|
+
{ field: "elapsed_ms", label: "Elapsed (ms)", kind: "number" },
|
|
752
|
+
{ field: "learner", label: "Learner", kind: "relation", options: ["learners"] },
|
|
753
|
+
{ field: "lesson", label: "Lesson", kind: "relation", options: ["lessons"] },
|
|
754
|
+
],
|
|
755
|
+
filters: [{ field: "verb", label: "Verb", kind: "select", options: ["started", "submitted", "completed", "scored"] }],
|
|
756
|
+
actions: [],
|
|
757
|
+
},
|
|
758
|
+
{
|
|
759
|
+
key: "certificates", label: "Certificates", dimension: "things", type: "certificate", icon: "Medal",
|
|
760
|
+
columns: [
|
|
761
|
+
{ field: "name", label: "Certificate", kind: "text", required: true },
|
|
762
|
+
{ field: "issued_at", label: "Issued", kind: "date" },
|
|
763
|
+
],
|
|
764
|
+
fields: [
|
|
765
|
+
{ field: "name", label: "Certificate", kind: "text", required: true },
|
|
766
|
+
{ field: "issued_at", label: "Issued", kind: "date" },
|
|
767
|
+
{ field: "tags", label: "Tags", kind: "tags" },
|
|
768
|
+
{ field: "learner", label: "Learner", kind: "relation", options: ["learners"] },
|
|
769
|
+
{ field: "course", label: "Course", kind: "relation", options: ["courses"] },
|
|
770
|
+
],
|
|
771
|
+
filters: [],
|
|
772
|
+
actions: THING_ACTIONS,
|
|
773
|
+
},
|
|
774
|
+
],
|
|
775
|
+
// ── staff — people ops: employees in departments, roles, shifts, time-off ───
|
|
776
|
+
staff: [
|
|
777
|
+
{
|
|
778
|
+
key: "employees", label: "Employees", dimension: "actors", type: "employee", icon: "Users",
|
|
779
|
+
columns: [
|
|
780
|
+
{ field: "name", label: "Name", kind: "text", required: true },
|
|
781
|
+
{ field: "title", label: "Title", kind: "text" },
|
|
782
|
+
{ field: "status", label: "Status", kind: "select", options: ["active", "on-leave", "offboarded"] },
|
|
783
|
+
],
|
|
784
|
+
fields: [
|
|
785
|
+
{ field: "name", label: "Name", kind: "text", required: true },
|
|
786
|
+
{ field: "email", label: "Email", kind: "text" },
|
|
787
|
+
{ field: "title", label: "Title", kind: "text" },
|
|
788
|
+
{ field: "status", label: "Status", kind: "select", options: ["active", "on-leave", "offboarded"] },
|
|
789
|
+
{ field: "start_date", label: "Start date", kind: "date" },
|
|
790
|
+
{ field: "department", label: "Department", kind: "relation", options: ["departments"] },
|
|
791
|
+
{ field: "role", label: "Role", kind: "relation", options: ["roles"] },
|
|
792
|
+
{ field: "manager", label: "Manager", kind: "relation", options: ["employees"] },
|
|
793
|
+
],
|
|
794
|
+
filters: [{ field: "status", label: "Status", kind: "select", options: ["active", "on-leave", "offboarded"] }],
|
|
795
|
+
actions: ACTOR_ACTIONS,
|
|
796
|
+
},
|
|
797
|
+
{
|
|
798
|
+
key: "departments", label: "Departments", dimension: "groups", type: "department", icon: "Building2",
|
|
799
|
+
columns: [
|
|
800
|
+
{ field: "name", label: "Department", kind: "text", required: true },
|
|
801
|
+
{ field: "function", label: "Function", kind: "select", options: ["sales", "marketing", "service", "education", "engineering", "ops", "finance"] },
|
|
802
|
+
],
|
|
803
|
+
fields: [
|
|
804
|
+
{ field: "name", label: "Department", kind: "text", required: true },
|
|
805
|
+
{ field: "function", label: "Function", kind: "select", options: ["sales", "marketing", "service", "education", "engineering", "ops", "finance"] },
|
|
806
|
+
{ field: "head", label: "Department head", kind: "relation", options: ["employees"] },
|
|
807
|
+
],
|
|
808
|
+
filters: [{ field: "function", label: "Function", kind: "select", options: ["sales", "marketing", "service", "education", "engineering", "ops", "finance"] }],
|
|
809
|
+
actions: GROUP_ACTIONS,
|
|
810
|
+
},
|
|
811
|
+
{
|
|
812
|
+
key: "roles", label: "Roles", dimension: "things", type: "role", icon: "BadgeCheck",
|
|
813
|
+
columns: [
|
|
814
|
+
{ field: "name", label: "Role", kind: "text", required: true },
|
|
815
|
+
{ field: "level", label: "Level", kind: "select", options: ["junior", "mid", "senior", "lead", "head"] },
|
|
816
|
+
],
|
|
817
|
+
fields: [
|
|
818
|
+
{ field: "name", label: "Role", kind: "text", required: true },
|
|
819
|
+
{ field: "level", label: "Level", kind: "select", options: ["junior", "mid", "senior", "lead", "head"] },
|
|
820
|
+
{ field: "description", label: "Description", kind: "markdown" },
|
|
821
|
+
],
|
|
822
|
+
filters: [{ field: "level", label: "Level", kind: "select", options: ["junior", "mid", "senior", "lead", "head"] }],
|
|
823
|
+
actions: THING_ACTIONS,
|
|
824
|
+
},
|
|
825
|
+
{
|
|
826
|
+
key: "shifts", label: "Shifts", dimension: "events", type: "shift", icon: "CalendarClock",
|
|
827
|
+
columns: [
|
|
828
|
+
{ field: "name", label: "Shift", kind: "text", required: true },
|
|
829
|
+
{ field: "date", label: "Date", kind: "date" },
|
|
830
|
+
{ field: "hours", label: "Hours", kind: "number" },
|
|
831
|
+
],
|
|
832
|
+
fields: [
|
|
833
|
+
{ field: "name", label: "Shift", kind: "text", required: true },
|
|
834
|
+
{ field: "date", label: "Date", kind: "date" },
|
|
835
|
+
{ field: "start", label: "Start time", kind: "text" },
|
|
836
|
+
{ field: "end", label: "End time", kind: "text" },
|
|
837
|
+
{ field: "hours", label: "Hours", kind: "number" },
|
|
838
|
+
{ field: "employee", label: "Employee", kind: "relation", options: ["employees"] },
|
|
117
839
|
],
|
|
118
840
|
filters: [],
|
|
119
841
|
actions: [],
|
|
120
842
|
},
|
|
843
|
+
{
|
|
844
|
+
key: "timeoff", label: "Time off", dimension: "events", type: "time-off", icon: "Plane",
|
|
845
|
+
columns: [
|
|
846
|
+
{ field: "name", label: "Request", kind: "text", required: true },
|
|
847
|
+
{ field: "kind", label: "Kind", kind: "select", options: ["vacation", "sick", "personal", "unpaid"] },
|
|
848
|
+
{ field: "status", label: "Status", kind: "select", options: ["pending", "approved", "rejected"] },
|
|
849
|
+
],
|
|
850
|
+
fields: [
|
|
851
|
+
{ field: "name", label: "Request", kind: "text", required: true },
|
|
852
|
+
{ field: "kind", label: "Kind", kind: "select", options: ["vacation", "sick", "personal", "unpaid"] },
|
|
853
|
+
{ field: "start", label: "From", kind: "date" },
|
|
854
|
+
{ field: "end", label: "To", kind: "date" },
|
|
855
|
+
{ field: "status", label: "Status", kind: "select", options: ["pending", "approved", "rejected"] },
|
|
856
|
+
{ field: "employee", label: "Employee", kind: "relation", options: ["employees"] },
|
|
857
|
+
],
|
|
858
|
+
filters: [{ field: "status", label: "Status", kind: "select", options: ["pending", "approved", "rejected"] }],
|
|
859
|
+
actions: [],
|
|
860
|
+
},
|
|
861
|
+
{
|
|
862
|
+
key: "reviews", label: "Reviews", dimension: "things", type: "review", icon: "Star",
|
|
863
|
+
columns: [
|
|
864
|
+
{ field: "name", label: "Review", kind: "text", required: true },
|
|
865
|
+
{ field: "period", label: "Period", kind: "text" },
|
|
866
|
+
{ field: "rating", label: "Rating", kind: "number" },
|
|
867
|
+
],
|
|
868
|
+
fields: [
|
|
869
|
+
{ field: "name", label: "Review", kind: "text", required: true },
|
|
870
|
+
{ field: "period", label: "Period", kind: "text" },
|
|
871
|
+
{ field: "rating", label: "Rating (1-5)", kind: "number" },
|
|
872
|
+
{ field: "notes", label: "Notes", kind: "markdown" },
|
|
873
|
+
{ field: "employee", label: "Employee", kind: "relation", options: ["employees"] },
|
|
874
|
+
],
|
|
875
|
+
filters: [],
|
|
876
|
+
actions: THING_ACTIONS,
|
|
877
|
+
},
|
|
878
|
+
],
|
|
879
|
+
// ── ecommerce — RELATION-FREE by contract (schema-canvas.test.ts) ───────────
|
|
880
|
+
ecommerce: [
|
|
881
|
+
{
|
|
882
|
+
key: "products", label: "Products", dimension: "things", type: "product", icon: "Package",
|
|
883
|
+
columns: [
|
|
884
|
+
{ field: "name", label: "Name", kind: "text", required: true },
|
|
885
|
+
{ field: "price", label: "Price", kind: "currency" },
|
|
886
|
+
{ field: "tags", label: "Tags", kind: "tags" },
|
|
887
|
+
],
|
|
888
|
+
fields: [
|
|
889
|
+
{ field: "name", label: "Name", kind: "text", required: true },
|
|
890
|
+
{ field: "price", label: "Price", kind: "currency" },
|
|
891
|
+
{ field: "description", label: "Description", kind: "markdown" },
|
|
892
|
+
{ field: "image", label: "Image", kind: "image" },
|
|
893
|
+
{ field: "tags", label: "Tags", kind: "tags" },
|
|
894
|
+
],
|
|
895
|
+
filters: [{ field: "tags", label: "Tags", kind: "tags" }],
|
|
896
|
+
actions: ["world:create-thing", "world:update-thing", "world:remove-thing"],
|
|
897
|
+
},
|
|
898
|
+
{
|
|
899
|
+
key: "orders", label: "Orders", dimension: "things", type: "order", icon: "ShoppingCart",
|
|
900
|
+
columns: [
|
|
901
|
+
{ field: "name", label: "Order #", kind: "text", required: true },
|
|
902
|
+
{ field: "price", label: "Total", kind: "currency" },
|
|
903
|
+
{ field: "tags", label: "Status", kind: "select", options: ["pending", "paid", "shipped", "cancelled"] },
|
|
904
|
+
],
|
|
905
|
+
fields: [
|
|
906
|
+
{ field: "name", label: "Order #", kind: "text", required: true },
|
|
907
|
+
{ field: "price", label: "Total", kind: "currency" },
|
|
908
|
+
{ field: "tags", label: "Status", kind: "select", options: ["pending", "paid", "shipped", "cancelled"] },
|
|
909
|
+
],
|
|
910
|
+
filters: [{ field: "tags", label: "Status", kind: "select", options: ["pending", "paid", "shipped", "cancelled"] }],
|
|
911
|
+
actions: ["world:update-thing"],
|
|
912
|
+
},
|
|
913
|
+
{
|
|
914
|
+
key: "customers", label: "Customers", dimension: "actors", type: "customer", icon: "Users",
|
|
915
|
+
columns: [
|
|
916
|
+
{ field: "name", label: "Name", kind: "text", required: true },
|
|
917
|
+
{ field: "tags", label: "Tags", kind: "tags" },
|
|
918
|
+
],
|
|
919
|
+
fields: [
|
|
920
|
+
{ field: "name", label: "Name", kind: "text", required: true },
|
|
921
|
+
{ field: "tags", label: "Tags", kind: "tags" },
|
|
922
|
+
],
|
|
923
|
+
filters: [],
|
|
924
|
+
actions: ["world:create-actor", "world:update-actor"],
|
|
925
|
+
},
|
|
121
926
|
],
|
|
122
|
-
|
|
927
|
+
// ── roofers — lead → inspection → estimate → job, with crews ─────────────────
|
|
928
|
+
roofers: [
|
|
123
929
|
{
|
|
124
930
|
key: "leads", label: "Leads", dimension: "things", type: "lead", icon: "PhoneCall",
|
|
125
931
|
columns: [
|
|
@@ -154,6 +960,7 @@ export const TEMPLATES = {
|
|
|
154
960
|
{ field: "name", label: "Inspection", kind: "text", required: true },
|
|
155
961
|
{ field: "date", label: "Date", kind: "date" },
|
|
156
962
|
{ field: "notes", label: "Site notes", kind: "markdown" },
|
|
963
|
+
{ field: "lead", label: "Lead", kind: "relation", options: ["leads"] },
|
|
157
964
|
{ field: "tags", label: "Status", kind: "select", options: ["scheduled", "complete", "cancelled"] },
|
|
158
965
|
],
|
|
159
966
|
filters: [{ field: "tags", label: "Status", kind: "select", options: ["scheduled", "complete", "cancelled"] }],
|
|
@@ -171,6 +978,7 @@ export const TEMPLATES = {
|
|
|
171
978
|
{ field: "price", label: "Total", kind: "currency" },
|
|
172
979
|
{ field: "material", label: "Material", kind: "text" },
|
|
173
980
|
{ field: "warranty", label: "Warranty", kind: "text" },
|
|
981
|
+
{ field: "lead", label: "Lead", kind: "relation", options: ["leads"] },
|
|
174
982
|
{ field: "tags", label: "Status", kind: "select", options: ["pending", "accepted", "rejected", "insurance-pending"] },
|
|
175
983
|
],
|
|
176
984
|
filters: [{ field: "tags", label: "Status", kind: "select", options: ["pending", "accepted", "rejected", "insurance-pending"] }],
|
|
@@ -190,6 +998,7 @@ export const TEMPLATES = {
|
|
|
190
998
|
{ field: "start_date", label: "Start date", kind: "date" },
|
|
191
999
|
{ field: "material", label: "Material", kind: "text" },
|
|
192
1000
|
{ field: "squares", label: "Squares", kind: "number" },
|
|
1001
|
+
{ field: "estimate", label: "Estimate", kind: "relation", options: ["estimates"] },
|
|
193
1002
|
{ field: "crew", label: "Assigned crew", kind: "relation", options: ["crews"] },
|
|
194
1003
|
{ field: "tags", label: "Status", kind: "select", options: ["scheduled", "active", "completed", "invoiced"] },
|
|
195
1004
|
],
|
|
@@ -210,7 +1019,8 @@ export const TEMPLATES = {
|
|
|
210
1019
|
actions: ["world:create-actor", "world:update-actor"],
|
|
211
1020
|
},
|
|
212
1021
|
],
|
|
213
|
-
|
|
1022
|
+
// ── movers — quote → survey → move, with customers ──────────────────────────
|
|
1023
|
+
movers: [
|
|
214
1024
|
{
|
|
215
1025
|
key: "quotes", label: "Quotes", dimension: "things", type: "quote", icon: "FileSearch",
|
|
216
1026
|
columns: [
|
|
@@ -226,6 +1036,7 @@ export const TEMPLATES = {
|
|
|
226
1036
|
{ field: "destination", label: "Destination address", kind: "text" },
|
|
227
1037
|
{ field: "move_date", label: "Move date", kind: "date" },
|
|
228
1038
|
{ field: "home_size", label: "Home size", kind: "select", options: ["studio", "1bed", "2bed", "3bed", "4bed+"] },
|
|
1039
|
+
{ field: "customer", label: "Customer", kind: "relation", options: ["customers"] },
|
|
229
1040
|
{ field: "tags", label: "Status", kind: "select", options: ["open", "survey-booked", "deposit-paid", "lost"] },
|
|
230
1041
|
],
|
|
231
1042
|
filters: [
|
|
@@ -246,6 +1057,7 @@ export const TEMPLATES = {
|
|
|
246
1057
|
{ field: "date", label: "Date", kind: "date" },
|
|
247
1058
|
{ field: "duration", label: "Duration (min)", kind: "number" },
|
|
248
1059
|
{ field: "notes", label: "Notes", kind: "markdown" },
|
|
1060
|
+
{ field: "quote", label: "Quote", kind: "relation", options: ["quotes"] },
|
|
249
1061
|
{ field: "tags", label: "Status", kind: "select", options: ["scheduled", "complete", "cancelled"] },
|
|
250
1062
|
],
|
|
251
1063
|
filters: [{ field: "tags", label: "Status", kind: "select", options: ["scheduled", "complete", "cancelled"] }],
|
|
@@ -285,36 +1097,71 @@ export const TEMPLATES = {
|
|
|
285
1097
|
actions: ["world:create-actor", "world:update-actor"],
|
|
286
1098
|
},
|
|
287
1099
|
],
|
|
288
|
-
service: [
|
|
289
|
-
{
|
|
290
|
-
key: "jobs", label: "Jobs", dimension: "things", type: "job", icon: "Wrench",
|
|
291
|
-
columns: [
|
|
292
|
-
{ field: "name", label: "Job", kind: "text", required: true },
|
|
293
|
-
{ field: "price", label: "Value", kind: "currency" },
|
|
294
|
-
{ field: "tags", label: "Status", kind: "select", options: ["open", "in-progress", "done", "invoiced"] },
|
|
295
|
-
],
|
|
296
|
-
fields: [
|
|
297
|
-
{ field: "name", label: "Job", kind: "text", required: true },
|
|
298
|
-
{ field: "price", label: "Value", kind: "currency" },
|
|
299
|
-
{ field: "description", label: "Notes", kind: "markdown" },
|
|
300
|
-
{ field: "tags", label: "Status", kind: "select", options: ["open", "in-progress", "done", "invoiced"] },
|
|
301
|
-
],
|
|
302
|
-
filters: [{ field: "tags", label: "Status", kind: "select", options: ["open", "in-progress", "done", "invoiced"] }],
|
|
303
|
-
actions: ["world:create-thing", "world:update-thing"],
|
|
304
|
-
},
|
|
305
|
-
{
|
|
306
|
-
key: "clients", label: "Clients", dimension: "actors", type: "client", icon: "User",
|
|
307
|
-
columns: [
|
|
308
|
-
{ field: "name", label: "Name", kind: "text", required: true },
|
|
309
|
-
{ field: "tags", label: "Tags", kind: "tags" },
|
|
310
|
-
],
|
|
311
|
-
fields: [
|
|
312
|
-
{ field: "name", label: "Name", kind: "text", required: true },
|
|
313
|
-
{ field: "tags", label: "Tags", kind: "tags" },
|
|
314
|
-
],
|
|
315
|
-
filters: [],
|
|
316
|
-
actions: ["world:create-actor", "world:update-actor"],
|
|
317
|
-
},
|
|
318
|
-
],
|
|
319
1100
|
};
|
|
1101
|
+
// ─── Manifest → TypeQL ───────────────────────────────────────────────────────
|
|
1102
|
+
// Compile a resource-type manifest into a TypeDB 3.0 schema string so it can be
|
|
1103
|
+
// rendered in the TQL schema viewer. The mapping is idiomatic TypeDB:
|
|
1104
|
+
// • nouns (groups · actors · things · learning) → `entity`
|
|
1105
|
+
// • flows (paths · events) with relation fields → `relation` (fields = roles)
|
|
1106
|
+
// • every non-relation field → `attribute`
|
|
1107
|
+
// • relation fields on an entity → a generated binary relation
|
|
1108
|
+
// The output is for visualisation/teaching, not for `define` against a live DB.
|
|
1109
|
+
const VTYPE = {
|
|
1110
|
+
text: "string", markdown: "string", select: "string", image: "string",
|
|
1111
|
+
tags: "string[]", number: "double", currency: "double", date: "datetime",
|
|
1112
|
+
relation: "string",
|
|
1113
|
+
};
|
|
1114
|
+
const ident = (s) => s.replace(/[^A-Za-z0-9_-]+/g, "-").replace(/^-+|-+$/g, "") || "x";
|
|
1115
|
+
export function manifestToTql(types, title = "Workspace types") {
|
|
1116
|
+
const keys = new Set(types.map(t => t.key));
|
|
1117
|
+
const linksTo = (kind, opt) => kind === "relation" && !!opt?.[0] && keys.has(opt[0]);
|
|
1118
|
+
const attrs = new Map(); // field -> value type (first wins)
|
|
1119
|
+
const playsBy = new Map(); // entity key -> ["rel:role", …]
|
|
1120
|
+
const relations = [];
|
|
1121
|
+
const entities = [];
|
|
1122
|
+
const addPlays = (k, p) => { const a = playsBy.get(k) ?? []; a.push(p); playsBy.set(k, a); };
|
|
1123
|
+
for (const t of types)
|
|
1124
|
+
for (const f of t.fields)
|
|
1125
|
+
if (f.kind !== "relation" && !attrs.has(f.field))
|
|
1126
|
+
attrs.set(f.field, VTYPE[f.kind]);
|
|
1127
|
+
for (const t of types) {
|
|
1128
|
+
const tk = ident(t.key);
|
|
1129
|
+
const scalars = t.fields.filter(f => f.kind !== "relation").map(f => ident(f.field));
|
|
1130
|
+
const rels = t.fields.filter(f => linksTo(f.kind, f.options));
|
|
1131
|
+
const isFlow = (t.dimension === "paths" || t.dimension === "events") && rels.length > 0;
|
|
1132
|
+
if (isFlow) {
|
|
1133
|
+
relations.push({ name: tk, relates: rels.map(f => ident(f.field)), owns: scalars });
|
|
1134
|
+
for (const f of rels)
|
|
1135
|
+
addPlays(ident(f.options[0]), `${tk}:${ident(f.field)}`);
|
|
1136
|
+
}
|
|
1137
|
+
else {
|
|
1138
|
+
entities.push({ key: tk, label: t.label, dim: t.dimension, owns: scalars });
|
|
1139
|
+
for (const f of rels) {
|
|
1140
|
+
const rn = `${tk}_${ident(f.field)}`;
|
|
1141
|
+
relations.push({ name: rn, relates: ["src", "dst"], owns: [] });
|
|
1142
|
+
addPlays(tk, `${rn}:src`);
|
|
1143
|
+
addPlays(ident(f.options[0]), `${rn}:dst`);
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
const out = [`# ${title} — generated TypeDB 3.0 schema`, "", "define", ""];
|
|
1148
|
+
out.push("# ── Attributes ──────────────────────────");
|
|
1149
|
+
for (const [name, vt] of [...attrs.keys()].sort().map(k => [k, attrs.get(k)]))
|
|
1150
|
+
out.push(`attribute ${ident(name)}, value ${vt};`);
|
|
1151
|
+
out.push("");
|
|
1152
|
+
out.push("# ── Entities ────────────────────────────");
|
|
1153
|
+
for (const e of entities) {
|
|
1154
|
+
const body = [...e.owns.map((o, i) => `owns ${o}${i === 0 ? " @key" : ""}`), ...(playsBy.get(e.key) ?? []).map(p => `plays ${p}`)];
|
|
1155
|
+
out.push(`# ${e.label} · ${e.dim}`);
|
|
1156
|
+
out.push(body.length ? `entity ${e.key},\n ${body.join(",\n ")};` : `entity ${e.key};`);
|
|
1157
|
+
}
|
|
1158
|
+
if (relations.length) {
|
|
1159
|
+
out.push("", "# ── Relations ───────────────────────────");
|
|
1160
|
+
for (const r of relations) {
|
|
1161
|
+
const body = [...r.relates.map(x => `relates ${x}`), ...r.owns.map(o => `owns ${o}`)];
|
|
1162
|
+
out.push(`relation ${r.name},\n ${body.join(",\n ")};`);
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
return out.join("\n") + "\n";
|
|
1166
|
+
}
|
|
320
1167
|
//# sourceMappingURL=templates.js.map
|