busa-sdk 0.40.0 → 0.41.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-CWlHll4H.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>>;
@@ -7014,7 +7051,25 @@ declare const cloudContract: {
7014
7051
  role: z.ZodOptional<z.ZodNullable<z.ZodString>>;
7015
7052
  }, z.core.$strip>>>>;
7016
7053
  body: z.ZodString;
7017
- mentionsAi: z.ZodBoolean;
7054
+ mentions: z.ZodDefault<z.ZodArray<z.ZodObject<{
7055
+ id: z.ZodString;
7056
+ type: z.ZodEnum<{
7057
+ agent: "agent";
7058
+ member: "member";
7059
+ }>;
7060
+ targetId: z.ZodString;
7061
+ label: z.ZodString;
7062
+ start: z.ZodNumber;
7063
+ end: z.ZodNumber;
7064
+ dispatchStatus: z.ZodEnum<{
7065
+ failed: "failed";
7066
+ linked: "linked";
7067
+ not_applicable: "not_applicable";
7068
+ queued: "queued";
7069
+ }>;
7070
+ sessionId: z.ZodNullable<z.ZodString>;
7071
+ error: z.ZodNullable<z.ZodString>;
7072
+ }, z.core.$strip>>>;
7018
7073
  createdAt: z.ZodString;
7019
7074
  updatedAt: z.ZodString;
7020
7075
  }, z.core.$strip>>, import("@orpc/contract").MergedErrorMap<Record<never, never>, Record<never, never>>, Record<never, never>>;
