@agent-native/core 0.185.0-nightly-20260923150956 → 0.185.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/corpus/templates/analytics/CHANGELOG.md +6 -0
  2. package/corpus/templates/brain/CHANGELOG.md +6 -0
  3. package/corpus/templates/calendar/CHANGELOG.md +11 -0
  4. package/corpus/templates/clips/CHANGELOG.md +37 -0
  5. package/corpus/templates/content/CHANGELOG.md +6 -0
  6. package/corpus/templates/design/CHANGELOG.md +9 -0
  7. package/corpus/templates/design/actions/get-design-system-index-status.ts +2 -5
  8. package/corpus/templates/design/actions/get-design-system.ts +6 -3
  9. package/corpus/templates/design/actions/list-design-systems.ts +53 -1
  10. package/corpus/templates/design/app/components/editor/design-start-pickers.tsx +10 -0
  11. package/corpus/templates/design/app/i18n-data.ts +10 -0
  12. package/corpus/templates/design/app/lib/design-system-data.ts +13 -10
  13. package/corpus/templates/design/app/pages/DesignSystems.tsx +11 -8
  14. package/corpus/templates/design/app/pages/Templates.tsx +6 -1
  15. package/corpus/templates/design/changelog/2026-09-22-fixed-the-design-system-picker-showing-a-still-indexing-buil.md +6 -0
  16. package/corpus/templates/design/server/lib/builder-design-system-proxy.ts +11 -30
  17. package/corpus/templates/mail/CHANGELOG.md +5 -0
  18. package/corpus/templates/slides/CHANGELOG.md +13 -0
  19. package/corpus/templates/slides/actions/apply-design-system.ts +2 -22
  20. package/corpus/templates/slides/actions/create-deck.ts +4 -54
  21. package/corpus/templates/slides/actions/get-design-system.ts +40 -3
  22. package/corpus/templates/slides/actions/list-design-systems.ts +26 -11
  23. package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +16 -23
  24. package/corpus/templates/slides/app/components/editor/NewDeckReferenceStep.tsx +14 -51
  25. package/corpus/templates/slides/app/hooks/use-design-systems.ts +1 -191
  26. package/corpus/templates/slides/app/i18n/en-US.ts +0 -4
  27. package/corpus/templates/slides/app/lib/design-system-selection.ts +4 -19
  28. package/corpus/templates/slides/app/pages/Index.tsx +3 -16
  29. package/corpus/templates/slides/shared/design-system-validation.ts +16 -18
  30. package/dist/automation/index.d.ts +1 -1
  31. package/dist/collab/routes.d.ts +1 -1
  32. package/dist/collab/struct-routes.d.ts +1 -1
  33. package/dist/secrets/routes.d.ts +3 -3
  34. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  35. package/dist/server/builder-design-systems.d.ts +23 -1
  36. package/dist/server/builder-design-systems.js +58 -17
  37. package/dist/server/index.d.ts +1 -1
  38. package/dist/server/index.js +1 -1
  39. package/dist/server/realtime-token.d.ts +1 -1
  40. package/dist/server/transcribe-voice.d.ts +1 -1
  41. package/docs/content/toolkit-settings.mdx +32 -0
  42. package/package.json +4 -4
  43. package/corpus/templates/slides/actions/refresh-design-system-indexing-status.ts +0 -120
@@ -1,39 +1,4 @@
1
- import { callAction, useActionQuery } from "@agent-native/core/client/hooks";
2
- import {
3
- createPollEngine,
4
- type PollEngineHandle,
5
- } from "@agent-native/core/shared";
6
- import { useEffect, useRef } from "react";
7
-
8
- import type { DesignSystemIndexingStatus } from "../../shared/design-system-validation";
9
-
10
- // Per-id backoff for `refresh-design-system-indexing-status`. A design
11
- // system stuck in "indexing" (Builder never confirms completion) used to be
12
- // checked on a fixed 5s cadence forever — in production, a handful of stuck
13
- // systems in one tab produced tens of thousands of calls over a few hours.
14
- // Doubling the delay each unconfirmed check, up to a cap, keeps a live check
15
- // prompt while bounding the worst case.
16
- const INDEXING_POLL_INITIAL_DELAY_MS = 5_000;
17
- const INDEXING_POLL_MAX_DELAY_MS = 5 * 60_000;
18
- // A row that still hasn't confirmed after this long is treated the same as
19
- // the server's own `stale` response (see refresh-design-system-indexing-
20
- // status): stop polling it locally. This only matters when the action call
21
- // itself keeps failing (so we never receive a `stale` response to act on) —
22
- // the server-computed staleness is the primary backstop.
23
- const INDEXING_POLL_BUDGET_MS = 30 * 60_000;
24
- const INDEXING_POLL_TIMEOUT_MS = 30_000;
25
-
26
- interface IndexingPollState {
27
- delayMs: number;
28
- nextDueAt: number;
29
- firstSeenAt: number;
30
- }
31
-
32
- type RefreshIndexingStatusResult = {
33
- updated?: boolean;
34
- stale?: boolean;
35
- indexingStatus?: DesignSystemIndexingStatus;
36
- };
1
+ import { useActionQuery } from "@agent-native/core/client/hooks";
37
2
 
