@agent-native/core 0.123.2 → 0.124.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/core/CHANGELOG.md +28 -0
  3. package/corpus/core/package.json +1 -1
  4. package/corpus/templates/analytics/server/lib/dashboard-report-render.ts +6 -3
  5. package/corpus/templates/analytics/server/lib/report-chart-svg.ts +18 -5
  6. package/corpus/templates/crm/actions/_crm-list-utils.ts +178 -0
  7. package/corpus/templates/crm/actions/add-crm-record-to-list.ts +23 -2
  8. package/corpus/templates/crm/actions/create-crm-list.ts +229 -43
  9. package/corpus/templates/crm/actions/create-crm-record.ts +13 -5
  10. package/corpus/templates/crm/actions/update-crm-list-entry.ts +1 -1
  11. package/corpus/templates/crm/app/components/crm/RecordGrid.tsx +22 -2
  12. package/corpus/templates/crm/app/components/crm/RecordWorkspace.tsx +143 -32
  13. package/corpus/templates/crm/app/components/crm/board/CrmBoard.tsx +190 -75
  14. package/corpus/templates/crm/app/components/crm/grid/CrmGrid.tsx +267 -115
  15. package/corpus/templates/crm/app/components/crm/grid/GridCell.tsx +265 -131
  16. package/corpus/templates/crm/app/components/crm/record/AttributePanel.tsx +79 -100
  17. package/corpus/templates/crm/app/components/crm/record/RecordHeader.tsx +12 -8
  18. package/corpus/templates/crm/app/components/crm/record/RecordLists.tsx +27 -31
  19. package/corpus/templates/crm/app/components/crm/record/RecordTabs.tsx +16 -13
  20. package/corpus/templates/crm/app/components/crm/record/attribute-row.tsx +108 -0
  21. package/corpus/templates/crm/app/components/crm/record/field-editors.tsx +201 -9
  22. package/corpus/templates/crm/app/components/crm/record/panel-resize.ts +61 -0
  23. package/corpus/templates/crm/app/components/crm/record/record-data.ts +5 -4
  24. package/corpus/templates/crm/app/components/crm/shared/README-tokens.md +103 -0
  25. package/corpus/templates/crm/app/components/crm/shared/RecordReferencePicker.tsx +117 -0
  26. package/corpus/templates/crm/app/components/crm/shared/attribute-value.ts +84 -0
  27. package/corpus/templates/crm/app/components/crm/shared/ui-tokens.ts +89 -0
  28. package/corpus/templates/crm/app/global.css +170 -0
  29. package/corpus/templates/crm/app/i18n/en-US.ts +1 -0
  30. package/corpus/templates/crm/changelog/2026-07-26-a-half-typed-number-or-date-no-longer-saves-as-empty-the-fie.md +6 -0
  31. package/corpus/templates/crm/changelog/2026-07-26-a-new-pipeline-board-now-opens-with-stage-columns-a-summabl.md +6 -0
  32. package/corpus/templates/crm/changelog/2026-07-26-record-reference-fields-like-account-can-now-be-linked-from-.md +6 -0
  33. package/corpus/templates/crm/changelog/2026-07-26-retyping-a-record-field-now-replaces-the-old-value-instead-o.md +6 -0
  34. package/corpus/templates/design/server/handlers/index-design-system-with-builder.ts +38 -21
  35. package/corpus/templates/slides/server/handlers/index-design-system-with-builder.ts +23 -20
  36. package/dist/collab/awareness.d.ts +2 -2
  37. package/dist/collab/awareness.d.ts.map +1 -1
  38. package/dist/collab/routes.d.ts +1 -1
  39. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  40. package/dist/notifications/routes.d.ts +3 -3
  41. package/dist/observability/routes.d.ts +3 -3
  42. package/dist/resources/handlers.d.ts +1 -1
  43. package/dist/server/transcribe-voice.d.ts +1 -1
  44. package/package.json +1 -1
@@ -423,6 +423,57 @@ export function valueSpecFor(attribute: CrmValueShape): CrmValueSpec {
423
423
  return ATTRIBUTE_VALUE_SPECS[attribute.attributeType];
424
424
  }
425
425
 
