busa-sdk 0.52.0 → 0.53.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/airapp.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { t as BusabaseClient } from "./client-SOzg2cGv.js";
1
+ import { t as BusabaseClient } from "./client-CsSxFhUP.js";
2
2
  //#region src/airapp.d.ts
3
3
  type NodeChangeRequestInput = Parameters<BusabaseClient["nodes"]["createChangeRequest"]>[0];
4
4
  type NodeOperationInput = NodeChangeRequestInput["operations"][number];
@@ -57,8 +57,8 @@ interface AirAppFolderDeclaration {
57
57
  * an app's Folder and Bases are plain data-schema resources, safe to bring
58
58
  * into existence unattended, but an AirApp is a bundle of code the viewer's
59
59
  * browser will execute, so bringing it into existence always goes through
60
- * `publishAirApp`'s separate, always-review-first ChangeRequest instead of
61
- * riding along on the same `autoMerge: true` request as the data layer.
60
+ * `publishAirApp`'s own separate request instead of riding along on the data
61
+ * layer's structure request.
62
62
  * Declaring it here matters for a second reason regardless: without it, an
63
63
  * unstamped Folder holding the app's own AirApp would look like it holds an
64
64
  * unattributable stranger, and the legacy claim would be refused.
@@ -222,14 +222,31 @@ interface AirAppFileInput {
222
222
  content: string;
223
223
  mimeType?: string;
224
224
  }
225
+ /**
226
+ * What one publish did. `merged` is the question a caller actually has — did
227
+ * this bundle go live, or is it waiting for someone?
228
+ *
229
+ * A publish is permission-aware like every other write: it merges when the
230
+ * app's credential holds `write` on the Folder, and falls back to a pending
231
+ * ChangeRequest when it does not. The CREATE path has no change request at all
232
+ * once it merges (the node is inserted directly), which is why that branch
233
+ * carries `nodeId` instead of `changeRequestId`.
234
+ */
225
235
  type AirAppPublishResult = {
226
236
  status: "created";
237
+ merged: true;
238
+ nodeId: string;
239
+ } | {
240
+ status: "created";
241
+ merged: false;
227
242
  changeRequestId: string;
228
243
  } | {
229
244
  status: "updated";
245
+ merged: boolean;
230
246
  changeRequestId: string;
231
247
  } | {
232
248
  status: "pending";
249
+ merged: false;
233
250
  changeRequestId: string;
234
251
  };
235
252
  /**
@@ -244,9 +261,10 @@ declare function buildAirAppFileOperations(localFiles: AirAppFileInput[], deploy
244
261
  /**
245
262
  * Publish the app's own AirApp bundle: create it under the Folder when this
246
263
  * Space has never had it, or propose the local files as an update when it
247
- * already exists. Always a separate, always-review-first ChangeRequest from
248
- * the data layer's `provisionDeclaredResources` — see the note on
249
- * `AirAppNodeDeclaration` for why the two must never share a request.
264
+ * already exists. Always a separate request from the data layer's
265
+ * `provisionDeclaredResources` — see the note on `AirAppNodeDeclaration` for
266
+ * why the two must never share a request. Permission-aware: it merges when the
267
+ * app's credential can write to the Folder, and waits for review when it cannot.
250
268
  *
251
269
  * Call after `provisionDeclaredResources` has confirmed the Folder exists.
252
270
  * Every call proposes the full local file list, even when nothing actually
package/dist/airapp.js CHANGED
@@ -1,4 +1,4 @@
1
- import { t as APP_ROOT_RESOURCE_KEY } from "./template-C5oO6Au_.js";
1
+ import { t as APP_ROOT_RESOURCE_KEY } from "./template-D10kjpd-.js";
2
2
  //#region src/airapp.ts
3
3
  /**
4
4
  * AirApp resource provisioning — how an app claims (or creates) the Folder and
@@ -439,9 +439,10 @@ async function findPendingAirAppCreate(client, slug) {
439
439
  /**
440
440
  * Publish the app's own AirApp bundle: create it under the Folder when this
441
441
  * Space has never had it, or propose the local files as an update when it
442
- * already exists. Always a separate, always-review-first ChangeRequest from
443
- * the data layer's `provisionDeclaredResources` — see the note on
444
- * `AirAppNodeDeclaration` for why the two must never share a request.
442
+ * already exists. Always a separate request from the data layer's
443
+ * `provisionDeclaredResources` — see the note on `AirAppNodeDeclaration` for
444
+ * why the two must never share a request. Permission-aware: it merges when the
445
+ * app's credential can write to the Folder, and waits for review when it cannot.
445
446
  *
446
447
  * Call after `provisionDeclaredResources` has confirmed the Folder exists.
447
448
  * Every call proposes the full local file list, even when nothing actually
@@ -464,38 +465,43 @@ async function publishAirApp(client, config, files) {
464
465
  const pendingChangeRequestId = await findPendingAirAppCreate(client, airApp.slug);
465
466
  if (pendingChangeRequestId) return {
466
467
  status: "pending",
468
+ merged: false,
467
469
  changeRequestId: pendingChangeRequestId
468
470
  };
469
- const changeRequest = await client.fileTrees.create({
471
+ const result = await client.fileTrees.create({
470
472
  type: "airapp",
471
473
  parentNodeId: current.folder.nodeId,
472
474
  slug: airApp.slug,
473
475
  name: airApp.name,
474
476
  description: airApp.description ?? "",
475
477
  files,
476
- mergeMode: "replace",
477
- autoMerge: false
478
+ mergeMode: "replace"
478
479
  });
479
- if (changeRequest.materialized) throw setupError("SCHEMA_INCOMPLETE", "AirApp create unexpectedly materialized despite autoMerge: false");
480
- return {
480
+ return result.materialized ? {
481
+ status: "created",
482
+ merged: true,
483
+ nodeId: result.node.id
484
+ } : {
481
485
  status: "created",
482
- changeRequestId: changeRequest.id
486
+ merged: false,
487
+ changeRequestId: result.id
483
488
  };
484
489
  }
485
490
  const operations = buildAirAppFileOperations(files, (await client.fileTrees.listFiles({
486
491
  nodeId: current.airApp.nodeId,
487
492
  type: "airapp"
488
493
  })).map((file) => file.path));
494
+ const changeRequest = await client.fileTrees.createChangeRequest({
495
+ nodeId: current.airApp.nodeId,
496
+ type: "airapp",
497
+ operations,
498
+ message: `Publish ${config.appName} AirApp`,
499
+ submittedBy: config.appId
500
+ });
489
501
  return {
490
502
  status: "updated",
491
- changeRequestId: (await client.fileTrees.createChangeRequest({
492
- nodeId: current.airApp.nodeId,
493
- type: "airapp",
494
- operations,
495
- message: `Publish ${config.appName} AirApp`,
496
- submittedBy: config.appId,
497
- autoMerge: false
498
- })).id
503
+ merged: changeRequest.status === "merged",
504
+ changeRequestId: changeRequest.id
499
505
  };
500
506
  }
501
507
  //#endregion
@@ -39,6 +39,7 @@ declare const BUILTIN_NODE_TYPES: readonly [{
39
39
  readonly capabilities: {
40
40
  readonly container: true;
41
41
  readonly creatable: true;
42
+ readonly commonlyCreated: true;
42
43
  readonly hasDetail: true;
43
44
  readonly publicAccess: "detail";
44
45
  };
@@ -50,6 +51,7 @@ declare const BUILTIN_NODE_TYPES: readonly [{
50
51
  readonly capabilities: {
51
52
  readonly hasDetail: true;
52
53
  readonly creatable: true;
54
+ readonly commonlyCreated: true;
53
55
  readonly publicAccess: "detail";
54
56
  };
55
57
  readonly operations: readonly [{
@@ -206,6 +208,7 @@ declare const BUILTIN_NODE_TYPES: readonly [{
206
208
  readonly capabilities: {
207
209
  readonly hasDetail: true;
208
210
  readonly creatable: true;
211
+ readonly commonlyCreated: true;
209
212
  readonly publicAccess: "detail";
210
213
  };
211
214
  readonly operations: readonly [];
@@ -216,6 +219,7 @@ declare const BUILTIN_NODE_TYPES: readonly [{
216
219
  readonly capabilities: {
217
220
  readonly hasDetail: true;
218
221
  readonly creatable: true;
222
+ readonly commonlyCreated: true;
219
223
  readonly publicAccess: "detail";
220
224
  };
221
225
  readonly operations: readonly [{
@@ -231,6 +235,7 @@ declare const BUILTIN_NODE_TYPES: readonly [{
231
235
  readonly hasDetail: true;
232
236
  readonly creatable: true;
233
237
  readonly publicAccess: "submit";
238
+ readonly hidden: true;
234
239
  };
235
240
  readonly operations: readonly [];
236
241
  }, {
@@ -615,6 +620,21 @@ declare const cloudContract: {
615
620
  slug: z.ZodString;
616
621
  path: z.ZodString;
617
622
  updatedAt: z.ZodString;
623
+ icon: z.ZodOptional<z.ZodNullable<z.ZodDiscriminatedUnion<[z.ZodObject<{
624
+ type: z.ZodLiteral<"emoji">;
625
+ value: z.ZodString;
626
+ }, z.core.$strip>, z.ZodObject<{
627
+ type: z.ZodLiteral<"attachment">;
628
+ url: z.ZodString;
629
+ attachmentId: z.ZodString;
630
+ originalUrl: z.ZodOptional<z.ZodString>;
631
+ originalAttachmentId: z.ZodOptional<z.ZodString>;
632
+ crop: z.ZodOptional<z.ZodObject<{
633
+ x: z.ZodNumber;
634
+ y: z.ZodNumber;
635
+ zoom: z.ZodNumber;
636
+ }, z.core.$strip>>;
637
+ }, z.core.$strip>], "type">>>;
618
638
  }, z.core.$strip>>, import("@orpc/contract").MergedErrorMap<Record<never, never>, Record<never, never>>, Record<never, never>>;
619
639
  isDescendant: import("@orpc/contract").ContractProcedure<z.ZodObject<{
620
640
  nodeId: z.ZodString;
@@ -10723,6 +10743,7 @@ declare const cloudContract: {
10723
10743
  targetBaseId: z.ZodOptional<z.ZodString>;
10724
10744
  targetBaseSlug: z.ZodOptional<z.ZodString>;
10725
10745
  }, z.core.$strip>>>;
10746
+ type: z.ZodOptional<z.ZodNever>;
10726
10747
  }, z.core.$strip>;
10727
10748
  message: z.ZodOptional<z.ZodString>;
10728
10749
  submittedBy: z.ZodDefault<z.ZodOptional<z.ZodString>>;
@@ -11711,6 +11732,54 @@ declare const cloudContract: {
11711
11732
  }, z.core.$strip>, import("@orpc/contract").MergedErrorMap<Record<never, never>, Record<never, never>>, Record<never, never>>;
11712
11733
  };
11713
11734
  fileTrees: {
11735
+ previewConfig: import("@orpc/contract").ContractProcedure<import("@orpc/contract").Schema<unknown, unknown>, z.ZodObject<{
11736
+ provider: z.ZodEnum<{
11737
+ builtin: "builtin";
11738
+ previewfile: "previewfile";
11739
+ }>;
11740
+ status: z.ZodEnum<{
11741
+ invalid_configuration: "invalid_configuration";
11742
+ not_configured: "not_configured";
11743
+ ready: "ready";
11744
+ }>;
11745
+ credentialSource: z.ZodEnum<{
11746
+ environment: "environment";
11747
+ none: "none";
11748
+ vault: "vault";
11749
+ }>;
11750
+ credentialConfigured: z.ZodBoolean;
11751
+ maxFileSizeBytes: z.ZodNumber;
11752
+ sessionTtlMinutes: z.ZodNumber;
11753
+ vaultEncryptionConfigured: z.ZodNullable<z.ZodBoolean>;
11754
+ }, z.core.$strip>, import("@orpc/contract").MergedErrorMap<Record<never, never>, Record<never, never>>, Record<never, never>>;
11755
+ preparePreview: import("@orpc/contract").ContractProcedure<z.ZodObject<{
11756
+ nodeId: z.ZodString;
11757
+ filePath: z.ZodString;
11758
+ type: z.ZodLiteral<"drive">;
11759
+ }, z.core.$strip>, z.ZodDiscriminatedUnion<[z.ZodObject<{
11760
+ state: z.ZodLiteral<"builtin">;
11761
+ provider: z.ZodLiteral<"builtin">;
11762
+ }, z.core.$strip>, z.ZodObject<{
11763
+ state: z.ZodLiteral<"ready">;
11764
+ provider: z.ZodLiteral<"previewfile">;
11765
+ previewUrl: z.ZodString;
11766
+ expiresAt: z.ZodString;
11767
+ }, z.core.$strip>, z.ZodObject<{
11768
+ state: z.ZodLiteral<"unavailable">;
11769
+ provider: z.ZodLiteral<"previewfile">;
11770
+ reason: z.ZodEnum<{
11771
+ authentication_failed: "authentication_failed";
11772
+ file_too_large: "file_too_large";
11773
+ invalid_configuration: "invalid_configuration";
11774
+ invalid_response: "invalid_response";
11775
+ not_configured: "not_configured";
11776
+ rate_limited: "rate_limited";
11777
+ service_unavailable: "service_unavailable";
11778
+ timeout: "timeout";
11779
+ unsupported: "unsupported";
11780
+ }>;
11781
+ retryable: z.ZodBoolean;
11782
+ }, z.core.$strip>], "state">, import("@orpc/contract").MergedErrorMap<Record<never, never>, Record<never, never>>, Record<never, never>>;
11714
11783
  create: import("@orpc/contract").ContractProcedure<z.ZodObject<{
11715
11784
  parentNodeId: z.ZodOptional<z.ZodString>;
11716
11785
  slug: z.ZodString;
@@ -14076,7 +14145,11 @@ declare const cloudContract: {
14076
14145
  nodeId: z.ZodString;
14077
14146
  }, z.core.$strip>, z.ZodObject<{
14078
14147
  changeRequestId: z.ZodString;
14079
- status: z.ZodLiteral<"pending_review">;
14148
+ status: z.ZodEnum<{
14149
+ merged: "merged";
14150
+ pending_review: "pending_review";
14151
+ }>;
14152
+ recordId: z.ZodOptional<z.ZodString>;
14080
14153
  }, z.core.$strip>, import("@orpc/contract").MergedErrorMap<Record<never, never>, Record<never, never>>, Record<never, never>>;
14081
14154
  };
14082
14155
  assets: {
@@ -14788,6 +14861,15 @@ declare const cloudContract: {
14788
14861
  createdAt: z.ZodString;
14789
14862
  lastActivityAt: z.ZodString;
14790
14863
  error: z.ZodDefault<z.ZodNullable<z.ZodString>>;
14864
+ modelOption: z.ZodDefault<z.ZodNullable<z.ZodObject<{
14865
+ id: z.ZodString;
14866
+ name: z.ZodString;
14867
+ currentValue: z.ZodString;
14868
+ options: z.ZodArray<z.ZodObject<{
14869
+ value: z.ZodString;
14870
+ name: z.ZodString;
14871
+ }, z.core.$strip>>;
14872
+ }, z.core.$strip>>>;
14791
14873
  }, z.core.$strip>>;
14792
14874
  ownedByCurrentUser: z.ZodBoolean;
14793
14875
  }, z.core.$strip>>, import("@orpc/contract").MergedErrorMap<Record<never, never>, Record<never, never>>, Record<never, never>>;
@@ -14812,6 +14894,15 @@ declare const cloudContract: {
14812
14894
  createdAt: z.ZodString;
14813
14895
  lastActivityAt: z.ZodString;
14814
14896
  error: z.ZodDefault<z.ZodNullable<z.ZodString>>;
14897
+ modelOption: z.ZodDefault<z.ZodNullable<z.ZodObject<{
14898
+ id: z.ZodString;
14899
+ name: z.ZodString;
14900
+ currentValue: z.ZodString;
14901
+ options: z.ZodArray<z.ZodObject<{
14902
+ value: z.ZodString;
14903
+ name: z.ZodString;
14904
+ }, z.core.$strip>>;
14905
+ }, z.core.$strip>>>;
14815
14906
  }, z.core.$strip>>, import("@orpc/contract").MergedErrorMap<Record<never, never>, Record<never, never>>, Record<never, never>>;
14816
14907
  create: import("@orpc/contract").ContractProcedure<z.ZodObject<{
14817
14908
  slug: z.ZodString;
@@ -14834,6 +14925,15 @@ declare const cloudContract: {
14834
14925
  createdAt: z.ZodString;
14835
14926
  lastActivityAt: z.ZodString;
14836
14927
  error: z.ZodDefault<z.ZodNullable<z.ZodString>>;
14928
+ modelOption: z.ZodDefault<z.ZodNullable<z.ZodObject<{
14929
+ id: z.ZodString;
14930
+ name: z.ZodString;
14931
+ currentValue: z.ZodString;
14932
+ options: z.ZodArray<z.ZodObject<{
14933
+ value: z.ZodString;
14934
+ name: z.ZodString;
14935
+ }, z.core.$strip>>;
14936
+ }, z.core.$strip>>>;
14837
14937
  }, z.core.$strip>, import("@orpc/contract").MergedErrorMap<Record<never, never>, Record<never, never>>, Record<never, never>>;
14838
14938
  prompt: import("@orpc/contract").ContractProcedure<z.ZodObject<{
14839
14939
  sessionId: z.ZodString;
@@ -14869,6 +14969,39 @@ declare const cloudContract: {
14869
14969
  }, z.core.$strip>, z.ZodObject<{
14870
14970
  ok: z.ZodBoolean;
14871
14971
  }, z.core.$strip>, import("@orpc/contract").MergedErrorMap<Record<never, never>, Record<never, never>>, Record<never, never>>;
14972
+ setConfigOption: import("@orpc/contract").ContractProcedure<z.ZodObject<{
14973
+ sessionId: z.ZodString;
14974
+ configId: z.ZodString;
14975
+ value: z.ZodString;
14976
+ }, z.core.$strip>, z.ZodObject<{
14977
+ id: z.ZodString;
14978
+ slug: z.ZodString;
14979
+ agentName: z.ZodString;
14980
+ transport: z.ZodEnum<{
14981
+ "local-subprocess": "local-subprocess";
14982
+ "remote-websocket": "remote-websocket";
14983
+ }>;
14984
+ status: z.ZodEnum<{
14985
+ busy: "busy";
14986
+ connecting: "connecting";
14987
+ ended: "ended";
14988
+ failed: "failed";
14989
+ idle: "idle";
14990
+ waiting_permission: "waiting_permission";
14991
+ }>;
14992
+ createdAt: z.ZodString;
14993
+ lastActivityAt: z.ZodString;
14994
+ error: z.ZodDefault<z.ZodNullable<z.ZodString>>;
14995
+ modelOption: z.ZodDefault<z.ZodNullable<z.ZodObject<{
14996
+ id: z.ZodString;
14997
+ name: z.ZodString;
14998
+ currentValue: z.ZodString;
14999
+ options: z.ZodArray<z.ZodObject<{
15000
+ value: z.ZodString;
15001
+ name: z.ZodString;
15002
+ }, z.core.$strip>>;
15003
+ }, z.core.$strip>>>;
15004
+ }, z.core.$strip>, import("@orpc/contract").MergedErrorMap<Record<never, never>, Record<never, never>>, Record<never, never>>;
14872
15005
  subscribe: import("@orpc/contract").ContractProcedure<z.ZodObject<{
14873
15006
  sessionId: z.ZodString;
14874
15007
  afterSeq: z.ZodDefault<z.ZodNumber>;
@@ -15602,6 +15735,52 @@ declare const cloudContract: {
15602
15735
  pendingChangeRequests: z.ZodNumber;
15603
15736
  warnings: z.ZodDefault<z.ZodArray<z.ZodString>>;
15604
15737
  }, z.core.$strip>, import("@orpc/contract").MergedErrorMap<Record<never, never>, Record<never, never>>, Record<never, never>>;
15738
+ fromGithubStream: import("@orpc/contract").ContractProcedure<z.ZodObject<{
15739
+ repoUrl: z.ZodString;
15740
+ intoFolder: z.ZodOptional<z.ZodString>;
15741
+ rename: z.ZodOptional<z.ZodBoolean>;
15742
+ autoMerge: z.ZodOptional<z.ZodBoolean>;
15743
+ }, z.core.$strip>, import("@orpc/contract").Schema<AsyncIteratorObject<{
15744
+ kind: "progress";
15745
+ message: string;
15746
+ } | {
15747
+ kind: "done";
15748
+ result: {
15749
+ targetFolderSlug: string;
15750
+ targetFolderNodeId: string;
15751
+ created: {
15752
+ folders: number;
15753
+ docs: number;
15754
+ bases: number;
15755
+ views: number;
15756
+ records: number;
15757
+ fileTreeNodes: number;
15758
+ files: number;
15759
+ };
15760
+ pendingChangeRequests: number;
15761
+ warnings?: string[] | undefined;
15762
+ };
15763
+ }, unknown, void>, AsyncIteratorClass<{
15764
+ kind: "progress";
15765
+ message: string;
15766
+ } | {
15767
+ kind: "done";
15768
+ result: {
15769
+ targetFolderSlug: string;
15770
+ targetFolderNodeId: string;
15771
+ created: {
15772
+ folders: number;
15773
+ docs: number;
15774
+ bases: number;
15775
+ views: number;
15776
+ records: number;
15777
+ fileTreeNodes: number;
15778
+ files: number;
15779
+ };
15780
+ pendingChangeRequests: number;
15781
+ warnings: string[];
15782
+ };
15783
+ }, unknown, void>>, import("@orpc/contract").MergedErrorMap<Record<never, never>, Record<never, never>>, Record<never, never>>;
15605
15784
  };
15606
15785
  templates: {
15607
15786
  list: import("@orpc/contract").ContractProcedure<z.ZodDefault<z.ZodOptional<z.ZodObject<{
@@ -15641,6 +15820,7 @@ declare const cloudContract: {
15641
15820
  }>>;
15642
15821
  tags: z.ZodDefault<z.ZodArray<z.ZodString>>;
15643
15822
  screenshots: z.ZodDefault<z.ZodArray<z.ZodString>>;
15823
+ video: z.ZodOptional<z.ZodString>;
15644
15824
  agentPrompts: z.ZodDefault<z.ZodArray<z.ZodString>>;
15645
15825
  version: z.ZodOptional<z.ZodString>;
15646
15826
  author: z.ZodOptional<z.ZodString>;
@@ -23110,10 +23290,24 @@ declare const SubmitFormInputSchema: z.ZodObject<{
23110
23290
  captchaToken: z.ZodOptional<z.ZodString>;
23111
23291
  }, z.core.$strip>;
23112
23292
  type SubmitFormDTO = z.input<typeof SubmitFormInputSchema>;
23113
- /** What the submit endpoint returns — the pending ChangeRequest id, never data. */
23293
+ /**
23294
+ * What the submit endpoint returns — a ChangeRequest id and what happened to it,
23295
+ * never the record data.
23296
+ *
23297
+ * `status` is permission-aware, like every other write: `merged` when the
23298
+ * submitter holds `write` on the target Base and the submission landed straight
23299
+ * away, `pending_review` when it is waiting for a human. An ANONYMOUS visitor can
23300
+ * never reach `merged`: permission is resolved against the target Base, which a
23301
+ * form does not share publicly, and a public-link request is capped at `read`
23302
+ * even where it is shared. So a public form still always waits.
23303
+ */
23114
23304
  declare const FormSubmitResultSchema: z.ZodObject<{
23115
23305
  changeRequestId: z.ZodString;
23116
- status: z.ZodLiteral<"pending_review">;
23306
+ status: z.ZodEnum<{
23307
+ merged: "merged";
23308
+ pending_review: "pending_review";
23309
+ }>;
23310
+ recordId: z.ZodOptional<z.ZodString>;
23117
23311
  }, z.core.$strip>;
23118
23312
  type FormSubmitResultVO = z.infer<typeof FormSubmitResultSchema>;
23119
23313
  //#endregion
@@ -24789,6 +24983,33 @@ declare const NodeDetailVOSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
24789
24983
  type NodeDetailVO = z.infer<typeof NodeDetailVOSchema>;
24790
24984
  //#endregion
24791
24985
  //#region ../../packages/busabase-contract/src/domains/filetree/types.d.ts
24986
+ type FilePreviewProvider = "builtin" | "previewfile";
24987
+ type FilePreviewCredentialSource = "environment" | "vault" | "none";
24988
+ type FilePreviewConfigurationStatus = "ready" | "not_configured" | "invalid_configuration";
24989
+ type FilePreviewUnavailableReason = "not_configured" | "invalid_configuration" | "file_too_large" | "unsupported" | "authentication_failed" | "rate_limited" | "timeout" | "service_unavailable" | "invalid_response";
24990
+ interface FilePreviewConfigVO {
24991
+ provider: FilePreviewProvider;
24992
+ status: FilePreviewConfigurationStatus;
24993
+ credentialSource: FilePreviewCredentialSource;
24994
+ credentialConfigured: boolean;
24995
+ maxFileSizeBytes: number;
24996
+ sessionTtlMinutes: number;
24997
+ vaultEncryptionConfigured: boolean | null;
24998
+ }
24999
+ type FilePreviewVO = {
25000
+ state: "builtin";
25001
+ provider: "builtin";
25002
+ } | {
25003
+ state: "ready";
25004
+ provider: "previewfile";
25005
+ previewUrl: string;
25006
+ expiresAt: string;
25007
+ } | {
25008
+ state: "unavailable";
25009
+ provider: "previewfile";
25010
+ reason: FilePreviewUnavailableReason;
25011
+ retryable: boolean;
25012
+ };
24792
25013
  interface FileTreeFileVO {
24793
25014
  path: string;
24794
25015
  name: string;
@@ -25087,6 +25308,10 @@ declare const UpdateVaultSettingsInputSchema: z.ZodObject<{
25087
25308
  }, z.core.$strip>>;
25088
25309
  }, z.core.$strip>;
25089
25310
  type UpdateVaultSettingsDTO = z.infer<typeof UpdateVaultSettingsInputSchema>;
25311
+ declare const UpdatePreviewFileCredentialInputSchema: z.ZodObject<{
25312
+ apiKey: z.ZodNullable<z.ZodString>;
25313
+ }, z.core.$strip>;
25314
+ type UpdatePreviewFileCredentialDTO = z.infer<typeof UpdatePreviewFileCredentialInputSchema>;
25090
25315
  declare const VaultItemVOSchema: z.ZodObject<{
25091
25316
  kind: z.ZodEnum<{
25092
25317
  secret: "secret";
@@ -25203,6 +25428,8 @@ interface NodeSearchResultVO {
25203
25428
  slug: string;
25204
25429
  path: string;
25205
25430
  updatedAt: string;
25431
+ /** Optional: absent on an older server response. See `NodeVO.icon`. */
25432
+ icon?: NodeIcon | null;
25206
25433
  }
25207
25434
  interface NodeVO {
25208
25435
  id: string;
@@ -25591,4 +25818,4 @@ declare function resolveConfig(config?: BusabaseConfig): ResolvedConfig;
25591
25818
  */
25592
25819
  declare function createBusabaseClient(config?: BusabaseConfig): BusabaseClient;
25593
25820
  //#endregion
25594
- export { AssetUsageVO as $, NodeVO as A, ViewConfigVO as At, UpdateVaultSettingsDTO as B, NodeIconSchema as Bt, CommentVO as C, GalleryCardSize as Ct, MentionInboxItemVO as D, RecordVO as Dt, LookupRollup as E, RecordLinkVO as Et, SearchResponseVO as F, ViewVO as Ft, VaultItemVO as G, VaultEnvironment as H, CreatableNodeType as Ht, SearchResultKind as I, AttachmentRef as It, VaultSettingsVO as J, VaultRuntimeEnv as K, SearchResultVO as L, CloudContract as Lt, OperationVO as M, ViewFilterVO as Mt, ReviewVO as N, ViewSortVO as Nt, MentionInboxPageVO as O, VIEW_FIELD_MAX_WIDTH as Ot, ReviewVerdict as P, ViewType as Pt, AssetTextStatus as Q, SourceAttributionVO as R, cloudContract as Rt, CommentSubjectType as S, BaseVO as St, FieldType as T, GanttScale as Tt, VaultItemInput as U, NodeType as Ut, VaultAccessPolicy as V, CREATABLE_NODE_TYPES as Vt, VaultItemKind as W, OperationKind as Wt, FileNodeVO as X, FileNodeMetadata as Y, AssetDetailVO as Z, ChangeRequestVO as _, ListFormsVO as _t, createBusabaseClient as a, FileTreeReadFileVO as at, CommentMentionTargetType as b, AssetAttachmentRef as bt, AuditAction as c, CreateFormDTO as ct, ChangeRequestBatchFailureVO as d, FormPageSourceVO as dt, AssetVO as et, ChangeRequestCountsVO as f, FormShareVO as ft, ChangeRequestTargetType as g, ListFormsDTO as gt, ChangeRequestStatus as h, FormVO as ht, ResolvedConfig as i, FileTreeNodeVO as it, OperationStatus as j, ViewFilterOperator as jt, NodeSearchResultVO as k, VIEW_FIELD_MIN_WIDTH as kt, AuditEventVO as l, FormBoundFieldVO as lt, ChangeRequestReviewBatchResultVO as m, FormThemeVO as mt, BusabaseConfig as n, GrepResultVO as nt, resolveConfig as o, NodeDetailVO as ot, ChangeRequestMergeBatchResultVO as p, FormSubmitResultVO as pt, VaultScopeType as q, DEFAULT_BASE_URL as r, FileTreeFileVO as rt, AgentTaskVO as s, ActivityItemVO as st, BusabaseClient as t, GrepInputDTO as tt, BusabaseSourceChannel as u, FormFieldBindingVO as ut, CommentMentionDispatchStatus as v, SubmitFormDTO as vt, CommitVO as w, GalleryCoverFit as wt, CommentMentionVO as x, BaseFieldVO as xt, CommentMentionInputDTO as y, UpdateFormDTO as yt, UserRefVO as z, NodeIcon as zt };
25821
+ export { AssetTextStatus as $, NodeVO as A, GalleryCardSize as At, UpdatePreviewFileCredentialDTO as B, ViewSortVO as Bt, CommentVO as C, ListFormsDTO as Ct, MentionInboxItemVO as D, AssetAttachmentRef as Dt, LookupRollup as E, UpdateFormDTO as Et, SearchResponseVO as F, VIEW_FIELD_MAX_WIDTH as Ft, VaultItemKind as G, cloudContract as Gt, VaultAccessPolicy as H, ViewVO as Ht, SearchResultKind as I, VIEW_FIELD_MIN_WIDTH as It, VaultScopeType as J, CREATABLE_NODE_TYPES as Jt, VaultItemVO as K, NodeIcon as Kt, SearchResultVO as L, ViewConfigVO as Lt, OperationVO as M, GanttScale as Mt, ReviewVO as N, RecordLinkVO as Nt, MentionInboxPageVO as O, BaseFieldVO as Ot, ReviewVerdict as P, RecordVO as Pt, AssetDetailVO as Q, SourceAttributionVO as R, ViewFilterOperator as Rt, CommentSubjectType as S, FormVO as St, FieldType as T, SubmitFormDTO as Tt, VaultEnvironment as U, AttachmentRef as Ut, UpdateVaultSettingsDTO as V, ViewType as Vt, VaultItemInput as W, CloudContract as Wt, FileNodeMetadata as X, NodeType as Xt, VaultSettingsVO as Y, CreatableNodeType as Yt, FileNodeVO as Z, OperationKind as Zt, ChangeRequestVO as _, FormFieldBindingVO as _t, createBusabaseClient as a, FilePreviewConfigurationStatus as at, CommentMentionTargetType as b, FormSubmitResultVO as bt, AuditAction as c, FilePreviewUnavailableReason as ct, ChangeRequestBatchFailureVO as d, FileTreeNodeVO as dt, AssetUsageVO as et, ChangeRequestCountsVO as f, FileTreeReadFileVO as ft, ChangeRequestTargetType as g, FormBoundFieldVO as gt, ChangeRequestStatus as h, CreateFormDTO as ht, ResolvedConfig as i, FilePreviewConfigVO as it, OperationStatus as j, GalleryCoverFit as jt, NodeSearchResultVO as k, BaseVO as kt, AuditEventVO as l, FilePreviewVO as lt, ChangeRequestReviewBatchResultVO as m, ActivityItemVO as mt, BusabaseConfig as n, GrepInputDTO as nt, resolveConfig as o, FilePreviewCredentialSource as ot, ChangeRequestMergeBatchResultVO as p, NodeDetailVO as pt, VaultRuntimeEnv as q, NodeIconSchema as qt, DEFAULT_BASE_URL as r, GrepResultVO as rt, AgentTaskVO as s, FilePreviewProvider as st, BusabaseClient as t, AssetVO as tt, BusabaseSourceChannel as u, FileTreeFileVO as ut, CommentMentionDispatchStatus as v, FormPageSourceVO as vt, CommitVO as w, ListFormsVO as wt, CommentMentionVO as x, FormThemeVO as xt, CommentMentionInputDTO as y, FormShareVO as yt, UserRefVO as z, ViewFilterVO as zt };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { $ as AssetUsageVO, A as NodeVO, At as ViewConfigVO, B as UpdateVaultSettingsDTO, Bt as NodeIconSchema, C as CommentVO, Ct as GalleryCardSize, D as MentionInboxItemVO, Dt as RecordVO, E as LookupRollup, Et as RecordLinkVO, F as SearchResponseVO, Ft as ViewVO, G as VaultItemVO, H as VaultEnvironment, Ht as CreatableNodeType, I as SearchResultKind, It as AttachmentRef, J as VaultSettingsVO, K as VaultRuntimeEnv, L as SearchResultVO, Lt as CloudContract, M as OperationVO, Mt as ViewFilterVO, N as ReviewVO, Nt as ViewSortVO, O as MentionInboxPageVO, Ot as VIEW_FIELD_MAX_WIDTH, P as ReviewVerdict, Pt as ViewType, Q as AssetTextStatus, R as SourceAttributionVO, Rt as cloudContract, S as CommentSubjectType, St as BaseVO, T as FieldType, Tt as GanttScale, U as VaultItemInput, Ut as NodeType, V as VaultAccessPolicy, Vt as CREATABLE_NODE_TYPES, W as VaultItemKind, Wt as OperationKind, X as FileNodeVO, Y as FileNodeMetadata, Z as AssetDetailVO, _ as ChangeRequestVO, _t as ListFormsVO, a as createBusabaseClient, at as FileTreeReadFileVO, b as CommentMentionTargetType, bt as AssetAttachmentRef, c as AuditAction, ct as CreateFormDTO, d as ChangeRequestBatchFailureVO, dt as FormPageSourceVO, et as AssetVO, f as ChangeRequestCountsVO, ft as FormShareVO, g as ChangeRequestTargetType, gt as ListFormsDTO, h as ChangeRequestStatus, ht as FormVO, i as ResolvedConfig, it as FileTreeNodeVO, j as OperationStatus, jt as ViewFilterOperator, k as NodeSearchResultVO, kt as VIEW_FIELD_MIN_WIDTH, l as AuditEventVO, lt as FormBoundFieldVO, m as ChangeRequestReviewBatchResultVO, mt as FormThemeVO, n as BusabaseConfig, nt as GrepResultVO, o as resolveConfig, ot as NodeDetailVO, p as ChangeRequestMergeBatchResultVO, pt as FormSubmitResultVO, q as VaultScopeType, r as DEFAULT_BASE_URL, rt as FileTreeFileVO, s as AgentTaskVO, st as ActivityItemVO, t as BusabaseClient, tt as GrepInputDTO, u as BusabaseSourceChannel, ut as FormFieldBindingVO, v as CommentMentionDispatchStatus, vt as SubmitFormDTO, w as CommitVO, wt as GalleryCoverFit, x as CommentMentionVO, xt as BaseFieldVO, y as CommentMentionInputDTO, yt as UpdateFormDTO, z as UserRefVO, zt as NodeIcon } from "./client-SOzg2cGv.js";
1
+ import { $ as AssetTextStatus, A as NodeVO, At as GalleryCardSize, B as UpdatePreviewFileCredentialDTO, Bt as ViewSortVO, C as CommentVO, Ct as ListFormsDTO, D as MentionInboxItemVO, Dt as AssetAttachmentRef, E as LookupRollup, Et as UpdateFormDTO, F as SearchResponseVO, Ft as VIEW_FIELD_MAX_WIDTH, G as VaultItemKind, Gt as cloudContract, H as VaultAccessPolicy, Ht as ViewVO, I as SearchResultKind, It as VIEW_FIELD_MIN_WIDTH, J as VaultScopeType, Jt as CREATABLE_NODE_TYPES, K as VaultItemVO, Kt as NodeIcon, L as SearchResultVO, Lt as ViewConfigVO, M as OperationVO, Mt as GanttScale, N as ReviewVO, Nt as RecordLinkVO, O as MentionInboxPageVO, Ot as BaseFieldVO, P as ReviewVerdict, Pt as RecordVO, Q as AssetDetailVO, R as SourceAttributionVO, Rt as ViewFilterOperator, S as CommentSubjectType, St as FormVO, T as FieldType, Tt as SubmitFormDTO, U as VaultEnvironment, Ut as AttachmentRef, V as UpdateVaultSettingsDTO, Vt as ViewType, W as VaultItemInput, Wt as CloudContract, X as FileNodeMetadata, Xt as NodeType, Y as VaultSettingsVO, Yt as CreatableNodeType, Z as FileNodeVO, Zt as OperationKind, _ as ChangeRequestVO, _t as FormFieldBindingVO, a as createBusabaseClient, at as FilePreviewConfigurationStatus, b as CommentMentionTargetType, bt as FormSubmitResultVO, c as AuditAction, ct as FilePreviewUnavailableReason, d as ChangeRequestBatchFailureVO, dt as FileTreeNodeVO, et as AssetUsageVO, f as ChangeRequestCountsVO, ft as FileTreeReadFileVO, g as ChangeRequestTargetType, gt as FormBoundFieldVO, h as ChangeRequestStatus, ht as CreateFormDTO, i as ResolvedConfig, it as FilePreviewConfigVO, j as OperationStatus, jt as GalleryCoverFit, k as NodeSearchResultVO, kt as BaseVO, l as AuditEventVO, lt as FilePreviewVO, m as ChangeRequestReviewBatchResultVO, mt as ActivityItemVO, n as BusabaseConfig, nt as GrepInputDTO, o as resolveConfig, ot as FilePreviewCredentialSource, p as ChangeRequestMergeBatchResultVO, pt as NodeDetailVO, q as VaultRuntimeEnv, qt as NodeIconSchema, r as DEFAULT_BASE_URL, rt as GrepResultVO, s as AgentTaskVO, st as FilePreviewProvider, t as BusabaseClient, tt as AssetVO, u as BusabaseSourceChannel, ut as FileTreeFileVO, v as CommentMentionDispatchStatus, vt as FormPageSourceVO, w as CommitVO, wt as ListFormsVO, x as CommentMentionVO, xt as FormThemeVO, y as CommentMentionInputDTO, yt as FormShareVO, z as UserRefVO, zt as ViewFilterVO } from "./client-CsSxFhUP.js";
2
2
  import { z } from "zod";
3
3
  //#region src/url.d.ts
4
4
  /**
@@ -426,4 +426,4 @@ declare class Busabase {
426
426
  }>>>>;
427
427
  }
428
428
  //#endregion
429
- export { type ActivityItemVO, type AgentTaskVO, type FileTreeFileVO as AirAppFileVO, type FileTreeFileVO as DriveFileVO, type FileTreeFileVO, type FileTreeFileVO as SkillFileVO, type FileTreeReadFileVO as AirAppReadFileVO, type FileTreeReadFileVO as DriveReadFileVO, type FileTreeReadFileVO, type FileTreeReadFileVO as SkillReadFileVO, type FileTreeNodeVO as AirAppVO, type FileTreeNodeVO as DriveVO, type FileTreeNodeVO, type FileTreeNodeVO as SkillVO, type AssetAttachmentRef, type AssetDetailVO, type AssetTextStatus, type AssetUsageVO, type AssetVO, type AttachmentRef, type AuditAction, type AuditEventVO, type BaseFieldVO, type BaseVO, Busabase, type BusabaseAssetsClient, BusabaseChangeRequestsClient, type BusabaseClient, type BusabaseConfig, type BusabaseRecordsClient, type BusabaseSourceChannel, CREATABLE_NODE_TYPES, type ChangeRequestBatchFailureVO, type ChangeRequestCountsVO, type ChangeRequestMergeBatchResultVO, type ChangeRequestReviewBatchResultVO, type ChangeRequestStatus, type ChangeRequestTargetType, type ChangeRequestVO, type CloudContract, type CommentMentionDispatchStatus, type CommentMentionInputDTO, type CommentMentionTargetType, type CommentMentionVO, type CommentSubjectType, type CommentVO, type CommitVO, type CreatableNodeType, type CreateFormDTO, DEFAULT_BASE_URL, type FieldType, type FileNodeMetadata, type FileNodeVO, type FormBoundFieldVO, type FormFieldBindingVO, type FormPageSourceVO, type FormShareVO, type FormSubmitResultVO, type FormThemeVO, type FormVO, type GalleryCardSize, type GalleryCoverFit, type GanttScale, type ListFormsDTO, type ListFormsVO, type LookupRollup, type MentionInboxItemVO, type MentionInboxPageVO, type NodeDetailVO, type NodeIcon, type NodeIconSchema, type NodeSearchResultVO, type NodeType, type NodeVO, type NodeWebUrlInput, type OperationKind, type OperationStatus, type OperationVO, type RecordByFieldInput, type RecordLinkVO, type RecordVO, type ResolvedConfig, type ReviewVO, type ReviewVerdict, type SearchResponseVO, type SearchResultKind, type SearchResultVO, type SourceAttributionVO, type SubmitFormDTO, type UpdateFormDTO, type UpdateVaultSettingsDTO, type UserRefVO, type VIEW_FIELD_MAX_WIDTH, type VIEW_FIELD_MIN_WIDTH, type VaultAccessPolicy, type VaultEnvironment, type VaultItemInput, type VaultItemKind, type VaultItemVO, type VaultRuntimeEnv, type VaultScopeType, type VaultSettingsVO, type ViewConfigVO, type ViewFilterOperator, type ViewFilterVO, type ViewSortVO, type ViewType, type ViewVO, cloudContract, createBusabaseClient, getRecordByField, grepAssets, nodeWebUrl, normalizeBaseUrl, resolveConfig, toFilesOnlyGrepResult, toUnifiedFilesGrepInput };
429
+ export { type ActivityItemVO, type AgentTaskVO, type FileTreeFileVO as AirAppFileVO, type FileTreeFileVO as DriveFileVO, type FileTreeFileVO, type FileTreeFileVO as SkillFileVO, type FileTreeReadFileVO as AirAppReadFileVO, type FileTreeReadFileVO as DriveReadFileVO, type FileTreeReadFileVO, type FileTreeReadFileVO as SkillReadFileVO, type FileTreeNodeVO as AirAppVO, type FileTreeNodeVO as DriveVO, type FileTreeNodeVO, type FileTreeNodeVO as SkillVO, type AssetAttachmentRef, type AssetDetailVO, type AssetTextStatus, type AssetUsageVO, type AssetVO, type AttachmentRef, type AuditAction, type AuditEventVO, type BaseFieldVO, type BaseVO, Busabase, type BusabaseAssetsClient, BusabaseChangeRequestsClient, type BusabaseClient, type BusabaseConfig, type BusabaseRecordsClient, type BusabaseSourceChannel, CREATABLE_NODE_TYPES, type ChangeRequestBatchFailureVO, type ChangeRequestCountsVO, type ChangeRequestMergeBatchResultVO, type ChangeRequestReviewBatchResultVO, type ChangeRequestStatus, type ChangeRequestTargetType, type ChangeRequestVO, type CloudContract, type CommentMentionDispatchStatus, type CommentMentionInputDTO, type CommentMentionTargetType, type CommentMentionVO, type CommentSubjectType, type CommentVO, type CommitVO, type CreatableNodeType, type CreateFormDTO, DEFAULT_BASE_URL, type FieldType, type FileNodeMetadata, type FileNodeVO, type FilePreviewConfigVO, type FilePreviewConfigurationStatus, type FilePreviewCredentialSource, type FilePreviewProvider, type FilePreviewUnavailableReason, type FilePreviewVO, type FormBoundFieldVO, type FormFieldBindingVO, type FormPageSourceVO, type FormShareVO, type FormSubmitResultVO, type FormThemeVO, type FormVO, type GalleryCardSize, type GalleryCoverFit, type GanttScale, type ListFormsDTO, type ListFormsVO, type LookupRollup, type MentionInboxItemVO, type MentionInboxPageVO, type NodeDetailVO, type NodeIcon, type NodeIconSchema, type NodeSearchResultVO, type NodeType, type NodeVO, type NodeWebUrlInput, type OperationKind, type OperationStatus, type OperationVO, type RecordByFieldInput, type RecordLinkVO, type RecordVO, type ResolvedConfig, type ReviewVO, type ReviewVerdict, type SearchResponseVO, type SearchResultKind, type SearchResultVO, type SourceAttributionVO, type SubmitFormDTO, type UpdateFormDTO, type UpdatePreviewFileCredentialDTO, type UpdateVaultSettingsDTO, type UserRefVO, type VIEW_FIELD_MAX_WIDTH, type VIEW_FIELD_MIN_WIDTH, type VaultAccessPolicy, type VaultEnvironment, type VaultItemInput, type VaultItemKind, type VaultItemVO, type VaultRuntimeEnv, type VaultScopeType, type VaultSettingsVO, type ViewConfigVO, type ViewFilterOperator, type ViewFilterVO, type ViewSortVO, type ViewType, type ViewVO, cloudContract, createBusabaseClient, getRecordByField, grepAssets, nodeWebUrl, normalizeBaseUrl, resolveConfig, toFilesOnlyGrepResult, toUnifiedFilesGrepInput };
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { n as TemplateRiskLevelSchema } from "./template-C5oO6Au_.js";
1
+ import { n as TemplateRiskLevelSchema } from "./template-D10kjpd-.js";
2
2
  import { t as normalizeBaseUrl } from "./url-B8GMXalA.js";
3
3
  import { ORPCError, createORPCClient } from "@orpc/client";
4
4
  import { OpenAPILink } from "@orpc/openapi-client/fetch";
@@ -124,6 +124,25 @@ const AgentPermissionRequestVOSchema = z.object({
124
124
  description: z.string().optional(),
125
125
  options: z.array(AgentPermissionOptionVOSchema)
126
126
  });
127
+ /**
128
+ * The agent's `category: "model"` ACP config option, reduced to what the UI
129
+ * needs to render a picker: which value is selected, and what it can become.
130
+ *
131
+ * Deliberately not the raw ACP `SessionConfigOption` — that type carries a
132
+ * `boolean` variant and grouped select options this domain has no use for,
133
+ * and re-exporting it here would leak an SDK shape across the contract
134
+ * boundary for a feature that only needs "id, current value, flat choices".
135
+ */
136
+ const AgentSessionModelOptionVOSchema = z.object({
137
+ /** The ACP `configId` to send back on `session/set_config_option`. */
138
+ id: z.string(),
139
+ name: z.string(),
140
+ currentValue: z.string(),
141
+ options: z.array(z.object({
142
+ value: z.string(),
143
+ name: z.string()
144
+ }))
145
+ });
127
146
  const AgentSessionVOSchema = z.object({
128
147
  /** Busabase's own id for the session; not the agent's ACP sessionId. */
129
148
  id: z.string(),
@@ -135,7 +154,15 @@ const AgentSessionVOSchema = z.object({
135
154
  createdAt: z.string(),
136
155
  lastActivityAt: z.string(),
137
156
  /** Set when status is "failed"; surfaced verbatim to the user. */
138
- error: z.string().nullable().default(null)
157
+ error: z.string().nullable().default(null),
158
+ /**
159
+ * Present only while the agent's `session/new` (or a later
160
+ * `config_option_update`) has advertised a `category: "model"` select.
161
+ * `null` for agents that offer no model choice, and for every session
162
+ * loaded from history — a finished process cannot take a config change,
163
+ * so there is nothing to render a picker for.
164
+ */
165
+ modelOption: AgentSessionModelOptionVOSchema.nullable().default(null)
139
166
  });
140
167
  /** One connected agent backend visible in the requested workspace scope. */
141
168
  const AgentConnectionVOSchema = z.object({
@@ -221,6 +248,12 @@ const RespondToAgentPermissionInputSchema = z.object({
221
248
  requestId: z.string().min(1),
222
249
  optionId: z.string().min(1)
223
250
  });
251
+ /** Change the session's `category: "model"` config option via `session/set_config_option`. */
252
+ const SetAgentSessionConfigOptionInputSchema = z.object({
253
+ sessionId: z.string().min(1),
254
+ configId: z.string().min(1),
255
+ value: z.string().min(1)
256
+ });
224
257
  //#endregion
225
258
  //#region ../../packages/busabase-contract/src/domains/agents/contract.ts
226
259
  /**
@@ -261,6 +294,12 @@ list: oc.input(ListAgentConnectionsInputSchema).output(AgentConnectionVOSchema.a
261
294
  */
262
295
  respondToPermission: oc.input(RespondToAgentPermissionInputSchema).output(z.object({ ok: z.boolean() })),
263
296
  /**
297
+ * Change the session's advertised model via ACP `session/set_config_option`.
298
+ * `value` is validated against the session's currently advertised options
299
+ * server-side — this is not a passthrough to the agent.
300
+ */
301
+ setConfigOption: oc.input(SetAgentSessionConfigOptionInputSchema).output(AgentSessionVOSchema),
302
+ /**
264
303
  * Live event stream for one session. Replays buffered events from `afterSeq`
265
304
  * first so a client that reconnects mid-turn does not lose the tokens it
266
305
  * missed, then follows live.
@@ -560,7 +599,26 @@ const updateFieldChangeRequestInputSchema = z.object({
560
599
  patch: z.object({
561
600
  name: fieldNameSchema.optional(),
562
601
  required: z.boolean().optional(),
563
- options: fieldOptionsSchema.optional()
602
+ options: fieldOptionsSchema.optional(),
603
+ /**
604
+ * Not a patch key — rejected on purpose, and the only key here that is.
605
+ *
606
+ * `update` cannot change a field's type; `convert` does, after
607
+ * `previewFieldConversion` has shown what happens to the stored values.
608
+ * But `patch` is a plain (non-strict) object, so `{ type: "markdown" }`
609
+ * used to be stripped silently: the request validated, the change request
610
+ * merged, `ok: true` came back, and the field was still whatever it was.
611
+ * A caller reaching for the obvious-but-wrong shape got a successful
612
+ * no-op, which reads exactly like a successful conversion.
613
+ *
614
+ * Blanket `.strict()` is not the fix here — see `contract/auto-merge.ts`
615
+ * on why these schemas stay open: the SDK ships on its own cadence
616
+ * against self-hosted servers, so a newer client sending a newer optional
617
+ * key is normal traffic, and strictness would 400 all of them to catch
618
+ * this one. Naming the single key that will never be legitimate keeps
619
+ * that forward compatibility intact.
620
+ */
621
+ type: z.never({ message: "A field type cannot be changed with `update`. Use operation: \"convert\" with `newType`, and call `previewFieldConversion` first to see how many stored values survive it." }).optional()
564
622
  }),
565
623
  message: z.string().optional(),
566
624
  submittedBy: z.string().optional().default("local-editor"),
@@ -727,6 +785,7 @@ const baseNodeType = {
727
785
  capabilities: {
728
786
  hasDetail: true,
729
787
  creatable: true,
788
+ commonlyCreated: true,
730
789
  publicAccess: "detail"
731
790
  },
732
791
  operations: [
@@ -831,6 +890,7 @@ const docNodeType = {
831
890
  capabilities: {
832
891
  hasDetail: true,
833
892
  creatable: true,
893
+ commonlyCreated: true,
834
894
  publicAccess: "detail"
835
895
  },
836
896
  operations: [{
@@ -862,6 +922,7 @@ const fileNodeType = {
862
922
  capabilities: {
863
923
  hasDetail: true,
864
924
  creatable: true,
925
+ commonlyCreated: true,
865
926
  publicAccess: "detail"
866
927
  },
867
928
  operations: []
@@ -877,6 +938,7 @@ const folderNodeType = {
877
938
  capabilities: {
878
939
  container: true,
879
940
  creatable: true,
941
+ commonlyCreated: true,
880
942
  hasDetail: true,
881
943
  publicAccess: "detail"
882
944
  },
@@ -887,9 +949,10 @@ const folderNodeType = {
887
949
  /**
888
950
  * Form node: an agent-authored, sandboxed web page bound to a Base via an
889
951
  * explicit field-binding contract. A submission does NOT write a record
890
- * directly — it produces a review-first record-create ChangeRequest on the
891
- * target Base (so the submitting act reuses the base's `record_create` op, not a
892
- * form-specific one). The form's own config (bindings/page/share) is owner-
952
+ * directly — it produces a record-create ChangeRequest on the target Base (so
953
+ * the submitting act reuses the base's `record_create` op, not a form-specific
954
+ * one), which then merges immediately or waits for review according to the
955
+ * submitter's permission on that Base. The form's own config (bindings/page/share) is owner-
893
956
  * managed and edited directly, so this node contributes no CR operations of its
894
957
  * own for now.
895
958
  */
@@ -897,10 +960,23 @@ const formNodeType = {
897
960
  type: "form",
898
961
  label: "Form",
899
962
  icon: "form",
963
+ /**
964
+ * `hidden` until a Form can be created from a create surface at all.
965
+ *
966
+ * `busabase_forms.target_base_id` is NOT NULL and `form` registers no
967
+ * `node_create` materializer, so a Form built through the generic New-item
968
+ * flow (which only collects name/slug/description) is a node row with no form
969
+ * config behind it — it opens to a dead end, every time, for everyone. The
970
+ * type stays fully `creatable` so `forms.create` (which does take a target
971
+ * Base) and the REST/MCP surface are untouched; it just no longer offers an
972
+ * entry point that cannot succeed. Drop this once the New-item flow asks for
973
+ * the target Base and a materializer writes the config row.
974
+ */
900
975
  capabilities: {
901
976
  hasDetail: true,
902
977
  creatable: true,
903
- publicAccess: "submit"
978
+ publicAccess: "submit",
979
+ hidden: true
904
980
  },
905
981
  operations: []
906
982
  };
@@ -1135,12 +1211,20 @@ const customPromptBodySchema = iStringSchema.refine((value) => iStringLocaleValu
1135
1211
  * One custom scenario prompt. `body`'s `{target}` placeholder is substituted at
1136
1212
  * render time with the same target string `PromptDef.body(target)` receives
1137
1213
  * today (see `node-agent-prompts.ts`) — this schema does not interpolate it.
1214
+ *
1215
+ * The placeholder is OPTIONAL and chooses placement only: a `body` that never
1216
+ * mentions `{target}` gets the target line prepended as its first paragraph, so
1217
+ * a custom prompt can never reach an agent without naming the node it acts on.
1218
+ * That is why the schema does not require it — forgetting it is not an error to
1219
+ * reject, it is a default to supply.
1138
1220
  */
1139
1221
  const customPromptDefSchema = z.object({
1140
1222
  /** Stable id, unique within this node's custom list. */
1141
1223
  key: z.string().trim().min(1, { message: "key must not be empty" }),
1142
1224
  /** Defaults to `change` (same default the curated prompts use) so a prompt
1143
- * cannot silently bypass the approval-first policy by omission. */
1225
+ * cannot silently opt out of the change-request path by omission — whether that
1226
+ * path then merges immediately or waits for review is the permission layer's
1227
+ * call, not the prompt's. */
1144
1228
  intent: customPromptIntentSchema.optional(),
1145
1229
  /** Short title shown in the dialog's left list. */
1146
1230
  label: customPromptLabelSchema,
@@ -1327,7 +1411,14 @@ const nodeSearchResultSchema = z.object({
1327
1411
  name: z.string(),
1328
1412
  slug: z.string(),
1329
1413
  path: z.string(),
1330
- updatedAt: z.string()
1414
+ updatedAt: z.string(),
1415
+ /**
1416
+ * The node's own custom avatar, same shape as `NodeVO.icon`. Optional so an
1417
+ * older server that predates this field is still a valid response — a
1418
+ * caller that doesn't know it falls back to the type icon exactly as it
1419
+ * always has.
1420
+ */
1421
+ icon: NodeIconSchema.nullable().optional()
1331
1422
  });
1332
1423
  const userRefSchema = z.object({
1333
1424
  id: z.string(),
@@ -1998,17 +2089,84 @@ const fileTreeNodeTypeSchema = z.enum([
1998
2089
  "drive",
1999
2090
  "airapp"
2000
2091
  ]);
2092
+ const filePreviewProviderSchema = z.enum(["builtin", "previewfile"]);
2093
+ const filePreviewCredentialSourceSchema = z.enum([
2094
+ "environment",
2095
+ "vault",
2096
+ "none"
2097
+ ]);
2098
+ const filePreviewConfigurationStatusSchema = z.enum([
2099
+ "ready",
2100
+ "not_configured",
2101
+ "invalid_configuration"
2102
+ ]);
2103
+ const filePreviewUnavailableReasonSchema = z.enum([
2104
+ "not_configured",
2105
+ "invalid_configuration",
2106
+ "file_too_large",
2107
+ "unsupported",
2108
+ "authentication_failed",
2109
+ "rate_limited",
2110
+ "timeout",
2111
+ "service_unavailable",
2112
+ "invalid_response"
2113
+ ]);
2114
+ const filePreviewConfigSchema = z.object({
2115
+ provider: filePreviewProviderSchema,
2116
+ status: filePreviewConfigurationStatusSchema,
2117
+ credentialSource: filePreviewCredentialSourceSchema,
2118
+ credentialConfigured: z.boolean(),
2119
+ maxFileSizeBytes: z.number().int().positive(),
2120
+ sessionTtlMinutes: z.number().int().positive(),
2121
+ vaultEncryptionConfigured: z.boolean().nullable()
2122
+ });
2123
+ const filePreviewSchema = z.discriminatedUnion("state", [
2124
+ z.object({
2125
+ state: z.literal("builtin"),
2126
+ provider: z.literal("builtin")
2127
+ }),
2128
+ z.object({
2129
+ state: z.literal("ready"),
2130
+ provider: z.literal("previewfile"),
2131
+ previewUrl: z.string().url(),
2132
+ expiresAt: z.string().datetime()
2133
+ }),
2134
+ z.object({
2135
+ state: z.literal("unavailable"),
2136
+ provider: z.literal("previewfile"),
2137
+ reason: filePreviewUnavailableReasonSchema,
2138
+ retryable: z.boolean()
2139
+ })
2140
+ ]);
2001
2141
  const fileTreeRefSchema = z.object({
2002
2142
  nodeId: z.string().describe("A node id OR a slug. A slug is only unique WITHIN a type, so pass `type` alongside one; a node id needs no hint."),
2003
2143
  type: fileTreeNodeTypeSchema.optional().describe("Disambiguates a slug. Unnecessary — and ignored — when `nodeId` is an id.")
2004
2144
  });
2005
2145
  const fileTreeContract = {
2146
+ previewConfig: oc.route({
2147
+ method: "GET",
2148
+ path: "/file-trees/preview-config",
2149
+ tags: ["File Trees"],
2150
+ summary: "Get Drive file preview configuration",
2151
+ successDescription: "Resolved preview provider state without exposing the configured API key."
2152
+ }).output(filePreviewConfigSchema),
2153
+ preparePreview: oc.route({
2154
+ method: "POST",
2155
+ path: "/file-trees/{nodeId}/preview",
2156
+ tags: ["File Trees"],
2157
+ summary: "Prepare a Drive file preview",
2158
+ successDescription: "Returns the built-in provider, a short-lived PreviewFile URL, or a recoverable provider failure."
2159
+ }).input(z.object({
2160
+ nodeId: z.string().min(1),
2161
+ filePath: z.string().min(1),
2162
+ type: z.literal("drive")
2163
+ })).output(filePreviewSchema),
2006
2164
  create: oc.route({
2007
2165
  method: "POST",
2008
2166
  path: "/file-trees",
2009
2167
  tags: ["File Trees"],
2010
2168
  summary: "Create file-tree node",
2011
- successDescription: "Review-first by default: a pending ChangeRequest proposing the node (`materialized: false`). Returns the materialized node instead (`materialized: true`) when `autoMerge: true` is passed."
2169
+ successDescription: "Merged in the same call when the actor has write access on the target node — the materialized node comes back (`materialized: true`). Review-first when the actor lacks write access or passes `autoMerge: false`: a pending ChangeRequest proposing the node (`materialized: false`)."
2012
2170
  }).input(createFileTreeInputSchema.extend({ type: fileTreeNodeTypeSchema })).output(z.union([fileTreeNodeSchema.extend({ materialized: z.literal(true) }), changeRequestSchema.extend({ materialized: z.literal(false) })])),
2013
2171
  listFiles: oc.route({
2014
2172
  method: "GET",
@@ -3029,14 +3187,14 @@ const baseContract = {
3029
3187
  path: "/bases",
3030
3188
  tags: ["Bases"],
3031
3189
  summary: "Create Base",
3032
- successDescription: "Review-first by default: a pending ChangeRequest proposing the Base (`materialized: false`). Returns the materialized Base instead (`materialized: true`) when `autoMerge: true` is passed."
3190
+ successDescription: "Merged in the same call when the actor has write access on the parent node — the materialized Base comes back (`materialized: true`). Review-first when the actor lacks write access or passes `autoMerge: false`: a pending ChangeRequest proposing the Base (`materialized: false`)."
3033
3191
  }).input(createBaseInputSchema).output(z.union([baseSchema.extend({ materialized: z.literal(true) }), changeRequestSchema.extend({ materialized: z.literal(false) })])),
3034
3192
  createChangeRequest: oc.route({
3035
3193
  method: "POST",
3036
3194
  path: "/bases/{baseId}/change-requests",
3037
3195
  tags: ["Bases", "Change Requests"],
3038
3196
  summary: "Create Change Request in Base",
3039
- successDescription: "Review-first by default: a pending ChangeRequest proposing the record (`materialized: false`). Returns the materialized record instead (`materialized: true`) when `autoMerge: true` is passed."
3197
+ successDescription: "Merged in the same call when the actor has write access on the Base's node — the materialized record comes back (`materialized: true`). Review-first when the actor lacks write access or passes `autoMerge: false`: a pending ChangeRequest proposing the record (`materialized: false`)."
3040
3198
  }).input(createChangeRequestInputSchema.extend({ baseId: z.string() })).output(z.union([recordSchema.extend({ materialized: z.literal(true) }), changeRequestSchema.extend({ materialized: z.literal(false) })])),
3041
3199
  createBulkChangeRequest: oc.route({
3042
3200
  method: "POST",
@@ -3194,7 +3352,7 @@ const docContract = { create: oc.route({
3194
3352
  path: "/docs",
3195
3353
  tags: ["Docs"],
3196
3354
  summary: "Create Doc node",
3197
- successDescription: "Review-first by default: a pending ChangeRequest proposing the Doc (`materialized: false`). Returns the materialized Doc node instead (`materialized: true`) when `autoMerge: true` is passed."
3355
+ successDescription: "Merged in the same call when the actor has write access on the parent node — the materialized Doc node comes back (`materialized: true`). Review-first when the actor lacks write access or passes `autoMerge: false`: a pending ChangeRequest proposing the Doc (`materialized: false`)."
3198
3356
  }).input(createDocInputSchema).output(z.union([docSchema.extend({ materialized: z.literal(true) }), changeRequestSchema.extend({ materialized: z.literal(false) })])) };
3199
3357
  //#endregion
3200
3358
  //#region ../../packages/busabase-contract/src/domains/doc/types.ts
@@ -3456,7 +3614,7 @@ const fileContract = { create: oc.route({
3456
3614
  path: "/files",
3457
3615
  tags: ["Files"],
3458
3616
  summary: "Create File node",
3459
- successDescription: "Review-first by default: a pending ChangeRequest proposing the File node (`materialized: false`). Returns the materialized File node instead (`materialized: true`) when `autoMerge: true` is passed."
3617
+ successDescription: "Merged in the same call when the actor has write access on the parent node — the materialized File node comes back (`materialized: true`). Review-first when the actor lacks write access or passes `autoMerge: false`: a pending ChangeRequest proposing the File node (`materialized: false`)."
3460
3618
  }).input(createFileNodeInputSchema).output(z.union([FileNodeVOSchema.extend({ materialized: z.literal(true) }), changeRequestSchema.extend({ materialized: z.literal(false) })])) };
3461
3619
  //#endregion
3462
3620
  //#region ../../packages/busabase-contract/src/domains/form/types.ts
@@ -3565,10 +3723,22 @@ const SubmitFormInputSchema = z.object({
3565
3723
  values: z.record(z.string(), z.unknown()),
3566
3724
  captchaToken: z.string().optional()
3567
3725
  });
3568
- /** What the submit endpoint returns — the pending ChangeRequest id, never data. */
3726
+ /**
3727
+ * What the submit endpoint returns — a ChangeRequest id and what happened to it,
3728
+ * never the record data.
3729
+ *
3730
+ * `status` is permission-aware, like every other write: `merged` when the
3731
+ * submitter holds `write` on the target Base and the submission landed straight
3732
+ * away, `pending_review` when it is waiting for a human. An ANONYMOUS visitor can
3733
+ * never reach `merged`: permission is resolved against the target Base, which a
3734
+ * form does not share publicly, and a public-link request is capped at `read`
3735
+ * even where it is shared. So a public form still always waits.
3736
+ */
3569
3737
  const FormSubmitResultSchema = z.object({
3570
3738
  changeRequestId: z.string(),
3571
- status: z.literal("pending_review")
3739
+ status: z.enum(["pending_review", "merged"]),
3740
+ /** The created record's id, present only when `status` is `merged`. */
3741
+ recordId: z.string().optional()
3572
3742
  });
3573
3743
  //#endregion
3574
3744
  //#region ../../packages/busabase-contract/src/domains/form/contract.ts
@@ -3606,7 +3776,7 @@ const formContract = {
3606
3776
  path: "/forms/{nodeId}/submit",
3607
3777
  tags: ["Forms"],
3608
3778
  summary: "Submit a filled-in form",
3609
- successDescription: "Creates a review-first record-create ChangeRequest on the target Base a form submission always waits for a human, whoever submitted it."
3779
+ successDescription: "Creates a record-create ChangeRequest on the target Base. Merged in the same call when the submitter holds write access on that Base (`status: \"merged\"`); otherwise it waits for a reviewer (`status: \"pending_review\"`). A visitor arriving through the form's public link is capped at read and therefore always waits."
3610
3780
  }).input(SubmitFormInputSchema.extend({ nodeId: z.string() })).output(FormSubmitResultSchema)
3611
3781
  };
3612
3782
  //#endregion
@@ -3757,9 +3927,10 @@ const InstallPlanVOSchema = z.object({
3757
3927
  warnings: z.array(z.string()).default([]),
3758
3928
  /**
3759
3929
  * True when a record carries a relation VALUE. A relation stores the ids of the
3760
- * records it points at, and those exist only once the records are merged — so a
3761
- * review-first install would land every relation empty. `autoMerge` is required
3762
- * in that case, and the UI must say why.
3930
+ * records it points at, and those exist only once the records are merged — so an
3931
+ * install left for review would land every relation empty. Such a package cannot
3932
+ * be installed by a caller whose content would queue (no write access, or an
3933
+ * explicit `autoMerge: false`), and the UI must say why.
3763
3934
  */
3764
3935
  requiresAutoMerge: z.boolean(),
3765
3936
  /**
@@ -3769,10 +3940,13 @@ const InstallPlanVOSchema = z.object({
3769
3940
  *
3770
3941
  * It is therefore an answer to "what happens if I install like this", not a
3771
3942
  * property of the package — a package whose records carry relation values
3772
- * reports `applicable: false` when planned WITHOUT `autoMerge` and true WITH
3773
- * it. A client that offers an auto-merge toggle must re-plan when it changes
3774
- * (the same way it re-plans when `rename` or `intoFolder` change), rather than
3775
- * treating one plan's `applicable` as final.
3943
+ * reports `applicable: false` when this caller's content would QUEUE and true
3944
+ * when it would merge. Note the plan resolves that the same permission-aware
3945
+ * way the install itself does, so omitting `autoMerge` reports what the caller
3946
+ * would actually get rather than assuming review. A client that offers an
3947
+ * auto-merge toggle must re-plan when it changes (the same way it re-plans when
3948
+ * `rename` or `intoFolder` change), rather than treating one plan's
3949
+ * `applicable` as final.
3776
3950
  *
3777
3951
  * There is deliberately no `blockedReason` string here: the reason is already
3778
3952
  * carried structurally by `collisions[]` (with `renamedTo`) and
@@ -3803,6 +3977,28 @@ const InstallResultVOSchema = z.object({
3803
3977
  pendingChangeRequests: z.number().int().min(0),
3804
3978
  warnings: z.array(z.string()).default([])
3805
3979
  });
3980
+ /**
3981
+ * One event from a streaming install.
3982
+ *
3983
+ * A whole install in a single response is what makes the plain `fromGithub`
3984
+ * route time out at a gateway: the work is minutes of GitHub fetch, node
3985
+ * creation, file upload and record writes, and until it finishes the connection
3986
+ * carries no bytes. A proxy in front of the app sees an idle socket and closes
3987
+ * it — the install itself keeps running server-side, so the user is told it
3988
+ * failed while it actually succeeded, which is the worst of both.
3989
+ *
3990
+ * `applyInstall` already reports its progress (`onProgress`); the non-streaming
3991
+ * route simply discarded it. Streaming those same messages keeps bytes moving
3992
+ * AND gives the user something truthful to look at during a long install.
3993
+ */
3994
+ const InstallEventVOSchema = z.discriminatedUnion("kind", [z.object({
3995
+ kind: z.literal("progress"),
3996
+ /** Human-readable, already localized by the caller's own copy — display as-is. */
3997
+ message: z.string()
3998
+ }), z.object({
3999
+ kind: z.literal("done"),
4000
+ result: InstallResultVOSchema
4001
+ })]);
3806
4002
  z.object({
3807
4003
  /** Which of the five passes stopped, e.g. `Pass 4/5 (sample records)`. */
3808
4004
  phase: z.string(),
@@ -3833,7 +4029,7 @@ const InstallFromGithubDTOSchema = z.object({
3833
4029
  repoUrl: repoUrlField,
3834
4030
  intoFolder: intoFolderField,
3835
4031
  rename: renameField,
3836
- autoMerge: z.boolean().optional().describe("Merge the content change requests on the spot instead of leaving them for review. This trusts the package author: a package can carry skills and AirApps, i.e. code this space's agents will execute.")
4032
+ autoMerge: z.boolean().optional().describe("Whether the package's content change requests merge on the spot. Omitted defaults to merging immediately when the caller holds write access (installing is already a space owner/admin operation, so normally they do), otherwise leaving them for review; pass explicit false to force review even with write access. Either way, installing trusts the package author: a package can carry skills and AirApps, i.e. code this space's agents will execute.")
3837
4033
  });
3838
4034
  //#endregion
3839
4035
  //#region ../../packages/busabase-contract/src/domains/install/contract.ts
@@ -3865,7 +4061,18 @@ const installContract = {
3865
4061
  tags: ["Install"],
3866
4062
  summary: "Install a package from a GitHub repo",
3867
4063
  successDescription: "Created counts plus the number of change requests left for review. Structure (folders, Bases, fields, views) is created immediately — a pending Base has no id to attach a view or record to; content (records, docs, skills, AirApps) lands as change requests unless `autoMerge` is set."
3868
- }).input(InstallFromGithubDTOSchema).output(InstallResultVOSchema)
4064
+ }).input(InstallFromGithubDTOSchema).output(InstallResultVOSchema),
4065
+ /**
4066
+ * The same install, streamed.
4067
+ *
4068
+ * Kept alongside `fromGithub` rather than replacing it: that route is in the
4069
+ * public OpenAPI surface and a plain request/response is the right shape for
4070
+ * a script. This one exists for a human waiting at a dashboard, where the
4071
+ * install is long enough that a silent connection gets closed by whatever
4072
+ * proxy sits in front of the app — and long enough that a progress line is
4073
+ * worth showing regardless.
4074
+ */
4075
+ fromGithubStream: oc.input(InstallFromGithubDTOSchema).output(eventIterator(InstallEventVOSchema))
3869
4076
  };
3870
4077
  //#endregion
3871
4078
  //#region ../../packages/busabase-contract/src/domains/templates/types.ts
@@ -3923,6 +4130,11 @@ const TemplateCardVOSchema = z.object({
3923
4130
  * accidentally point at a different ref than the one it installs.
3924
4131
  */
3925
4132
  screenshots: z.array(z.string()).default([]),
4133
+ /**
4134
+ * Absolute URL of the demo clip, or absent. Resolved against a different host
4135
+ * than the screenshots — see `videoUrl` in the catalog logic.
4136
+ */
4137
+ video: z.string().optional(),
3926
4138
  agentPrompts: z.array(z.string()).default([]),
3927
4139
  version: z.string().optional(),
3928
4140
  author: z.string().optional(),
@@ -4012,6 +4224,7 @@ const VaultItemInputSchema = z.object({
4012
4224
  })
4013
4225
  });
4014
4226
  const UpdateVaultSettingsInputSchema = z.object({ items: z.array(VaultItemInputSchema).max(200) });
4227
+ const UpdatePreviewFileCredentialInputSchema = z.object({ apiKey: VaultItemValueSchema.trim().min(1).nullable() });
4015
4228
  const VaultItemVOSchema = VaultItemInputSchema.extend({
4016
4229
  id: z.string(),
4017
4230
  scopeId: z.string().nullable(),
@@ -4043,6 +4256,13 @@ const vaultContract = {
4043
4256
  summary: "Replace local Vault settings",
4044
4257
  successDescription: "Updated local Vault secrets and variables."
4045
4258
  }).input(UpdateVaultSettingsInputSchema).output(VaultSettingsVOSchema),
4259
+ updatePreviewFileCredential: oc.route({
4260
+ method: "PUT",
4261
+ path: "/vault/previewfile",
4262
+ tags: ["Vault"],
4263
+ summary: "Set or remove the local PreviewFile credential",
4264
+ successDescription: "The credential was updated without returning its value."
4265
+ }).input(UpdatePreviewFileCredentialInputSchema).output(VaultSuccessSchema),
4046
4266
  clear: oc.route({
4047
4267
  method: "DELETE",
4048
4268
  path: "/vault",
@@ -59,6 +59,19 @@ z.object({
59
59
  /** Card/detail screenshots, package-relative (`assets/screenshots/overview.webp`). */
60
60
  screenshots: z.array(z.string()).default([]),
61
61
  /**
62
+ * Optional demo clip, package-relative (`assets/recordings/busa-crm.mp4`).
63
+ *
64
+ * No companion poster field on purpose: the detail page uses
65
+ * `screenshots[0]`, which the catalog already requires to be the cover. One
66
+ * declared path instead of two that can disagree with each other.
67
+ *
68
+ * Note for anyone adding a sibling field here: this is a plain `z.object`, so
69
+ * an unrecognized key in `busabase.json` is silently stripped rather than
70
+ * rejected. A template cannot declare a field ahead of the schema landing —
71
+ * it just vanishes, with no error from `busabase-cli check`.
72
+ */
73
+ video: z.string().optional(),
74
+ /**
62
75
  * Ready-made prompts shown after install ("Ask agent" prefills the first).
63
76
  *
64
77
  * They are the difference between a folder of tables and something a user can
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "busa-sdk",
3
- "version": "0.52.0",
3
+ "version": "0.53.0",
4
4
  "description": "Typed TypeScript/JavaScript SDK for the Busabase OpenAPI REST API. Talks to a local or remote `busabase server` (or Busabase Cloud). Short-name alias for busabase-sdk.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/busabase/busabase/tree/main/apps/busabase-sdk",