@madewithremy/admin 0.1.14 → 0.1.16

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/index.d.ts CHANGED
@@ -1059,6 +1059,38 @@ declare namespace data {
1059
1059
  export { type data_LiftFromLiveParams as LiftFromLiveParams, data_liftFromDev as liftFromDev, data_liftFromLive as liftFromLive };
1060
1060
  }
1061
1061
 
1062
+ /**
1063
+ * One shape for every long operation's progress: a bulk load, an index
1064
+ * reload, a move, an index build, a resource changing phase. Rate and ETA are
1065
+ * measured by the platform from the operation's own record, so the CLI, the
1066
+ * dashboard and a search's refusal message quote the same numbers.
1067
+ *
1068
+ * Transcribed from youai-api: src/common/DataSources/progress.ts
1069
+ */
1070
+ interface OperationProgress {
1071
+ /** The operation's own phase word: `running`, `copying`, `building`, `provisioning`… */
1072
+ phase: string;
1073
+ unit: 'documents' | 'objects' | 'vectors' | 'steps';
1074
+ done: number;
1075
+ /** Null when the operation has no known end (a planning walk, a phase transition). */
1076
+ total: number | null;
1077
+ /** Units per minute over the last few minutes; null until measured. */
1078
+ ratePerMinute: number | null;
1079
+ /** When the rest lands at that rate; null without a rate or a total. */
1080
+ etaAt: string | null;
1081
+ startedAt: string | null;
1082
+ /** When the operation last moved. */
1083
+ updatedAt: string | null;
1084
+ /** No movement for 30 minutes while under way. */
1085
+ stalled: boolean;
1086
+ /** The operation's own word on itself: an error, a pause reason, a step. */
1087
+ note: string | null;
1088
+ history: {
1089
+ phase: string;
1090
+ at: string;
1091
+ }[];
1092
+ }
1093
+
1062
1094
  /**
1063
1095
  * Response types for bulk ingestion jobs.
1064
1096
  *
@@ -1066,6 +1098,7 @@ declare namespace data {
1066
1098
  * src/http/routes/V2Apps/manage/dataSourceJobs.ts (jobView)
1067
1099
  * src/common/DataSources/jobs/types.ts
1068
1100
  */
1101
+
1069
1102
  /**
1070
1103
  * Where a job's documents come from. `store` is every object under a prefix of
1071
1104
  * one of the app's file stores (what `files put` fills); `manifest` is a JSONL
@@ -1153,10 +1186,37 @@ interface DataSourceJobPlan {
1153
1186
  capacity: {
1154
1187
  placement: 'shared' | 'dedicated';
1155
1188
  resourceId: string | null;
1189
+ /**
1190
+ * Chunks the placement holds in total at this source's dimensions: the
1191
+ * shared pool's per-source cap, or what the resource would hold were this
1192
+ * source alone on it.
1193
+ */
1156
1194
  maxPoints: number;
1195
+ /** Chunks already there (other sources on the resource, or this one's own). */
1157
1196
  heldPoints: number;
1158
1197
  /** False means approve is refused until the source moves or the resource grows. */
1159
1198
  fits: boolean;
1199
+ /**
1200
+ * Dedicated only: the bytes the decision was made on. `binding` names the
1201
+ * limit that refused; `held`, `incoming` and `usable` are disk and RAM.
1202
+ */
1203
+ footprint?: {
1204
+ dimensions: number;
1205
+ fits: boolean;
1206
+ binding: 'disk' | 'ram' | null;
1207
+ held: {
1208
+ diskBytes: number;
1209
+ ramBytes: number;
1210
+ };
1211
+ incoming: {
1212
+ diskBytes: number;
1213
+ ramBytes: number;
1214
+ };
1215
+ usable: {
1216
+ diskBytes: number;
1217
+ ramBytes: number;
1218
+ };
1219
+ } | null;
1160
1220
  };
1161
1221
  durationMinutes: number;
1162
1222
  warnings: string[];
@@ -1222,6 +1282,12 @@ interface DataSourceJob {
1222
1282
  startedAt: string | null;
1223
1283
  finishedAt: string | null;
1224
1284
  lastProgressAt: string | null;
1285
+ /**
1286
+ * The job in the one progress shape: objects listed while planning,
1287
+ * documents processed against the plan's projection after, with the
1288
+ * coordinator's measured rate and ETA.
1289
+ */
1290
+ progress: OperationProgress;
1225
1291
  }
1226
1292
  /** GET /datasources/jobs */
