@rubytech/create-maxy-code 0.1.125 → 0.1.127

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 (78) hide show
  1. package/dist/index.js +23 -1
  2. package/package.json +2 -2
  3. package/payload/platform/config/brand.json +20 -1
  4. package/payload/platform/lib/aeo-llms-txt-writer/dist/index.d.ts +33 -0
  5. package/payload/platform/lib/aeo-llms-txt-writer/dist/index.d.ts.map +1 -0
  6. package/payload/platform/lib/aeo-llms-txt-writer/dist/index.js +119 -0
  7. package/payload/platform/lib/aeo-llms-txt-writer/dist/index.js.map +1 -0
  8. package/payload/platform/lib/aeo-llms-txt-writer/src/index.ts +172 -0
  9. package/payload/platform/lib/aeo-llms-txt-writer/tsconfig.json +8 -0
  10. package/payload/platform/lib/graph-style/dist/index.d.ts +78 -0
  11. package/payload/platform/lib/graph-style/dist/index.d.ts.map +1 -0
  12. package/payload/platform/lib/graph-style/dist/index.js +296 -0
  13. package/payload/platform/lib/graph-style/dist/index.js.map +1 -0
  14. package/payload/platform/lib/graph-style/src/__tests__/parity.test.ts +114 -0
  15. package/payload/platform/lib/graph-style/src/index.ts +307 -0
  16. package/payload/platform/lib/graph-style/tsconfig.json +9 -0
  17. package/payload/platform/lib/graph-style/vitest.config.ts +9 -0
  18. package/payload/platform/package-lock.json +318 -0
  19. package/payload/platform/package.json +3 -2
  20. package/payload/platform/plugins/.claude-plugin/marketplace.json +5 -0
  21. package/payload/platform/plugins/admin/.claude-plugin/plugin.json +1 -1
  22. package/payload/platform/plugins/admin/PLUGIN.md +4 -1
  23. package/payload/platform/plugins/admin/mcp/dist/index.js +73 -0
  24. package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
  25. package/payload/platform/plugins/admin/mcp/dist/tools/publish-site.d.ts +34 -0
  26. package/payload/platform/plugins/admin/mcp/dist/tools/publish-site.d.ts.map +1 -0
  27. package/payload/platform/plugins/admin/mcp/dist/tools/publish-site.js +176 -0
  28. package/payload/platform/plugins/admin/mcp/dist/tools/publish-site.js.map +1 -0
  29. package/payload/platform/plugins/admin/skills/publish-site/SKILL.md +19 -57
  30. package/payload/platform/plugins/aeo/mcp/dist/tools/aeo-write-llms-txt.d.ts +5 -38
  31. package/payload/platform/plugins/aeo/mcp/dist/tools/aeo-write-llms-txt.d.ts.map +1 -1
  32. package/payload/platform/plugins/aeo/mcp/dist/tools/aeo-write-llms-txt.js +7 -114
  33. package/payload/platform/plugins/aeo/mcp/dist/tools/aeo-write-llms-txt.js.map +1 -1
  34. package/payload/platform/plugins/docs/references/visitor-graph.md +4 -3
  35. package/payload/platform/plugins/graph-viewer/.claude-plugin/plugin.json +8 -0
  36. package/payload/platform/plugins/graph-viewer/PLUGIN.md +56 -0
  37. package/payload/platform/plugins/graph-viewer/mcp/dist/index.d.ts +7 -0
  38. package/payload/platform/plugins/graph-viewer/mcp/dist/index.d.ts.map +1 -0
  39. package/payload/platform/plugins/graph-viewer/mcp/dist/index.js +74 -0
  40. package/payload/platform/plugins/graph-viewer/mcp/dist/index.js.map +1 -0
  41. package/payload/platform/plugins/graph-viewer/mcp/dist/lib/neo4j.d.ts +5 -0
  42. package/payload/platform/plugins/graph-viewer/mcp/dist/lib/neo4j.d.ts.map +1 -0
  43. package/payload/platform/plugins/graph-viewer/mcp/dist/lib/neo4j.js +43 -0
  44. package/payload/platform/plugins/graph-viewer/mcp/dist/lib/neo4j.js.map +1 -0
  45. package/payload/platform/plugins/graph-viewer/mcp/dist/render/draw.d.ts +28 -0
  46. package/payload/platform/plugins/graph-viewer/mcp/dist/render/draw.d.ts.map +1 -0
  47. package/payload/platform/plugins/graph-viewer/mcp/dist/render/draw.js +73 -0
  48. package/payload/platform/plugins/graph-viewer/mcp/dist/render/draw.js.map +1 -0
  49. package/payload/platform/plugins/graph-viewer/mcp/dist/render/layout.d.ts +40 -0
  50. package/payload/platform/plugins/graph-viewer/mcp/dist/render/layout.d.ts.map +1 -0
  51. package/payload/platform/plugins/graph-viewer/mcp/dist/render/layout.js +77 -0
  52. package/payload/platform/plugins/graph-viewer/mcp/dist/render/layout.js.map +1 -0
  53. package/payload/platform/plugins/graph-viewer/mcp/dist/tools/graph-render.d.ts +45 -0
  54. package/payload/platform/plugins/graph-viewer/mcp/dist/tools/graph-render.d.ts.map +1 -0
  55. package/payload/platform/plugins/graph-viewer/mcp/dist/tools/graph-render.js +170 -0
  56. package/payload/platform/plugins/graph-viewer/mcp/dist/tools/graph-render.js.map +1 -0
  57. package/payload/platform/plugins/graph-viewer/mcp/package.json +25 -0
  58. package/payload/platform/plugins/graph-viewer/mcp/vitest.config.ts +8 -0
  59. package/payload/platform/plugins/graph-viewer/skills/render-graph/SKILL.md +35 -0
  60. package/payload/platform/scripts/check-plugin-tools-mcp-consistency.mjs +136 -0
  61. package/payload/platform/templates/specialists/agents/content-producer.md +3 -3
  62. package/payload/server/public/assets/{admin-D6IfAzYY.js → admin-FcRHAL-3.js} +7 -7
  63. package/payload/server/public/assets/{data-BGbQyufe.js → data-Ds37mflX.js} +1 -1
  64. package/payload/server/public/assets/{graph-D-1lRTeL.js → graph-CmWRhaiS.js} +1 -1
  65. package/payload/server/public/assets/graph-labels-Ch2r00Gt.js +1 -0
  66. package/payload/server/public/assets/page-BOtNny_4.js +51 -0
  67. package/payload/server/public/assets/page-BcHhJXUt.js +1 -0
  68. package/payload/server/public/consent.css +97 -0
  69. package/payload/server/public/consent.js +259 -0
  70. package/payload/server/public/data.html +3 -3
  71. package/payload/server/public/graph.html +3 -3
  72. package/payload/server/public/index.html +4 -4
  73. package/payload/server/public/privacy.html +68 -5
  74. package/payload/server/public/v.js +53 -0
  75. package/payload/server/server.js +465 -176
  76. package/payload/server/public/assets/graph-labels-BRXJHNYE.js +0 -1
  77. package/payload/server/public/assets/page-B4oirCvn.js +0 -1
  78. package/payload/server/public/assets/page-FmJ7PIYx.js +0 -51
