busabase-sdk 0.30.1 → 0.40.1

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-DJmL8Jl_.js";
1
+ import { t as BusabaseClient } from "./client-DbETz_5k.js";
2
2
  //#region src/airapp.d.ts
3
3
  type NodeChangeRequestInput = Parameters<BusabaseClient["nodes"]["createChangeRequest"]>[0];
4
4
  type NodeOperationInput = NodeChangeRequestInput["operations"][number];
@@ -319,6 +319,10 @@ declare const NodeIconSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
319
319
  type NodeIcon = z.infer<typeof NodeIconSchema>;
320
320
  //#endregion
321
321
  //#region ../../packages/busabase-contract/src/contract/schemas.d.ts
322
+ /** @see nodeSettingsSchema — declared here so `NodeOutput` can reference it. */
323
+ type NodeSettings = {
324
+ airappEngine?: "browser" | "local" | "remote" | null;
325
+ };
322
326
  interface NodeOutput {
323
327
  id: string;
324
328
  parentId: string | null;
@@ -338,6 +342,15 @@ interface NodeOutput {
338
342
  metadata: Record<string, unknown> & {
339
343
  version?: string;
340
344
  };
345
+ /**
346
+ * System settings the product DOES read and act on — the opposite of
347
+ * `metadata` above, and separate for that reason.
348
+ *
349
+ * Written only by `PATCH /nodes/{nodeId}/settings`, whose input is a closed
350
+ * schema; the generic metadata endpoint cannot address it. See
351
+ * `nodeSettingsSchema`.
352
+ */
353
+ settings?: NodeSettings;
341
354
  /**
342
355
  * This node's OWN declared visibility, or null when it simply inherits from
343
356
  * its ancestors. Access control, so it is a real column rather than a
@@ -1628,6 +1641,113 @@ declare const cloudContract: {
1628
1641
  nodeId: z.ZodString;
1629
1642
  metadata: z.ZodRecord<z.ZodString, z.ZodUnknown>;
1630
1643
  }, z.core.$strip>, z.ZodType<NodeOutput, unknown, z.core.$ZodTypeInternals<NodeOutput, unknown>>, import("@orpc/contract").MergedErrorMap<Record<never, never>, Record<never, never>>, Record<never, never>>;
1644
+ updateSettings: import("@orpc/contract").ContractProcedure<z.ZodObject<{
1645
+ nodeId: z.ZodString;
1646
+ settings: z.ZodObject<{
1647
+ airappEngine: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
1648
+ browser: "browser";
1649
+ local: "local";
1650
+ remote: "remote";
1651
+ }>>>;
1652
+ }, z.core.$strict>;
1653
+ }, z.core.$strip>, z.ZodType<NodeOutput, unknown, z.core.$ZodTypeInternals<NodeOutput, unknown>>, import("@orpc/contract").MergedErrorMap<Record<never, never>, Record<never, never>>, Record<never, never>>;
1654
+ getAgentPrompts: import("@orpc/contract").ContractProcedure<z.ZodObject<{
1655
+ nodeId: z.ZodString;
1656
+ }, z.core.$strip>, z.ZodObject<{
1657
+ nodeId: z.ZodString;
1658
+ agentPrompts: z.ZodNullable<z.ZodArray<z.ZodObject<{
1659
+ key: z.ZodString;
1660
+ intent: z.ZodOptional<z.ZodEnum<{
1661
+ change: "change";
1662
+ "read-only": "read-only";
1663
+ }>>;
1664
+ label: z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodEnum<{
1665
+ de: "de";
1666
+ en: "en";
1667
+ es: "es";
1668
+ fr: "fr";
1669
+ ja: "ja";
1670
+ ko: "ko";
1671
+ pt: "pt";
1672
+ "zh-CN": "zh-CN";
1673
+ "zh-TW": "zh-TW";
1674
+ }> & z.core.$partial, z.ZodString>]>;
1675
+ body: z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodEnum<{
1676
+ de: "de";
1677
+ en: "en";
1678
+ es: "es";
1679
+ fr: "fr";
1680
+ ja: "ja";
1681
+ ko: "ko";
1682
+ pt: "pt";
1683
+ "zh-CN": "zh-CN";
1684
+ "zh-TW": "zh-TW";
1685
+ }> & z.core.$partial, z.ZodString>]>;
1686
+ }, z.core.$strip>>>;
1687
+ }, z.core.$strip>, import("@orpc/contract").MergedErrorMap<Record<never, never>, Record<never, never>>, Record<never, never>>;
1688
+ updateAgentPrompts: import("@orpc/contract").ContractProcedure<z.ZodObject<{
1689
+ nodeId: z.ZodString;
1690
+ agentPrompts: z.ZodNullable<z.ZodArray<z.ZodObject<{
1691
+ key: z.ZodString;
1692
+ intent: z.ZodOptional<z.ZodEnum<{
1693
+ change: "change";
1694
+ "read-only": "read-only";
1695
+ }>>;
1696
+ label: z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodEnum<{
1697
+ de: "de";
1698
+ en: "en";
1699
+ es: "es";
1700
+ fr: "fr";
1701
+ ja: "ja";
1702
+ ko: "ko";
1703
+ pt: "pt";
1704
+ "zh-CN": "zh-CN";
1705
+ "zh-TW": "zh-TW";
1706
+ }> & z.core.$partial, z.ZodString>]>;
1707
+ body: z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodEnum<{
1708
+ de: "de";
1709
+ en: "en";
1710
+ es: "es";
1711
+ fr: "fr";
1712
+ ja: "ja";
1713
+ ko: "ko";
1714
+ pt: "pt";
1715
+ "zh-CN": "zh-CN";
1716
+ "zh-TW": "zh-TW";
1717
+ }> & z.core.$partial, z.ZodString>]>;
1718
+ }, z.core.$strip>>>;
1719
+ }, z.core.$strip>, z.ZodObject<{
1720
+ nodeId: z.ZodString;
1721
+ agentPrompts: z.ZodNullable<z.ZodArray<z.ZodObject<{
1722
+ key: z.ZodString;
1723
+ intent: z.ZodOptional<z.ZodEnum<{
1724
+ change: "change";
1725
+ "read-only": "read-only";
1726
+ }>>;
1727
+ label: z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodEnum<{
1728
+ de: "de";
1729
+ en: "en";
1730
+ es: "es";
1731
+ fr: "fr";
1732
+ ja: "ja";
1733
+ ko: "ko";
1734
+ pt: "pt";
1735
+ "zh-CN": "zh-CN";
1736
+ "zh-TW": "zh-TW";
1737
+ }> & z.core.$partial, z.ZodString>]>;
1738
+ body: z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodEnum<{
1739
+ de: "de";
1740
+ en: "en";
1741
+ es: "es";
1742
+ fr: "fr";
1743
+ ja: "ja";
1744
+ ko: "ko";
1745
+ pt: "pt";
1746
+ "zh-CN": "zh-CN";
1747
+ "zh-TW": "zh-TW";
1748
+ }> & z.core.$partial, z.ZodString>]>;
1749
+ }, z.core.$strip>>>;
1750
+ }, z.core.$strip>, import("@orpc/contract").MergedErrorMap<Record<never, never>, Record<never, never>>, Record<never, never>>;
1631
1751
  updateContent: import("@orpc/contract").ContractProcedure<z.ZodObject<{
1632
1752
  nodeId: z.ZodString;
1633
1753
  content: z.ZodDiscriminatedUnion<[z.ZodObject<{
@@ -2729,8 +2849,10 @@ declare const cloudContract: {
2729
2849
  "drive.created": "drive.created";
2730
2850
  "field.created": "field.created";
2731
2851
  "file.created": "file.created";
2852
+ "node.agent_prompts_updated": "node.agent_prompts_updated";
2732
2853
  "node.metadata_updated": "node.metadata_updated";
2733
2854
  "node.purged": "node.purged";
2855
+ "node.settings_updated": "node.settings_updated";
2734
2856
  "record.viewed": "record.viewed";
2735
2857
  "skill.created": "skill.created";
2736
2858
  }>;
@@ -2784,8 +2906,10 @@ declare const cloudContract: {
2784
2906
  "drive.created": "drive.created";
2785
2907
  "field.created": "field.created";
2786
2908
  "file.created": "file.created";
2909
+ "node.agent_prompts_updated": "node.agent_prompts_updated";
2787
2910
  "node.metadata_updated": "node.metadata_updated";
2788
2911
  "node.purged": "node.purged";
2912
+ "node.settings_updated": "node.settings_updated";
2789
2913
  "record.viewed": "record.viewed";
2790
2914
  "skill.created": "skill.created";
2791
2915
  }>;
@@ -2815,8 +2939,10 @@ declare const cloudContract: {
2815
2939
  "drive.created": "drive.created";
2816
2940
  "field.created": "field.created";
2817
2941
  "file.created": "file.created";
2942
+ "node.agent_prompts_updated": "node.agent_prompts_updated";
2818
2943
  "node.metadata_updated": "node.metadata_updated";
2819
2944
  "node.purged": "node.purged";
2945
+ "node.settings_updated": "node.settings_updated";
2820
2946
  "record.viewed": "record.viewed";
2821
2947
  "skill.created": "skill.created";
2822
2948
  }>;
@@ -3949,8 +4075,10 @@ declare const cloudContract: {
3949
4075
  "drive.created": "drive.created";
3950
4076
  "field.created": "field.created";
3951
4077
  "file.created": "file.created";
4078
+ "node.agent_prompts_updated": "node.agent_prompts_updated";
3952
4079
  "node.metadata_updated": "node.metadata_updated";
3953
4080
  "node.purged": "node.purged";
4081
+ "node.settings_updated": "node.settings_updated";
3954
4082
  "record.viewed": "record.viewed";
3955
4083
  "skill.created": "skill.created";
3956
4084
  }>;
@@ -5282,8 +5410,10 @@ declare const cloudContract: {
5282
5410
  "drive.created": "drive.created";
5283
5411
  "field.created": "field.created";
5284
5412
  "file.created": "file.created";
5413
+ "node.agent_prompts_updated": "node.agent_prompts_updated";
5285
5414
  "node.metadata_updated": "node.metadata_updated";
5286
5415
  "node.purged": "node.purged";
5416
+ "node.settings_updated": "node.settings_updated";
5287
5417
  "record.viewed": "record.viewed";
5288
5418
  "skill.created": "skill.created";
5289
5419
  }>;
@@ -6613,8 +6743,10 @@ declare const cloudContract: {
6613
6743
  "drive.created": "drive.created";
6614
6744
  "field.created": "field.created";
6615
6745
  "file.created": "file.created";
6746
+ "node.agent_prompts_updated": "node.agent_prompts_updated";
6616
6747
  "node.metadata_updated": "node.metadata_updated";
6617
6748
  "node.purged": "node.purged";
6749
+ "node.settings_updated": "node.settings_updated";
6618
6750
  "record.viewed": "record.viewed";
6619
6751
  "skill.created": "skill.created";
6620
6752
  }>;
@@ -6882,7 +7014,25 @@ declare const cloudContract: {
6882
7014
  role: z.ZodOptional<z.ZodNullable<z.ZodString>>;
6883
7015
  }, z.core.$strip>>>>;
6884
7016
  body: z.ZodString;
6885
- mentionsAi: z.ZodBoolean;
7017
+ mentions: z.ZodDefault<z.ZodArray<z.ZodObject<{
7018
+ id: z.ZodString;
7019
+ type: z.ZodEnum<{
7020
+ agent: "agent";
7021
+ member: "member";
7022
+ }>;
7023
+ targetId: z.ZodString;
7024
+ label: z.ZodString;
7025
+ start: z.ZodNumber;
7026
+ end: z.ZodNumber;
7027
+ dispatchStatus: z.ZodEnum<{
7028
+ failed: "failed";
7029
+ linked: "linked";
7030
+ not_applicable: "not_applicable";
7031
+ queued: "queued";
7032
+ }>;
7033
+ sessionId: z.ZodNullable<z.ZodString>;
7034
+ error: z.ZodNullable<z.ZodString>;
7035
+ }, z.core.$strip>>>;
6886
7036
  createdAt: z.ZodString;
6887
7037
  updatedAt: z.ZodString;
6888
7038
  }, z.core.$strip>>, import("@orpc/contract").MergedErrorMap<Record<never, never>, Record<never, never>>, Record<never, never>>;
@@ -6896,7 +7046,15 @@ declare const cloudContract: {
6896
7046
  subjectId: z.ZodString;
6897
7047
  authorId: z.ZodDefault<z.ZodOptional<z.ZodString>>;
6898
7048
  body: z.ZodString;
6899
- mentionsAi: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
7049
+ mentions: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodObject<{
7050
+ type: z.ZodEnum<{
7051
+ agent: "agent";
7052
+ member: "member";
7053
+ }>;
7054
+ id: z.ZodString;
7055
+ start: z.ZodNumber;
7056
+ end: z.ZodNumber;
7057
+ }, z.core.$strip>>>>;
6900
7058
  }, z.core.$strip>, z.ZodObject<{
6901
7059
  id: z.ZodString;
6902
7060
  subjectType: z.ZodEnum<{
@@ -6919,7 +7077,25 @@ declare const cloudContract: {
6919
7077
  role: z.ZodOptional<z.ZodNullable<z.ZodString>>;
6920
7078
  }, z.core.$strip>>>>;
6921
7079
  body: z.ZodString;
6922
- mentionsAi: z.ZodBoolean;
7080
+ mentions: z.ZodDefault<z.ZodArray<z.ZodObject<{
7081
+ id: z.ZodString;
7082
+ type: z.ZodEnum<{
7083
+ agent: "agent";
7084
+ member: "member";
7085
+ }>;
7086
+ targetId: z.ZodString;
7087
+ label: z.ZodString;
7088
+ start: z.ZodNumber;
7089
+ end: z.ZodNumber;
7090
+ dispatchStatus: z.ZodEnum<{
7091
+ failed: "failed";
7092
+ linked: "linked";
7093
+ not_applicable: "not_applicable";
7094
+ queued: "queued";
7095
+ }>;
7096
+ sessionId: z.ZodNullable<z.ZodString>;
7097
+ error: z.ZodNullable<z.ZodString>;
7098
+ }, z.core.$strip>>>;
6923
7099
  createdAt: z.ZodString;
6924
7100
  updatedAt: z.ZodString;
6925
7101
  }, z.core.$strip>, import("@orpc/contract").MergedErrorMap<Record<never, never>, Record<never, never>>, Record<never, never>>;
@@ -7383,7 +7559,25 @@ declare const cloudContract: {
7383
7559
  role: z.ZodOptional<z.ZodNullable<z.ZodString>>;
7384
7560
  }, z.core.$strip>>>>;
7385
7561
  body: z.ZodString;
7386
- mentionsAi: z.ZodBoolean;
7562
+ mentions: z.ZodDefault<z.ZodArray<z.ZodObject<{
7563
+ id: z.ZodString;
7564
+ type: z.ZodEnum<{
7565
+ agent: "agent";
7566
+ member: "member";
7567
+ }>;
7568
+ targetId: z.ZodString;
7569
+ label: z.ZodString;
7570
+ start: z.ZodNumber;
7571
+ end: z.ZodNumber;
7572
+ dispatchStatus: z.ZodEnum<{
7573
+ failed: "failed";
7574
+ linked: "linked";
7575
+ not_applicable: "not_applicable";
7576
+ queued: "queued";
7577
+ }>;
7578
+ sessionId: z.ZodNullable<z.ZodString>;
7579
+ error: z.ZodNullable<z.ZodString>;
7580
+ }, z.core.$strip>>>;
7387
7581
  createdAt: z.ZodString;
7388
7582
  updatedAt: z.ZodString;
7389
7583
  }, z.core.$strip>>;
@@ -7391,7 +7585,7 @@ declare const cloudContract: {
7391
7585
  };
7392
7586
  live: {
7393
7587
  subscribe: import("@orpc/contract").ContractProcedure<import("@orpc/contract").Schema<unknown, unknown>, import("@orpc/contract").Schema<AsyncIteratorObject<{
7394
- kind: "change_request.created" | "change_request.deleted" | "change_request.merged" | "change_request.pending_review" | "change_request.reviewed" | "change_request.updated" | "node.metadata_updated";
7588
+ kind: "change_request.created" | "change_request.deleted" | "change_request.merged" | "change_request.pending_review" | "change_request.reviewed" | "change_request.updated" | "node.metadata_updated" | "node.settings_updated";
7395
7589
  spaceId: string;
7396
7590
  actorId: string;
7397
7591
  changeRequestId: string | null;
@@ -7401,7 +7595,7 @@ declare const cloudContract: {
7401
7595
  viewIds: string[];
7402
7596
  operationCount: number;
7403
7597
  }, unknown, void>, AsyncIteratorClass<{
7404
- kind: "change_request.created" | "change_request.deleted" | "change_request.merged" | "change_request.pending_review" | "change_request.reviewed" | "change_request.updated" | "node.metadata_updated";
7598
+ kind: "change_request.created" | "change_request.deleted" | "change_request.merged" | "change_request.pending_review" | "change_request.reviewed" | "change_request.updated" | "node.metadata_updated" | "node.settings_updated";
7405
7599
  spaceId: string;
7406
7600
  actorId: string;
7407
7601
  changeRequestId: string | null;
@@ -12444,10 +12638,10 @@ declare const cloudContract: {
12444
12638
  nodeId: z.ZodString;
12445
12639
  files: z.ZodRecord<z.ZodString, z.ZodString>;
12446
12640
  binaryFiles: z.ZodDefault<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>>;
12447
- engine: z.ZodDefault<z.ZodEnum<{
12641
+ engine: z.ZodEnum<{
12448
12642
  local: "local";
12449
12643
  remote: "remote";
12450
- }>>;
12644
+ }>;
12451
12645
  }, z.core.$strip>, import("@orpc/contract").Schema<AsyncIteratorObject<{
12452
12646
  type: "log";
12453
12647
  line: string;
@@ -15156,8 +15350,17 @@ declare const cloudContract: {
15156
15350
  textContentHash: z.ZodNullable<z.ZodString>;
15157
15351
  byteCount: z.ZodNumber;
15158
15352
  }, z.core.$strip>, import("@orpc/contract").MergedErrorMap<Record<never, never>, Record<never, never>>, Record<never, never>>;
15353
+ exportDocBodies: import("@orpc/contract").ContractProcedure<z.ZodObject<{
15354
+ nodeIds: z.ZodArray<z.ZodString>;
15355
+ }, z.core.$strip>, z.ZodObject<{
15356
+ bodies: z.ZodArray<z.ZodObject<{
15357
+ nodeId: z.ZodString;
15358
+ markdown: z.ZodString;
15359
+ }, z.core.$strip>>;
15360
+ }, z.core.$strip>, import("@orpc/contract").MergedErrorMap<Record<never, never>, Record<never, never>>, Record<never, never>>;
15159
15361
  importBegin: import("@orpc/contract").ContractProcedure<z.ZodObject<{
15160
15362
  sourceSpaceId: z.ZodString;
15363
+ resume: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
15161
15364
  }, z.core.$strip>, z.ZodObject<{
15162
15365
  sessionId: z.ZodString;
15163
15366
  }, z.core.$strip>, import("@orpc/contract").MergedErrorMap<Record<never, never>, Record<never, never>>, Record<never, never>>;
@@ -19411,6 +19614,24 @@ declare const cloudContract: {
19411
19614
  listPage: import("@orpc/contract").ContractProcedure<z.ZodObject<{
19412
19615
  baseId: z.ZodString;
19413
19616
  viewId: z.ZodOptional<z.ZodString>;
19617
+ filters: z.ZodOptional<z.ZodArray<z.ZodObject<{
19618
+ fieldSlug: z.ZodString;
19619
+ fieldType: z.ZodOptional<z.ZodString>;
19620
+ operator: z.ZodEnum<{
19621
+ contains: "contains";
19622
+ equals: "equals";
19623
+ is_empty: "is_empty";
19624
+ is_false: "is_false";
19625
+ is_true: "is_true";
19626
+ not_empty: "not_empty";
19627
+ }>;
19628
+ value: z.ZodOptional<z.ZodUnknown>;
19629
+ }, z.core.$strip>>>;
19630
+ dateRange: z.ZodOptional<z.ZodObject<{
19631
+ fieldSlug: z.ZodString;
19632
+ gte: z.ZodString;
19633
+ lt: z.ZodString;
19634
+ }, z.core.$strip>>;
19414
19635
  page: z.ZodDefault<z.ZodOptional<z.ZodCoercedNumber<unknown>>>;
19415
19636
  pageSize: z.ZodDefault<z.ZodOptional<z.ZodCoercedNumber<unknown>>>;
19416
19637
  }, z.core.$strip>, z.ZodObject<{
@@ -19637,6 +19858,39 @@ declare const cloudContract: {
19637
19858
  }, z.core.$strip>>>, z.ZodObject<{
19638
19859
  total: z.ZodNumber;
19639
19860
  }, z.core.$strip>, import("@orpc/contract").MergedErrorMap<Record<never, never>, Record<never, never>>, Record<never, never>>;
19861
+ groupBy: import("@orpc/contract").ContractProcedure<z.ZodObject<{
19862
+ baseId: z.ZodString;
19863
+ fieldSlug: z.ZodString;
19864
+ viewId: z.ZodOptional<z.ZodString>;
19865
+ filters: z.ZodOptional<z.ZodArray<z.ZodObject<{
19866
+ fieldSlug: z.ZodString;
19867
+ fieldType: z.ZodOptional<z.ZodString>;
19868
+ operator: z.ZodEnum<{
19869
+ contains: "contains";
19870
+ equals: "equals";
19871
+ is_empty: "is_empty";
19872
+ is_false: "is_false";
19873
+ is_true: "is_true";
19874
+ not_empty: "not_empty";
19875
+ }>;
19876
+ value: z.ZodOptional<z.ZodUnknown>;
19877
+ }, z.core.$strip>>>;
19878
+ }, z.core.$strip>, z.ZodObject<{
19879
+ groups: z.ZodArray<z.ZodObject<{
19880
+ value: z.ZodNullable<z.ZodString>;
19881
+ count: z.ZodNumber;
19882
+ }, z.core.$strip>>;
19883
+ total: z.ZodNumber;
19884
+ }, z.core.$strip>, import("@orpc/contract").MergedErrorMap<Record<never, never>, import("@orpc/contract").MergedErrorMap<Record<never, never>, {
19885
+ BAD_REQUEST: {
19886
+ status: number;
19887
+ message: string;
19888
+ };
19889
+ NOT_FOUND: {
19890
+ status: number;
19891
+ message: string;
19892
+ };
19893
+ }>>, Record<never, never>>;
19640
19894
  get: import("@orpc/contract").ContractProcedure<z.ZodUnion<readonly [z.ZodObject<{
19641
19895
  recordId: z.ZodString;
19642
19896
  }, z.core.$strict>, z.ZodObject<{
@@ -23731,8 +23985,10 @@ declare const activityItemSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
23731
23985
  "drive.created": "drive.created";
23732
23986
  "field.created": "field.created";
23733
23987
  "file.created": "file.created";
23988
+ "node.agent_prompts_updated": "node.agent_prompts_updated";
23734
23989
  "node.metadata_updated": "node.metadata_updated";
23735
23990
  "node.purged": "node.purged";
23991
+ "node.settings_updated": "node.settings_updated";
23736
23992
  "record.viewed": "record.viewed";
23737
23993
  "skill.created": "skill.created";
23738
23994
  }>;
@@ -24686,7 +24942,7 @@ type BusabaseSourceChannel = "web_ui" | "browser" | "openapi" | "sdk" | "cli" |
24686
24942
  type ReviewVerdict = "approved" | "rejected";
24687
24943
  type SearchResultKind = "record" | "change_request" | "base" | "file" | "node";
24688
24944
  type CommentSubjectType = "record" | "change_request" | "operation" | "commit";
24689
- type AuditAction = "record.viewed" | "change_request.created" | "change_request.updated" | "change_request.deleted" | "change_request.reviewed" | "change_request.merged" | "base.created" | "field.created" | "doc.created" | "doc.updated" | "file.created" | "skill.created" | "drive.created" | "airapp.created" | "asset.deleted" | "asset.metadata_updated" | "asset.text_written" | "asset.text_marked_none" | "node.metadata_updated" | "node.purged";
24945
+ type AuditAction = "record.viewed" | "change_request.created" | "change_request.updated" | "change_request.deleted" | "change_request.reviewed" | "change_request.merged" | "base.created" | "field.created" | "doc.created" | "doc.updated" | "file.created" | "skill.created" | "drive.created" | "airapp.created" | "asset.deleted" | "asset.metadata_updated" | "asset.text_written" | "asset.text_marked_none" | "node.metadata_updated" | "node.settings_updated" | "node.agent_prompts_updated" | "node.purged";
24690
24946
  interface UserRefVO {
24691
24947
  id: string;
24692
24948
  name: string | null;
@@ -24731,6 +24987,19 @@ interface NodeVO {
24731
24987
  metadata: Record<string, unknown> & {
24732
24988
  version?: string;
24733
24989
  };
24990
+ /**
24991
+ * System settings the product DOES read and act on — the opposite of
24992
+ * `metadata` above, which is why they are separate fields with separate
24993
+ * endpoints. Written only by `PATCH /nodes/{nodeId}/settings`, whose input is
24994
+ * a closed schema; the generic metadata endpoint cannot address it.
24995
+ *
24996
+ * Absent (or an absent key) means "unset". For an AirApp's engine that means
24997
+ * "follow the app" — `airapp.json` decides — which is why absence has to stay
24998
+ * distinguishable from any particular value.
24999
+ */
25000
+ settings?: {
25001
+ airappEngine?: "browser" | "local" | "remote" | null;
25002
+ };
24734
25003
  /**
24735
25004
  * This node's OWN declared visibility, or null when it inherits from its
24736
25005
  * ancestors. A real column rather than a metadata key, because it is the node
@@ -24867,6 +25136,34 @@ interface ReviewVO {
24867
25136
  visibleOperationHeads: Record<string, string>;
24868
25137
  createdAt: string;
24869
25138
  }
25139
+ type CommentMentionTargetType = "member" | "agent";
25140
+ /**
25141
+ * Dispatch state of one mention BEFORE a session exists. Once `linked`, the
25142
+ * agent session owns running/waiting/done/failed — it is never mirrored here.
25143
+ */
25144
+ type CommentMentionDispatchStatus = "not_applicable" | "queued" | "linked" | "failed";
25145
+ /**
25146
+ * One mention as the composer submits it. `start`/`end` are UTF-16 code unit
25147
+ * offsets into the comment body (see the contract schema for why).
25148
+ */
25149
+ interface CommentMentionInputDTO {
25150
+ type: CommentMentionTargetType;
25151
+ id: string;
25152
+ start: number;
25153
+ end: number;
25154
+ }
25155
+ interface CommentMentionVO {
25156
+ id: string;
25157
+ type: CommentMentionTargetType;
25158
+ targetId: string;
25159
+ /** Server-resolved display name; falls back to the raw target id. */
25160
+ label: string;
25161
+ start: number;
25162
+ end: number;
25163
+ dispatchStatus: CommentMentionDispatchStatus;
25164
+ sessionId: string | null;
25165
+ error: string | null;
25166
+ }
24870
25167
  interface CommentVO {
24871
25168
  id: string;
24872
25169
  subjectType: CommentSubjectType;
@@ -24878,7 +25175,7 @@ interface CommentVO {
24878
25175
  authorId: string;
24879
25176
  author?: UserRefVO | null;
24880
25177
  body: string;
24881
- mentionsAi: boolean;
25178
+ mentions: CommentMentionVO[];
24882
25179
  createdAt: string;
24883
25180
  updatedAt: string;
24884
25181
  }
@@ -25026,4 +25323,4 @@ declare function resolveConfig(config?: BusabaseConfig): ResolvedConfig;
25026
25323
  */
25027
25324
  declare function createBusabaseClient(config?: BusabaseConfig): BusabaseClient;
25028
25325
  //#endregion
25029
- 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 };
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 };
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-DJmL8Jl_.js";
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";
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 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
@@ -354,7 +354,7 @@ const LocaleSchema = z.enum({
354
354
  * - ZH: isIString 接受 JSON 字符串并尝试解析为按语言分布的对象;纯字符串将返回 false。
355
355
  */
356
356
  const iStringRecordSchema = z.partialRecord(LocaleSchema, z.string());
357
- z.union([z.string(), iStringRecordSchema]).describe("i18n string");
357
+ const iStringSchema = z.union([z.string(), iStringRecordSchema]).describe("i18n string");
358
358
  //#endregion
359
359
  //#region ../../packages/busabase-contract/src/contract/auto-merge.ts
360
360
  /**
@@ -1082,6 +1082,81 @@ const NodeIconSchema = z.discriminatedUnion("type", [z.object({
1082
1082
  }).optional()
1083
1083
  })]);
1084
1084
  //#endregion
1085
+ //#region ../../packages/busabase-contract/src/contract/node-agent-prompt-schemas.ts
1086
+ /**
1087
+ * 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:
1090
+ *
1091
+ * - Write: `busabase-cli nodes set-agent-prompts` validates a file against this
1092
+ * schema client-side, before calling `nodes.updateMetadata` — a malformed file
1093
+ * never reaches the network.
1094
+ * - Read: `buildNodeAgentPrompts` (`packages/busabase-core/.../node-agent-prompts.ts`)
1095
+ * `.safeParse`s whatever is stored in `metadata.agentPrompts` and falls back to
1096
+ * the node type's default scenarios on failure, so a bad write (or a manual
1097
+ * jsonb edit) can never crash the Agent Prompts dialog.
1098
+ *
1099
+ * One schema, one place to edit the limits — do not duplicate this validation on
1100
+ * either side.
1101
+ */
1102
+ /** Recommended limits from the spec (§7.3) — kept as named constants so a limit
1103
+ * change has exactly one place to edit, and so error messages can cite them. */
1104
+ const CUSTOM_AGENT_PROMPT_LIMITS = {
1105
+ /** Max custom prompts per node. */
1106
+ maxPrompts: 50,
1107
+ /** Max characters per localized `label` value. */
1108
+ maxLabelChars: 80,
1109
+ /** Max bytes (UTF-8) per localized `body` value. */
1110
+ maxBodyBytes: 8192
1111
+ };
1112
+ /** Same intent vocabulary `PromptDef.intent` uses — `change` is the router-side
1113
+ * default when omitted, matching the existing curated-prompt behavior. */
1114
+ const customPromptIntentSchema = z.enum(["read-only", "change"]);
1115
+ const iStringLocaleValues = (value) => typeof value === "string" ? [value] : Object.values(value);
1116
+ /** UTF-8 byte length — `body` includes CJK/JA text, whose per-character byte
1117
+ * cost is not 1, so a character-count limit alone would under-enforce §7.3's
1118
+ * "8 KiB per localized body" budget. */
1119
+ const utf8ByteLength = (value) => new TextEncoder().encode(value).length;
1120
+ const customPromptLabelSchema = iStringSchema.refine((value) => iStringLocaleValues(value).every((v) => v.length <= CUSTOM_AGENT_PROMPT_LIMITS.maxLabelChars), { message: `label must be at most ${CUSTOM_AGENT_PROMPT_LIMITS.maxLabelChars} characters per locale` });
1121
+ const customPromptBodySchema = iStringSchema.refine((value) => iStringLocaleValues(value).every((v) => utf8ByteLength(v) <= CUSTOM_AGENT_PROMPT_LIMITS.maxBodyBytes), { message: `body must be at most ${CUSTOM_AGENT_PROMPT_LIMITS.maxBodyBytes} bytes (UTF-8) per locale` });
1122
+ /**
1123
+ * One custom scenario prompt. `body`'s `{target}` placeholder is substituted at
1124
+ * render time with the same target string `PromptDef.body(target)` receives
1125
+ * today (see `node-agent-prompts.ts`) — this schema does not interpolate it.
1126
+ */
1127
+ const customPromptDefSchema = z.object({
1128
+ /** Stable id, unique within this node's custom list. */
1129
+ key: z.string().trim().min(1, { message: "key must not be empty" }),
1130
+ /** Defaults to `change` (same default the curated prompts use) so a prompt
1131
+ * cannot silently bypass the approval-first policy by omission. */
1132
+ intent: customPromptIntentSchema.optional(),
1133
+ /** Short title shown in the dialog's left list. */
1134
+ label: customPromptLabelSchema,
1135
+ /** Template text; "{target}" is substituted with the rendered target line. */
1136
+ body: customPromptBodySchema
1137
+ });
1138
+ /**
1139
+ * The full `metadata.agentPrompts` array. `.max` bounds the list; the
1140
+ * `superRefine` catches duplicate keys with an issue path pointing at the
1141
+ * offending entry, so a CLI/server validation error names which entry and
1142
+ * which key collided instead of a bare "keys must be unique".
1143
+ */
1144
+ const customAgentPromptsSchema = z.array(customPromptDefSchema).max(CUSTOM_AGENT_PROMPT_LIMITS.maxPrompts, { message: `at most ${CUSTOM_AGENT_PROMPT_LIMITS.maxPrompts} custom prompts per node` }).superRefine((prompts, ctx) => {
1145
+ const firstIndexByKey = /* @__PURE__ */ new Map();
1146
+ prompts.forEach((prompt, index) => {
1147
+ const firstIndex = firstIndexByKey.get(prompt.key);
1148
+ if (firstIndex === void 0) {
1149
+ firstIndexByKey.set(prompt.key, index);
1150
+ return;
1151
+ }
1152
+ ctx.addIssue({
1153
+ code: "custom",
1154
+ path: [index, "key"],
1155
+ message: `duplicate key "${prompt.key}" — already used at entry ${firstIndex + 1}`
1156
+ });
1157
+ });
1158
+ });
1159
+ //#endregion
1085
1160
  //#region ../../packages/busabase-contract/src/contract/schemas.ts
1086
1161
  const nodeSchema = z.lazy(() => z.object({
1087
1162
  id: z.string(),
@@ -1091,6 +1166,7 @@ const nodeSchema = z.lazy(() => z.object({
1091
1166
  name: z.string(),
1092
1167
  description: z.string(),
1093
1168
  metadata: z.object({ version: z.string().optional() }).catchall(z.unknown()).default({}),
1169
+ settings: nodeSettingsSchema.default({}),
1094
1170
  explicitVisibility: z.enum([
1095
1171
  "private",
1096
1172
  "workspace",
@@ -1174,6 +1250,65 @@ const updateNodeMetadataInputSchema = z.object({
1174
1250
  nodeId: z.string(),
1175
1251
  metadata: z.record(z.string(), z.unknown())
1176
1252
  });
1253
+ /**
1254
+ * System settings Busabase itself acts on, per node.
1255
+ *
1256
+ * A CLOSED object, unlike `metadata`'s `z.record(z.string(), z.unknown())`.
1257
+ * That difference is the point: `metadata` is the open bag callers put their
1258
+ * own keys in, and its endpoint merges whatever it is handed. Anything the
1259
+ * product *reads and acts on* must not live there — `metadata.visibility` had
1260
+ * to be pulled out into its own column precisely because the generic endpoint
1261
+ * handed a `write`-level actor a door into an ACL input.
1262
+ *
1263
+ * Adding a key here is a deliberate change to this schema, which is what keeps
1264
+ * `PATCH /nodes/{nodeId}/settings` from becoming a second free-form bag.
1265
+ *
1266
+ * `strictObject`, not `object`: zod's default is to STRIP an unknown key, which
1267
+ * would hand a client that misspelled `airappEngine` a 200 and no effect —
1268
+ * exactly the silent failure a closed schema exists to prevent. Verified
1269
+ * against a running server, where the permissive version returned 200.
1270
+ */
1271
+ const nodeSettingsSchema = z.strictObject({
1272
+ /**
1273
+ * Which engine an AirApp runs on, when a human has chosen.
1274
+ *
1275
+ * `undefined` means "follow the app" — `airapp.json`'s `preferredEngine`
1276
+ * decides, or the default does. A value means somebody overrode it in the
1277
+ * node settings dialog, and it outranks the manifest from then on. So absence
1278
+ * must stay distinguishable from any particular value; `null` clears an
1279
+ * override and returns the node to following the app.
1280
+ */
1281
+ airappEngine: z.enum([
1282
+ "browser",
1283
+ "local",
1284
+ "remote"
1285
+ ]).nullish() });
1286
+ const updateNodeSettingsInputSchema = z.object({
1287
+ nodeId: z.string(),
1288
+ settings: nodeSettingsSchema
1289
+ });
1290
+ /**
1291
+ * This node's custom scenario prompts.
1292
+ *
1293
+ * A separate read from `nodes.get`/`nodes.list` on purpose: the list is capped
1294
+ * at 50 prompts x 8 KiB of body per locale, so carrying it on every node of
1295
+ * every sidebar load is exactly what its own column exists to avoid. The dialog
1296
+ * asks for it when it opens.
1297
+ *
1298
+ * `agentPrompts: null` means "this node has never set any" — distinct from `[]`,
1299
+ * which means "set, and deliberately empty". Both fall back to the node type's
1300
+ * default scenarios in the UI, but only the first is a node nobody has touched.
1301
+ */
1302
+ const getNodeAgentPromptsInputSchema = z.object({ nodeId: z.string() });
1303
+ const nodeAgentPromptsSchema = z.object({
1304
+ nodeId: z.string(),
1305
+ agentPrompts: customAgentPromptsSchema.nullable()
1306
+ });
1307
+ const updateNodeAgentPromptsInputSchema = z.object({
1308
+ nodeId: z.string(),
1309
+ /** Replaces the whole list — this is not a merge. Send `null` to clear. */
1310
+ agentPrompts: customAgentPromptsSchema.nullable()
1311
+ });
1177
1312
  const searchNodesByNameInputSchema = z.object({
1178
1313
  query: z.string().min(1),
1179
1314
  limit: z.coerce.number().int().min(1).max(50).optional().default(20)
@@ -1269,6 +1404,55 @@ const commentSubjectTypeSchema = z.enum([
1269
1404
  "operation",
1270
1405
  "commit"
1271
1406
  ]);
1407
+ /**
1408
+ * Who a mention points at. `member` tags a person; `agent` names a launchable
1409
+ * Agent target and is what actually starts a session.
1410
+ */
1411
+ const commentMentionTargetTypeSchema = z.enum(["member", "agent"]);
1412
+ /**
1413
+ * Dispatch lifecycle of ONE mention row, before a session exists.
1414
+ *
1415
+ * `not_applicable` is every member row (a person is not dispatched to).
1416
+ * Once `linked`, running/waiting/done/failed belongs to the agent session,
1417
+ * never to a second status column here.
1418
+ */
1419
+ const commentMentionDispatchStatusSchema = z.enum([
1420
+ "not_applicable",
1421
+ "queued",
1422
+ "linked",
1423
+ "failed"
1424
+ ]);
1425
+ /**
1426
+ * One mention as the composer submits it.
1427
+ *
1428
+ * `start`/`end` are **UTF-16 code unit** offsets into `body` — the same unit
1429
+ * `<textarea>` selection APIs and `String.prototype.slice` use, so nothing has
1430
+ * to convert at the UI boundary. A label containing an astral-plane character
1431
+ * (an emoji in a display name) therefore spans two units per visible glyph;
1432
+ * the server rejects a span that would split a surrogate pair.
1433
+ *
1434
+ * No `label` here on purpose: the client never supplies identity. The server
1435
+ * resolves the display name from the member/catalog it already trusts.
1436
+ */
1437
+ const commentMentionInputSchema = z.object({
1438
+ type: commentMentionTargetTypeSchema,
1439
+ /** Member/actor id, or launchable agent slug (`claude-acp`, `buda:<agentId>`). */
1440
+ id: z.string().min(1),
1441
+ start: z.number().int().min(0),
1442
+ end: z.number().int().min(0)
1443
+ });
1444
+ const commentMentionSchema = z.object({
1445
+ id: z.string(),
1446
+ type: commentMentionTargetTypeSchema,
1447
+ targetId: z.string(),
1448
+ /** Server-resolved display name. Falls back to the raw target id. */
1449
+ label: z.string(),
1450
+ start: z.number().int(),
1451
+ end: z.number().int(),
1452
+ dispatchStatus: commentMentionDispatchStatusSchema,
1453
+ sessionId: z.string().nullable(),
1454
+ error: z.string().nullable()
1455
+ });
1272
1456
  const commentSchema = z.object({
1273
1457
  id: z.string(),
1274
1458
  subjectType: commentSubjectTypeSchema,
@@ -1280,7 +1464,7 @@ const commentSchema = z.object({
1280
1464
  authorId: z.string(),
1281
1465
  author: userRefSchema.nullable().optional().default(null),
1282
1466
  body: z.string(),
1283
- mentionsAi: z.boolean(),
1467
+ mentions: z.array(commentMentionSchema).default([]),
1284
1468
  createdAt: z.string(),
1285
1469
  updatedAt: z.string()
1286
1470
  });
@@ -1369,7 +1553,8 @@ const liveEventSchema = z.object({
1369
1553
  "change_request.reviewed",
1370
1554
  "change_request.merged",
1371
1555
  "change_request.pending_review",
1372
- "node.metadata_updated"
1556
+ "node.metadata_updated",
1557
+ "node.settings_updated"
1373
1558
  ]),
1374
1559
  spaceId: z.string(),
1375
1560
  actorId: z.string(),
@@ -1400,6 +1585,8 @@ const auditActionSchema = z.enum([
1400
1585
  "asset.text_written",
1401
1586
  "asset.text_marked_none",
1402
1587
  "node.metadata_updated",
1588
+ "node.settings_updated",
1589
+ "node.agent_prompts_updated",
1403
1590
  "node.purged"
1404
1591
  ]);
1405
1592
  const auditEventSchema = z.object({
@@ -1515,7 +1702,12 @@ const commentSubjectInputSchema = z.object({
1515
1702
  const createCommentInputSchema = commentSubjectInputSchema.extend({
1516
1703
  authorId: z.string().optional().default("local-admin"),
1517
1704
  body: z.string().trim().min(1),
1518
- mentionsAi: z.boolean().optional().default(false)
1705
+ /**
1706
+ * Structured mentions, owned by the composer. Never inferred from the body by
1707
+ * regex: display names contain spaces and collide with ordinary prose, so
1708
+ * "ask codex about this" must not invoke Codex.
1709
+ */
1710
+ mentions: z.array(commentMentionInputSchema).optional().default([])
1519
1711
  });
1520
1712
  const listInputSchema = z.object({ limit: z.coerce.number().int().min(1).max(100).optional().default(50) }).optional().default({ limit: 50 });
1521
1713
  /**
@@ -1818,8 +2010,14 @@ const airAppRunLocalInputSchema = z.object({
1818
2010
  /** Where the server should run it. `"local"` spawns a bare process on the
1819
2011
  * Busabase host (previewable, data bridge via reverse proxy, NOT isolated);
1820
2012
  * `"remote"` runs the same lifecycle on a provisioned machine elsewhere.
1821
- * `"browser"` never reaches this endpoint — it runs entirely in the tab. */
1822
- engine: z.enum(["local", "remote"]).default("local")
2013
+ * `"browser"` never reaches this endpoint — it runs entirely in the tab.
2014
+ *
2015
+ * Required, deliberately. This used to default to `"local"`, so a call that
2016
+ * simply omitted the field asked the server to spawn a host process — the
2017
+ * most privileged of the two options, reached by saying nothing. Naming the
2018
+ * engine is now the caller's job, and the handler independently refuses one
2019
+ * this deployment does not offer. */
2020
+ engine: z.enum(["local", "remote"])
1823
2021
  });
1824
2022
  const airAppRuntimeEventSchema = z.discriminatedUnion("type", [
1825
2023
  z.object({
@@ -2410,6 +2608,41 @@ const listRecordsResponseSchema = z.object({
2410
2608
  const listRecordsPageInputSchema = z.object({
2411
2609
  baseId: z.string().min(1),
2412
2610
  viewId: z.string().min(1).optional(),
2611
+ /**
2612
+ * Extra conditions ANDed with the View's own filters — "this View, further
2613
+ * narrowed". The motivating case is one board column: the saved View's
2614
+ * filters plus `stackField equals <choice>`, paged independently of the
2615
+ * other columns.
2616
+ *
2617
+ * Unlike `records.list`'s `filters` (a SUPERSET push-down the client then
2618
+ * narrows), these are applied with the same authority as a saved View's:
2619
+ * every returned page is exactly what the client's own matcher would keep.
2620
+ * That distinction is the whole point — a *superset* page can be missing
2621
+ * records, and a board column that silently drops cards reads as data loss.
2622
+ */
2623
+ filters: z.array(listRecordsFilterSchema).optional(),
2624
+ /**
2625
+ * Scope the page to records whose `date`/`created_time`/`updated_time` field
2626
+ * falls in `[gte, lt)` — an absolute UTC instant range, not a `filters`
2627
+ * condition. It is deliberately NOT an operator on `listRecordsFilterSchema`:
2628
+ * that model mirrors the client's label-based view-filter matching (see
2629
+ * `recordMatchesViewFilter`), which for a date renders via
2630
+ * `toLocaleDateString()` — meaningless without knowing the viewer's
2631
+ * timezone, which the server never has. A UTC instant range has no such
2632
+ * ambiguity, so it is resolved once here, by the caller (who DOES know the
2633
+ * viewer's timezone), and applied as a real timestamp comparison.
2634
+ *
2635
+ * The motivating case is a Calendar month grid: the client computes the UTC
2636
+ * bounds of its own local 42-day grid and asks for only that slice, instead
2637
+ * of every record in the Base.
2638
+ */
2639
+ dateRange: z.object({
2640
+ fieldSlug: z.string().min(1),
2641
+ /** Inclusive lower bound, ISO 8601 UTC instant. */
2642
+ gte: z.string(),
2643
+ /** Exclusive upper bound, ISO 8601 UTC instant. */
2644
+ lt: z.string()
2645
+ }).optional(),
2413
2646
  page: z.coerce.number().int().min(1).optional().default(1),
2414
2647
  pageSize: z.coerce.number().int().min(1).max(100).optional().default(50)
2415
2648
  });
@@ -2454,6 +2687,42 @@ const countRecordsInputSchema = z.object({
2454
2687
  const countRecordsResponseSchema = z.object({
2455
2688
  /** Total active records in the space (optionally scoped to a base). */
2456
2689
  total: z.number().int().nonnegative() });
2690
+ const groupRecordsInputSchema = z.object({
2691
+ /** Group within exactly one Base — a field slug is only unambiguous there. */
2692
+ baseId: z.string().min(1),
2693
+ /**
2694
+ * The field to group by. Restricted to `select` and `checkbox`: their stored
2695
+ * value IS the grouping key (a choice id / a boolean), so a SQL GROUP BY
2696
+ * returns exactly the buckets a client would build. Text/number keys would
2697
+ * be truncated at the projection limit, and date keys would bucket by the
2698
+ * server's timezone rather than the viewer's — both would report a
2699
+ * confidently wrong split, so they're rejected instead of approximated.
2700
+ */
2701
+ fieldSlug: z.string().min(1),
2702
+ /** Group only the rows a saved View would display (its filters; sort ignored). */
2703
+ viewId: z.string().min(1).optional(),
2704
+ /** Ad-hoc filters, ANDed with the View's own when both are given. */
2705
+ filters: z.array(listRecordsFilterSchema).optional()
2706
+ });
2707
+ const groupRecordsResponseSchema = z.object({
2708
+ groups: z.array(z.object({
2709
+ /**
2710
+ * The raw stored key: a `select` choice id, or `"true"`/`"false"` for a
2711
+ * checkbox. For a select, `null` is the bucket of records with no value
2712
+ * (what a Kanban board shows as its "Uncategorized" column). A checkbox
2713
+ * never reports `null` — an unset checkbox counts as `"false"`, matching
2714
+ * how view filters already treat it (`is_false` covers null/undefined).
2715
+ *
2716
+ * Choice LABELS are deliberately not resolved here — the client already
2717
+ * holds the Base's field definitions and renders labels itself, and
2718
+ * returning ids keeps this response stable across a choice rename.
2719
+ */
2720
+ value: z.string().nullable(),
2721
+ count: z.number().int().nonnegative()
2722
+ })),
2723
+ /** Sum of every group's count — the same number `records.count` would return. */
2724
+ total: z.number().int().nonnegative()
2725
+ });
2457
2726
  const createChangeRequestInputSchema = z.object({
2458
2727
  fields: z.record(z.string(), z.unknown()).describe("Record field values keyed by field slug. The base's PRIMARY field (its first field) becomes the record's display name and the change request title everywhere — always give it a short, human-readable value, never an id or placeholder."),
2459
2728
  message: z.string().optional().default("Initial change request").describe("Explanation shown to the human reviewer. Write a conventional-commit style subject — imperative verb + what + why, e.g. \"Add Acme Corp — qualified lead from the June webinar\"."),
@@ -2653,7 +2922,7 @@ const recordContract = {
2653
2922
  path: "/records/page",
2654
2923
  tags: ["Records"],
2655
2924
  summary: "List a numbered record page",
2656
- successDescription: "A random-access page of active records. When viewId is supplied, the saved view is authoritatively filtered and sorted before total and page slicing are calculated."
2925
+ successDescription: "A random-access page of active records. When viewId is supplied, the saved view is authoritatively filtered and sorted before total and page slicing are calculated. `dateRange` additionally scopes to a `[gte, lt)` UTC instant window on a date/created_time/updated_time field."
2657
2926
  }).input(listRecordsPageInputSchema).output(listRecordsPageResponseSchema),
2658
2927
  count: oc.route({
2659
2928
  method: "GET",
@@ -2663,6 +2932,23 @@ const recordContract = {
2663
2932
  description: "A real SQL COUNT — always the exact total, never a partial or capped number, so it's safe to render as a canonical figure (e.g. a dashboard summary tile). Plain `baseId` scoping is always cheap. Adding `viewId` and/or `filters` is exact too — provably-exact conditions (e.g. text equals/contains, not_empty/is_empty, checkbox is_true/is_false) stay a cheap SQL COUNT; everything else falls back to evaluating every matching row server-side, which is exact but not free on a large Base. Both `viewId` and `filters` require `baseId`.",
2664
2933
  successDescription: "Total active records matching the scope: the whole space, one Base, a saved View, an ad-hoc filter set, or a combination."
2665
2934
  }).input(countRecordsInputSchema).output(countRecordsResponseSchema),
2935
+ groupBy: oc.route({
2936
+ method: "GET",
2937
+ path: "/records/group-by",
2938
+ tags: ["Records"],
2939
+ summary: "Count records per group",
2940
+ description: "One SQL GROUP BY returning every bucket's exact count — the split a board column header or a summary tile needs, without reading the records themselves. `fieldSlug` must name a `select` or `checkbox` field: their stored value IS the grouping key, so the buckets are exactly the ones a client would build. Grouping by a text, number or date field is rejected rather than approximated (text keys are truncated at the projection limit; date keys would bucket by the server's timezone, not the viewer's). `viewId` and `filters` narrow the set first, with the same exactness rules as `records.count`: provably-exact conditions stay a cheap SQL aggregate, anything else falls back to evaluating every matching row server-side — exact, but not free on a large Base. Groups come back keyed by raw choice id (or `\"true\"`/`\"false\"`), with `null` for records that have no value; labels are the client's to render.",
2941
+ successDescription: "Every group's exact count, plus the total across all groups. Groups with zero records are omitted — a Base's full choice list lives in its field definition, so the client already knows which buckets to render empty."
2942
+ }).errors({
2943
+ BAD_REQUEST: {
2944
+ status: 400,
2945
+ message: "Field is not groupable"
2946
+ },
2947
+ NOT_FOUND: {
2948
+ status: 404,
2949
+ message: "Base or field not found"
2950
+ }
2951
+ }).input(groupRecordsInputSchema).output(groupRecordsResponseSchema),
2666
2952
  get: oc.route({
2667
2953
  method: "GET",
2668
2954
  path: "/records/get",
@@ -2836,19 +3122,55 @@ const ExportAssetTextVOSchema = z.object({
2836
3122
  textContentHash: z.string().nullable(),
2837
3123
  byteCount: z.number().int().nonnegative()
2838
3124
  });
2839
- const ImportBeginInputSchema = z.object({
3125
+ const ExportDocBodiesInputSchema = z.object({ nodeIds: z.array(z.string()).min(1).max(25) });
3126
+ const ExportDocBodiesVOSchema = z.object({
2840
3127
  /**
2841
- * The space id the archive was ORIGINALLY exported from (`manifest.spaceId`
2842
- * in the `.bbdump`, already integrity-verified before this is called).
2843
- * `importTableRows`'s "nodes" handling needs this to recognize the
2844
- * archive's own root-node row deterministically (`rootNodeIdForSpace`)
2845
- * scanning each batch's rows for "the one with a null `parentId`" only
2846
- * works when that row happens to land in the SAME batch as its children,
2847
- * which cursor pagination (id-ordered, not tree-ordered) does not
2848
- * guarantee once a space has more nodes than one page. See the matching
2849
- * comment in `import-logic.ts`.
3128
+ * One entry per requested node that is a Doc in this space. A node id that
3129
+ * does not resolve is simply absent (not an error): the caller asked for a
3130
+ * batch, and one bad id must not cost it the other 24. A Doc that exists but
3131
+ * has no body object yet yields `markdown: ""`, matching what a read through
3132
+ * the Doc domain would return.
2850
3133
  */
2851
- sourceSpaceId: z.string() });
3134
+ bodies: z.array(z.object({
3135
+ nodeId: z.string(),
3136
+ markdown: z.string()
3137
+ })) });
3138
+ const ImportBeginInputSchema = z.object({
3139
+ /**
3140
+ * The space id the archive was ORIGINALLY exported from (`manifest.spaceId`
3141
+ * in the `.bbdump`, already integrity-verified before this is called).
3142
+ * `importTableRows`'s "nodes" handling needs this to recognize the
3143
+ * archive's own root-node row deterministically (`rootNodeIdForSpace`) —
3144
+ * scanning each batch's rows for "the one with a null `parentId`" only
3145
+ * works when that row happens to land in the SAME batch as its children,
3146
+ * which cursor pagination (id-ordered, not tree-ordered) does not
3147
+ * guarantee once a space has more nodes than one page. See the matching
3148
+ * comment in `import-logic.ts`.
3149
+ */
3150
+ sourceSpaceId: z.string(),
3151
+ /**
3152
+ * Continue a restore that was interrupted partway through, instead of
3153
+ * requiring an empty space.
3154
+ *
3155
+ * A restore that FAILS rolls itself back (`importAbort`), so the target is
3156
+ * left clean and a plain re-run works. What cannot roll itself back is a
3157
+ * restore whose process died — Ctrl-C, OOM, a dropped connection, the
3158
+ * machine rebooting. That leaves the space holding however many of the
3159
+ * archive's rows had landed, and every subsequent attempt is refused
3160
+ * ("requires an empty target space") with no way forward except wiping it.
3161
+ *
3162
+ * In this mode the empty-space guard is skipped and inserts become
3163
+ * `ON CONFLICT DO NOTHING`, so replaying the same archive re-lands only what
3164
+ * is missing. Blobs and doc bodies are content-addressed writes to object
3165
+ * storage and were already idempotent.
3166
+ *
3167
+ * DANGEROUS if pointed at the wrong space: rows that collide are silently
3168
+ * skipped rather than reported, so restoring archive A into a space holding
3169
+ * archive B's data would interleave the two instead of refusing. Only pass
3170
+ * it to continue the SAME archive into the SAME space.
3171
+ */
3172
+ resume: z.boolean().optional().default(false)
3173
+ });
2852
3174
  const ImportBeginVOSchema = z.object({ sessionId: z.string() });
2853
3175
  /**
2854
3176
  * `docBodies`, `attachmentBlobs` and `assetTextBlobs` are pseudo-tables: doc
@@ -2906,6 +3228,13 @@ const dumpContract = {
2906
3228
  summary: "Resolve the download URL for one asset's extracted-text object",
2907
3229
  successDescription: "A resolved download URL for the asset's DERIVED text blob (`asset-texts/blobs/sha256/…`) plus its `textStorageKey` and `textContentHash`, so a backup can archive the exact bytes and verify them. `downloadUrl` is null when the row owns no separate object (auto-registered text-kind rows point at their attachment's own key, already covered by the attachment blobs; `status: \"none\"` rows have no text at all)."
2908
3230
  }).input(ExportAssetTextInputSchema).output(ExportAssetTextVOSchema),
3231
+ exportDocBodies: oc.route({
3232
+ method: "POST",
3233
+ path: "/dump/export/doc-bodies",
3234
+ tags: ["Dump"],
3235
+ summary: "Read the raw markdown for a batch of Doc nodes",
3236
+ successDescription: "The raw body behind each requested Doc, read straight from object storage — archived Docs included, which the ordinary `nodes.get` deliberately refuses. Ids that do not resolve to a Doc in this space are omitted rather than failing the batch."
3237
+ }).input(ExportDocBodiesInputSchema).output(ExportDocBodiesVOSchema),
2909
3238
  importBegin: oc.route({
2910
3239
  method: "POST",
2911
3240
  path: "/dump/import/begin",
@@ -4458,6 +4787,27 @@ const busabaseContractRoutes = {
4458
4787
  summary: "Update node metadata",
4459
4788
  successDescription: "Shallow-merged the supplied top-level keys into the active node's existing metadata. Requires write access on the node. Node CONTENT (a Doc body, or a whiteboard/workflow/html document) does not go through here — use PUT /nodes/{nodeId}/content instead."
4460
4789
  }).input(updateNodeMetadataInputSchema).output(nodeSchema),
4790
+ updateSettings: oc.route({
4791
+ method: "PATCH",
4792
+ path: "/nodes/{nodeId}/settings",
4793
+ tags: ["Nodes"],
4794
+ summary: "Update node system settings",
4795
+ successDescription: "Replaced the node's system settings. Unlike metadata this is a closed set of keys Busabase itself acts on, so an unknown key is rejected rather than stored. Send a key as null to clear it — for an AirApp's engine that returns the node to following its airapp.json. Requires write access on the node."
4796
+ }).input(updateNodeSettingsInputSchema).output(nodeSchema),
4797
+ getAgentPrompts: oc.route({
4798
+ method: "GET",
4799
+ path: "/nodes/{nodeId}/agent-prompts",
4800
+ tags: ["Nodes"],
4801
+ summary: "Get node custom agent prompts",
4802
+ successDescription: "This node's custom scenario prompts, which replace the node type's default prompts in the Ask-agent dialog. `null` means the node has never had any set, which is not the same as an empty list. Read separately from the node itself because the list is large enough (50 prompts x 8 KiB per locale) that carrying it on every node listing would be its own problem. Requires read access on the node."
4803
+ }).input(getNodeAgentPromptsInputSchema).output(nodeAgentPromptsSchema),
4804
+ updateAgentPrompts: oc.route({
4805
+ method: "PUT",
4806
+ path: "/nodes/{nodeId}/agent-prompts",
4807
+ tags: ["Nodes"],
4808
+ summary: "Replace node custom agent prompts",
4809
+ successDescription: "Replaced this node's custom scenario prompts — the whole list, not a merge. Send `null` to clear them and return the node to its type's default prompts. Requires write access on the node."
4810
+ }).input(updateNodeAgentPromptsInputSchema).output(nodeAgentPromptsSchema),
4461
4811
  updateContent: oc.route({
4462
4812
  method: "PUT",
4463
4813
  path: "/nodes/{nodeId}/content",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "busabase-sdk",
3
- "version": "0.30.1",
3
+ "version": "0.40.1",
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",
@@ -68,8 +68,8 @@
68
68
  "typescript": "^7.0.2",
69
69
  "vitest": "^4.1.11",
70
70
  "open-domains": "0.0.2",
71
- "openlib": "0.1.1",
72
- "busabase-contract": "0.30.1"
71
+ "busabase-contract": "0.40.1",
72
+ "openlib": "0.1.1"
73
73
  },
74
74
  "engines": {
75
75
  "node": ">=24.18.0"