426
+ /**
427
+ * The `<input>` type an inline text editor must use, for every surface.
428
+ *
429
+ * A numeric attribute deliberately gets `text`, not `number`. `<input
430
+ * type="number">` reports `value === ""` for anything the control cannot parse
431
+ * — a half-typed "91e", "1,2", a lone "-" — while `validity.badInput` is true.
432
+ * That empty string reaches `parse` as "the user cleared the field" and is
433
+ * stored as null, so a typed amount silently becomes NULL. Keeping the raw text
434
+ * lets `parse` fail loudly with `not-a-number` instead. `inputMode` keeps the
435
+ * numeric keypad on touch.
436
+ */
437
+ export function editorInputType(attribute: CrmValueShape): {
438
+ type: CrmValueSpec["inputType"];
439
+ inputMode?: "decimal";
440
+ } {
441
+ // A multi value is a comma-separated list, which no typed input accepts.
442
+ if (attribute.multi) return { type: "text" };
443
+ const spec = valueSpecFor(attribute);
444
+ if (spec.inputType === "number") {
445
+ return { type: "text", inputMode: "decimal" };
446
+ }
447
+ return { type: spec.inputType };
448
+ }
449
+
450
+ const REFERENCE_OBJECT_KINDS: Record<string, string> = {
451
+ accounts: "account",
452
+ people: "person",
453
+ opportunities: "opportunity",
454
+ };
455
+
456
+ /**
457
+ * The record kind a reference picker may narrow its search to, read from
458
+ * `config.reference.allowedObjectTypes`.
459
+ *
460
+ * `null` means "do not narrow": either the attribute declares no scope, or it
461
+ * declares several object types, which `list-crm-records` takes one `kind` at a
462
+ * time and cannot express. Picking one of several would hide exactly the record
463
+ * the user is looking for, so an unexpressible scope stays open and the picker
464
+ * says which types the attribute accepts.
465
+ */
466
+ export function referenceSearchKind(attribute: CrmValueShape): string | null {
467
+ const reference = attribute.config?.reference;
468
+ if (!reference || typeof reference !== "object") return null;
469
+ const allowed = (reference as { allowedObjectTypes?: unknown })
470
+ .allowedObjectTypes;
471
+ if (!Array.isArray(allowed) || allowed.length !== 1) return null;
472
+ const objectType = allowed[0];
473
+ if (typeof objectType !== "string") return null;
474
+ return REFERENCE_OBJECT_KINDS[objectType] ?? null;
475
+ }
476
+
426
477
  /** Every type has a spec and no system-only type is editable anywhere. */