@@ -0,0 +1,296 @@
1
+ "use strict";
2
+ /**
3
+ * Shared palette + display-string primitives for any surface that renders
4
+ * the Neo4j graph. Both the live `/graph` page in platform/ui and the
5
+ * graph-viewer MCP plugin's PNG renderer import from here so a node looks
6
+ * the same wherever it appears: same colour family per label, same short
7
+ * canvas label per node.
8
+ *
9
+ * UI-only constants (filter-popover sets, zoom-tier wrap helpers,
10
+ * agent-action label sets) stay in platform/ui/app/lib/graph-labels.ts and
11
+ * platform/ui/app/graph/display-helpers.ts — they re-export the symbols
12
+ * defined here. The two parity tests (this lib's __tests__ and the UI's
13
+ * unchanged colour-stability tests) keep the surfaces in lockstep.
14
+ *
15
+ * Sources of truth:
16
+ * - Label list: .docs/neo4j.md "Schema (Phase 0)" + "Standards Compliance"
17
+ * - Brand colour for LocalBusiness: brand.json defaultColors.primary
18
+ * (resolved at runtime; this module supplies the schema-default fallback)
19
+ */
20
+ Object.defineProperty(exports, "__esModule", { value: true });
21
+ exports.ALL_GRAPH_LABELS = exports.FALLBACK_LABEL_COLOUR = exports.GRAPH_LABEL_COLOURS = void 0;
22
+ exports.pickDisplayLabel = pickDisplayLabel;
23
+ exports.colourForLabel = colourForLabel;
24
+ exports.resolveNodeColour = resolveNodeColour;
25
+ exports.formatRunTimestamp = formatRunTimestamp;
26
+ exports.formatMessageTimestamp = formatMessageTimestamp;
27
+ exports.pickShortLabel = pickShortLabel;
28
+ exports.pickDisplayName = pickDisplayName;
29
+ /**
30
+ * Label → display colour mapping. Closed list of node labels written by
31
+ * the Maxy MCP write paths. A new label without an entry here renders in
32
+ * FALLBACK_LABEL_COLOUR and is omitted from the legend.
33
+ */
34
+ exports.GRAPH_LABEL_COLOURS = {
35
+ // Business identity — slate-blue family
36
+ LocalBusiness: '#4F6B8A',
37
+ Service: '#6B85A0',
38
+ PriceSpecification: '#8AA0B8',
39
+ OpeningHoursSpecification: '#A8BACE',
40
+ // Estate-agent ontology. Listing/Property share the business slate-blue
41
+ // family; Viewing/Offer are transactional events placed in a warm amber
42
+ // family distinct from Agent and from the dusty-rose Task/Project/Event
43
+ // hues so the legend reads them as a separate band.
44
+ Listing: '#3F5670',
45
+ Property: '#5C7A99',
46
+ Viewing: '#D4A574',
47
+ Offer: '#B08850',
48
+ // External business entity — schema:Organization, written by memory-write
49
+ // as the Supplier label. Warm tobacco — distinct hue from internal-business
50
+ // slates so external entities are scannable at a glance.
51
+ Organization: '#8A6B47',
52
+ // People — terracotta family (warm, human)
53
+ Person: '#B86E4A',
54
+ UserProfile: '#D08960',
55
+ Preference: '#DFA67A',
56
+ AdminUser: '#8C5230',
57
+ AccessGrant: '#66381F',
58
+ // Knowledge — moss family (organic)
59
+ KnowledgeDocument: '#6E8A5A',
60
+ // chunked WhatsApp/messaging archive parent. Sits in the
61
+ // knowledge moss family because it's structurally a document parent
62
+ // (HAS_SECTION → :Section:Conversation chunks); the conversational
63
+ // plum family is reserved for the live Conversation/Message labels.
64
+ ConversationArchive: '#82A06A',
65
+ Section: '#8AA876',
66
+ Chunk: '#A6C194',
67
+ DigitalDocument: '#5A7548',
68
+ CreativeWork: '#B5C9A2',
69
+ Question: '#C7D6B5',
70
+ FAQPage: '#95B385',
71
+ DefinedTerm: '#76906A',
72
+ Review: '#3F5A2E',
73
+ ImageObject: '#A0BB8C',
74
+ // Conversational — muted plum/lavender family.
75
+ // Pairwise-distinctness invariants enforced by the UI test
76
+ // graph-labels.test.ts; UserMessage matches Preference (Person/family cue,
77
+ // the one intentional duplicate in the registry).
78
+ Conversation: '#6B5A85',
79
+ AdminConversation: '#4F4070',
80
+ PublicConversation: '#8A75A8',
81
+ Message: '#6B7280',
82
+ UserMessage: '#DFA67A',
83
+ AssistantMessage: '#C9A876',
84
+ ToolCall: '#B5ABCB',
85
+ // Tasks / projects / events — dusty rose family
86
+ Task: '#B0617A',
87
+ Project: '#8E4A60',
88
+ Event: '#C68095',
89
+ // Workflows — muted teal
90
+ Workflow: '#3A6F77',
91
+ WorkflowStep: '#5A8E96',
92
+ WorkflowRun: '#7AAAB2',
93
+ StepResult: '#9CC4CB',
94
+ // Email — muted moss, hue-adjacent to Knowledge but lower-saturation
95
+ // and warmer; never co-rendered with KnowledgeDocument.
96
+ Email: '#6F7F4A',
97
+ EmailAccount: '#91A063',
98
+ // Public-agent projection — burnished bronze sits between
99
+ // people-terracotta and email-moss but shares neither hue.
100
+ Agent: '#B8893D',
101
+ };
102
+ exports.FALLBACK_LABEL_COLOUR = '#94A3B8';
103
+ exports.ALL_GRAPH_LABELS = Object.freeze(Object.keys(exports.GRAPH_LABEL_COLOURS));
104
+ /**
105
+ * Select the sublabel whose colour should drive the node hue. Walks the
106
+ * label array from index 1 (skipping the base label at index 0) and
107
+ * returns the first sublabel that has a registered colour; falls back to
108
+ * labels[0]. Pure — drift-counting lives in resolveNodeColour.
109
+ */
110
+ function pickDisplayLabel(labels) {
111
+ for (let i = 1; i < labels.length; i++) {
112
+ if (Object.prototype.hasOwnProperty.call(exports.GRAPH_LABEL_COLOURS, labels[i])) {
113
+ return labels[i];
114
+ }
115
+ }
116
+ return labels[0] ?? null;
117
+ }
118
+ function colourForLabel(label) {
119
+ return exports.GRAPH_LABEL_COLOURS[label] ?? exports.FALLBACK_LABEL_COLOUR;
120
+ }
121
+ /**
122
+ * Single-source colour resolver. driftCandidates counts registered
123
+ * sublabels in labels[1..]; a node with two registered sublabels has
124
+ * driftCandidates = 2 and its rendered hue is order-dependent.
125
+ */
126
+ function resolveNodeColour(labels) {
127
+ const displayLabel = pickDisplayLabel(labels);
128
+ const colour = displayLabel ? colourForLabel(displayLabel) : exports.FALLBACK_LABEL_COLOUR;
129
+ let driftCandidates = 0;
130
+ for (let i = 1; i < labels.length; i++) {
131
+ if (Object.prototype.hasOwnProperty.call(exports.GRAPH_LABEL_COLOURS, labels[i])) {
132
+ driftCandidates++;
133
+ }
134
+ }
135
+ return { displayLabel, colour, driftCandidates };
136
+ }
137
+ const ISO_MINUTE_RE = /^(\d{4}-\d{2}-\d{2})T(\d{2}:\d{2})/;
138
+ const ISO_SECOND_RE = /^\d{4}-\d{2}-\d{2}T(\d{2}:\d{2}:\d{2})/;
139
+ /**
140
+ * YYYY-MM-DD HH:mm from an ISO 8601 prefix. Reads the prefix directly so
141
+ * timezone-stored UTC timestamps render identically across operator
142
+ * timezones; parsing to Date + reformatting would flip the day.
143
+ */
144
+ function formatRunTimestamp(iso) {
145
+ const m = iso.match(ISO_MINUTE_RE);
146
+ if (!m)
147
+ return null;
148
+ return `${m[1]} ${m[2]}`;
149
+ }
150
+ /** HH:mm:ss from an ISO 8601 prefix. Same tz-stable contract. */
151
+ function formatMessageTimestamp(iso) {
152
+ const m = iso.match(ISO_SECOND_RE);
153
+ if (!m)
154
+ return null;
155
+ return m[1];
156
+ }
157
+ /**
158
+ * 24-char canvas label for a node. Label precedence per label family
159
+ * (ToolCall.toolName, WorkflowRun startedAt formatted, WorkflowStep.label,
160
+ * Person givenName+familyName compose, Agent displayName/slug, Message
161
+ * role+timestamp, ConversationArchive.title), then a generic fallthrough
162
+ * across curated keys (name, title, summary, givenName, subject, text),
163
+ * then a Conversation-specific `Conv <id8>` fallback so unpopulated
164
+ * conversations don't render as the literal label.
165
+ */
166
+ function pickShortLabel(node) {
167
+ const props = node.properties;
168
+ const primaryLabel = node.labels[0];
169
+ if (primaryLabel === 'ToolCall') {
170
+ const v = props.toolName;
171
+ if (typeof v === 'string' && v.length > 0) {
172
+ return v.length > 24 ? v.slice(0, 24) + '…' : v;
173
+ }
174
+ }
175
+ else if (primaryLabel === 'WorkflowRun') {
176
+ const v = props.startedAt;
177
+ if (typeof v === 'string' && v.length > 0) {
178
+ const ts = formatRunTimestamp(v);
179
+ if (ts)
180
+ return ts;
181
+ }
182
+ }
183
+ else if (primaryLabel === 'WorkflowStep') {
184
+ const v = props.label;
185
+ if (typeof v === 'string' && v.length > 0) {
186
+ return v.length > 24 ? v.slice(0, 24) + '…' : v;
187
+ }
188
+ }
189
+ else if (primaryLabel === 'Person') {
190
+ const given = typeof props.givenName === 'string' ? props.givenName : '';
191
+ const family = typeof props.familyName === 'string' ? props.familyName : '';
192
+ const full = [given, family].filter((s) => s.length > 0).join(' ');
193
+ if (full.length > 0) {
194
+ return full.length > 24 ? full.slice(0, 24) + '…' : full;
195
+ }
196
+ }
197
+ else if (primaryLabel === 'Agent') {
198
+ const dn = typeof props.displayName === 'string' ? props.displayName : '';
199
+ const slug = typeof props.slug === 'string' ? props.slug : '';
200
+ const v = dn.length > 0 ? dn : slug;
201
+ if (v.length > 0) {
202
+ return v.length > 24 ? v.slice(0, 24) + '…' : v;
203
+ }
204
+ }
205
+ else if (primaryLabel === 'Message') {
206
+ const role = typeof props.role === 'string' ? props.role : '';
207
+ const roleShort = role === 'user' ? 'user'
208
+ : role === 'assistant' ? 'asst'
209
+ : role === 'system' ? 'sys'
210
+ : role === 'tool' ? 'tool'
211
+ : null;
212
+ const createdAt = typeof props.createdAt === 'string' ? props.createdAt : '';
213
+ if (roleShort && createdAt) {
214
+ const ts = formatMessageTimestamp(createdAt);
215
+ if (ts)
216
+ return `${roleShort} ${ts}`;
217
+ }
218
+ }
219
+ else if (primaryLabel === 'ConversationArchive') {
220
+ const t = typeof props.title === 'string' ? props.title : '';
221
+ if (t.length > 0) {
222
+ return t.length > 24 ? t.slice(0, 24) + '…' : t;
223
+ }
224
+ return primaryLabel;
225
+ }
226
+ for (const k of ['name', 'title', 'summary', 'givenName', 'subject', 'text']) {
227
+ const v = props[k];
228
+ if (typeof v === 'string' && v.length > 0) {
229
+ return v.length > 24 ? v.slice(0, 24) + '…' : v;
230
+ }
231
+ }
232
+ if (primaryLabel === 'Conversation') {
233
+ const id = typeof props.conversationId === 'string' ? props.conversationId : null;
234
+ if (id)
235
+ return `Conv ${id.slice(0, 8)}`;
236
+ }
237
+ return primaryLabel ?? '…';
238
+ }
239
+ /**
240
+ * Untruncated sibling of pickShortLabel. Used by side-panel headings and
241
+ * tooltips where the 24-char canvas-overlap cap does not apply.
242
+ */
243
+ function pickDisplayName(node) {
244
+ const props = node.properties;
245
+ const primaryLabel = node.labels[0];
246
+ if (primaryLabel === 'ToolCall') {
247
+ const v = props.toolName;
248
+ if (typeof v === 'string' && v.length > 0)
249
+ return v;
250
+ }
251
+ else if (primaryLabel === 'WorkflowRun') {
252
+ const v = props.startedAt;
253
+ if (typeof v === 'string' && v.length > 0) {
254
+ const ts = formatRunTimestamp(v);
255
+ if (ts)
256
+ return ts;
257
+ }
258
+ }
259
+ else if (primaryLabel === 'WorkflowStep') {
260
+ const v = props.label;
261
+ if (typeof v === 'string' && v.length > 0)
262
+ return v;
263
+ }
264
+ else if (primaryLabel === 'Person') {
265
+ const given = typeof props.givenName === 'string' ? props.givenName : '';
266
+ const family = typeof props.familyName === 'string' ? props.familyName : '';
267
+ const full = [given, family].filter((s) => s.length > 0).join(' ');
268
+ if (full.length > 0)
269
+ return full;
270
+ }
271
+ else if (primaryLabel === 'Agent') {
272
+ const dn = typeof props.displayName === 'string' ? props.displayName : '';
273
+ const slug = typeof props.slug === 'string' ? props.slug : '';
274
+ const v = dn.length > 0 ? dn : slug;
275
+ if (v.length > 0)
276
+ return v;
277
+ }
278
+ else if (primaryLabel === 'ConversationArchive') {
279
+ const t = typeof props.title === 'string' ? props.title : '';
280
+ if (t.length > 0)
281
+ return t;
282
+ return primaryLabel;
283
+ }
284
+ for (const k of ['name', 'title', 'summary', 'givenName', 'subject', 'text']) {
285
+ const v = props[k];
286
+ if (typeof v === 'string' && v.length > 0)
287
+ return v;
288
+ }
289
+ if (primaryLabel === 'Conversation') {
290
+ const id = typeof props.conversationId === 'string' ? props.conversationId : null;
291
+ if (id)
292
+ return `Conv ${id.slice(0, 8)}`;
293
+ }
294
+ return primaryLabel ?? '…';
295
+ }
296
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Parity gate for the shared graph-style lib. Asserts the small set of
3
+ * load-bearing fixtures every UI and plugin caller relies on. Richer
4
+ * coverage lives in the UI's existing tests under
5
+ * platform/ui/app/lib/__tests__/graph-labels.test.ts and
6
+ * platform/ui/app/graph/__tests__/*; those tests now exercise the
7
+ * re-exported symbols and pass unchanged if extraction was faithful.
8
+ */
9
+
10
+ import { describe, it, expect } from "vitest";
11
+ import {
12
+ GRAPH_LABEL_COLOURS,
13
+ FALLBACK_LABEL_COLOUR,
14
+ pickDisplayLabel,
15
+ resolveNodeColour,
16
+ pickShortLabel,
17
+ pickDisplayName,
18
+ } from "../index.js";
19
+
20
+ describe("palette invariants", () => {
21
+ it("registers every label family with a hex colour", () => {
22
+ for (const [label, colour] of Object.entries(GRAPH_LABEL_COLOURS)) {
23
+ expect(colour, `${label} colour`).toMatch(/^#[0-9A-Fa-f]{6}$/);
24
+ }
25
+ });
26
+
27
+ it("FALLBACK_LABEL_COLOUR is a hex", () => {
28
+ expect(FALLBACK_LABEL_COLOUR).toMatch(/^#[0-9A-Fa-f]{6}$/);
29
+ });
30
+
31
+ it("UserMessage and Preference deliberately share a hue (Person-family cue)", () => {
32
+ expect(GRAPH_LABEL_COLOURS.UserMessage).toBe(GRAPH_LABEL_COLOURS.Preference);
33
+ });
34
+ });
35
+
36
+ describe("pickDisplayLabel", () => {
37
+ it("returns the first registered sublabel", () => {
38
+ expect(pickDisplayLabel(["Conversation", "AdminConversation"])).toBe(
39
+ "AdminConversation",
40
+ );
41
+ });
42
+
43
+ it("falls back to labels[0] when no sublabel is registered", () => {
44
+ expect(pickDisplayLabel(["Person", "UnregisteredSublabel"])).toBe("Person");
45
+ });
46
+
47
+ it("returns null on empty labels", () => {
48
+ expect(pickDisplayLabel([])).toBeNull();
49
+ });
50
+ });
51
+
52
+ describe("resolveNodeColour", () => {
53
+ it("counts drift candidates", () => {
54
+ const r = resolveNodeColour(["Conversation", "PublicConversation", "AssistantMessage"]);
55
+ expect(r.driftCandidates).toBe(2);
56
+ expect(r.colour).toBe(GRAPH_LABEL_COLOURS.PublicConversation);
57
+ });
58
+ });
59
+
60
+ describe("pickShortLabel", () => {
61
+ it("Person composes from given+family", () => {
62
+ expect(
63
+ pickShortLabel({
64
+ id: "x",
65
+ labels: ["Person"],
66
+ properties: { givenName: "Dan", familyName: "Brett" },
67
+ }),
68
+ ).toBe("Dan Brett");
69
+ });
70
+
71
+ it("Message renders role + HH:mm:ss", () => {
72
+ expect(
73
+ pickShortLabel({
74
+ id: "x",
75
+ labels: ["Message"],
76
+ properties: { role: "user", createdAt: "2026-05-25T14:33:42Z" },
77
+ }),
78
+ ).toBe("user 14:33:42");
79
+ });
80
+
81
+ it("Conversation falls back to Conv <id8>", () => {
82
+ expect(
83
+ pickShortLabel({
84
+ id: "x",
85
+ labels: ["Conversation"],
86
+ properties: { conversationId: "abcdef0123456789" },
87
+ }),
88
+ ).toBe("Conv abcdef01");
89
+ });
90
+
91
+ it("truncates over-cap labels to 24 chars + ellipsis", () => {
92
+ const longName = "This is a very long string that exceeds twenty-four chars";
93
+ const out = pickShortLabel({
94
+ id: "x",
95
+ labels: ["LocalBusiness"],
96
+ properties: { name: longName },
97
+ });
98
+ expect(out.length).toBeLessThanOrEqual(25); // 24 + '…'
99
+ expect(out.endsWith("…")).toBe(true);
100
+ });
101
+ });
102
+
103
+ describe("pickDisplayName", () => {
104
+ it("untruncated counterpart to pickShortLabel", () => {
105
+ const longName = "This is a very long string that exceeds twenty-four chars";
106
+ expect(
107
+ pickDisplayName({
108
+ id: "x",
109
+ labels: ["LocalBusiness"],
110
+ properties: { name: longName },
111
+ }),
112
+ ).toBe(longName);
113
+ });
114
+ });