1227
1293
  interface DataSourceJobsListResult {
@@ -1318,12 +1384,18 @@ interface DataSourceSyncResult {
1318
1384
  * src/common/DataSources/evals/types.ts
1319
1385
  */
1320
1386
 
1321
- /** An index reload in flight after an eviction, or its last failure. */
1387
+ /**
1388
+ * An index reload in flight, or its last failure: after an eviction on the
1389
+ * shared pool, after a lost node or a resume on dedicated capacity, or a
1390
+ * reindex. Null on the source when the index is simply resident.
1391
+ */
1322
1392
  interface DataSourcesHydration {
1323
1393
  copied: number;
1324
1394
  total: number;
1325
1395
  startedAt: string;
1326
1396
  error: string | null;
1397
+ /** The reload in the one progress shape, with the platform's measured rate and ETA. */
1398
+ progress: OperationProgress;
1327
1399
  }
1328
1400
  /** POST /datasources/hydrate */
1329
1401
  interface DataSourcesHydrateResult {
@@ -1948,14 +2020,16 @@ interface DataSourcesPlacement {
1948
2020
  * null) can be moving too.
1949
2021
  */
1950
2022
  /**
1951
- * Dedicated capacity's index, as Qdrant reports it: `deferred` while a bulk
1952
- * load runs (the node writes, nothing is indexed), `building` while the graph
1953
- * is built after one, `ready` otherwise.
2023
+ * Dedicated capacity's index, as Qdrant reports it: `building` while the
2024
+ * optimizer is behind the writes (a load can outrun it for a while), `ready`
2025
+ * otherwise.
1954
2026
  */
1955
2027
  interface DataSourcesIndex {
1956
- state: 'ready' | 'deferred' | 'building';
2028
+ state: 'ready' | 'building';
1957
2029
  indexedVectors: number;
1958
2030
  totalVectors: number;
2031
+ /** The optimizer's progress in the one shape, with the platform's measured rate and ETA. */
2032
+ progress: OperationProgress;
1959
2033
  }
1960
2034
  interface DataSourcesMigration {
1961
2035
  /** Where it is going; null is the shared pool. */
@@ -1966,6 +2040,8 @@ interface DataSourcesMigration {
1966
2040
  startedAt: string;
1967
2041
  /** Set when the move failed; the source is unfrozen and a new move may start. */
1968
2042
  error: string | null;
2043
+ /** The copy in the one progress shape, with the platform's measured rate and ETA. */
2044
+ progress: OperationProgress;
1969
2045
  }
1970
2046
  /** One data source in the GET /datasources listing. */
1971
2047
  interface DataSourcesListEntry {
@@ -1999,10 +2075,9 @@ interface DataSourcesListEntry {
1999
2075
  /** An index reload in flight after an eviction, or its last failure. */
2000
2076
  hydration: DataSourcesHydration | null;
2001
2077
  /**
2002
- * Dedicated capacity only; null on the shared pool. `deferred` while a bulk
2003
- * load runs (the node writes, nothing is indexed), `building` while the
2004
- * index is built after one, `ready` otherwise. Search answers
2005
- * `index_building` (503) in the first two states.
2078
+ * Dedicated capacity only; null on the shared pool. `building` while the
2079
+ * optimizer is behind the writes, `ready` otherwise. Search answers
2080
+ * `index_building` (503) while building.
2006
2081
  */
2007
2082
  index: DataSourcesIndex | null;
2008
2083
  /** The source this one was sampled from (`datasources sample`), or null. */
@@ -2278,7 +2353,7 @@ declare function addDocument(ctx: AdminContext, params: AddDocumentParams): Prom
2278
2353
  interface WaitForIngestParams {
2279
2354
  slug: string;
2280
2355
  documentIds: string[];
2281
- /** Defaults to DEFAULT_WAIT_TIMEOUT_MS (15 min). */
2356
+ /** How long without movement before giving up. Defaults to DEFAULT_WAIT_TIMEOUT_MS (15 min). */
2282
2357
  timeoutMs?: number;
2283
2358
  /**
2284
2359
  * Receives the exact progress strings the CLI prints today:
@@ -2315,7 +2390,7 @@ interface WaitForIngestResult {
2315
2390
  declare function waitForIngest(ctx: AdminContext, params: WaitForIngestParams): Promise<WaitForIngestResult>;
2316
2391
  interface WaitForCandidateParams {
2317
2392
  slug: string;
2318
- /** Defaults to DEFAULT_WAIT_TIMEOUT_MS (15 min). */
2393
+ /** How long without movement before giving up. Defaults to DEFAULT_WAIT_TIMEOUT_MS (15 min). */
2319
2394
  timeoutMs?: number;
2320
2395
  /** Receives `rebuilding… X/Y done (Ns)`. */
2321
2396
  onProgress?: (message: string) => void;
@@ -2540,9 +2615,9 @@ interface MoveParams {
2540
2615
  declare function move(ctx: AdminContext, params: MoveParams): Promise<DataSourcesMoveResult>;
2541
2616
  interface WaitForMoveParams {
2542
2617
  slug: string;
2543
- /** Defaults to DEFAULT_WAIT_TIMEOUT_MS (15 min). */
2618
+ /** How long without movement before giving up. Defaults to DEFAULT_WAIT_TIMEOUT_MS (15 min). */
2544
2619
  timeoutMs?: number;
2545
- /** Receives `moving… X/Y documents (Ns)`. */
2620
+ /** Receives `copying… X/Y documents · N/min · about M min left (Ns)`. */
2546
2621
  onProgress?: (message: string) => void;
2547
2622
  }
2548
2623
  type WaitForMoveResult = {
@@ -2813,11 +2888,16 @@ declare function resume$1(ctx: AdminContext, params: JobIdParams & {
2813
2888
  /** Embed at the provider's priority tier from here on (1.5x the embedding price). */
2814
2889
  priority?: boolean;
2815
2890
  }): Promise<DataSourceJobResult>;
2891
+ /**
2892
+ * Run a finished job's failed batches again, after fixing what failed them.
2893
+ * The job goes back to `running`; `nothing_to_retry` when none failed.
2894
+ */
2895
+ declare function retry(ctx: AdminContext, params: JobIdParams): Promise<DataSourceJobResult>;
2816
2896
  /** End the job. Documents already indexed stay. */
2817
2897
  declare function cancel(ctx: AdminContext, params: JobIdParams): Promise<DataSourceJobResult>;
2818
2898
  interface WaitParams$1 {
2819
2899
  id: string;
2820
- /** Default one hour. */
2900
+ /** How long without movement before giving up. Default one hour. */
2821
2901
  timeoutMs?: number;
2822
2902
  onProgress?: (message: string) => void;
2823
2903
  }
@@ -2853,7 +2933,11 @@ declare function waitForPlan(ctx: AdminContext, params: WaitParams$1): Promise<W
2853
2933
  * with the pause reason, since nothing more will happen without them.
2854
2934
  */
2855
2935
  declare function waitForJob(ctx: AdminContext, params: WaitParams$1): Promise<WaitResult>;
2856
- /** One line of progress in the job's own terms. */
2936
+ /**
2937
+ * One line of progress in the job's own terms: the platform's phase, count,
2938
+ * rate and ETA, with the spend so far beside them. A planning walk that has
2939
+ * finished listing says so, since its count has stopped moving on purpose.
2940
+ */
2857
2941
  declare function describeProgress(job: DataSourceJob, start: number): string;
2858
2942
 
2859
2943
  type dataSourceJobs_JobIdParams = JobIdParams;
@@ -2864,12 +2948,13 @@ declare const dataSourceJobs_approve: typeof approve;
2864
2948
  declare const dataSourceJobs_cancel: typeof cancel;
2865
2949
  declare const dataSourceJobs_describeProgress: typeof describeProgress;
2866
2950
  declare const dataSourceJobs_pause: typeof pause;
2951
+ declare const dataSourceJobs_retry: typeof retry;
2867
2952
  declare const dataSourceJobs_start: typeof start;
2868
2953
  declare const dataSourceJobs_uploadManifest: typeof uploadManifest;
2869
2954
  declare const dataSourceJobs_waitForJob: typeof waitForJob;
2870
2955
  declare const dataSourceJobs_waitForPlan: typeof waitForPlan;
2871
2956
  declare namespace dataSourceJobs {
2872
- export { DEFAULT_WAIT_TIMEOUT_MS$2 as DEFAULT_WAIT_TIMEOUT_MS, type dataSourceJobs_JobIdParams as JobIdParams, type ListParams$1 as ListParams, type dataSourceJobs_StartParams as StartParams, type dataSourceJobs_UploadManifestParams as UploadManifestParams, type WaitParams$1 as WaitParams, type dataSourceJobs_WaitResult as WaitResult, dataSourceJobs_approve as approve, dataSourceJobs_cancel as cancel, dataSourceJobs_describeProgress as describeProgress, get$7 as get, list$7 as list, dataSourceJobs_pause as pause, resume$1 as resume, dataSourceJobs_start as start, dataSourceJobs_uploadManifest as uploadManifest, dataSourceJobs_waitForJob as waitForJob, dataSourceJobs_waitForPlan as waitForPlan };
2957
+ export { DEFAULT_WAIT_TIMEOUT_MS$2 as DEFAULT_WAIT_TIMEOUT_MS, type dataSourceJobs_JobIdParams as JobIdParams, type ListParams$1 as ListParams, type dataSourceJobs_StartParams as StartParams, type dataSourceJobs_UploadManifestParams as UploadManifestParams, type WaitParams$1 as WaitParams, type dataSourceJobs_WaitResult as WaitResult, dataSourceJobs_approve as approve, dataSourceJobs_cancel as cancel, dataSourceJobs_describeProgress as describeProgress, get$7 as get, list$7 as list, dataSourceJobs_pause as pause, resume$1 as resume, dataSourceJobs_retry as retry, dataSourceJobs_start as start, dataSourceJobs_uploadManifest as uploadManifest, dataSourceJobs_waitForJob as waitForJob, dataSourceJobs_waitForPlan as waitForPlan };
2873
2958
  }
2874
2959
 
2875
2960
  /**
@@ -2973,15 +3058,9 @@ declare const DEFAULT_WAIT_TIMEOUT_MS$1: number;
2973
3058
  * Warm a source's index if it is cold. A search on a large cold index answers
2974
3059
  * `index_warming` until the reload lands; call this before a demo, or after an
2975
3060
  * eviction you know about. Answers `resident: true` when nothing was needed.
2976
- *
2977
- * With `since`, refill instead: copy every document built at or after that
2978
- * time into the index whether or not it is resident. What a dedicated
2979
- * instance needs after restoring from a snapshot taken then; the platform
2980
- * does this on its own when it sees the restore, this is the by-hand path.
2981
3061
  */
2982
3062
  declare function hydrate(ctx: AdminContext, params: {
2983
3063
  slug: string;
2984
- since?: string;
2985
3064
  }): Promise<DataSourcesHydrateResult>;
2986
3065
  /**
2987
3066
  * Recreate a dedicated source's collection with the platform's current shape
@@ -2999,7 +3078,9 @@ declare function reindex(ctx: AdminContext, params: {
2999
3078
  }): Promise<DataSourcesHydrateResult>;
3000
3079
  interface WaitForHydrationParams {
3001
3080
  slug: string;
3081
+ /** How long without movement before giving up. Defaults to DEFAULT_WAIT_TIMEOUT_MS (30 min). */
3002
3082
  timeoutMs?: number;
3083
+ /** Receives `copying… X/Y documents · N/min · about M min left (Ns)`. */
3003
3084
  onProgress?: (message: string) => void;
3004
3085
  }
3005
3086
  type WaitForHydrationResult = {
@@ -4525,32 +4606,42 @@ declare namespace files {
4525
4606
  * src/common/Provisioning/types.ts
4526
4607
  * src/common/Provisioning/offerings/define.ts
4527
4608
  */
4609
+
4528
4610
  /** Where a resource is in its lifecycle. Written only by the platform. */
4529
4611
  type InfraPhase = 'requested' | 'provisioning' | 'active' | 'hibernating' | 'hibernated' | 'resuming' | 'decommissioning' | 'destroyed' | 'failed';
4530
4612
  /** What the owner asked for. Written only by the owner's actions. */
4531
4613
  type InfraDesiredState = 'active' | 'hibernated' | 'destroyed';
4532
4614
  /**
4533
- * What the platform last saw of an active resource's instance. `restoring` is
4534
- * an instance that came back empty and is being refilled from its snapshot;
4535
- * searches return `capacity_restoring` until it is `ready`.
4615
+ * What the platform last saw of an active resource's instance. `rebuilding`
4616
+ * is a serving instance onto which one or more placed sources are being copied
4617
+ * back from durable storage (a new pod found their index empty); searches on
4618
+ * those sources answer `index_warming` with the copy's progress until it lands.
4536
4619
  */
4537
- type InfraHealth = 'ready' | 'not-ready' | 'missing' | 'restoring';
4620
+ type InfraHealth = 'ready' | 'not-ready' | 'missing' | 'rebuilding';
4538
4621
  /** A leasable product from the platform catalog. Prices are cogs + margin. */
4539
4622
  interface InfraOffering {
4540
4623
  id: string;
4541
4624
  kind: 'retrieval';
4542
4625
  /** User-facing size, e.g. "Small". */
4543
4626
  label: string;
4544
- /** User-facing capacity, e.g. "Up to ~1M chunks". */
4627
+ /** User-facing capacity, e.g. "Up to ~34M chunks at 2560 dimensions (~48M at 1024, ~26M at 4096)". */
4545
4628
  description: string;
4546
4629
  hourlyPriceDollars: number;
4547
4630
  /** Hourly × 730. */
4548
4631
  monthlyPriceDollars: number;
4549
- /** Retained-storage rate while hibernated. */
4632
+ /** Zero: a hibernated resource holds nothing; its sources' documents stay in the platform's own store. */
4550
4633
  hibernatedHourlyPriceDollars: number;
4551
4634
  hibernatedMonthlyPriceDollars: number;
4635
+ /**
4636
+ * What the size holds: its disk and RAM, and the chunks that comes to at
4637
+ * each embedding dimension on offer, keyed by dimension ("2560"). A chunk
4638
+ * embedded at 2560 dimensions takes two and a half times a 1024-dimension
4639
+ * one, so a resource's room depends on what is placed on it.
4640
+ */
4552
4641
  capacity: {
4553
- maxPoints: number;
4642
+ diskGiB: number;
4643
+ memoryGiB: number;
4644
+ chunksByDimensions: Record<string, number>;
4554
4645
  };
4555
4646
  capabilities: {
4556
4647
  hibernate: boolean;
@@ -4573,17 +4664,36 @@ interface InfraResource {
4573
4664
  health: InfraHealth | null;
4574
4665
  /**
4575
4666
  * What the instance is doing right now, while a transition is under way
4576
- * ("Waiting for capacity", "Snapshotting collection 1/2"); null when nothing is.
4667
+ * ("Waiting for capacity", "Starting Qdrant", "Scaling down"); null when nothing is.
4577
4668
  */
4578
4669
  detail: string | null;
4670
+ /**
4671
+ * The same in the one progress shape, with numbers where there are any: a
4672
+ * rebuild of the sources placed here (documents, rate, ETA), an index build
4673
+ * the optimizer is behind on (vectors), or a transition's step. Null when the
4674
+ * resource is simply serving.
4675
+ */
4676
+ progress: OperationProgress | null;
4677
+ /**
4678
+ * What the sources placed here take on the instance: estimated from their
4679
+ * chunk counts at their dimensions, and measured from the instance itself
4680
+ * while it is up (null until it has reported), against what the size can
4681
+ * hold. Null when the offering is unknown.
4682
+ */
4683
+ footprint: {
4684
+ chunks: number;
4685
+ estimatedDiskBytes: number;
4686
+ measuredDiskBytes: number | null;
4687
+ measuredRamBytes: number | null;
4688
+ measuredAt: string | null;
4689
+ usableDiskBytes: number;
4690
+ } | null;
4579
4691
  /**
4580
4692
  * The size this resource is being resized to, while a resize is under way;
4581
4693
  * null otherwise. A resize passes through `hibernated` and back to the phase
4582
4694
  * it started from.
4583
4695
  */
4584
4696
  resizingTo: InfraOffering | null;
4585
- /** When the last verified snapshot was taken; null if never. */
4586
- lastSnapshotAt: string | null;
4587
4697
  /**
4588
4698
  * What this resource has actually been charged, from the ledger's own
4589
4699
  * writes, with the hours at each rate beside it. Rates are on `offering`.
@@ -4612,7 +4722,8 @@ interface InfraEvent {
4612
4722
  }
4613
4723
  /**
4614
4724
  * One line of the platform's narration of a resource: a step reported while
4615
- * a transition ran ("Waiting for capacity", "Restoring collections 2/3"), a
4725
+ * a transition ran ("Waiting for capacity", "Starting Qdrant"), a rebuild it
4726
+ * started ("Instance replaced; checking each placed source's index on it"), a
4616
4727
  * failed attempt, or a failure with what Kubernetes said about the pod at the
4617
4728
  * time (`data`). Not the instance's own stdout.
4618
4729
  */
@@ -4759,16 +4870,17 @@ interface ResizeParams {
4759
4870
  offeringId: string;
4760
4871
  }
4761
4872
  /**
4762
- * Change a resource's size, keeping its data.
4873
+ * Change a resource's size, keeping its documents.
4763
4874
  *
4764
- * The platform parks the resource (a fresh snapshot), swaps its spec, and
4765
- * brings it back up restored from that snapshot, so a resize passes through
4766
- * `hibernated` and searches on its sources pause for the few minutes it
4767
- * takes. A resource that is already hibernated swaps in place and stays
4768
- * parked. Growing is gated on a month of credits at the new rate like a
4769
- * provision; shrinking is refused below what the resource holds. The response
4770
- * carries `resizingTo` until the swap has happened; `waitForPhase` with
4771
- * `until: (r) => r.resizingTo === null` blocks on the whole thing.
4875
+ * The platform parks the resource, swaps its spec, and brings it back up with
4876
+ * its sources' indexes rebuilt from durable storage in the background, so a
4877
+ * resize passes through `hibernated` and searches on those sources answer
4878
+ * `index_warming` with the rebuild's progress until it lands. A resource that
4879
+ * is already hibernated swaps in place and stays parked. Growing is gated on a
4880
+ * month of credits at the new rate like a provision; shrinking is refused
4881
+ * below what the resource holds. The response carries `resizingTo` until the
4882
+ * swap has happened; `waitForPhase` with `until: (r) => r.resizingTo === null`
4883
+ * blocks on the whole thing.
4772
4884
  *
4773
4885
  * @throws AdminApiError `resource_not_found` (404), `offering_not_found`
4774
4886
  * (400), `offering_retired` (422), `same_offering` (400),
@@ -4793,7 +4905,7 @@ interface WaitForPhaseParams {
4793
4905
  * phase it started from and is done only once `resizingTo` has cleared.
4794
4906
  */
4795
4907
  until?: (resource: InfraResource) => boolean;
4796
- /** Default 10 minutes. */
4908
+ /** How long without movement before giving up. Default 10 minutes. */
4797
4909
  timeoutMs?: number;
4798
4910
  onProgress?: (message: string) => void;
4799
4911
  }
@@ -7370,4 +7482,4 @@ declare class AdminTimeoutError extends Error {
7370
7482
 
7371
7483
  declare const admin: AdminClient;
7372
7484
 
7373
- export { AdminApiError, type AdminClient, type AdminClientOptions, type AdminContext, AdminTimeoutError, type AgentThreadDetail, type AgentThreadListItem, type AgentThreadsGetResult, type AgentThreadsListResult, type AgentToolCall, type AgentTranscriptMessage, type AgentTurnError, type AnalyticsAiHostRow, type AnalyticsAiSourcesResult, type AnalyticsAiVendorRow, type AnalyticsBatchResult, type AnalyticsCrawlersOverviewResult, type AnalyticsCrawlersRecentResult, type AnalyticsCrawlersRecentRow, type AnalyticsCrawlersResult, type AnalyticsCrawlersTimeseriesBucket, type AnalyticsCrawlersTimeseriesResult, type AnalyticsLiveResult, type AnalyticsMapPoint, type AnalyticsMapResult, type AnalyticsMetric, type AnalyticsQueryResult, type AnalyticsQueryResultRow, type AnalyticsSourceRow, type AnalyticsSourcesResult, type AppCronJobStatus, type AppCronJobStatusReason, type AppCronRunState, type AppEmailSuppression, type AppSecretRow, type CrashGroup, type CrashOccurrenceRow, type CrashesGetResult, type CrashesListResult, type CrashesOccurrencesResult, type CrashesStatsBucket, type CrashesStatsResult, type CronJobDecorated, type CronOverviewResult, type CronRunResult, type CronRunSummary, type DashboardLiveRelease, type DashboardReleaseMethod, type DashboardResult, type DataLiftFromDevResult, type DataLiftFromLiveResult, type DataSourceConnector, type DataSourceConnectorCredentials, type DataSourceConnectorDeletions, type DataSourceConnectorGetResult, type DataSourceConnectorPolicy, type DataSourceConnectorResult, type DataSourceInspectReport, type DataSourceInspectResult, type DataSourceJob, type DataSourceJobGetResult, type DataSourceJobManifestTokenResult, type DataSourceJobPlan, type DataSourceJobResult, type DataSourceJobSource, type DataSourceJobState, type DataSourceJobsListResult, type DataSourceMapDeployResult, type DataSourceMapTestDocument, type DataSourceMapTestOutcome, type DataSourceMapTestResult, type DataSourceMapper, type DataSourceObjectSelection, type DataSourceQuarantineResult, type DataSourceQuarantinedObject, type DataSourceRemapResult, type DataSourceSyncResult, type DataSourcesBuildProgress, type DataSourcesChunkingConfig, type DataSourcesChunkingStrategy, type DataSourcesConfigResult, type DataSourcesConfigUpdateResult, type DataSourcesCreateResult, type DataSourcesDeleteResult, type DataSourcesDocument, type DataSourcesDocumentConfirmResult, type DataSourcesDocumentDeleteManyResult, type DataSourcesDocumentDeleteResult, type DataSourcesDocumentSelector, type DataSourcesDocumentStatus, type DataSourcesDocumentsResult, type DataSourcesDropResult, type DataSourcesHydrateResult, type DataSourcesHydration, type DataSourcesIndex, type DataSourcesIngestConfig, type DataSourcesIngestUpdate, type DataSourcesListEntry, type DataSourcesListResult, type DataSourcesMigration, type DataSourcesMoveResult, type DataSourcesPlacement, type DataSourcesPromoteResult, type DataSourcesRetrievalConfig, type DataSourcesRetrievalUpdate, type DataSourcesRevectorizeResult, type DataSourcesSampleResult, type DataSourcesSearchCitation, type DataSourcesSearchResult, type DataSourcesSearchResultItem, type DataSourcesUploadTokenResult, type DatasetFile, type DbQueryResult, type DiagnosticsAuditEnvironment, type DiagnosticsDashboardResult, type DiagnosticsFinding, type DiagnosticsLighthouseScores, type DiagnosticsPayload, type DiagnosticsReleaseResult, type DiagnosticsRuntimeFindings, type DomainsCheckResult, type DomainsCustomAddResult, type DomainsCustomCheckResult, type DomainsCustomHostnameUiStatus, type DomainsCustomHostnameView, type DomainsCustomListResult, type DomainsCustomRemoveResult, type DomainsCustomRetryResult, type DomainsDnsInstructions, type DomainsGetResult, type DomainsSetResult, type EmailBatchLifecycle, type EmailBatchResult, type EmailBatchSummary, type EmailBatchesResult, type EmailDomainBase, type EmailEffectiveSender, type EmailInboxResult, type EmailListResult, type EmailMessageKind, type EmailMessageResult, type EmailMessageStatus, type EmailSenderTier, type EmailSendingStatusResult, type EmailStatsResult, type EmailSummary, type EmailSuppressResult, type EmailSuppressionsResult, type EmailUnsuppressResult, type EvalAggregates, type EvalCompareResult, type EvalExpectation, type EvalQueriesAddResult, type EvalQueriesListResult, type EvalQuery, type EvalQueryResult, type EvalQueryStyle, type EvalRetrieval, type EvalRun, type EvalRunResult, type EvalRunState, type EvalRunsListResult, type EvalSet, type EvalSetGetResult, type EvalSetResult, type EvalSetState, type EvalSetsListResult, type EventChannelActivity, type EventsChannelsListResult, type EventsPublishResult, type EventsTailFrame, type FilesDeleteResult, type FilesFileMeta, type FilesListEntry, type FilesListResult, type FilesLsResult, type FilesScanBadge, type FilesScanFlagged, type FilesScanStore, type FilesStatResult, type FilesStoreSummaryEntry, type FilesUploadUrlResult, type FilesUrlResult, type FrontendErrorType, type InboundDnsInstructions, type InboundEmailDomainAddResult, type InboundEmailDomainCheckResult, type InboundEmailDomainDeleteResult, type InboundEmailDomainUiStatus, type InboundEmailDomainVerifyResult, type InboundEmailDomainView, type InboundEmailDomainsListResult, type InboxEmailPreview, type IssueAuthorKind, type IssueCommentRow, type IssueEventType, type IssueKind, type IssueRow, type IssueStatus, type IssuesCommentResult, type IssuesCreateResult, type IssuesDeleteResult, type IssuesGetResult, type IssuesListResult, type IssuesUpdateResult, type JewelPairRow, type JewelPairSummaryRow, type JewelVerdict, type JewelsDatasetSummary, type JewelsDryrunResult, type JewelsExportResult, type JewelsGradeResult, type JewelsGrading, type JewelsOverviewResult, type JewelsPairResult, type JewelsPairsResult, type JewelsQueueResult, type JewelsResolveResult, type JewelsRunResult, type JewelsRunsResult, type JewelsTimeseriesBucket, type JewelsTimeseriesResult, type JewelsTrainResult, type LiftedDatabase, type MethodsInvokeResult, type OutboundDnsInstructions, type OutboundEmailDomainAddResult, type OutboundEmailDomainCheckResult, type OutboundEmailDomainDeleteResult, type OutboundEmailDomainUiStatus, type OutboundEmailDomainVerifyResult, type OutboundEmailDomainView, type OutboundEmailDomainsListResult, type PlatformSuppression, type PrerenderGetResult, type PrerenderInvalidateResult, type PrerenderPage, type PrerenderPagesResult, type PrerenderViewResult, type ReleaseFailureFields, type ReleaseFragment, type ReleasesByCommitResult, type ReleasesGetResult, type ReleasesListResult, type RequestsGetResult, type RequestsListResult, type RequestsListRow, type RequestsStatsMethodBucket, type RequestsStatsMethodResult, type RequestsStatsSummaryBucket, type RequestsStatsSummaryResult, type SecretsDeleteResult, type SecretsGetResult, type SecretsListResult, type SecretsSetResult, type SettingsResult, type SuppressionSource, type TrainingLogEntry, type TrainingRunRow, type TrainingRunStatus, type UserAuthProvider, type UserListItem, type UserRecord, type UsersCreateApiKeyResult, type UsersListResult, type UsersRevokeApiKeyResult, type UsersSetRoleResult, type V2AppSettings, type V2BuildLogEntry, type V2BuildStats, type V2CommitInfo, type V2EmailMessage, type V2ReleaseStatus, type VoiceAvailableNumber, type VoiceNumbersBuyResult, type VoiceNumbersListResult, type VoiceNumbersReleaseResult, type VoiceNumbersSearchResult, type VoiceNumbersSetNameResult, type VoicePhoneNumberStatus, type VoicePhoneNumberView, type VoiceResolvedPolicy, type VoiceSessionChannel, type VoiceSessionCost, type VoiceSessionCostLine, type VoiceSessionDetail, type VoiceSessionGetResult, type VoiceSessionListItem, type VoiceSessionSip, type VoiceSessionSpeechEntry, type VoiceSessionStatus, type VoiceSessionToolEntry, type VoiceSessionTranscriptEntry, type VoiceSessionsListResult, type VoiceSettingsCeilings, type VoiceSettingsGetResult, type VoiceSettingsOverrides, type VoiceSettingsSetResult, admin, createAdminClient, admin as default };
7485
+ export { AdminApiError, type AdminClient, type AdminClientOptions, type AdminContext, AdminTimeoutError, type AgentThreadDetail, type AgentThreadListItem, type AgentThreadsGetResult, type AgentThreadsListResult, type AgentToolCall, type AgentTranscriptMessage, type AgentTurnError, type AnalyticsAiHostRow, type AnalyticsAiSourcesResult, type AnalyticsAiVendorRow, type AnalyticsBatchResult, type AnalyticsCrawlersOverviewResult, type AnalyticsCrawlersRecentResult, type AnalyticsCrawlersRecentRow, type AnalyticsCrawlersResult, type AnalyticsCrawlersTimeseriesBucket, type AnalyticsCrawlersTimeseriesResult, type AnalyticsLiveResult, type AnalyticsMapPoint, type AnalyticsMapResult, type AnalyticsMetric, type AnalyticsQueryResult, type AnalyticsQueryResultRow, type AnalyticsSourceRow, type AnalyticsSourcesResult, type AppCronJobStatus, type AppCronJobStatusReason, type AppCronRunState, type AppEmailSuppression, type AppSecretRow, type CrashGroup, type CrashOccurrenceRow, type CrashesGetResult, type CrashesListResult, type CrashesOccurrencesResult, type CrashesStatsBucket, type CrashesStatsResult, type CronJobDecorated, type CronOverviewResult, type CronRunResult, type CronRunSummary, type DashboardLiveRelease, type DashboardReleaseMethod, type DashboardResult, type DataLiftFromDevResult, type DataLiftFromLiveResult, type DataSourceConnector, type DataSourceConnectorCredentials, type DataSourceConnectorDeletions, type DataSourceConnectorGetResult, type DataSourceConnectorPolicy, type DataSourceConnectorResult, type DataSourceInspectReport, type DataSourceInspectResult, type DataSourceJob, type DataSourceJobGetResult, type DataSourceJobManifestTokenResult, type DataSourceJobPlan, type DataSourceJobResult, type DataSourceJobSource, type DataSourceJobState, type DataSourceJobsListResult, type DataSourceMapDeployResult, type DataSourceMapTestDocument, type DataSourceMapTestOutcome, type DataSourceMapTestResult, type DataSourceMapper, type DataSourceObjectSelection, type DataSourceQuarantineResult, type DataSourceQuarantinedObject, type DataSourceRemapResult, type DataSourceSyncResult, type DataSourcesBuildProgress, type DataSourcesChunkingConfig, type DataSourcesChunkingStrategy, type DataSourcesConfigResult, type DataSourcesConfigUpdateResult, type DataSourcesCreateResult, type DataSourcesDeleteResult, type DataSourcesDocument, type DataSourcesDocumentConfirmResult, type DataSourcesDocumentDeleteManyResult, type DataSourcesDocumentDeleteResult, type DataSourcesDocumentSelector, type DataSourcesDocumentStatus, type DataSourcesDocumentsResult, type DataSourcesDropResult, type DataSourcesHydrateResult, type DataSourcesHydration, type DataSourcesIndex, type DataSourcesIngestConfig, type DataSourcesIngestUpdate, type DataSourcesListEntry, type DataSourcesListResult, type DataSourcesMigration, type DataSourcesMoveResult, type DataSourcesPlacement, type DataSourcesPromoteResult, type DataSourcesRetrievalConfig, type DataSourcesRetrievalUpdate, type DataSourcesRevectorizeResult, type DataSourcesSampleResult, type DataSourcesSearchCitation, type DataSourcesSearchResult, type DataSourcesSearchResultItem, type DataSourcesUploadTokenResult, type DatasetFile, type DbQueryResult, type DiagnosticsAuditEnvironment, type DiagnosticsDashboardResult, type DiagnosticsFinding, type DiagnosticsLighthouseScores, type DiagnosticsPayload, type DiagnosticsReleaseResult, type DiagnosticsRuntimeFindings, type DomainsCheckResult, type DomainsCustomAddResult, type DomainsCustomCheckResult, type DomainsCustomHostnameUiStatus, type DomainsCustomHostnameView, type DomainsCustomListResult, type DomainsCustomRemoveResult, type DomainsCustomRetryResult, type DomainsDnsInstructions, type DomainsGetResult, type DomainsSetResult, type EmailBatchLifecycle, type EmailBatchResult, type EmailBatchSummary, type EmailBatchesResult, type EmailDomainBase, type EmailEffectiveSender, type EmailInboxResult, type EmailListResult, type EmailMessageKind, type EmailMessageResult, type EmailMessageStatus, type EmailSenderTier, type EmailSendingStatusResult, type EmailStatsResult, type EmailSummary, type EmailSuppressResult, type EmailSuppressionsResult, type EmailUnsuppressResult, type EvalAggregates, type EvalCompareResult, type EvalExpectation, type EvalQueriesAddResult, type EvalQueriesListResult, type EvalQuery, type EvalQueryResult, type EvalQueryStyle, type EvalRetrieval, type EvalRun, type EvalRunResult, type EvalRunState, type EvalRunsListResult, type EvalSet, type EvalSetGetResult, type EvalSetResult, type EvalSetState, type EvalSetsListResult, type EventChannelActivity, type EventsChannelsListResult, type EventsPublishResult, type EventsTailFrame, type FilesDeleteResult, type FilesFileMeta, type FilesListEntry, type FilesListResult, type FilesLsResult, type FilesScanBadge, type FilesScanFlagged, type FilesScanStore, type FilesStatResult, type FilesStoreSummaryEntry, type FilesUploadUrlResult, type FilesUrlResult, type FrontendErrorType, type InboundDnsInstructions, type InboundEmailDomainAddResult, type InboundEmailDomainCheckResult, type InboundEmailDomainDeleteResult, type InboundEmailDomainUiStatus, type InboundEmailDomainVerifyResult, type InboundEmailDomainView, type InboundEmailDomainsListResult, type InboxEmailPreview, type IssueAuthorKind, type IssueCommentRow, type IssueEventType, type IssueKind, type IssueRow, type IssueStatus, type IssuesCommentResult, type IssuesCreateResult, type IssuesDeleteResult, type IssuesGetResult, type IssuesListResult, type IssuesUpdateResult, type JewelPairRow, type JewelPairSummaryRow, type JewelVerdict, type JewelsDatasetSummary, type JewelsDryrunResult, type JewelsExportResult, type JewelsGradeResult, type JewelsGrading, type JewelsOverviewResult, type JewelsPairResult, type JewelsPairsResult, type JewelsQueueResult, type JewelsResolveResult, type JewelsRunResult, type JewelsRunsResult, type JewelsTimeseriesBucket, type JewelsTimeseriesResult, type JewelsTrainResult, type LiftedDatabase, type MethodsInvokeResult, type OperationProgress, type OutboundDnsInstructions, type OutboundEmailDomainAddResult, type OutboundEmailDomainCheckResult, type OutboundEmailDomainDeleteResult, type OutboundEmailDomainUiStatus, type OutboundEmailDomainVerifyResult, type OutboundEmailDomainView, type OutboundEmailDomainsListResult, type PlatformSuppression, type PrerenderGetResult, type PrerenderInvalidateResult, type PrerenderPage, type PrerenderPagesResult, type PrerenderViewResult, type ReleaseFailureFields, type ReleaseFragment, type ReleasesByCommitResult, type ReleasesGetResult, type ReleasesListResult, type RequestsGetResult, type RequestsListResult, type RequestsListRow, type RequestsStatsMethodBucket, type RequestsStatsMethodResult, type RequestsStatsSummaryBucket, type RequestsStatsSummaryResult, type SecretsDeleteResult, type SecretsGetResult, type SecretsListResult, type SecretsSetResult, type SettingsResult, type SuppressionSource, type TrainingLogEntry, type TrainingRunRow, type TrainingRunStatus, type UserAuthProvider, type UserListItem, type UserRecord, type UsersCreateApiKeyResult, type UsersListResult, type UsersRevokeApiKeyResult, type UsersSetRoleResult, type V2AppSettings, type V2BuildLogEntry, type V2BuildStats, type V2CommitInfo, type V2EmailMessage, type V2ReleaseStatus, type VoiceAvailableNumber, type VoiceNumbersBuyResult, type VoiceNumbersListResult, type VoiceNumbersReleaseResult, type VoiceNumbersSearchResult, type VoiceNumbersSetNameResult, type VoicePhoneNumberStatus, type VoicePhoneNumberView, type VoiceResolvedPolicy, type VoiceSessionChannel, type VoiceSessionCost, type VoiceSessionCostLine, type VoiceSessionDetail, type VoiceSessionGetResult, type VoiceSessionListItem, type VoiceSessionSip, type VoiceSessionSpeechEntry, type VoiceSessionStatus, type VoiceSessionToolEntry, type VoiceSessionTranscriptEntry, type VoiceSessionsListResult, type VoiceSettingsCeilings, type VoiceSettingsGetResult, type VoiceSettingsOverrides, type VoiceSettingsSetResult, admin, createAdminClient, admin as default };
package/dist/index.js CHANGED
@@ -393,6 +393,8 @@ function sleep(ms) {
393
393
  // src/poll.ts
394
394
  async function pollUntil(read, isSettled, options) {
395
395
  const start2 = Date.now();
396
+ let movedAt = start2;
397
+ let lastKey;
396
398
  let transientSince = null;
397
399
  while (true) {
398
400
  let value;
@@ -416,7 +418,14 @@ async function pollUntil(read, isSettled, options) {
416
418
  if (isSettled(value)) {
417
419
  return { settled: true, value };
418
420
  }
419
- if (Date.now() - start2 > options.timeoutMs) {
421
+ if (options.progressKey) {
422
+ const key = options.progressKey(value);
423
+ if (key !== lastKey) {
424
+ lastKey = key;
425
+ movedAt = Date.now();
426
+ }
427
+ }
428
+ if (Date.now() - movedAt > options.timeoutMs) {
420
429
  return { settled: false, value };
421
430
  }
422
431
  if (options.describe) {
@@ -432,6 +441,34 @@ function timedOut(timeoutMs, still) {
432
441
  return `Timed out after ${Math.round(timeoutMs / 1e3)}s ${still}`;
433
442
  }
434
443
 
444
+ // src/output.ts
445
+ var PRETTY = process.stdout.isTTY === true;
446
+ function describeEta(eta, now = Date.now()) {
447
+ if (!eta) {
448
+ return null;
449
+ }
450
+ const minutes = Math.max(1, Math.round((Date.parse(eta) - now) / 6e4));
451
+ if (minutes < 90) {
452
+ return `about ${minutes} min left`;
453
+ }
454
+ const hours = Math.round(minutes / 60 * 10) / 10;
455
+ return `about ${hours} h left`;
456
+ }
457
+ function renderProgress(p, start2, extra) {
458
+ const count = p.total !== null ? `${p.done.toLocaleString()}/${p.total.toLocaleString()} ${p.unit}` : p.done > 0 ? `${p.done.toLocaleString()} ${p.unit}` : null;
459
+ const rate = p.ratePerMinute !== null && p.ratePerMinute > 0 ? `${Math.round(p.ratePerMinute).toLocaleString()}/min` : null;
460
+ const parts = [
461
+ `${p.phase}\u2026`,
462
+ count,
463
+ rate,
464
+ describeEta(p.etaAt),
465
+ extra ?? null,
466
+ p.stalled ? "no progress for 30 min" : null
467
+ ].filter((part) => Boolean(part));
468
+ const elapsed = start2 !== void 0 ? ` (${elapsedSeconds(start2)}s)` : "";
469
+ return `${parts.join(" \xB7 ")}${elapsed}`;
470
+ }
471
+
435
472
  // src/upload.ts
436
473
  async function uploadDirect(upload, bytes, filename) {
437
474
  const form = new FormData();
@@ -534,6 +571,7 @@ async function waitForIngest(ctx, params) {
534
571
  timeoutMs,
535
572
  pollMs: POLL_MS,
536
573
  describe: (tracked2, start2) => `ingesting\u2026 ${tracked2.length - pendingOf(tracked2).length}/${tracked2.length} done (${elapsedSeconds(start2)}s)`,
574
+ progressKey: (tracked2) => pendingOf(tracked2).length,
537
575
  onProgress
538
576
  }
539
577
  );
@@ -570,6 +608,7 @@ async function waitForCandidate(ctx, params) {
570
608
  timeoutMs,
571
609
  pollMs: POLL_MS,
572
610
  describe: (progress, start2) => progress ? `rebuilding\u2026 ${progress.done}/${progress.total} done (${elapsedSeconds(start2)}s)` : `rebuilding\u2026 (${elapsedSeconds(start2)}s)`,
611
+ progressKey: (progress) => progress?.processing ?? null,
573
612
  onProgress: params.onProgress
574
613
  }
575
614
  );
@@ -722,7 +761,10 @@ async function waitForMove(ctx, params) {
722
761
  {
723
762
  timeoutMs,
724
763
  pollMs: POLL_MS,
725
- describe: (source2, start2) => `moving\u2026 ${source2.migration.copied}/${source2.migration.total} documents (${elapsedSeconds(start2)}s)`,
764
+ describe: (source2, start2) => renderProgress(source2.migration.progress, start2),
765
+ // A corpus of any size moves as long as it keeps moving; the timeout
766
+ // bounds silence.
767
+ progressKey: (source2) => source2.migration?.copied ?? null,
726
768
  onProgress: params.onProgress
727
769
  }
728
770
  );
@@ -829,6 +871,7 @@ __export(dataSourceJobs_exports, {
829
871
  list: () => list4,
830
872
  pause: () => pause,
831
873
  resume: () => resume,
874
+ retry: () => retry,
832
875
  start: () => start,
833
876
  uploadManifest: () => uploadManifest,
834
877
  waitForJob: () => waitForJob,
@@ -905,6 +948,13 @@ function resume(ctx, params) {
905
948
  controlBody(params)
906
949
  );
907
950
  }
951
+ function retry(ctx, params) {
952
+ return call(
953
+ ctx,
954
+ "POST",
955
+ `${base2(ctx.appId)}/${encodeURIComponent(params.id)}/retry`
956
+ );
957
+ }
908
958
  function cancel(ctx, params) {
909
959
  return call(
910
960
  ctx,
@@ -931,6 +981,9 @@ async function settle(ctx, params, isSettled) {
931
981
  timeoutMs,
932
982
  pollMs: POLL_MS2,
933
983
  describe: describeProgress,
984
+ // A load of any length is waited out while it moves; the timeout bounds
985
+ // silence. Planning moves by objects listed, a run by documents.
986
+ progressKey: (job2) => `${job2.state}:${job2.progress.done}`,
934
987
  onProgress: params.onProgress
935
988
  }
936
989
  );
@@ -966,14 +1019,15 @@ async function settle(ctx, params, isSettled) {
966
1019
  return { status: "done", job };
967
1020
  }
968
1021
  function describeProgress(job, start2) {
969
- const elapsed = `(${elapsedSeconds(start2)}s)`;
970
- if (job.state === "planning") {
971
- return job.enumerationDone ? `planning\u2026 reading a sample of ${job.counts.objectsSeen.toLocaleString()} objects ${elapsed}` : `planning\u2026 ${job.counts.objectsSeen.toLocaleString()} objects counted ${elapsed}`;
1022
+ if (job.state === "planning" && job.enumerationDone) {
1023
+ return renderProgress(
1024
+ { ...job.progress, phase: "planning" },
1025
+ start2,
1026
+ `reading a sample of ${job.counts.objectsSeen.toLocaleString()} objects`
1027
+ );
972
1028
  }
973
- const total = job.plan?.projected.documents ?? job.counts.objectsSeen;
974
- const processed = job.counts.documentsDone + job.counts.documentsSkipped + job.counts.documentsFailed;
975
- const spend = `$${job.estimatedDollars.toFixed(2)}${job.budgetDollars !== null ? ` of $${job.budgetDollars.toFixed(2)}` : ""}`;
976
- return `${job.state}\u2026 ${processed.toLocaleString()}/${total.toLocaleString()} documents \xB7 ${spend} ${elapsed}`;
1029
+ const spend = job.state === "planning" ? null : `$${job.estimatedDollars.toFixed(2)}${job.budgetDollars !== null ? ` of $${job.budgetDollars.toFixed(2)}` : ""}`;
1030
+ return renderProgress(job.progress, start2, spend);
977
1031
  }
978
1032
 
979
1033
  // src/ops/dataSourceConnectors.ts
@@ -1073,7 +1127,7 @@ function hydrate(ctx, params) {
1073
1127
  ctx,
1074
1128
  "POST",
1075
1129
  `${base4(ctx.appId)}/hydrate`,
1076
- { slug: params.slug, ...params.since ? { since: params.since } : {} }
1130
+ { slug: params.slug }
1077
1131
  );
1078
1132
  }
1079
1133
  function reindex(ctx, params) {
@@ -1099,7 +1153,10 @@ async function waitForHydration(ctx, params) {
1099
1153
  {
1100
1154
  timeoutMs,
1101
1155
  pollMs: POLL_MS3,
1102
- describe: (source2, start2) => `loading\u2026 ${source2.hydration.copied}/${source2.hydration.total} documents (${elapsedSeconds(start2)}s)`,
1156
+ describe: (source2, start2) => renderProgress(source2.hydration.progress, start2),
1157
+ // A reload of any size is waited out while it moves; the timeout
1158
+ // bounds silence.
1159
+ progressKey: (source2) => source2.hydration?.copied ?? null,
1103
1160
  onProgress: params.onProgress
1104
1161
  }
1105
1162
  );
@@ -1978,7 +2035,14 @@ async function waitForPhase(ctx, params) {
1978
2035
  {
1979
2036
  timeoutMs,
1980
2037
  pollMs: POLL_MS5,
1981
- describe: (resource2, start2) => `${resource2.phase}${resource2.detail ? ` \xB7 ${resource2.detail}` : ""}${resource2.resizingTo ? ` \xB7 resizing to ${resource2.resizingTo.label}` : ""}\u2026 (${elapsedSeconds(start2)}s)`,
2038
+ describe: (resource2, start2) => resource2.progress ? renderProgress(
2039
+ resource2.progress,
2040
+ start2,
2041
+ resource2.resizingTo ? `resizing to ${resource2.resizingTo.label}` : null
2042
+ ) : `${resource2.phase}${resource2.detail ? ` \xB7 ${resource2.detail}` : ""}${resource2.resizingTo ? ` \xB7 resizing to ${resource2.resizingTo.label}` : ""}\u2026 (${elapsedSeconds(start2)}s)`,
2043
+ // A rebuild after a resume runs as long as it must; the timeout bounds
2044
+ // silence, and a phase or step change counts as movement.
2045
+ progressKey: (resource2) => `${resource2.phase}:${resource2.progress?.done ?? ""}:${resource2.detail ?? ""}`,
1982
2046
  onProgress: params.onProgress
1983
2047
  }
1984
2048
  );