427
478
  export function assertValueRegistryComplete(): void {
428
479
  for (const type of CRM_ATTRIBUTE_TYPES) {
@@ -566,6 +617,39 @@ export function editorDraftFor(
566
617
  return state.seed === seed ? state : { draft: seed, seed };
567
618
  }
568
619
 
620
+ // ---------------------------------------------------------------------------
621
+ // Reference values
622
+ // ---------------------------------------------------------------------------
623
+
624
+ /** The individual records a reference value names, in stored order. */
625
+ export function referenceMembers(
626
+ value: CrmAttributeValue | undefined,
627
+ ): string[] {
628
+ if (value === undefined || value === null) return [];
629
+ return (Array.isArray(value) ? value : [value])
630
+ .filter((entry): entry is string => typeof entry === "string")
631
+ .filter((entry) => entry !== "");
632
+ }
633
+
634
+ /**
635
+ * The value a reference picker produces for `pick`. A single reference is
636
+ * replaced outright; a multi reference toggles membership and collapses to
637
+ * `null` — not `[]` — when the last member goes, because an empty array and no
638
+ * value must not read as two different states downstream.
639
+ */
640
+ export function toggleReferenceValue(
641
+ value: CrmAttributeValue | undefined,
642
+ pick: string,
643
+ multi: boolean,
644
+ ): CrmEditableValue {
645
+ if (!multi) return pick;
646
+ const members = referenceMembers(value);
647
+ const next = members.includes(pick)
648
+ ? members.filter((entry) => entry !== pick)
649
+ : [...members, pick];
650
+ return next.length ? next : null;
651
+ }
652
+
569
653
  /**
570
654
  * Days a value has sat past its status option's `targetDays`. `null` when the
571
655
  * attribute is not a status, has no SLA, or has no known `activeFrom` — an
@@ -0,0 +1,89 @@
1
+ /**
2
+ * The TS half of the CRM surface token layer. Everything expressible as CSS
3
+ * lives in `app/global.css`; this file exists only for the values that must be
4
+ * *numbers* in JS — virtualizer row math, board layout, resizable panel
5
+ * clamps, timers — plus the two bits of shared geometry logic.
6
+ *
7
+ * Read `README-tokens.md` in this directory before styling a surface.
8
+ */
9
+
10
+ /** Fixed. There is no density toggle; every consumer must agree on 36. */
11
+ export const ROW_HEIGHT = 36;
12
+ export const HEADER_HEIGHT = 40;
13
+
14
+ export const BOARD_CARD_WIDTH = 246;
15
+ export const BOARD_COLUMN_WIDTH = 268;
16
+ export const BOARD_CARD_GAP = 8;
17
+ export const BOARD_COLUMN_HEADER_HEIGHT = 36;
18
+
19
+ /** Record page is two panes: a resizable left panel plus main content. */
20
+ export const RECORD_PANEL_MIN_WIDTH = 320;
21
+ export const RECORD_MAIN_MIN_WIDTH = 350;
22
+
23
+ /** Milliseconds, mirroring --motion-* in global.css. Use these only for JS
24
+ * timers; anything CSS can express should use the vars instead. */
25
+ export const MOTION = {
26
+ fast: 80,
27
+ comfortable: 140,
28
+ breezy: 200,
29
+ sluggish: 300,
30
+ sloth: 400,
31
+ } as const;
32
+
33
+ /** Cell selection ring geometry. The ring overlaps the shared 1px divider on
34
+ * three sides so a range reads as one outline rather than a double line. */
35
+ export const SELECTION_RING_INSET = "-1px -1px -1px 0";
36
+
37
+ export interface OverlayOptions {
38
+ selected?: boolean;
39
+ /** Cells: select with the content color at 8% instead of the accent at 10%,
40
+ * because the row underneath already carries the accent tint. */
41
+ soft?: boolean;
42
+ className?: string;
43
+ }
44
+
45
+ /**
46
+ * The one hover/selection implementation. Returns the overlay class plus the
47
+ * state attribute it keys off; spread it onto the row, cell, or card.
48
+ */
49
+ export function overlayProps(options: OverlayOptions = {}): {
50
+ className: string;
51
+ "data-selected"?: "true";
52
+ } {
53
+ return {
54
+ className: [
55
+ "crm-overlay",
56
+ options.soft && "crm-overlay-soft",
57
+ options.className,
58
+ ]
59
+ .filter(Boolean)
60
+ .join(" "),
61
+ ...(options.selected ? { "data-selected": "true" as const } : {}),
62
+ };
63
+ }
64
+
65
+ export interface SelectionEdges {
66
+ top: boolean;
67
+ right: boolean;
68
+ bottom: boolean;
69
+ left: boolean;
70
+ }
71
+
72
+ /**
73
+ * A selected range is drawn per cell, so a corner may only round where the two
74
+ * border segments that form it are both present. Rounding by cell position
75
+ * instead of by edge pair is the usual bug: it rounds interior corners that
76
+ * have no visible border and the range reads as loose tiles.
77
+ */
78
+ export function selectionCornerRadius(
79
+ edges: SelectionEdges,
80
+ radius = 4,
81
+ ): string {
82
+ const corner = (a: boolean, b: boolean) => (a && b ? `${radius}px` : "0");
83
+ return [
84
+ corner(edges.top, edges.left),
85
+ corner(edges.top, edges.right),
86
+ corner(edges.bottom, edges.right),
87
+ corner(edges.bottom, edges.left),
88
+ ].join(" ");
89
+ }
@@ -40,6 +40,55 @@
40
40
  --sidebar-accent-foreground: 0 0% 15%;
41
41
  --sidebar-border: 0 0% 90%;
42
42
  --sidebar-ring: 0 0% 40%;
43
+
44
+ /* --- CRM surface tokens -------------------------------------------------
45
+ Geometry for the grid/record/board surfaces. Utilities generated from
46
+ these live in the `@theme inline` block below; the raw vars here exist for
47
+ `calc()`, virtualizer math, and arbitrary values. */
48
+
49
+ /* Fixed grid metrics. There is no density toggle: rows are always 36px. */
50
+ --crm-row-h: 36px;
51
+ --crm-header-h: 40px;
52
+ --crm-cell-px: 12px;
53
+ --crm-cell-pt: 8px;
54
+
55
+ /* Hairline used on BOTH grid axes. Near-invisible by design — a divider you
56
+ can read at a glance is already too dark. */
57
+ --crm-hairline: hsl(var(--foreground) / 0.07);
58
+
59
+ /* Overlay alphas. Hover and selection animate this OPACITY on a dedicated
60
+ layer; they never swap background-color (see `.crm-overlay`). */
61
+ --crm-overlay-hover: 0.04;
62
+ --crm-overlay-hover-strong: 0.08;
63
+ --crm-overlay-selected: 0.1;
64
+
65
+ /* The single knob for "selected/active" tint. Our skin has no brand hue, so
66
+ selection derives from --primary; repoint this one var if that changes. */
67
+ --crm-accent: var(--primary);
68
+
69
+ /* Shadows are blue-black, never neutral grey, and always carry a hairline
70
+ ring in the same stack so elevation and outline can never disagree. */
71
+ --crm-shadow: 219 39% 18%;
72
+ --crm-shadow-sticky: 6px 0 16px 4px hsl(var(--crm-shadow) / 0.12);
73
+ --crm-elevation-1:
74
+ 0 0 0 1px hsl(var(--crm-shadow) / 0.06),
75
+ 0 1px 2px -1px hsl(var(--crm-shadow) / 0.1);
76
+ --crm-elevation-2:
77
+ 0 0 0 1px hsl(var(--crm-shadow) / 0.06),
78
+ 0 4px 12px -2px hsl(var(--crm-shadow) / 0.12),
79
+ 0 2px 4px -2px hsl(var(--crm-shadow) / 0.08);
80
+ --crm-elevation-3:
81
+ 0 0 0 1px hsl(var(--crm-shadow) / 0.05),
82
+ 0 16px 40px -8px hsl(var(--crm-shadow) / 0.2),
83
+ 0 4px 10px -4px hsl(var(--crm-shadow) / 0.1);
84
+
85
+ /* Motion scale. --motion-comfortable is the app default (see
86
+ --default-transition-duration). Zeroed under prefers-reduced-motion. */
87
+ --motion-fast: 80ms;
88
+ --motion-comfortable: 140ms;
89
+ --motion-breezy: 200ms;
90
+ --motion-sluggish: 300ms;
91
+ --motion-sloth: 400ms;
43
92
  }
44
93
 
45
94
  .dark {
@@ -76,6 +125,61 @@
76
125
  --sidebar-accent-foreground: 0 0% 90%;
77
126
  --sidebar-border: 0 0% 20%;
78
127
  --sidebar-ring: 0 0% 60%;
128
+
129
+ /* Dark dividers stay subtractive — a line darker than the surface, not a
130
+ lighter one. An alpha-white hairline here reads as a seam, not a grid. */
131
+ --crm-hairline: hsl(0 0% 0% / 0.16);
132
+ --crm-shadow: 219 45% 6%;
133
+ --crm-shadow-sticky: 6px 0 16px 4px hsl(var(--crm-shadow) / 0.4);
134
+ --crm-elevation-1:
135
+ 0 0 0 1px hsl(0 0% 100% / 0.06), 0 1px 2px -1px hsl(var(--crm-shadow) / 0.5);
136
+ --crm-elevation-2:
137
+ 0 0 0 1px hsl(0 0% 100% / 0.06),
138
+ 0 4px 12px -2px hsl(var(--crm-shadow) / 0.55),
139
+ 0 2px 4px -2px hsl(var(--crm-shadow) / 0.4);
140
+ --crm-elevation-3:
141
+ 0 0 0 1px hsl(0 0% 100% / 0.05),
142
+ 0 16px 40px -8px hsl(var(--crm-shadow) / 0.65),
143
+ 0 4px 10px -4px hsl(var(--crm-shadow) / 0.45);
144
+ }
145
+
146
+ /* `inline` so every value resolves against the element's own cascade — that is
147
+ what lets one utility follow --foreground/--crm-shadow across light/dark. */
148
+ @theme inline {
149
+ /* Radii, by the thing they wrap. `rounded-lg` (8px) already covers buttons
150
+ and menu items, so it is not restated here. */
151
+ --radius-badge: 4px;
152
+ --radius-chip: 10px;
153
+ --radius-row: 11px;
154
+ --radius-card: 12px;
155
+ --radius-column: 16px;
156
+ --radius-panel: 20px;
157
+ --radius-avatar-company: 30%;
158
+
159
+ /* Content ramp: alpha over the surface, never solid greys, so text
160
+ composites correctly on tinted cells and hover overlays. */
161
+ --color-content-secondary: hsl(var(--foreground) / 0.63);
162
+ --color-content-tertiary: hsl(var(--foreground) / 0.5);
163
+ --color-content-ghost: hsl(var(--foreground) / 0.38);
164
+ --color-hairline: var(--crm-hairline);
165
+
166
+ --shadow-e1: var(--crm-elevation-1);
167
+ --shadow-e2: var(--crm-elevation-2);
168
+ --shadow-e3: var(--crm-elevation-3);
169
+
170
+ --tracking-ui: -0.02em;
171
+ --tracking-body: -0.01em;
172
+
173
+ /* 400/500/600 only. Capping the weight namespace means a stray `font-bold`
174
+ anywhere in the app renders 600 instead of shipping a heavier voice. */
175
+ --font-weight-bold: 600;
176
+ --font-weight-extrabold: 600;
177
+ --font-weight-black: 600;
178
+
179
+ /* Makes every bare `transition-*` in the app 140ms without touching a
180
+ component. Named steps stay available as duration-[var(--motion-*)]. */
181
+ --default-transition-duration: var(--motion-comfortable);
182
+ --ease-drop: cubic-bezier(0.45, 0, 0.2, 1);
79
183
  }
80
184
 
81
185
  @layer base {
@@ -87,6 +191,72 @@
87
191
  @apply bg-background text-foreground;
88
192
  font-family: "Inter Variable", Inter, sans-serif;
89
193
  font-feature-settings: "cv02", "cv03", "cv04", "cv11";
194
+ letter-spacing: var(--tracking-ui);
195
+ }
196
+ /* Body and caption sizes ride a touch looser than the -0.02em UI default.
197
+ Zero specificity, so any `tracking-*` utility still wins. */
198
+ :where(p, small, figcaption, .text-sm, .text-xs) {
199
+ letter-spacing: var(--tracking-body);
200
+ }
201
+ :where(b, strong) {
202
+ font-weight: 600;
203
+ }
204
+ }
205
+
206
+ @layer components {
207
+ /* Hover/selection primitive. The overlay is a real layer whose OPACITY
208
+ animates; swapping background-color instead loses the composite over
209
+ tinted cells and cannot cross-fade. Host may be static or positioned —
210
+ Tailwind's position utilities sit in a later layer and still win. */
211
+ .crm-overlay {
212
+ position: relative;
213
+ isolation: isolate;
214
+ }
215
+ .crm-overlay::before {
216
+ content: "";
217
+ position: absolute;
218
+ inset: 0;
219
+ z-index: -1;
220
+ border-radius: inherit;
221
+ pointer-events: none;
222
+ background: hsl(var(--foreground));
223
+ opacity: 0;
224
+ transition:
225
+ opacity var(--motion-comfortable) ease-in-out,
226
+ background-color var(--motion-comfortable) ease-in-out;
227
+ }
228
+ .crm-overlay:hover::before,
229
+ .crm-overlay[data-hovered="true"]::before {
230
+ opacity: var(--crm-overlay-hover);
231
+ }
232
+ .crm-overlay[data-selected="true"]::before {
233
+ background: hsl(var(--crm-accent));
234
+ opacity: var(--crm-overlay-selected);
235
+ }
236
+ /* Cells select without the accent tint — the row already carries it. */
237
+ .crm-overlay-soft[data-selected="true"]::before {
238
+ background: hsl(var(--foreground));
239
+ opacity: var(--crm-overlay-hover-strong);
240
+ }
241
+ }
242
+
243
+ @media (prefers-reduced-motion: reduce) {
244
+ :root {
245
+ --motion-fast: 0ms;
246
+ --motion-comfortable: 0ms;
247
+ --motion-breezy: 0ms;
248
+ --motion-sluggish: 0ms;
249
+ --motion-sloth: 0ms;
250
+ }
251
+ /* Zeroing the vars only covers what opts into them. 0.01ms rather than 0 so
252
+ transitionend/animationend still fire for components that unmount on them. */
253
+ *,
254
+ *::before,
255
+ *::after {
256
+ animation-duration: 0.01ms !important;
257
+ animation-iteration-count: 1 !important;
258
+ transition-duration: 0.01ms !important;
259
+ scroll-behavior: auto !important;
90
260
  }
91
261
  }
