busabase-sdk 0.9.2 → 0.9.4
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.d.ts +10932 -4862
- package/dist/index.js +655 -92
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -56,6 +56,7 @@ var ConfirmUploadVOSchema = z.object({
|
|
|
56
56
|
storageKey: z.string(),
|
|
57
57
|
publicUrl: z.string()
|
|
58
58
|
});
|
|
59
|
+
var AssetTextStatusSchema = z.enum(["missing", "present", "none", "stale"]);
|
|
59
60
|
var AssetVOSchema = z.object({
|
|
60
61
|
id: z.string(),
|
|
61
62
|
attachmentId: z.string(),
|
|
@@ -69,6 +70,8 @@ var AssetVOSchema = z.object({
|
|
|
69
70
|
contentHash: z.string().nullable(),
|
|
70
71
|
/** How many places reference this asset (Base records + Doc bodies). */
|
|
71
72
|
usageCount: z.number().int().nonnegative(),
|
|
73
|
+
/** Drive Grep Retrieval text-slot status — see {@link AssetTextStatusSchema}. */
|
|
74
|
+
textStatus: AssetTextStatusSchema,
|
|
72
75
|
createdAt: z.string()
|
|
73
76
|
});
|
|
74
77
|
var AssetUsageVOSchema = z.object({
|
|
@@ -92,6 +95,108 @@ var AssetDetailVOSchema = z.object({
|
|
|
92
95
|
asset: AssetVOSchema,
|
|
93
96
|
usages: z.array(AssetUsageVOSchema)
|
|
94
97
|
});
|
|
98
|
+
var PutTextInputSchema = z.object({
|
|
99
|
+
assetId: z.string(),
|
|
100
|
+
/** Inline text body, ≤ 1 MB. For larger text, use `createTextUploadUrl` + bind by `storageKey`. */
|
|
101
|
+
text: z.string().optional(),
|
|
102
|
+
/** Bind a presigned-uploaded text object (a temp `asset-texts/pending/*.txt` key). */
|
|
103
|
+
storageKey: z.string().optional(),
|
|
104
|
+
/**
|
|
105
|
+
* Claimed content hash for the `storageKey` bind path (`sha256:<hex>`, echoing
|
|
106
|
+
* `createTextUploadUrl`'s input like `open-domains/attachments`' confirm step).
|
|
107
|
+
* The server always computes the ACTUAL hash from the bytes during the
|
|
108
|
+
* confirm scan and rejects a mismatch (hash-poisoning defense) — this field
|
|
109
|
+
* is only an optional early-mismatch check, never trusted for addressing.
|
|
110
|
+
*/
|
|
111
|
+
contentHash: z.string().optional(),
|
|
112
|
+
/** Mark as having no extractable text (e.g. a scanned, image-only PDF). */
|
|
113
|
+
none: z.boolean().optional()
|
|
114
|
+
});
|
|
115
|
+
var AssetTextVOSchema = z.object({
|
|
116
|
+
assetId: z.string(),
|
|
117
|
+
textStatus: AssetTextStatusSchema,
|
|
118
|
+
lineCount: z.number().int().nonnegative(),
|
|
119
|
+
charCount: z.number().int().nonnegative(),
|
|
120
|
+
byteCount: z.number().int().nonnegative()
|
|
121
|
+
});
|
|
122
|
+
var CreateTextUploadUrlInputSchema = z.object({
|
|
123
|
+
assetId: z.string(),
|
|
124
|
+
sizeBytes: z.number().int().positive(),
|
|
125
|
+
/** Optional claim, mirrors `RequestUploadUrlDTO.contentHash` (never trusted for addressing). */
|
|
126
|
+
contentHash: z.string().optional()
|
|
127
|
+
});
|
|
128
|
+
var CreateTextUploadUrlVOSchema = z.object({
|
|
129
|
+
uploadUrl: z.string(),
|
|
130
|
+
storageKey: z.string(),
|
|
131
|
+
expiresIn: z.number().int().nonnegative()
|
|
132
|
+
});
|
|
133
|
+
var GrepScopeSchema = z.object({
|
|
134
|
+
assetIds: z.array(z.string()).optional(),
|
|
135
|
+
/** Drive/Skill mounted path prefix (matches `busabase_asset_usages.path`). */
|
|
136
|
+
drivePath: z.string().optional(),
|
|
137
|
+
mimeTypes: z.array(z.string()).optional()
|
|
138
|
+
});
|
|
139
|
+
var GREP_DEFAULT_MAX_MATCHES = 100;
|
|
140
|
+
var GREP_HARD_MAX_MATCHES = 1e3;
|
|
141
|
+
var GREP_DEFAULT_CONTEXT_LINES = 0;
|
|
142
|
+
var GREP_MAX_CONTEXT_LINES = 10;
|
|
143
|
+
var GrepInputSchema = z.object({
|
|
144
|
+
pattern: z.string().min(1),
|
|
145
|
+
/** JS RegExp flags, e.g. `"i"` for case-insensitive. `g`/`y` are ignored (grep always scans every match per line). */
|
|
146
|
+
flags: z.string().optional().default(""),
|
|
147
|
+
scope: GrepScopeSchema.optional(),
|
|
148
|
+
maxMatches: z.coerce.number().int().min(1).max(GREP_HARD_MAX_MATCHES).optional().default(GREP_DEFAULT_MAX_MATCHES),
|
|
149
|
+
contextLines: z.coerce.number().int().min(0).max(GREP_MAX_CONTEXT_LINES).optional().default(GREP_DEFAULT_CONTEXT_LINES)
|
|
150
|
+
});
|
|
151
|
+
var GrepMatchVOSchema = z.object({
|
|
152
|
+
assetId: z.string(),
|
|
153
|
+
fileName: z.string(),
|
|
154
|
+
/** Drive/Skill mounted path, or "" when the asset isn't path-mounted (e.g. a File node). */
|
|
155
|
+
drivePath: z.string(),
|
|
156
|
+
line: z.number().int().positive(),
|
|
157
|
+
/** 1-based character column (not byte offset) of the match start within the line. */
|
|
158
|
+
column: z.number().int().positive(),
|
|
159
|
+
/** The matching line, truncated if it exceeds the long-line guard. */
|
|
160
|
+
text: z.string(),
|
|
161
|
+
before: z.array(z.string()),
|
|
162
|
+
after: z.array(z.string())
|
|
163
|
+
});
|
|
164
|
+
var GrepResultVOSchema = z.object({
|
|
165
|
+
matches: z.array(GrepMatchVOSchema),
|
|
166
|
+
filesScanned: z.number().int().nonnegative(),
|
|
167
|
+
/** Asset ids in scope with no text yet (contentKind text-or-writable-binary, no row). */
|
|
168
|
+
missing: z.array(z.string()),
|
|
169
|
+
/** Asset ids in scope whose derived text is stale (source replaced since it was written). */
|
|
170
|
+
stale: z.array(z.string()),
|
|
171
|
+
/** Count of assets in scope explicitly marked `none` (no extractable text). */
|
|
172
|
+
unsearchable: z.number().int().nonnegative(),
|
|
173
|
+
/**
|
|
174
|
+
* Asset ids whose scan was attempted but failed (storage error, corrupt
|
|
175
|
+
* cache file, object deleted mid-flight) — NOT counted in `filesScanned`.
|
|
176
|
+
* Honest coverage: these were not actually searched, so a caller must not
|
|
177
|
+
* treat their absence from `matches` as a clean "no match".
|
|
178
|
+
*/
|
|
179
|
+
errored: z.array(z.string()),
|
|
180
|
+
/**
|
|
181
|
+
* Count of in-scope, present-and-searchable assets the scan never even
|
|
182
|
+
* reached because the deadline or `maxMatches` budget ran out first. Only
|
|
183
|
+
* nonzero when `truncated` is true.
|
|
184
|
+
*/
|
|
185
|
+
notReached: z.number().int().nonnegative(),
|
|
186
|
+
truncated: z.boolean()
|
|
187
|
+
});
|
|
188
|
+
var ReadTextLinesInputSchema = z.object({
|
|
189
|
+
assetId: z.string(),
|
|
190
|
+
startLine: z.coerce.number().int().min(1),
|
|
191
|
+
endLine: z.coerce.number().int().min(1)
|
|
192
|
+
});
|
|
193
|
+
var ReadLinesVOSchema = z.object({
|
|
194
|
+
lines: z.array(z.string()),
|
|
195
|
+
startLine: z.number().int().positive(),
|
|
196
|
+
endLine: z.number().int().positive(),
|
|
197
|
+
totalLines: z.number().int().nonnegative(),
|
|
198
|
+
truncated: z.boolean()
|
|
199
|
+
});
|
|
95
200
|
|
|
96
201
|
// ../../packages/busabase-contract/src/domains/assets/contract.ts
|
|
97
202
|
var UpdateAssetMetadataInputSchema = z.object({
|
|
@@ -133,7 +238,7 @@ var assetsContract = {
|
|
|
133
238
|
path: "/assets/{assetId}/metadata",
|
|
134
239
|
tags: ["Assets"],
|
|
135
240
|
summary: "Update asset metadata",
|
|
136
|
-
successDescription: "Updated AI-readable metadata for a file, such as summary,
|
|
241
|
+
successDescription: "Updated AI-readable metadata for a file, such as summary, tags, source URL, or schema-specific hints. Large text does not live here \u2014 see putText / grep / readTextLines."
|
|
137
242
|
}).input(UpdateAssetMetadataInputSchema).output(AssetDetailVOSchema),
|
|
138
243
|
delete: oc.route({
|
|
139
244
|
method: "DELETE",
|
|
@@ -141,7 +246,39 @@ var assetsContract = {
|
|
|
141
246
|
tags: ["Assets"],
|
|
142
247
|
summary: "Delete asset",
|
|
143
248
|
successDescription: "Removed the asset and, if no other row references its bytes, the stored object. Refused while the asset is still referenced (where-used)."
|
|
144
|
-
}).input(z.object({ assetId: z.string() })).output(z.object({ deleted: z.boolean() }))
|
|
249
|
+
}).input(z.object({ assetId: z.string() })).output(z.object({ deleted: z.boolean() })),
|
|
250
|
+
// ── Drive Grep Retrieval ─────────────────────────────────────────────────
|
|
251
|
+
// Busabase stores, indexes, and searches text; it never generates it. Text
|
|
252
|
+
// always arrives via putText — an agent's own extractor, or (future) an
|
|
253
|
+
// Outgoing-Hook-triggered service — never a bundled parser/OCR library.
|
|
254
|
+
putText: oc.route({
|
|
255
|
+
method: "PUT",
|
|
256
|
+
path: "/assets/{assetId}/text",
|
|
257
|
+
tags: ["Assets"],
|
|
258
|
+
summary: "Write (or mark none) an asset's text slot",
|
|
259
|
+
successDescription: "Text slot updated: inline body (\u22641MB), or bound from a presigned upload (server-verified content hash, hash-poisoning-safe), or marked `none` for files with no extractable text. Direct write, audit-logged, not ChangeRequest-gated."
|
|
260
|
+
}).input(PutTextInputSchema).output(AssetTextVOSchema),
|
|
261
|
+
createTextUploadUrl: oc.route({
|
|
262
|
+
method: "POST",
|
|
263
|
+
path: "/assets/text/upload-urls",
|
|
264
|
+
tags: ["Assets"],
|
|
265
|
+
summary: "Request a presigned upload URL for large text",
|
|
266
|
+
successDescription: "Presigned (or dev) upload URL for a temporary text object; PUT the bytes there, then call putText with the returned storageKey to bind, verify, and content-address it."
|
|
267
|
+
}).input(CreateTextUploadUrlInputSchema).output(CreateTextUploadUrlVOSchema),
|
|
268
|
+
grep: oc.route({
|
|
269
|
+
method: "POST",
|
|
270
|
+
path: "/assets/grep",
|
|
271
|
+
tags: ["Assets"],
|
|
272
|
+
summary: "Search every text-bearing asset in scope",
|
|
273
|
+
successDescription: "Streaming regex/literal matches with real file + line + column numbers and context, across every asset with text \u2014 any size, no 256KB cap. Honest coverage: missing/stale/unsearchable/errored name assets that were not (fully or successfully) searched, notReached counts present assets the scan never got to, and truncated flags a capped response."
|
|
274
|
+
}).input(GrepInputSchema).output(GrepResultVOSchema),
|
|
275
|
+
readTextLines: oc.route({
|
|
276
|
+
method: "GET",
|
|
277
|
+
path: "/assets/{assetId}/text/lines",
|
|
278
|
+
tags: ["Assets"],
|
|
279
|
+
summary: "Read an exact line range from an asset's text",
|
|
280
|
+
successDescription: "Lines [startLine, endLine] (range capped at 2000 lines / ~2MB response) read via a storage byte-range request \u2014 the server never loads the whole object, even for a multi-GB file."
|
|
281
|
+
}).input(ReadTextLinesInputSchema).output(ReadLinesVOSchema)
|
|
145
282
|
};
|
|
146
283
|
var i18n = {
|
|
147
284
|
locales: ["en", "zh-CN", "zh-TW", "ja", "ko", "de", "fr", "es", "pt"]};
|
|
@@ -170,6 +307,7 @@ var fieldTypeSchema = z.enum([
|
|
|
170
307
|
"select",
|
|
171
308
|
"multiselect",
|
|
172
309
|
"url",
|
|
310
|
+
"embed",
|
|
173
311
|
"email",
|
|
174
312
|
"phone",
|
|
175
313
|
"created_time",
|
|
@@ -207,6 +345,11 @@ var fieldOptionsSchema = z.object({
|
|
|
207
345
|
code: z.object({
|
|
208
346
|
language: z.string().optional()
|
|
209
347
|
}).optional(),
|
|
348
|
+
embed: z.object({
|
|
349
|
+
aspectRatio: z.enum(["16:9", "4:3", "1:1"]).optional(),
|
|
350
|
+
height: z.number().int().positive().max(1200).optional(),
|
|
351
|
+
providers: z.array(z.string()).optional()
|
|
352
|
+
}).optional(),
|
|
210
353
|
inverseFieldId: z.string().optional(),
|
|
211
354
|
multiple: z.boolean().optional(),
|
|
212
355
|
// Display formatting for `number` columns (Notion-style: one number type,
|
|
@@ -257,7 +400,12 @@ var createBaseInputSchema = z.object({
|
|
|
257
400
|
required: z.boolean().default(false),
|
|
258
401
|
options: fieldOptionsSchema.optional().default({})
|
|
259
402
|
})
|
|
260
|
-
).default([])
|
|
403
|
+
).default([]),
|
|
404
|
+
// Review-first by default: without `autoMerge: true`, this proposes the Base
|
|
405
|
+
// as a pending ChangeRequest (status "in_review") instead of creating it
|
|
406
|
+
// immediately. Pass `autoMerge: true` only for callers that don't need human
|
|
407
|
+
// review (seed/migration scripts, an explicit no-review agent task).
|
|
408
|
+
autoMerge: z.boolean().optional().default(false)
|
|
261
409
|
});
|
|
262
410
|
var createBaseFieldInputSchema = z.object({
|
|
263
411
|
name: fieldNameSchema,
|
|
@@ -629,20 +777,21 @@ var commentSchema = z.object({
|
|
|
629
777
|
createdAt: z.string(),
|
|
630
778
|
updatedAt: z.string()
|
|
631
779
|
});
|
|
780
|
+
var changeRequestStatusSchema = z.enum([
|
|
781
|
+
"in_review",
|
|
782
|
+
"changes_requested",
|
|
783
|
+
"approved",
|
|
784
|
+
"rejected",
|
|
785
|
+
"merged",
|
|
786
|
+
"abandoned",
|
|
787
|
+
"conflict"
|
|
788
|
+
]);
|
|
632
789
|
var changeRequestSchema = z.object({
|
|
633
790
|
id: z.string(),
|
|
634
791
|
baseId: z.string().nullable(),
|
|
635
792
|
targetType: z.enum(["base", "node"]),
|
|
636
793
|
nodeId: z.string().nullable(),
|
|
637
|
-
status:
|
|
638
|
-
"in_review",
|
|
639
|
-
"changes_requested",
|
|
640
|
-
"approved",
|
|
641
|
-
"rejected",
|
|
642
|
-
"merged",
|
|
643
|
-
"abandoned",
|
|
644
|
-
"conflict"
|
|
645
|
-
]),
|
|
794
|
+
status: changeRequestStatusSchema,
|
|
646
795
|
submittedBy: z.string(),
|
|
647
796
|
submittedByUser: userRefSchema.nullable().optional().default(null),
|
|
648
797
|
sourceMeta: z.record(z.string(), z.unknown()),
|
|
@@ -688,7 +837,14 @@ var liveEventSchema = z.object({
|
|
|
688
837
|
"change_request.updated",
|
|
689
838
|
"change_request.deleted",
|
|
690
839
|
"change_request.reviewed",
|
|
691
|
-
"change_request.merged"
|
|
840
|
+
"change_request.merged",
|
|
841
|
+
// Fired only when a CONTENT change request freshly enters human review
|
|
842
|
+
// (record_* ops created via record-ops.ts) — never for structural ops
|
|
843
|
+
// that auto-merge instantly (those still fire "change_request.created"
|
|
844
|
+
// via the audit funnel, but nothing needs reviewing). Consumed by
|
|
845
|
+
// `use-live-sync.ts` to pop a desktop Notification, and by
|
|
846
|
+
// busabase-cloud's host hook to persist an inbox notification row.
|
|
847
|
+
"change_request.pending_review"
|
|
692
848
|
]),
|
|
693
849
|
spaceId: z.string(),
|
|
694
850
|
actorId: z.string(),
|
|
@@ -718,6 +874,8 @@ var auditActionSchema = z.enum([
|
|
|
718
874
|
"drive.created",
|
|
719
875
|
"asset.deleted",
|
|
720
876
|
"asset.metadata_updated",
|
|
877
|
+
"asset.text_written",
|
|
878
|
+
"asset.text_marked_none",
|
|
721
879
|
"node.purged"
|
|
722
880
|
]);
|
|
723
881
|
var auditEventSchema = z.object({
|
|
@@ -838,6 +996,25 @@ var createCommentInputSchema = commentSubjectInputSchema.extend({
|
|
|
838
996
|
var listInputSchema = z.object({
|
|
839
997
|
limit: z.coerce.number().int().min(1).max(100).optional().default(50)
|
|
840
998
|
}).optional().default({ limit: 50 });
|
|
999
|
+
var listChangeRequestsPagedInputSchema = z.object({
|
|
1000
|
+
limit: z.coerce.number().int().min(1).max(100).optional().default(50),
|
|
1001
|
+
/** Opaque base64 cursor (`createdAt|id`) for keyset pagination. */
|
|
1002
|
+
cursor: z.string().optional(),
|
|
1003
|
+
status: z.array(changeRequestStatusSchema).optional(),
|
|
1004
|
+
mine: z.boolean().optional()
|
|
1005
|
+
}).optional().default({ limit: 50 });
|
|
1006
|
+
var listChangeRequestsResponseSchema = z.object({
|
|
1007
|
+
changeRequests: z.array(changeRequestSchema),
|
|
1008
|
+
nextCursor: z.string().nullable()
|
|
1009
|
+
});
|
|
1010
|
+
var changeRequestCountsSchema = z.object({
|
|
1011
|
+
review: z.number().int().nonnegative(),
|
|
1012
|
+
changes: z.number().int().nonnegative(),
|
|
1013
|
+
created: z.number().int().nonnegative(),
|
|
1014
|
+
approved: z.number().int().nonnegative(),
|
|
1015
|
+
merged: z.number().int().nonnegative(),
|
|
1016
|
+
rejected: z.number().int().nonnegative()
|
|
1017
|
+
});
|
|
841
1018
|
var searchInputSchema = z.object({
|
|
842
1019
|
query: z.string().default(""),
|
|
843
1020
|
limit: z.coerce.number().int().min(1).max(100).optional().default(20),
|
|
@@ -872,6 +1049,69 @@ var authInfoSchema = z.object({
|
|
|
872
1049
|
*/
|
|
873
1050
|
spaces: z.array(authSpaceSchema)
|
|
874
1051
|
});
|
|
1052
|
+
var viewFilterOperatorSchema = z.enum([
|
|
1053
|
+
"contains",
|
|
1054
|
+
"equals",
|
|
1055
|
+
"not_empty",
|
|
1056
|
+
"is_empty",
|
|
1057
|
+
"is_true",
|
|
1058
|
+
"is_false"
|
|
1059
|
+
]);
|
|
1060
|
+
var viewFilterSchema = z.object({
|
|
1061
|
+
fieldSlug: z.string(),
|
|
1062
|
+
// Stable field identity — survives slug reuse; populated on merge.
|
|
1063
|
+
fieldId: z.string().optional(),
|
|
1064
|
+
operator: viewFilterOperatorSchema,
|
|
1065
|
+
value: z.unknown().optional()
|
|
1066
|
+
});
|
|
1067
|
+
var viewSortSchema = z.object({
|
|
1068
|
+
direction: z.enum(["asc", "desc"]),
|
|
1069
|
+
fieldSlug: z.string(),
|
|
1070
|
+
fieldId: z.string().optional()
|
|
1071
|
+
});
|
|
1072
|
+
var viewConfigSchema = z.object({
|
|
1073
|
+
filters: z.array(viewFilterSchema).default([]),
|
|
1074
|
+
sorts: z.array(viewSortSchema).default([]),
|
|
1075
|
+
visibleFieldSlugs: z.array(z.string()).nullable().optional()
|
|
1076
|
+
});
|
|
1077
|
+
var viewSchema = z.object({
|
|
1078
|
+
id: z.string(),
|
|
1079
|
+
baseId: z.string(),
|
|
1080
|
+
slug: z.string(),
|
|
1081
|
+
name: z.string(),
|
|
1082
|
+
description: z.string(),
|
|
1083
|
+
type: z.literal("table"),
|
|
1084
|
+
config: viewConfigSchema,
|
|
1085
|
+
status: z.enum(["active", "archived"]),
|
|
1086
|
+
createdBy: z.string(),
|
|
1087
|
+
createdByUser: userRefSchema.nullable().optional().default(null),
|
|
1088
|
+
archivedAt: z.string().nullable(),
|
|
1089
|
+
createdAt: z.string(),
|
|
1090
|
+
updatedAt: z.string()
|
|
1091
|
+
});
|
|
1092
|
+
var createViewInputSchema = z.object({
|
|
1093
|
+
config: viewConfigSchema.optional().default({ filters: [], sorts: [] }),
|
|
1094
|
+
description: z.string().optional().default(""),
|
|
1095
|
+
message: z.string().optional().default("Create view"),
|
|
1096
|
+
name: z.string().min(1),
|
|
1097
|
+
slug: z.string().min(1).regex(/^[a-z0-9-]+$/).optional(),
|
|
1098
|
+
submittedBy: z.string().optional().default("local-producer")
|
|
1099
|
+
});
|
|
1100
|
+
var updateViewInputSchema = z.object({
|
|
1101
|
+
config: viewConfigSchema.optional(),
|
|
1102
|
+
description: z.string().optional(),
|
|
1103
|
+
message: z.string().optional().default("Update view"),
|
|
1104
|
+
name: z.string().min(1).optional(),
|
|
1105
|
+
submittedBy: z.string().optional().default("local-producer")
|
|
1106
|
+
});
|
|
1107
|
+
var deleteViewInputSchema = z.object({
|
|
1108
|
+
message: z.string().optional().default("Delete view"),
|
|
1109
|
+
submittedBy: z.string().optional().default("local-producer")
|
|
1110
|
+
});
|
|
1111
|
+
var restoreViewInputSchema = z.object({
|
|
1112
|
+
message: z.string().optional().default("Restore view"),
|
|
1113
|
+
submittedBy: z.string().optional().default("local-producer")
|
|
1114
|
+
});
|
|
875
1115
|
|
|
876
1116
|
// ../../packages/busabase-contract/src/domains/base/contract/record-schemas.ts
|
|
877
1117
|
var recordSchema = z.object({
|
|
@@ -889,16 +1129,44 @@ var recordSchema = z.object({
|
|
|
889
1129
|
base: baseSchema,
|
|
890
1130
|
headCommit: commitSchema
|
|
891
1131
|
});
|
|
1132
|
+
var listRecordsFilterSchema = z.object({
|
|
1133
|
+
fieldSlug: z.string(),
|
|
1134
|
+
fieldType: z.string().optional(),
|
|
1135
|
+
operator: viewFilterOperatorSchema,
|
|
1136
|
+
value: z.unknown().optional()
|
|
1137
|
+
});
|
|
1138
|
+
var listRecordsSortSchema = z.object({
|
|
1139
|
+
fieldSlug: z.string(),
|
|
1140
|
+
fieldType: z.string().optional(),
|
|
1141
|
+
direction: z.enum(["asc", "desc"]).optional().default("asc")
|
|
1142
|
+
});
|
|
892
1143
|
var listRecordsInputSchema = z.object({
|
|
893
1144
|
limit: z.coerce.number().int().min(1).max(100).optional().default(50),
|
|
894
1145
|
baseId: z.string().optional(),
|
|
895
|
-
/** Opaque base64 cursor (
|
|
896
|
-
cursor: z.string().optional()
|
|
1146
|
+
/** Opaque base64 cursor for keyset pagination (createdAt-keyed, or sort-keyed when `sort` is set). */
|
|
1147
|
+
cursor: z.string().optional(),
|
|
1148
|
+
/** View filters for server-side push-down (superset; client still narrows). */
|
|
1149
|
+
filters: z.array(listRecordsFilterSchema).optional(),
|
|
1150
|
+
/** View sort for server-side push-down (number/date fields only). */
|
|
1151
|
+
sort: listRecordsSortSchema.optional()
|
|
897
1152
|
}).optional().default({ limit: 50 });
|
|
898
1153
|
var listRecordsResponseSchema = z.object({
|
|
899
1154
|
records: z.array(recordSchema),
|
|
900
1155
|
nextCursor: z.string().nullable()
|
|
901
1156
|
});
|
|
1157
|
+
var listArchivedRecordsPagedInputSchema = z.object({
|
|
1158
|
+
baseId: z.string(),
|
|
1159
|
+
limit: z.coerce.number().int().min(1).max(100).optional().default(50),
|
|
1160
|
+
/** Opaque base64 cursor (createdAt-keyed) for keyset pagination. */
|
|
1161
|
+
cursor: z.string().optional()
|
|
1162
|
+
});
|
|
1163
|
+
var countRecordsInputSchema = z.object({
|
|
1164
|
+
baseId: z.string().optional()
|
|
1165
|
+
}).optional().default({});
|
|
1166
|
+
var countRecordsResponseSchema = z.object({
|
|
1167
|
+
/** Total active records in the space (optionally scoped to a base). */
|
|
1168
|
+
total: z.number().int().nonnegative()
|
|
1169
|
+
});
|
|
902
1170
|
var createChangeRequestInputSchema = z.object({
|
|
903
1171
|
fields: z.record(z.string(), z.unknown()).describe(
|
|
904
1172
|
"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 \u2014 always give it a short, human-readable value, never an id or placeholder."
|
|
@@ -940,71 +1208,6 @@ var recordLinkSchema = z.object({
|
|
|
940
1208
|
createdAt: z.string(),
|
|
941
1209
|
updatedAt: z.string()
|
|
942
1210
|
});
|
|
943
|
-
var viewFilterOperatorSchema = z.enum([
|
|
944
|
-
"contains",
|
|
945
|
-
"equals",
|
|
946
|
-
"not_empty",
|
|
947
|
-
"is_empty",
|
|
948
|
-
"is_true",
|
|
949
|
-
"is_false"
|
|
950
|
-
]);
|
|
951
|
-
var viewFilterSchema = z.object({
|
|
952
|
-
fieldSlug: z.string(),
|
|
953
|
-
// Stable field identity — survives slug reuse; populated on merge.
|
|
954
|
-
fieldId: z.string().optional(),
|
|
955
|
-
operator: viewFilterOperatorSchema,
|
|
956
|
-
value: z.unknown().optional()
|
|
957
|
-
});
|
|
958
|
-
var viewSortSchema = z.object({
|
|
959
|
-
direction: z.enum(["asc", "desc"]),
|
|
960
|
-
fieldSlug: z.string(),
|
|
961
|
-
fieldId: z.string().optional()
|
|
962
|
-
});
|
|
963
|
-
var viewConfigSchema = z.object({
|
|
964
|
-
filters: z.array(viewFilterSchema).default([]),
|
|
965
|
-
sorts: z.array(viewSortSchema).default([]),
|
|
966
|
-
visibleFieldSlugs: z.array(z.string()).nullable().optional()
|
|
967
|
-
});
|
|
968
|
-
var viewSchema = z.object({
|
|
969
|
-
id: z.string(),
|
|
970
|
-
baseId: z.string(),
|
|
971
|
-
slug: z.string(),
|
|
972
|
-
name: z.string(),
|
|
973
|
-
description: z.string(),
|
|
974
|
-
type: z.literal("table"),
|
|
975
|
-
config: viewConfigSchema,
|
|
976
|
-
status: z.enum(["active", "archived"]),
|
|
977
|
-
createdBy: z.string(),
|
|
978
|
-
createdByUser: userRefSchema.nullable().optional().default(null),
|
|
979
|
-
archivedAt: z.string().nullable(),
|
|
980
|
-
createdAt: z.string(),
|
|
981
|
-
updatedAt: z.string()
|
|
982
|
-
});
|
|
983
|
-
var createViewInputSchema = z.object({
|
|
984
|
-
config: viewConfigSchema.optional().default({ filters: [], sorts: [] }),
|
|
985
|
-
description: z.string().optional().default(""),
|
|
986
|
-
message: z.string().optional().default("Create view"),
|
|
987
|
-
name: z.string().min(1),
|
|
988
|
-
slug: z.string().min(1).regex(/^[a-z0-9-]+$/).optional(),
|
|
989
|
-
submittedBy: z.string().optional().default("local-producer")
|
|
990
|
-
});
|
|
991
|
-
var updateViewInputSchema = z.object({
|
|
992
|
-
config: viewConfigSchema.optional(),
|
|
993
|
-
description: z.string().optional(),
|
|
994
|
-
message: z.string().optional().default("Update view"),
|
|
995
|
-
name: z.string().min(1).optional(),
|
|
996
|
-
submittedBy: z.string().optional().default("local-producer")
|
|
997
|
-
});
|
|
998
|
-
var deleteViewInputSchema = z.object({
|
|
999
|
-
message: z.string().optional().default("Delete view"),
|
|
1000
|
-
submittedBy: z.string().optional().default("local-producer")
|
|
1001
|
-
});
|
|
1002
|
-
var restoreViewInputSchema = z.object({
|
|
1003
|
-
message: z.string().optional().default("Restore view"),
|
|
1004
|
-
submittedBy: z.string().optional().default("local-producer")
|
|
1005
|
-
});
|
|
1006
|
-
|
|
1007
|
-
// ../../packages/busabase-contract/src/domains/base/contract/routes.ts
|
|
1008
1211
|
var baseContract = {
|
|
1009
1212
|
list: oc.route({
|
|
1010
1213
|
method: "GET",
|
|
@@ -1055,13 +1258,20 @@ var baseContract = {
|
|
|
1055
1258
|
summary: "List archived records for a Base",
|
|
1056
1259
|
successDescription: "Records that have been archived (soft-deleted) from a Base."
|
|
1057
1260
|
}).input(z.object({ baseId: z.string() })).output(z.array(recordSchema)),
|
|
1261
|
+
listArchivedRecordsPaged: oc.route({
|
|
1262
|
+
method: "GET",
|
|
1263
|
+
path: "/bases/{baseId}/records/archived/paged",
|
|
1264
|
+
tags: ["Records"],
|
|
1265
|
+
summary: "List archived records for a Base with keyset pagination",
|
|
1266
|
+
successDescription: "A page of archived (soft-deleted) records plus an opaque nextCursor (null at the end)."
|
|
1267
|
+
}).input(listArchivedRecordsPagedInputSchema).output(listRecordsResponseSchema),
|
|
1058
1268
|
create: oc.route({
|
|
1059
1269
|
method: "POST",
|
|
1060
1270
|
path: "/bases",
|
|
1061
1271
|
tags: ["Bases"],
|
|
1062
1272
|
summary: "Create Base",
|
|
1063
|
-
successDescription: "
|
|
1064
|
-
}).input(createBaseInputSchema).output(baseSchema),
|
|
1273
|
+
successDescription: "Review-first by default: a pending ChangeRequest proposing the Base. Returns the materialized Base instead when `autoMerge: true` is passed."
|
|
1274
|
+
}).input(createBaseInputSchema).output(z.union([baseSchema, changeRequestSchema])),
|
|
1065
1275
|
createChangeRequest: oc.route({
|
|
1066
1276
|
method: "POST",
|
|
1067
1277
|
path: "/bases/{baseId}/change-requests",
|
|
@@ -1169,6 +1379,13 @@ var recordContract = {
|
|
|
1169
1379
|
summary: "List records with keyset pagination",
|
|
1170
1380
|
successDescription: "A page of canonical records plus an opaque nextCursor (null at the end)."
|
|
1171
1381
|
}).input(listRecordsInputSchema).output(listRecordsResponseSchema),
|
|
1382
|
+
count: oc.route({
|
|
1383
|
+
method: "GET",
|
|
1384
|
+
path: "/records/count",
|
|
1385
|
+
tags: ["Records"],
|
|
1386
|
+
summary: "Count records",
|
|
1387
|
+
successDescription: "Total active records in the space, optionally scoped to a base."
|
|
1388
|
+
}).input(countRecordsInputSchema).output(countRecordsResponseSchema),
|
|
1172
1389
|
get: oc.route({
|
|
1173
1390
|
method: "GET",
|
|
1174
1391
|
path: "/records/{recordId}",
|
|
@@ -1252,7 +1469,12 @@ var createDocInputSchema = z.object({
|
|
|
1252
1469
|
slug: z.string().min(1).regex(/^[a-z0-9-]+$/),
|
|
1253
1470
|
name: z.string().min(1),
|
|
1254
1471
|
description: z.string().optional().default(""),
|
|
1255
|
-
body: z.string().optional().default("")
|
|
1472
|
+
body: z.string().optional().default(""),
|
|
1473
|
+
// Review-first by default: without `autoMerge: true`, this proposes the Doc
|
|
1474
|
+
// as a pending ChangeRequest (status "in_review") instead of creating it
|
|
1475
|
+
// immediately. Pass `autoMerge: true` only for callers that don't need human
|
|
1476
|
+
// review (seed/migration scripts, an explicit no-review agent task).
|
|
1477
|
+
autoMerge: z.boolean().optional().default(false)
|
|
1256
1478
|
});
|
|
1257
1479
|
var updateDocInputSchema = z.object({
|
|
1258
1480
|
body: z.string()
|
|
@@ -1277,8 +1499,8 @@ var docContract = {
|
|
|
1277
1499
|
path: "/docs",
|
|
1278
1500
|
tags: ["Docs"],
|
|
1279
1501
|
summary: "Create Doc node",
|
|
1280
|
-
successDescription: "
|
|
1281
|
-
}).input(createDocInputSchema).output(docSchema),
|
|
1502
|
+
successDescription: "Review-first by default: a pending ChangeRequest proposing the Doc. Returns the materialized Doc node instead when `autoMerge: true` is passed."
|
|
1503
|
+
}).input(createDocInputSchema).output(z.union([docSchema, changeRequestSchema])),
|
|
1282
1504
|
get: oc.route({
|
|
1283
1505
|
method: "GET",
|
|
1284
1506
|
path: "/docs/{nodeId}",
|
|
@@ -1350,7 +1572,12 @@ var createFileTreeInputSchema = z.object({
|
|
|
1350
1572
|
description: z.string().optional().default(""),
|
|
1351
1573
|
visibility: z.enum(["private", "workspace", "public"]).optional().default("private"),
|
|
1352
1574
|
version: z.string().optional().default("0.1.0"),
|
|
1353
|
-
files: z.array(z.union([assetFileInputSchema, textFileInputSchema])).optional().default([])
|
|
1575
|
+
files: z.array(z.union([assetFileInputSchema, textFileInputSchema])).optional().default([]),
|
|
1576
|
+
// Review-first by default: without `autoMerge: true`, this proposes the node
|
|
1577
|
+
// as a pending ChangeRequest (status "in_review") instead of creating it
|
|
1578
|
+
// immediately. Pass `autoMerge: true` only for callers that don't need human
|
|
1579
|
+
// review (seed/migration scripts, an explicit no-review agent task).
|
|
1580
|
+
autoMerge: z.boolean().optional().default(false)
|
|
1354
1581
|
});
|
|
1355
1582
|
var fileTreeFileOperationInputSchema = z.union([
|
|
1356
1583
|
assetFileOperationInputSchema,
|
|
@@ -1392,8 +1619,8 @@ var makeFileTreeContract = (routeBase, tag) => {
|
|
|
1392
1619
|
path: basePath,
|
|
1393
1620
|
tags: [tag],
|
|
1394
1621
|
summary: `Create ${label} node`,
|
|
1395
|
-
successDescription: `
|
|
1396
|
-
}).input(createFileTreeInputSchema).output(fileTreeNodeSchema),
|
|
1622
|
+
successDescription: `Review-first by default: a pending ChangeRequest proposing the ${label} node. Returns the materialized ${label} node instead when \`autoMerge: true\` is passed.`
|
|
1623
|
+
}).input(createFileTreeInputSchema).output(z.union([fileTreeNodeSchema, changeRequestSchema])),
|
|
1397
1624
|
get: oc.route({
|
|
1398
1625
|
method: "GET",
|
|
1399
1626
|
path: `${basePath}/{nodeId}`,
|
|
@@ -1453,7 +1680,12 @@ var createFileNodeInputSchema = z.object({
|
|
|
1453
1680
|
slug: z.string().min(1).regex(/^[a-z0-9-]+$/),
|
|
1454
1681
|
name: z.string().min(1),
|
|
1455
1682
|
description: z.string().optional().default(""),
|
|
1456
|
-
assetId: z.string().min(1)
|
|
1683
|
+
assetId: z.string().min(1),
|
|
1684
|
+
// Review-first by default: without `autoMerge: true`, this proposes the File
|
|
1685
|
+
// node as a pending ChangeRequest (status "in_review") instead of creating it
|
|
1686
|
+
// immediately. Pass `autoMerge: true` only for callers that don't need human
|
|
1687
|
+
// review (seed/migration scripts, an explicit no-review agent task).
|
|
1688
|
+
autoMerge: z.boolean().optional().default(false)
|
|
1457
1689
|
});
|
|
1458
1690
|
var fileContract = {
|
|
1459
1691
|
list: oc.route({
|
|
@@ -1468,8 +1700,8 @@ var fileContract = {
|
|
|
1468
1700
|
path: "/files",
|
|
1469
1701
|
tags: ["Files"],
|
|
1470
1702
|
summary: "Create File node",
|
|
1471
|
-
successDescription: "
|
|
1472
|
-
}).input(createFileNodeInputSchema).output(FileNodeVOSchema),
|
|
1703
|
+
successDescription: "Review-first by default: a pending ChangeRequest proposing the File node. Returns the materialized File node instead when `autoMerge: true` is passed."
|
|
1704
|
+
}).input(createFileNodeInputSchema).output(z.union([FileNodeVOSchema, changeRequestSchema])),
|
|
1473
1705
|
get: oc.route({
|
|
1474
1706
|
method: "GET",
|
|
1475
1707
|
path: "/files/{nodeId}",
|
|
@@ -1501,6 +1733,273 @@ var folderContract = {
|
|
|
1501
1733
|
|
|
1502
1734
|
// ../../packages/busabase-contract/src/domains/skill/contract.ts
|
|
1503
1735
|
var skillContract = makeFileTreeContract("skills", "Skills");
|
|
1736
|
+
var VaultItemKeySchema = z.string().trim().min(1).max(128).regex(/^[A-Z_][A-Z0-9_]*$/, "Use uppercase letters, numbers, and underscores");
|
|
1737
|
+
var VaultItemValueSchema = z.string().max(8192);
|
|
1738
|
+
var VaultItemKindSchema = z.enum(["secret", "variable"]);
|
|
1739
|
+
var VaultScopeTypeSchema = z.enum([
|
|
1740
|
+
"personal",
|
|
1741
|
+
"workspace",
|
|
1742
|
+
"base",
|
|
1743
|
+
"agent",
|
|
1744
|
+
"tool",
|
|
1745
|
+
"api_key"
|
|
1746
|
+
]);
|
|
1747
|
+
var VaultEnvironmentSchema = z.enum(["local", "development", "staging", "production"]);
|
|
1748
|
+
var VaultAccessPolicySchema = z.object({
|
|
1749
|
+
runtime: z.boolean().default(true),
|
|
1750
|
+
reveal: z.boolean().default(true),
|
|
1751
|
+
edit: z.boolean().default(true),
|
|
1752
|
+
share: z.boolean().default(false)
|
|
1753
|
+
});
|
|
1754
|
+
var VaultItemInputSchema = z.object({
|
|
1755
|
+
id: z.string().optional(),
|
|
1756
|
+
kind: VaultItemKindSchema,
|
|
1757
|
+
key: VaultItemKeySchema,
|
|
1758
|
+
value: VaultItemValueSchema,
|
|
1759
|
+
scopeType: VaultScopeTypeSchema.default("personal"),
|
|
1760
|
+
scopeId: z.string().trim().nullable().optional(),
|
|
1761
|
+
environment: VaultEnvironmentSchema.default("local"),
|
|
1762
|
+
description: z.string().trim().max(512).default(""),
|
|
1763
|
+
access: VaultAccessPolicySchema.default({
|
|
1764
|
+
runtime: true,
|
|
1765
|
+
reveal: true,
|
|
1766
|
+
edit: true,
|
|
1767
|
+
share: false
|
|
1768
|
+
})
|
|
1769
|
+
});
|
|
1770
|
+
var UpdateVaultSettingsInputSchema = z.object({
|
|
1771
|
+
items: z.array(VaultItemInputSchema).max(200)
|
|
1772
|
+
});
|
|
1773
|
+
var VaultItemVOSchema = VaultItemInputSchema.extend({
|
|
1774
|
+
id: z.string(),
|
|
1775
|
+
scopeId: z.string().nullable(),
|
|
1776
|
+
updatedAt: z.string(),
|
|
1777
|
+
createdAt: z.string(),
|
|
1778
|
+
lastUsedAt: z.string().nullable()
|
|
1779
|
+
});
|
|
1780
|
+
var VaultSettingsVOSchema = z.object({
|
|
1781
|
+
ownerId: z.string().nullable(),
|
|
1782
|
+
items: z.array(VaultItemVOSchema),
|
|
1783
|
+
updatedAt: z.string().nullable()
|
|
1784
|
+
});
|
|
1785
|
+
z.record(VaultItemKeySchema, VaultItemValueSchema).default({});
|
|
1786
|
+
var VaultSuccessSchema = z.object({ success: z.boolean() });
|
|
1787
|
+
|
|
1788
|
+
// ../../packages/busabase-contract/src/domains/vault/contract.ts
|
|
1789
|
+
var vaultContract = {
|
|
1790
|
+
get: oc.route({
|
|
1791
|
+
method: "GET",
|
|
1792
|
+
path: "/vault",
|
|
1793
|
+
tags: ["Vault"],
|
|
1794
|
+
summary: "Get local Vault settings",
|
|
1795
|
+
successDescription: "Local Vault secrets and variables for this Busabase instance."
|
|
1796
|
+
}).output(VaultSettingsVOSchema),
|
|
1797
|
+
update: oc.route({
|
|
1798
|
+
method: "PUT",
|
|
1799
|
+
path: "/vault",
|
|
1800
|
+
tags: ["Vault"],
|
|
1801
|
+
summary: "Replace local Vault settings",
|
|
1802
|
+
successDescription: "Updated local Vault secrets and variables."
|
|
1803
|
+
}).input(UpdateVaultSettingsInputSchema).output(VaultSettingsVOSchema),
|
|
1804
|
+
clear: oc.route({
|
|
1805
|
+
method: "DELETE",
|
|
1806
|
+
path: "/vault",
|
|
1807
|
+
tags: ["Vault"],
|
|
1808
|
+
summary: "Clear local Vault settings",
|
|
1809
|
+
successDescription: "Removed local Vault secrets and variables."
|
|
1810
|
+
}).output(VaultSuccessSchema)
|
|
1811
|
+
};
|
|
1812
|
+
var WebhookEventTypeSchema = z.enum(["record.created", "ai_mention", "changes_requested"]);
|
|
1813
|
+
z.enum(["webhook", "notify_agent", "run_snippet"]);
|
|
1814
|
+
var WebhookDeliveryStatusSchema = z.enum(["success", "failed", "skipped"]);
|
|
1815
|
+
var WebhookHttpConfigSchema = z.object({
|
|
1816
|
+
targetUrl: z.string().url(),
|
|
1817
|
+
secret: z.string().min(1).max(256).optional(),
|
|
1818
|
+
headers: z.record(z.string(), z.string()).optional()
|
|
1819
|
+
});
|
|
1820
|
+
var WebhookSnippetConfigSchema = z.object({
|
|
1821
|
+
code: z.string().min(1).max(2e4),
|
|
1822
|
+
timeoutMs: z.number().int().min(100).max(5e3).default(2e3)
|
|
1823
|
+
});
|
|
1824
|
+
var WebhookHttpConfigVOSchema = z.object({
|
|
1825
|
+
targetUrl: z.string().url(),
|
|
1826
|
+
hasSecret: z.boolean(),
|
|
1827
|
+
headers: z.record(z.string(), z.string()).optional()
|
|
1828
|
+
});
|
|
1829
|
+
var WebhookSnippetConfigVOSchema = WebhookSnippetConfigSchema;
|
|
1830
|
+
var webhookRuleCommonInputFields = {
|
|
1831
|
+
name: z.string().min(1).max(200),
|
|
1832
|
+
eventType: WebhookEventTypeSchema,
|
|
1833
|
+
baseId: z.string().nullable().optional(),
|
|
1834
|
+
enabled: z.boolean().default(true)
|
|
1835
|
+
};
|
|
1836
|
+
var WebhookRuleInputSchema = z.discriminatedUnion("actionKind", [
|
|
1837
|
+
z.object({
|
|
1838
|
+
...webhookRuleCommonInputFields,
|
|
1839
|
+
actionKind: z.literal("webhook"),
|
|
1840
|
+
config: WebhookHttpConfigSchema
|
|
1841
|
+
}),
|
|
1842
|
+
z.object({
|
|
1843
|
+
...webhookRuleCommonInputFields,
|
|
1844
|
+
actionKind: z.literal("notify_agent"),
|
|
1845
|
+
config: WebhookHttpConfigSchema
|
|
1846
|
+
}),
|
|
1847
|
+
z.object({
|
|
1848
|
+
...webhookRuleCommonInputFields,
|
|
1849
|
+
actionKind: z.literal("run_snippet"),
|
|
1850
|
+
config: WebhookSnippetConfigSchema
|
|
1851
|
+
})
|
|
1852
|
+
]);
|
|
1853
|
+
var WebhookRuleUpdateInputSchema = z.discriminatedUnion("actionKind", [
|
|
1854
|
+
z.object({
|
|
1855
|
+
id: z.string(),
|
|
1856
|
+
...webhookRuleCommonInputFields,
|
|
1857
|
+
actionKind: z.literal("webhook"),
|
|
1858
|
+
config: WebhookHttpConfigSchema
|
|
1859
|
+
}),
|
|
1860
|
+
z.object({
|
|
1861
|
+
id: z.string(),
|
|
1862
|
+
...webhookRuleCommonInputFields,
|
|
1863
|
+
actionKind: z.literal("notify_agent"),
|
|
1864
|
+
config: WebhookHttpConfigSchema
|
|
1865
|
+
}),
|
|
1866
|
+
z.object({
|
|
1867
|
+
id: z.string(),
|
|
1868
|
+
...webhookRuleCommonInputFields,
|
|
1869
|
+
actionKind: z.literal("run_snippet"),
|
|
1870
|
+
config: WebhookSnippetConfigSchema
|
|
1871
|
+
})
|
|
1872
|
+
]);
|
|
1873
|
+
var webhookRuleVOCommonFields = {
|
|
1874
|
+
id: z.string(),
|
|
1875
|
+
spaceId: z.string(),
|
|
1876
|
+
baseId: z.string().nullable(),
|
|
1877
|
+
name: z.string(),
|
|
1878
|
+
eventType: WebhookEventTypeSchema,
|
|
1879
|
+
enabled: z.boolean(),
|
|
1880
|
+
createdBy: z.string(),
|
|
1881
|
+
createdAt: z.string(),
|
|
1882
|
+
updatedAt: z.string(),
|
|
1883
|
+
lastTriggeredAt: z.string().nullable(),
|
|
1884
|
+
lastStatus: WebhookDeliveryStatusSchema.nullable()
|
|
1885
|
+
};
|
|
1886
|
+
var WebhookRuleVOSchema = z.discriminatedUnion("actionKind", [
|
|
1887
|
+
z.object({
|
|
1888
|
+
...webhookRuleVOCommonFields,
|
|
1889
|
+
actionKind: z.literal("webhook"),
|
|
1890
|
+
config: WebhookHttpConfigVOSchema
|
|
1891
|
+
}),
|
|
1892
|
+
z.object({
|
|
1893
|
+
...webhookRuleVOCommonFields,
|
|
1894
|
+
actionKind: z.literal("notify_agent"),
|
|
1895
|
+
config: WebhookHttpConfigVOSchema
|
|
1896
|
+
}),
|
|
1897
|
+
z.object({
|
|
1898
|
+
...webhookRuleVOCommonFields,
|
|
1899
|
+
actionKind: z.literal("run_snippet"),
|
|
1900
|
+
config: WebhookSnippetConfigVOSchema
|
|
1901
|
+
})
|
|
1902
|
+
]);
|
|
1903
|
+
var WebhookDeliveryVOSchema = z.object({
|
|
1904
|
+
id: z.string(),
|
|
1905
|
+
ruleId: z.string(),
|
|
1906
|
+
eventType: WebhookEventTypeSchema,
|
|
1907
|
+
status: WebhookDeliveryStatusSchema,
|
|
1908
|
+
httpStatus: z.number().nullable(),
|
|
1909
|
+
detail: z.string().nullable(),
|
|
1910
|
+
durationMs: z.number().nullable(),
|
|
1911
|
+
createdAt: z.string()
|
|
1912
|
+
});
|
|
1913
|
+
z.object({}).optional().default({});
|
|
1914
|
+
var ListWebhookDeliveriesInputSchema = z.object({
|
|
1915
|
+
ruleId: z.string(),
|
|
1916
|
+
limit: z.coerce.number().int().min(1).max(100).default(20)
|
|
1917
|
+
});
|
|
1918
|
+
|
|
1919
|
+
// ../../packages/busabase-contract/src/domains/webhook/contract.ts
|
|
1920
|
+
var webhookContract = {
|
|
1921
|
+
list: oc.route({
|
|
1922
|
+
method: "GET",
|
|
1923
|
+
path: "/webhooks",
|
|
1924
|
+
tags: ["Webhooks"],
|
|
1925
|
+
summary: "List webhook automation rules",
|
|
1926
|
+
successDescription: "Configured webhook automation rules for this space."
|
|
1927
|
+
}).output(WebhookRuleVOSchema.array()),
|
|
1928
|
+
get: oc.route({
|
|
1929
|
+
method: "GET",
|
|
1930
|
+
path: "/webhooks/{id}",
|
|
1931
|
+
tags: ["Webhooks"],
|
|
1932
|
+
summary: "Get webhook automation rule",
|
|
1933
|
+
successDescription: "A single webhook automation rule."
|
|
1934
|
+
}).input(z.object({ id: z.string() })).output(WebhookRuleVOSchema),
|
|
1935
|
+
create: oc.route({
|
|
1936
|
+
method: "POST",
|
|
1937
|
+
path: "/webhooks",
|
|
1938
|
+
tags: ["Webhooks"],
|
|
1939
|
+
summary: "Create webhook automation rule",
|
|
1940
|
+
successDescription: "Created webhook automation rule. Dispatches on the configured event via an HTTP webhook, an agent notification, or a sandboxed snippet."
|
|
1941
|
+
}).input(WebhookRuleInputSchema).output(WebhookRuleVOSchema),
|
|
1942
|
+
update: oc.route({
|
|
1943
|
+
method: "PUT",
|
|
1944
|
+
path: "/webhooks/{id}",
|
|
1945
|
+
tags: ["Webhooks"],
|
|
1946
|
+
summary: "Update webhook automation rule",
|
|
1947
|
+
successDescription: "Updated webhook automation rule."
|
|
1948
|
+
}).input(WebhookRuleUpdateInputSchema).output(WebhookRuleVOSchema),
|
|
1949
|
+
delete: oc.route({
|
|
1950
|
+
method: "DELETE",
|
|
1951
|
+
path: "/webhooks/{id}",
|
|
1952
|
+
tags: ["Webhooks"],
|
|
1953
|
+
summary: "Delete webhook automation rule",
|
|
1954
|
+
successDescription: "Removed the webhook automation rule."
|
|
1955
|
+
}).input(z.object({ id: z.string() })).output(z.object({ success: z.boolean() })),
|
|
1956
|
+
deliveries: oc.route({
|
|
1957
|
+
method: "GET",
|
|
1958
|
+
path: "/webhooks/{ruleId}/deliveries",
|
|
1959
|
+
tags: ["Webhooks"],
|
|
1960
|
+
summary: "List webhook rule delivery attempts",
|
|
1961
|
+
successDescription: "Recent delivery attempts for a webhook rule, newest first."
|
|
1962
|
+
}).input(ListWebhookDeliveriesInputSchema).output(WebhookDeliveryVOSchema.array()),
|
|
1963
|
+
testFire: oc.route({
|
|
1964
|
+
method: "POST",
|
|
1965
|
+
path: "/webhooks/{id}/test-fire",
|
|
1966
|
+
tags: ["Webhooks"],
|
|
1967
|
+
summary: "Test-fire a webhook automation rule",
|
|
1968
|
+
successDescription: "The delivery record produced by firing this rule right now with a synthetic payload \u2014 runs regardless of the rule's enabled state or its real trigger."
|
|
1969
|
+
}).input(z.object({ id: z.string() })).output(WebhookDeliveryVOSchema)
|
|
1970
|
+
};
|
|
1971
|
+
var activityItemSchema = z.discriminatedUnion("kind", [
|
|
1972
|
+
z.object({
|
|
1973
|
+
kind: z.literal("change_request"),
|
|
1974
|
+
timestamp: z.string(),
|
|
1975
|
+
changeRequest: changeRequestSchema
|
|
1976
|
+
}),
|
|
1977
|
+
z.object({
|
|
1978
|
+
kind: z.literal("operation"),
|
|
1979
|
+
timestamp: z.string(),
|
|
1980
|
+
operationId: z.string(),
|
|
1981
|
+
changeRequest: changeRequestSchema
|
|
1982
|
+
}),
|
|
1983
|
+
z.object({
|
|
1984
|
+
kind: z.literal("record"),
|
|
1985
|
+
timestamp: z.string(),
|
|
1986
|
+
record: recordSchema
|
|
1987
|
+
}),
|
|
1988
|
+
z.object({
|
|
1989
|
+
kind: z.literal("audit"),
|
|
1990
|
+
timestamp: z.string(),
|
|
1991
|
+
auditEvent: auditEventSchema,
|
|
1992
|
+
record: recordSchema.nullable()
|
|
1993
|
+
})
|
|
1994
|
+
]);
|
|
1995
|
+
var listActivityPagedInputSchema = z.object({
|
|
1996
|
+
limit: z.coerce.number().int().min(1).max(100).optional().default(50),
|
|
1997
|
+
cursor: z.string().optional()
|
|
1998
|
+
}).optional().default({ limit: 50 });
|
|
1999
|
+
var listActivityResponseSchema = z.object({
|
|
2000
|
+
items: z.array(activityItemSchema),
|
|
2001
|
+
nextCursor: z.string().nullable()
|
|
2002
|
+
});
|
|
1504
2003
|
|
|
1505
2004
|
// ../../packages/busabase-contract/src/contract/busabase.ts
|
|
1506
2005
|
var changeRequestBatchResultSchema = z.object({
|
|
@@ -1576,6 +2075,15 @@ var busabaseContractRoutes = {
|
|
|
1576
2075
|
successDescription: "Recorded audit event."
|
|
1577
2076
|
}).input(createAuditEventInputSchema).output(auditEventSchema)
|
|
1578
2077
|
},
|
|
2078
|
+
activity: {
|
|
2079
|
+
listPaged: oc.route({
|
|
2080
|
+
method: "GET",
|
|
2081
|
+
path: "/activity/paged",
|
|
2082
|
+
tags: ["Activity"],
|
|
2083
|
+
summary: "List the activity feed with keyset pagination",
|
|
2084
|
+
successDescription: "A page of activity items (change requests, operations, records and audit events merged, newest first) plus an opaque nextCursor (null at the end)."
|
|
2085
|
+
}).input(listActivityPagedInputSchema).output(listActivityResponseSchema)
|
|
2086
|
+
},
|
|
1579
2087
|
comments: {
|
|
1580
2088
|
list: oc.route({
|
|
1581
2089
|
method: "GET",
|
|
@@ -1613,6 +2121,8 @@ var busabaseContractRoutes = {
|
|
|
1613
2121
|
docs: docContract,
|
|
1614
2122
|
folders: folderContract,
|
|
1615
2123
|
assets: assetsContract,
|
|
2124
|
+
vault: vaultContract,
|
|
2125
|
+
webhooks: webhookContract,
|
|
1616
2126
|
changeRequests: {
|
|
1617
2127
|
list: oc.route({
|
|
1618
2128
|
method: "GET",
|
|
@@ -1621,6 +2131,20 @@ var busabaseContractRoutes = {
|
|
|
1621
2131
|
summary: "List change requests",
|
|
1622
2132
|
successDescription: "Change requests waiting for review or ready to merge."
|
|
1623
2133
|
}).input(listInputSchema).output(z.array(changeRequestSchema)),
|
|
2134
|
+
listPaged: oc.route({
|
|
2135
|
+
method: "GET",
|
|
2136
|
+
path: "/change-requests/paged",
|
|
2137
|
+
tags: ["Change Requests"],
|
|
2138
|
+
summary: "List change requests with keyset pagination",
|
|
2139
|
+
successDescription: "A page of change requests plus an opaque nextCursor (null at the end). Filter with `status` and/or `mine`."
|
|
2140
|
+
}).input(listChangeRequestsPagedInputSchema).output(listChangeRequestsResponseSchema),
|
|
2141
|
+
counts: oc.route({
|
|
2142
|
+
method: "GET",
|
|
2143
|
+
path: "/change-requests/counts",
|
|
2144
|
+
tags: ["Change Requests"],
|
|
2145
|
+
summary: "Count change requests by inbox tab",
|
|
2146
|
+
successDescription: "Whole-space change request counts per inbox tab (review / changes / created / approved / merged / rejected)."
|
|
2147
|
+
}).output(changeRequestCountsSchema),
|
|
1624
2148
|
get: oc.route({
|
|
1625
2149
|
method: "GET",
|
|
1626
2150
|
path: "/change-requests/{changeRequestId}",
|
|
@@ -1742,6 +2266,7 @@ var notFoundErrors = {
|
|
|
1742
2266
|
data: ErrorResponseSchema
|
|
1743
2267
|
}
|
|
1744
2268
|
};
|
|
2269
|
+
var { vault: _localVault, ...cloudWorkbenchRoutes } = busabaseContractRoutes;
|
|
1745
2270
|
var cloudExtraRoutes = {
|
|
1746
2271
|
system: {
|
|
1747
2272
|
health: oc.route({
|
|
@@ -1822,7 +2347,7 @@ var cloudExtraRoutes = {
|
|
|
1822
2347
|
}
|
|
1823
2348
|
};
|
|
1824
2349
|
var cloudContract = oc.prefix("/api/v1").router({
|
|
1825
|
-
...
|
|
2350
|
+
...cloudWorkbenchRoutes,
|
|
1826
2351
|
...cloudExtraRoutes
|
|
1827
2352
|
});
|
|
1828
2353
|
|
|
@@ -1924,10 +2449,48 @@ var Busabase = class {
|
|
|
1924
2449
|
get agentTasks() {
|
|
1925
2450
|
return this.client.agentTasks;
|
|
1926
2451
|
}
|
|
2452
|
+
get webhooks() {
|
|
2453
|
+
return this.client.webhooks;
|
|
2454
|
+
}
|
|
1927
2455
|
/** Full-text search across records, change requests, and Bases. */
|
|
1928
2456
|
search(input) {
|
|
1929
2457
|
return this.client.search(input);
|
|
1930
2458
|
}
|
|
2459
|
+
/**
|
|
2460
|
+
* Supply text for an Asset's Drive Grep Retrieval text slot in one call —
|
|
2461
|
+
* inline for small text, a presigned upload for large text — so callers
|
|
2462
|
+
* never see the underlying three-step flow
|
|
2463
|
+
* (`createTextUploadUrl` → PUT bytes → `putText({ storageKey })`).
|
|
2464
|
+
*
|
|
2465
|
+
* @example
|
|
2466
|
+
* ```ts
|
|
2467
|
+
* await bb.putText(assetId, extractedText); // picks inline vs presigned by size
|
|
2468
|
+
* ```
|
|
2469
|
+
*/
|
|
2470
|
+
async putText(assetId, text) {
|
|
2471
|
+
const INLINE_TEXT_MAX_BYTES = 1024 * 1024;
|
|
2472
|
+
const byteLength = typeof Buffer !== "undefined" ? Buffer.byteLength(text, "utf8") : new Blob([text]).size;
|
|
2473
|
+
if (byteLength <= INLINE_TEXT_MAX_BYTES) {
|
|
2474
|
+
return this.client.assets.putText({ assetId, text });
|
|
2475
|
+
}
|
|
2476
|
+
const upload = await this.client.assets.createTextUploadUrl({
|
|
2477
|
+
assetId,
|
|
2478
|
+
sizeBytes: byteLength
|
|
2479
|
+
});
|
|
2480
|
+
const doFetch = this.config.fetch ?? fetch;
|
|
2481
|
+
const response = await doFetch(upload.uploadUrl, {
|
|
2482
|
+
method: "PUT",
|
|
2483
|
+
headers: { "content-type": "text/plain; charset=utf-8" },
|
|
2484
|
+
body: text
|
|
2485
|
+
});
|
|
2486
|
+
if (!response.ok) {
|
|
2487
|
+
const detail = await response.text().catch(() => "");
|
|
2488
|
+
throw new Error(
|
|
2489
|
+
`putText: presigned upload failed (${response.status} ${response.statusText})${detail ? `: ${detail}` : ""}`
|
|
2490
|
+
);
|
|
2491
|
+
}
|
|
2492
|
+
return this.client.assets.putText({ assetId, storageKey: upload.storageKey });
|
|
2493
|
+
}
|
|
1931
2494
|
/** Service health — reaches the server without requiring auth. */
|
|
1932
2495
|
health() {
|
|
1933
2496
|
return this.client.system.health();
|