38
3
  type DesignSystemSummary = {
39
4
  id: string;
@@ -45,7 +10,6 @@ type DesignSystemSummary = {
45
10
  accessRole?: "owner" | "admin" | "editor" | "commenter" | "viewer";
46
11
  canManage?: boolean;
47
12
  createdAt: string;
48
- indexingStatus?: DesignSystemIndexingStatus;
49
13
  };
50
14
 
51
15
  export function useDesignSystems() {
@@ -55,160 +19,6 @@ export function useDesignSystems() {
55
19
 
56
20
  const designSystems: DesignSystemSummary[] = data?.designSystems ?? [];
57
21
  const defaultSystem = designSystems.find((ds) => ds.isDefault);
58
- const indexingIdsKey = designSystems
59
- .filter((ds) => ds.indexingStatus === "indexing")
60
- .map((ds) => ds.id)
61
- .join(",");
62
-
63
- const refetchRef = useRef(refetch);
64
- refetchRef.current = refetch;
65
- const scheduleRef = useRef(new Map<string, IndexingPollState>());
66
- const engineRef = useRef<PollEngineHandle | null>(null);
67
-
68
- // `list-design-systems` only reads the status persisted at index/sync time,
69
- // which never advances past "indexing" on its own once Builder actually
70
- // finishes (or fails) — see refresh-design-system-indexing-status. Keep
71
- // checking only those rows, at a per-id backoff, until the list reports a
72
- // terminal state. A variable cadence needs createPollEngine directly, not
73
- // usePollLoop (whose public intervalMs is a fixed number) — see
74
- // use-run-stuck-detection.ts for the same pattern. Created once so an id
75
- // being added or removed from the indexing set (below) doesn't reset the
76
- // backoff already earned by the others.
77
- useEffect(() => {
78
- const attempt = async (signal: AbortSignal) => {
79
- const now = Date.now();
80
- const due = Array.from(scheduleRef.current.entries()).filter(
81
- ([, state]) => state.nextDueAt <= now,
82
- );
83
- if (due.length === 0) return;
84
-
85
- let anyUpdated = false;
86
- await Promise.all(
87
- due.map(async ([id, state]) => {
88
- let result: RefreshIndexingStatusResult | null = null;
89
- try {
90
- result = await callAction(
91
- "refresh-design-system-indexing-status",
92
- { id },
93
- { signal },
94
- );
95
- } catch (err) {
96
- // `result` stays null (distinct from a real response) and falls
97
- // through to the same backoff as an unconfirmed response below.
98
- // Leaving nextDueAt unmoved here would make a persistent failure
99
- // (revoked access, an outage) retry on every tick instead of
100
- // backing off.
101
- console.error(
102
- `Failed to refresh indexing status for design system ${id}:`,
103
- err,
104
- );
105
- }
106
- // A CONFIRMED terminal indexingStatus is also a done signal even
107
- // when `updated` is false — another writer (a second tab, an
108
- // agent) already persisted it. Without this, that id kept
109
- // re-checking every backoff step, showing "indexing" until the
110
- // 30-minute budget ran out instead of picking up the already-saved
111
- // result. A missing field (not the same as a confirmed "indexing")
112
- // falls through to the unconfirmed path below rather than being
113
- // read as terminal.
114
- if (
115
- result?.updated ||
116
- (result?.indexingStatus !== undefined &&
117
- result.indexingStatus !== "indexing")
118
- ) {
119
- anyUpdated = true;
120
- scheduleRef.current.delete(id);
121
- return;
122
- }
123
- // Re-read the clock instead of reusing the outer `now`: a focus
124
- // reset (below) can rewrite this same state object in place while
125
- // this call was in flight, and anchoring to a stale start time
126
- // would fight that reset instead of building on it.
127
- const settledAt = Date.now();
128
- if (
129
- result?.stale ||
130
- settledAt - state.firstSeenAt > INDEXING_POLL_BUDGET_MS
131
- ) {
132
- // The server confirmed this row hasn't moved in a long time, or
133
- // we've been unable to confirm either way for the whole budget.
134
- // Stop polling it — the persisted status is untouched and still
135
- // truthfully reads "indexing", it's just no longer worth
136
- // checking on a fixed cadence.
137
- scheduleRef.current.delete(id);
138
- return;
139
- }
140
- // Use the current delay for this wait, then double it for the
141
- // next one — so the first re-check lands at the initial delay
142
- // instead of already doubled.
143
- state.nextDueAt = settledAt + state.delayMs;
144
- state.delayMs = Math.min(
145
- state.delayMs * 2,
146
- INDEXING_POLL_MAX_DELAY_MS,
147
- );
148
- }),
149
- );
150
- if (anyUpdated) void refetchRef.current();
151
- };
152
-
153
- const engine = createPollEngine(attempt, {
154
- intervalMs: () => {
155
- const now = Date.now();
156
- let minDelay = INDEXING_POLL_MAX_DELAY_MS;
157
- for (const state of scheduleRef.current.values()) {
158
- minDelay = Math.min(minDelay, Math.max(0, state.nextDueAt - now));
159
- }
160
- return minDelay;
161
- },
162
- timeoutMs: INDEXING_POLL_TIMEOUT_MS,
163
- // Nothing to check until the sync effect below populates a first id.
164
- leading: false,
165
- });
166
- engineRef.current = engine;
167
- engine.start();
168
-
169
- return () => {
170
- engine.stop();
171
- engineRef.current = null;
172
- };
173
- }, []);
174
-
175
- // Add newly-seen ids (fresh budget, immediate check) and drop ids the list
176
- // no longer reports as indexing. Existing entries keep their backoff.
177
- useEffect(() => {
178
- const now = Date.now();
179
- const active = new Set(indexingIdsKey ? indexingIdsKey.split(",") : []);
180
- let addedNew = false;
181
- for (const id of scheduleRef.current.keys()) {
182
- if (!active.has(id)) scheduleRef.current.delete(id);
183
- }
184
- for (const id of active) {
185
- if (!scheduleRef.current.has(id)) {
186
- scheduleRef.current.set(id, {
187
- delayMs: INDEXING_POLL_INITIAL_DELAY_MS,
188
- nextDueAt: now,
189
- firstSeenAt: now,
190
- });
191
- addedNew = true;
192
- }
193
- }
194
- if (addedNew) engineRef.current?.pollNow();
195
- }, [indexingIdsKey]);
196
-
197
- // A tab that was away for a while (and so backed off toward the 5 min cap)
198
- // deserves a prompt recheck once the user actually comes back to it.
199
- useEffect(() => {
200
- const onFocus = () => {
201
- const now = Date.now();
202
- for (const state of scheduleRef.current.values()) {
203
- state.delayMs = INDEXING_POLL_INITIAL_DELAY_MS;
204
- state.nextDueAt = now;
205
- state.firstSeenAt = now;
206
- }
207
- engineRef.current?.pollNow();
208
- };
209
- window.addEventListener("focus", onFocus);
210
- return () => window.removeEventListener("focus", onFocus);
211
- }, []);
212
22
 
213
23
  return { designSystems, defaultSystem, isLoading, error, refetch };
214
24
  }
@@ -826,10 +826,6 @@ const messages = {
826
826
  continue: "Continue",
827
827
  continueToGenerate: "Continue to generate",
828
828
  designSystem: "Design system",
829
- designSystemIndexing: "Indexing…",
830
- designSystemUnavailable: "Unavailable",
831
- designSystemIndexingNotice:
832
- "This design system is still indexing. Choose another one or wait for indexing to finish before continuing.",
833
829
  referenceDeck: "Reference deck",
834
830
  referenceDeckPlaceholder: "Match the style of an existing deck",
835
831
  referenceDeckNone: "Skip",
@@ -1,31 +1,16 @@
1
- import type { DesignSystemIndexingStatus } from "../../shared/design-system-validation";
2
-
3
1
  export interface SelectableDesignSystem {
4
2
  id: string;
5
- indexingStatus?: DesignSystemIndexingStatus;
6
- }
7
-
8
- /** A design system with no usable tokens/components yet must not be picked for generation. */
9
- export function isDesignSystemSelectable(
10
- designSystem: Pick<SelectableDesignSystem, "indexingStatus">,
11
- ): boolean {
12
- return (
13
- designSystem.indexingStatus !== "indexing" &&
14
- designSystem.indexingStatus !== "unavailable"
15
- );
16
3
  }
17
4
 
18
5
  /**
19
- * Drops a candidate default/last-used id when it now points at a design
20
- * system that isn't selectable, instead of silently pre-selecting one the
21
- * picker would immediately have to reject.
6
+ * Drops a candidate default/last-used id when it no longer points at a
7
+ * design system in the current list, instead of silently pre-selecting one
8
+ * the picker would immediately have to reject.
22
9
  */
23
10
  export function resolveSelectableDesignSystemId(
24
11
  designSystems: SelectableDesignSystem[],
25
12
  candidateId: string | null | undefined,
26
13
  ): string | null {
27
14
  if (!candidateId) return null;
28
- const match = designSystems.find((ds) => ds.id === candidateId);
29
- if (!match) return null;
30
- return isDesignSystemSelectable(match) ? candidateId : null;
15
+ return designSystems.some((ds) => ds.id === candidateId) ? candidateId : null;
31
16
  }
@@ -83,10 +83,7 @@ import {
83
83
  } from "@/lib/deck-filter";
84
84
  import { deckListViewState } from "@/lib/deck-list-loading";
85
85
  import { sortDecksByRecency } from "@/lib/deck-sorting";
86
- import {
87
- isDesignSystemSelectable,
88
- resolveSelectableDesignSystemId,
89
- } from "@/lib/design-system-selection";
86
+ import { resolveSelectableDesignSystemId } from "@/lib/design-system-selection";
90
87
  import {
91
88
  IMPORT_ACTION_TIMEOUT_MS,
92
89
  importUploadedDeckIntoDeck,
@@ -427,24 +424,14 @@ export default function Index() {
427
424
  defaultSystem?.id,
428
425
  );
429
426
  const workspaceDesignSystemId =
430
- workspaceDesignSystem &&
431
- workspaceDesignSystem.status === "available" &&
432
- designSystems.some(
433
- (designSystem) =>
434
- designSystem.id === workspaceDesignSystem.id &&
435
- isDesignSystemSelectable(designSystem),
436
- )
427
+ workspaceDesignSystem && workspaceDesignSystem.status === "available"
437
428
  ? workspaceDesignSystem.id
438
429
  : null;
439
430
  const lastUsedDesignSystemId =
440
431
  recentReferences.find(
441
432
  (reference) =>
442
433
  reference.kind === "design-system" &&
443
- designSystems.some(
444
- (designSystem) =>
445
- designSystem.id === reference.id &&
446
- isDesignSystemSelectable(designSystem),
447
- ),
434
+ designSystems.some((designSystem) => designSystem.id === reference.id),
448
435
  )?.id ?? null;
449
436
  const lastUsedReferenceDeckId =
450
437
  recentReferences.find(
@@ -63,23 +63,15 @@ export function missingDesignSystemDataFields(value: unknown): string[] {
63
63
 
64
64
  export type DesignSystemIndexingStatus = "ready" | "indexing" | "unavailable";
65
65
 
66
- const READY_BUILDER_STATUSES = new Set(["ready", "complete", "completed"]);
67
- const UNAVAILABLE_BUILDER_STATUSES = new Set([
68
- "error",
69
- "failed",
70
- "cancelled",
71
- "canceled",
72
- ]);
73
-
74
66
  /**
75
67
  * A Builder-indexed proxy design system (see `builder-design-system-proxy.ts`)
76
68
  * has no usable tokens/components until Builder confirms indexing finished —
77
69
  * selecting it before then is exactly what produced the "still being
78
- * indexed" agent stall this guards against. A locally authored design system
79
- * has no `builderStatus` at all and is always immediately usable. An
80
- * unrecognized or missing status on a Builder-sourced row is treated as still
81
- * indexing rather than ready, so a stale or malformed row never becomes
82
- * silently selectable.
70
+ * indexed" agent stall this guards against (ENG-13035).
71
+ *
72
+ * Rather than rely on builderStatus (which can get stuck), check for actual work:
73
+ * Proof of completion: docCount > 0, tokenValues exist, or persisted colors/typography.
74
+ * A locally authored design system has no `builderStatus` at all and is always ready.
83
75
  */
84
76
  export function getDesignSystemIndexingStatus(
85
77
  data: unknown,
@@ -88,11 +80,17 @@ export function getDesignSystemIndexingStatus(
88
80
  data && typeof data === "object" ? (data as Record<string, unknown>) : null;
89
81
  if (!record || record.source !== "builder") return "ready";
90
82
 
91
- const rawStatus = record.builderStatus;
92
- const status =
93
- typeof rawStatus === "string" ? rawStatus.trim().toLowerCase() : "";
94
- if (READY_BUILDER_STATUSES.has(status)) return "ready";
95
- if (UNAVAILABLE_BUILDER_STATUSES.has(status)) return "unavailable";
83
+ const hasColors = record.colors && typeof record.colors === "object";
84
+ const hasTypography =
85
+ record.typography && typeof record.typography === "object";
86
+ const docCount = typeof record.docCount === "number" ? record.docCount : 0;
87
+ const hasTokens =
88
+ record.tokenValues &&
89
+ typeof record.tokenValues === "object" &&
90
+ Object.keys(record.tokenValues as Record<string, unknown>).length > 0;
91
+
92
+ if (hasColors || hasTypography || docCount > 0 || hasTokens) return "ready";
93
+ if (record.warning) return "unavailable";
96
94
  return "indexing";
97
95
  }
98
96
 
@@ -186,8 +186,8 @@ export declare function createAutomationCallbackHandler(runtime: AutomationRunti
186
186
  duplicate?: undefined;
187
187
  eventId?: undefined;
188
188
  } | {
189
+ error?: undefined;
189
190
  accepted: boolean;
190
191
  duplicate: boolean;
191
192
  eventId: string;
192
- error?: undefined;
193
193
  }>;
@@ -26,8 +26,8 @@ export declare const getCollabState: import("h3").EventHandlerWithFetch<import("
26
26
  * Body: { update: string (base64), requestSource?: string }
27
27
  */
28
28
  export declare const postCollabUpdate: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
29
- error: string;
30
29
  ok?: undefined;
30
+ error: string;
31
31
  } | {
32
32
  error?: undefined;
33
33
  ok: boolean;
@@ -13,8 +13,8 @@
13
13
  * Body: { json: any, fieldName?: string, type?: "map"|"array", requestSource?: string }
14
14
  */
15
15
  export declare const postCollabJson: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
16
- error: string;
17
16
  ok?: undefined;
17
+ error: string;
18
18
  } | {
19
19
  error?: undefined;
20
20
  ok: boolean;
@@ -57,16 +57,16 @@ export declare function createListSecretsHandler(): import("h3").EventHandlerWit
57
57
  /** POST /_agent-native/secrets/:key — write a secret. */
58
58
  export declare function createWriteSecretHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
59
59
  error: string;
60
- status?: undefined;
61
60
  ok?: undefined;
61
+ status?: undefined;
62
62
  } | {
63
63
  ok: boolean;
64
64
  status: string;
65
65
  error?: undefined;
66
66
  } | {
67
+ ok?: undefined;
67
68
  error: string;
68
69
  removed?: undefined;
69
- ok?: undefined;
70
70
  } | {
71
71
  ok: boolean;
72
72
  removed: boolean;
@@ -77,9 +77,9 @@ export declare function createWriteSecretHandler(): import("h3").EventHandlerWit
77
77
  * or the current stored value without changing anything.
78
78
  */
79
79
  export declare function createTestSecretHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
80
+ ok?: undefined;
80
81
  error: string;
81
82
  note?: undefined;
82
- ok?: undefined;
83
83
  } | {
84
84
  ok: boolean;
85
85
  note?: undefined;
@@ -43,8 +43,8 @@ export declare function resolveAgentEngineApiKeyWriteTarget(event: H3Event, scop
43
43
  export declare function createAgentEngineApiKeyHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
44
44
  error: any;
45
45
  key?: undefined;
46
- scope?: undefined;
47
46
  ok?: undefined;
47
+ scope?: undefined;
48
48
  } | {
49
49
  ok: boolean;
50
50
  key: string;
@@ -80,10 +80,19 @@ export interface BuilderDesignSystemDocument {
80
80
  export interface BuilderDesignSystemHydratedReference extends BuilderDesignSystemProxyReference {
81
81
  docs: BuilderDesignSystemDocument[];
82
82
  tokenValues: Record<string, string>;
83
+ /** Builder-reported indexed document count; the only trusted readiness signal. */
83
84
  docCount: number;
84
- /** True only when Builder explicitly confirms that indexing is complete. */
85
+ /** True only when Builder reports at least one indexed document. */
85
86
  completionConfirmed?: boolean;
86
87
  }
88
+ export type BuilderDesignSystemDocumentCountResult = {
89
+ ok: true;
90
+ docCount: number;
91
+ } | {
92
+ ok: false;
93
+ reason: "unreachable" | "invalid-response";
94
+ detail: string;
95
+ };
87
96
  export interface BuilderDesignSystemIndexOptions {
88
97
  projectName?: string;
89
98
  description?: string;
@@ -220,6 +229,19 @@ export declare function designSystemTierUpgradeUrl(): string;
220
229
  export declare function localBuilderDesignSystemId(builderDesignSystemId: string): string;
221
230
  export declare function createBuilderDesignSystemProxyFields({ result, projectName, description, surface, sourceKind, githubSources, syncedAt, }: BuilderDesignSystemProxyFieldsOptions): BuilderDesignSystemProxyFields;
222
231
  export declare function parseBuilderDesignSystemProxyReference(data: unknown): BuilderDesignSystemProxyReference | null;
232
+ /**
233
+ * Builder's own status field drifts out of sync with reality, so the indexed
234
+ * document count is the only readiness signal worth branching on. Every
235
+ * consumer shares this one definition rather than re-deriving the comparison.
236
+ */
237
+ export declare function isBuilderDesignSystemReadyByCount(docCount: number): boolean;
238
+ /**
239
+ * Reads docCount from Builder's design-system detail endpoint. A count that
240
+ * cannot be read is never reported as zero: "still indexing" and "Builder did
241
+ * not answer" must stay distinguishable, or a stalled network reads as a
242
+ * legitimately empty system forever.
243
+ */
244
+ export declare function fetchBuilderDesignSystemDocumentCount(designSystemId: string): Promise<BuilderDesignSystemDocumentCountResult>;
223
245
  export declare function fetchBuilderDesignSystemDocs(designSystemId: string, options?: BuilderDesignSystemDocsOptions): Promise<BuilderDesignSystemDocument[]>;
224
246
  export declare function hydrateBuilderDesignSystemReference(reference: BuilderDesignSystemProxyReference, options?: BuilderDesignSystemDocsOptions): Promise<BuilderDesignSystemHydratedReference>;
225
247
  /**
@@ -939,9 +939,54 @@ function normalizeBuilderDesignSystemStatus(value) {
939
939
  return "in-progress";
940
940
  }
941
941
  }
942
- function isConfirmedBuilderDesignSystemStatus(value) {
943
- const status = normalizeBuilderDesignSystemStatus(value);
944
- return status === "ready" || status === "complete" || status === "completed";
942
+ /**
943
+ * Builder's own status field drifts out of sync with reality, so the indexed
944
+ * document count is the only readiness signal worth branching on. Every
945
+ * consumer shares this one definition rather than re-deriving the comparison.
946
+ */
947
+ export function isBuilderDesignSystemReadyByCount(docCount) {
948
+ return docCount > 0;
949
+ }
950
+ /**
951
+ * Reads docCount from Builder's design-system detail endpoint. A count that
952
+ * cannot be read is never reported as zero: "still indexing" and "Builder did
953
+ * not answer" must stay distinguishable, or a stalled network reads as a
954
+ * legitimately empty system forever.
955
+ */
956
+ export async function fetchBuilderDesignSystemDocumentCount(designSystemId) {
957
+ let response;
958
+ try {
959
+ response = await requestBuilderDesignSystem("builder:designsystem:read", (authorization) => {
960
+ const url = makeBuilderDesignSystemUrl(encodeURIComponent(designSystemId), authorization);
961
+ url.searchParams.set("includeDocumentCount", "true");
962
+ return fetchWithTimeout(url, {
963
+ method: "GET",
964
+ headers: makeBuilderHeaders(authorization),
965
+ });
966
+ });
967
+ }
968
+ catch (error) {
969
+ return {
970
+ ok: false,
971
+ reason: "unreachable",
972
+ detail: error instanceof Error
973
+ ? error.message
974
+ : "Builder design-system document count request failed.",
975
+ };
976
+ }
977
+ if (!response.ok) {
978
+ const body = await parseErrorBody(response);
979
+ return {
980
+ ok: false,
981
+ reason: "unreachable",
982
+ detail: "Builder answered " +
983
+ response.status +
984
+ " for the design-system document count: " +
985
+ body,
986
+ };
987
+ }
988
+ const json = await response.json();
989
+ return { ok: true, docCount: json.docCount ?? 0 };
945
990
  }
946
991
  async function fetchBuilderDesignSystemDocsResponse(designSystemId, options) {
947
992
  const response = await requestBuilderDesignSystem("builder:designsystem:read", (authorization) => {
@@ -962,10 +1007,7 @@ async function fetchBuilderDesignSystemDocsResponse(designSystemId, options) {
962
1007
  await assertOk(response, "Builder design-system docs fetch failed");
963
1008
  const json = (await response.json());
964
1009
  if (Array.isArray(json)) {
965
- return {
966
- docs: json.map(normalizeBuilderDesignSystemDocument),
967
- completionConfirmed: false,
968
- };
1010
+ return { docs: json.map(normalizeBuilderDesignSystemDocument) };
969
1011
  }
970
1012
  if (!json || typeof json !== "object") {
971
1013
  throw new Error("Builder design-system docs fetch returned an invalid response.");
@@ -979,13 +1021,8 @@ async function fetchBuilderDesignSystemDocsResponse(designSystemId, options) {
979
1021
  const status = typeof rawStatus === "string"
980
1022
  ? normalizeBuilderDesignSystemStatus(rawStatus)
981
1023
  : undefined;
982
- const isTerminalFailure = status === "error" || status === "failed" || status === "cancelled";
983
1024
  return {
984
1025
  docs: rawDocs.map(normalizeBuilderDesignSystemDocument),
985
- completionConfirmed: !isTerminalFailure &&
986
- (envelope.complete === true ||
987
- envelope.completed === true ||
988
- isConfirmedBuilderDesignSystemStatus(status)),
989
1026
  ...(status ? { status } : {}),
990
1027
  };
991
1028
  }
@@ -1000,14 +1037,19 @@ export async function hydrateBuilderDesignSystemReference(reference, options = {
1000
1037
  const pageSize = options.pageSize && options.pageSize > 0
1001
1038
  ? options.pageSize
1002
1039
  : DEFAULT_BUILDER_DOC_PAGE_SIZE;
1040
+ const count = await fetchBuilderDesignSystemDocumentCount(reference.builderDesignSystemId);
1041
+ if (!count.ok) {
1042
+ throw new Error("Builder design-system document count could not be read (" +
1043
+ count.reason +
1044
+ "): " +
1045
+ count.detail);
1046
+ }
1003
1047
  const docs = [];
1004
1048
  let page = Math.max(0, options.page ?? 0);
1005
- let completionConfirmed = false;
1006
1049
  let builderStatus = reference.builderStatus;
1007
1050
  for (let pageNumber = 0; pageNumber < MAX_BUILDER_DOC_PAGES; pageNumber++) {
1008
1051
  const response = await fetchBuilderDesignSystemDocsResponse(reference.builderDesignSystemId, { ...options, page, pageSize });
1009
1052
  docs.push(...response.docs);
1010
- completionConfirmed ||= response.completionConfirmed;
1011
1053
  builderStatus = response.status ?? builderStatus;
1012
1054
  if (response.docs.length < pageSize || options.minimal)
1013
1055
  break;
@@ -1030,9 +1072,8 @@ export async function hydrateBuilderDesignSystemReference(reference, options = {
1030
1072
  ...(builderStatus ? { builderStatus } : {}),
1031
1073
  docs,
1032
1074
  tokenValues,
1033
- docCount: docs.length,
1034
- completionConfirmed: completionConfirmed ||
1035
- isConfirmedBuilderDesignSystemStatus(builderStatus),
1075
+ docCount: count.docCount,
1076
+ completionConfirmed: isBuilderDesignSystemReadyByCount(count.docCount),
1036
1077
  };
1037
1078
  }
1038
1079
  /**
@@ -83,7 +83,7 @@ export { buildWorkspaceProviderAuthorizationUrl, createWorkspaceProviderOAuthHan
83
83
  export { CredentialStoreUnavailableError, FeatureNotConfiguredError, hasBuilderPrivateKey, isBuilderEnvManaged, getBuilderProxyOrigin, getBuilderImageGenerationBaseUrl, getBuilderWebSearchBaseUrl, getBuilderAuthHeader, resolveBuilderPrivateKey, resolveBuilderAuthHeader, resolveHasBuilderPrivateKey, resolveHasCompleteBuilderConnection, resolveBuilderCredentials, resolveBuilderCredentialsDetailed, resolveBuilderGatewayCredentialsDetailed, resolveBuilderGatewayAuth, resolveBuilderGatewayCredentials, resolveHasBuilderGatewayCredential, resolveBuilderCredentialSource, resolveBuilderCredential, readDeployCredentialEnv, resolveVercelDeploymentProtectionHeaders, writeBuilderCredentials, deleteBuilderCredentials, resolveSecret, type BuilderCredentialsDetailed, } from "./credential-provider.js";
84
84
  export { BUILDER_PUBLISH_MCP_RESOURCE, canAuthorizeBuilderApiRequest, hasBuilderApiCredentialCustody, resolveBuilderApiAuthorization, resolveBuilderRequestAuthorization, type BuilderLegacyCredentialKey, type BuilderRequestAuthorization, } from "./builder-api-auth.js";
85
85
  export { BUILDER_ASSETS_WRITE_SCOPE, BUILDER_OAUTH_SCOPE, type BuilderOAuthPermissionScope, } from "./builder-oauth.js";
86
- export { assertBuilderDesignSystemCodeIndexingAllowed, builderDesignSystemUrl, builderProjectBranchUrl, buildBuilderDesignSystemIndexFiles, collectBuilderDesignSystemGitHubFiles, createBuilderDesignSystemProxyFields, designSystemTierUpgradeUrl, fetchBuilderDesignSystemDecodeJobStatus, fetchBuilderDesignSystemDocs, fetchBuilderDesignSystemRecord, fetchBuilderDesignSystemTierLimit, getBuilderDesignSystemsBaseUrl, hydrateBuilderDesignSystemReference, indexBuilderDesignSystem, localBuilderDesignSystemId, mimeTypeForBuilderDesignSystemFilename, parseBuilderDesignSystemProxyReference, startBuilderDesignSystemIndex, startBuilderDesignSystemUpload, type BuildBuilderDesignSystemIndexFilesOptions, type BuilderDesignSystemCodeFileInput, type BuilderDesignSystemDecodeJobStatus, type BuilderDesignSystemDocsOptions, type BuilderDesignSystemDocument, type BuilderDesignSystemHydratedReference, type BuilderDesignSystemIndexFile, type BuilderDesignSystemIndexFromSourcesOptions, type BuilderDesignSystemIndexOptions, type BuilderDesignSystemIndexResult, type BuilderDesignSystemRecord, type BuilderDesignSystemStatus, type BuilderDesignSystemTierLimit, type BuilderDesignSystemGitHubFile, type BuilderDesignSystemGitHubFileCollection, type BuilderDesignSystemGitHubSource, type BuilderDesignSystemUploadAttachment, type BuilderDesignSystemUploadSlot, type BuilderDesignSystemProxyFields, type BuilderDesignSystemProxyFieldsOptions, type BuilderDesignSystemProxyReference, type BuilderDesignSystemSourceKind, } from "./builder-design-systems.js";
86
+ export { assertBuilderDesignSystemCodeIndexingAllowed, builderDesignSystemUrl, builderProjectBranchUrl, buildBuilderDesignSystemIndexFiles, collectBuilderDesignSystemGitHubFiles, createBuilderDesignSystemProxyFields, designSystemTierUpgradeUrl, fetchBuilderDesignSystemDecodeJobStatus, fetchBuilderDesignSystemDocs, fetchBuilderDesignSystemDocumentCount, fetchBuilderDesignSystemRecord, fetchBuilderDesignSystemTierLimit, getBuilderDesignSystemsBaseUrl, hydrateBuilderDesignSystemReference, indexBuilderDesignSystem, isBuilderDesignSystemReadyByCount, localBuilderDesignSystemId, mimeTypeForBuilderDesignSystemFilename, parseBuilderDesignSystemProxyReference, startBuilderDesignSystemIndex, startBuilderDesignSystemUpload, type BuildBuilderDesignSystemIndexFilesOptions, type BuilderDesignSystemCodeFileInput, type BuilderDesignSystemDecodeJobStatus, type BuilderDesignSystemDocsOptions, type BuilderDesignSystemDocument, type BuilderDesignSystemDocumentCountResult, type BuilderDesignSystemHydratedReference, type BuilderDesignSystemIndexFile, type BuilderDesignSystemIndexFromSourcesOptions, type BuilderDesignSystemIndexOptions, type BuilderDesignSystemIndexResult, type BuilderDesignSystemRecord, type BuilderDesignSystemStatus, type BuilderDesignSystemTierLimit, type BuilderDesignSystemGitHubFile, type BuilderDesignSystemGitHubFileCollection, type BuilderDesignSystemGitHubSource, type BuilderDesignSystemUploadAttachment, type BuilderDesignSystemUploadSlot, type BuilderDesignSystemProxyFields, type BuilderDesignSystemProxyFieldsOptions, type BuilderDesignSystemProxyReference, type BuilderDesignSystemSourceKind, } from "./builder-design-systems.js";
87
87
  export { createBuilderProject, ensureBuilderProject, findBuilderProjectForRepo, getBuilderBranchProjectId, isBuilderBranchingEnabled, requestBuilderBrowserConnection, resolveBuilderBranchProjectId, resolveIsBuilderBranchingEnabled, runBuilderAgent, type BuilderAgentAttachment, type BuilderAgentUploadAttachment, type BuilderAgentUrlAttachment, type BuilderProjectResult, type RunBuilderAgentResult, } from "./builder-browser.js";
88
88
  export { ensureFusionContainer, sendFusionBranchMessage, pushFusionBranch, reserveFusionHostingSlug, deployFusionProject, getFusionDeploys, getFusionBranchEditorUrl, getFusionHostingUrl, type FusionBranchRef, type EnsureFusionContainerResult, type SendFusionMessageResult, } from "./fusion-app.js";
89
89
  export { sendEmail, isEmailConfigured, getEmailReadiness, getEmailProvider, type EmailAttachment, type EmailReadiness, type EmailProvider, type SendEmailArgs, } from "./email.js";
@@ -93,7 +93,7 @@ resolveBuilderGatewayCredentialsDetailed, resolveBuilderGatewayAuth,
93
93
  resolveBuilderGatewayCredentials, resolveHasBuilderGatewayCredential, resolveBuilderCredentialSource, resolveBuilderCredential, readDeployCredentialEnv, resolveVercelDeploymentProtectionHeaders, writeBuilderCredentials, deleteBuilderCredentials, resolveSecret, } from "./credential-provider.js";
94
94
  export { BUILDER_PUBLISH_MCP_RESOURCE, canAuthorizeBuilderApiRequest, hasBuilderApiCredentialCustody, resolveBuilderApiAuthorization, resolveBuilderRequestAuthorization, } from "./builder-api-auth.js";
95
95
  export { BUILDER_ASSETS_WRITE_SCOPE, BUILDER_OAUTH_SCOPE, } from "./builder-oauth.js";
96
- export { assertBuilderDesignSystemCodeIndexingAllowed, builderDesignSystemUrl, builderProjectBranchUrl, buildBuilderDesignSystemIndexFiles, collectBuilderDesignSystemGitHubFiles, createBuilderDesignSystemProxyFields, designSystemTierUpgradeUrl, fetchBuilderDesignSystemDecodeJobStatus, fetchBuilderDesignSystemDocs, fetchBuilderDesignSystemRecord, fetchBuilderDesignSystemTierLimit, getBuilderDesignSystemsBaseUrl, hydrateBuilderDesignSystemReference, indexBuilderDesignSystem, localBuilderDesignSystemId, mimeTypeForBuilderDesignSystemFilename, parseBuilderDesignSystemProxyReference, startBuilderDesignSystemIndex, startBuilderDesignSystemUpload, } from "./builder-design-systems.js";
96
+ export { assertBuilderDesignSystemCodeIndexingAllowed, builderDesignSystemUrl, builderProjectBranchUrl, buildBuilderDesignSystemIndexFiles, collectBuilderDesignSystemGitHubFiles, createBuilderDesignSystemProxyFields, designSystemTierUpgradeUrl, fetchBuilderDesignSystemDecodeJobStatus, fetchBuilderDesignSystemDocs, fetchBuilderDesignSystemDocumentCount, fetchBuilderDesignSystemRecord, fetchBuilderDesignSystemTierLimit, getBuilderDesignSystemsBaseUrl, hydrateBuilderDesignSystemReference, indexBuilderDesignSystem, isBuilderDesignSystemReadyByCount, localBuilderDesignSystemId, mimeTypeForBuilderDesignSystemFilename, parseBuilderDesignSystemProxyReference, startBuilderDesignSystemIndex, startBuilderDesignSystemUpload, } from "./builder-design-systems.js";
97
97
  export { createBuilderProject, ensureBuilderProject, findBuilderProjectForRepo, getBuilderBranchProjectId, isBuilderBranchingEnabled, requestBuilderBrowserConnection, resolveBuilderBranchProjectId, resolveIsBuilderBranchingEnabled, runBuilderAgent, } from "./builder-browser.js";
98
98
  export { ensureFusionContainer, sendFusionBranchMessage, pushFusionBranch, reserveFusionHostingSlug, deployFusionProject, getFusionDeploys, getFusionBranchEditorUrl, getFusionHostingUrl, } from "./fusion-app.js";
99
99
  export { sendEmail, isEmailConfigured, getEmailReadiness, getEmailProvider, } from "./email.js";
@@ -59,8 +59,8 @@ export declare function createRealtimeTokenHandler(): import("h3").EventHandlerW
59
59
  expiresAt?: undefined;
60
60
  ttlSeconds?: undefined;
61
61
  } | {
62
+ error?: undefined;
62
63
  token: string;
63
64
  expiresAt: string;
64
65
  ttlSeconds: number;
65
- error?: undefined;
66
66
  }>>;
@@ -20,6 +20,6 @@ export declare function createTranscribeVoiceHandler(): import("h3").EventHandle
20
20
  error: string;
21
21
  text?: undefined;
22
22
  } | {
23
- text: string;
24
23
  error?: undefined;
24
+ text: string;
25
25
  }>>;