92
262
 
@@ -358,6 +358,7 @@ const messages = {
358
358
  },
359
359
  },
360
360
  record: {
361
+ resizePanel: "Resize panel",
361
362
  loadFailedTitle: "This record could not be loaded",
362
363
  loadFailedDescription:
363
364
  "CRM could not read this record. It may be outside the records you can access.",
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-26
4
+ ---
5
+
6
+ A half-typed number or date no longer saves as empty — the field says it cannot read the value and keeps what the record already had.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-26
4
+ ---
5
+
6
+ A new pipeline board now opens with stage columns, a summable amount, and each card's values copied from the record it was added from
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: added
3
+ date: 2026-07-26
4
+ ---
5
+
6
+ Record reference fields like Account can now be linked from the record page: search records in a popover and see the link as a chip you can remove.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-26
4
+ ---
5
+
6
+ Retyping a record field now replaces the old value instead of appending to it, wherever the field is edited.
@@ -1,6 +1,8 @@
1
+ import { getOrgContext } from "@agent-native/core/org";
1
2
  import {
2
3
  FeatureNotConfiguredError,
3
4
  getSession,
5
+ runWithRequestContext,
4
6
  startBuilderDesignSystemIndex,
5
7
  } from "@agent-native/core/server";
6
8
  import {
@@ -89,28 +91,43 @@ export const indexDesignSystemWithBuilder = defineEventHandler(
89
91
  .replace(/[-_]+/g, " ")
90
92
  .trim() || "Imported brand";
91
93
 
94
+ // `session.orgId` is set at sign-in and not refreshed when the user
95
+ // switches orgs; `getOrgContext` resolves the live active-org setting.
96
+ let orgId: string | undefined;
92
97
  try {
93
- const result = await startBuilderDesignSystemIndex({
94
- projectName: suggestedTitle,
95
- files: [
96
- {
97
- name: filename,
98
- data: part.data,
99
- mimeType: "application/octet-stream",
100
- },
101
- ],
102
- });
103
- const proxy = await upsertBuilderProxyDesignSystem({
104
- result,
105
- ownerEmail: session.email,
106
- orgId: session.orgId ?? null,
107
- projectName: suggestedTitle,
108
- });
109
- return {
110
- ...result,
111
- ...proxy,
112
- uploadedFileCount: 1,
113
- };
98
+ orgId = (await getOrgContext(event)).orgId ?? undefined;
99
+ } catch {
100
+ // Org tables can be unavailable during first boot; fall back below.
101
+ }
102
+ orgId ??= session.orgId ?? undefined;
103
+
104
+ try {
105
+ return await runWithRequestContext(
106
+ { userEmail: session.email, orgId },
107
+ async () => {
108
+ const result = await startBuilderDesignSystemIndex({
109
+ projectName: suggestedTitle,
110
+ files: [
111
+ {
112
+ name: filename,
113
+ data: part.data,
114
+ mimeType: "application/octet-stream",
115
+ },
116
+ ],
117
+ });
118
+ const proxy = await upsertBuilderProxyDesignSystem({
119
+ result,
120
+ ownerEmail: session.email,
121
+ orgId: orgId ?? null,
122
+ projectName: suggestedTitle,
123
+ });
124
+ return {
125
+ ...result,
126
+ ...proxy,
127
+ uploadedFileCount: 1,
128
+ };
129
+ },
130
+ );
114
131
  } catch (err) {
115
132
  if (err instanceof FeatureNotConfiguredError) {
116
133
  setResponseStatus(event, 412);
@@ -11,6 +11,7 @@ import {
11
11
  } from "h3";
12
12
 
13
13
  import { upsertBuilderProxyDesignSystem } from "../lib/builder-design-system-proxy.js";
14
+ import { withSlidesRequestContext } from "./request-auth-context.js";
14
15
 
15
16
  const MAX_FIG_BYTES = 200 * 1024 * 1024;
16
17
  const MULTIPART_OVERHEAD_BYTES = 1024 * 1024;
@@ -72,27 +73,29 @@ export const indexDesignSystemWithBuilder = defineEventHandler(
72
73
  .trim() || "Imported brand";
73
74
 
74
75
  try {
75
- const result = await startBuilderDesignSystemIndex({
76
- projectName: suggestedTitle,
77
- files: [
78
- {
79
- name: part.filename || "brand.fig",
80
- data: part.data,
81
- mimeType: "application/octet-stream",
82
- },
83
- ],
84
- });
85
- const proxy = await upsertBuilderProxyDesignSystem({
86
- result,
87
- ownerEmail: session.email,
88
- orgId: session.orgId ?? null,
89
- projectName: suggestedTitle,
76
+ return await withSlidesRequestContext(event, async ({ orgId }) => {
77
+ const result = await startBuilderDesignSystemIndex({
78
+ projectName: suggestedTitle,
79
+ files: [
80
+ {
81
+ name: part.filename || "brand.fig",
82
+ data: part.data,
83
+ mimeType: "application/octet-stream",
84
+ },
85
+ ],
86
+ });
87
+ const proxy = await upsertBuilderProxyDesignSystem({
88
+ result,
89
+ ownerEmail: session.email,
90
+ orgId: orgId ?? null,
91
+ projectName: suggestedTitle,
92
+ });
93
+ return {
94
+ ...result,
95
+ ...proxy,
96
+ uploadedFileCount: 1,
97
+ };
90
98
  });
91
- return {
92
- ...result,
93
- ...proxy,
94
- uploadedFileCount: 1,
95
- };
96
99
  } catch (err) {
97
100
  if (err instanceof FeatureNotConfiguredError) {
98
101
  setResponseStatus(event, 412);
@@ -62,11 +62,11 @@ export declare const postAwareness: import("h3").EventHandlerWithFetch<import("h
62
62
  error: string;
63
63
  states?: undefined;
64
64
  } | {
65
- error?: undefined;
66
65
  states: {
67
66
  clientId: number;
68
67
  state: string;
69
68
  }[];
69
+ error?: undefined;
70
70
  }>>;
71
71
  /**
72
72
  * GET /_agent-native/collab/:docId/users
@@ -77,10 +77,10 @@ export declare const getActiveUsers: import("h3").EventHandlerWithFetch<import("
77
77
  error: string;
78
78
  users?: undefined;
79
79
  } | {
80
- error?: undefined;
81
80
  users: {
82
81
  clientId: number;
83
82
  lastSeen: number;
84
83
  }[];
84
+ error?: undefined;
85
85
  }>>;
86
86
  //# sourceMappingURL=awareness.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"awareness.d.ts","sourceRoot":"","sources":["../../src/collab/awareness.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAgB3C,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAOD,eAAO,MAAM,sBAAsB,EAAG,kBAA2B,CAAC;AAElE,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,WAAW,CAAC;IACpB,IAAI,EAAE,kBAAkB,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,MAAM,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACnD,gFAAgF;IAChF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sCAAsC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2EAA2E;IAC3E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,yEAAyE;IACzE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAOD,wBAAgB,mBAAmB,IAAI,YAAY,CAElD;AAED,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,cAAc,GAAG,SAAS,GAChC,IAAI,CAON;AAED,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,KAAK,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,EAClD,KAAK,CAAC,EAAE,cAAc,GACrB,IAAI,CAgBN;AAoBD,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,SAAS,GAAE,MAAmB,GAC7B,IAAI,CAON;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAE1E;AAiBD,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAO1E;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,GAAG,IAAI,CAOnE;AAkCD;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa;;;;;;kBAwDa,MAAM;eAAS,MAAM;;GAoB1D,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,cAAc;;;;;;kBAYM,MAAM;kBAAY,MAAM;;GAMvD,CAAC"}
1
+ {"version":3,"file":"awareness.d.ts","sourceRoot":"","sources":["../../src/collab/awareness.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAgB3C,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAOD,eAAO,MAAM,sBAAsB,EAAG,kBAA2B,CAAC;AAElE,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,WAAW,CAAC;IACpB,IAAI,EAAE,kBAAkB,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,MAAM,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACnD,gFAAgF;IAChF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sCAAsC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2EAA2E;IAC3E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,yEAAyE;IACzE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAOD,wBAAgB,mBAAmB,IAAI,YAAY,CAElD;AAED,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,cAAc,GAAG,SAAS,GAChC,IAAI,CAON;AAED,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,KAAK,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,EAClD,KAAK,CAAC,EAAE,cAAc,GACrB,IAAI,CAgBN;AAoBD,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,SAAS,GAAE,MAAmB,GAC7B,IAAI,CAON;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAE1E;AAiBD,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAO1E;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,GAAG,IAAI,CAOnE;AAkCD;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa;;;;;kBAwDa,MAAM;eAAS,MAAM;;;GAoB1D,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,cAAc;;;;;kBAYM,MAAM;kBAAY,MAAM;;;GAMvD,CAAC"}
@@ -41,9 +41,9 @@ export declare const postCollabUpdate: import("h3").EventHandlerWithFetch<import
41
41
  * Body: { text: string, fieldName?: string, requestSource?: string }
42
42
  */
43
43
  export declare const postCollabText: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
44
- text?: undefined;
45
44
  ok?: undefined;
46
45
  error: string;
46
+ text?: undefined;
47
47
  } | {
48
48
  error?: undefined;
49
49
  ok: boolean;
@@ -17,12 +17,12 @@ declare const _default: import("../../action.js").ActionDefinition<{
17
17
  id?: undefined;
18
18
  provider?: undefined;
19
19
  } | {
20
+ error?: undefined;
20
21
  configured?: undefined;
21
22
  connectPath?: undefined;
22
23
  url: string;
23
24
  id: string;
24
25
  provider: string;
25
- error?: undefined;
26
26
  }>;
27
27
  export default _default;
28
28
  //# sourceMappingURL=upload-image.d.ts.map
@@ -13,13 +13,13 @@
13
13
  export declare function createNotificationsHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<"" | import("./types.js").Notification[] | {
14
14
  count: number;
15
15
  updated?: undefined;
16
- error?: undefined;
17
16
  ok?: undefined;
17
+ error?: undefined;
18
18
  } | {
19
19
  count?: undefined;
20
20
  updated: number;
21
- error?: undefined;
22
21
  ok?: undefined;
22
+ error?: undefined;
23
23
  } | {
24
24
  count?: undefined;
25
25
  updated?: undefined;
@@ -28,7 +28,7 @@ export declare function createNotificationsHandler(): import("h3").EventHandlerW
28
28
  } | {
29
29
  count?: undefined;
30
30
  updated?: undefined;
31
- error?: undefined;
32
31
  ok: boolean;
32
+ error?: undefined;
33
33
  }>>;
34
34
  //# sourceMappingURL=routes.d.ts.map
@@ -41,16 +41,16 @@ export declare function createObservabilityHandler(): import("h3").EventHandlerW
41
41
  thumbsUpRate: number;
42
42
  avgEvalScore: number;
43
43
  } | {
44
- error?: undefined;
45
44
  summary: import("./types.js").TraceSummary;
46
45
  spans: import("./types.js").TraceSpan[];
47
46
  id?: undefined;
47
+ error?: undefined;
48
48
  ok?: undefined;
49
49
  } | {
50
- error?: undefined;
51
50
  summary?: undefined;
52
51
  spans?: undefined;
53
52
  id: string;
53
+ error?: undefined;
54
54
  ok?: undefined;
55
55
  } | {
56
56
  summary?: undefined;
@@ -59,10 +59,10 @@ export declare function createObservabilityHandler(): import("h3").EventHandlerW
59
59
  error: any;
60
60
  ok?: undefined;
61
61
  } | {
62
- error?: undefined;
63
62
  summary?: undefined;
64
63
  spans?: undefined;
65
64
  id?: undefined;
66
65
  ok: boolean;
66
+ error?: undefined;
67
67
  }>>;
68
68
  //# sourceMappingURL=routes.d.ts.map
@@ -49,8 +49,8 @@ export declare function handleUpdateResource(event: any): Promise<import("./stor
49
49
  }>;
50
50
  /** DELETE /_agent-native/resources/:id — delete a resource */
51
51
  export declare function handleDeleteResource(event: any): Promise<{
52
- error: string;
53
52
  ok?: undefined;
53
+ error: string;
54
54
  } | {
55
55
  error?: undefined;
56
56
  ok: boolean;