@@ -7028,7 +7083,15 @@ declare const cloudContract: {
7028
7083
  subjectId: z.ZodString;
7029
7084
  authorId: z.ZodDefault<z.ZodOptional<z.ZodString>>;
7030
7085
  body: z.ZodString;
7031
- mentionsAi: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
7086
+ mentions: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodObject<{
7087
+ type: z.ZodEnum<{
7088
+ agent: "agent";
7089
+ member: "member";
7090
+ }>;
7091
+ id: z.ZodString;
7092
+ start: z.ZodNumber;
7093
+ end: z.ZodNumber;
7094
+ }, z.core.$strip>>>>;
7032
7095
  }, z.core.$strip>, z.ZodObject<{
7033
7096
  id: z.ZodString;
7034
7097
  subjectType: z.ZodEnum<{
@@ -7051,10 +7114,62 @@ declare const cloudContract: {
7051
7114
  role: z.ZodOptional<z.ZodNullable<z.ZodString>>;
7052
7115
  }, z.core.$strip>>>>;
7053
7116
  body: z.ZodString;
7054
- mentionsAi: z.ZodBoolean;
7117
+ mentions: z.ZodDefault<z.ZodArray<z.ZodObject<{
7118
+ id: z.ZodString;
7119
+ type: z.ZodEnum<{
7120
+ agent: "agent";
7121
+ member: "member";
7122
+ }>;
7123
+ targetId: z.ZodString;
7124
+ label: z.ZodString;
7125
+ start: z.ZodNumber;
7126
+ end: z.ZodNumber;
7127
+ dispatchStatus: z.ZodEnum<{
7128
+ failed: "failed";
7129
+ linked: "linked";
7130
+ not_applicable: "not_applicable";
7131
+ queued: "queued";
7132
+ }>;
7133
+ sessionId: z.ZodNullable<z.ZodString>;
7134
+ error: z.ZodNullable<z.ZodString>;
7135
+ }, z.core.$strip>>>;
7055
7136
  createdAt: z.ZodString;
7056
7137
  updatedAt: z.ZodString;
7057
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>>;
7058
7173
  };
7059
7174
  agent: {
7060
7175
  listTasks: import("@orpc/contract").ContractProcedure<import("@orpc/contract").Schema<unknown, unknown>, z.ZodArray<z.ZodObject<{
@@ -7515,7 +7630,25 @@ declare const cloudContract: {
7515
7630
  role: z.ZodOptional<z.ZodNullable<z.ZodString>>;
7516
7631
  }, z.core.$strip>>>>;
7517
7632
  body: z.ZodString;
7518
- mentionsAi: z.ZodBoolean;
7633
+ mentions: z.ZodDefault<z.ZodArray<z.ZodObject<{
7634
+ id: z.ZodString;
7635
+ type: z.ZodEnum<{
7636
+ agent: "agent";
7637
+ member: "member";
7638
+ }>;
7639
+ targetId: z.ZodString;
7640
+ label: z.ZodString;
7641
+ start: z.ZodNumber;
7642
+ end: z.ZodNumber;
7643
+ dispatchStatus: z.ZodEnum<{
7644
+ failed: "failed";
7645
+ linked: "linked";
7646
+ not_applicable: "not_applicable";
7647
+ queued: "queued";
7648
+ }>;
7649
+ sessionId: z.ZodNullable<z.ZodString>;
7650
+ error: z.ZodNullable<z.ZodString>;
7651
+ }, z.core.$strip>>>;
7519
7652
  createdAt: z.ZodString;
7520
7653
  updatedAt: z.ZodString;
7521
7654
  }, z.core.$strip>>;
@@ -10600,7 +10733,7 @@ declare const cloudContract: {
10600
10733
  fieldId: z.ZodString;
10601
10734
  message: z.ZodOptional<z.ZodString>;
10602
10735
  submittedBy: z.ZodDefault<z.ZodOptional<z.ZodString>>;
10603
- autoMerge: z.ZodOptional<z.ZodLiteral<false>>;
10736
+ autoMerge: z.ZodOptional<z.ZodBoolean>;
10604
10737
  baseId: z.ZodString;
10605
10738
  operation: z.ZodLiteral<"delete">;
10606
10739
  }, z.core.$strip>, z.ZodObject<{
@@ -10641,7 +10774,7 @@ declare const cloudContract: {
10641
10774
  }>>;
10642
10775
  message: z.ZodOptional<z.ZodString>;
10643
10776
  submittedBy: z.ZodDefault<z.ZodOptional<z.ZodString>>;
10644
- autoMerge: z.ZodOptional<z.ZodLiteral<false>>;
10777
+ autoMerge: z.ZodOptional<z.ZodBoolean>;
10645
10778
  baseId: z.ZodString;
10646
10779
  operation: z.ZodLiteral<"convert">;
10647
10780
  }, z.core.$strip>, z.ZodObject<{
@@ -11120,6 +11253,10 @@ declare const cloudContract: {
11120
11253
  whiteboard: "whiteboard";
11121
11254
  yaml: "yaml";
11122
11255
  }>;
11256
+ selectChoiceMode: z.ZodDefault<z.ZodEnum<{
11257
+ auto_create: "auto_create";
11258
+ null_on_missing: "null_on_missing";
11259
+ }>>;
11123
11260
  baseId: z.ZodString;
11124
11261
  }, z.core.$strip>, z.ZodObject<{
11125
11262
  totalCount: z.ZodNumber;
@@ -11133,7 +11270,7 @@ declare const cloudContract: {
11133
11270
  lifecycleChangeRequest: import("@orpc/contract").ContractProcedure<z.ZodDiscriminatedUnion<[z.ZodObject<{
11134
11271
  message: z.ZodOptional<z.ZodString>;
11135
11272
  submittedBy: z.ZodDefault<z.ZodOptional<z.ZodString>>;
11136
- autoMerge: z.ZodOptional<z.ZodLiteral<false>>;
11273
+ autoMerge: z.ZodOptional<z.ZodBoolean>;
11137
11274
  baseId: z.ZodString;
11138
11275
  operation: z.ZodLiteral<"archive">;
11139
11276
  }, z.core.$strip>, z.ZodObject<{
@@ -14160,7 +14297,7 @@ declare const cloudContract: {
14160
14297
  }, z.core.$strict>>;
14161
14298
  message: z.ZodDefault<z.ZodOptional<z.ZodString>>;
14162
14299
  submittedBy: z.ZodDefault<z.ZodOptional<z.ZodString>>;
14163
- autoMerge: z.ZodOptional<z.ZodLiteral<false>>;
14300
+ autoMerge: z.ZodOptional<z.ZodBoolean>;
14164
14301
  }, z.core.$strip>, z.ZodObject<{
14165
14302
  id: z.ZodString;
14166
14303
  baseId: z.ZodNullable<z.ZodString>;
@@ -20261,13 +20398,13 @@ declare const cloudContract: {
20261
20398
  deleteMode: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
20262
20399
  archive: "archive";
20263
20400
  }>>>;
20264
- autoMerge: z.ZodOptional<z.ZodLiteral<false>>;
20401
+ autoMerge: z.ZodOptional<z.ZodBoolean>;
20265
20402
  recordId: z.ZodString;
20266
20403
  operation: z.ZodLiteral<"delete">;
20267
20404
  }, z.core.$strip>, z.ZodObject<{
20268
20405
  message: z.ZodOptional<z.ZodString>;
20269
20406
  submittedBy: z.ZodDefault<z.ZodOptional<z.ZodString>>;
20270
- autoMerge: z.ZodOptional<z.ZodLiteral<false>>;
20407
+ autoMerge: z.ZodOptional<z.ZodBoolean>;
20271
20408
  recordId: z.ZodString;
20272
20409
  operation: z.ZodLiteral<"restore">;
20273
20410
  }, z.core.$strip>], "operation">, z.ZodUnion<readonly [z.ZodObject<{
@@ -24962,6 +25099,13 @@ interface NodeVO {
24962
25099
  * as `children.length > 0`.
24963
25100
  */
24964
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;
24965
25109
  }
24966
25110
  interface CommitVO {
24967
25111
  id: string;
@@ -25074,6 +25218,34 @@ interface ReviewVO {
25074
25218
  visibleOperationHeads: Record<string, string>;
25075
25219
  createdAt: string;
25076
25220
  }
25221
+ type CommentMentionTargetType = "member" | "agent";
25222
+ /**
25223
+ * Dispatch state of one mention BEFORE a session exists. Once `linked`, the
25224
+ * agent session owns running/waiting/done/failed — it is never mirrored here.
25225
+ */
25226
+ type CommentMentionDispatchStatus = "not_applicable" | "queued" | "linked" | "failed";
25227
+ /**
25228
+ * One mention as the composer submits it. `start`/`end` are UTF-16 code unit
25229
+ * offsets into the comment body (see the contract schema for why).
25230
+ */
25231
+ interface CommentMentionInputDTO {
25232
+ type: CommentMentionTargetType;
25233
+ id: string;
25234
+ start: number;
25235
+ end: number;
25236
+ }
25237
+ interface CommentMentionVO {
25238
+ id: string;
25239
+ type: CommentMentionTargetType;
25240
+ targetId: string;
25241
+ /** Server-resolved display name; falls back to the raw target id. */
25242
+ label: string;
25243
+ start: number;
25244
+ end: number;
25245
+ dispatchStatus: CommentMentionDispatchStatus;
25246
+ sessionId: string | null;
25247
+ error: string | null;
25248
+ }
25077
25249
  interface CommentVO {
25078
25250
  id: string;
25079
25251
  subjectType: CommentSubjectType;
@@ -25085,10 +25257,38 @@ interface CommentVO {
25085
25257
  authorId: string;
25086
25258
  author?: UserRefVO | null;
25087
25259
  body: string;
25088
- mentionsAi: boolean;
25260
+ mentions: CommentMentionVO[];
25089
25261
  createdAt: string;
25090
25262
  updatedAt: string;
25091
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
+ }
25092
25292
  interface AgentTaskVO {
25093
25293
  changeRequest: ChangeRequestVO;
25094
25294
  trigger: "changes_requested" | "ai_mention";
@@ -25233,4 +25433,4 @@ declare function resolveConfig(config?: BusabaseConfig): ResolvedConfig;
25233
25433
  */
25234
25434
  declare function createBusabaseClient(config?: BusabaseConfig): BusabaseClient;
25235
25435
  //#endregion
25236
- export { FileTreeReadFileVO as $, SearchResultKind as A, AttachmentRef as At, VaultRuntimeEnv as B, NodeSearchResultVO as C, VIEW_FIELD_MIN_WIDTH as Ct, ReviewVO as D, ViewSortVO as Dt, OperationVO as E, ViewFilterVO as Et, VaultAccessPolicy as F, CREATABLE_NODE_TYPES as Ft, AssetDetailVO as G, VaultSettingsVO as H, VaultEnvironment as I, CreatableNodeType as It, AssetVO as J, AssetTextStatus as K, VaultItemInput as L, NodeType as Lt, SourceAttributionVO as M, cloudContract as Mt, UserRefVO as N, NodeIcon as Nt, ReviewVerdict as O, ViewType as Ot, UpdateVaultSettingsDTO as P, NodeIconSchema as Pt, FileTreeNodeVO as Q, VaultItemKind as R, OperationKind as Rt, LookupRollup as S, VIEW_FIELD_MAX_WIDTH as St, OperationStatus as T, ViewFilterOperator as Tt, FileNodeMetadata as U, VaultScopeType as V, FileNodeVO as W, GrepResultVO as X, GrepInputDTO as Y, FileTreeFileVO as Z, ChangeRequestVO as _, GalleryCardSize as _t, createBusabaseClient as a, FormPageSourceVO as at, CommitVO as b, RecordLinkVO as bt, AuditAction as c, FormThemeVO as ct, ChangeRequestBatchFailureVO as d, ListFormsVO as dt, NodeDetailVO as et, ChangeRequestCountsVO as f, SubmitFormDTO as ft, ChangeRequestTargetType as g, BaseVO as gt, ChangeRequestStatus as h, BaseFieldVO as ht, ResolvedConfig as i, FormFieldBindingVO as it, SearchResultVO as j, CloudContract as jt, SearchResponseVO as k, ViewVO as kt, AuditEventVO as l, FormVO as lt, ChangeRequestReviewBatchResultVO as m, AssetAttachmentRef as mt, BusabaseConfig as n, CreateFormDTO as nt, resolveConfig as o, FormShareVO as ot, ChangeRequestMergeBatchResultVO as p, UpdateFormDTO as pt, AssetUsageVO as q, DEFAULT_BASE_URL as r, FormBoundFieldVO as rt, AgentTaskVO as s, FormSubmitResultVO as st, BusabaseClient as t, ActivityItemVO as tt, BusabaseSourceChannel as u, ListFormsDTO as ut, CommentSubjectType as v, GalleryCoverFit as vt, NodeVO as w, ViewConfigVO as wt, FieldType as x, RecordVO as xt, CommentVO as y, GanttScale as yt, VaultItemVO as z };
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 FileTreeReadFileVO, A as SearchResultKind, At as AttachmentRef, B as VaultRuntimeEnv, C as NodeSearchResultVO, Ct as VIEW_FIELD_MIN_WIDTH, D as ReviewVO, Dt as ViewSortVO, E as OperationVO, Et as ViewFilterVO, F as VaultAccessPolicy, Ft as CREATABLE_NODE_TYPES, G as AssetDetailVO, H as VaultSettingsVO, I as VaultEnvironment, It as CreatableNodeType, J as AssetVO, K as AssetTextStatus, L as VaultItemInput, Lt as NodeType, M as SourceAttributionVO, Mt as cloudContract, N as UserRefVO, Nt as NodeIcon, O as ReviewVerdict, Ot as ViewType, P as UpdateVaultSettingsDTO, Pt as NodeIconSchema, Q as FileTreeNodeVO, R as VaultItemKind, Rt as OperationKind, S as LookupRollup, St as VIEW_FIELD_MAX_WIDTH, T as OperationStatus, Tt as ViewFilterOperator, U as FileNodeMetadata, V as VaultScopeType, W as FileNodeVO, X as GrepResultVO, Y as GrepInputDTO, Z as FileTreeFileVO, _ as ChangeRequestVO, _t as GalleryCardSize, a as createBusabaseClient, at as FormPageSourceVO, b as CommitVO, bt as RecordLinkVO, c as AuditAction, ct as FormThemeVO, d as ChangeRequestBatchFailureVO, dt as ListFormsVO, et as NodeDetailVO, f as ChangeRequestCountsVO, ft as SubmitFormDTO, g as ChangeRequestTargetType, gt as BaseVO, h as ChangeRequestStatus, ht as BaseFieldVO, i as ResolvedConfig, it as FormFieldBindingVO, j as SearchResultVO, jt as CloudContract, k as SearchResponseVO, kt as ViewVO, l as AuditEventVO, lt as FormVO, m as ChangeRequestReviewBatchResultVO, mt as AssetAttachmentRef, n as BusabaseConfig, nt as CreateFormDTO, o as resolveConfig, ot as FormShareVO, p as ChangeRequestMergeBatchResultVO, pt as UpdateFormDTO, q as AssetUsageVO, r as DEFAULT_BASE_URL, rt as FormBoundFieldVO, s as AgentTaskVO, st as FormSubmitResultVO, t as BusabaseClient, tt as ActivityItemVO, u as BusabaseSourceChannel, ut as ListFormsDTO, v as CommentSubjectType, vt as GalleryCoverFit, w as NodeVO, wt as ViewConfigVO, x as FieldType, xt as RecordVO, y as CommentVO, yt as GanttScale, z as VaultItemVO } from "./client-CWlHll4H.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 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(),
@@ -1404,6 +1416,55 @@ const commentSubjectTypeSchema = z.enum([
1404
1416
  "operation",
1405
1417
  "commit"
1406
1418
  ]);
1419
+ /**
1420
+ * Who a mention points at. `member` tags a person; `agent` names a launchable
1421
+ * Agent target and is what actually starts a session.
1422
+ */
1423
+ const commentMentionTargetTypeSchema = z.enum(["member", "agent"]);
1424
+ /**
1425
+ * Dispatch lifecycle of ONE mention row, before a session exists.
1426
+ *
1427
+ * `not_applicable` is every member row (a person is not dispatched to).
1428
+ * Once `linked`, running/waiting/done/failed belongs to the agent session,
1429
+ * never to a second status column here.
1430
+ */
1431
+ const commentMentionDispatchStatusSchema = z.enum([
1432
+ "not_applicable",
1433
+ "queued",
1434
+ "linked",
1435
+ "failed"
1436
+ ]);
1437
+ /**
1438
+ * One mention as the composer submits it.
1439
+ *
1440
+ * `start`/`end` are **UTF-16 code unit** offsets into `body` — the same unit
1441
+ * `<textarea>` selection APIs and `String.prototype.slice` use, so nothing has
1442
+ * to convert at the UI boundary. A label containing an astral-plane character
1443
+ * (an emoji in a display name) therefore spans two units per visible glyph;
1444
+ * the server rejects a span that would split a surrogate pair.
1445
+ *
1446
+ * No `label` here on purpose: the client never supplies identity. The server
1447
+ * resolves the display name from the member/catalog it already trusts.
1448
+ */
1449
+ const commentMentionInputSchema = z.object({
1450
+ type: commentMentionTargetTypeSchema,
1451
+ /** Member/actor id, or launchable agent slug (`claude-acp`, `buda:<agentId>`). */
1452
+ id: z.string().min(1),
1453
+ start: z.number().int().min(0),
1454
+ end: z.number().int().min(0)
1455
+ });
1456
+ const commentMentionSchema = z.object({
1457
+ id: z.string(),
1458
+ type: commentMentionTargetTypeSchema,
1459
+ targetId: z.string(),
1460
+ /** Server-resolved display name. Falls back to the raw target id. */
1461
+ label: z.string(),
1462
+ start: z.number().int(),
1463
+ end: z.number().int(),
1464
+ dispatchStatus: commentMentionDispatchStatusSchema,
1465
+ sessionId: z.string().nullable(),
1466
+ error: z.string().nullable()
1467
+ });
1407
1468
  const commentSchema = z.object({
1408
1469
  id: z.string(),
1409
1470
  subjectType: commentSubjectTypeSchema,
@@ -1415,10 +1476,55 @@ const commentSchema = z.object({
1415
1476
  authorId: z.string(),
1416
1477
  author: userRefSchema.nullable().optional().default(null),
1417
1478
  body: z.string(),
1418
- mentionsAi: z.boolean(),
1479
+ mentions: z.array(commentMentionSchema).default([]),
1419
1480
  createdAt: z.string(),
1420
1481
  updatedAt: z.string()
1421
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
+ });
1422
1528
  const changeRequestStatusSchema = z.enum([
1423
1529
  "in_review",
1424
1530
  "changes_requested",
@@ -1634,7 +1740,7 @@ const createDeleteChangeRequestInputSchema = z.object({
1634
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\"."),
1635
1741
  submittedBy: z.string().optional().default("local-producer"),
1636
1742
  deleteMode: z.enum(["archive"]).optional().default("archive"),
1637
- 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\"`.")
1638
1744
  });
1639
1745
  const reviseOperationInputSchema = z.object({
1640
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."),
@@ -1653,7 +1759,12 @@ const commentSubjectInputSchema = z.object({
1653
1759
  const createCommentInputSchema = commentSubjectInputSchema.extend({
1654
1760
  authorId: z.string().optional().default("local-admin"),
1655
1761
  body: z.string().trim().min(1),
1656
- mentionsAi: z.boolean().optional().default(false)
1762
+ /**
1763
+ * Structured mentions, owned by the composer. Never inferred from the body by
1764
+ * regex: display names contain spaces and collide with ordinary prose, so
1765
+ * "ask codex about this" must not invoke Codex.
1766
+ */
1767
+ mentions: z.array(commentMentionInputSchema).optional().default([])
1657
1768
  });
1658
1769
  const listInputSchema = z.object({ limit: z.coerce.number().int().min(1).max(100).optional().default(50) }).optional().default({ limit: 50 });
1659
1770
  /**
@@ -1885,7 +1996,7 @@ const createFileTreeChangeRequestInputSchema = z.object({
1885
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\"."),
1886
1997
  submittedBy: z.string().optional().default("local-producer"),
1887
1998
  operations: z.array(fileTreeFileOperationInputSchema).min(1),
1888
- 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.")
1889
2000
  });
1890
2001
  const fileTreeNodeTypeSchema = z.enum([
1891
2002
  "skill",
@@ -2271,7 +2382,7 @@ const EditAssetContentInputSchema = z.object({
2271
2382
  edits: z.array(AssetContentEditSchema).min(1),
2272
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\"."),
2273
2384
  submittedBy: z.string().optional().default("agent"),
2274
- 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.")
2275
2386
  });
2276
2387
  /**
2277
2388
  * `GET /assets/{assetId}/content` result. oRPC contracts here are JSON in/out
@@ -2375,7 +2486,7 @@ const assetsContract = {
2375
2486
  path: "/assets/{assetId}/edit-content",
2376
2487
  tags: ["Assets", "Change Requests"],
2377
2488
  summary: "Edit an asset's file content via string-replace edits, as a ChangeRequest",
2378
- 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."
2379
2490
  }).input(EditAssetContentInputSchema).output(changeRequestSchema)
2380
2491
  };
2381
2492
  //#endregion
@@ -2731,7 +2842,7 @@ const recordGetInputSchema = z.union([z.object({ recordId: z.string().min(1).des
2731
2842
  const restoreRecordInputSchema = z.object({
2732
2843
  message: z.string().optional(),
2733
2844
  submittedBy: z.string().optional().default("local-editor"),
2734
- 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\"`.")
2735
2846
  });
2736
2847
  /**
2737
2848
  * Every record change request in one shape. These three used to be PUT, DELETE,
@@ -2924,7 +3035,7 @@ const recordContract = {
2924
3035
  path: "/records/{recordId}/change-requests",
2925
3036
  tags: ["Records", "Change Requests"],
2926
3037
  summary: "Create record change request",
2927
- 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."
2928
3039
  }).input(recordChangeRequestInputSchema).output(z.union([recordSchema.extend({ materialized: z.literal(true) }), changeRequestSchema.extend({ materialized: z.literal(false) })])),
2929
3040
  listChangeRequests: oc.route({
2930
3041
  method: "GET",
@@ -3381,7 +3492,7 @@ const formContract = {
3381
3492
  path: "/forms/{nodeId}/submit",
3382
3493
  tags: ["Forms"],
3383
3494
  summary: "Submit a filled-in form",
3384
- 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."
3385
3496
  }).input(SubmitFormInputSchema.extend({ nodeId: z.string() })).output(FormSubmitResultSchema)
3386
3497
  };
3387
3498
  //#endregion
@@ -3391,7 +3502,7 @@ const formContract = {
3391
3502
  *
3392
3503
  * The manual existed only over MCP: `instructions`, `resources/*` and the
3393
3504
  * `busabase_guide` tool. Anything driving the REST API — busabase-cli, a script,
3394
- * 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
3395
3506
  * field types, or the AirApp runtime contract, and was then judged on whether it
3396
3507
  * guessed the house rules. These routes publish the same documents, built from
3397
3508
  * the same source, so the two surfaces cannot drift.
@@ -4593,6 +4704,28 @@ const getNodeInputSchema = z.object({
4593
4704
  const NodeIconUploadUrlInputSchema = RequestUploadUrlInputSchema.extend({ nodeId: z.string() });
4594
4705
  const NodeIconConfirmInputSchema = ConfirmUploadInputSchema.extend({ nodeId: z.string() });
4595
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
4596
4729
  //#region ../../packages/busabase-contract/src/contract/busabase.ts
4597
4730
  const changeRequestBatchFailureSchema = z.object({
4598
4731
  changeRequestId: z.string(),
@@ -4712,6 +4845,13 @@ const busabaseContractRoutes = {
4712
4845
  summary: "List a node's ancestor ids",
4713
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."
4714
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),
4715
4855
  createChangeRequest: oc.route({
4716
4856
  method: "POST",
4717
4857
  path: "/nodes/change-requests",
@@ -4946,7 +5086,28 @@ const busabaseContractRoutes = {
4946
5086
  tags: ["Comments"],
4947
5087
  summary: "Create comment",
4948
5088
  successDescription: "Created comment attached to a Busabase subject."
4949
- }).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)
4950
5111
  },
4951
5112
  agent: { listTasks: oc.route({
4952
5113
  method: "GET",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "busa-sdk",
3
- "version": "0.40.0",
3
+ "version": "0.41.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",