busa-sdk 0.16.0 → 0.16.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -557,7 +557,13 @@ var htmlNodeType = {
557
557
  label: "HTML",
558
558
  icon: "code-xml",
559
559
  capabilities: { hasDetail: true, creatable: true },
560
- operations: []
560
+ operations: [
561
+ {
562
+ kind: "html_document_update",
563
+ label: "Update HTML",
564
+ tone: "border-blue-200 bg-blue-50 text-blue-800"
565
+ }
566
+ ]
561
567
  };
562
568
 
563
569
  // ../../packages/busabase-contract/src/domains/skill/definition.ts
@@ -572,7 +578,13 @@ var whiteboardNodeType = {
572
578
  label: "Whiteboard",
573
579
  icon: "pen-tool",
574
580
  capabilities: { hasDetail: true, creatable: true },
575
- operations: []
581
+ operations: [
582
+ {
583
+ kind: "whiteboard_document_update",
584
+ label: "Update whiteboard",
585
+ tone: "border-blue-200 bg-blue-50 text-blue-800"
586
+ }
587
+ ]
576
588
  };
577
589
 
578
590
  // ../../packages/busabase-contract/src/domains/workflow/definition.ts
@@ -581,7 +593,13 @@ var workflowNodeType = {
581
593
  label: "Workflow",
582
594
  icon: "workflow",
583
595
  capabilities: { hasDetail: true, creatable: true },
584
- operations: []
596
+ operations: [
597
+ {
598
+ kind: "workflow_document_update",
599
+ label: "Update workflow",
600
+ tone: "border-blue-200 bg-blue-50 text-blue-800"
601
+ }
602
+ ]
585
603
  };
586
604
 
587
605
  // ../../packages/busabase-contract/src/domains/registry.ts
