busabase-sdk 0.40.1 → 0.42.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/README.md CHANGED
@@ -120,7 +120,7 @@ An app that ships its own AirApp node inside the Folder declares it too — `air
120
120
 
121
121
  **Bases evolve by appending fields.** A live Base whose fields are a strict *prefix* of the declaration is an older schema of yours: the missing suffix is added, one approval-gated `bases.fieldChangeRequest` per field, and anything left unapproved surfaces as `SETUP_PENDING` naming the requests. A field renamed, retyped, reordered, or removed is not an upgrade this can reason about, so it refuses rather than guessing which shape is right.
122
122
 
123
- Failures are an `AirAppSetupError` carrying a `code`: `SETUP_REQUIRED` (offer to initialize), `SETUP_PENDING` (submitted, awaiting approval — approval-first working as designed), `SETUP_CONFLICT`, `SETUP_PERMISSION`, `SCHEMA_INCOMPLETE`. `message` keeps the `"CODE: detail"` shape so code that parses the prefix keeps working.
123
+ Failures are an `AirAppSetupError` carrying a `code`: `SETUP_REQUIRED` (offer to initialize), `SETUP_PENDING` (submitted, awaiting approval — the permission model working as designed), `SETUP_CONFLICT`, `SETUP_PERMISSION`, `SCHEMA_INCOMPLETE`. `message` keeps the `"CODE: detail"` shape so code that parses the prefix keeps working.
124
124
 
125
125
  ### `busabase-sdk/airapp-gate` — the connect UI (browser)
126
126
 
package/dist/airapp.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { t as BusabaseClient } from "./client-DbETz_5k.js";
1
+ import { t as BusabaseClient } from "./client-vnydDLvt.js";
2
2
  //#region src/airapp.d.ts
3
3
  type NodeChangeRequestInput = Parameters<BusabaseClient["nodes"]["createChangeRequest"]>[0];
4
4
  type NodeOperationInput = NodeChangeRequestInput["operations"][number];
@@ -380,6 +380,22 @@ interface NodeOutput {
380
380
  * what it equals whenever it's omitted).
381
381
  */
382
382
  hasChildren?: boolean;
383
+ /**
384
+ * This node carries its OWN live public share row (`nodes.share`, scope
385
+ * `public`, not expired) — what the sidebar renders its "shared" marker
386
+ * from, so an admin can see at a glance which nodes are published without
387
+ * opening every "•••" → Share dialog.
388
+ *
389
+ * Deliberately NOT the inherited answer: a node under a shared folder IS
390
+ * publicly reachable (that is `effective_public_scope`, which is what the
391
+ * ACL gates read), but it is not itself a thing anybody chose to publish,
392
+ * and marking a whole subtree would drown the one row that matters. Read
393
+ * "who made this public" off the nearest ancestor with `shared: true`.
394
+ *
395
+ * Optional/omitted means the read path didn't resolve share state at all
396
+ * (e.g. a node detail fetch), NOT that the node is unshared.
397
+ */
398
+ shared?: boolean;
383
399
  }
384
400
  //#endregion
385
401
  //#region ../../node_modules/@orpc/shared/dist/index.d.mts
@@ -614,6 +630,27 @@ declare const cloudContract: {
614
630
  }, z.core.$strip>, z.ZodObject<{
615
631
  ancestorIds: z.ZodArray<z.ZodString>;
616
632
  }, z.core.$strip>, import("@orpc/contract").MergedErrorMap<Record<never, never>, Record<never, never>>, Record<never, never>>;
633
+ resolveRouteState: import("@orpc/contract").ContractProcedure<z.ZodObject<{
634
+ nodeId: z.ZodString;
635
+ type: z.ZodOptional<z.ZodEnum<{
636
+ [x: string]: string;
637
+ }>>;
638
+ }, z.core.$strip>, z.ZodDiscriminatedUnion<[z.ZodObject<{
639
+ status: z.ZodLiteral<"active">;
640
+ nodeId: z.ZodString;
641
+ }, z.core.$strip>, z.ZodObject<{
642
+ status: z.ZodLiteral<"archived">;
643
+ nodeId: z.ZodString;
644
+ type: z.ZodEnum<{
645
+ [x: string]: string;
646
+ }>;
647
+ name: z.ZodString;
648
+ slug: z.ZodString;
649
+ archivedAt: z.ZodString;
650
+ canRestore: z.ZodBoolean;
651
+ }, z.core.$strip>, z.ZodObject<{
652
+ status: z.ZodLiteral<"unavailable">;
653
+ }, z.core.$strip>], "status">, import("@orpc/contract").MergedErrorMap<Record<never, never>, Record<never, never>>, Record<never, never>>;
617
654
  createChangeRequest: import("@orpc/contract").ContractProcedure<z.ZodObject<{
618
655
  message: z.ZodDefault<z.ZodOptional<z.ZodString>>;
619
656
  submittedBy: z.ZodDefault<z.ZodOptional<z.ZodString>>;
@@ -7099,6 +7136,40 @@ declare const cloudContract: {
7099
7136
  createdAt: z.ZodString;
7100
7137
  updatedAt: z.ZodString;
7101
7138
  }, z.core.$strip>, import("@orpc/contract").MergedErrorMap<Record<never, never>, Record<never, never>>, Record<never, never>>;
7139
+ listMentions: import("@orpc/contract").ContractProcedure<z.ZodObject<{
7140
+ page: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
7141
+ pageSize: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
7142
+ }, z.core.$strip>, z.ZodObject<{
7143
+ items: z.ZodArray<z.ZodObject<{
7144
+ commentId: z.ZodString;
7145
+ subjectType: z.ZodEnum<{
7146
+ change_request: "change_request";
7147
+ commit: "commit";
7148
+ operation: "operation";
7149
+ record: "record";
7150
+ }>;
7151
+ body: z.ZodString;
7152
+ authorId: z.ZodString;
7153
+ author: z.ZodDefault<z.ZodOptional<z.ZodNullable<z.ZodObject<{
7154
+ id: z.ZodString;
7155
+ name: z.ZodNullable<z.ZodString>;
7156
+ email: z.ZodNullable<z.ZodString>;
7157
+ image: z.ZodNullable<z.ZodString>;
7158
+ role: z.ZodOptional<z.ZodNullable<z.ZodString>>;
7159
+ }, z.core.$strip>>>>;
7160
+ createdAt: z.ZodString;
7161
+ unread: z.ZodBoolean;
7162
+ href: z.ZodNullable<z.ZodString>;
7163
+ }, z.core.$strip>>;
7164
+ total: z.ZodNumber;
7165
+ unreadCount: z.ZodNumber;
7166
+ }, z.core.$strip>, import("@orpc/contract").MergedErrorMap<Record<never, never>, Record<never, never>>, Record<never, never>>;
7167
+ markMentionsRead: import("@orpc/contract").ContractProcedure<z.ZodObject<{
7168
+ commentId: z.ZodString;
7169
+ }, z.core.$strip>, z.ZodObject<{
7170
+ marked: z.ZodNumber;
7171
+ unreadCount: z.ZodNumber;
7172
+ }, z.core.$strip>, import("@orpc/contract").MergedErrorMap<Record<never, never>, Record<never, never>>, Record<never, never>>;
7102
7173
  };
7103
7174
  agent: {
7104
7175
  listTasks: import("@orpc/contract").ContractProcedure<import("@orpc/contract").Schema<unknown, unknown>, z.ZodArray<z.ZodObject<{
@@ -10662,7 +10733,7 @@ declare const cloudContract: {
10662
10733
  fieldId: z.ZodString;
10663
10734
  message: z.ZodOptional<z.ZodString>;
10664
10735
  submittedBy: z.ZodDefault<z.ZodOptional<z.ZodString>>;
10665
- autoMerge: z.ZodOptional<z.ZodLiteral<false>>;
10736
+ autoMerge: z.ZodOptional<z.ZodBoolean>;
10666
10737
  baseId: z.ZodString;
10667
10738
  operation: z.ZodLiteral<"delete">;
10668
10739
  }, z.core.$strip>, z.ZodObject<{
@@ -10703,7 +10774,7 @@ declare const cloudContract: {
10703
10774
  }>>;
10704
10775
  message: z.ZodOptional<z.ZodString>;
10705
10776
  submittedBy: z.ZodDefault<z.ZodOptional<z.ZodString>>;
10706
- autoMerge: z.ZodOptional<z.ZodLiteral<false>>;
10777
+ autoMerge: z.ZodOptional<z.ZodBoolean>;
10707
10778
  baseId: z.ZodString;
10708
10779
  operation: z.ZodLiteral<"convert">;
10709
10780
  }, z.core.$strip>, z.ZodObject<{
@@ -11182,6 +11253,10 @@ declare const cloudContract: {
11182
11253
  whiteboard: "whiteboard";
11183
11254
  yaml: "yaml";
11184
11255
  }>;
11256
+ selectChoiceMode: z.ZodDefault<z.ZodEnum<{
11257
+ auto_create: "auto_create";
11258
+ null_on_missing: "null_on_missing";
11259
+ }>>;
11185
11260
  baseId: z.ZodString;
11186
11261
  }, z.core.$strip>, z.ZodObject<{
11187
11262
  totalCount: z.ZodNumber;
@@ -11195,7 +11270,7 @@ declare const cloudContract: {
11195
11270
  lifecycleChangeRequest: import("@orpc/contract").ContractProcedure<z.ZodDiscriminatedUnion<[z.ZodObject<{
11196
11271
  message: z.ZodOptional<z.ZodString>;
11197
11272
  submittedBy: z.ZodDefault<z.ZodOptional<z.ZodString>>;
11198
- autoMerge: z.ZodOptional<z.ZodLiteral<false>>;
11273
+ autoMerge: z.ZodOptional<z.ZodBoolean>;
11199
11274
  baseId: z.ZodString;
11200
11275
  operation: z.ZodLiteral<"archive">;
11201
11276
  }, z.core.$strip>, z.ZodObject<{
@@ -14222,7 +14297,7 @@ declare const cloudContract: {
14222
14297
  }, z.core.$strict>>;
14223
14298
  message: z.ZodDefault<z.ZodOptional<z.ZodString>>;
14224
14299
  submittedBy: z.ZodDefault<z.ZodOptional<z.ZodString>>;
14225
- autoMerge: z.ZodOptional<z.ZodLiteral<false>>;
14300
+ autoMerge: z.ZodOptional<z.ZodBoolean>;
14226
14301
  }, z.core.$strip>, z.ZodObject<{
14227
14302
  id: z.ZodString;
14228
14303
  baseId: z.ZodNullable<z.ZodString>;
@@ -20323,13 +20398,13 @@ declare const cloudContract: {
20323
20398
  deleteMode: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
20324
20399
  archive: "archive";
20325
20400
  }>>>;
20326
- autoMerge: z.ZodOptional<z.ZodLiteral<false>>;
20401
+ autoMerge: z.ZodOptional<z.ZodBoolean>;
20327
20402
  recordId: z.ZodString;
20328
20403
  operation: z.ZodLiteral<"delete">;
20329
20404
  }, z.core.$strip>, z.ZodObject<{
20330
20405
  message: z.ZodOptional<z.ZodString>;
20331
20406
  submittedBy: z.ZodDefault<z.ZodOptional<z.ZodString>>;
20332
- autoMerge: z.ZodOptional<z.ZodLiteral<false>>;
20407
+ autoMerge: z.ZodOptional<z.ZodBoolean>;
20333
20408
  recordId: z.ZodString;
20334
20409
  operation: z.ZodLiteral<"restore">;
20335
20410
  }, z.core.$strip>], "operation">, z.ZodUnion<readonly [z.ZodObject<{
@@ -25024,6 +25099,13 @@ interface NodeVO {
25024
25099
  * as `children.length > 0`.
25025
25100
  */
25026
25101
  hasChildren?: boolean;
25102
+ /**
25103
+ * This node carries its OWN live public share (`nodes.share`) — see the
25104
+ * matching field on the contract's `NodeOutput` (contract/schemas.ts).
25105
+ * Optional/omitted means the read path didn't resolve share state at all,
25106
+ * NOT that the node is unshared.
25107
+ */
25108
+ shared?: boolean;
25027
25109
  }
25028
25110
  interface CommitVO {
25029
25111
  id: string;
@@ -25179,6 +25261,34 @@ interface CommentVO {
25179
25261
  createdAt: string;
25180
25262
  updatedAt: string;
25181
25263
  }
25264
+ /**
25265
+ * One row of the Inbox's Mentions tab.
25266
+ *
25267
+ * Keyed by comment, not by mention row: being named twice in one comment is
25268
+ * legitimate (each occurrence renders its own chip) but it is still one thing
25269
+ * to go read, so it is one entry here.
25270
+ */
25271
+ interface MentionInboxItemVO {
25272
+ commentId: string;
25273
+ subjectType: CommentSubjectType;
25274
+ body: string;
25275
+ authorId: string;
25276
+ author: UserRefVO | null;
25277
+ createdAt: string;
25278
+ unread: boolean;
25279
+ /**
25280
+ * Dashboard-relative path to the comment in context, or null when the
25281
+ * subject has no page of its own (a `commit`-scoped comment not attached to
25282
+ * a change request — there is no commit detail route). A null href still
25283
+ * renders a row.
25284
+ */
25285
+ href: string | null;
25286
+ }
25287
+ interface MentionInboxPageVO {
25288
+ items: MentionInboxItemVO[];
25289
+ total: number;
25290
+ unreadCount: number;
25291
+ }
25182
25292
  interface AgentTaskVO {
25183
25293
  changeRequest: ChangeRequestVO;
25184
25294
  trigger: "changes_requested" | "ai_mention";
@@ -25323,4 +25433,4 @@ declare function resolveConfig(config?: BusabaseConfig): ResolvedConfig;
25323
25433
  */
25324
25434
  declare function createBusabaseClient(config?: BusabaseConfig): BusabaseClient;
25325
25435
  //#endregion
25326
- export { GrepInputDTO as $, OperationVO as A, ViewFilterVO as At, VaultEnvironment as B, CreatableNodeType as Bt, CommentVO as C, GanttScale as Ct, NodeSearchResultVO as D, VIEW_FIELD_MIN_WIDTH as Dt, LookupRollup as E, VIEW_FIELD_MAX_WIDTH as Et, SearchResultVO as F, CloudContract as Ft, VaultScopeType as G, VaultItemKind as H, OperationKind as Ht, SourceAttributionVO as I, cloudContract as It, FileNodeVO as J, VaultSettingsVO as K, UserRefVO as L, NodeIcon as Lt, ReviewVerdict as M, ViewType as Mt, SearchResponseVO as N, ViewVO as Nt, NodeVO as O, ViewConfigVO as Ot, SearchResultKind as P, AttachmentRef as Pt, AssetVO as Q, UpdateVaultSettingsDTO as R, NodeIconSchema as Rt, CommentSubjectType as S, GalleryCoverFit as St, FieldType as T, RecordVO as Tt, VaultItemVO as U, VaultItemInput as V, NodeType as Vt, VaultRuntimeEnv as W, AssetTextStatus as X, AssetDetailVO as Y, AssetUsageVO as Z, ChangeRequestVO as _, UpdateFormDTO as _t, createBusabaseClient as a, ActivityItemVO as at, CommentMentionTargetType as b, BaseVO as bt, AuditAction as c, FormFieldBindingVO as ct, ChangeRequestBatchFailureVO as d, FormSubmitResultVO as dt, GrepResultVO as et, ChangeRequestCountsVO as f, FormThemeVO as ft, ChangeRequestTargetType as g, SubmitFormDTO as gt, ChangeRequestStatus as h, ListFormsVO as ht, ResolvedConfig as i, NodeDetailVO as it, ReviewVO as j, ViewSortVO as jt, OperationStatus as k, ViewFilterOperator as kt, AuditEventVO as l, FormPageSourceVO as lt, ChangeRequestReviewBatchResultVO as m, ListFormsDTO as mt, BusabaseConfig as n, FileTreeNodeVO as nt, resolveConfig as o, CreateFormDTO as ot, ChangeRequestMergeBatchResultVO as p, FormVO as pt, FileNodeMetadata as q, DEFAULT_BASE_URL as r, FileTreeReadFileVO as rt, AgentTaskVO as s, FormBoundFieldVO as st, BusabaseClient as t, FileTreeFileVO as tt, BusabaseSourceChannel as u, FormShareVO as ut, CommentMentionDispatchStatus as v, AssetAttachmentRef as vt, CommitVO as w, RecordLinkVO as wt, CommentMentionVO as x, GalleryCardSize as xt, CommentMentionInputDTO as y, BaseFieldVO as yt, VaultAccessPolicy as z, CREATABLE_NODE_TYPES as zt };
25436
+ 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 };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { $ as GrepInputDTO, A as OperationVO, At as ViewFilterVO, B as VaultEnvironment, Bt as CreatableNodeType, C as CommentVO, Ct as GanttScale, D as NodeSearchResultVO, Dt as VIEW_FIELD_MIN_WIDTH, E as LookupRollup, Et as VIEW_FIELD_MAX_WIDTH, F as SearchResultVO, Ft as CloudContract, G as VaultScopeType, H as VaultItemKind, Ht as OperationKind, I as SourceAttributionVO, It as cloudContract, J as FileNodeVO, K as VaultSettingsVO, L as UserRefVO, Lt as NodeIcon, M as ReviewVerdict, Mt as ViewType, N as SearchResponseVO, Nt as ViewVO, O as NodeVO, Ot as ViewConfigVO, P as SearchResultKind, Pt as AttachmentRef, Q as AssetVO, R as UpdateVaultSettingsDTO, Rt as NodeIconSchema, S as CommentSubjectType, St as GalleryCoverFit, T as FieldType, Tt as RecordVO, U as VaultItemVO, V as VaultItemInput, Vt as NodeType, W as VaultRuntimeEnv, X as AssetTextStatus, Y as AssetDetailVO, Z as AssetUsageVO, _ as ChangeRequestVO, _t as UpdateFormDTO, a as createBusabaseClient, at as ActivityItemVO, b as CommentMentionTargetType, bt as BaseVO, c as AuditAction, ct as FormFieldBindingVO, d as ChangeRequestBatchFailureVO, dt as FormSubmitResultVO, et as GrepResultVO, f as ChangeRequestCountsVO, ft as FormThemeVO, g as ChangeRequestTargetType, gt as SubmitFormDTO, h as ChangeRequestStatus, ht as ListFormsVO, i as ResolvedConfig, it as NodeDetailVO, j as ReviewVO, jt as ViewSortVO, k as OperationStatus, kt as ViewFilterOperator, l as AuditEventVO, lt as FormPageSourceVO, m as ChangeRequestReviewBatchResultVO, mt as ListFormsDTO, n as BusabaseConfig, nt as FileTreeNodeVO, o as resolveConfig, ot as CreateFormDTO, p as ChangeRequestMergeBatchResultVO, pt as FormVO, q as FileNodeMetadata, r as DEFAULT_BASE_URL, rt as FileTreeReadFileVO, s as AgentTaskVO, st as FormBoundFieldVO, t as BusabaseClient, tt as FileTreeFileVO, u as BusabaseSourceChannel, ut as FormShareVO, v as CommentMentionDispatchStatus, vt as AssetAttachmentRef, w as CommitVO, wt as RecordLinkVO, x as CommentMentionVO, xt as GalleryCardSize, y as CommentMentionInputDTO, yt as BaseFieldVO, z as VaultAccessPolicy, zt as CREATABLE_NODE_TYPES } from "./client-DbETz_5k.js";
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-vnydDLvt.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 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 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 };
package/dist/index.js CHANGED
@@ -358,24 +358,30 @@ const iStringSchema = z.union([z.string(), iStringRecordSchema]).describe("i18n
358
358
  //#endregion
359
359
  //#region ../../packages/busabase-contract/src/contract/auto-merge.ts
360
360
  /**
361
- * `autoMerge` on an operation that deliberately never auto-merges.
361
+ * `autoMerge` on a destructive-but-reversible operation.
362
362
  *
363
- * These schemas are NOT `.strict()` and making them strict is not the fix. The
364
- * SDK and CLI ship on their own npm cadence (published ahead of the server as of
365
- * writing), and busabase is self-hosted, so a newer client sending a newer
366
- * optional field to an older server is normal traffic. Blanket strictness turns
367
- * that graceful degradation into a hard 400 for every field, to catch one.
363
+ * These six operations (record delete/restore, field delete/convert, Base
364
+ * archive, mounted-asset content edits, and file batches containing a delete)
365
+ * used to reject `autoMerge: true` outright: they queued for human review no
366
+ * matter who called them. That made sense while the product was positioned as
367
+ * approval-first, but it is not how Busabase is positioned or how the rest of
368
+ * the write surface behaves — every other write is *permission-aware*
369
+ * (`shouldAutoMerge`): unset + write access on the target node means "just do
370
+ * it", and only an explicit `false` forces review.
368
371
  *
369
- * So reject exactly the field that actually confused callers, and say WHY plus
370
- * what to do instead an agent reading "unrecognized key: autoMerge" learns
371
- * nothing it can act on, which is how the original silent-drop bug survived.
372
+ * A single person running their own workspace hit the old behaviour as pure
373
+ * friction: archiving one duplicate record left a change request they then had
374
+ * to go and approve themselves. Reversibility is what makes the permission-aware
375
+ * default safe here — delete ARCHIVES, archive is undone by restore, and a
376
+ * field convert is preceded by `previewFieldConversion`. Callers who do want a
377
+ * second pair of eyes still get it by passing an explicit `autoMerge: false`,
378
+ * which is exactly how every other endpoint in this family expresses that.
372
379
  *
373
- * Rejects `true` only. An explicit `false` asks for exactly what these operations
374
- * already do, so refusing it would be pedantry with a cost: every review-first
375
- * call site in this repo passes a uniform `autoMerge: false`, and clients that do
376
- * the same must not start collecting 400s on the subset of endpoints where the
377
- * flag happens to be moot. Same forward-compatibility argument that rules out
378
- * blanket `.strict()`.
380
+ * The schemas that use this are NOT `.strict()`, and making them strict is not
381
+ * the fix: the SDK and CLI ship on their own npm cadence and busabase is
382
+ * self-hosted, so a newer client sending a newer optional field to an older
383
+ * server is normal traffic. Blanket strictness turns that graceful degradation
384
+ * into a hard 400 for every field, to catch one.
379
385
  *
380
386
  * This lives in its own leaf module (zod only, no sibling imports) on purpose:
381
387
  * putting it in `contract/schemas.ts` created an import cycle with the domain
@@ -383,7 +389,7 @@ const iStringSchema = z.union([z.string(), iStringRecordSchema]).describe("i18n
383
389
  * `ReferenceError: Cannot access 'autoMergeNotAccepted' before initialization`
384
390
  * that `tsc` reported as clean.
385
391
  */
386
- const autoMergeNotAccepted = (reason) => z.literal(false, { error: `\`autoMerge: true\` is not accepted here: ${reason}` }).optional().describe(`Only \`false\` (or omitted) is accepted. ${reason}`);
392
+ const destructiveAutoMerge = (undoNote) => z.boolean().optional().describe(`Whether to approve and merge this change immediately. Omitted defaults to merging immediately if the actor has write access on the target node, otherwise falling back to a pending Change Request; pass explicit false to force review even with write access. ${undoNote}`);
387
393
  //#endregion
388
394
  //#region ../../packages/busabase-contract/src/domains/base/contract/base-schemas.ts
389
395
  const fieldNameSchema = z.union([z.string().min(1), iStringRecordSchema.refine((record) => Object.values(record).some((value) => value && value.trim().length > 0), "field name must have at least one non-empty locale value")]);
@@ -530,16 +536,13 @@ const createBaseFieldInputSchema = z.object({
530
536
  * node, otherwise falls back to a pending ChangeRequest. Explicit `false` forces
531
537
  * review even with write access.
532
538
  *
533
- * Deliberately NOT on the `delete` and `convert` branches below. The line this
534
- * codebase already drawsrecord `update` auto-merges, record `delete`/`restore`
535
- * never do, and `assets.editContent` never does is about whether CONTENT data
536
- * is at stake, not about the verb. Adding, renaming, reordering, or un-deleting a
537
- * field touches only the schema; deleting one soft-deletes its stored values with
538
- * it, and converting one can drop values outright (which is why
539
- * `previewFieldConversion` exists as a dry run). Those two stay in front of a
540
- * human.
539
+ * The `delete` and `convert` branches below used to reject `autoMerge` outright.
540
+ * They no longer do see `contract/auto-merge.ts` for why. They carry a
541
+ * `destructiveAutoMerge` schema instead: the same tri-state, with a description
542
+ * that says what the operation costs to undo, so a caller who genuinely wants a
543
+ * second pair of eyes knows to pass `false`.
541
544
  */
542
- const fieldAutoMergeSchema = z.boolean().optional().describe("Whether to approve and merge this field change immediately. Omitted defaults to merging immediately if the actor has write access on the Base's node, otherwise falling back to a pending Change Request; pass explicit false to force review even with write access. Not accepted by the delete and convert operations, which always require review.");
545
+ const fieldAutoMergeSchema = z.boolean().optional().describe("Whether to approve and merge this field change immediately. Omitted defaults to merging immediately if the actor has write access on the Base's node, otherwise falling back to a pending Change Request; pass explicit false to force review even with write access.");
543
546
  const createFieldChangeRequestInputSchema = createBaseFieldInputSchema.extend({
544
547
  message: z.string().optional().default("Add field"),
545
548
  submittedBy: z.string().optional().default("local-editor"),
@@ -549,7 +552,7 @@ const deleteFieldChangeRequestInputSchema = z.object({
549
552
  fieldId: z.string().min(1),
550
553
  message: z.string().optional(),
551
554
  submittedBy: z.string().optional().default("local-editor"),
552
- autoMerge: autoMergeNotAccepted("deleting a field soft-deletes its stored values with it, so it always requires review. Omit the flag.")
555
+ autoMerge: destructiveAutoMerge("A deleted field is soft-deleted with its stored values and is brought back by the `restore` operation.")
553
556
  });
554
557
  const updateFieldChangeRequestInputSchema = z.object({
555
558
  fieldId: z.string().min(1),
@@ -564,7 +567,15 @@ const updateFieldChangeRequestInputSchema = z.object({
564
567
  });
565
568
  const previewFieldConversionInputSchema = z.object({
566
569
  fieldId: z.string().min(1),
567
- newType: fieldTypeSchema
570
+ newType: fieldTypeSchema,
571
+ /**
572
+ * Mirrors `convertFieldChangeRequest.selectChoiceMode` so the dry run models the
573
+ * conversion the caller is actually going to submit. Under `auto_create` a value with
574
+ * no matching choice is not a conflict — the merge mints a choice for it — while under
575
+ * `null_on_missing` the same value is dropped. Defaults to `null_on_missing`, matching
576
+ * the mutation's own default.
577
+ */
578
+ selectChoiceMode: z.enum(["auto_create", "null_on_missing"]).default("null_on_missing")
568
579
  });
569
580
  const previewFieldConversionOutputSchema = z.object({
570
581
  totalCount: z.number(),
@@ -581,7 +592,7 @@ const convertFieldChangeRequestInputSchema = z.object({
581
592
  selectChoiceMode: z.enum(["auto_create", "null_on_missing"]).default("null_on_missing"),
582
593
  message: z.string().optional(),
583
594
  submittedBy: z.string().optional().default("local-editor"),
584
- autoMerge: autoMergeNotAccepted("converting a field's type can drop values, so it always requires review. Run previewFieldConversion first to see what would change, then omit the flag.")
595
+ autoMerge: destructiveAutoMerge("A convert can drop values that do not fit the new type — call `previewFieldConversion` first to see exactly which, and pass `autoMerge: false` if you want a human to sign off on that preview.")
585
596
  });
586
597
  const reorderFieldsChangeRequestInputSchema = z.object({
587
598
  fieldIds: z.array(z.string()).min(1),
@@ -592,7 +603,7 @@ const reorderFieldsChangeRequestInputSchema = z.object({
592
603
  const archiveBaseInputSchema = z.object({
593
604
  message: z.string().optional(),
594
605
  submittedBy: z.string().optional().default("local-editor"),
595
- autoMerge: autoMergeNotAccepted("archiving a Base removes it and every record in it from every listing at once, so it always requires review. Omit the flag.")
606
+ autoMerge: destructiveAutoMerge("Archiving takes the Base and every record in it out of every listing at once. That is reversible via `operation: \"restore\"`, but it is the widest-blast-radius write in this family — pass `autoMerge: false` when it should stop for a human.")
596
607
  });
597
608
  const restoreBaseInputSchema = z.object({
598
609
  message: z.string().optional(),
@@ -875,7 +886,7 @@ const folderNodeType = {
875
886
  /**
876
887
  * Form node: an agent-authored, sandboxed web page bound to a Base via an
877
888
  * explicit field-binding contract. A submission does NOT write a record
878
- * directly — it produces an approval-first record-create ChangeRequest on the
889
+ * directly — it produces a review-first record-create ChangeRequest on the
879
890
  * target Base (so the submitting act reuses the base's `record_create` op, not a
880
891
  * form-specific one). The form's own config (bindings/page/share) is owner-
881
892
  * managed and edited directly, so this node contributes no CR operations of its
@@ -1085,8 +1096,8 @@ const NodeIconSchema = z.discriminatedUnion("type", [z.object({
1085
1096
  //#region ../../packages/busabase-contract/src/contract/node-agent-prompt-schemas.ts
1086
1097
  /**
1087
1098
  * Per-node custom scenario prompts (`node.metadata.agentPrompts`) — the single
1088
- * schema shared by BOTH write and read paths, per
1089
- * `apps/busabase-cloud/content/spec/node-agent-prompts-v2.md` §7.3:
1099
+ * schema shared by BOTH write and read paths, per the node-agent-prompts
1100
+ * design (v2) §7.3:
1090
1101
  *
1091
1102
  * - Write: `busabase-cli nodes set-agent-prompts` validates a file against this
1092
1103
  * schema client-side, before calling `nodes.updateMetadata` — a malformed file
@@ -1178,7 +1189,8 @@ const nodeSchema = z.lazy(() => z.object({
1178
1189
  updatedAt: z.string(),
1179
1190
  baseId: z.string().nullable(),
1180
1191
  children: z.array(nodeSchema),
1181
- hasChildren: z.boolean().optional()
1192
+ hasChildren: z.boolean().optional(),
1193
+ shared: z.boolean().optional()
1182
1194
  }));
1183
1195
  const nodePrincipalSchema = z.object({
1184
1196
  id: z.string(),
@@ -1468,6 +1480,51 @@ const commentSchema = z.object({
1468
1480
  createdAt: z.string(),
1469
1481
  updatedAt: z.string()
1470
1482
  });
1483
+ /**
1484
+ * One row of the Inbox's Mentions tab: a comment the caller was `@`-mentioned
1485
+ * in, plus where to go to read it in context.
1486
+ *
1487
+ * Keyed by COMMENT, not by mention row — being named twice in one comment is
1488
+ * legitimate (each occurrence needs its own span to render its own chip), but
1489
+ * it is still one thing to go read, so it is one entry here.
1490
+ */
1491
+ const mentionInboxItemSchema = z.object({
1492
+ commentId: z.string(),
1493
+ subjectType: commentSubjectTypeSchema,
1494
+ /** Comment body, for the row's preview line. */
1495
+ body: z.string(),
1496
+ authorId: z.string(),
1497
+ author: userRefSchema.nullable().optional().default(null),
1498
+ createdAt: z.string(),
1499
+ /** Null once read. The newest unread stamp across this comment's mentions. */
1500
+ unread: z.boolean(),
1501
+ /**
1502
+ * Dashboard-relative path to the comment's context, or null when the subject
1503
+ * has no page of its own (a `commit`-scoped comment on a comment that is not
1504
+ * attached to a change request — the repo has no commit detail route).
1505
+ * A null href still renders a row: swallowing the notification because we
1506
+ * cannot link it would leave the recipient never knowing they were mentioned.
1507
+ */
1508
+ href: z.string().nullable()
1509
+ });
1510
+ const mentionInboxPageSchema = z.object({
1511
+ items: z.array(mentionInboxItemSchema),
1512
+ total: z.number().int(),
1513
+ /** Distinct unread comments — what the tab badge shows. */
1514
+ unreadCount: z.number().int()
1515
+ });
1516
+ const listMentionInboxInputSchema = z.object({
1517
+ page: z.number().int().min(1).optional().default(1),
1518
+ pageSize: z.number().int().min(1).max(100).optional().default(50)
1519
+ });
1520
+ const markMentionsReadInputSchema = z.object({
1521
+ /** Stamps every unread mention row this caller has on that comment. */
1522
+ commentId: z.string() });
1523
+ const markMentionsReadOutputSchema = z.object({
1524
+ /** How many rows were stamped; 0 when it was already read. */
1525
+ marked: z.number().int(),
1526
+ unreadCount: z.number().int()
1527
+ });
1471
1528
  const changeRequestStatusSchema = z.enum([
1472
1529
  "in_review",
1473
1530
  "changes_requested",
@@ -1683,7 +1740,7 @@ const createDeleteChangeRequestInputSchema = z.object({
1683
1740
  message: z.string().optional().default("Delete record").describe("Explanation shown to the human reviewer. Say what is being removed and why, e.g. \"Archive duplicate contact — merged into Acme Corp\"."),
1684
1741
  submittedBy: z.string().optional().default("local-producer"),
1685
1742
  deleteMode: z.enum(["archive"]).optional().default("archive"),
1686
- autoMerge: autoMergeNotAccepted("archiving a record removes user content from every listing, so it always requires review. Omit the flag.")
1743
+ autoMerge: destructiveAutoMerge("Archiving is reversible: the record leaves every listing but is restored intact by `operation: \"restore\"`.")
1687
1744
  });
1688
1745
  const reviseOperationInputSchema = z.object({
1689
1746
  fields: z.record(z.string(), z.unknown()).describe("Updated field values keyed by field slug. If you set the base's PRIMARY field (its first field), keep it a short human-readable name — it is the record's display title everywhere."),
@@ -1939,7 +1996,7 @@ const createFileTreeChangeRequestInputSchema = z.object({
1939
1996
  message: z.string().optional().default("Update file tree").describe("Explanation shown to the human reviewer. Write a conventional-commit style subject — imperative verb + what + why, e.g. \"Rewrite README.md quickstart for the new auth flow\"."),
1940
1997
  submittedBy: z.string().optional().default("local-producer"),
1941
1998
  operations: z.array(fileTreeFileOperationInputSchema).min(1),
1942
- autoMerge: z.boolean().optional().describe("Whether to approve and merge these file changes immediately. Omitted defaults to merging immediately if the actor has write access on the node, otherwise falling back to a pending Change Request; pass explicit false to force review even with write access. IGNORED when any operation is a delete — those batches always require review.")
1999
+ autoMerge: z.boolean().optional().describe("Whether to approve and merge these file changes immediately. Omitted defaults to merging immediately if the actor has write access on the node, otherwise falling back to a pending Change Request; pass explicit false to force review even with write access. Applies to every operation kind, deletes included.")
1943
2000
  });
1944
2001
  const fileTreeNodeTypeSchema = z.enum([
1945
2002
  "skill",
@@ -2325,7 +2382,7 @@ const EditAssetContentInputSchema = z.object({
2325
2382
  edits: z.array(AssetContentEditSchema).min(1),
2326
2383
  message: z.string().optional().default("Edit file content").describe("Explanation shown to the human reviewer. Write a conventional-commit style subject — imperative verb + what + why, e.g. \"Fix typo in setup instructions\"."),
2327
2384
  submittedBy: z.string().optional().default("agent"),
2328
- autoMerge: autoMergeNotAccepted("editContent rewrites the real mounted file bytes, so it always requires review. Omit the flag.")
2385
+ autoMerge: destructiveAutoMerge("This rewrites the real mounted file bytes; the previous content stays in the Change Request history, so it is recoverable but not one-click undoable.")
2329
2386
  });
2330
2387
  /**
2331
2388
  * `GET /assets/{assetId}/content` result. oRPC contracts here are JSON in/out
@@ -2429,7 +2486,7 @@ const assetsContract = {
2429
2486
  path: "/assets/{assetId}/edit-content",
2430
2487
  tags: ["Assets", "Change Requests"],
2431
2488
  summary: "Edit an asset's file content via string-replace edits, as a ChangeRequest",
2432
- successDescription: "Applied the string-replace edits (coding-agent Edit-tool semantics: unique-match or replaceAll) to the asset's current mounted Drive/Skill file content and proposed the result as a ChangeRequest (status \"in_review\") for human review. Reuses the existing filetree update-via-CR pipeline end to end, including baseContentHash optimistic-concurrency conflict protection at merge time. Requires the asset to be mounted in exactly one editable Drive/Skill location."
2489
+ successDescription: "Applied the string-replace edits (coding-agent Edit-tool semantics: unique-match or replaceAll) to the asset's current mounted Drive/Skill file content and recorded the result as a ChangeRequest merged immediately when the actor has write access on the mounting node, left \"in_review\" otherwise or when `autoMerge: false` is passed. Reuses the existing filetree update-via-CR pipeline end to end, including baseContentHash optimistic-concurrency conflict protection at merge time. Requires the asset to be mounted in exactly one editable Drive/Skill location."
2433
2490
  }).input(EditAssetContentInputSchema).output(changeRequestSchema)
2434
2491
  };
2435
2492
  //#endregion
@@ -2785,7 +2842,7 @@ const recordGetInputSchema = z.union([z.object({ recordId: z.string().min(1).des
2785
2842
  const restoreRecordInputSchema = z.object({
2786
2843
  message: z.string().optional(),
2787
2844
  submittedBy: z.string().optional().default("local-editor"),
2788
- autoMerge: autoMergeNotAccepted("restoring a record brings archived content back into every listing, so it always requires review. Omit the flag.")
2845
+ autoMerge: destructiveAutoMerge("Restoring is itself the undo of an archive, and is undone again by `operation: \"delete\"`.")
2789
2846
  });
2790
2847
  /**
2791
2848
  * Every record change request in one shape. These three used to be PUT, DELETE,
@@ -2978,7 +3035,7 @@ const recordContract = {
2978
3035
  path: "/records/{recordId}/change-requests",
2979
3036
  tags: ["Records", "Change Requests"],
2980
3037
  summary: "Create record change request",
2981
- successDescription: "Creates a record change request selected by `operation`. Updates auto-merge when the actor has write access unless `autoMerge: false`; delete and restore remain review-first."
3038
+ successDescription: "Creates a record change request selected by `operation`. All three operations are permission-aware: they merge immediately when the actor has write access on the Base's node, and land as a pending Change Request otherwise or when `autoMerge: false` is passed."
2982
3039
  }).input(recordChangeRequestInputSchema).output(z.union([recordSchema.extend({ materialized: z.literal(true) }), changeRequestSchema.extend({ materialized: z.literal(false) })])),
2983
3040
  listChangeRequests: oc.route({
2984
3041
  method: "GET",
@@ -3435,7 +3492,7 @@ const formContract = {
3435
3492
  path: "/forms/{nodeId}/submit",
3436
3493
  tags: ["Forms"],
3437
3494
  summary: "Submit a filled-in form",
3438
- successDescription: "Creates an approval-first record-create ChangeRequest on the target Base."
3495
+ successDescription: "Creates a review-first record-create ChangeRequest on the target Base — a form submission always waits for a human, whoever submitted it."
3439
3496
  }).input(SubmitFormInputSchema.extend({ nodeId: z.string() })).output(FormSubmitResultSchema)
3440
3497
  };
3441
3498
  //#endregion
@@ -3445,7 +3502,7 @@ const formContract = {
3445
3502
  *
3446
3503
  * The manual existed only over MCP: `instructions`, `resources/*` and the
3447
3504
  * `busabase_guide` tool. Anything driving the REST API — busabase-cli, a script,
3448
- * a CI step, an AirApp — was told nothing about the approval-first rules, the
3505
+ * a CI step, an AirApp — was told nothing about the change-request rules, the
3449
3506
  * field types, or the AirApp runtime contract, and was then judged on whether it
3450
3507
  * guessed the house rules. These routes publish the same documents, built from
3451
3508
  * the same source, so the two surfaces cannot drift.
@@ -4647,6 +4704,28 @@ const getNodeInputSchema = z.object({
4647
4704
  const NodeIconUploadUrlInputSchema = RequestUploadUrlInputSchema.extend({ nodeId: z.string() });
4648
4705
  const NodeIconConfirmInputSchema = ConfirmUploadInputSchema.extend({ nodeId: z.string() });
4649
4706
  //#endregion
4707
+ //#region ../../packages/busabase-contract/src/contract/node-route-state-schemas.ts
4708
+ /**
4709
+ * Lightweight route guard for the dashboard. Archived variants intentionally
4710
+ * carry metadata only: resolving a tombstone must never hydrate node content.
4711
+ */
4712
+ const NodeRouteStateVOSchema = z.discriminatedUnion("status", [
4713
+ z.object({
4714
+ status: z.literal("active"),
4715
+ nodeId: z.string()
4716
+ }),
4717
+ z.object({
4718
+ status: z.literal("archived"),
4719
+ nodeId: z.string(),
4720
+ type: z.enum(NODE_TYPES),
4721
+ name: z.string(),
4722
+ slug: z.string(),
4723
+ archivedAt: z.string(),
4724
+ canRestore: z.boolean()
4725
+ }),
4726
+ z.object({ status: z.literal("unavailable") })
4727
+ ]);
4728
+ //#endregion
4650
4729
  //#region ../../packages/busabase-contract/src/contract/busabase.ts
4651
4730
  const changeRequestBatchFailureSchema = z.object({
4652
4731
  changeRequestId: z.string(),
@@ -4766,6 +4845,13 @@ const busabaseContractRoutes = {
4766
4845
  summary: "List a node's ancestor ids",
4767
4846
  successDescription: "The node's ancestor ids, root-first, excluding the node itself (`[]` directly under the workspace root). `nodeId` accepts an id or a slug, same as `nodes.get`; pass `type` when a slug exists under more than one type. Lets a depth-bounded, lazily-expanded tree open straight to a deep node on a cold load (a refresh, a bookmark, a shared link) without one round trip per level."
4768
4847
  }).input(getNodeInputSchema).output(nodeAncestorsVOSchema),
4848
+ resolveRouteState: oc.route({
4849
+ method: "GET",
4850
+ path: "/nodes/route-state/{nodeId}",
4851
+ tags: ["Nodes"],
4852
+ summary: "Resolve whether a dashboard node route is active, archived, or unavailable",
4853
+ successDescription: "A lightweight route state. Archived nodes return only tombstone metadata, never node content. Hidden, deleted, ambiguous, and anonymous archived nodes are all unavailable."
4854
+ }).input(getNodeInputSchema).output(NodeRouteStateVOSchema),
4769
4855
  createChangeRequest: oc.route({
4770
4856
  method: "POST",
4771
4857
  path: "/nodes/change-requests",
@@ -5000,7 +5086,28 @@ const busabaseContractRoutes = {
5000
5086
  tags: ["Comments"],
5001
5087
  summary: "Create comment",
5002
5088
  successDescription: "Created comment attached to a Busabase subject."
5003
- }).input(createCommentInputSchema).output(commentSchema)
5089
+ }).input(createCommentInputSchema).output(commentSchema),
5090
+ /**
5091
+ * The Inbox's Mentions tab: comments this caller was `@`-mentioned in.
5092
+ *
5093
+ * Scoped to the caller — there is no "whose mentions" input, because a
5094
+ * mention inbox that could be pointed at somebody else would be a way to
5095
+ * read comments across the workspace by proxy.
5096
+ */
5097
+ listMentions: oc.route({
5098
+ method: "GET",
5099
+ path: "/comments/mentions",
5100
+ tags: ["Comments"],
5101
+ summary: "List comments that mention me",
5102
+ successDescription: "One entry per comment the caller is mentioned in, newest first, with the unread count for the tab badge."
5103
+ }).input(listMentionInboxInputSchema).output(mentionInboxPageSchema),
5104
+ markMentionsRead: oc.route({
5105
+ method: "POST",
5106
+ path: "/comments/mentions/read",
5107
+ tags: ["Comments"],
5108
+ summary: "Mark my mentions on a comment as read",
5109
+ successDescription: "Stamps every unread mention this caller has on that comment, and returns the remaining unread count."
5110
+ }).input(markMentionsReadInputSchema).output(markMentionsReadOutputSchema)
5004
5111
  },
5005
5112
  agent: { listTasks: oc.route({
5006
5113
  method: "GET",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "busabase-sdk",
3
- "version": "0.40.1",
3
+ "version": "0.42.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).",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/busabase/busabase/tree/main/apps/busabase-sdk",
@@ -61,15 +61,15 @@
61
61
  "zod": "^4.3.6"
62
62
  },
63
63
  "devDependencies": {
64
- "@types/node": "^24.13.2",
64
+ "@types/node": "^26.3.0",
65
65
  "jsdom": "^27.0.0",
66
66
  "tsdown": "^0.22.14",
67
67
  "tsx": "^4.20.5",
68
68
  "typescript": "^7.0.2",
69
69
  "vitest": "^4.1.11",
70
70
  "open-domains": "0.0.2",
71
- "busabase-contract": "0.40.1",
72
- "openlib": "0.1.1"
71
+ "openlib": "0.1.1",
72
+ "busabase-contract": "0.42.0"
73
73
  },
74
74
  "engines": {
75
75
  "node": ">=24.18.0"