@@ -650,12 +668,8 @@ var nodeSchema = z.lazy(
650
668
  slug: z.string(),
651
669
  name: z.string(),
652
670
  description: z.string(),
653
- metadata: z.object({
654
- entryFile: z.string().optional(),
655
- visibility: z.enum(["private", "workspace", "public"]).optional(),
656
- version: z.string().optional(),
657
- assetId: z.string().optional()
658
- }).catchall(z.unknown()).default({}),
671
+ metadata: z.object({ version: z.string().optional() }).catchall(z.unknown()).default({}),
672
+ explicitVisibility: z.enum(["private", "workspace", "public"]).nullable().default(null),
659
673
  position: z.number(),
660
674
  createdAt: z.string(),
661
675
  updatedAt: z.string(),
@@ -762,7 +776,17 @@ var commitSchema = z.object({
762
776
  nodeId: z.string().nullable(),
763
777
  operationId: z.string().nullable(),
764
778
  parentCommitId: z.string().nullable(),
765
- fields: z.record(z.string(), z.unknown()),
779
+ // Deliberately loose (`z.record`), NOT a discriminated union keyed on `operation`.
780
+ //
781
+ // Do not "tighten" this. Commits already in the database were written before
782
+ // per-operation payload validation existed, so their shapes carry no guarantee.
783
+ // The write path (`insertCommit`) and the merge path (`parseCommitPayload`) are
784
+ // strict precisely because they only ever touch freshly-written payloads; this VO
785
+ // is also used to render *history* and approval detail pages, which read arbitrarily
786
+ // old commits. Making it strict would turn any legacy-shaped row into a 500 on a
787
+ // read-only screen. This is not a compatibility shim — it is the requirement not to
788
+ // break reading data that already exists.
789
+ payload: z.record(z.string(), z.unknown()),
766
790
  operation: z.enum(OPERATION_KINDS),
767
791
  message: z.string(),
768
792
  author: z.string(),
@@ -2167,21 +2191,6 @@ var createDocInputSchema = z.object({
2167
2191
  // force review even with write access.
2168
2192
  autoMerge: z.boolean().optional()
2169
2193
  });
2170
- var updateDocInputSchema = z.object({
2171
- body: z.string()
2172
- });
2173
- var createDocChangeRequestInputSchema = z.object({
2174
- body: z.string(),
2175
- message: z.string().optional().default("Update doc").describe(
2176
- 'Explanation shown to the human reviewer. Write a conventional-commit style subject \u2014 imperative verb + what + why, e.g. "Add rollback steps to the deploy runbook".'
2177
- ),
2178
- submittedBy: z.string().optional().default("local-producer"),
2179
- // A Doc body update is the Doc-domain twin of a record `update`, which has taken
2180
- // the permission-aware default since #5712 — and this node type already has a
2181
- // direct-write bypass (`PUT /docs/{nodeId}/body`), so review-first here was never
2182
- // an actual guarantee, just a slower path to the same place.
2183
- autoMerge: z.boolean().optional()
2184
- });
2185
2194
  var docContract = {
2186
2195
  create: oc.route({
2187
2196
  method: "POST",
@@ -2201,21 +2210,7 @@ var docContract = {
2201
2210
  tags: ["Docs"],
2202
2211
  summary: "Read an exact line range from a Doc body",
2203
2212
  successDescription: "Lines [startLine, endLine] (range capped at 2000 lines / ~2MB response) sliced from the Doc's full body \u2014 Docs are KB-scale, so the whole body is read in memory; no byte-range/checkpoint machinery like assets.readTextLines uses for potentially multi-GB files. The Doc-domain follow-up to a Unified Grep match with `source: \"docs\"`, so an agent can read just the lines around a match instead of `nodes.get`'s entire body."
2204
- }).input(ReadDocLinesInputSchema).output(ReadLinesVOSchema),
2205
- updateBody: oc.route({
2206
- method: "PUT",
2207
- path: "/docs/{nodeId}/body",
2208
- tags: ["Docs"],
2209
- summary: "Update Doc body",
2210
- successDescription: "Updated the Doc body."
2211
- }).input(updateDocInputSchema.extend({ nodeId: z.string() })).output(docSchema),
2212
- createChangeRequest: oc.route({
2213
- method: "POST",
2214
- path: "/docs/{nodeId}/change-requests",
2215
- tags: ["Docs", "Change Requests"],
2216
- summary: "Create Doc change request",
2217
- successDescription: "Created a change request that proposes a new Doc body."
2218
- }).input(createDocChangeRequestInputSchema.extend({ nodeId: z.string() })).output(changeRequestSchema)
2213
+ }).input(ReadDocLinesInputSchema).output(ReadLinesVOSchema)
2219
2214
  };
2220
2215
  var DumpTableSchema = z.enum([
2221
2216
  "nodes",
@@ -3039,6 +3034,125 @@ var UnifiedGrepResultVOSchema = z.object({
3039
3034
  /** True when any source truncated, or any source has `notReached > 0`. */
3040
3035
  truncated: z.boolean()
3041
3036
  });
3037
+ var positionSchema = z.object({
3038
+ x: z.number().finite(),
3039
+ y: z.number().finite()
3040
+ });
3041
+ var WhiteboardDocumentSchema = z.object({
3042
+ version: z.literal(1),
3043
+ elements: z.array(z.unknown()).default([]),
3044
+ appState: z.record(z.string(), z.unknown()).default({})
3045
+ });
3046
+ var workflowNodeBase = {
3047
+ id: z.string().min(1),
3048
+ position: positionSchema,
3049
+ label: z.string().min(1).max(120),
3050
+ description: z.string().max(500).default("")
3051
+ };
3052
+ var WorkflowNodeSchema = z.discriminatedUnion("kind", [
3053
+ z.object({
3054
+ ...workflowNodeBase,
3055
+ kind: z.literal("trigger"),
3056
+ eventName: z.string().max(160).default("manual")
3057
+ }),
3058
+ z.object({
3059
+ ...workflowNodeBase,
3060
+ kind: z.literal("webhook"),
3061
+ method: z.enum(["GET", "POST", "PUT", "PATCH", "DELETE"]).default("POST"),
3062
+ url: z.string().max(2e3).default("")
3063
+ }),
3064
+ z.object({
3065
+ ...workflowNodeBase,
3066
+ kind: z.literal("function"),
3067
+ webhookRuleId: z.string().max(160).default(""),
3068
+ functionName: z.string().max(160).default("")
3069
+ }),
3070
+ z.object({
3071
+ ...workflowNodeBase,
3072
+ kind: z.literal("condition"),
3073
+ expression: z.string().max(2e3).default("")
3074
+ }),
3075
+ z.object({
3076
+ ...workflowNodeBase,
3077
+ kind: z.literal("wait"),
3078
+ duration: z.number().int().min(0).max(525600).default(1),
3079
+ unit: z.enum(["minutes", "hours", "days"]).default("hours")
3080
+ }),
3081
+ z.object({
3082
+ ...workflowNodeBase,
3083
+ kind: z.literal("approval"),
3084
+ approver: z.string().max(160).default("")
3085
+ }),
3086
+ z.object({
3087
+ ...workflowNodeBase,
3088
+ kind: z.literal("action"),
3089
+ actionName: z.string().max(160).default("")
3090
+ }),
3091
+ z.object({
3092
+ ...workflowNodeBase,
3093
+ kind: z.literal("end"),
3094
+ outcome: z.string().max(160).default("completed")
3095
+ })
3096
+ ]);
3097
+ var GraphEdgeSchema = z.object({
3098
+ id: z.string().min(1),
3099
+ source: z.string().min(1),
3100
+ target: z.string().min(1)
3101
+ });
3102
+ var WorkflowEdgeSchema = GraphEdgeSchema.extend({
3103
+ label: z.string().max(120).default(""),
3104
+ outcome: z.string().max(120).default("default")
3105
+ });
3106
+ var WorkflowSettingsSchema = z.object({
3107
+ executionMode: z.enum(["manual", "event"]).default("manual"),
3108
+ concurrency: z.number().int().min(1).max(50).default(1),
3109
+ timeoutMs: z.number().int().min(1e3).max(3e5).default(3e4),
3110
+ errorPolicy: z.enum(["stop", "continue"]).default("stop")
3111
+ });
3112
+ var WorkflowDocumentSchema = z.object({
3113
+ version: z.literal(2),
3114
+ nodes: z.array(WorkflowNodeSchema).default([]),
3115
+ edges: z.array(WorkflowEdgeSchema).default([]),
3116
+ settings: WorkflowSettingsSchema.default({
3117
+ executionMode: "manual",
3118
+ concurrency: 1,
3119
+ timeoutMs: 3e4,
3120
+ errorPolicy: "stop"
3121
+ })
3122
+ });
3123
+ var HtmlDocumentSchema = z.object({
3124
+ version: z.literal(1),
3125
+ source: z.string().max(5e5)
3126
+ });
3127
+
3128
+ // ../../packages/busabase-contract/src/contract/node-content-schemas.ts
3129
+ var NODE_CONTENT_VARIANTS = {
3130
+ doc: z.object({ kind: z.literal("doc"), body: z.string() }),
3131
+ whiteboard: z.object({ kind: z.literal("whiteboard"), document: WhiteboardDocumentSchema }),
3132
+ workflow: z.object({ kind: z.literal("workflow"), document: WorkflowDocumentSchema }),
3133
+ html: z.object({ kind: z.literal("html"), document: HtmlDocumentSchema })
3134
+ };
3135
+ var nodeContentInputSchema = z.discriminatedUnion("kind", [
3136
+ NODE_CONTENT_VARIANTS.doc,
3137
+ NODE_CONTENT_VARIANTS.whiteboard,
3138
+ NODE_CONTENT_VARIANTS.workflow,
3139
+ NODE_CONTENT_VARIANTS.html
3140
+ ]);
3141
+ var updateNodeContentInputSchema = z.object({
3142
+ nodeId: z.string(),
3143
+ content: nodeContentInputSchema,
3144
+ message: z.string().optional().default("Update content").describe(
3145
+ 'Explanation shown to the human reviewer. Write a conventional-commit style subject \u2014 imperative verb + what + why, e.g. "Add rollback steps to the deploy runbook".'
3146
+ ),
3147
+ submittedBy: z.string().optional().default("local-producer"),
3148
+ // Server-decided, not client-decided: `shouldAutoMerge(autoMerge, hasWrite) =
3149
+ // autoMerge !== false && hasWrite`. Omitted/true merges immediately IF the
3150
+ // actor holds `write` on the node; otherwise (or with explicit `false`) the
3151
+ // content lands as a pending ChangeRequest instead. A `changeRequest`-level
3152
+ // caller passing `autoMerge: true` still lands in review — the server never
3153
+ // lets the client escalate past its own permission.
3154
+ autoMerge: z.boolean().optional()
3155
+ });
3042
3156
  var folderSchema = z.object({
3043
3157
  node: nodeSchema,
3044
3158
  children: z.array(nodeSchema)
@@ -3049,6 +3163,11 @@ var genericNodeDetailSchema = (type) => z.object({
3049
3163
  type: z.literal(type),
3050
3164
  node: nodeSchema
3051
3165
  });
3166
+ var richNodeDetailSchema = (type, documentSchema) => z.object({
3167
+ type: z.literal(type),
3168
+ node: nodeSchema,
3169
+ document: documentSchema
3170
+ });
3052
3171
  var NODE_DETAIL_VARIANTS = {
3053
3172
  folder: folderSchema.extend({ type: z.literal("folder") }),
3054
3173
  doc: docSchema.extend({ type: z.literal("doc") }),
@@ -3061,9 +3180,9 @@ var NODE_DETAIL_VARIANTS = {
3061
3180
  airapp: fileTreeNodeSchema.extend({ type: z.literal("airapp") }),
3062
3181
  base: genericNodeDetailSchema("base"),
3063
3182
  form: genericNodeDetailSchema("form"),
3064
- whiteboard: genericNodeDetailSchema("whiteboard"),
3065
- workflow: genericNodeDetailSchema("workflow"),
3066
- html: genericNodeDetailSchema("html")
3183
+ whiteboard: richNodeDetailSchema("whiteboard", WhiteboardDocumentSchema),
3184
+ workflow: richNodeDetailSchema("workflow", WorkflowDocumentSchema),
3185
+ html: richNodeDetailSchema("html", HtmlDocumentSchema)
3067
3186
  };
3068
3187
  var NodeDetailVOSchema = z.discriminatedUnion("type", [
3069
3188
  NODE_DETAIL_VARIANTS.folder,
@@ -3146,7 +3265,7 @@ var busabaseContractRoutes = {
3146
3265
  path: "/grep",
3147
3266
  tags: ["Search"],
3148
3267
  summary: "Search files, Docs, and Base records with one pattern (unified grep)",
3149
- successDescription: "Streaming regex/literal matches across every in-scope source \u2014 Drive/Skill files, Doc bodies, and Base records (canonical headCommit.fields, never the truncated search projection) \u2014 with one shared pattern, one shared maxMatches/deadline budget (files scanned first, then docs, then whatever budget remains goes to records), and a per-source honest coverage report (files keeps its existing missing/stale/unsearchable/errored/notReached; docs and records report scanned/errored/notReached). truncated is set when any source truncated or has notReached > 0."
3268
+ successDescription: "Streaming regex/literal matches across every in-scope source \u2014 Drive/Skill files, Doc bodies, and Base records (canonical headCommit.payload, never the truncated search projection) \u2014 with one shared pattern, one shared maxMatches/deadline budget (files scanned first, then docs, then whatever budget remains goes to records), and a per-source honest coverage report (files keeps its existing missing/stale/unsearchable/errored/notReached; docs and records report scanned/errored/notReached). truncated is set when any source truncated or has notReached > 0."
3150
3269
  }).input(UnifiedGrepInputSchema).output(UnifiedGrepResultVOSchema),
3151
3270
  nodes: {
3152
3271
  list: oc.route({
@@ -3189,8 +3308,15 @@ var busabaseContractRoutes = {
3189
3308
  path: "/nodes/{nodeId}/metadata",
3190
3309
  tags: ["Nodes"],
3191
3310
  summary: "Update node metadata",
3192
- successDescription: "Shallow-merged the supplied top-level keys into the active node's existing metadata. Requires write access on the node."
3311
+ 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 \u2014 use PUT /nodes/{nodeId}/content instead."
3193
3312
  }).input(updateNodeMetadataInputSchema).output(nodeSchema),
3313
+ updateContent: oc.route({
3314
+ method: "PUT",
3315
+ path: "/nodes/{nodeId}/content",
3316
+ tags: ["Nodes", "Change Requests"],
3317
+ summary: "Update node content",
3318
+ successDescription: "ChangeRequest carrying the proposed content. Merged immediately when the actor holds write access on the node and `autoMerge` was not explicitly `false`; otherwise left `in_review` for a human. Accepts doc, whiteboard, workflow, and html nodes \u2014 the types that own exactly one document."
3319
+ }).input(updateNodeContentInputSchema).output(changeRequestSchema),
3194
3320
  purge: oc.route({
3195
3321
  method: "DELETE",
3196
3322
  path: "/nodes/{nodeId}",
@@ -3930,7 +4056,7 @@ var Busabase = class {
3930
4056
  /**
3931
4057
  * Unified grep — one regex/literal pattern scanned across every in-scope
3932
4058
  * source (Drive/Skill files, Doc bodies, and Base records — records read
3933
- * the canonical `headCommit.fields`, never the truncated search
4059
+ * the canonical `headCommit.payload`, never the truncated search
3934
4060
  * projection), with a shared `maxMatches`/deadline budget and per-source
3935
4061
  * honest coverage. `bb.assets.grep` remains available as a files-only SDK
3936
4062
  * convenience and delegates here with `sources: ["files"]`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "busa-sdk",
3
- "version": "0.16.0",
3
+ "version": "0.16.2",
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",